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

© 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 (5 Nov 2009)