[ 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  <vigra/numerictraits.hxx>
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 chosen '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  <vigra/numerictraits.hxx>
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  <vigra/numerictraits.hxx>
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. Then we can deduce the appropriate
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  <vigra/numerictraits.hxx>
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  <vigra/numerictraits.hxx>
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 'ambiguous 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  <vigra/numerictraits.hxx>
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  <vigra/numerictraits.hxx>
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 that 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  <vigra/numerictraits.hxx>
469 
470  Namespace: vigra
471 */
472 
473 
474 namespace vigra {
475  namespace detail {
476  template <typename s, typename t>
477  inline static t clamp_integer_to_unsigned(s value, t maximum) {
478  return
479  value <= s() ?
480  t() :
481  (value >= static_cast<s>(maximum) ? maximum : static_cast<t>(value));
482  }
483 
484  template <typename s, typename t>
485  inline static t clamp_integer_to_signed(s value, t minimum, t maximum) {
486  return
487  value <= static_cast<s>(minimum) ?
488  minimum :
489  (value >= static_cast<s>(maximum) ? maximum : static_cast<t>(value));
490  }
491 
492  template <typename s, typename t>
493  inline static t clamp_float_to_unsigned(s value, t maximum) {
494  return
495  value <= s() ?
496  t() :
497  (value >= static_cast<s>(maximum) ? maximum : static_cast<t>(value + 0.5));
498  }
499 
500  template <typename s, typename t>
501  inline static t clamp_float_to_signed(s value, t minimum, t maximum) {
502  if (value >= s()) {
503  return value >= static_cast<s>(maximum) ? maximum : static_cast<t>(value + 0.5);
504  } else {
505  return value <= static_cast<s>(minimum) ? minimum : static_cast<t>(value - 0.5);
506  }
507  }
508  } // end namespace detail
509 
510 struct Error_NumericTraits_not_specialized_for_this_case { };
511 struct Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char { };
512 
513 template<class A>
514 struct NumericTraits
515 {
516  typedef Error_NumericTraits_not_specialized_for_this_case Type;
517  typedef Error_NumericTraits_not_specialized_for_this_case Promote;
518  typedef Error_NumericTraits_not_specialized_for_this_case UnsignedPromote;
519  typedef Error_NumericTraits_not_specialized_for_this_case RealPromote;
520  typedef Error_NumericTraits_not_specialized_for_this_case ComplexPromote;
521  typedef Error_NumericTraits_not_specialized_for_this_case ValueType;
522 
523  typedef Error_NumericTraits_not_specialized_for_this_case isScalar;
524  typedef Error_NumericTraits_not_specialized_for_this_case isIntegral;
525  typedef Error_NumericTraits_not_specialized_for_this_case isSigned;
526  typedef Error_NumericTraits_not_specialized_for_this_case isOrdered;
527  typedef Error_NumericTraits_not_specialized_for_this_case isComplex;
528 };
529 
530 template<>
531 struct NumericTraits<char>
532 {
533  typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char Type;
534  typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char Promote;
535  typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char UnsignedPromote;
536  typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char RealPromote;
537  typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char ComplexPromote;
538  typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char ValueType;
539 
540  typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char isScalar;
541  typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char isIntegral;
542  typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char isSigned;
543  typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char isOrdered;
544  typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char isComplex;
545 };
546 
547 #ifndef NO_BOOL
548 template<>
549 struct NumericTraits<bool>
550 {
551  typedef bool Type;
552  typedef int Promote;
553  typedef unsigned int UnsignedPromote;
554  typedef double RealPromote;
555  typedef std::complex<RealPromote> ComplexPromote;
556  typedef Type ValueType;
557 
558  typedef VigraTrueType isIntegral;
559  typedef VigraTrueType isScalar;
560  typedef VigraFalseType isSigned;
561  typedef VigraTrueType isOrdered;
562  typedef VigraFalseType isComplex;
563 
564  static bool zero() { return false; }
565  static bool one() { return true; }
566  static bool nonZero() { return true; }
567  static bool min() { return false; }
568  static bool max() { return true; }
569 
570 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
571  enum { minConst = false , maxConst = true };
572 #else
573  static const bool minConst = false;
574  static const bool maxConst = true;
575 #endif
576 
577  static Promote toPromote(bool v) { return v ? 1 : 0; }
578  static RealPromote toRealPromote(bool v) { return v ? 1.0 : 0.0; }
579  static bool fromPromote(Promote v) {
580  return (v == 0) ? false : true;
581  }
582  static bool fromRealPromote(RealPromote v) {
583  return (v == 0.0) ? false : true;
584  }
585 };
586 #endif
587 
588 template<>
589 struct NumericTraits<signed char>
590 {
591  typedef signed char Type;
592  typedef int Promote;
593  typedef unsigned int UnsignedPromote;
594  typedef double RealPromote;
595  typedef std::complex<RealPromote> ComplexPromote;
596  typedef Type ValueType;
597 
598  typedef VigraTrueType isIntegral;
599  typedef VigraTrueType isScalar;
600  typedef VigraTrueType isSigned;
601  typedef VigraTrueType isOrdered;
602  typedef VigraFalseType isComplex;
603 
604  static signed char zero() { return 0; }
605  static signed char one() { return 1; }
606  static signed char nonZero() { return 1; }
607  static signed char min() { return SCHAR_MIN; }
608  static signed char max() { return SCHAR_MAX; }
609 
610 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
611  enum { minConst = SCHAR_MIN, maxConst = SCHAR_MIN };
612 #else
613  static const signed char minConst = SCHAR_MIN;
614  static const signed char maxConst = SCHAR_MIN;
615 #endif
616 
617  static Promote toPromote(signed char v) { return v; }
618  static RealPromote toRealPromote(signed char v) { return v; }
619  static signed char fromPromote(Promote v) {
620  return detail::clamp_integer_to_signed<Promote, signed char>(v, SCHAR_MIN, SCHAR_MAX);
621  }
622  static signed char fromRealPromote(RealPromote v) {
623  return detail::clamp_float_to_signed<RealPromote, signed char>(v, SCHAR_MIN, SCHAR_MAX);
624  }
625 };
626 
627 template<>
628 struct NumericTraits<unsigned char>
629 {
630  typedef unsigned char Type;
631  typedef int Promote;
632  typedef unsigned int UnsignedPromote;
633  typedef double RealPromote;
634  typedef std::complex<RealPromote> ComplexPromote;
635  typedef Type ValueType;
636 
637  typedef VigraTrueType isIntegral;
638  typedef VigraTrueType isScalar;
639  typedef VigraFalseType isSigned;
640  typedef VigraTrueType isOrdered;
641  typedef VigraFalseType isComplex;
642 
643  static unsigned char zero() { return 0; }
644  static unsigned char one() { return 1; }
645  static unsigned char nonZero() { return 1; }
646  static unsigned char min() { return 0; }
647  static unsigned char max() { return UCHAR_MAX; }
648 
649 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
650  enum { minConst = 0, maxConst = UCHAR_MAX };
651 #else
652  static const unsigned char minConst = 0;
653  static const unsigned char maxConst = UCHAR_MAX;
654 #endif
655 
656  static Promote toPromote(unsigned char v) { return v; }
657  static RealPromote toRealPromote(unsigned char v) { return v; }
658  static unsigned char fromPromote(Promote v) {
659  return detail::clamp_integer_to_unsigned<Promote, unsigned char>(v, UCHAR_MAX);
660  }
661  static unsigned char fromRealPromote(RealPromote v) {
662  return detail::clamp_float_to_unsigned<RealPromote, unsigned char>(v, UCHAR_MAX);
663  }
664 };
665 
666 template<>
667 struct NumericTraits<short int>
668 {
669  typedef short int Type;
670  typedef int Promote;
671  typedef unsigned int UnsignedPromote;
672  typedef double RealPromote;
673  typedef std::complex<RealPromote> ComplexPromote;
674  typedef Type ValueType;
675 
676  typedef VigraTrueType isIntegral;
677  typedef VigraTrueType isScalar;
678  typedef VigraTrueType isSigned;
679  typedef VigraTrueType isOrdered;
680  typedef VigraFalseType isComplex;
681 
682  static short int zero() { return 0; }
683  static short int one() { return 1; }
684  static short int nonZero() { return 1; }
685  static short int min() { return SHRT_MIN; }
686  static short int max() { return SHRT_MAX; }
687 
688 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
689  enum { minConst = SHRT_MIN, maxConst = SHRT_MAX };
690 #else
691  static const short int minConst = SHRT_MIN;
692  static const short int maxConst = SHRT_MAX;
693 #endif
694 
695  static Promote toPromote(short int v) { return v; }
696  static RealPromote toRealPromote(short int v) { return v; }
697  static short int fromPromote(Promote v) {
698  return detail::clamp_integer_to_signed<Promote, short int>(v, SHRT_MIN, SHRT_MAX);
699  }
700  static short int fromRealPromote(RealPromote v) {
701  return detail::clamp_float_to_signed<RealPromote, short int>(v, SHRT_MIN, SHRT_MAX);
702  }
703 };
704 
705 template<>
706 struct NumericTraits<short unsigned int>
707 {
708  typedef short unsigned int Type;
709  typedef int Promote;
710  typedef unsigned int UnsignedPromote;
711  typedef double RealPromote;
712  typedef std::complex<RealPromote> ComplexPromote;
713  typedef Type ValueType;
714 
715  typedef VigraTrueType isIntegral;
716  typedef VigraTrueType isScalar;
717  typedef VigraFalseType isSigned;
718  typedef VigraTrueType isOrdered;
719  typedef VigraFalseType isComplex;
720 
721  static short unsigned int zero() { return 0; }
722  static short unsigned int one() { return 1; }
723  static short unsigned int nonZero() { return 1; }
724  static short unsigned int min() { return 0; }
725  static short unsigned int max() { return USHRT_MAX; }
726 
727 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
728  enum { minConst = 0, maxConst = USHRT_MAX };
729 #else
730  static const short unsigned int minConst = 0;
731  static const short unsigned int maxConst = USHRT_MAX;
732 #endif
733 
734  static Promote toPromote(short unsigned int v) { return v; }
735  static RealPromote toRealPromote(short unsigned int v) { return v; }
736  static short unsigned int fromPromote(Promote v) {
737  return detail::clamp_integer_to_unsigned<Promote, short unsigned int>(v, USHRT_MAX);
738  }
739  static short unsigned int fromRealPromote(RealPromote v) {
740  return detail::clamp_float_to_unsigned<RealPromote, short unsigned int>(v, USHRT_MAX);
741  }
742 };
743 
744 template<>
745 struct NumericTraits<int>
746 {
747  typedef int Type;
748  typedef int Promote;
749  typedef unsigned int UnsignedPromote;
750  typedef double RealPromote;
751  typedef std::complex<RealPromote> ComplexPromote;
752  typedef Type ValueType;
753 
754  typedef VigraTrueType isIntegral;
755  typedef VigraTrueType isScalar;
756  typedef VigraTrueType isSigned;
757  typedef VigraTrueType isOrdered;
758  typedef VigraFalseType isComplex;
759 
760  static int zero() { return 0; }
761  static int one() { return 1; }
762  static int nonZero() { return 1; }
763  static int min() { return INT_MIN; }
764  static int max() { return INT_MAX; }
765 
766 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
767  enum { minConst = INT_MIN, maxConst = INT_MAX };
768 #else
769  static const int minConst = INT_MIN;
770  static const int maxConst = INT_MAX;
771 #endif
772 
773  static Promote toPromote(int v) { return v; }
774  static RealPromote toRealPromote(int v) { return v; }
775  static int fromPromote(Promote v) { return v; }
776  static int fromRealPromote(RealPromote v) {
777  return detail::clamp_float_to_signed<RealPromote, int>(v, INT_MIN, INT_MAX);
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 detail::clamp_float_to_unsigned<RealPromote, unsigned int>(v, UINT_MAX);
815  }
816 };
817 
818 template<>
819 struct NumericTraits<long>
820 {
821  typedef long Type;
822  typedef long Promote;
823  typedef unsigned long UnsignedPromote;
824  typedef double RealPromote;
825  typedef std::complex<RealPromote> ComplexPromote;
826  typedef Type ValueType;
827 
828  typedef VigraTrueType isIntegral;
829  typedef VigraTrueType isScalar;
830  typedef VigraTrueType isSigned;
831  typedef VigraTrueType isOrdered;
832  typedef VigraFalseType isComplex;
833 
834  static long zero() { return 0; }
835  static long one() { return 1; }
836  static long nonZero() { return 1; }
837  static long min() { return LONG_MIN; }
838  static long max() { return LONG_MAX; }
839 
840 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
841  enum { minConst = LONG_MIN, maxConst = LONG_MAX };
842 #else
843  static const long minConst = LONG_MIN;
844  static const long maxConst = LONG_MAX;
845 #endif
846 
847  static Promote toPromote(long v) { return v; }
848  static RealPromote toRealPromote(long v) { return static_cast<RealPromote>(v); }
849  static long fromPromote(Promote v) { return v; }
850  static long fromRealPromote(RealPromote v) {
851  return detail::clamp_float_to_signed<RealPromote, long>(v, LONG_MIN, LONG_MAX);
852  }
853 };
854 
855 template<>
856 struct NumericTraits<unsigned long>
857 {
858  typedef unsigned long Type;
859  typedef unsigned long Promote;
860  typedef unsigned long UnsignedPromote;
861  typedef double RealPromote;
862  typedef std::complex<RealPromote> ComplexPromote;
863  typedef Type ValueType;
864 
865  typedef VigraTrueType isIntegral;
866  typedef VigraTrueType isScalar;
867  typedef VigraFalseType isSigned;
868  typedef VigraTrueType isOrdered;
869  typedef VigraFalseType isComplex;
870 
871  static unsigned long zero() { return 0; }
872  static unsigned long one() { return 1; }
873  static unsigned long nonZero() { return 1; }
874  static unsigned long min() { return 0; }
875  static unsigned long max() { return ULONG_MAX; }
876 
877 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
878  enum { minConst = 0, maxConst = ULONG_MAX };
879 #else
880  static const unsigned long minConst = 0;
881  static const unsigned long maxConst = ULONG_MAX;
882 #endif
883 
884  static Promote toPromote(unsigned long v) { return v; }
885  static RealPromote toRealPromote(unsigned long v) { return static_cast<RealPromote>(v); }
886  static unsigned long fromPromote(Promote v) { return v; }
887  static unsigned long fromRealPromote(RealPromote v) {
888  return detail::clamp_float_to_unsigned<RealPromote, unsigned long>(v, ULONG_MAX);
889  }
890 };
891 
892 #ifdef LLONG_MAX
893 template<>
894 struct NumericTraits<long long>
895 {
896  typedef long long Type;
897  typedef long long Promote;
898  typedef unsigned long long UnsignedPromote;
899  typedef double RealPromote;
900  typedef std::complex<RealPromote> ComplexPromote;
901  typedef Type ValueType;
902 
903  typedef VigraTrueType isIntegral;
904  typedef VigraTrueType isScalar;
905  typedef VigraTrueType isSigned;
906  typedef VigraTrueType isOrdered;
907  typedef VigraFalseType isComplex;
908 
909  static long long zero() { return 0; }
910  static long long one() { return 1; }
911  static long long nonZero() { return 1; }
912  static long long min() { return LLONG_MIN; }
913  static long long max() { return LLONG_MAX; }
914 
915 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
916  enum { minConst = LLONG_MIN, maxConst = LLONG_MAX };
917 #else
918  static const long long minConst = LLONG_MIN;
919  static const long long maxConst = LLONG_MAX;
920 #endif
921 
922  static Promote toPromote(long long v) { return v; }
923  static RealPromote toRealPromote(long long v) { return (RealPromote)v; }
924  static long long fromPromote(Promote v) { return v; }
925  static long long fromRealPromote(RealPromote v) {
926  return detail::clamp_float_to_signed<RealPromote, long long>(v, LLONG_MIN, LLONG_MAX);
927  }
928 };
929 
930 template<>
931 struct NumericTraits<unsigned long long>
932 {
933  typedef unsigned long long Type;
934  typedef unsigned long long Promote;
935  typedef unsigned long long UnsignedPromote;
936  typedef double RealPromote;
937  typedef std::complex<RealPromote> ComplexPromote;
938  typedef Type ValueType;
939 
940  typedef VigraTrueType isIntegral;
941  typedef VigraTrueType isScalar;
942  typedef VigraFalseType isSigned;
943  typedef VigraTrueType isOrdered;
944  typedef VigraFalseType isComplex;
945 
946  static unsigned long long zero() { return 0; }
947  static unsigned long long one() { return 1; }
948  static unsigned long long nonZero() { return 1; }
949  static unsigned long long min() { return 0; }
950  static unsigned long long max() { return ULLONG_MAX; }
951 
952 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
953  enum { minConst = 0, maxConst = ULLONG_MAX };
954 #else
955  static const unsigned long long minConst = 0;
956  static const unsigned long long maxConst = ULLONG_MAX;
957 #endif
958 
959  static Promote toPromote(unsigned long long v) { return v; }
960  static RealPromote toRealPromote(unsigned long long v) { return (RealPromote)v; }
961  static unsigned long long fromPromote(Promote v) { return v; }
962  static unsigned long long fromRealPromote(RealPromote v) {
963  return detail::clamp_float_to_unsigned<RealPromote, unsigned long long>(v, ULLONG_MAX);
964  }
965 };
966 #endif // LLONG_MAX
967 
968 template<>
969 struct NumericTraits<float>
970 {
971  typedef float Type;
972  typedef float Promote;
973  typedef float UnsignedPromote;
974  typedef float RealPromote;
975  typedef std::complex<RealPromote> ComplexPromote;
976  typedef Type ValueType;
977 
978  typedef VigraFalseType isIntegral;
979  typedef VigraTrueType isScalar;
980  typedef VigraTrueType isSigned;
981  typedef VigraTrueType isOrdered;
982  typedef VigraFalseType isComplex;
983 
984  static float zero() { return 0.0; }
985  static float one() { return 1.0; }
986  static float nonZero() { return 1.0; }
987  static float epsilon() { return FLT_EPSILON; }
988  static float smallestPositive() { return FLT_MIN; }
989  static float min() { return -FLT_MAX; }
990  static float max() { return FLT_MAX; }
991 
992  static Promote toPromote(float v) { return v; }
993  static RealPromote toRealPromote(float v) { return v; }
994  static float fromPromote(Promote v) { return v; }
995  static float fromRealPromote(RealPromote v) { return v; }
996 };
997 
998 template<>
999 struct NumericTraits<double>
1000 {
1001  typedef double Type;
1002  typedef double Promote;
1003  typedef double UnsignedPromote;
1004  typedef double RealPromote;
1005  typedef std::complex<RealPromote> ComplexPromote;
1006  typedef Type ValueType;
1007 
1008  typedef VigraFalseType isIntegral;
1009  typedef VigraTrueType isScalar;
1010  typedef VigraTrueType isSigned;
1011  typedef VigraTrueType isOrdered;
1012  typedef VigraFalseType isComplex;
1013 
1014  static double zero() { return 0.0; }
1015  static double one() { return 1.0; }
1016  static double nonZero() { return 1.0; }
1017  static double epsilon() { return DBL_EPSILON; }
1018  static double smallestPositive() { return DBL_MIN; }
1019  static double min() { return -DBL_MAX; }
1020  static double max() { return DBL_MAX; }
1021 
1022  static Promote toPromote(double v) { return v; }
1023  static RealPromote toRealPromote(double v) { return v; }
1024  static double fromPromote(Promote v) { return v; }
1025  static double fromRealPromote(RealPromote v) { return v; }
1026 };
1027 
1028 template<>
1029 struct NumericTraits<long double>
1030 {
1031  typedef long double Type;
1032  typedef long double Promote;
1033  typedef long double UnsignedPromote;
1034  typedef long double RealPromote;
1035  typedef std::complex<RealPromote> ComplexPromote;
1036  typedef Type ValueType;
1037 
1038  typedef VigraFalseType isIntegral;
1039  typedef VigraTrueType isScalar;
1040  typedef VigraTrueType isSigned;
1041  typedef VigraTrueType isOrdered;
1042  typedef VigraFalseType isComplex;
1043 
1044  static long double zero() { return 0.0; }
1045  static long double one() { return 1.0; }
1046  static long double nonZero() { return 1.0; }
1047  static long double epsilon() { return LDBL_EPSILON; }
1048  static long double smallestPositive() { return LDBL_MIN; }
1049  static long double min() { return -LDBL_MAX; }
1050  static long double max() { return LDBL_MAX; }
1051 
1052  static Promote toPromote(long double v) { return v; }
1053  static RealPromote toRealPromote(long double v) { return v; }
1054  static long double fromPromote(Promote v) { return v; }
1055  static long double fromRealPromote(RealPromote v) { return v; }
1056 };
1057 
1058 #ifndef NO_PARTIAL_TEMPLATE_SPECIALIZATION
1059 
1060 template<class T>
1061 struct NumericTraits<std::complex<T> >
1062 {
1063  typedef std::complex<T> Type;
1064  typedef std::complex<typename NumericTraits<T>::Promote> Promote;
1065  typedef std::complex<typename NumericTraits<T>::UnsignedPromote> UnsignedPromote;
1066  typedef std::complex<typename NumericTraits<T>::RealPromote> RealPromote;
1067  typedef std::complex<RealPromote> ComplexPromote;
1068  typedef T ValueType;
1069 
1070  typedef VigraFalseType isIntegral;
1071  typedef VigraFalseType isScalar;
1072  typedef typename NumericTraits<T>::isSigned isSigned;
1073  typedef VigraFalseType isOrdered;
1074  typedef VigraTrueType isComplex;
1075 
1076  static Type zero() { return Type(0.0); }
1077  static Type one() { return Type(1.0); }
1078  static Type nonZero() { return one(); }
1079  static Type epsilon() { return Type(NumericTraits<T>::epsilon()); }
1080  static Type smallestPositive() { return Type(NumericTraits<T>::smallestPositive()); }
1081 
1082  static Promote toPromote(Type const & v) { return v; }
1083  static Type fromPromote(Promote const & v) { return v; }
1084  static Type fromRealPromote(RealPromote v) { return Type(v); }
1085 };
1086 
1087 #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION
1088 
1089 /********************************************************/
1090 /* */
1091 /* SquareRootTraits */
1092 /* */
1093 /********************************************************/
1094 
1095 template<class T>
1096 struct SquareRootTraits
1097 {
1098  typedef T Type;
1099  typedef typename NumericTraits<T>::RealPromote SquareRootResult;
1100  typedef typename NumericTraits<T>::RealPromote SquareRootArgument;
1101 };
1102 
1103 
1104 /********************************************************/
1105 /* */
1106 /* NormTraits */
1107 /* */
1108 /********************************************************/
1109 
1110 struct Error_NormTraits_not_specialized_for_this_case { };
1111 
1112 template<class T>
1113 struct NormTraits
1114 {
1115  typedef T Type;
1116  typedef Error_NormTraits_not_specialized_for_this_case SquaredNormType;
1117  typedef Error_NormTraits_not_specialized_for_this_case NormType;
1118 };
1119 
1120 #define VIGRA_DEFINE_NORM_TRAITS(T) \
1121  template <> struct NormTraits<T> { \
1122  typedef T Type; \
1123  typedef NumericTraits<T>::Promote SquaredNormType; \
1124  typedef T NormType; \
1125  };
1126 
1127 VIGRA_DEFINE_NORM_TRAITS(bool)
1128 VIGRA_DEFINE_NORM_TRAITS(signed char)
1129 VIGRA_DEFINE_NORM_TRAITS(unsigned char)
1130 VIGRA_DEFINE_NORM_TRAITS(short)
1131 VIGRA_DEFINE_NORM_TRAITS(unsigned short)
1132 VIGRA_DEFINE_NORM_TRAITS(int)
1133 VIGRA_DEFINE_NORM_TRAITS(unsigned int)
1134 VIGRA_DEFINE_NORM_TRAITS(long)
1135 VIGRA_DEFINE_NORM_TRAITS(unsigned long)
1136 VIGRA_DEFINE_NORM_TRAITS(float)
1137 VIGRA_DEFINE_NORM_TRAITS(double)
1138 VIGRA_DEFINE_NORM_TRAITS(long double)
1139 
1140 #ifdef LLONG_MAX
1141 VIGRA_DEFINE_NORM_TRAITS(long long)
1142 VIGRA_DEFINE_NORM_TRAITS(unsigned long long)
1143 #endif // LLONG_MAX
1144 
1145 #undef VIGRA_DEFINE_NORM_TRAITS
1146 
1147 #ifndef NO_PARTIAL_TEMPLATE_SPECIALIZATION
1148 
1149 template<class T>
1150 struct NormTraits<std::complex<T> >
1151 {
1152  typedef std::complex<T> Type;
1153  typedef typename NormTraits<T>::SquaredNormType SquaredNormType;
1154  typedef typename SquareRootTraits<SquaredNormType>::SquareRootResult NormType;
1155 };
1156 
1157 #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION
1158 
1159 /********************************************************/
1160 /* */
1161 /* PromoteTraits */
1162 /* */
1163 /********************************************************/
1164 
1165 namespace detail {
1166 
1167 template <class T, class U>
1168 struct PromoteType
1169 {
1170  static T & t();
1171  static U & u();
1172  // let C++ figure out the promote type by adding a T and an U
1173  typedef typename SizeToType<sizeof(*typeToSize(t() + u()))>::result Promote;
1174  static Promote toPromote(T t) { return Promote(t); }
1175  static Promote toPromote(U u) { return Promote(u); }
1176 };
1177 
1178 
1179 template <class T>
1180 struct PromoteType<T, T>
1181 {
1182  static T & t();
1183  // let C++ figure out the promote type by adding two Ts
1184  typedef typename SizeToType<sizeof(*typeToSize(t() + t()))>::result Promote;
1185  static Promote toPromote(T t) { return Promote(t); }
1186 };
1187 
1188 } // namespace detail
1189 
1190 struct Error_PromoteTraits_not_specialized_for_this_case { };
1191 
1192 template<class A, class B>
1193 struct PromoteTraits
1194 {
1195  typedef Error_PromoteTraits_not_specialized_for_this_case Promote;
1196 };
1197 
1198 #include "promote_traits.hxx"
1199 
1200 #ifndef NO_PARTIAL_TEMPLATE_SPECIALIZATION
1201 
1202 template <class T>
1203 struct PromoteTraits<std::complex<T>, std::complex<T> >
1204 {
1205  typedef std::complex<typename PromoteTraits<T, T>::Promote> Promote;
1206  static Promote toPromote(std::complex<T> const & v) { return v; }
1207 };
1208 
1209 template <class T1, class T2>
1210 struct PromoteTraits<std::complex<T1>, std::complex<T2> >
1211 {
1212  typedef std::complex<typename PromoteTraits<T1, T2>::Promote> Promote;
1213  static Promote toPromote(std::complex<T1> const & v) { return v; }
1214  static Promote toPromote(std::complex<T2> const & v) { return v; }
1215 };
1216 
1217 template <class T1, class T2>
1218 struct PromoteTraits<std::complex<T1>, T2 >
1219 {
1220  typedef std::complex<typename PromoteTraits<T1, T2>::Promote> Promote;
1221  static Promote toPromote(std::complex<T1> const & v) { return v; }
1222  static Promote toPromote(T2 const & v) { return Promote(v); }
1223 };
1224 
1225 template <class T1, class T2>
1226 struct PromoteTraits<T1, std::complex<T2> >
1227 {
1228  typedef std::complex<typename PromoteTraits<T1, T2>::Promote> Promote;
1229  static Promote toPromote(T1 const & v) { return Promote(v); }
1230  static Promote toPromote(std::complex<T2> const & v) { return v; }
1231 };
1232 
1233 #endif
1234 
1235 namespace detail {
1236 
1237 template <class T>
1238 struct RequiresExplicitCast {
1239  template <class U>
1240  static U const & cast(U const & v)
1241  { return v; }
1242 };
1243 
1244 #if !defined(_MSC_VER) || _MSC_VER >= 1300
1245 # define VIGRA_SPECIALIZED_CAST(type) \
1246  template <> \
1247  struct RequiresExplicitCast<type> { \
1248  static type cast(float v) \
1249  { return NumericTraits<type>::fromRealPromote(v); } \
1250  static type cast(double v) \
1251  { return NumericTraits<type>::fromRealPromote(v); } \
1252  static type cast(type v) \
1253  { return v; } \
1254  template <class U> \
1255  static type cast(U v) \
1256  { return static_cast<type>(v); } \
1257  \
1258  };
1259 #else
1260 # define VIGRA_SPECIALIZED_CAST(type) \
1261  template <> \
1262  struct RequiresExplicitCast<type> { \
1263  static type cast(float v) \
1264  { return NumericTraits<type>::fromRealPromote(v); } \
1265  static type cast(double v) \
1266  { return NumericTraits<type>::fromRealPromote(v); } \
1267  static type cast(signed char v) \
1268  { return v; } \
1269  static type cast(unsigned char v) \
1270  { return v; } \
1271  static type cast(short v) \
1272  { return v; } \
1273  static type cast(unsigned short v) \
1274  { return v; } \
1275  static type cast(int v) \
1276  { return v; } \
1277  static type cast(unsigned int v) \
1278  { return v; } \
1279  static type cast(long v) \
1280  { return v; } \
1281  static type cast(unsigned long v) \
1282  { return v; } \
1283  };
1284 #endif
1285 
1286 
1287 VIGRA_SPECIALIZED_CAST(signed char)
1288 VIGRA_SPECIALIZED_CAST(unsigned char)
1289 VIGRA_SPECIALIZED_CAST(short)
1290 VIGRA_SPECIALIZED_CAST(unsigned short)
1291 VIGRA_SPECIALIZED_CAST(int)
1292 VIGRA_SPECIALIZED_CAST(unsigned int)
1293 VIGRA_SPECIALIZED_CAST(long)
1294 VIGRA_SPECIALIZED_CAST(unsigned long)
1295 
1296 template <>
1297 struct RequiresExplicitCast<bool> {
1298  template <class U>
1299  static bool cast(U v)
1300  { return v == NumericTraits<U>::zero()
1301  ? false
1302  : true; }
1303 };
1304 
1305 template <>
1306 struct RequiresExplicitCast<float> {
1307  static float cast(int v)
1308  { return (float)v; }
1309 
1310  static float cast(unsigned int v)
1311  { return (float)v; }
1312 
1313  static float cast(long v)
1314  { return (float)v; }
1315 
1316  static float cast(unsigned long v)
1317  { return (float)v; }
1318 
1319  static float cast(long long v)
1320  { return (float)v; }
1321 
1322  static float cast(unsigned long long v)
1323  { return (float)v; }
1324 
1325  static float cast(double v)
1326  { return (float)v; }
1327 
1328  static float cast(long double v)
1329  { return (float)v; }
1330 
1331  template <class U>
1332  static U cast(U v)
1333  { return v; }
1334 };
1335 
1336 template <>
1337 struct RequiresExplicitCast<double> {
1338  static double cast(Int64 v)
1339  { return (double)v; }
1340 
1341  static double cast(UInt64 v)
1342  { return (double)v; }
1343 
1344  template <class U>
1345  static U cast(U v)
1346  { return v; }
1347 };
1348 
1349 #undef VIGRA_SPECIALIZED_CAST
1350 
1351 } // namespace detail
1352 
1353 
1354 
1355 } // namespace vigra
1356 
1357 #endif // VIGRA_NUMERICTRAITS_HXX
1358 

© 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.9.0 (Tue Oct 22 2013)