casacore
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>
33#include <casacore/casa/BasicSL/Complex.h>
34
35namespace 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
223template <class T> class NumericTraits {
224public:
225 // Template argument
226 typedef T value_type;
227 // Numeric type
228 typedef Char BaseType;
229 // Conjugate (<src>real<->complex</src>) type
231 // Higher precision type (<src>Float->Double</src>)
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
256template <> class NumericTraits_F<Float> {
257public:
258 // Template argument
260 // Numeric type
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
293template <> class NumericTraits_D<Double> {
294public:
295 // Template argument
297 // Numeric type
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
330template <> class NumericTraits_C<Complex> {
331public:
332 // Template argument
334 // Numeric type
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
369template <> class NumericTraits_DC<DComplex> {
370public:
371 // Template argument
373 // Numeric type
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
#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.
Char BaseType
Numeric type.
static void setImag(T &, const BaseType &)
Set the imaginary part of a complex value only (a NOP for reals)
static const Double & minimum
Char ConjugateType
Conjugate (real<->complex) type.
static const Double & maximum
Char PrecisionType
Higher precision type (Float->Double)
static uInt size()
Number of relevant numeric values.
T value_type
Template argument.
static BaseType getValue(const T &, const uInt)
Get the nsize()-th numeric value.
static const Double & epsilon
Relevant minimum and maximum numbers.
this file contains all the compiler specific defines
Definition: mainpage.dox:28
unsigned int uInt
Definition: aipstype.h:51
float Float
Definition: aipstype.h:54
double Double
Definition: aipstype.h:55
char Char
Definition: aipstype.h:46