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

vigra/numerictraits.hxx

00001 /************************************************************************/
00002 /*                                                                      */
00003 /*               Copyright 1998-2002 by Ullrich Koethe                  */
00004 /*       Cognitive Systems Group, University of Hamburg, Germany        */
00005 /*                                                                      */
00006 /*    This file is part of the VIGRA computer vision library.           */
00007 /*    ( Version 1.6.0, Aug 13 2008 )                                    */
00008 /*    The VIGRA Website is                                              */
00009 /*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
00010 /*    Please direct questions, bug reports, and contributions to        */
00011 /*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
00012 /*        vigra@informatik.uni-hamburg.de                               */
00013 /*                                                                      */
00014 /*    Permission is hereby granted, free of charge, to any person       */
00015 /*    obtaining a copy of this software and associated documentation    */
00016 /*    files (the "Software"), to deal in the Software without           */
00017 /*    restriction, including without limitation the rights to use,      */
00018 /*    copy, modify, merge, publish, distribute, sublicense, and/or      */
00019 /*    sell copies of the Software, and to permit persons to whom the    */
00020 /*    Software is furnished to do so, subject to the following          */
00021 /*    conditions:                                                       */
00022 /*                                                                      */
00023 /*    The above copyright notice and this permission notice shall be    */
00024 /*    included in all copies or substantial portions of the             */
00025 /*    Software.                                                         */
00026 /*                                                                      */
00027 /*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
00028 /*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
00029 /*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
00030 /*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
00031 /*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
00032 /*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
00033 /*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
00034 /*    OTHER DEALINGS IN THE SOFTWARE.                                   */                
00035 /*                                                                      */
00036 /************************************************************************/
00037  
00038  
00039 #ifndef VIGRA_NUMERICTRAITS_HXX
00040 #define VIGRA_NUMERICTRAITS_HXX
00041 
00042 #include <limits.h>
00043 #include <cfloat>
00044 #include <complex>
00045 #include "metaprogramming.hxx"
00046 #include "sized_int.hxx"
00047 
00048 /********************************************************/
00049 /*                                                      */
00050 /*                      NumericTraits                   */
00051 /*                                                      */
00052 /********************************************************/
00053 
00054 
00055 /** \page NumericPromotionTraits Numeric and Promotion Traits
00056 
00057     Meta-information about arithmetic types.
00058     
00059     <UL style="list-style-image:url(documents/bullet.gif)">
00060     <LI> \ref NumericTraits
00061          <BR>&nbsp;&nbsp;&nbsp;<em>Unary traits for promotion, conversion, creation of arithmetic objects</em>
00062     <LI> \ref PromoteTraits
00063          <BR>&nbsp;&nbsp;&nbsp;<em>Binary traits for promotion of arithmetic objects</em>
00064     <LI> \ref SquareRootTraits
00065          <BR>&nbsp;&nbsp;&nbsp;<em>Unary traits for the calculation of the square root of arithmetic objects</em>
00066     <LI> \ref NormTraits
00067          <BR>&nbsp;&nbsp;&nbsp;<em>Unary traits for the calculation of the norm and squared norm of arithmetic objects</em>
00068     </UL>
00069     
00070     These traits classes contain information that is used by generic
00071     algorithms and data structures to determine intermediate and result
00072     types of numerical calculations, to convert between different 
00073     representations of arithmetic types, and to create certain important
00074     constants of each type. Thus, algorithms and data structures
00075     operating that need arithmetic operations can be made more
00076     independent from the actual data representation.
00077     
00078     NumericTraits are implemented as template specializations of one
00079     arithmetic type, while PromoteTraits are specialized for a pair of
00080     arithmetic types that shall be combined in one operation.    
00081 */
00082 
00083 /** \page NumericTraits template<> struct NumericTraits<ArithmeticType>
00084 
00085     Unary traits for promotion, conversion, creation of arithmetic objects.
00086 
00087     <b>\#include</b> 
00088     <<a href="numerictraits_8hxx-source.html">vigra/numerictraits.hxx</a>>
00089 
00090     This traits class is used derive important properties of
00091     an arithmetic type. Consider the following algorithm:
00092     
00093     \code
00094     // calculate the sum of a sequence of bytes
00095     int sumBytes(unsigned char * begin, unsigned char * end)
00096     {
00097         int result = 0;
00098         for(; begin != end; ++begin)  result += *begin;
00099         return result;
00100     }
00101     \endcode 
00102     
00103     The return type of this function can not be 'unsigned char' because
00104     the summation would very likely overflow. Since we know the source
00105     type, we can easily choose 'int' as an appropriate return type.
00106     Likewise, we would have choosen 'float' if we had to sum a 
00107     sequence of floats. If we want to make this 
00108     algorithm generic, we would like to derive the appropriate return 
00109     type automatically. This can be done with NumericTraits. 
00110     The code would look like this (we use \ref DataAccessors to 
00111     read the data from the sequence):
00112     
00113     \code
00114     // calculate the sum of any sequence
00115     template <class Iterator, class Accessor>
00116     typename vigra::NumericTraits<typename Accessor::value_type>::Promote
00117     sumSequence(Iterator begin, Iterator end, Accessor a)
00118     {
00119         // an abbreviation
00120         typedef vigra::NumericTraits<typename Accessor::value_type>  SrcTraits;
00121         
00122         // find out result type
00123         typedef typename SrcTraits::Promote ResultType;
00124       
00125         // init result to zero
00126         ResultType result = vigra::NumericTraits<ResultType>::zero();
00127     
00128         for(; begin != end; ++begin)
00129         {  
00130             // cast current item to ResultType and add
00131             result += SrcTraits::toPromote(a(begin));
00132         }
00133         
00134         return result;
00135     }
00136     \endcode
00137     
00138     In this example NumericTraits is not only used to deduce the 
00139     ReturnType of the operation, but also to initialize it with the
00140     constant 'zero'. This is necessary since we do not know in general,
00141     which expression must be used to obtain a zero of some arbitrary
00142     type - '<TT>ResultType result = 0;</TT>' would only work if the 
00143     ResultType had an constructor taking an '<TT>int</TT>' argument, and we 
00144     would not even have any guarantee as to what the semantics of this
00145     constructor are. In addition, the traits are used to cast the 
00146     source type into the promote type.
00147     
00148     Similarly, an algorithm that needs multiplication would use the 
00149     return type <TT>RealPromote</TT> and the functions <TT>one()</TT> and
00150     <TT>toRealPromote()</TT>. The following members are defined in 
00151     <b> <TT>NumericTraits<ArithmeticType></TT></b>:
00152     
00153     <table>
00154     <tr><td>
00155     <b> <TT>typedef ... Type;</TT></b>
00156     </td><td>
00157     
00158             the type itself 
00159         
00160     </td></tr>
00161     <tr><td>
00162     <b> <TT>typedef ... Promote;</TT></b>
00163     </td><td>
00164     
00165             promote type for addition and subtraction 
00166         
00167     </td></tr>
00168     <tr><td>
00169     <b> <TT>typedef ... RealPromote;</TT></b>
00170     </td><td>
00171             promote type for multiplication and division with a real number
00172     
00173     (only defined if <TT>ArithmeticType</TT> supports these operations) 
00174     
00175     </td></tr>
00176     <tr><td>
00177     <b> <TT>typedef ... ComplexPromote;</TT></b>
00178     </td><td>
00179     
00180             promote type for complex arithmetic 
00181         
00182     </td></tr>
00183     <tr><td>
00184     <b> <TT>typedef ... ValueType;</TT></b>
00185     </td><td>
00186     
00187             for scalar types: the type itself<br>
00188             otherwise: typename Type::value_type (if defined)
00189         
00190     </td></tr>
00191     <tr><td>
00192     <b> <TT>static Promote toPromote(ArithmeticType v);</TT></b>
00193     </td><td>
00194         convert to <TT>Promote</TT> type 
00195     
00196     </td></tr>
00197     <tr><td>
00198     <b> <TT>static RealPromote toRealPromote(ArithmeticType v);</TT></b>
00199     </td><td>
00200         convert to <TT>RealPromote</TT> type 
00201 
00202     (only defined if <TT>ArithmeticType</TT> supports multiplication) 
00203     
00204     </td></tr>
00205     <tr><td>
00206     <b> <TT>static ArithmeticType fromPromote(Promote v);</TT></b> 
00207     </td><td>
00208         convert from <TT>Promote</TT> type
00209     
00210     if <TT>v</TT> is outside the range of <TT>ArithmeticType</TT> it is clipped;
00211 
00212     </td></tr>
00213     <tr><td>
00214     <b> <TT>static ArithmeticType fromRealPromote(RealPromote v);</TT></b>
00215     </td><td>
00216         convert from <TT>RealPromote</TT> type 
00217     
00218     (only defined if 
00219     <TT>ArithmeticType</TT> supports multiplication)
00220     
00221     if <TT>ArithmeticType</TT> is an integral type, the result is rounded 
00222     
00223     if <TT>v</TT> is outside the range of <TT>ArithmeticType</TT> it is clipped
00224     
00225     </td></tr>
00226     <tr><td>
00227     <b> <TT>static ArithmeticType zero();</TT></b>
00228     </td><td>
00229     create neutral element of addition
00230     
00231     i.e. <TT>(ArithmeticType a = ...,</TT> 
00232     <TT>  a + NumericTraits<ArithmeticType>::zero() == a)</TT> 
00233     must always yield <TT>true</TT> 
00234     
00235     </td></tr>
00236     <tr><td>
00237     <b> <TT>static ArithmeticType nonZero();</TT></b>
00238     </td><td>
00239     create a non-zero element (if multiplication is defined, this yields one())
00240     
00241     i.e. <TT>(ArithmeticType a = ...,</TT> 
00242     <TT>  a + NumericTraits<ArithmeticType>::nonZero() == a)</TT> 
00243     must always yield <TT>false</TT> 
00244     
00245     </td></tr>
00246     <tr><td>
00247     <b> <TT>static ArithmeticType min();</TT></b>
00248     </td><td>
00249     the smallest number representable in this type.<br>
00250     Only available if isOrdered is VigraTrueType. For integral types,
00251     this equals <TT>INT_MIN</TT> etc., for real valued types it is <TT>-FLT_MAX</TT>
00252     etc. (<b>not</b> <TT>FLT_MIN</TT> -- this is the smallest positive <tt>float</tt>)
00253     
00254     </td></tr>
00255     <tr><td>
00256     <b> <TT>static ArithmeticType max();</TT></b>
00257     </td><td>
00258     the largest number representable in this type.<br>
00259     Only available if isOrdered is VigraTrueType. For integral types,
00260     this equals <TT>INT_MAX</TT> etc., for real valued types it is <TT>FLT_MAX</TT>
00261     etc.
00262     
00263     </td></tr>
00264     <tr><td>
00265     <b> <TT>static ArithmeticType one();</TT></b>
00266     </td><td>
00267     create neutral element of multiplication 
00268     
00269     (only defined if <TT>ArithmeticType</TT> supports multiplication)
00270     
00271     i.e. <TT>(ArithmeticType a = ...,</TT> 
00272     <TT>  a * NumericTraits<ArithmeticType>::one() == a)</TT> 
00273     must always yield <TT>true</TT> 
00274     
00275     </td></tr>
00276     <tr><td>
00277     <b> <TT>typedef ... isIntegral;</TT></b>
00278     </td><td>
00279         VigraTrueType if <TT>ArithmeticType</TT> is an integral type, 
00280         VigraFalseType otherwise 
00281     
00282     </td></tr>
00283     <tr><td>
00284     <b> <TT>typedef ... isScalar;</TT></b>
00285     </td><td>
00286         VigraTrueType if <TT>ArithmeticType</TT> is a scalar type, 
00287         VigraFalseType otherwise 
00288     
00289     </td></tr>
00290     <tr><td>
00291     <tr><td>
00292     <b> <TT>typedef ... isSigned;</TT></b>
00293     </td><td>
00294         VigraTrueType if <TT>ArithmeticType</TT> is a signed type, 
00295         VigraFalseType otherwise 
00296     
00297     </td></tr>
00298     <tr><td>
00299     <tr><td>
00300     <b> <TT>typedef ... isOrdered;</TT></b>
00301     </td><td>
00302         VigraTrueType if <TT>ArithmeticType</TT> supports operator<(), 
00303         VigraFalseType otherwise 
00304     
00305     </td></tr>
00306     <tr><td>
00307     <b> <TT>typedef ... isComplex;</TT></b>
00308     </td><td>
00309         VigraTrueType if <TT>ArithmeticType</TT> is a complex number, 
00310         VigraFalseType otherwise 
00311     
00312     </td></tr>
00313     <tr><td>
00314     </table>
00315     
00316     NumericTraits for the built-in types are defined in <b>\#include</b> 
00317     <<a href="numerictraits_8hxx-source.html">vigra/numerictraits.hxx</a>>
00318     
00319     Namespace: vigra
00320     
00321 */
00322 
00323 /** \page PromoteTraits template<> struct PromoteTraits<ArithmeticType1, ArithmeticType2>
00324 
00325     Binary traits for promotion of arithmetic objects.
00326     
00327     <b>\#include</b> 
00328     <<a href="numerictraits_8hxx-source.html">vigra/numerictraits.hxx</a>>
00329 
00330     This traits class is used to determine the appropriate result type
00331     of arithmetic expressions which depend of two arguments. Consider
00332     the following function:
00333     
00334     \code
00335     template <class T>
00336     T min(T t1, T t2)
00337     {
00338         return (t1 < t2) ? t1 : t2;
00339     }
00340     \endcode
00341     
00342     This template is only applicable if both arguments have the same
00343     type. However, sometimes we may want to use the function in cases
00344     where the argument types differ. The we can deduce the approrpiate
00345     return type by using <TT>PromoteTraits</TT>:
00346     
00347     \code
00348     template <class T1, class T2>
00349     typename vigra::PromoteTraits<T1, T2>::Promote
00350     min(T1 t1, T2 t2)
00351     {
00352         return (t1 < t2) ? vigra::PromoteTraits<T1, T2>::toPromote(t1) : 
00353                            vigra::PromoteTraits<T1, T2>::toPromote(t2);
00354     }    
00355     \endcode
00356     
00357     In addition, the traits class provide static functions to cast the
00358     arguments to the promote type. For example, if <TT>T1</TT> were <TT>int</TT> and 
00359     <TT>T2</TT> were <TT>float</TT>, the <TT>Promote</TT> type would be <TT>float</TT>. 
00360     The following members are defined in 
00361     <b> <TT>PromoteTraits<ArithmeticType1, ArithmeticType2></TT></b>:
00362     
00363     <table>
00364     <tr>
00365     <td>
00366     <b> <TT>typedef ... Promote;</TT></b>
00367     </td><td>
00368             promote type 
00369     </td></tr>
00370     <tr><td>
00371     <b> <TT>static Promote toPromote(ArithmeticType1 v);</TT></b> 
00372     
00373     <b> <TT>static Promote toPromote(ArithmeticType2 v);</TT></b>
00374     </td><td>
00375         convert to <TT>Promote</TT> type 
00376     </td></tr>
00377     </table>
00378     
00379     PromoteTraits for the built-in types are defined in <b>\#include</b> 
00380     <<a href="numerictraits_8hxx-source.html">vigra/numerictraits.hxx</a>>
00381     
00382     Namespace: vigra
00383 */
00384 
00385 /** \page SquareRootTraits template<> struct SquareRootTraits<ArithmeticType>
00386 
00387     Unary traits for the calculation of the square root of arithmetic objects.
00388     
00389     <b>\#include</b> 
00390     <<a href="numerictraits_8hxx-source.html">vigra/numerictraits.hxx</a>>
00391 
00392     This traits class is used to determine appropriate argument and result types
00393     for the function sqrt(). These traits are typically used like this:
00394     
00395     \code
00396     ArithmeticType t = ...;
00397     SquareRootTraits<ArithmeticType>::SquareRootResult r = 
00398           sqrt((SquareRootTraits<ArithmeticType>::SquareRootArgument)t);
00399     \endcode
00400     
00401     This approach avoids 'ambigouos overload errors' when taking the square root of 
00402     an integer type. It also takes care of determining the proper result of the
00403     sqrt() function of \ref vigra::FixedPoint and of the norm() function, when
00404     it is implemented via sqrt(squaredNorm(x)).
00405     The following members are defined in <b> <TT>SquareRootTraits<ArithmeticType></TT></b>:
00406     
00407     <table>
00408     <tr><td>
00409     <b> <TT>typedef ArithmeticType Type;</TT></b>
00410     </td><td>
00411             the type itself
00412     </td></tr>
00413     <tr><td>
00414     <b> <TT>typedef ... SquareRootArgument;</TT></b>
00415     </td><td>
00416             required argument type for srqt(), i.e. <tt>sqrt((SquareRootArgument)x)</tt>
00417     </td></tr>
00418     <tr><td>
00419     <b> <TT>typedef ... SquareRootResult;</TT></b>
00420     </td><td>
00421             result of <tt>sqrt((SquareRootArgument)x)</tt>
00422     </td></tr>
00423     </table>
00424     
00425     NormTraits for the built-in types are defined in <b>\#include</b> 
00426     <<a href="numerictraits_8hxx-source.html">vigra/numerictraits.hxx</a>>
00427     
00428     Namespace: vigra
00429 */
00430 
00431 /** \page NormTraits template<> struct NormTraits<ArithmeticType>
00432 
00433     Unary traits for the calculation of the norm and squared norm of arithmetic objects.
00434     
00435     <b>\#include</b> 
00436     <<a href="numerictraits_8hxx-source.html">vigra/numerictraits.hxx</a>>
00437 
00438     This traits class is used to determine appropriate result types
00439     for the functions norm() and squaredNorm(). These functions are always 
00440     declared like this (where <tt>ArithmeticType</tt> is a type thats supports a norm):
00441     
00442     \code
00443     NormTraits<ArithmeticType>::NormType        norm(ArithmeticType const & t);
00444     NormTraits<ArithmeticType>::SquaredNormType squaredNorm(ArithmeticType const & t);
00445     \endcode
00446     
00447     The following members are defined in <b> <TT>NormTraits<ArithmeticType></TT></b>:
00448     
00449     <table>
00450     <tr><td>
00451     <b> <TT>typedef ArithmeticType Type;</TT></b>
00452     </td><td>
00453             the type itself
00454     </td></tr>
00455     <tr><td>
00456     <b> <TT>typedef ... SquaredNormType;</TT></b>
00457     </td><td>
00458             result of <tt>squaredNorm(ArithmeticType)</tt>
00459     </td></tr>
00460     <tr><td>
00461     <b> <TT>typedef ... NormType;</TT></b>
00462     </td><td>
00463             result of <tt>norm(ArithmeticType)</tt><br>
00464             Usually equal to <tt>SquareRootTraits<SquaredNormType>::SquareRootResult</tt>
00465     </td></tr>
00466     </table>
00467     
00468     NormTraits for the built-in types are defined in <b>\#include</b> 
00469     <<a href="numerictraits_8hxx-source.html">vigra/numerictraits.hxx</a>>
00470     
00471     Namespace: vigra
00472 */
00473 
00474 namespace vigra {
00475 
00476 struct Error_NumericTraits_not_specialized_for_this_case { };
00477 struct Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char { };
00478 
00479 template<class A>
00480 struct NumericTraits
00481 {
00482     typedef Error_NumericTraits_not_specialized_for_this_case Type;
00483     typedef Error_NumericTraits_not_specialized_for_this_case Promote;
00484     typedef Error_NumericTraits_not_specialized_for_this_case UnsignedPromote;
00485     typedef Error_NumericTraits_not_specialized_for_this_case RealPromote;
00486     typedef Error_NumericTraits_not_specialized_for_this_case ComplexPromote;
00487     typedef Error_NumericTraits_not_specialized_for_this_case ValueType;
00488 
00489     typedef Error_NumericTraits_not_specialized_for_this_case isScalar;
00490     typedef Error_NumericTraits_not_specialized_for_this_case isIntegral;
00491     typedef Error_NumericTraits_not_specialized_for_this_case isSigned;
00492     typedef Error_NumericTraits_not_specialized_for_this_case isOrdered;
00493     typedef Error_NumericTraits_not_specialized_for_this_case isComplex;
00494 };
00495 
00496 template<>
00497 struct NumericTraits<char>
00498 {
00499     typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char Type;
00500     typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char Promote;
00501     typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char UnsignedPromote;
00502     typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char RealPromote;
00503     typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char ComplexPromote;
00504     typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char ValueType;
00505 
00506     typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char isScalar;
00507     typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char isIntegral;
00508     typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char isSigned;
00509     typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char isOrdered;
00510     typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char isComplex;
00511 };
00512 
00513 #ifndef NO_BOOL
00514 template<>
00515 struct NumericTraits<bool>
00516 {
00517     typedef bool Type;
00518     typedef int Promote;
00519     typedef unsigned int UnsignedPromote;
00520     typedef double RealPromote;
00521     typedef std::complex<RealPromote> ComplexPromote;
00522     typedef Type ValueType;
00523 
00524     typedef VigraTrueType isIntegral;
00525     typedef VigraTrueType isScalar;
00526     typedef VigraFalseType isSigned;
00527     typedef VigraTrueType isOrdered;
00528     typedef VigraFalseType isComplex;
00529     
00530     static bool zero() { return false; }
00531     static bool one() { return true; }
00532     static bool nonZero() { return true; }
00533     static bool min() { return false; }
00534     static bool max() { return true; }
00535     
00536 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
00537     enum { minConst = false , maxConst = true };
00538 #else
00539     static const bool minConst = false;
00540     static const bool maxConst = true;
00541 #endif
00542     
00543     static Promote toPromote(bool v) { return v ? 1 : 0; }
00544     static RealPromote toRealPromote(bool v) { return v ? 1.0 : 0.0; }
00545     static bool fromPromote(Promote v) { 
00546         return (v == 0) ? false : true; 
00547     }
00548     static bool fromRealPromote(RealPromote v) {
00549         return (v == 0.0) ? false : true; 
00550     }
00551 };
00552 #endif
00553 
00554 template<>
00555 struct NumericTraits<signed char>
00556 {
00557     typedef signed char Type;
00558     typedef int Promote;
00559     typedef unsigned int UnsignedPromote;
00560     typedef double RealPromote;
00561     typedef std::complex<RealPromote> ComplexPromote;
00562     typedef Type ValueType;
00563 
00564     typedef VigraTrueType isIntegral;
00565     typedef VigraTrueType isScalar;
00566     typedef VigraTrueType isSigned;
00567     typedef VigraTrueType isOrdered;
00568     typedef VigraFalseType isComplex;
00569     
00570     static signed char zero() { return 0; }
00571     static signed char one() { return 1; }
00572     static signed char nonZero() { return 1; }
00573     static signed char min() { return SCHAR_MIN; }
00574     static signed char max() { return SCHAR_MAX; }
00575     
00576 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
00577     enum { minConst = SCHAR_MIN, maxConst = SCHAR_MIN };
00578 #else
00579     static const signed char minConst = SCHAR_MIN;
00580     static const signed char maxConst = SCHAR_MIN;
00581 #endif
00582     
00583     static Promote toPromote(signed char v) { return v; }
00584     static RealPromote toRealPromote(signed char v) { return v; }
00585     static signed char fromPromote(Promote v) { 
00586         return ((v < SCHAR_MIN) ? SCHAR_MIN : (v > SCHAR_MAX) ? SCHAR_MAX : v); 
00587     }
00588     static signed char fromRealPromote(RealPromote v) {
00589         return ((v < 0.0) 
00590                    ? ((v < (RealPromote)SCHAR_MIN) 
00591                        ? SCHAR_MIN 
00592                        : static_cast<signed char>(v - 0.5)) 
00593                    : (v > (RealPromote)SCHAR_MAX) 
00594                        ? SCHAR_MAX 
00595                        : static_cast<signed char>(v + 0.5)); 
00596     }
00597 };
00598 
00599 template<>
00600 struct NumericTraits<unsigned char>
00601 {
00602     typedef unsigned char Type;
00603     typedef int Promote;
00604     typedef unsigned int UnsignedPromote;
00605     typedef double RealPromote;
00606     typedef std::complex<RealPromote> ComplexPromote;
00607     typedef Type ValueType;
00608 
00609     typedef VigraTrueType isIntegral;
00610     typedef VigraTrueType isScalar;
00611     typedef VigraFalseType isSigned;
00612     typedef VigraTrueType isOrdered;
00613     typedef VigraFalseType isComplex;
00614     
00615     static unsigned char zero() { return 0; }
00616     static unsigned char one() { return 1; }
00617     static unsigned char nonZero() { return 1; }
00618     static unsigned char min() { return 0; }
00619     static unsigned char max() { return UCHAR_MAX; }
00620     
00621 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
00622     enum { minConst = 0, maxConst = UCHAR_MAX };
00623 #else
00624     static const unsigned char minConst = 0;
00625     static const unsigned char maxConst = UCHAR_MAX;
00626 #endif
00627     
00628     static Promote toPromote(unsigned char v) { return v; }
00629     static RealPromote toRealPromote(unsigned char v) { return v; }
00630     static unsigned char fromPromote(Promote const & v) { 
00631         return Type((v < 0) 
00632              ? 0 
00633              : (v > (Promote)UCHAR_MAX) 
00634                     ? UCHAR_MAX
00635                     : v); 
00636     }
00637     static unsigned char fromRealPromote(RealPromote const & v) {
00638             return Type((v < 0.0) 
00639                      ? 0 
00640                      : ((v > (RealPromote)UCHAR_MAX) 
00641                          ? UCHAR_MAX 
00642                          : v + 0.5));
00643     }
00644 };
00645 
00646 template<>
00647 struct NumericTraits<short int>
00648 {
00649     typedef short int Type;
00650     typedef int Promote;
00651     typedef unsigned int UnsignedPromote;
00652     typedef double RealPromote;
00653     typedef std::complex<RealPromote> ComplexPromote;
00654     typedef Type ValueType;
00655 
00656     typedef VigraTrueType isIntegral;
00657     typedef VigraTrueType isScalar;
00658     typedef VigraTrueType isSigned;
00659     typedef VigraTrueType isOrdered;
00660     typedef VigraFalseType isComplex;
00661     
00662     static short int zero() { return 0; }
00663     static short int one() { return 1; }
00664     static short int nonZero() { return 1; }
00665     static short int min() { return SHRT_MIN; }
00666     static short int max() { return SHRT_MAX; }
00667     
00668 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
00669     enum { minConst = SHRT_MIN, maxConst = SHRT_MAX };
00670 #else
00671     static const short int minConst = SHRT_MIN;
00672     static const short int maxConst = SHRT_MAX;
00673 #endif
00674     
00675     static Promote toPromote(short int v) { return v; }
00676     static RealPromote toRealPromote(short int v) { return v; }
00677     static short int fromPromote(Promote v) { 
00678         return ((v < SHRT_MIN) ? SHRT_MIN : 
00679                 (v > SHRT_MAX) ? SHRT_MAX : v); 
00680     }
00681     static short int fromRealPromote(RealPromote v) {
00682         return ((v < 0.0) 
00683                  ? ((v < (RealPromote)SHRT_MIN) 
00684                      ? SHRT_MIN 
00685                      : static_cast<short int>(v - 0.5)) 
00686                  : ((v > (RealPromote)SHRT_MAX) 
00687                      ? SHRT_MAX 
00688                      : static_cast<short int>(v + 0.5))); 
00689     }
00690 };
00691 
00692 template<>
00693 struct NumericTraits<short unsigned int>
00694 {
00695     typedef short unsigned int Type;
00696     typedef int Promote;
00697     typedef unsigned int UnsignedPromote;
00698     typedef double RealPromote;
00699     typedef std::complex<RealPromote> ComplexPromote;
00700     typedef Type ValueType;
00701 
00702     typedef VigraTrueType isIntegral;
00703     typedef VigraTrueType isScalar;
00704     typedef VigraFalseType isSigned;
00705     typedef VigraTrueType isOrdered;
00706     typedef VigraFalseType isComplex;
00707 
00708     static short unsigned int zero() { return 0; }
00709     static short unsigned int one() { return 1; }
00710     static short unsigned int nonZero() { return 1; }
00711     static short unsigned int min() { return 0; }
00712     static short unsigned int max() { return USHRT_MAX; }
00713     
00714 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
00715     enum { minConst = 0, maxConst = USHRT_MAX };
00716 #else
00717     static const short unsigned int minConst = 0;
00718     static const short unsigned int maxConst = USHRT_MAX;
00719 #endif
00720 
00721     static Promote toPromote(short unsigned int v) { return v; }
00722     static RealPromote toRealPromote(short unsigned int v) { return v; }
00723     static short unsigned int fromPromote(Promote v) { 
00724         return Type((v < 0) 
00725               ? 0 
00726               : (v > USHRT_MAX) 
00727                    ? USHRT_MAX 
00728                    : v); 
00729     }
00730     static short unsigned int fromRealPromote(RealPromote v) {
00731             return Type((v < 0.0) 
00732                      ? 0 
00733                      : ((v > (RealPromote)USHRT_MAX) 
00734                          ? USHRT_MAX 
00735                          : v + 0.5));
00736     }
00737 };
00738 
00739 template<>
00740 struct NumericTraits<int>
00741 {
00742     typedef int Type;
00743     typedef int Promote;
00744     typedef unsigned int UnsignedPromote;
00745     typedef double RealPromote;
00746     typedef std::complex<RealPromote> ComplexPromote;
00747     typedef Type ValueType;
00748 
00749     typedef VigraTrueType isIntegral;
00750     typedef VigraTrueType isScalar;
00751     typedef VigraTrueType isSigned;
00752     typedef VigraTrueType isOrdered;
00753     typedef VigraFalseType isComplex;
00754 
00755     static int zero() { return 0; }
00756     static int one() { return 1; }
00757     static int nonZero() { return 1; }
00758     static int min() { return INT_MIN; }
00759     static int max() { return INT_MAX; }
00760     
00761 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
00762     enum { minConst = INT_MIN, maxConst = INT_MAX };
00763 #else
00764     static const int minConst = INT_MIN;
00765     static const int maxConst = INT_MAX;
00766 #endif
00767 
00768     static Promote toPromote(int v) { return v; }
00769     static RealPromote toRealPromote(int v) { return v; }
00770     static int fromPromote(Promote v) { return v; }
00771     static int fromRealPromote(RealPromote v) {
00772         return ((v < 0.0) 
00773                  ? ((v < (RealPromote)INT_MIN) 
00774                      ? INT_MIN 
00775                      : static_cast<int>(v - 0.5)) 
00776                  : ((v > (RealPromote)INT_MAX) 
00777                      ? INT_MAX 
00778                      : static_cast<int>(v + 0.5))); 
00779     }
00780 };
00781 
00782 template<>
00783 struct NumericTraits<unsigned int>
00784 {
00785     typedef unsigned int Type;
00786     typedef unsigned int Promote;
00787     typedef unsigned int UnsignedPromote;
00788     typedef double RealPromote;
00789     typedef std::complex<RealPromote> ComplexPromote;
00790     typedef Type ValueType;
00791 
00792     typedef VigraTrueType isIntegral;
00793     typedef VigraTrueType isScalar;
00794     typedef VigraFalseType isSigned;
00795     typedef VigraTrueType isOrdered;
00796     typedef VigraFalseType isComplex;
00797     
00798     static unsigned int zero() { return 0; }
00799     static unsigned int one() { return 1; }
00800     static unsigned int nonZero() { return 1; }
00801     static unsigned int min() { return 0; }
00802     static unsigned int max() { return UINT_MAX; }
00803     
00804 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
00805     enum { minConst = 0, maxConst = UINT_MAX };
00806 #else
00807     static const unsigned int minConst = 0;
00808     static const unsigned int maxConst = UINT_MAX;
00809 #endif
00810 
00811     static Promote toPromote(unsigned int v) { return v; }
00812     static RealPromote toRealPromote(unsigned int v) { return v; }
00813     static unsigned int fromPromote(Promote v) { return v; }
00814     static unsigned int fromRealPromote(RealPromote v) {
00815             return ((v < 0.0) 
00816                      ? 0 
00817                      : ((v > (RealPromote)UINT_MAX) 
00818                          ? UINT_MAX 
00819                          : static_cast<unsigned int>(v + 0.5)));
00820     }
00821 };
00822 
00823 template<>
00824 struct NumericTraits<long>
00825 {
00826     typedef long Type;
00827     typedef long Promote;
00828     typedef unsigned long UnsignedPromote;
00829     typedef double RealPromote;
00830     typedef std::complex<RealPromote> ComplexPromote;
00831     typedef Type ValueType;
00832 
00833     typedef VigraTrueType isIntegral;
00834     typedef VigraTrueType isScalar;
00835     typedef VigraTrueType isSigned;
00836     typedef VigraTrueType isOrdered;
00837     typedef VigraFalseType isComplex;
00838     
00839     static long zero() { return 0; }
00840     static long one() { return 1; }
00841     static long nonZero() { return 1; }
00842     static long min() { return LONG_MIN; }
00843     static long max() { return LONG_MAX; }
00844     
00845 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
00846     enum { minConst = LONG_MIN, maxConst = LONG_MAX };
00847 #else
00848     static const long minConst = LONG_MIN;
00849     static const long maxConst = LONG_MAX;
00850 #endif
00851 
00852     static Promote toPromote(long v) { return v; }
00853     static RealPromote toRealPromote(long v) { return v; }
00854     static long fromPromote(Promote v) { return v; }
00855     static long fromRealPromote(RealPromote v) {
00856         return ((v < 0.0) 
00857                  ? ((v < (RealPromote)LONG_MIN) 
00858                      ? LONG_MIN 
00859                      : static_cast<long>(v - 0.5)) 
00860                  : ((v > (RealPromote)LONG_MAX) 
00861                      ? LONG_MAX 
00862                      : static_cast<long>(v + 0.5))); 
00863     }
00864 };
00865 
00866 template<>
00867 struct NumericTraits<unsigned long>
00868 {
00869     typedef unsigned long Type;
00870     typedef unsigned long Promote;
00871     typedef unsigned long UnsignedPromote;
00872     typedef double RealPromote;
00873     typedef std::complex<RealPromote> ComplexPromote;
00874     typedef Type ValueType;
00875 
00876     typedef VigraTrueType isIntegral;
00877     typedef VigraTrueType isScalar;
00878     typedef VigraFalseType isSigned;
00879     typedef VigraTrueType isOrdered;
00880     typedef VigraFalseType isComplex;
00881     
00882     static unsigned long zero() { return 0; }
00883     static unsigned long one() { return 1; }
00884     static unsigned long nonZero() { return 1; }
00885     static unsigned long min() { return 0; }
00886     static unsigned long max() { return ULONG_MAX; }
00887     
00888 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
00889     enum { minConst = 0, maxConst = ULONG_MAX };
00890 #else
00891     static const unsigned long minConst = 0;
00892     static const unsigned long maxConst = ULONG_MAX;
00893 #endif
00894 
00895     static Promote toPromote(unsigned long v) { return v; }
00896     static RealPromote toRealPromote(unsigned long v) { return v; }
00897     static unsigned long fromPromote(Promote v) { return v; }
00898     static unsigned long fromRealPromote(RealPromote v) {
00899             return ((v < 0.0) 
00900                      ? 0 
00901                      : ((v > (RealPromote)ULONG_MAX) 
00902                          ? ULONG_MAX 
00903                          : static_cast<unsigned long>(v + 0.5)));
00904     }
00905 };
00906 
00907 #ifdef LLONG_MAX
00908 template<>
00909 struct NumericTraits<long long>
00910 {
00911     typedef long long Type;
00912     typedef long long Promote;
00913     typedef unsigned long long UnsignedPromote;
00914     typedef double RealPromote;
00915     typedef std::complex<RealPromote> ComplexPromote;
00916     typedef Type ValueType;
00917 
00918     typedef VigraTrueType isIntegral;
00919     typedef VigraTrueType isScalar;
00920     typedef VigraTrueType isSigned;
00921     typedef VigraTrueType isOrdered;
00922     typedef VigraFalseType isComplex;
00923     
00924     static long long zero() { return 0; }
00925     static long long one() { return 1; }
00926     static long long nonZero() { return 1; }
00927     static long long min() { return LLONG_MIN; }
00928     static long long max() { return LLONG_MAX; }
00929     
00930 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
00931     enum { minConst = LLONG_MIN, maxConst = LLONG_MAX };
00932 #else
00933     static const long long minConst = LLONG_MIN;
00934     static const long long maxConst = LLONG_MAX;
00935 #endif
00936 
00937     static Promote toPromote(long long v) { return v; }
00938     static RealPromote toRealPromote(long long v) { return v; }
00939     static long long fromPromote(Promote v) { return v; }
00940     static long long fromRealPromote(RealPromote v) {
00941         return ((v < 0.0) 
00942                  ? ((v < (RealPromote)LLONG_MIN) 
00943                      ? LLONG_MIN 
00944                      : static_cast<long long>(v - 0.5)) 
00945                  : ((v > (RealPromote)LLONG_MAX) 
00946                      ? LLONG_MAX 
00947                      : static_cast<long long>(v + 0.5))); 
00948     }
00949 };
00950 
00951 template<>
00952 struct NumericTraits<unsigned long long>
00953 {
00954     typedef unsigned long long Type;
00955     typedef unsigned long long Promote;
00956     typedef unsigned long long UnsignedPromote;
00957     typedef double RealPromote;
00958     typedef std::complex<RealPromote> ComplexPromote;
00959     typedef Type ValueType;
00960 
00961     typedef VigraTrueType isIntegral;
00962     typedef VigraTrueType isScalar;
00963     typedef VigraFalseType isSigned;
00964     typedef VigraTrueType isOrdered;
00965     typedef VigraFalseType isComplex;
00966     
00967     static unsigned long long zero() { return 0; }
00968     static unsigned long long one() { return 1; }
00969     static unsigned long long nonZero() { return 1; }
00970     static unsigned long long min() { return 0; }
00971     static unsigned long long max() { return ULLONG_MAX; }
00972     
00973 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
00974     enum { minConst = 0, maxConst = ULLONG_MAX };
00975 #else
00976     static const unsigned long long minConst = 0;
00977     static const unsigned long long maxConst = ULLONG_MAX;
00978 #endif
00979 
00980     static Promote toPromote(unsigned long long v) { return v; }
00981     static RealPromote toRealPromote(unsigned long long v) { return v; }
00982     static unsigned long long fromPromote(Promote v) { return v; }
00983     static unsigned long long fromRealPromote(RealPromote v) {
00984             return ((v < 0.0) 
00985                      ? 0 
00986                      : ((v > (RealPromote)ULLONG_MAX) 
00987                          ? ULONG_MAX 
00988                          : static_cast<unsigned long long>(v + 0.5)));
00989     }
00990 };
00991 #endif // LLONG_MAX
00992 
00993 template<>
00994 struct NumericTraits<float>
00995 {
00996     typedef float Type;
00997     typedef float Promote;
00998     typedef float UnsignedPromote;
00999     typedef float RealPromote;
01000     typedef std::complex<RealPromote> ComplexPromote;
01001     typedef Type ValueType;
01002     
01003     typedef VigraFalseType isIntegral;
01004     typedef VigraTrueType isScalar;
01005     typedef VigraTrueType isSigned;
01006     typedef VigraTrueType isOrdered;
01007     typedef VigraFalseType isComplex;
01008     
01009     static float zero() { return 0.0; }
01010     static float one() { return 1.0; }
01011     static float nonZero() { return 1.0; }
01012     static float epsilon() { return FLT_EPSILON; }
01013     static float smallestPositive() { return FLT_MIN; }
01014     static float min() { return -FLT_MAX; }
01015     static float max() { return FLT_MAX; }
01016     
01017     static Promote toPromote(float v) { return v; }
01018     static RealPromote toRealPromote(float v) { return v; }
01019     static float fromPromote(Promote v) { return v; }
01020     static float fromRealPromote(RealPromote v) { return v; }
01021 };
01022 
01023 template<>
01024 struct NumericTraits<double>
01025 {
01026     typedef double Type;
01027     typedef double Promote;
01028     typedef double UnsignedPromote;
01029     typedef double RealPromote;
01030     typedef std::complex<RealPromote> ComplexPromote;
01031     typedef Type ValueType;
01032 
01033     typedef VigraFalseType isIntegral;
01034     typedef VigraTrueType isScalar;
01035     typedef VigraTrueType isSigned;
01036     typedef VigraTrueType isOrdered;
01037     typedef VigraFalseType isComplex;
01038     
01039     static double zero() { return 0.0; }
01040     static double one() { return 1.0; }
01041     static double nonZero() { return 1.0; }
01042     static double epsilon() { return DBL_EPSILON; }
01043     static double smallestPositive() { return DBL_MIN; }
01044     static double min() { return -DBL_MAX; }
01045     static double max() { return DBL_MAX; }
01046 
01047     static Promote toPromote(double v) { return v; }
01048     static RealPromote toRealPromote(double v) { return v; }
01049     static double fromPromote(Promote v) { return v; }
01050     static double fromRealPromote(RealPromote v) { return v; }
01051 };
01052 
01053 template<>
01054 struct NumericTraits<long double>
01055 {
01056     typedef long double Type;
01057     typedef long double Promote;
01058     typedef long double UnsignedPromote;
01059     typedef long double RealPromote;
01060     typedef std::complex<RealPromote> ComplexPromote;
01061     typedef Type ValueType;
01062 
01063     typedef VigraFalseType isIntegral;
01064     typedef VigraTrueType isScalar;
01065     typedef VigraTrueType isSigned;
01066     typedef VigraTrueType isOrdered;
01067     typedef VigraFalseType isComplex;
01068     
01069     static long double zero() { return 0.0; }
01070     static long double one() { return 1.0; }
01071     static long double nonZero() { return 1.0; }
01072     static long double epsilon() { return LDBL_EPSILON; }
01073     static long double smallestPositive() { return LDBL_MIN; }
01074     static long double min() { return -LDBL_MAX; }
01075     static long double max() { return LDBL_MAX; }
01076 
01077     static Promote toPromote(long double v) { return v; }
01078     static RealPromote toRealPromote(long double v) { return v; }
01079     static long double fromPromote(Promote v) { return v; }
01080     static long double fromRealPromote(RealPromote v) { return v; }
01081 };
01082 
01083 #ifndef NO_PARTIAL_TEMPLATE_SPECIALIZATION
01084 
01085 template<class T>
01086 struct NumericTraits<std::complex<T> >
01087 {
01088     typedef std::complex<T> Type;
01089     typedef std::complex<typename NumericTraits<T>::Promote> Promote;
01090     typedef std::complex<typename NumericTraits<T>::UnsignedPromote> UnsignedPromote;
01091     typedef std::complex<typename NumericTraits<T>::RealPromote> RealPromote;
01092     typedef std::complex<RealPromote> ComplexPromote;
01093     typedef T ValueType;
01094 
01095     typedef VigraFalseType isIntegral;
01096     typedef VigraFalseType isScalar;
01097     typedef typename NumericTraits<T>::isSigned isSigned;
01098     typedef VigraFalseType isOrdered;
01099     typedef VigraTrueType isComplex;
01100     
01101     static Type zero() { return Type(0.0); }
01102     static Type one() { return Type(1.0); }
01103     static Type nonZero() { return one(); }
01104     static Type epsilon() { return Type(NumericTraits<T>::epsilon()); }
01105     static Type smallestPositive() { return Type(NumericTraits<T>::smallestPositive()); }
01106 
01107     static Promote toPromote(Type const & v) { return v; }
01108     static Type fromPromote(Promote const & v) { return v; }
01109     static Type fromRealPromote(RealPromote v) { return Type(v); }
01110 };
01111 
01112 #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION
01113 
01114 /********************************************************/
01115 /*                                                      */
01116 /*                    SquareRootTraits                  */
01117 /*                                                      */
01118 /********************************************************/
01119 
01120 template<class T>
01121 struct SquareRootTraits
01122 {
01123     typedef T                                                    Type;
01124     typedef typename NumericTraits<T>::RealPromote               SquareRootResult;
01125     typedef typename NumericTraits<T>::RealPromote               SquareRootArgument;
01126 };
01127 
01128 
01129 /********************************************************/
01130 /*                                                      */
01131 /*                       NormTraits                     */
01132 /*                                                      */
01133 /********************************************************/
01134 
01135 struct Error_NormTraits_not_specialized_for_this_case { };
01136 
01137 template<class T>
01138 struct NormTraits
01139 {
01140     typedef T                                                Type;
01141     typedef Error_NormTraits_not_specialized_for_this_case   SquaredNormType;
01142     typedef Error_NormTraits_not_specialized_for_this_case   NormType;
01143 };
01144 
01145 #define VIGRA_DEFINE_NORM_TRAITS(T) \
01146     template <> struct NormTraits<T> { \
01147         typedef T Type; \
01148         typedef NumericTraits<T>::Promote SquaredNormType; \
01149         typedef T NormType; \
01150     };
01151 
01152 VIGRA_DEFINE_NORM_TRAITS(bool)
01153 VIGRA_DEFINE_NORM_TRAITS(signed char)
01154 VIGRA_DEFINE_NORM_TRAITS(unsigned char)
01155 VIGRA_DEFINE_NORM_TRAITS(short)
01156 VIGRA_DEFINE_NORM_TRAITS(unsigned short)
01157 VIGRA_DEFINE_NORM_TRAITS(int)
01158 VIGRA_DEFINE_NORM_TRAITS(unsigned int)
01159 VIGRA_DEFINE_NORM_TRAITS(long)
01160 VIGRA_DEFINE_NORM_TRAITS(unsigned long)
01161 VIGRA_DEFINE_NORM_TRAITS(float)
01162 VIGRA_DEFINE_NORM_TRAITS(double)
01163 VIGRA_DEFINE_NORM_TRAITS(long double)
01164 
01165 #ifdef LLONG_MAX
01166 VIGRA_DEFINE_NORM_TRAITS(long long)
01167 VIGRA_DEFINE_NORM_TRAITS(unsigned long long)
01168 #endif // LLONG_MAX
01169 
01170 #undef VIGRA_DEFINE_NORM_TRAITS
01171 
01172 #ifndef NO_PARTIAL_TEMPLATE_SPECIALIZATION
01173 
01174 template<class T>
01175 struct NormTraits<std::complex<T> >
01176 {
01177     typedef std::complex<T>                                              Type;
01178     typedef typename NormTraits<T>::SquaredNormType                      SquaredNormType;
01179     typedef typename SquareRootTraits<SquaredNormType>::SquareRootResult NormType;
01180 };
01181 
01182 #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION
01183 
01184 /********************************************************/
01185 /*                                                      */
01186 /*                      PromoteTraits                   */
01187 /*                                                      */
01188 /********************************************************/
01189 
01190 namespace detail {
01191 
01192 template <class T, class U>
01193 struct PromoteType
01194 {
01195     static T & t();
01196     static U & u();
01197     // let C++ figure out the promote type by adding a T and an U
01198     typedef typename SizeToType<sizeof(*typeToSize(t() + u()))>::result Promote;
01199     static Promote toPromote(T t) { return Promote(t); }
01200     static Promote toPromote(U u) { return Promote(u); }
01201 };
01202 
01203 
01204 template <class T>
01205 struct PromoteType<T, T>
01206 {
01207     static T & t();
01208     // let C++ figure out the promote type by adding two Ts
01209     typedef typename SizeToType<sizeof(*typeToSize(t() + t()))>::result Promote;
01210     static Promote toPromote(T t) { return Promote(t); }
01211 };
01212 
01213 } // namespace detail
01214 
01215 struct Error_PromoteTraits_not_specialized_for_this_case { };
01216 
01217 template<class A, class B>
01218 struct PromoteTraits
01219 {
01220     typedef Error_PromoteTraits_not_specialized_for_this_case Promote;
01221 };
01222 
01223 #include "promote_traits.hxx"
01224 
01225 #ifndef NO_PARTIAL_TEMPLATE_SPECIALIZATION
01226 
01227 template <class T>
01228 struct PromoteTraits<std::complex<T>, std::complex<T> >
01229 {
01230     typedef std::complex<typename PromoteTraits<T, T>::Promote> Promote;
01231     static Promote toPromote(std::complex<T> const & v) { return v; }
01232 };
01233 
01234 template <class T1, class T2>
01235 struct PromoteTraits<std::complex<T1>, std::complex<T2> >
01236 {
01237     typedef std::complex<typename PromoteTraits<T1, T2>::Promote> Promote;
01238     static Promote toPromote(std::complex<T1> const & v) { return v; }
01239     static Promote toPromote(std::complex<T2> const & v) { return v; }
01240 };
01241 
01242 template <class T1, class T2>
01243 struct PromoteTraits<std::complex<T1>, T2 >
01244 {
01245     typedef std::complex<typename PromoteTraits<T1, T2>::Promote> Promote;
01246     static Promote toPromote(std::complex<T1> const & v) { return v; }
01247     static Promote toPromote(T2 const & v) { return Promote(v); }
01248 };
01249 
01250 template <class T1, class T2>
01251 struct PromoteTraits<T1, std::complex<T2> >
01252 {
01253     typedef std::complex<typename PromoteTraits<T1, T2>::Promote> Promote;
01254     static Promote toPromote(T1 const & v) { return Promote(v); }
01255     static Promote toPromote(std::complex<T2> const & v) { return v; }
01256 };
01257 
01258 #endif
01259 
01260 namespace detail {
01261 
01262 template <class T>
01263 struct RequiresExplicitCast {
01264     template <class U>
01265     static U const & cast(U const & v)
01266         { return v; }
01267 };
01268 
01269 #if !defined(_MSC_VER) || _MSC_VER >= 1300
01270 #  define VIGRA_SPECIALIZED_CAST(type) \
01271     template <> \
01272     struct RequiresExplicitCast<type> { \
01273         static type cast(float v) \
01274             { return NumericTraits<type>::fromRealPromote(v); } \
01275         static type cast(double v) \
01276             { return NumericTraits<type>::fromRealPromote(v); } \
01277         static type cast(type v) \
01278             { return v; } \
01279         template <class U> \
01280         static type cast(U v) \
01281             { return static_cast<type>(v); } \
01282  \
01283     };
01284 #else
01285 #  define VIGRA_SPECIALIZED_CAST(type) \
01286     template <> \
01287     struct RequiresExplicitCast<type> { \
01288         static type cast(float v) \
01289             { return NumericTraits<type>::fromRealPromote(v); } \
01290         static type cast(double v) \
01291             { return NumericTraits<type>::fromRealPromote(v); } \
01292         static type cast(signed char v) \
01293             { return v; } \
01294         static type cast(unsigned char v) \
01295             { return v; } \
01296         static type cast(short v) \
01297             { return v; } \
01298         static type cast(unsigned short v) \
01299             { return v; } \
01300         static type cast(int v) \
01301             { return v; } \
01302         static type cast(unsigned int v) \
01303             { return v; } \
01304         static type cast(long v) \
01305             { return v; } \
01306         static type cast(unsigned long v) \
01307             { return v; } \
01308     };
01309 #endif
01310 
01311 
01312 VIGRA_SPECIALIZED_CAST(signed char)
01313 VIGRA_SPECIALIZED_CAST(unsigned char)
01314 VIGRA_SPECIALIZED_CAST(short)
01315 VIGRA_SPECIALIZED_CAST(unsigned short)
01316 VIGRA_SPECIALIZED_CAST(int)
01317 VIGRA_SPECIALIZED_CAST(unsigned int)
01318 VIGRA_SPECIALIZED_CAST(long)
01319 VIGRA_SPECIALIZED_CAST(unsigned long)
01320 
01321 template <>
01322 struct RequiresExplicitCast<float> {
01323     template <class U>
01324     static U cast(U v)
01325         { return v; }
01326 };
01327 
01328 template <>
01329 struct RequiresExplicitCast<double> {
01330     template <class U>
01331     static U cast(U v)
01332         { return v; }
01333 };
01334 
01335 #undef VIGRA_SPECIALIZED_CAST
01336 
01337 } // namespace detail
01338 
01339 
01340 
01341 } // namespace vigra
01342 
01343 #endif // VIGRA_NUMERICTRAITS_HXX
01344 

© 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.6.0 (13 Aug 2008)