casacore
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NumericTraits.h
Go to the documentation of this file.
1 //# NumericTraits.h: Defines relationships between numeric data types
2 //# Copyright (C) 1996,1997,1998,2000,2002
3 //# Associated Universities, Inc. Washington DC, USA.
4 //#
5 //# This library is free software; you can redistribute it and/or modify it
6 //# under the terms of the GNU Library General Public License as published by
7 //# the Free Software Foundation; either version 2 of the License, or (at your
8 //# option) any later version.
9 //#
10 //# This library is distributed in the hope that it will be useful, but WITHOUT
11 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13 //# License for more details.
14 //#
15 //# You should have received a copy of the GNU Library General Public License
16 //# along with this library; if not, write to the Free Software Foundation,
17 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
18 //#
19 //# Correspondence concerning AIPS++ should be addressed as follows:
20 //# Internet email: aips2-request@nrao.edu.
21 //# Postal address: AIPS++ Project Office
22 //# National Radio Astronomy Observatory
23 //# 520 Edgemont Road
24 //# Charlottesville, VA 22903-2475 USA
25 //#
26 //# $Id$
27 
28 #ifndef SCIMATH_NUMERICTRAITS_H
29 #define SCIMATH_NUMERICTRAITS_H
30 
31 //# Include files
32 #include <casacore/casa/aips.h>
34 
35 namespace casacore { //# NAMESPACE CASACORE - BEGIN
36 
37 //
38 // <summary> Relationships between numeric data types </summary>
39 // <use visibility=export>
40 //
41 // <reviewed reviewer="nkilleen" date="1996/12/12" tests="tConvolver,tFFTServer">
42 // </reviewed>
43 //
44 // <etymology>
45 // A trait is a characteristic feature. NumericTraits defines relationships
46 // between and characteristics of Numeric data types.
47 // </etymology>
48 //
49 // <synopsis>
50 
51 // This templated class contains a number of typedefs and definitions that
52 // describe the relationship between different numeric data types and there
53 // characteristics. Its use is in templated classes either where the use of one
54 // type implictly implies the use of a corresponding one or where a
55 // characteristic value differs with templating argument. Use of this class
56 // often avoids the need for double templating.
57 //
58 // Currently this class defines the following relationships:
59 // <dl>
60 // <dt> <src>value_type</src>
61 // <dd> The template type itself. The name <src>value_type</src> is the
62 // C++ standard (e.g. <src>DComplex::value_type</src> equals
63 // <src>double</src>)
64 // <dt> <src>BaseType</src>
65 // <dd> The numeric base type. I.e. <src>Double</src> for <src>Double</src>
66 // and <src>DComplex</src>; <src>Float</src> for <src>Float</src> and
67 // <src>Complex</src>
68 // <dt> <src>ConjugateType</src>
69 // <dd> The corresponding complex type for a real type, and real type
70 // for a complex type. It is the type of the result if a Fourier
71 // Transform was to be done.
72 // <dt> <src>PrecisionType</src>
73 // <dd> The Type of the next higher numerical precision. I.e. <src>Double</src>
74 // or <src>DComplex</src>
75 // </dl>
76 //
77 // And the following characteristics:
78 // <dl>
79 // <dt> <src>epsilon</src>
80 // <dd> A Double containing the smallest value such that 1+epsilon is different
81 // from 1.
82 // <dt> <src>minimum</src>
83 // <dd> A Double containing the smallest positive representable number,
84 // excluding denormalised numbers.
85 // <dt> <src>maximum</src>
86 // <dd> A Double containing the largest representable number.
87 // <dt> <src>size()</src>
88 // <dd> The number of numeric values in the templated entity. It will be
89 // 2 for complex numbers; 1 for real numbers.
90 // <dt> <src>setImag(T &other, const BaseType &val)</src>
91 // <dd> Set an imaginary part (for complex numbers) or a NOP (for reals).
92 // <dt> <src>getValue(T &other, const uInt n)</src>
93 // <dd> Get the <src>n%size()-th</src> value in the argument.
94 // For complex numbers the sequence is real, imaginary part.
95 // <dt> <src>setValue(T &other, const BaseType &val, const uInt n)</src>
96 // <dd> Set the <src>n%size()-th</src> value in the argument.
97 // For complex numbers the sequence is real, imaginary part.
98 // </dl>
99 //
100 // For complex numbers these values are applicable to the real or imaginary
101 // components separately.
102 //
103 // The use of this class is best illustrated in a number of examples.
104 //
105 // A default template declaration is required by the C++ standard.
106 // It should never be used, except through the specialisations.
107 // The default types for ConjugateType and PrecisionType are deliberatly set to
108 // a non-numeric type to further discourage the use of the non-specialized
109 // class defined below. It also helps when using this class with the Sun native
110 // compiler.
111 // <note role=warning> The specialized instantiations seem to have a name with
112 // an appended code. This is only for cxx2html reasons. The name is in all
113 // cases <src>NumericTraits</src>
114 // </note>
115 //
116 // This class is implemented as a number of specialisations for the
117 // following data types.
118 // <ul>
119 // <li> Float
120 // <li> Double
121 // <li> Complex
122 // <li> DComplex
123 // </ul>
124 // This class should not be used with other template types and does nothing
125 // except return its template type if it is used. ie. <br>
126 // <src>NumericTraits<ArbitraryType>\::ConjugateType</src> returns
127 // <src>Char</src> and <br>
128 // <src>NumericTraits<ArbitraryType>\::PrecisionType</src> returns
129 // <src>Char</src><br>
130 // <src>NumericTraits<ArbitraryType>\::epsilon</src> is undefined<br>
131 // <src>NumericTraits<ArbitraryType>\::minimum</src> is undefined<br>
132 // <src>NumericTraits<ArbitraryType>\::maximum</src> is undefined
133 // </synopsis>
134 //
135 // <example>
136 // <h4>Example 1:</h4>
137 // Suppose you are writing a templated class that needs to do Fourier
138 // Transforms. The FFTServer class can do FFT's of Float or Double data
139 // types, but you need to doubly template it on the conjugate data type. To
140 // avoid having the conjugate data type appear as a template in the class
141 // you are writing you can use the ConjugateType typedef.
142 // <srcblock>
143 // template<class T> class myClass {
144 // private:
145 // FFTServer<T, NumericTraits<T>::ConjugateType> server;
146 // }
147 // </srcblock>
148 // The ConjugateType transforms
149 // <ul>
150 // <li> Float -> Complex
151 // <li> Double -> DComplex
152 // <li> Complex -> Float
153 // <li> DComplex -> Double
154 // </ul>
155 //
156 // <h4>Example 2:</h4>
157 // Suppose you have a templated numerical integrator class. Because the
158 // individual samples can be negative it is possible to add two numbers
159 // of nearly equal magnitude but opposite sign and lose precision
160 // considerably. One way to combat this is to make the accumulator variable
161 // the next higher precision numerical type. The PrecisionType typedef
162 // defines what type this is
163 // <srcblock>
164 // template<class T> class Integrator {
165 // private:
166 // NumericTraits<T>::PrecisionType accumulator;
167 // }
168 // </srcblock>
169 // The PrecisionType transforms
170 // <ul>
171 // <li> Float -> Double
172 // <li> Double -> Double
173 // <li> Complex -> DComplex
174 // <li> DComplex -> DComplex
175 // </ul>
176 
177 // <h4>Example 3:</h4>
178 // Suppose you have a templated class that needs to use the <src>allNear</src>
179 // functions from
180 // <linkto group="ArrayMath.h#Array mathematical operations">ArrayMath</linkto>
181 // to determine if a templated Array is near
182 // one. The tolerance argument to the allNear function will depend on the
183 // template type and this is not known until the template is instantiated. The
184 // epsilon trait can be used to supply this value.
185 
186 // <srcblock>
187 // template<class T> void myClass<T>::myFunction(Array<T> & aArray) {
188 // if (allNear(aArray, T(1), NumericTraits<T>::epsilon))
189 // return;
190 // // Do something
191 // }
192 // </srcblock>
193 
194 // <dl>
195 // <dt><src>NumericTraits<T>\::epsilon</src>
196 // <dd> is FLT_EPSILON for Float and Complex types and DBL_EPSILON for Double
197 // and DComplex data types.
198 // <dt><src>NumericTraits<T>\::minimum</src>
199 // <dd>is FLT_MIN for Float and complex Types and DBL_MIN for Double and
200 // DComplex data types.
201 // <dt><src>NumericTraits<T>\::maximum</src>
202 // <dd>is FLT_MAX for Float and complex Types and DBL_MAX for Double and
203 // DComplex data types.
204 // </dl>
205 // See the <linkto class=Dummy_Constants_class">C class/namespace</linkto>
206 // for the values of these variables.
207 // </example>
208 //
209 // <motivation>
210 // This is a nice way to make the Convolver class singly templated (as it
211 // should be), even though the FFTServer it contains is doubly templated.
212 // </motivation>
213 //
214 // <thrown>
215 // <li> This class does not throw any exceptions
216 // </thrown>
217 //
218 // <todo asof="2002/06/25">
219 // <li> Nothing (I hope!)
220 // </todo>
221 //
222 
223 template <class T> class NumericTraits {
224 public:
225  // Template argument
226  typedef T value_type;
227  // Numeric type
228  typedef Char BaseType;
229  // Conjugate (<src>real<->complex</src>) type
230  typedef Char ConjugateType;
231  // Higher precision type (<src>Float->Double</src>)
232  typedef Char PrecisionType;
233  // Relevant minimum and maximum numbers
234  // <group>
235  static const Double & epsilon;
236  static const Double & minimum;
237  static const Double & maximum;
238  // </group>
239  // Number of relevant numeric values
240  static uInt size() { return 0; }
241  // Set the imaginary part of a complex value only (a NOP for reals)
242  static void setImag(T &, const BaseType &) {;}
243  // Get the <src>n%size()-th</src> numeric value
244  static BaseType getValue(const T &, const uInt) { return 0; }
245  // Set the <src>n%size()-th</src> numeric value
246  static void setValue(T &, const BaseType &, const uInt) {;}
247 };
248 
249 #if defined NumericTraits_F
250 #undef NumericTraits_F
251 #endif
252 #define NumericTraits_F NumericTraits
253 
254 // <summary>NumericTraits specialization for Float</summary>
255 
256 template <> class NumericTraits_F<Float> {
257 public:
258  // Template argument
259  typedef Float value_type;
260  // Numeric type
261  typedef Float BaseType;
262  // Conjugate (<src>real<->complex</src>) type
264  // Higher precision type (<src>Float->Double</src>)
266  // Relevant minimum and maximum numbers
267  // <group>
268  static const Double & epsilon;
269  static const Double & minimum;
270  static const Double & maximum;
271  // </group>
272  // Number of relevant numeric values
273  static uInt size() { return 1; }
274  // Set the imaginary part of a complex value only (a NOP for reals)
275  static void setImag(value_type &, const BaseType &) {;}
276  // Get the <src>n%size()-th</src> numeric value
277  static BaseType getValue(const value_type &other, const uInt) {
278  return other; }
279  // Set the <src>n%size()-th</src> numeric value
280  static void setValue(value_type &other, const BaseType &val, const uInt) {
281  other = val; }
282 };
283 
284 #undef NumericTraits_F
285 
286 #if defined NumericTraits_D
287 #undef NumericTraits_D
288 #endif
289 #define NumericTraits_D NumericTraits
290 
291 // <summary>NumericTraits specialization for Double</summary>
292 
293 template <> class NumericTraits_D<Double> {
294 public:
295  // Template argument
297  // Numeric type
298  typedef Double BaseType;
299  // Conjugate (<src>real<->complex</src>) type
301  // Higher precision type (<src>Float->Double</src>)
303  // Relevant minimum and maximum numbers
304  // <group>
305  static const Double & epsilon;
306  static const Double & minimum;
307  static const Double & maximum;
308  // </group>
309  // Number of relevant numeric values
310  static uInt size() { return 1; }
311  // Set the imaginary part of a complex value only (a NOP for reals)
312  static void setImag(value_type &, const BaseType &) {;}
313  // Get the <src>n%size()-th</src> numeric value
314  static BaseType getValue(const value_type &other, const uInt) {
315  return other; }
316  // Set the <src>n%size()-th</src> numeric value
317  static void setValue(value_type &other, const BaseType &val, const uInt) {
318  other = val; }
319 };
320 
321 #undef NumericTraits_D
322 
323 #if defined NumericTraits_C
324 #undef NumericTraits_C
325 #endif
326 #define NumericTraits_C NumericTraits
327 
328 // <summary>NumericTraits specialization for Complex</summary>
329 
330 template <> class NumericTraits_C<Complex> {
331 public:
332  // Template argument
334  // Numeric type
335  typedef Float BaseType;
336  // Conjugate (<src>real<->complex</src>) type
338  // Higher precision type (<src>Float->Double</src>)
340  // Relevant minimum and maximum numbers
341  // <group>
342  static const Double & epsilon;
343  static const Double & minimum;
344  static const Double & maximum;
345  // </group>
346  // Number of relevant numeric values
347  static uInt size() { return 2; }
348  // Set the imaginary part of a complex value only (a NOP for reals)
349  static void setImag(value_type &other, const BaseType &val) {
350  other = value_type(other.real(), val); }
351  // Get the <src>n%size()-th</src> numeric value
352  static BaseType getValue(const value_type &other, const uInt n) {
353  return ((n%2 == 0) ? other.real() : other.imag()); }
354  // Set the <src>n%size()-th</src> numeric value
355  static void setValue(value_type &other, const BaseType &val, const uInt n) {
356  other = (n%2 == 0) ? value_type(val, other.imag()) :
357  value_type(other.real(), val); }
358 };
359 
360 #undef NumericTraits_C
361 
362 #if defined NumericTraits_DC
363 #undef NumericTraits_DC
364 #endif
365 #define NumericTraits_DC NumericTraits
366 
367 // <summary>NumericTraits specialization for DComplex</summary>
368 
369 template <> class NumericTraits_DC<DComplex> {
370 public:
371  // Template argument
373  // Numeric type
374  typedef Double BaseType;
375  // Conjugate (<src>real<->complex</src>) type
377  // Higher precision type (<src>Float->Double</src>)
379  // Relevant minimum and maximum numbers
380  // <group>
381  static const Double & epsilon;
382  static const Double & minimum;
383  static const Double & maximum;
384  // </group>
385  // Number of relevant numeric values
386  static uInt size() { return 2; }
387  // Set the imaginary part of a complex value only (a NOP for reals)
388  static void setImag(value_type &other, const BaseType &val) {
389  other = value_type(other.real(), val); }
390  // Get the <src>n%size()-th</src> numeric value
391  static BaseType getValue(const value_type &other, const uInt n) {
392  return ((n%2 == 0) ? other.real() : other.imag()); }
393  // Set the <src>n%size()-th</src> numeric value
394  static void setValue(value_type &other, const BaseType &val, const uInt n) {
395  other = (n%2 == 0) ? value_type(val, other.imag()) :
396  value_type(other.real(), val); }
397 };
398 
399 #undef NumericTraits_DC
400 
401 
402 } //# NAMESPACE CASACORE - END
403 
404 #endif
static void setImag(value_type &, const BaseType &)
Set the imaginary part of a complex value only (a NOP for reals)
static BaseType getValue(const value_type &other, const uInt n)
Get the nsize()-th numeric value.
static uInt size()
Number of relevant numeric values.
static void setValue(T &, const BaseType &, const uInt)
Set the nsize()-th numeric value.
static const Double & epsilon
Relevant minimum and maximum numbers.
char Char
Definition: aipstype.h:46
DComplex PrecisionType
Higher precision type (Float-&gt;Double)
Relationships between numeric data types.
static const Double & epsilon
Relevant minimum and maximum numbers.
Double ConjugateType
Conjugate (real&lt;-&gt;complex) type.
#define NumericTraits_DC
static const Double & epsilon
Relevant minimum and maximum numbers.
static void setImag(value_type &other, const BaseType &val)
Set the imaginary part of a complex value only (a NOP for reals)
static BaseType getValue(const value_type &other, const uInt)
Get the nsize()-th numeric value.
Double PrecisionType
Higher precision type (Float-&gt;Double)
static void setImag(T &, const BaseType &)
Set the imaginary part of a complex value only (a NOP for reals)
static const Double & epsilon
Relevant minimum and maximum numbers.
DComplex ConjugateType
Conjugate (real&lt;-&gt;complex) type.
Double value_type
Template argument.
static BaseType getValue(const T &, const uInt)
Get the nsize()-th numeric value.
Float value_type
Template argument.
Char ConjugateType
Conjugate (real&lt;-&gt;complex) type.
T value_type
Template argument.
Char PrecisionType
Higher precision type (Float-&gt;Double)
Complex ConjugateType
Conjugate (real&lt;-&gt;complex) type.
Float ConjugateType
Conjugate (real&lt;-&gt;complex) type.
static void setImag(value_type &other, const BaseType &val)
Set the imaginary part of a complex value only (a NOP for reals)
static void setValue(value_type &other, const BaseType &val, const uInt)
Set the nsize()-th numeric value.
static void setValue(value_type &other, const BaseType &val, const uInt n)
Set the nsize()-th numeric value.
#define NumericTraits_C
static void setValue(value_type &other, const BaseType &val, const uInt)
Set the nsize()-th numeric value.
double Double
Definition: aipstype.h:55
Complex value_type
Template argument.
static BaseType getValue(const value_type &other, const uInt n)
Get the nsize()-th numeric value.
#define NumericTraits_D
static const Double & epsilon
Relevant minimum and maximum numbers.
DComplex value_type
Template argument.
float Float
Definition: aipstype.h:54
#define NumericTraits_F
static uInt size()
Number of relevant numeric values.
static const Double & maximum
Double PrecisionType
Higher precision type (Float-&gt;Double)
DComplex PrecisionType
Higher precision type (Float-&gt;Double)
static uInt size()
Number of relevant numeric values.
static BaseType getValue(const value_type &other, const uInt)
Get the nsize()-th numeric value.
Char BaseType
Numeric type.
static void setImag(value_type &, const BaseType &)
Set the imaginary part of a complex value only (a NOP for reals)
static void setValue(value_type &other, const BaseType &val, const uInt n)
Set the nsize()-th numeric value.
static uInt size()
Number of relevant numeric values.
static const Double & minimum
unsigned int uInt
Definition: aipstype.h:51
static uInt size()
Number of relevant numeric values.