[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

numerictraits.hxx
1 /************************************************************************/
2 /* */
3 /* Copyright 1998-2002 by Ullrich Koethe */
4 /* */
5 /* This file is part of the VIGRA computer vision library. */
6 /* The VIGRA Website is */
7 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
8 /* Please direct questions, bug reports, and contributions to */
9 /* ullrich.koethe@iwr.uni-heidelberg.de or */
10 /* vigra@informatik.uni-hamburg.de */
11 /* */
12 /* Permission is hereby granted, free of charge, to any person */
13 /* obtaining a copy of this software and associated documentation */
14 /* files (the "Software"), to deal in the Software without */
15 /* restriction, including without limitation the rights to use, */
16 /* copy, modify, merge, publish, distribute, sublicense, and/or */
17 /* sell copies of the Software, and to permit persons to whom the */
18 /* Software is furnished to do so, subject to the following */
19 /* conditions: */
20 /* */
21 /* The above copyright notice and this permission notice shall be */
22 /* included in all copies or substantial portions of the */
23 /* Software. */
24 /* */
25 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32 /* OTHER DEALINGS IN THE SOFTWARE. */
33 /* */
34 /************************************************************************/
35 
36 
37 #ifndef VIGRA_NUMERICTRAITS_HXX
38 #define VIGRA_NUMERICTRAITS_HXX
39 
40 #include <climits>
41 #include <limits>
42 #include <cfloat>
43 #include <complex>
44 #include "metaprogramming.hxx"
45 #include "sized_int.hxx"
46 
47 /********************************************************/
48 /* */
49 /* NumericTraits */
50 /* */
51 /********************************************************/
52 
53 
54 /** \page NumericPromotionTraits Numeric and Promotion Traits
55 
56  Meta-information about arithmetic types.
57 
58  <UL style="list-style-image:url(documents/bullet.gif)">
59  <LI> \ref NumericTraits
60  <BR>&nbsp;&nbsp;&nbsp;<em>Unary traits for promotion, conversion, creation of arithmetic objects</em>
61  <LI> \ref PromoteTraits
62  <BR>&nbsp;&nbsp;&nbsp;<em>Binary traits for promotion of arithmetic objects</em>
63  <LI> \ref SquareRootTraits
64  <BR>&nbsp;&nbsp;&nbsp;<em>Unary traits for the calculation of the square root of arithmetic objects</em>
65  <LI> \ref NormTraits
66  <BR>&nbsp;&nbsp;&nbsp;<em>Unary traits for the calculation of the norm and squared norm of arithmetic objects</em>
67  </UL>
68 
69  These traits classes contain information that is used by generic
70  algorithms and data structures to determine intermediate and result
71  types of numerical calculations, to convert between different
72  representations of arithmetic types, and to create certain important
73  constants of each type. Thus, algorithms and data structures
74  operating that need arithmetic operations can be made more
75  independent from the actual data representation.
76 
77  NumericTraits are implemented as template specializations of one
78  arithmetic type, while PromoteTraits are specialized for a pair of
79  arithmetic types that shall be combined in one operation.
80 */
81 
82 /** \page NumericTraits template<> struct NumericTraits<ArithmeticType>
83 
84  Unary traits for promotion, conversion, creation of arithmetic objects.
85 
86  <b>\#include</b>
87  <<a href="numerictraits_8hxx-source.html">vigra/numerictraits.hxx</a>>
88 
89  This traits class is used derive important properties of
90  an arithmetic type. Consider the following algorithm:
91 
92  \code
93  // calculate the sum of a sequence of bytes
94  int sumBytes(unsigned char * begin, unsigned char * end)
95  {
96  int result = 0;
97  for(; begin != end; ++begin) result += *begin;
98  return result;
99  }
100  \endcode
101 
102  The return type of this function can not be 'unsigned char' because
103  the summation would very likely overflow. Since we know the source
104  type, we can easily choose 'int' as an appropriate return type.
105  Likewise, we would have choosen 'float' if we had to sum a
106  sequence of floats. If we want to make this
107  algorithm generic, we would like to derive the appropriate return
108  type automatically. This can be done with NumericTraits.
109  The code would look like this (we use \ref DataAccessors to
110  read the data from the sequence):
111 
112  \code
113  // calculate the sum of any sequence
114  template <class Iterator, class Accessor>
115  typename vigra::NumericTraits<typename Accessor::value_type>::Promote
116  sumSequence(Iterator begin, Iterator end, Accessor a)
117  {
118  // an abbreviation
119  typedef vigra::NumericTraits<typename Accessor::value_type> SrcTraits;
120 
121  // find out result type
122  typedef typename SrcTraits::Promote ResultType;
123 
124  // init result to zero
125  ResultType result = vigra::NumericTraits<ResultType>::zero();
126 
127  for(; begin != end; ++begin)
128  {
129  // cast current item to ResultType and add
130  result += SrcTraits::toPromote(a(begin));
131  }
132 
133  return result;
134  }
135  \endcode
136 
137  In this example NumericTraits is not only used to deduce the
138  ReturnType of the operation, but also to initialize it with the
139  constant 'zero'. This is necessary since we do not know in general,
140  which expression must be used to obtain a zero of some arbitrary
141  type - '<TT>ResultType result = 0;</TT>' would only work if the
142  ResultType had an constructor taking an '<TT>int</TT>' argument, and we
143  would not even have any guarantee as to what the semantics of this
144  constructor are. In addition, the traits are used to cast the
145  source type into the promote type.
146 
147  Similarly, an algorithm that needs multiplication would use the
148  return type <TT>RealPromote</TT> and the functions <TT>one()</TT> and
149  <TT>toRealPromote()</TT>. The following members are defined in
150  <b> <TT>NumericTraits<ArithmeticType></TT></b>:
151 
152  <table>
153  <tr><td>
154  <b> <TT>typedef ... Type;</TT></b>
155  </td><td>
156 
157  the type itself
158 
159  </td></tr>
160  <tr><td>
161  <b> <TT>typedef ... Promote;</TT></b>
162  </td><td>
163 
164  promote type for addition and subtraction
165 
166  </td></tr>
167  <tr><td>
168  <b> <TT>typedef ... RealPromote;</TT></b>
169  </td><td>
170  promote type for multiplication and division with a real number
171 
172  (only defined if <TT>ArithmeticType</TT> supports these operations)
173 
174  </td></tr>
175  <tr><td>
176  <b> <TT>typedef ... ComplexPromote;</TT></b>
177  </td><td>
178 
179  promote type for complex arithmetic
180 
181  </td></tr>
182  <tr><td>
183  <b> <TT>typedef ... ValueType;</TT></b>
184  </td><td>
185 
186  for scalar types: the type itself<br>
187  otherwise: typename Type::value_type (if defined)
188 
189  </td></tr>
190  <tr><td>
191  <b> <TT>static Promote toPromote(ArithmeticType v);</TT></b>
192  </td><td>
193  convert to <TT>Promote</TT> type
194 
195  </td></tr>
196  <tr><td>
197  <b> <TT>static RealPromote toRealPromote(ArithmeticType v);</TT></b>
198  </td><td>
199  convert to <TT>RealPromote</TT> type
200 
201  (only defined if <TT>ArithmeticType</TT> supports multiplication)
202 
203  </td></tr>
204  <tr><td>
205  <b> <TT>static ArithmeticType fromPromote(Promote v);</TT></b>
206  </td><td>
207  convert from <TT>Promote</TT> type
208 
209  if <TT>v</TT> is outside the range of <TT>ArithmeticType</TT> it is clipped;
210 
211  </td></tr>
212  <tr><td>
213  <b> <TT>static ArithmeticType fromRealPromote(RealPromote v);</TT></b>
214  </td><td>
215  convert from <TT>RealPromote</TT> type
216 
217  (only defined if
218  <TT>ArithmeticType</TT> supports multiplication)
219 
220  if <TT>ArithmeticType</TT> is an integral type, the result is rounded
221 
222  if <TT>v</TT> is outside the range of <TT>ArithmeticType</TT> it is clipped
223 
224  </td></tr>
225  <tr><td>
226  <b> <TT>static ArithmeticType zero();</TT></b>
227  </td><td>
228  create neutral element of addition
229 
230  i.e. <TT>(ArithmeticType a = ...,</TT>
231  <TT> a + NumericTraits<ArithmeticType>::zero() == a)</TT>
232  must always yield <TT>true</TT>
233 
234  </td></tr>
235  <tr><td>
236  <b> <TT>static ArithmeticType nonZero();</TT></b>
237  </td><td>
238  create a non-zero element (if multiplication is defined, this yields one())
239 
240  i.e. <TT>(ArithmeticType a = ...,</TT>
241  <TT> a + NumericTraits<ArithmeticType>::nonZero() == a)</TT>
242  must always yield <TT>false</TT>
243 
244  </td></tr>
245  <tr><td>
246  <b> <TT>static ArithmeticType min();</TT></b>
247  </td><td>
248  the smallest number representable in this type.<br>
249  Only available if isOrdered is VigraTrueType. For integral types,
250  this equals <TT>INT_MIN</TT> etc., for real valued types it is <TT>-FLT_MAX</TT>
251  etc. (<b>not</b> <TT>FLT_MIN</TT> -- this is the smallest positive <tt>float</tt>)
252 
253  </td></tr>
254  <tr><td>
255  <b> <TT>static ArithmeticType max();</TT></b>
256  </td><td>
257  the largest number representable in this type.<br>
258  Only available if isOrdered is VigraTrueType. For integral types,
259  this equals <TT>INT_MAX</TT> etc., for real valued types it is <TT>FLT_MAX</TT>
260  etc.
261 
262  </td></tr>
263  <tr><td>
264  <b> <TT>static ArithmeticType one();</TT></b>
265  </td><td>
266  create neutral element of multiplication
267 
268  (only defined if <TT>ArithmeticType</TT> supports multiplication)
269 
270  i.e. <TT>(ArithmeticType a = ...,</TT>
271  <TT> a * NumericTraits<ArithmeticType>::one() == a)</TT>
272  must always yield <TT>true</TT>
273 
274  </td></tr>
275  <tr><td>
276  <b> <TT>typedef ... isIntegral;</TT></b>
277  </td><td>
278  VigraTrueType if <TT>ArithmeticType</TT> is an integral type,
279  VigraFalseType otherwise
280 
281  </td></tr>
282  <tr><td>
283  <b> <TT>typedef ... isScalar;</TT></b>
284  </td><td>
285  VigraTrueType if <TT>ArithmeticType</TT> is a scalar type,
286  VigraFalseType otherwise
287 
288  </td></tr>
289  <tr><td>
290  <tr><td>
291  <b> <TT>typedef ... isSigned;</TT></b>
292  </td><td>
293  VigraTrueType if <TT>ArithmeticType</TT> is a signed type,
294  VigraFalseType otherwise
295 
296  </td></tr>
297  <tr><td>
298  <tr><td>
299  <b> <TT>typedef ... isOrdered;</TT></b>
300  </td><td>
301  VigraTrueType if <TT>ArithmeticType</TT> supports operator<(),
302  VigraFalseType otherwise
303 
304  </td></tr>
305  <tr><td>
306  <b> <TT>typedef ... isComplex;</TT></b>
307  </td><td>
308  VigraTrueType if <TT>ArithmeticType</TT> is a complex number,
309  VigraFalseType otherwise
310 
311  </td></tr>
312  <tr><td>
313  </table>
314 
315  NumericTraits for the built-in types are defined in <b>\#include</b>
316  <<a href="numerictraits_8hxx-source.html">vigra/numerictraits.hxx</a>>
317 
318  Namespace: vigra
319 
320 */
321 
322 /** \page PromoteTraits template<> struct PromoteTraits<ArithmeticType1, ArithmeticType2>
323 
324  Binary traits for promotion of arithmetic objects.
325 
326  <b>\#include</b>
327  <<a href="numerictraits_8hxx-source.html">vigra/numerictraits.hxx</a>>
328 
329  This traits class is used to determine the appropriate result type
330  of arithmetic expressions which depend of two arguments. Consider
331  the following function:
332 
333  \code
334  template <class T>
335  T min(T t1, T t2)
336  {
337  return (t1 < t2) ? t1 : t2;
338  }
339  \endcode
340 
341  This template is only applicable if both arguments have the same
342  type. However, sometimes we may want to use the function in cases
343  where the argument types differ. The we can deduce the approrpiate
344  return type by using <TT>PromoteTraits</TT>:
345 
346  \code
347  template <class T1, class T2>
348  typename vigra::PromoteTraits<T1, T2>::Promote
349  min(T1 t1, T2 t2)
350  {
351  return (t1 < t2) ? vigra::PromoteTraits<T1, T2>::toPromote(t1) :
352  vigra::PromoteTraits<T1, T2>::toPromote(t2);
353  }
354  \endcode
355 
356  In addition, the traits class provide static functions to cast the
357  arguments to the promote type. For example, if <TT>T1</TT> were <TT>int</TT> and
358  <TT>T2</TT> were <TT>float</TT>, the <TT>Promote</TT> type would be <TT>float</TT>.
359  The following members are defined in
360  <b> <TT>PromoteTraits<ArithmeticType1, ArithmeticType2></TT></b>:
361 
362  <table>
363  <tr>
364  <td>
365  <b> <TT>typedef ... Promote;</TT></b>
366  </td><td>
367  promote type
368  </td></tr>
369  <tr><td>
370  <b> <TT>static Promote toPromote(ArithmeticType1 v);</TT></b>
371 
372  <b> <TT>static Promote toPromote(ArithmeticType2 v);</TT></b>
373  </td><td>
374  convert to <TT>Promote</TT> type
375  </td></tr>
376  </table>
377 
378  PromoteTraits for the built-in types are defined in <b>\#include</b>
379  <<a href="numerictraits_8hxx-source.html">vigra/numerictraits.hxx</a>>
380 
381  Namespace: vigra
382 */
383 
384 /** \page SquareRootTraits template<> struct SquareRootTraits<ArithmeticType>
385 
386  Unary traits for the calculation of the square root of arithmetic objects.
387 
388  <b>\#include</b>
389  <<a href="numerictraits_8hxx-source.html">vigra/numerictraits.hxx</a>>
390 
391  This traits class is used to determine appropriate argument and result types
392  for the function sqrt(). These traits are typically used like this:
393 
394  \code
395  ArithmeticType t = ...;
396  SquareRootTraits<ArithmeticType>::SquareRootResult r =
397  sqrt((SquareRootTraits<ArithmeticType>::SquareRootArgument)t);
398  \endcode
399 
400  This approach avoids 'ambigouos overload errors' when taking the square root of
401  an integer type. It also takes care of determining the proper result of the
402  sqrt() function of \ref vigra::FixedPoint and of the norm() function, when
403  it is implemented via sqrt(squaredNorm(x)).
404  The following members are defined in <b> <TT>SquareRootTraits<ArithmeticType></TT></b>:
405 
406  <table>
407  <tr><td>
408  <b> <TT>typedef ArithmeticType Type;</TT></b>
409  </td><td>
410  the type itself
411  </td></tr>
412  <tr><td>
413  <b> <TT>typedef ... SquareRootArgument;</TT></b>
414  </td><td>
415  required argument type for srqt(), i.e. <tt>sqrt((SquareRootArgument)x)</tt>
416  </td></tr>
417  <tr><td>
418  <b> <TT>typedef ... SquareRootResult;</TT></b>
419  </td><td>
420  result of <tt>sqrt((SquareRootArgument)x)</tt>
421  </td></tr>
422  </table>
423 
424  NormTraits for the built-in types are defined in <b>\#include</b>
425  <<a href="numerictraits_8hxx-source.html">vigra/numerictraits.hxx</a>>
426 
427  Namespace: vigra
428 */
429 
430 /** \page NormTraits template<> struct NormTraits<ArithmeticType>
431 
432  Unary traits for the calculation of the norm and squared norm of arithmetic objects.
433 
434  <b>\#include</b>
435  <<a href="numerictraits_8hxx-source.html">vigra/numerictraits.hxx</a>>
436 
437  This traits class is used to determine appropriate result types
438  for the functions norm() and squaredNorm(). These functions are always
439  declared like this (where <tt>ArithmeticType</tt> is a type thats supports a norm):
440 
441  \code
442  NormTraits<ArithmeticType>::NormType norm(ArithmeticType const & t);
443  NormTraits<ArithmeticType>::SquaredNormType squaredNorm(ArithmeticType const & t);
444  \endcode
445 
446  The following members are defined in <b> <TT>NormTraits<ArithmeticType></TT></b>:
447 
448  <table>
449  <tr><td>
450  <b> <TT>typedef ArithmeticType Type;</TT></b>
451  </td><td>
452  the type itself
453  </td></tr>
454  <tr><td>
455  <b> <TT>typedef ... SquaredNormType;</TT></b>
456  </td><td>
457  result of <tt>squaredNorm(ArithmeticType)</tt>
458  </td></tr>
459  <tr><td>
460  <b> <TT>typedef ... NormType;</TT></b>
461  </td><td>
462  result of <tt>norm(ArithmeticType)</tt><br>
463  Usually equal to <tt>SquareRootTraits<SquaredNormType>::SquareRootResult</tt>
464  </td></tr>
465  </table>
466 
467  NormTraits for the built-in types are defined in <b>\#include</b>
468  <<a href="numerictraits_8hxx-source.html">vigra/numerictraits.hxx</a>>
469 
470  Namespace: vigra
471 */
472 
473 namespace vigra {
474 
475 struct Error_NumericTraits_not_specialized_for_this_case { };
476 struct Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char { };
477 
478 template<class A>
479 struct NumericTraits
480 {
481  typedef Error_NumericTraits_not_specialized_for_this_case Type;
482  typedef Error_NumericTraits_not_specialized_for_this_case Promote;
483  typedef Error_NumericTraits_not_specialized_for_this_case UnsignedPromote;
484  typedef Error_NumericTraits_not_specialized_for_this_case RealPromote;
485  typedef Error_NumericTraits_not_specialized_for_this_case ComplexPromote;
486  typedef Error_NumericTraits_not_specialized_for_this_case ValueType;
487 
488  typedef Error_NumericTraits_not_specialized_for_this_case isScalar;
489  typedef Error_NumericTraits_not_specialized_for_this_case isIntegral;
490  typedef Error_NumericTraits_not_specialized_for_this_case isSigned;
491  typedef Error_NumericTraits_not_specialized_for_this_case isOrdered;
492  typedef Error_NumericTraits_not_specialized_for_this_case isComplex;
493 };
494 
495 template<>
496 struct NumericTraits<char>
497 {
498  typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char Type;
499  typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char Promote;
500  typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char UnsignedPromote;
501  typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char RealPromote;
502  typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char ComplexPromote;
503  typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char ValueType;
504 
505  typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char isScalar;
506  typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char isIntegral;
507  typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char isSigned;
508  typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char isOrdered;
509  typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char isComplex;
510 };
511 
512 #ifndef NO_BOOL
513 template<>
514 struct NumericTraits<bool>
515 {
516  typedef bool Type;
517  typedef int Promote;
518  typedef unsigned int UnsignedPromote;
519  typedef double RealPromote;
520  typedef std::complex<RealPromote> ComplexPromote;
521  typedef Type ValueType;
522 
523  typedef VigraTrueType isIntegral;
524  typedef VigraTrueType isScalar;
525  typedef VigraFalseType isSigned;
526  typedef VigraTrueType isOrdered;
527  typedef VigraFalseType isComplex;
528 
529  static bool zero() { return false; }
530  static bool one() { return true; }
531  static bool nonZero() { return true; }
532  static bool min() { return false; }
533  static bool max() { return true; }
534 
535 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
536  enum { minConst = false , maxConst = true };
537 #else
538  static const bool minConst = false;
539  static const bool maxConst = true;
540 #endif
541 
542  static Promote toPromote(bool v) { return v ? 1 : 0; }
543  static RealPromote toRealPromote(bool v) { return v ? 1.0 : 0.0; }
544  static bool fromPromote(Promote v) {
545  return (v == 0) ? false : true;
546  }
547  static bool fromRealPromote(RealPromote v) {
548  return (v == 0.0) ? false : true;
549  }
550 };
551 #endif
552 
553 template<>
554 struct NumericTraits<signed char>
555 {
556  typedef signed char Type;
557  typedef int Promote;
558  typedef unsigned int UnsignedPromote;
559  typedef double RealPromote;
560  typedef std::complex<RealPromote> ComplexPromote;
561  typedef Type ValueType;
562 
563  typedef VigraTrueType isIntegral;
564  typedef VigraTrueType isScalar;
565  typedef VigraTrueType isSigned;
566  typedef VigraTrueType isOrdered;
567  typedef VigraFalseType isComplex;
568 
569  static signed char zero() { return 0; }
570  static signed char one() { return 1; }
571  static signed char nonZero() { return 1; }
572  static signed char min() { return SCHAR_MIN; }
573  static signed char max() { return SCHAR_MAX; }
574 
575 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
576  enum { minConst = SCHAR_MIN, maxConst = SCHAR_MIN };
577 #else
578  static const signed char minConst = SCHAR_MIN;
579  static const signed char maxConst = SCHAR_MIN;
580 #endif
581 
582  static Promote toPromote(signed char v) { return v; }
583  static RealPromote toRealPromote(signed char v) { return v; }
584  static signed char fromPromote(Promote v) {
585  return ((v < SCHAR_MIN) ? SCHAR_MIN : (v > SCHAR_MAX) ? SCHAR_MAX : v);
586  }
587  static signed char fromRealPromote(RealPromote v) {
588  return ((v < 0.0)
589  ? ((v < (RealPromote)SCHAR_MIN)
590  ? SCHAR_MIN
591  : static_cast<signed char>(v - 0.5))
592  : (v > (RealPromote)SCHAR_MAX)
593  ? SCHAR_MAX
594  : static_cast<signed char>(v + 0.5));
595  }
596 };
597 
598 template<>
599 struct NumericTraits<unsigned char>
600 {
601  typedef unsigned char Type;
602  typedef int Promote;
603  typedef unsigned int UnsignedPromote;
604  typedef double RealPromote;
605  typedef std::complex<RealPromote> ComplexPromote;
606  typedef Type ValueType;
607 
608  typedef VigraTrueType isIntegral;
609  typedef VigraTrueType isScalar;
610  typedef VigraFalseType isSigned;
611  typedef VigraTrueType isOrdered;
612  typedef VigraFalseType isComplex;
613 
614  static unsigned char zero() { return 0; }
615  static unsigned char one() { return 1; }
616  static unsigned char nonZero() { return 1; }
617  static unsigned char min() { return 0; }
618  static unsigned char max() { return UCHAR_MAX; }
619 
620 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
621  enum { minConst = 0, maxConst = UCHAR_MAX };
622 #else
623  static const unsigned char minConst = 0;
624  static const unsigned char maxConst = UCHAR_MAX;
625 #endif
626 
627  static Promote toPromote(unsigned char v) { return v; }
628  static RealPromote toRealPromote(unsigned char v) { return v; }
629  static unsigned char fromPromote(Promote const & v) {
630  return Type((v < 0)
631  ? 0
632  : (v > (Promote)UCHAR_MAX)
633  ? UCHAR_MAX
634  : v);
635  }
636  static unsigned char fromRealPromote(RealPromote const & v) {
637  return Type((v < 0.0)
638  ? 0
639  : ((v > (RealPromote)UCHAR_MAX)
640  ? UCHAR_MAX
641  : v + 0.5));
642  }
643 };
644 
645 template<>
646 struct NumericTraits<short int>
647 {
648  typedef short int Type;
649  typedef int Promote;
650  typedef unsigned int UnsignedPromote;
651  typedef double RealPromote;
652  typedef std::complex<RealPromote> ComplexPromote;
653  typedef Type ValueType;
654 
655  typedef VigraTrueType isIntegral;
656  typedef VigraTrueType isScalar;
657  typedef VigraTrueType isSigned;
658  typedef VigraTrueType isOrdered;
659  typedef VigraFalseType isComplex;
660 
661  static short int zero() { return 0; }
662  static short int one() { return 1; }
663  static short int nonZero() { return 1; }
664  static short int min() { return SHRT_MIN; }
665  static short int max() { return SHRT_MAX; }
666 
667 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
668  enum { minConst = SHRT_MIN, maxConst = SHRT_MAX };
669 #else
670  static const short int minConst = SHRT_MIN;
671  static const short int maxConst = SHRT_MAX;
672 #endif
673 
674  static Promote toPromote(short int v) { return v; }
675  static RealPromote toRealPromote(short int v) { return v; }
676  static short int fromPromote(Promote v) {
677  return ((v < SHRT_MIN) ? SHRT_MIN :
678  (v > SHRT_MAX) ? SHRT_MAX : v);
679  }
680  static short int fromRealPromote(RealPromote v) {
681  return ((v < 0.0)
682  ? ((v < (RealPromote)SHRT_MIN)
683  ? SHRT_MIN
684  : static_cast<short int>(v - 0.5))
685  : ((v > (RealPromote)SHRT_MAX)
686  ? SHRT_MAX
687  : static_cast<short int>(v + 0.5)));
688  }
689 };
690 
691 template<>
692 struct NumericTraits<short unsigned int>
693 {
694  typedef short unsigned int Type;
695  typedef int Promote;
696  typedef unsigned int UnsignedPromote;
697  typedef double RealPromote;
698  typedef std::complex<RealPromote> ComplexPromote;
699  typedef Type ValueType;
700 
701  typedef VigraTrueType isIntegral;
702  typedef VigraTrueType isScalar;
703  typedef VigraFalseType isSigned;
704  typedef VigraTrueType isOrdered;
705  typedef VigraFalseType isComplex;
706 
707  static short unsigned int zero() { return 0; }
708  static short unsigned int one() { return 1; }
709  static short unsigned int nonZero() { return 1; }
710  static short unsigned int min() { return 0; }
711  static short unsigned int max() { return USHRT_MAX; }
712 
713 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
714  enum { minConst = 0, maxConst = USHRT_MAX };
715 #else
716  static const short unsigned int minConst = 0;
717  static const short unsigned int maxConst = USHRT_MAX;
718 #endif
719 
720  static Promote toPromote(short unsigned int v) { return v; }
721  static RealPromote toRealPromote(short unsigned int v) { return v; }
722  static short unsigned int fromPromote(Promote v) {
723  return Type((v < 0)
724  ? 0
725  : (v > USHRT_MAX)
726  ? USHRT_MAX
727  : v);
728  }
729  static short unsigned int fromRealPromote(RealPromote v) {
730  return Type((v < 0.0)
731  ? 0
732  : ((v > (RealPromote)USHRT_MAX)
733  ? USHRT_MAX
734  : v + 0.5));
735  }
736 };
737 
738 template<>
739 struct NumericTraits<int>
740 {
741  typedef int Type;
742  typedef int Promote;
743  typedef unsigned int UnsignedPromote;
744  typedef double RealPromote;
745  typedef std::complex<RealPromote> ComplexPromote;
746  typedef Type ValueType;
747 
748  typedef VigraTrueType isIntegral;
749  typedef VigraTrueType isScalar;
750  typedef VigraTrueType isSigned;
751  typedef VigraTrueType isOrdered;
752  typedef VigraFalseType isComplex;
753 
754  static int zero() { return 0; }
755  static int one() { return 1; }
756  static int nonZero() { return 1; }
757  static int min() { return INT_MIN; }
758  static int max() { return INT_MAX; }
759 
760 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
761  enum { minConst = INT_MIN, maxConst = INT_MAX };
762 #else
763  static const int minConst = INT_MIN;
764  static const int maxConst = INT_MAX;
765 #endif
766 
767  static Promote toPromote(int v) { return v; }
768  static RealPromote toRealPromote(int v) { return v; }
769  static int fromPromote(Promote v) { return v; }
770  static int fromRealPromote(RealPromote v) {
771  return ((v < 0.0)
772  ? ((v < (RealPromote)INT_MIN)
773  ? INT_MIN
774  : static_cast<int>(v - 0.5))
775  : ((v > (RealPromote)INT_MAX)
776  ? INT_MAX
777  : static_cast<int>(v + 0.5)));
778  }
779 };
780 
781 template<>
782 struct NumericTraits<unsigned int>
783 {
784  typedef unsigned int Type;
785  typedef unsigned int Promote;
786  typedef unsigned int UnsignedPromote;
787  typedef double RealPromote;
788  typedef std::complex<RealPromote> ComplexPromote;
789  typedef Type ValueType;
790 
791  typedef VigraTrueType isIntegral;
792  typedef VigraTrueType isScalar;
793  typedef VigraFalseType isSigned;
794  typedef VigraTrueType isOrdered;
795  typedef VigraFalseType isComplex;
796 
797  static unsigned int zero() { return 0; }
798  static unsigned int one() { return 1; }
799  static unsigned int nonZero() { return 1; }
800  static unsigned int min() { return 0; }
801  static unsigned int max() { return UINT_MAX; }
802 
803 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
804  enum { minConst = 0, maxConst = UINT_MAX };
805 #else
806  static const unsigned int minConst = 0;
807  static const unsigned int maxConst = UINT_MAX;
808 #endif
809 
810  static Promote toPromote(unsigned int v) { return v; }
811  static RealPromote toRealPromote(unsigned int v) { return v; }
812  static unsigned int fromPromote(Promote v) { return v; }
813  static unsigned int fromRealPromote(RealPromote v) {
814  return ((v < 0.0)
815  ? 0
816  : ((v > (RealPromote)UINT_MAX)
817  ? UINT_MAX
818  : static_cast<unsigned int>(v + 0.5)));
819  }
820 };
821 
822 template<>
823 struct NumericTraits<long>
824 {
825  typedef long Type;
826  typedef long Promote;
827  typedef unsigned long UnsignedPromote;
828  typedef double RealPromote;
829  typedef std::complex<RealPromote> ComplexPromote;
830  typedef Type ValueType;
831 
832  typedef VigraTrueType isIntegral;
833  typedef VigraTrueType isScalar;
834  typedef VigraTrueType isSigned;
835  typedef VigraTrueType isOrdered;
836  typedef VigraFalseType isComplex;
837 
838  static long zero() { return 0; }
839  static long one() { return 1; }
840  static long nonZero() { return 1; }
841  static long min() { return LONG_MIN; }
842  static long max() { return LONG_MAX; }
843 
844 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
845  enum { minConst = LONG_MIN, maxConst = LONG_MAX };
846 #else
847  static const long minConst = LONG_MIN;
848  static const long maxConst = LONG_MAX;
849 #endif
850 
851  static Promote toPromote(long v) { return v; }
852  static RealPromote toRealPromote(long v) { return v; }
853  static long fromPromote(Promote v) { return v; }
854  static long fromRealPromote(RealPromote v) {
855  return ((v < 0.0)
856  ? ((v < (RealPromote)LONG_MIN)
857  ? LONG_MIN
858  : static_cast<long>(v - 0.5))
859  : ((v > (RealPromote)LONG_MAX)
860  ? LONG_MAX
861  : static_cast<long>(v + 0.5)));
862  }
863 };
864 
865 template<>
866 struct NumericTraits<unsigned long>
867 {
868  typedef unsigned long Type;
869  typedef unsigned long Promote;
870  typedef unsigned long UnsignedPromote;
871  typedef double RealPromote;
872  typedef std::complex<RealPromote> ComplexPromote;
873  typedef Type ValueType;
874 
875  typedef VigraTrueType isIntegral;
876  typedef VigraTrueType isScalar;
877  typedef VigraFalseType isSigned;
878  typedef VigraTrueType isOrdered;
879  typedef VigraFalseType isComplex;
880 
881  static unsigned long zero() { return 0; }
882  static unsigned long one() { return 1; }
883  static unsigned long nonZero() { return 1; }
884  static unsigned long min() { return 0; }
885  static unsigned long max() { return ULONG_MAX; }
886 
887 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
888  enum { minConst = 0, maxConst = ULONG_MAX };
889 #else
890  static const unsigned long minConst = 0;
891  static const unsigned long maxConst = ULONG_MAX;
892 #endif
893 
894  static Promote toPromote(unsigned long v) { return v; }
895  static RealPromote toRealPromote(unsigned long v) { return v; }
896  static unsigned long fromPromote(Promote v) { return v; }
897  static unsigned long fromRealPromote(RealPromote v) {
898  return ((v < 0.0)
899  ? 0
900  : ((v > (RealPromote)ULONG_MAX)
901  ? ULONG_MAX
902  : static_cast<unsigned long>(v + 0.5)));
903  }
904 };
905 
906 #ifdef LLONG_MAX
907 template<>
908 struct NumericTraits<long long>
909 {
910  typedef long long Type;
911  typedef long long Promote;
912  typedef unsigned long long UnsignedPromote;
913  typedef double RealPromote;
914  typedef std::complex<RealPromote> ComplexPromote;
915  typedef Type ValueType;
916 
917  typedef VigraTrueType isIntegral;
918  typedef VigraTrueType isScalar;
919  typedef VigraTrueType isSigned;
920  typedef VigraTrueType isOrdered;
921  typedef VigraFalseType isComplex;
922 
923  static long long zero() { return 0; }
924  static long long one() { return 1; }
925  static long long nonZero() { return 1; }
926  static long long min() { return LLONG_MIN; }
927  static long long max() { return LLONG_MAX; }
928 
929 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
930  enum { minConst = LLONG_MIN, maxConst = LLONG_MAX };
931 #else
932  static const long long minConst = LLONG_MIN;
933  static const long long maxConst = LLONG_MAX;
934 #endif
935 
936  static Promote toPromote(long long v) { return v; }
937  static RealPromote toRealPromote(long long v) { return (RealPromote)v; }
938  static long long fromPromote(Promote v) { return v; }
939  static long long fromRealPromote(RealPromote v) {
940  return ((v < 0.0)
941  ? ((v < (RealPromote)LLONG_MIN)
942  ? LLONG_MIN
943  : static_cast<long long>(v - 0.5))
944  : ((v > (RealPromote)LLONG_MAX)
945  ? LLONG_MAX
946  : static_cast<long long>(v + 0.5)));
947  }
948 };
949 
950 template<>
951 struct NumericTraits<unsigned long long>
952 {
953  typedef unsigned long long Type;
954  typedef unsigned long long Promote;
955  typedef unsigned long long UnsignedPromote;
956  typedef double RealPromote;
957  typedef std::complex<RealPromote> ComplexPromote;
958  typedef Type ValueType;
959 
960  typedef VigraTrueType isIntegral;
961  typedef VigraTrueType isScalar;
962  typedef VigraFalseType isSigned;
963  typedef VigraTrueType isOrdered;
964  typedef VigraFalseType isComplex;
965 
966  static unsigned long long zero() { return 0; }
967  static unsigned long long one() { return 1; }
968  static unsigned long long nonZero() { return 1; }
969  static unsigned long long min() { return 0; }
970  static unsigned long long max() { return ULLONG_MAX; }
971 
972 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
973  enum { minConst = 0, maxConst = ULLONG_MAX };
974 #else
975  static const unsigned long long minConst = 0;
976  static const unsigned long long maxConst = ULLONG_MAX;
977 #endif
978 
979  static Promote toPromote(unsigned long long v) { return v; }
980  static RealPromote toRealPromote(unsigned long long v) { return (RealPromote)v; }
981  static unsigned long long fromPromote(Promote v) { return v; }
982  static unsigned long long fromRealPromote(RealPromote v) {
983  return ((v < 0.0)
984  ? 0
985  : ((v > (RealPromote)ULLONG_MAX)
986  ? ULONG_MAX
987  : static_cast<unsigned long long>(v + 0.5)));
988  }
989 };
990 #endif // LLONG_MAX
991 
992 template<>
993 struct NumericTraits<float>
994 {
995  typedef float Type;
996  typedef float Promote;
997  typedef float UnsignedPromote;
998  typedef float RealPromote;
999  typedef std::complex<RealPromote> ComplexPromote;
1000  typedef Type ValueType;
1001 
1002  typedef VigraFalseType isIntegral;
1003  typedef VigraTrueType isScalar;
1004  typedef VigraTrueType isSigned;
1005  typedef VigraTrueType isOrdered;
1006  typedef VigraFalseType isComplex;
1007 
1008  static float zero() { return 0.0; }
1009  static float one() { return 1.0; }
1010  static float nonZero() { return 1.0; }
1011  static float epsilon() { return FLT_EPSILON; }
1012  static float smallestPositive() { return FLT_MIN; }
1013  static float min() { return -FLT_MAX; }
1014  static float max() { return FLT_MAX; }
1015 
1016  static Promote toPromote(float v) { return v; }
1017  static RealPromote toRealPromote(float v) { return v; }
1018  static float fromPromote(Promote v) { return v; }
1019  static float fromRealPromote(RealPromote v) { return v; }
1020 };
1021 
1022 template<>
1023 struct NumericTraits<double>
1024 {
1025  typedef double Type;
1026  typedef double Promote;
1027  typedef double UnsignedPromote;
1028  typedef double RealPromote;
1029  typedef std::complex<RealPromote> ComplexPromote;
1030  typedef Type ValueType;
1031 
1032  typedef VigraFalseType isIntegral;
1033  typedef VigraTrueType isScalar;
1034  typedef VigraTrueType isSigned;
1035  typedef VigraTrueType isOrdered;
1036  typedef VigraFalseType isComplex;
1037 
1038  static double zero() { return 0.0; }
1039  static double one() { return 1.0; }
1040  static double nonZero() { return 1.0; }
1041  static double epsilon() { return DBL_EPSILON; }
1042  static double smallestPositive() { return DBL_MIN; }
1043  static double min() { return -DBL_MAX; }
1044  static double max() { return DBL_MAX; }
1045 
1046  static Promote toPromote(double v) { return v; }
1047  static RealPromote toRealPromote(double v) { return v; }
1048  static double fromPromote(Promote v) { return v; }
1049  static double fromRealPromote(RealPromote v) { return v; }
1050 };
1051 
1052 template<>
1053 struct NumericTraits<long double>
1054 {
1055  typedef long double Type;
1056  typedef long double Promote;
1057  typedef long double UnsignedPromote;
1058  typedef long double RealPromote;
1059  typedef std::complex<RealPromote> ComplexPromote;
1060  typedef Type ValueType;
1061 
1062  typedef VigraFalseType isIntegral;
1063  typedef VigraTrueType isScalar;
1064  typedef VigraTrueType isSigned;
1065  typedef VigraTrueType isOrdered;
1066  typedef VigraFalseType isComplex;
1067 
1068  static long double zero() { return 0.0; }
1069  static long double one() { return 1.0; }
1070  static long double nonZero() { return 1.0; }
1071  static long double epsilon() { return LDBL_EPSILON; }
1072  static long double smallestPositive() { return LDBL_MIN; }
1073  static long double min() { return -LDBL_MAX; }
1074  static long double max() { return LDBL_MAX; }
1075 
1076  static Promote toPromote(long double v) { return v; }
1077  static RealPromote toRealPromote(long double v) { return v; }
1078  static long double fromPromote(Promote v) { return v; }
1079  static long double fromRealPromote(RealPromote v) { return v; }
1080 };
1081 
1082 #ifndef NO_PARTIAL_TEMPLATE_SPECIALIZATION
1083 
1084 template<class T>
1085 struct NumericTraits<std::complex<T> >
1086 {
1087  typedef std::complex<T> Type;
1088  typedef std::complex<typename NumericTraits<T>::Promote> Promote;
1089  typedef std::complex<typename NumericTraits<T>::UnsignedPromote> UnsignedPromote;
1090  typedef std::complex<typename NumericTraits<T>::RealPromote> RealPromote;
1091  typedef std::complex<RealPromote> ComplexPromote;
1092  typedef T ValueType;
1093 
1094  typedef VigraFalseType isIntegral;
1095  typedef VigraFalseType isScalar;
1096  typedef typename NumericTraits<T>::isSigned isSigned;
1097  typedef VigraFalseType isOrdered;
1098  typedef VigraTrueType isComplex;
1099 
1100  static Type zero() { return Type(0.0); }
1101  static Type one() { return Type(1.0); }
1102  static Type nonZero() { return one(); }
1103  static Type epsilon() { return Type(NumericTraits<T>::epsilon()); }
1104  static Type smallestPositive() { return Type(NumericTraits<T>::smallestPositive()); }
1105 
1106  static Promote toPromote(Type const & v) { return v; }
1107  static Type fromPromote(Promote const & v) { return v; }
1108  static Type fromRealPromote(RealPromote v) { return Type(v); }
1109 };
1110 
1111 #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION
1112 
1113 /********************************************************/
1114 /* */
1115 /* SquareRootTraits */
1116 /* */
1117 /********************************************************/
1118 
1119 template<class T>
1120 struct SquareRootTraits
1121 {
1122  typedef T Type;
1123  typedef typename NumericTraits<T>::RealPromote SquareRootResult;
1124  typedef typename NumericTraits<T>::RealPromote SquareRootArgument;
1125 };
1126 
1127 
1128 /********************************************************/
1129 /* */
1130 /* NormTraits */
1131 /* */
1132 /********************************************************/
1133 
1134 struct Error_NormTraits_not_specialized_for_this_case { };
1135 
1136 template<class T>
1137 struct NormTraits
1138 {
1139  typedef T Type;
1140  typedef Error_NormTraits_not_specialized_for_this_case SquaredNormType;
1141  typedef Error_NormTraits_not_specialized_for_this_case NormType;
1142 };
1143 
1144 #define VIGRA_DEFINE_NORM_TRAITS(T) \
1145  template <> struct NormTraits<T> { \
1146  typedef T Type; \
1147  typedef NumericTraits<T>::Promote SquaredNormType; \
1148  typedef T NormType; \
1149  };
1150 
1151 VIGRA_DEFINE_NORM_TRAITS(bool)
1152 VIGRA_DEFINE_NORM_TRAITS(signed char)
1153 VIGRA_DEFINE_NORM_TRAITS(unsigned char)
1154 VIGRA_DEFINE_NORM_TRAITS(short)
1155 VIGRA_DEFINE_NORM_TRAITS(unsigned short)
1156 VIGRA_DEFINE_NORM_TRAITS(int)
1157 VIGRA_DEFINE_NORM_TRAITS(unsigned int)
1158 VIGRA_DEFINE_NORM_TRAITS(long)
1159 VIGRA_DEFINE_NORM_TRAITS(unsigned long)
1160 VIGRA_DEFINE_NORM_TRAITS(float)
1161 VIGRA_DEFINE_NORM_TRAITS(double)
1162 VIGRA_DEFINE_NORM_TRAITS(long double)
1163 
1164 #ifdef LLONG_MAX
1165 VIGRA_DEFINE_NORM_TRAITS(long long)
1166 VIGRA_DEFINE_NORM_TRAITS(unsigned long long)
1167 #endif // LLONG_MAX
1168 
1169 #undef VIGRA_DEFINE_NORM_TRAITS
1170 
1171 #ifndef NO_PARTIAL_TEMPLATE_SPECIALIZATION
1172 
1173 template<class T>
1174 struct NormTraits<std::complex<T> >
1175 {
1176  typedef std::complex<T> Type;
1177  typedef typename NormTraits<T>::SquaredNormType SquaredNormType;
1178  typedef typename SquareRootTraits<SquaredNormType>::SquareRootResult NormType;
1179 };
1180 
1181 #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION
1182 
1183 /********************************************************/
1184 /* */
1185 /* PromoteTraits */
1186 /* */
1187 /********************************************************/
1188 
1189 namespace detail {
1190 
1191 template <class T, class U>
1192 struct PromoteType
1193 {
1194  static T & t();
1195  static U & u();
1196  // let C++ figure out the promote type by adding a T and an U
1197  typedef typename SizeToType<sizeof(*typeToSize(t() + u()))>::result Promote;
1198  static Promote toPromote(T t) { return Promote(t); }
1199  static Promote toPromote(U u) { return Promote(u); }
1200 };
1201 
1202 
1203 template <class T>
1204 struct PromoteType<T, T>
1205 {
1206  static T & t();
1207  // let C++ figure out the promote type by adding two Ts
1208  typedef typename SizeToType<sizeof(*typeToSize(t() + t()))>::result Promote;
1209  static Promote toPromote(T t) { return Promote(t); }
1210 };
1211 
1212 } // namespace detail
1213 
1214 struct Error_PromoteTraits_not_specialized_for_this_case { };
1215 
1216 template<class A, class B>
1217 struct PromoteTraits
1218 {
1219  typedef Error_PromoteTraits_not_specialized_for_this_case Promote;
1220 };
1221 
1222 #include "promote_traits.hxx"
1223 
1224 #ifndef NO_PARTIAL_TEMPLATE_SPECIALIZATION
1225 
1226 template <class T>
1227 struct PromoteTraits<std::complex<T>, std::complex<T> >
1228 {
1229  typedef std::complex<typename PromoteTraits<T, T>::Promote> Promote;
1230  static Promote toPromote(std::complex<T> const & v) { return v; }
1231 };
1232 
1233 template <class T1, class T2>
1234 struct PromoteTraits<std::complex<T1>, std::complex<T2> >
1235 {
1236  typedef std::complex<typename PromoteTraits<T1, T2>::Promote> Promote;
1237  static Promote toPromote(std::complex<T1> const & v) { return v; }
1238  static Promote toPromote(std::complex<T2> const & v) { return v; }
1239 };
1240 
1241 template <class T1, class T2>
1242 struct PromoteTraits<std::complex<T1>, T2 >
1243 {
1244  typedef std::complex<typename PromoteTraits<T1, T2>::Promote> Promote;
1245  static Promote toPromote(std::complex<T1> const & v) { return v; }
1246  static Promote toPromote(T2 const & v) { return Promote(v); }
1247 };
1248 
1249 template <class T1, class T2>
1250 struct PromoteTraits<T1, std::complex<T2> >
1251 {
1252  typedef std::complex<typename PromoteTraits<T1, T2>::Promote> Promote;
1253  static Promote toPromote(T1 const & v) { return Promote(v); }
1254  static Promote toPromote(std::complex<T2> const & v) { return v; }
1255 };
1256 
1257 #endif
1258 
1259 namespace detail {
1260 
1261 template <class T>
1262 struct RequiresExplicitCast {
1263  template <class U>
1264  static U const & cast(U const & v)
1265  { return v; }
1266 };
1267 
1268 #if !defined(_MSC_VER) || _MSC_VER >= 1300
1269 # define VIGRA_SPECIALIZED_CAST(type) \
1270  template <> \
1271  struct RequiresExplicitCast<type> { \
1272  static type cast(float v) \
1273  { return NumericTraits<type>::fromRealPromote(v); } \
1274  static type cast(double v) \
1275  { return NumericTraits<type>::fromRealPromote(v); } \
1276  static type cast(type v) \
1277  { return v; } \
1278  template <class U> \
1279  static type cast(U v) \
1280  { return static_cast<type>(v); } \
1281  \
1282  };
1283 #else
1284 # define VIGRA_SPECIALIZED_CAST(type) \
1285  template <> \
1286  struct RequiresExplicitCast<type> { \
1287  static type cast(float v) \
1288  { return NumericTraits<type>::fromRealPromote(v); } \
1289  static type cast(double v) \
1290  { return NumericTraits<type>::fromRealPromote(v); } \
1291  static type cast(signed char v) \
1292  { return v; } \
1293  static type cast(unsigned char v) \
1294  { return v; } \
1295  static type cast(short v) \
1296  { return v; } \
1297  static type cast(unsigned short v) \
1298  { return v; } \
1299  static type cast(int v) \
1300  { return v; } \
1301  static type cast(unsigned int v) \
1302  { return v; } \
1303  static type cast(long v) \
1304  { return v; } \
1305  static type cast(unsigned long v) \
1306  { return v; } \
1307  };
1308 #endif
1309 
1310 
1311 VIGRA_SPECIALIZED_CAST(signed char)
1312 VIGRA_SPECIALIZED_CAST(unsigned char)
1313 VIGRA_SPECIALIZED_CAST(short)
1314 VIGRA_SPECIALIZED_CAST(unsigned short)
1315 VIGRA_SPECIALIZED_CAST(int)
1316 VIGRA_SPECIALIZED_CAST(unsigned int)
1317 VIGRA_SPECIALIZED_CAST(long)
1318 VIGRA_SPECIALIZED_CAST(unsigned long)
1319 
1320 template <>
1321 struct RequiresExplicitCast<bool> {
1322  template <class U>
1323  static bool cast(U v)
1324  { return v == NumericTraits<U>::zero()
1325  ? false
1326  : true; }
1327 };
1328 
1329 template <>
1330 struct RequiresExplicitCast<float> {
1331  static float cast(int v)
1332  { return (float)v; }
1333 
1334  static float cast(unsigned int v)
1335  { return (float)v; }
1336 
1337  static float cast(long v)
1338  { return (float)v; }
1339 
1340  static float cast(unsigned long v)
1341  { return (float)v; }
1342 
1343  static float cast(long long v)
1344  { return (float)v; }
1345 
1346  static float cast(unsigned long long v)
1347  { return (float)v; }
1348 
1349  static float cast(double v)
1350  { return (float)v; }
1351 
1352  static float cast(long double v)
1353  { return (float)v; }
1354 
1355  template <class U>
1356  static U cast(U v)
1357  { return v; }
1358 };
1359 
1360 template <>
1361 struct RequiresExplicitCast<double> {
1362  static double cast(Int64 v)
1363  { return (double)v; }
1364 
1365  static double cast(UInt64 v)
1366  { return (double)v; }
1367 
1368  template <class U>
1369  static U cast(U v)
1370  { return v; }
1371 };
1372 
1373 #undef VIGRA_SPECIALIZED_CAST
1374 
1375 } // namespace detail
1376 
1377 
1378 
1379 } // namespace vigra
1380 
1381 #endif // VIGRA_NUMERICTRAITS_HXX
1382 

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.7.1 (Tue Jul 10 2012)