casa
$Rev:20696$
|
00001 //# NumericTraits.h: Defines relationships between numeric data types 00002 //# Copyright (C) 1996,1997,1998,2000,2002 00003 //# Associated Universities, Inc. Washington DC, USA. 00004 //# 00005 //# This library is free software; you can redistribute it and/or modify it 00006 //# under the terms of the GNU Library General Public License as published by 00007 //# the Free Software Foundation; either version 2 of the License, or (at your 00008 //# option) any later version. 00009 //# 00010 //# This library is distributed in the hope that it will be useful, but WITHOUT 00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00012 //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00013 //# License for more details. 00014 //# 00015 //# You should have received a copy of the GNU Library General Public License 00016 //# along with this library; if not, write to the Free Software Foundation, 00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. 00018 //# 00019 //# Correspondence concerning AIPS++ should be addressed as follows: 00020 //# Internet email: aips2-request@nrao.edu. 00021 //# Postal address: AIPS++ Project Office 00022 //# National Radio Astronomy Observatory 00023 //# 520 Edgemont Road 00024 //# Charlottesville, VA 22903-2475 USA 00025 //# 00026 //# $Id: NumericTraits.h 21024 2011-03-01 11:46:18Z gervandiepen $ 00027 00028 #ifndef SCIMATH_NUMERICTRAITS_H 00029 #define SCIMATH_NUMERICTRAITS_H 00030 00031 //# Include files 00032 #include <casa/aips.h> 00033 #include <casa/BasicSL/Complex.h> 00034 00035 namespace casa { //# NAMESPACE CASA - BEGIN 00036 00037 // 00038 // <summary> Relationships between numeric data types </summary> 00039 // <use visibility=export> 00040 // 00041 // <reviewed reviewer="nkilleen" date="1996/12/12" tests="tConvolver,tFFTServer"> 00042 // </reviewed> 00043 // 00044 // <etymology> 00045 // A trait is a characteristic feature. NumericTraits defines relationships 00046 // between and characteristics of Numeric data types. 00047 // </etymology> 00048 // 00049 // <synopsis> 00050 00051 // This templated class contains a number of typedefs and definitions that 00052 // describe the relationship between different numeric data types and there 00053 // characteristics. Its use is in templated classes either where the use of one 00054 // type implictly implies the use of a corresponding one or where a 00055 // characteristic value differs with templating argument. Use of this class 00056 // often avoids the need for double templating. 00057 // 00058 // Currently this class defines the following relationships: 00059 // <dl> 00060 // <dt> <src>value_type</src> 00061 // <dd> The template type itself. The name <src>value_type</src> is the 00062 // C++ standard (e.g. <src>DComplex::value_type</src> equals 00063 // <src>double</src>) 00064 // <dt> <src>BaseType</src> 00065 // <dd> The numeric base type. I.e. <src>Double</src> for <src>Double</src> 00066 // and <src>DComplex</src>; <src>Float</src> for <src>Float</src> and 00067 // <src>Complex</src> 00068 // <dt> <src>ConjugateType</src> 00069 // <dd> The corresponding complex type for a real type, and real type 00070 // for a complex type. It is the type of the result if a Fourier 00071 // Transform was to be done. 00072 // <dt> <src>PrecisionType</src> 00073 // <dd> The Type of the next higher numerical precision. I.e. <src>Double</src> 00074 // or <src>DComplex</src> 00075 // </dl> 00076 // 00077 // And the following characteristics: 00078 // <dl> 00079 // <dt> <src>epsilon</src> 00080 // <dd> A Double containing the smallest value such that 1+epsilon is different 00081 // from 1. 00082 // <dt> <src>minimum</src> 00083 // <dd> A Double containing the smallest positive representable number, 00084 // excluding denormalised numbers. 00085 // <dt> <src>maximum</src> 00086 // <dd> A Double containing the largest representable number. 00087 // <dt> <src>size()</src> 00088 // <dd> The number of numeric values in the templated entity. It will be 00089 // 2 for complex numbers; 1 for real numbers. 00090 // <dt> <src>setImag(T &other, const BaseType &val)</src> 00091 // <dd> Set an imaginary part (for complex numbers) or a NOP (for reals). 00092 // <dt> <src>getValue(T &other, const uInt n)</src> 00093 // <dd> Get the <src>n%size()-th</src> value in the argument. 00094 // For complex numbers the sequence is real, imaginary part. 00095 // <dt> <src>setValue(T &other, const BaseType &val, const uInt n)</src> 00096 // <dd> Set the <src>n%size()-th</src> value in the argument. 00097 // For complex numbers the sequence is real, imaginary part. 00098 // </dl> 00099 // 00100 // For complex numbers these values are applicable to the real or imaginary 00101 // components separately. 00102 // 00103 // The use of this class is best illustrated in a number of examples. 00104 // 00105 // A default template declaration is required by the C++ standard. 00106 // It should never be used, except through the specialisations. 00107 // The default types for ConjugateType and PrecisionType are deliberatly set to 00108 // a non-numeric type to further discourage the use of the non-specialized 00109 // class defined below. It also helps when using this class with the Sun native 00110 // compiler. 00111 // <note role=warning> The specialized instantiations seem to have a name with 00112 // an appended code. This is only for cxx2html reasons. The name is in all 00113 // cases <src>NumericTraits</src> 00114 // </note> 00115 // 00116 // This class is implemented as a number of specialisations for the 00117 // following data types. 00118 // <ul> 00119 // <li> Float 00120 // <li> Double 00121 // <li> Complex 00122 // <li> DComplex 00123 // </ul> 00124 // This class should not be used with other template types and does nothing 00125 // except return its template type if it is used. ie. <br> 00126 // <src>NumericTraits<ArbitraryType>::ConjugateType</src> returns 00127 // <src>Char</src> and <br> 00128 // <src>NumericTraits<ArbitraryType>::PrecisionType</src> returns 00129 // <src>Char</src><br> 00130 // <src>NumericTraits<ArbitraryType>::epsilon</src> is undefined<br> 00131 // <src>NumericTraits<ArbitraryType>::minimum</src> is undefined<br> 00132 // <src>NumericTraits<ArbitraryType>::maximum</src> is undefined 00133 // </synopsis> 00134 // 00135 // <example> 00136 // <h4>Example 1:</h4> 00137 // Suppose you are writing a templated class that needs to do Fourier 00138 // Transforms. The FFTServer class can do FFT's of Float or Double data 00139 // types, but you need to doubly template it on the conjugate data type. To 00140 // avoid having the conjugate data type appear as a template in the class 00141 // you are writing you can use the ConjugateType typedef. 00142 // <srcblock> 00143 // template<class T> class myClass { 00144 // private: 00145 // FFTServer<T, NumericTraits<T>::ConjugateType> server; 00146 // } 00147 // </srcblock> 00148 // The ConjugateType transforms 00149 // <ul> 00150 // <li> Float -> Complex 00151 // <li> Double -> DComplex 00152 // <li> Complex -> Float 00153 // <li> DComplex -> Double 00154 // </ul> 00155 // 00156 // <h4>Example 2:</h4> 00157 // Suppose you have a templated numerical integrator class. Because the 00158 // individual samples can be negative it is possible to add two numbers 00159 // of nearly equal magnitude but opposite sign and lose precision 00160 // considerably. One way to combat this is to make the accumulator variable 00161 // the next higher precision numerical type. The PrecisionType typedef 00162 // defines what type this is 00163 // <srcblock> 00164 // template<class T> class Integrator { 00165 // private: 00166 // NumericTraits<T>::PrecisionType accumulator; 00167 // } 00168 // </srcblock> 00169 // The PrecisionType transforms 00170 // <ul> 00171 // <li> Float -> Double 00172 // <li> Double -> Double 00173 // <li> Complex -> DComplex 00174 // <li> DComplex -> DComplex 00175 // </ul> 00176 00177 // <h4>Example 3:</h4> 00178 // Suppose you have a templated class that needs to use the <src>allNear</src> 00179 // functions from 00180 // <linkto group="ArrayMath.h#Array mathematical operations">ArrayMath</linkto> 00181 // to determine if a templated Array is near 00182 // one. The tolerance argument to the allNear function will depend on the 00183 // template type and this is not known until the template is instantiated. The 00184 // epsilon trait can be used to supply this value. 00185 00186 // <srcblock> 00187 // template<class T> void myClass<T>::myFunction(Array<T> & aArray) { 00188 // if (allNear(aArray, T(1), NumericTraits<T>::epsilon)) 00189 // return; 00190 // // Do something 00191 // } 00192 // </srcblock> 00193 00194 // <dl> 00195 // <dt><src>NumericTraits<T>::epsilon</src> 00196 // <dd> is FLT_EPSILON for Float and Complex types and DBL_EPSILON for Double 00197 // and DComplex data types. 00198 // <dt><src>NumericTraits<T>::minimum</src> 00199 // <dd>is FLT_MIN for Float and complex Types and DBL_MIN for Double and 00200 // DComplex data types. 00201 // <dt><src>NumericTraits<T>::maximum</src> 00202 // <dd>is FLT_MAX for Float and complex Types and DBL_MAX for Double and 00203 // DComplex data types. 00204 // </dl> 00205 // See the <linkto class=Dummy_Constants_class">C class/namespace</linkto> 00206 // for the values of these variables. 00207 // </example> 00208 // 00209 // <motivation> 00210 // This is a nice way to make the Convolver class singly templated (as it 00211 // should be), even though the FFTServer it contains is doubly templated. 00212 // </motivation> 00213 // 00214 // <thrown> 00215 // <li> This class does not throw any exceptions 00216 // </thrown> 00217 // 00218 // <todo asof="2002/06/25"> 00219 // <li> Nothing (I hope!) 00220 // </todo> 00221 // 00222 00223 template <class T> class NumericTraits { 00224 public: 00225 // Template argument 00226 typedef T value_type; 00227 // Numeric type 00228 typedef Char BaseType; 00229 // Conjugate (<src>real<->complex</src>) type 00230 typedef Char ConjugateType; 00231 // Higher precision type (<src>Float->Double</src>) 00232 typedef Char PrecisionType; 00233 // Relevant minimum and maximum numbers 00234 // <group> 00235 static const Double & epsilon; 00236 static const Double & minimum; 00237 static const Double & maximum; 00238 // </group> 00239 // Number of relevant numeric values 00240 static uInt size() { return 0; } 00241 // Set the imaginary part of a complex value only (a NOP for reals) 00242 static void setImag(T &, const BaseType &) {;} 00243 // Get the <src>n%size()-th</src> numeric value 00244 static BaseType getValue(const T &, const uInt) { return 0; } 00245 // Set the <src>n%size()-th</src> numeric value 00246 static void setValue(T &, const BaseType &, const uInt) {;} 00247 }; 00248 00249 #if defined NumericTraits_F 00250 #undef NumericTraits_F 00251 #endif 00252 #define NumericTraits_F NumericTraits 00253 00254 // <summary>NumericTraits specialization for Float</summary> 00255 00256 template <> class NumericTraits_F<Float> { 00257 public: 00258 // Template argument 00259 typedef Float value_type; 00260 // Numeric type 00261 typedef Float BaseType; 00262 // Conjugate (<src>real<->complex</src>) type 00263 typedef Complex ConjugateType; 00264 // Higher precision type (<src>Float->Double</src>) 00265 typedef Double PrecisionType; 00266 // Relevant minimum and maximum numbers 00267 // <group> 00268 static const Double & epsilon; 00269 static const Double & minimum; 00270 static const Double & maximum; 00271 // </group> 00272 // Number of relevant numeric values 00273 static uInt size() { return 1; } 00274 // Set the imaginary part of a complex value only (a NOP for reals) 00275 static void setImag(value_type &, const BaseType &) {;} 00276 // Get the <src>n%size()-th</src> numeric value 00277 static BaseType getValue(const value_type &other, const uInt) { 00278 return other; } 00279 // Set the <src>n%size()-th</src> numeric value 00280 static void setValue(value_type &other, const BaseType &val, const uInt) { 00281 other = val; } 00282 }; 00283 00284 #undef NumericTraits_F 00285 00286 #if defined NumericTraits_D 00287 #undef NumericTraits_D 00288 #endif 00289 #define NumericTraits_D NumericTraits 00290 00291 // <summary>NumericTraits specialization for Double</summary> 00292 00293 template <> class NumericTraits_D<Double> { 00294 public: 00295 // Template argument 00296 typedef Double value_type; 00297 // Numeric type 00298 typedef Double BaseType; 00299 // Conjugate (<src>real<->complex</src>) type 00300 typedef DComplex ConjugateType; 00301 // Higher precision type (<src>Float->Double</src>) 00302 typedef Double PrecisionType; 00303 // Relevant minimum and maximum numbers 00304 // <group> 00305 static const Double & epsilon; 00306 static const Double & minimum; 00307 static const Double & maximum; 00308 // </group> 00309 // Number of relevant numeric values 00310 static uInt size() { return 1; } 00311 // Set the imaginary part of a complex value only (a NOP for reals) 00312 static void setImag(value_type &, const BaseType &) {;} 00313 // Get the <src>n%size()-th</src> numeric value 00314 static BaseType getValue(const value_type &other, const uInt) { 00315 return other; } 00316 // Set the <src>n%size()-th</src> numeric value 00317 static void setValue(value_type &other, const BaseType &val, const uInt) { 00318 other = val; } 00319 }; 00320 00321 #undef NumericTraits_D 00322 00323 #if defined NumericTraits_C 00324 #undef NumericTraits_C 00325 #endif 00326 #define NumericTraits_C NumericTraits 00327 00328 // <summary>NumericTraits specialization for Complex</summary> 00329 00330 template <> class NumericTraits_C<Complex> { 00331 public: 00332 // Template argument 00333 typedef Complex value_type; 00334 // Numeric type 00335 typedef Float BaseType; 00336 // Conjugate (<src>real<->complex</src>) type 00337 typedef Float ConjugateType; 00338 // Higher precision type (<src>Float->Double</src>) 00339 typedef DComplex PrecisionType; 00340 // Relevant minimum and maximum numbers 00341 // <group> 00342 static const Double & epsilon; 00343 static const Double & minimum; 00344 static const Double & maximum; 00345 // </group> 00346 // Number of relevant numeric values 00347 static uInt size() { return 2; } 00348 // Set the imaginary part of a complex value only (a NOP for reals) 00349 static void setImag(value_type &other, const BaseType &val) { 00350 other = value_type(other.real(), val); } 00351 // Get the <src>n%size()-th</src> numeric value 00352 static BaseType getValue(const value_type &other, const uInt n) { 00353 return ((n%2 == 0) ? other.real() : other.imag()); } 00354 // Set the <src>n%size()-th</src> numeric value 00355 static void setValue(value_type &other, const BaseType &val, const uInt n) { 00356 other = (n%2 == 0) ? value_type(val, other.imag()) : 00357 value_type(other.real(), val); } 00358 }; 00359 00360 #undef NumericTraits_C 00361 00362 #if defined NumericTraits_DC 00363 #undef NumericTraits_DC 00364 #endif 00365 #define NumericTraits_DC NumericTraits 00366 00367 // <summary>NumericTraits specialization for DComplex</summary> 00368 00369 template <> class NumericTraits_DC<DComplex> { 00370 public: 00371 // Template argument 00372 typedef DComplex value_type; 00373 // Numeric type 00374 typedef Double BaseType; 00375 // Conjugate (<src>real<->complex</src>) type 00376 typedef Double ConjugateType; 00377 // Higher precision type (<src>Float->Double</src>) 00378 typedef DComplex PrecisionType; 00379 // Relevant minimum and maximum numbers 00380 // <group> 00381 static const Double & epsilon; 00382 static const Double & minimum; 00383 static const Double & maximum; 00384 // </group> 00385 // Number of relevant numeric values 00386 static uInt size() { return 2; } 00387 // Set the imaginary part of a complex value only (a NOP for reals) 00388 static void setImag(value_type &other, const BaseType &val) { 00389 other = value_type(other.real(), val); } 00390 // Get the <src>n%size()-th</src> numeric value 00391 static BaseType getValue(const value_type &other, const uInt n) { 00392 return ((n%2 == 0) ? other.real() : other.imag()); } 00393 // Set the <src>n%size()-th</src> numeric value 00394 static void setValue(value_type &other, const BaseType &val, const uInt n) { 00395 other = (n%2 == 0) ? value_type(val, other.imag()) : 00396 value_type(other.real(), val); } 00397 }; 00398 00399 #undef NumericTraits_DC 00400 00401 00402 } //# NAMESPACE CASA - END 00403 00404 #endif