core/vnl/vnl_na.cxx
Go to the documentation of this file.
00001 // This is core/vnl/vnl_na.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 // \file
00007 
00008 #include "vnl_na.h"
00009 #include <vxl_config.h>
00010 #include <vcl_istream.h>
00011 #include <vcl_ios.h>
00012 #include <vnl/vnl_math.h>
00013 
00014 //: A particular qNaN to indicate not available.
00015 // This returns the bit pattern 0x7ff00000000007a2, as used by Octave and R
00016 // Don't assume that any VXL functions will treat the value as NA rather than NaN, unless
00017 // explicitly documented.
00018 double vnl_na(double)
00019 {
00020   double a;
00021 
00022 #if VXL_HAS_INT_64
00023   *reinterpret_cast<vxl_uint_64*>(&a) = 0x7ff00000000007a2LL;
00024 #else
00025 # if VXL_BIG_ENDIAN
00026 #  define hw 0
00027 #  define lw 1
00028 # else  // VXL_LITTLE_ENDIAN
00029 #  define hw 1
00030 #  define lw 0
00031 # endif
00032   reinterpret_cast<vxl_uint_32*>(&a)[hw]=0x7ff00000;
00033   reinterpret_cast<vxl_uint_32*>(&a)[lw]=0x000007a2;
00034 #endif
00035 
00036   return a;
00037 }
00038 
00039 
00040 
00041 //: A particular qNaN to indicate not available.
00042 // This returns the bit pattern 0x7f8007a2
00043 // Don't assume that any VXL functions will treat the value as NA rather than NaN, unless
00044 // explicitly documented.
00045 float vnl_na(float)
00046 {
00047   float a;
00048 
00049   *reinterpret_cast<vxl_uint_32*>(&a) = 0x7f8007a2L;
00050 
00051   return a;
00052 }
00053 
00054 //: True if parameter is specific NA qNaN.
00055 // Tests for bit pattern 0x7ff00000000007a2, as used by Octave and R
00056 bool vnl_na_isna(double x)
00057 {
00058 #if VXL_HAS_INT_64
00059   return ((*reinterpret_cast<vxl_uint_64*>(&x))&0xfff7ffffffffffffLL) // ignore signalling bit
00060     == 0x7ff00000000007a2LL;
00061 #else
00062   return ((reinterpret_cast<vxl_int_32*>(&x)[hw]) & 0xfff7ffff) == 0x7ff00000 &&
00063          reinterpret_cast<vxl_int_32*>(&x)[lw] == 0x000007a2;
00064 #endif
00065 }
00066 
00067 //: True if parameter is specific NA qNaN.
00068 // Tests for bit pattern 0x7F8007a2
00069 bool vnl_na_isna(float x)
00070 {
00071   return ((*reinterpret_cast<vxl_uint_32*>(&x))&0xffbfffffL) // ignore signalling bit
00072     == 0x7f8007a2L;
00073 }
00074 
00075 
00076 
00077 //: Replace NaNs with NA, leave other values alone.
00078 double vnl_na_nan_to_na(double v)
00079 {
00080   return vnl_math_isnan(v) ? vnl_na(double()) : v;
00081 }
00082 
00083 //: Replace NaNs with NA, leave other values alone.
00084 float vnl_na_nan_to_na(float v)
00085 {
00086   return vnl_math_isnan(v) ? vnl_na(float()) : v;
00087 }
00088 
00089 
00090 //: Read a floating point number or "NA" from a stream.
00091 template <class T> inline void vnl_na_extract_type(vcl_istream &is, T& x)
00092 {
00093   if (!is) return;
00094   is >> x;
00095 
00096   if (!!is || is.eof()) return;
00097   is.clear();
00098 
00099   char c=' ';
00100   is >> c;
00101   if (c != 'N' && c!='n')
00102   {
00103     is.putback(c);
00104     is.clear(vcl_ios::badbit);
00105     return;
00106   }
00107   is >> c;
00108   if (c != 'A' && c!='a')
00109   {
00110     is.putback(c);
00111     is.clear(vcl_ios::badbit);
00112     return;
00113   }
00114   x = vnl_na(T());
00115 }
00116 
00117 void vnl_na_extract(vcl_istream &is, double& x) { vnl_na_extract_type(is, x); }
00118 void vnl_na_extract(vcl_istream &is, float& x) { vnl_na_extract_type(is, x); }
00119 
00120 //: Write a floating point number or "NA" to a stream.
00121 void vnl_na_insert(vcl_ostream &os, double x)
00122 {
00123   if (vnl_na_isna(x))
00124     os << "NA";
00125   else
00126     os << x;
00127 }
00128 
00129 //: Write a floating point number or "NA" to a stream.
00130 void vnl_na_insert(vcl_ostream &os, float x)
00131 {
00132   if (vnl_na_isna(x))
00133     os << "NA";
00134   else
00135     os << x;
00136 }
00137 //----------------------------------------------------------------------