core/vnl/vnl_na.h
Go to the documentation of this file.
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_