00001 // This is core/vnl/vnl_na.h 00002 #ifndef vnl_na_h_ 00003 #define vnl_na_h_ 00004 #ifdef VCL_NEEDS_PRAGMA_INTERFACE 00005 #pragma interface 00006 #endif 00007 00008 00009 #include <vcl_iosfwd.h> 00010 00011 //: 00012 // \file 00013 // \brief NA (Not Available) is a particular double (or single-precision) NaN to represent missing data. 00014 // For example, where a vnl_vector<double> represents a series of samples from an image, 00015 // NA could be used to represent places where the measurement was taken outside the image. 00016 // 00017 // NA is distinct from the two other standard meanings of NaN - Indeterminate and Error. 00018 // It is entirely up to each algorithm to treat NA values meaningfully. Unless 00019 // a function's interpretation of NA is explicitly documented, you should assume that 00020 // it will be treated similarly to every other NaN. 00021 // The IEEE754 bit value used to represent NA in double-precision is 0x7ff00000000007a2, the 00022 // same as used by Octave and R. Initial values of NA are stored as signalling NaNs, but 00023 // many uses will convert this to the non-signalling variant 0x7ff80000000007a2. vnl_isna() 00024 // will accept either variant. 00025 // 00026 // The single precision NA is stored as 0x7f8007a2. I cannot find any external support for 00027 // this or any other value for single precision NA. There is no automatic conversion between 00028 // the NA values during casting, promotion, etc. If you want to convert a float to double, 00029 // whilst preserving the NA-ness of the value, you will have to test for and set the new NA 00030 // value explicitly. 00031 // 00032 // You can read and write floating point values from a stream using standard operators 00033 // by using a conversion manipulator. 00034 // \verbatim 00035 // double x, y; 00036 // is >> vnl_na_stream(x) >> vnl_na_stream(x); 00037 // os << vnl_na_stream(x) << ' ' << vnl_na_stream(x); 00038 // \endverbatim 00039 00040 00041 //: qNaN to indicate value Not Available. 00042 // Don't assume that any VXL functions will do something sensible in the face of NA, unless 00043 // explicitly documented. 00044 double vnl_na(double dummy); 00045 00046 //: qNaN to indicate value Not Available. 00047 // Don't assume that any VXL functions will do something sensible in the face of NA, unless 00048 // explicitly documented. 00049 float vnl_na(float dummy); 00050 00051 //: True if parameter is specific NA qNaN. 00052 // Tests for bit pattern 0x7ff00000000007a2, as used by Octave and R 00053 bool vnl_na_isna(double); 00054 00055 //: True if parameter is specific NA qNaN. 00056 // Tests for bit pattern 0x7f8007a2 00057 bool vnl_na_isna(float); 00058 00059 00060 //: Replace NaNs with NA, leave other values alone. 00061 double vnl_na_nan_to_na(double v); 00062 00063 //: Replace NaNs with NA, leave other values alone. 00064 float vnl_na_nan_to_na(float v); 00065 00066 00067 //: Read a floating point number or "NA" from a stream. 00068 // Should behave exactly like a>>x, if the extraction operator was aware of the 00069 // character sequence \code NA. 00070 void vnl_na_extract(vcl_istream &is, double& x); 00071 00072 00073 //: Write a floating point number or "NA" to a stream. 00074 // Should behave exactly like a<<x, if the insertion operator was aware of the 00075 // character sequence \code NA. 00076 void vnl_na_insert(vcl_ostream &is, double x); 00077 00078 //: Read a floating point number or "NA" from a stream. 00079 // Should behave exactly like a>>x, if the extraction operator was aware of the 00080 // character sequence \code NA. 00081 void vnl_na_extract(vcl_istream &is, float& x); 00082 00083 00084 //: Write a floating point number or "NA" to a stream. 00085 // Should behave exactly like a<<x, if the insertion operator was aware of the 00086 // character sequence \code NA. 00087 void vnl_na_insert(vcl_ostream &is, float x); 00088 00089 00090 //: Wrapper around a double or float that handles streaming NA. 00091 template <class T> struct vnl_na_stream_t 00092 { 00093 T& x_; 00094 vnl_na_stream_t(T& x): x_(x) {} 00095 }; 00096 00097 //: Wrapper around a double or float that handles streaming NA. 00098 template <class T> struct vnl_na_stream_const_t 00099 { 00100 const T& x_; 00101 vnl_na_stream_const_t(const T& x): x_(x) {} 00102 }; 00103 00104 //: Wrap a double or float to handle streaming NA. 00105 template <class T> inline vnl_na_stream_t<T> vnl_na_stream(T& x) 00106 { 00107 return vnl_na_stream_t<T>(x); 00108 } 00109 00110 //: Wrap a double or float to handle streaming NA. 00111 template <class T> inline vnl_na_stream_const_t<T> vnl_na_stream(const T& x) 00112 { 00113 return vnl_na_stream_const_t<T>(x); 00114 } 00115 00116 //: Insert wrapped double or float into stream, whilst handling NA. 00117 template <class T> inline vcl_ostream& operator <<(vcl_ostream &os, const vnl_na_stream_t<T>& ns) 00118 { 00119 vnl_na_insert(os, ns.x_); 00120 return os; 00121 } 00122 00123 //: Insert wrapped double or float into stream, whilst handling NA. 00124 template <class T> inline vcl_ostream& operator <<(vcl_ostream &os, const vnl_na_stream_const_t<T>& ns) 00125 { 00126 vnl_na_insert(os, ns.x_); 00127 return os; 00128 } 00129 00130 //: Extract wrapped double or float from stream, whilst handling NA. 00131 template <class T> inline vcl_istream& operator >>(vcl_istream &is, const vnl_na_stream_t<T>& ns) 00132 { 00133 vnl_na_extract(is, ns.x_); 00134 return is; 00135 } 00136 00137 00138 #endif // vnl_na_h_