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> class NumericTraits {
222public:
223 // Template argument
224 typedef T value_type;
225 // Numeric type
226 typedef Char BaseType;
227 // Conjugate (<src>real<->complex</src>) type
229 // Higher precision type (<src>Float->Double</src>)
231 // Relevant minimum and maximum numbers
232 // <group>
233 static const Double & epsilon;
234 static const Double & minimum;
235 static const Double & maximum;
236 // </group>
237 // Number of relevant numeric values
238 static uInt size() { return 0; }
239 // Set the imaginary part of a complex value only (a NOP for reals)
240 static void setImag(T &, const BaseType &) {;}
241 // Get the <src>n%size()-th</src> numeric value
242 static BaseType getValue(const T &, const uInt) { return 0; }
243 // Set the <src>n%size()-th</src> numeric value
244 static void setValue(T &, const BaseType &, const uInt) {;}
245};
246
247#if defined NumericTraits_F
248#undef NumericTraits_F
249#endif
250#define NumericTraits_F NumericTraits
251
252// <summary>NumericTraits specialization for Float</summary>
253
254template <> class NumericTraits_F<Float> {
255public:
256 // Template argument
258 // Numeric type
260 // Conjugate (<src>real<->complex</src>) type
261 typedef Complex ConjugateType;
262 // Higher precision type (<src>Float->Double</src>)
264 // Relevant minimum and maximum numbers
265 // <group>
266 static const Double & epsilon;
267 static const Double & minimum;
268 static const Double & maximum;
269 // </group>
270 // Number of relevant numeric values
271 static uInt size() { return 1; }
272 // Set the imaginary part of a complex value only (a NOP for reals)
273 static void setImag(value_type &, const BaseType &) {;}
274 // Get the <src>n%size()-th</src> numeric value
275 static BaseType getValue(const value_type &other, const uInt) {
276 return other; }
277 // Set the <src>n%size()-th</src> numeric value
278 static void setValue(value_type &other, const BaseType &val, const uInt) {
279 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 <> class NumericTraits_D<Double> {
292public:
293 // Template argument
295 // Numeric type
297 // Conjugate (<src>real<->complex</src>) type
298 typedef DComplex ConjugateType;
299 // Higher precision type (<src>Float->Double</src>)
301 // Relevant minimum and maximum numbers
302 // <group>
303 static const Double & epsilon;
304 static const Double & minimum;
305 static const Double & maximum;
306 // </group>
307 // Number of relevant numeric values
308 static uInt size() { return 1; }
309 // Set the imaginary part of a complex value only (a NOP for reals)
310 static void setImag(value_type &, const BaseType &) {;}
311 // Get the <src>n%size()-th</src> numeric value
312 static BaseType getValue(const value_type &other, const uInt) {
313 return other; }
314 // Set the <src>n%size()-th</src> numeric value
315 static void setValue(value_type &other, const BaseType &val, const uInt) {
316 other = val; }
317};
318
319#undef NumericTraits_D
320
321#if defined NumericTraits_C
322#undef NumericTraits_C
323#endif
324#define NumericTraits_C NumericTraits
325
326// <summary>NumericTraits specialization for Complex</summary>
327
328template <> class NumericTraits_C<Complex> {
329public:
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 // Get the <src>n%size()-th</src> numeric value
350 static BaseType getValue(const value_type &other, const uInt n) {
351 return ((n%2 == 0) ? other.real() : other.imag()); }
352 // Set the <src>n%size()-th</src> numeric value
353 static void setValue(value_type &other, const BaseType &val, const uInt n) {
354 other = (n%2 == 0) ? value_type(val, other.imag()) :
355 value_type(other.real(), val); }
356};
357
358#undef NumericTraits_C
359
360#if defined NumericTraits_DC
361#undef NumericTraits_DC
362#endif
363#define NumericTraits_DC NumericTraits
364
365// <summary>NumericTraits specialization for DComplex</summary>
366
367template <> class NumericTraits_DC<DComplex> {
368public:
369 // Template argument
370 typedef DComplex value_type;
371 // Numeric type
373 // Conjugate (<src>real<->complex</src>) type
375 // Higher precision type (<src>Float->Double</src>)
376 typedef DComplex PrecisionType;
377 // Relevant minimum and maximum numbers
378 // <group>
379 static const Double & epsilon;
380 static const Double & minimum;
381 static const Double & maximum;
382 // </group>
383 // Number of relevant numeric values
384 static uInt size() { return 2; }
385 // Set the imaginary part of a complex value only (a NOP for reals)
386 static void setImag(value_type &other, const BaseType &val) {
387 other = value_type(other.real(), val); }
388 // Get the <src>n%size()-th</src> numeric value
389 static BaseType getValue(const value_type &other, const uInt n) {
390 return ((n%2 == 0) ? other.real() : other.imag()); }
391 // Set the <src>n%size()-th</src> numeric value
392 static void setValue(value_type &other, const BaseType &val, const uInt n) {
393 other = (n%2 == 0) ? value_type(val, other.imag()) :
394 value_type(other.real(), val); }
395};
396
397#undef NumericTraits_DC
398
399
400} //# NAMESPACE CASACORE - END
401
402#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:49
float Float
Definition aipstype.h:52
double Double
Definition aipstype.h:53
char Char
Definition aipstype.h:44