casacore
Loading...
Searching...
No Matches
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: casa-feedback@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#ifndef SCIMATH_NUMERICTRAITS_H
27#define SCIMATH_NUMERICTRAITS_H
28
29// # Include files
30#include <casacore/casa/aips.h>
31#include <casacore/casa/BasicSL/Complex.h>
32
33namespace casacore { // # NAMESPACE CASACORE - BEGIN
34
35//
36// <summary> Relationships between numeric data types </summary>
37// <use visibility=export>
38//
39// <reviewed reviewer="nkilleen" date="1996/12/12" tests="tConvolver,tFFTServer">
40// </reviewed>
41//
42// <etymology>
43// A trait is a characteristic feature. NumericTraits defines relationships
44// between and characteristics of Numeric data types.
45// </etymology>
46//
47// <synopsis>
48
49// This templated class contains a number of typedefs and definitions that
50// describe the relationship between different numeric data types and there
51// characteristics. Its use is in templated classes either where the use of one
52// type implictly implies the use of a corresponding one or where a
53// characteristic value differs with templating argument. Use of this class
54// often avoids the need for double templating.
55//
56// Currently this class defines the following relationships:
57// <dl>
58// <dt> <src>value_type</src>
59// <dd> The template type itself. The name <src>value_type</src> is the
60// C++ standard (e.g. <src>DComplex::value_type</src> equals
61// <src>double</src>)
62// <dt> <src>BaseType</src>
63// <dd> The numeric base type. I.e. <src>Double</src> for <src>Double</src>
64// and <src>DComplex</src>; <src>Float</src> for <src>Float</src> and
65// <src>Complex</src>
66// <dt> <src>ConjugateType</src>
67// <dd> The corresponding complex type for a real type, and real type
68// for a complex type. It is the type of the result if a Fourier
69// Transform was to be done.
70// <dt> <src>PrecisionType</src>
71// <dd> The Type of the next higher numerical precision. I.e. <src>Double</src>
72// or <src>DComplex</src>
73// </dl>
74//
75// And the following characteristics:
76// <dl>
77// <dt> <src>epsilon</src>
78// <dd> A Double containing the smallest value such that 1+epsilon is different
79// from 1.
80// <dt> <src>minimum</src>
81// <dd> A Double containing the smallest positive representable number,
82// excluding denormalised numbers.
83// <dt> <src>maximum</src>
84// <dd> A Double containing the largest representable number.
85// <dt> <src>size()</src>
86// <dd> The number of numeric values in the templated entity. It will be
87// 2 for complex numbers; 1 for real numbers.
88// <dt> <src>setImag(T &other, const BaseType &val)</src>
89// <dd> Set an imaginary part (for complex numbers) or a NOP (for reals).
90// <dt> <src>getValue(T &other, const uInt n)</src>
91// <dd> Get the <src>n%size()-th</src> value in the argument.
92// For complex numbers the sequence is real, imaginary part.
93// <dt> <src>setValue(T &other, const BaseType &val, const uInt n)</src>
94// <dd> Set the <src>n%size()-th</src> value in the argument.
95// For complex numbers the sequence is real, imaginary part.
96// </dl>
97//
98// For complex numbers these values are applicable to the real or imaginary
99// components separately.
100//
101// The use of this class is best illustrated in a number of examples.
102//
103// A default template declaration is required by the C++ standard.
104// It should never be used, except through the specialisations.
105// The default types for ConjugateType and PrecisionType are deliberatly set to
106// a non-numeric type to further discourage the use of the non-specialized
107// class defined below. It also helps when using this class with the Sun native
108// compiler.
109// <note role=warning> The specialized instantiations seem to have a name with
110// an appended code. This is only for cxx2html reasons. The name is in all
111// cases <src>NumericTraits</src>
112// </note>
113//
114// This class is implemented as a number of specialisations for the
115// following data types.
116// <ul>
117// <li> Float
118// <li> Double
119// <li> Complex
120// <li> DComplex
121// </ul>
122// This class should not be used with other template types and does nothing
123// except return its template type if it is used. ie. <br>
124// <src>NumericTraits<ArbitraryType>\::ConjugateType</src> returns
125// <src>Char</src> and <br>
126// <src>NumericTraits<ArbitraryType>\::PrecisionType</src> returns
127// <src>Char</src><br>
128// <src>NumericTraits<ArbitraryType>\::epsilon</src> is undefined<br>
129// <src>NumericTraits<ArbitraryType>\::minimum</src> is undefined<br>
130// <src>NumericTraits<ArbitraryType>\::maximum</src> is undefined
131// </synopsis>
132//
133// <example>
134// <h4>Example 1:</h4>
135// Suppose you are writing a templated class that needs to do Fourier
136// Transforms. The FFTServer class can do FFT's of Float or Double data
137// types, but you need to doubly template it on the conjugate data type. To
138// avoid having the conjugate data type appear as a template in the class
139// you are writing you can use the ConjugateType typedef.
140// <srcblock>
141// template<class T> class myClass {
142// private:
143// FFTServer<T, NumericTraits<T>::ConjugateType> server;
144// }
145// </srcblock>
146// The ConjugateType transforms
147// <ul>
148// <li> Float -> Complex
149// <li> Double -> DComplex
150// <li> Complex -> Float
151// <li> DComplex -> Double
152// </ul>
153//
154// <h4>Example 2:</h4>
155// Suppose you have a templated numerical integrator class. Because the
156// individual samples can be negative it is possible to add two numbers
157// of nearly equal magnitude but opposite sign and lose precision
158// considerably. One way to combat this is to make the accumulator variable
159// the next higher precision numerical type. The PrecisionType typedef
160// defines what type this is
161// <srcblock>
162// template<class T> class Integrator {
163// private:
164// NumericTraits<T>::PrecisionType accumulator;
165// }
166// </srcblock>
167// The PrecisionType transforms
168// <ul>
169// <li> Float -> Double
170// <li> Double -> Double
171// <li> Complex -> DComplex
172// <li> DComplex -> DComplex
173// </ul>
174
175// <h4>Example 3:</h4>
176// Suppose you have a templated class that needs to use the <src>allNear</src>
177// functions from
178// <linkto group="ArrayMath.h#Array mathematical operations">ArrayMath</linkto>
179// to determine if a templated Array is near
180// one. The tolerance argument to the allNear function will depend on the
181// template type and this is not known until the template is instantiated. The
182// epsilon trait can be used to supply this value.
183
184// <srcblock>
185// template<class T> void myClass<T>::myFunction(Array<T> & aArray) {
186// if (allNear(aArray, T(1), NumericTraits<T>::epsilon))
187// return;
188// // Do something
189// }
190// </srcblock>
191
192// <dl>
193// <dt><src>NumericTraits<T>\::epsilon</src>
194// <dd> is FLT_EPSILON for Float and Complex types and DBL_EPSILON for Double
195// and DComplex data types.
196// <dt><src>NumericTraits<T>\::minimum</src>
197// <dd>is FLT_MIN for Float and complex Types and DBL_MIN for Double and
198// DComplex data types.
199// <dt><src>NumericTraits<T>\::maximum</src>
200// <dd>is FLT_MAX for Float and complex Types and DBL_MAX for Double and
201// DComplex data types.
202// </dl>
203// See the <linkto class=Dummy_Constants_class">C class/namespace</linkto>
204// for the values of these variables.
205// </example>
206//
207// <motivation>
208// This is a nice way to make the Convolver class singly templated (as it
209// should be), even though the FFTServer it contains is doubly templated.
210// </motivation>
211//
212// <thrown>
213// <li> This class does not throw any exceptions
214// </thrown>
215//
216// <todo asof="2002/06/25">
217// <li> Nothing (I hope!)
218// </todo>
219//
220
221template <class T>
223 public:
224 // Template argument
225 typedef T value_type;
226 // Numeric type
227 typedef Char BaseType;
228 // Conjugate (<src>real<->complex</src>) type
230 // Higher precision type (<src>Float->Double</src>)
232 // Relevant minimum and maximum numbers
233 // <group>
234 static const Double &epsilon;
235 static const Double &minimum;
236 static const Double &maximum;
237 // </group>
238 // Number of relevant numeric values
239 static uInt size() { return 0; }
240 // Set the imaginary part of a complex value only (a NOP for reals)
241 static void setImag(T &, const BaseType &) { ; }
242 // Get the <src>n%size()-th</src> numeric value
243 static BaseType getValue(const T &, const uInt) { return 0; }
244 // Set the <src>n%size()-th</src> numeric value
245 static void setValue(T &, const BaseType &, const uInt) { ; }
246};
247
248#if defined NumericTraits_F
249#undef NumericTraits_F
250#endif
251#define NumericTraits_F NumericTraits
252
253// <summary>NumericTraits specialization for Float</summary>
254
255template <>
257 public:
258 // Template argument
260 // Numeric type
262 // Conjugate (<src>real<->complex</src>) type
263 typedef Complex ConjugateType;
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) { return other; }
278 // Set the <src>n%size()-th</src> numeric value
279 static void setValue(value_type &other, const BaseType &val, const uInt) { other = val; }
280};
281
282#undef NumericTraits_F
283
284#if defined NumericTraits_D
285#undef NumericTraits_D
286#endif
287#define NumericTraits_D NumericTraits
288
289// <summary>NumericTraits specialization for Double</summary>
290
291template <>
293 public:
294 // Template argument
296 // Numeric type
298 // Conjugate (<src>real<->complex</src>) type
299 typedef DComplex ConjugateType;
300 // Higher precision type (<src>Float->Double</src>)
302 // Relevant minimum and maximum numbers
303 // <group>
304 static const Double &epsilon;
305 static const Double &minimum;
306 static const Double &maximum;
307 // </group>
308 // Number of relevant numeric values
309 static uInt size() { return 1; }
310 // Set the imaginary part of a complex value only (a NOP for reals)
311 static void setImag(value_type &, const BaseType &) { ; }
312 // Get the <src>n%size()-th</src> numeric value
313 static BaseType getValue(const value_type &other, const uInt) { return other; }
314 // Set the <src>n%size()-th</src> numeric value
315 static void setValue(value_type &other, const BaseType &val, const uInt) { other = val; }
316};
317
318#undef NumericTraits_D
319
320#if defined NumericTraits_C
321#undef NumericTraits_C
322#endif
323#define NumericTraits_C NumericTraits
324
325// <summary>NumericTraits specialization for Complex</summary>
326
327template <>
328class NumericTraits_C<Complex> {
329 public:
330 // Template argument
331 typedef Complex value_type;
332 // Numeric type
334 // Conjugate (<src>real<->complex</src>) type
336 // Higher precision type (<src>Float->Double</src>)
337 typedef DComplex PrecisionType;
338 // Relevant minimum and maximum numbers
339 // <group>
340 static const Double &epsilon;
341 static const Double &minimum;
342 static const Double &maximum;
343 // </group>
344 // Number of relevant numeric values
345 static uInt size() { return 2; }
346 // Set the imaginary part of a complex value only (a NOP for reals)
347 static void setImag(value_type &other, const BaseType &val) {
348 other = value_type(other.real(), val);
349 }
350 // Get the <src>n%size()-th</src> numeric value
351 static BaseType getValue(const value_type &other, const uInt n) {
352 return ((n % 2 == 0) ? other.real() : other.imag());
353 }
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()) : value_type(other.real(), val);
357 }
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
369template <>
370class NumericTraits_DC<DComplex> {
371 public:
372 // Template argument
373 typedef DComplex value_type;
374 // Numeric type
376 // Conjugate (<src>real<->complex</src>) type
378 // Higher precision type (<src>Float->Double</src>)
379 typedef DComplex PrecisionType;
380 // Relevant minimum and maximum numbers
381 // <group>
382 static const Double &epsilon;
383 static const Double &minimum;
384 static const Double &maximum;
385 // </group>
386 // Number of relevant numeric values
387 static uInt size() { return 2; }
388 // Set the imaginary part of a complex value only (a NOP for reals)
389 static void setImag(value_type &other, const BaseType &val) {
390 other = value_type(other.real(), val);
391 }
392 // Get the <src>n%size()-th</src> numeric value
393 static BaseType getValue(const value_type &other, const uInt n) {
394 return ((n % 2 == 0) ? other.real() : other.imag());
395 }
396 // Set the <src>n%size()-th</src> numeric value
397 static void setValue(value_type &other, const BaseType &val, const uInt n) {
398 other = (n % 2 == 0) ? value_type(val, other.imag()) : value_type(other.real(), val);
399 }
400};
401
402#undef NumericTraits_DC
403
404} // namespace casacore
405
406#endif
#define NumericTraits_F
#define NumericTraits_C
#define NumericTraits_DC
#define NumericTraits_D
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 n)
Set the nsize()-th numeric value.
static BaseType getValue(const value_type &other, const uInt n)
Get the nsize()-th numeric value.
DComplex PrecisionType
Higher precision type (Float->Double).
static const Double & epsilon
Relevant minimum and maximum numbers.
Float ConjugateType
Conjugate (real<->complex) type.
static uInt size()
Number of relevant numeric values.
Complex value_type
Template argument.
DComplex value_type
Template argument.
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 n)
Set the nsize()-th numeric value.
static uInt size()
Number of relevant numeric values.
static const Double & epsilon
Relevant minimum and maximum numbers.
DComplex PrecisionType
Higher precision type (Float->Double).
static BaseType getValue(const value_type &other, const uInt n)
Get the nsize()-th numeric value.
Double ConjugateType
Conjugate (real<->complex) type.
Double PrecisionType
Higher precision type (Float->Double).
Double value_type
Template argument.
DComplex ConjugateType
Conjugate (real<->complex) type.
static uInt size()
Number of relevant numeric values.
static BaseType getValue(const value_type &other, const uInt)
Get the nsize()-th numeric value.
static void setValue(value_type &other, const BaseType &val, const uInt)
Set the nsize()-th numeric value.
static void setImag(value_type &, const BaseType &)
Set the imaginary part of a complex value only (a NOP for reals).
static const Double & epsilon
Relevant minimum and maximum numbers.
static BaseType getValue(const value_type &other, const uInt)
Get the nsize()-th numeric value.
Float value_type
Template argument.
static const Double & epsilon
Relevant minimum and maximum numbers.
Double PrecisionType
Higher precision type (Float->Double).
Complex ConjugateType
Conjugate (real<->complex) type.
static void setValue(value_type &other, const BaseType &val, const uInt)
Set the nsize()-th numeric value.
static uInt size()
Number of relevant numeric values.
static void setImag(value_type &, const BaseType &)
Set the imaginary part of a complex value only (a NOP for reals).
static void setValue(T &, const BaseType &, const uInt)
Set the nsize()-th numeric value.
static void setImag(T &, const BaseType &)
Set the imaginary part of a complex value only (a NOP for reals).
static const Double & minimum
static const Double & maximum
static uInt size()
Number of relevant numeric values.
static BaseType getValue(const T &, const uInt)
Get the nsize()-th numeric value.
static const Double & epsilon
For temporary backward namespace compatibility, use casa as alias for casacore.
Definition mainpage.dox:28
unsigned int uInt
Definition aipstype.h:49
float Float
Definition aipstype.h:52
double Double
Definition aipstype.h:53
char Char
Definition aipstype.h:44