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

vigra/numerictraits.hxx VIGRA

00001 /************************************************************************/
00002 /*                                                                      */
00003 /*               Copyright 1998-2002 by Ullrich Koethe                  */
00004 /*                                                                      */
00005 /*    This file is part of the VIGRA computer vision library.           */
00006 /*    The VIGRA Website is                                              */
00007 /*        http://hci.iwr.uni-heidelberg.de/vigra/                       */
00008 /*    Please direct questions, bug reports, and contributions to        */
00009 /*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
00010 /*        vigra@informatik.uni-hamburg.de                               */
00011 /*                                                                      */
00012 /*    Permission is hereby granted, free of charge, to any person       */
00013 /*    obtaining a copy of this software and associated documentation    */
00014 /*    files (the "Software"), to deal in the Software without           */
00015 /*    restriction, including without limitation the rights to use,      */
00016 /*    copy, modify, merge, publish, distribute, sublicense, and/or      */
00017 /*    sell copies of the Software, and to permit persons to whom the    */
00018 /*    Software is furnished to do so, subject to the following          */
00019 /*    conditions:                                                       */
00020 /*                                                                      */
00021 /*    The above copyright notice and this permission notice shall be    */
00022 /*    included in all copies or substantial portions of the             */
00023 /*    Software.                                                         */
00024 /*                                                                      */
00025 /*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
00026 /*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
00027 /*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
00028 /*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
00029 /*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
00030 /*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
00031 /*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
00032 /*    OTHER DEALINGS IN THE SOFTWARE.                                   */                
00033 /*                                                                      */
00034 /************************************************************************/
00035  
00036  
00037 #ifndef VIGRA_NUMERICTRAITS_HXX
00038 #define VIGRA_NUMERICTRAITS_HXX
00039 
00040 #include <climits>
00041 #include <limits>
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     <vigra/numerictraits.hxx>
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 chosen '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     <vigra/numerictraits.hxx>
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     <vigra/numerictraits.hxx>
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. Then we can deduce the appropriate
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     <vigra/numerictraits.hxx>
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     <vigra/numerictraits.hxx>
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 'ambiguous 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     <vigra/numerictraits.hxx>
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     <vigra/numerictraits.hxx>
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 that 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     <vigra/numerictraits.hxx>
00469     
00470     Namespace: vigra
00471 */
00472 
00473 
00474 namespace vigra {
00475     namespace detail {
00476         template <typename s, typename t>
00477         inline static t clamp_integer_to_unsigned(s value, t maximum) {
00478             return
00479                 value <= s() ?
00480                 t() :
00481                 (value >= static_cast<s>(maximum) ? maximum : static_cast<t>(value));
00482         }
00483 
00484         template <typename s, typename t>
00485         inline static t clamp_integer_to_signed(s value, t minimum, t maximum) {
00486             return
00487                 value <= static_cast<s>(minimum) ?
00488                 minimum :
00489                 (value >= static_cast<s>(maximum) ? maximum : static_cast<t>(value));
00490         }
00491 
00492         template <typename s, typename t>
00493         inline static t clamp_float_to_unsigned(s value, t maximum) {
00494             return
00495                 value <= s() ?
00496                 t() :
00497                 (value >= static_cast<s>(maximum) ? maximum : static_cast<t>(value + 0.5));
00498         }
00499 
00500         template <typename s, typename t>
00501         inline static t clamp_float_to_signed(s value, t minimum, t maximum) {
00502             if (value >= s()) {
00503                 return value >= static_cast<s>(maximum) ? maximum : static_cast<t>(value + 0.5);
00504             } else {
00505                 return value <= static_cast<s>(minimum) ? minimum : static_cast<t>(value - 0.5);
00506             }
00507         }
00508     } // end namespace detail
00509 
00510 struct Error_NumericTraits_not_specialized_for_this_case { };
00511 struct Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char { };
00512 
00513 template<class A>
00514 struct NumericTraits
00515 {
00516     typedef Error_NumericTraits_not_specialized_for_this_case Type;
00517     typedef Error_NumericTraits_not_specialized_for_this_case Promote;
00518     typedef Error_NumericTraits_not_specialized_for_this_case UnsignedPromote;
00519     typedef Error_NumericTraits_not_specialized_for_this_case RealPromote;
00520     typedef Error_NumericTraits_not_specialized_for_this_case ComplexPromote;
00521     typedef Error_NumericTraits_not_specialized_for_this_case ValueType;
00522 
00523     typedef Error_NumericTraits_not_specialized_for_this_case isScalar;
00524     typedef Error_NumericTraits_not_specialized_for_this_case isIntegral;
00525     typedef Error_NumericTraits_not_specialized_for_this_case isSigned;
00526     typedef Error_NumericTraits_not_specialized_for_this_case isOrdered;
00527     typedef Error_NumericTraits_not_specialized_for_this_case isComplex;
00528 };
00529 
00530 template<>
00531 struct NumericTraits<char>
00532 {
00533     typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char Type;
00534     typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char Promote;
00535     typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char UnsignedPromote;
00536     typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char RealPromote;
00537     typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char ComplexPromote;
00538     typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char ValueType;
00539 
00540     typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char isScalar;
00541     typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char isIntegral;
00542     typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char isSigned;
00543     typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char isOrdered;
00544     typedef Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_unsigned_char isComplex;
00545 };
00546 
00547 #ifndef NO_BOOL
00548 template<>
00549 struct NumericTraits<bool>
00550 {
00551     typedef bool Type;
00552     typedef int Promote;
00553     typedef unsigned int UnsignedPromote;
00554     typedef double RealPromote;
00555     typedef std::complex<RealPromote> ComplexPromote;
00556     typedef Type ValueType;
00557 
00558     typedef VigraTrueType isIntegral;
00559     typedef VigraTrueType isScalar;
00560     typedef VigraFalseType isSigned;
00561     typedef VigraTrueType isOrdered;
00562     typedef VigraFalseType isComplex;
00563     
00564     static bool zero() { return false; }
00565     static bool one() { return true; }
00566     static bool nonZero() { return true; }
00567     static bool min() { return false; }
00568     static bool max() { return true; }
00569     
00570 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
00571     enum { minConst = false , maxConst = true };
00572 #else
00573     static const bool minConst = false;
00574     static const bool maxConst = true;
00575 #endif
00576     
00577     static Promote toPromote(bool v) { return v ? 1 : 0; }
00578     static RealPromote toRealPromote(bool v) { return v ? 1.0 : 0.0; }
00579     static bool fromPromote(Promote v) { 
00580         return (v == 0) ? false : true; 
00581     }
00582     static bool fromRealPromote(RealPromote v) {
00583         return (v == 0.0) ? false : true; 
00584     }
00585 };
00586 #endif
00587 
00588 template<>
00589 struct NumericTraits<signed char>
00590 {
00591     typedef signed char Type;
00592     typedef int Promote;
00593     typedef unsigned int UnsignedPromote;
00594     typedef double RealPromote;
00595     typedef std::complex<RealPromote> ComplexPromote;
00596     typedef Type ValueType;
00597 
00598     typedef VigraTrueType isIntegral;
00599     typedef VigraTrueType isScalar;
00600     typedef VigraTrueType isSigned;
00601     typedef VigraTrueType isOrdered;
00602     typedef VigraFalseType isComplex;
00603     
00604     static signed char zero() { return 0; }
00605     static signed char one() { return 1; }
00606     static signed char nonZero() { return 1; }
00607     static signed char min() { return SCHAR_MIN; }
00608     static signed char max() { return SCHAR_MAX; }
00609     
00610 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
00611     enum { minConst = SCHAR_MIN, maxConst = SCHAR_MIN };
00612 #else
00613     static const signed char minConst = SCHAR_MIN;
00614     static const signed char maxConst = SCHAR_MIN;
00615 #endif
00616     
00617     static Promote toPromote(signed char v) { return v; }
00618     static RealPromote toRealPromote(signed char v) { return v; }
00619     static signed char fromPromote(Promote v) {
00620         return detail::clamp_integer_to_signed<Promote, signed char>(v, SCHAR_MIN, SCHAR_MAX);
00621     }
00622     static signed char fromRealPromote(RealPromote v) {
00623         return detail::clamp_float_to_signed<RealPromote, signed char>(v, SCHAR_MIN, SCHAR_MAX);
00624     }
00625 };
00626 
00627 template<>
00628 struct NumericTraits<unsigned char>
00629 {
00630     typedef unsigned char Type;
00631     typedef int Promote;
00632     typedef unsigned int UnsignedPromote;
00633     typedef double RealPromote;
00634     typedef std::complex<RealPromote> ComplexPromote;
00635     typedef Type ValueType;
00636 
00637     typedef VigraTrueType isIntegral;
00638     typedef VigraTrueType isScalar;
00639     typedef VigraFalseType isSigned;
00640     typedef VigraTrueType isOrdered;
00641     typedef VigraFalseType isComplex;
00642     
00643     static unsigned char zero() { return 0; }
00644     static unsigned char one() { return 1; }
00645     static unsigned char nonZero() { return 1; }
00646     static unsigned char min() { return 0; }
00647     static unsigned char max() { return UCHAR_MAX; }
00648     
00649 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
00650     enum { minConst = 0, maxConst = UCHAR_MAX };
00651 #else
00652     static const unsigned char minConst = 0;
00653     static const unsigned char maxConst = UCHAR_MAX;
00654 #endif
00655     
00656     static Promote toPromote(unsigned char v) { return v; }
00657     static RealPromote toRealPromote(unsigned char v) { return v; }
00658     static unsigned char fromPromote(Promote v) {
00659         return detail::clamp_integer_to_unsigned<Promote, unsigned char>(v, UCHAR_MAX);
00660     }
00661     static unsigned char fromRealPromote(RealPromote v) {
00662         return detail::clamp_float_to_unsigned<RealPromote, unsigned char>(v, UCHAR_MAX);
00663     }
00664 };
00665 
00666 template<>
00667 struct NumericTraits<short int>
00668 {
00669     typedef short int Type;
00670     typedef int Promote;
00671     typedef unsigned int UnsignedPromote;
00672     typedef double RealPromote;
00673     typedef std::complex<RealPromote> ComplexPromote;
00674     typedef Type ValueType;
00675 
00676     typedef VigraTrueType isIntegral;
00677     typedef VigraTrueType isScalar;
00678     typedef VigraTrueType isSigned;
00679     typedef VigraTrueType isOrdered;
00680     typedef VigraFalseType isComplex;
00681     
00682     static short int zero() { return 0; }
00683     static short int one() { return 1; }
00684     static short int nonZero() { return 1; }
00685     static short int min() { return SHRT_MIN; }
00686     static short int max() { return SHRT_MAX; }
00687     
00688 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
00689     enum { minConst = SHRT_MIN, maxConst = SHRT_MAX };
00690 #else
00691     static const short int minConst = SHRT_MIN;
00692     static const short int maxConst = SHRT_MAX;
00693 #endif
00694     
00695     static Promote toPromote(short int v) { return v; }
00696     static RealPromote toRealPromote(short int v) { return v; }
00697     static short int fromPromote(Promote v) {
00698         return detail::clamp_integer_to_signed<Promote, short int>(v, SHRT_MIN, SHRT_MAX);
00699     }
00700     static short int fromRealPromote(RealPromote v) {
00701         return detail::clamp_float_to_signed<RealPromote, short int>(v, SHRT_MIN, SHRT_MAX);
00702     }
00703 };
00704 
00705 template<>
00706 struct NumericTraits<short unsigned int>
00707 {
00708     typedef short unsigned int Type;
00709     typedef int Promote;
00710     typedef unsigned int UnsignedPromote;
00711     typedef double RealPromote;
00712     typedef std::complex<RealPromote> ComplexPromote;
00713     typedef Type ValueType;
00714 
00715     typedef VigraTrueType isIntegral;
00716     typedef VigraTrueType isScalar;
00717     typedef VigraFalseType isSigned;
00718     typedef VigraTrueType isOrdered;
00719     typedef VigraFalseType isComplex;
00720 
00721     static short unsigned int zero() { return 0; }
00722     static short unsigned int one() { return 1; }
00723     static short unsigned int nonZero() { return 1; }
00724     static short unsigned int min() { return 0; }
00725     static short unsigned int max() { return USHRT_MAX; }
00726     
00727 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
00728     enum { minConst = 0, maxConst = USHRT_MAX };
00729 #else
00730     static const short unsigned int minConst = 0;
00731     static const short unsigned int maxConst = USHRT_MAX;
00732 #endif
00733 
00734     static Promote toPromote(short unsigned int v) { return v; }
00735     static RealPromote toRealPromote(short unsigned int v) { return v; }
00736     static short unsigned int fromPromote(Promote v) {
00737         return detail::clamp_integer_to_unsigned<Promote, short unsigned int>(v, USHRT_MAX);
00738     }
00739     static short unsigned int fromRealPromote(RealPromote v) {
00740         return detail::clamp_float_to_unsigned<RealPromote, short unsigned int>(v, USHRT_MAX);
00741     }
00742 };
00743 
00744 template<>
00745 struct NumericTraits<int>
00746 {
00747     typedef int Type;
00748     typedef int Promote;
00749     typedef unsigned int UnsignedPromote;
00750     typedef double RealPromote;
00751     typedef std::complex<RealPromote> ComplexPromote;
00752     typedef Type ValueType;
00753 
00754     typedef VigraTrueType isIntegral;
00755     typedef VigraTrueType isScalar;
00756     typedef VigraTrueType isSigned;
00757     typedef VigraTrueType isOrdered;
00758     typedef VigraFalseType isComplex;
00759 
00760     static int zero() { return 0; }
00761     static int one() { return 1; }
00762     static int nonZero() { return 1; }
00763     static int min() { return INT_MIN; }
00764     static int max() { return INT_MAX; }
00765     
00766 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
00767     enum { minConst = INT_MIN, maxConst = INT_MAX };
00768 #else
00769     static const int minConst = INT_MIN;
00770     static const int maxConst = INT_MAX;
00771 #endif
00772 
00773     static Promote toPromote(int v) { return v; }
00774     static RealPromote toRealPromote(int v) { return v; }
00775     static int fromPromote(Promote v) { return v; }
00776     static int fromRealPromote(RealPromote v) {
00777         return detail::clamp_float_to_signed<RealPromote, int>(v, INT_MIN, INT_MAX);
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 detail::clamp_float_to_unsigned<RealPromote, unsigned int>(v, UINT_MAX);
00815     }
00816 };
00817 
00818 template<>
00819 struct NumericTraits<long>
00820 {
00821     typedef long Type;
00822     typedef long Promote;
00823     typedef unsigned long UnsignedPromote;
00824     typedef double RealPromote;
00825     typedef std::complex<RealPromote> ComplexPromote;
00826     typedef Type ValueType;
00827 
00828     typedef VigraTrueType isIntegral;
00829     typedef VigraTrueType isScalar;
00830     typedef VigraTrueType isSigned;
00831     typedef VigraTrueType isOrdered;
00832     typedef VigraFalseType isComplex;
00833     
00834     static long zero() { return 0; }
00835     static long one() { return 1; }
00836     static long nonZero() { return 1; }
00837     static long min() { return LONG_MIN; }
00838     static long max() { return LONG_MAX; }
00839     
00840 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
00841     enum { minConst = LONG_MIN, maxConst = LONG_MAX };
00842 #else
00843     static const long minConst = LONG_MIN;
00844     static const long maxConst = LONG_MAX;
00845 #endif
00846 
00847     static Promote toPromote(long v) { return v; }
00848     static RealPromote toRealPromote(long v) { return static_cast<RealPromote>(v); }
00849     static long fromPromote(Promote v) { return v; }
00850     static long fromRealPromote(RealPromote v) {
00851         return detail::clamp_float_to_signed<RealPromote, long>(v, LONG_MIN, LONG_MAX);
00852     }
00853 };
00854 
00855 template<>
00856 struct NumericTraits<unsigned long>
00857 {
00858     typedef unsigned long Type;
00859     typedef unsigned long Promote;
00860     typedef unsigned long UnsignedPromote;
00861     typedef double RealPromote;
00862     typedef std::complex<RealPromote> ComplexPromote;
00863     typedef Type ValueType;
00864 
00865     typedef VigraTrueType isIntegral;
00866     typedef VigraTrueType isScalar;
00867     typedef VigraFalseType isSigned;
00868     typedef VigraTrueType isOrdered;
00869     typedef VigraFalseType isComplex;
00870     
00871     static unsigned long zero() { return 0; }
00872     static unsigned long one() { return 1; }
00873     static unsigned long nonZero() { return 1; }
00874     static unsigned long min() { return 0; }
00875     static unsigned long max() { return ULONG_MAX; }
00876     
00877 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
00878     enum { minConst = 0, maxConst = ULONG_MAX };
00879 #else
00880     static const unsigned long minConst = 0;
00881     static const unsigned long maxConst = ULONG_MAX;
00882 #endif
00883 
00884     static Promote toPromote(unsigned long v) { return v; }
00885     static RealPromote toRealPromote(unsigned long v) { return static_cast<RealPromote>(v); }
00886     static unsigned long fromPromote(Promote v) { return v; }
00887     static unsigned long fromRealPromote(RealPromote v) {
00888         return detail::clamp_float_to_unsigned<RealPromote, unsigned long>(v, ULONG_MAX);
00889     }
00890 };
00891 
00892 #ifdef LLONG_MAX
00893 template<>
00894 struct NumericTraits<long long>
00895 {
00896     typedef long long Type;
00897     typedef long long Promote;
00898     typedef unsigned long long UnsignedPromote;
00899     typedef double RealPromote;
00900     typedef std::complex<RealPromote> ComplexPromote;
00901     typedef Type ValueType;
00902 
00903     typedef VigraTrueType isIntegral;
00904     typedef VigraTrueType isScalar;
00905     typedef VigraTrueType isSigned;
00906     typedef VigraTrueType isOrdered;
00907     typedef VigraFalseType isComplex;
00908     
00909     static long long zero() { return 0; }
00910     static long long one() { return 1; }
00911     static long long nonZero() { return 1; }
00912     static long long min() { return LLONG_MIN; }
00913     static long long max() { return LLONG_MAX; }
00914     
00915 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
00916     enum { minConst = LLONG_MIN, maxConst = LLONG_MAX };
00917 #else
00918     static const long long minConst = LLONG_MIN;
00919     static const long long maxConst = LLONG_MAX;
00920 #endif
00921 
00922     static Promote toPromote(long long v) { return v; }
00923     static RealPromote toRealPromote(long long v) { return (RealPromote)v; }
00924     static long long fromPromote(Promote v) { return v; }
00925     static long long fromRealPromote(RealPromote v) {
00926         return detail::clamp_float_to_signed<RealPromote, long long>(v, LLONG_MIN, LLONG_MAX);
00927     }
00928 };
00929 
00930 template<>
00931 struct NumericTraits<unsigned long long>
00932 {
00933     typedef unsigned long long Type;
00934     typedef unsigned long long Promote;
00935     typedef unsigned long long UnsignedPromote;
00936     typedef double RealPromote;
00937     typedef std::complex<RealPromote> ComplexPromote;
00938     typedef Type ValueType;
00939 
00940     typedef VigraTrueType isIntegral;
00941     typedef VigraTrueType isScalar;
00942     typedef VigraFalseType isSigned;
00943     typedef VigraTrueType isOrdered;
00944     typedef VigraFalseType isComplex;
00945     
00946     static unsigned long long zero() { return 0; }
00947     static unsigned long long one() { return 1; }
00948     static unsigned long long nonZero() { return 1; }
00949     static unsigned long long min() { return 0; }
00950     static unsigned long long max() { return ULLONG_MAX; }
00951     
00952 #ifdef NO_INLINE_STATIC_CONST_DEFINITION
00953     enum { minConst = 0, maxConst = ULLONG_MAX };
00954 #else
00955     static const unsigned long long minConst = 0;
00956     static const unsigned long long maxConst = ULLONG_MAX;
00957 #endif
00958 
00959     static Promote toPromote(unsigned long long v) { return v; }
00960     static RealPromote toRealPromote(unsigned long long v) { return (RealPromote)v; }
00961     static unsigned long long fromPromote(Promote v) { return v; }
00962     static unsigned long long fromRealPromote(RealPromote v) {
00963         return detail::clamp_float_to_unsigned<RealPromote, unsigned long long>(v, ULLONG_MAX);
00964     }
00965 };
00966 #endif // LLONG_MAX
00967 
00968 template<>
00969 struct NumericTraits<float>
00970 {
00971     typedef float Type;
00972     typedef float Promote;
00973     typedef float UnsignedPromote;
00974     typedef float RealPromote;
00975     typedef std::complex<RealPromote> ComplexPromote;
00976     typedef Type ValueType;
00977     
00978     typedef VigraFalseType isIntegral;
00979     typedef VigraTrueType isScalar;
00980     typedef VigraTrueType isSigned;
00981     typedef VigraTrueType isOrdered;
00982     typedef VigraFalseType isComplex;
00983     
00984     static float zero() { return 0.0; }
00985     static float one() { return 1.0; }
00986     static float nonZero() { return 1.0; }
00987     static float epsilon() { return FLT_EPSILON; }
00988     static float smallestPositive() { return FLT_MIN; }
00989     static float min() { return -FLT_MAX; }
00990     static float max() { return FLT_MAX; }
00991     
00992     static Promote toPromote(float v) { return v; }
00993     static RealPromote toRealPromote(float v) { return v; }
00994     static float fromPromote(Promote v) { return v; }
00995     static float fromRealPromote(RealPromote v) { return v; }
00996 };
00997 
00998 template<>
00999 struct NumericTraits<double>
01000 {
01001     typedef double Type;
01002     typedef double Promote;
01003     typedef double UnsignedPromote;
01004     typedef double RealPromote;
01005     typedef std::complex<RealPromote> ComplexPromote;
01006     typedef Type ValueType;
01007 
01008     typedef VigraFalseType isIntegral;
01009     typedef VigraTrueType isScalar;
01010     typedef VigraTrueType isSigned;
01011     typedef VigraTrueType isOrdered;
01012     typedef VigraFalseType isComplex;
01013     
01014     static double zero() { return 0.0; }
01015     static double one() { return 1.0; }
01016     static double nonZero() { return 1.0; }
01017     static double epsilon() { return DBL_EPSILON; }
01018     static double smallestPositive() { return DBL_MIN; }
01019     static double min() { return -DBL_MAX; }
01020     static double max() { return DBL_MAX; }
01021 
01022     static Promote toPromote(double v) { return v; }
01023     static RealPromote toRealPromote(double v) { return v; }
01024     static double fromPromote(Promote v) { return v; }
01025     static double fromRealPromote(RealPromote v) { return v; }
01026 };
01027 
01028 template<>
01029 struct NumericTraits<long double>
01030 {
01031     typedef long double Type;
01032     typedef long double Promote;
01033     typedef long double UnsignedPromote;
01034     typedef long double RealPromote;
01035     typedef std::complex<RealPromote> ComplexPromote;
01036     typedef Type ValueType;
01037 
01038     typedef VigraFalseType isIntegral;
01039     typedef VigraTrueType isScalar;
01040     typedef VigraTrueType isSigned;
01041     typedef VigraTrueType isOrdered;
01042     typedef VigraFalseType isComplex;
01043     
01044     static long double zero() { return 0.0; }
01045     static long double one() { return 1.0; }
01046     static long double nonZero() { return 1.0; }
01047     static long double epsilon() { return LDBL_EPSILON; }
01048     static long double smallestPositive() { return LDBL_MIN; }
01049     static long double min() { return -LDBL_MAX; }
01050     static long double max() { return LDBL_MAX; }
01051 
01052     static Promote toPromote(long double v) { return v; }
01053     static RealPromote toRealPromote(long double v) { return v; }
01054     static long double fromPromote(Promote v) { return v; }
01055     static long double fromRealPromote(RealPromote v) { return v; }
01056 };
01057 
01058 #ifndef NO_PARTIAL_TEMPLATE_SPECIALIZATION
01059 
01060 template<class T>
01061 struct NumericTraits<std::complex<T> >
01062 {
01063     typedef std::complex<T> Type;
01064     typedef std::complex<typename NumericTraits<T>::Promote> Promote;
01065     typedef std::complex<typename NumericTraits<T>::UnsignedPromote> UnsignedPromote;
01066     typedef std::complex<typename NumericTraits<T>::RealPromote> RealPromote;
01067     typedef std::complex<RealPromote> ComplexPromote;
01068     typedef T ValueType;
01069 
01070     typedef VigraFalseType isIntegral;
01071     typedef VigraFalseType isScalar;
01072     typedef typename NumericTraits<T>::isSigned isSigned;
01073     typedef VigraFalseType isOrdered;
01074     typedef VigraTrueType isComplex;
01075     
01076     static Type zero() { return Type(0.0); }
01077     static Type one() { return Type(1.0); }
01078     static Type nonZero() { return one(); }
01079     static Type epsilon() { return Type(NumericTraits<T>::epsilon()); }
01080     static Type smallestPositive() { return Type(NumericTraits<T>::smallestPositive()); }
01081 
01082     static Promote toPromote(Type const & v) { return v; }
01083     static Type fromPromote(Promote const & v) { return v; }
01084     static Type fromRealPromote(RealPromote v) { return Type(v); }
01085 };
01086 
01087 #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION
01088 
01089 /********************************************************/
01090 /*                                                      */
01091 /*                    SquareRootTraits                  */
01092 /*                                                      */
01093 /********************************************************/
01094 
01095 template<class T>
01096 struct SquareRootTraits
01097 {
01098     typedef T                                                    Type;
01099     typedef typename NumericTraits<T>::RealPromote               SquareRootResult;
01100     typedef typename NumericTraits<T>::RealPromote               SquareRootArgument;
01101 };
01102 
01103 
01104 /********************************************************/
01105 /*                                                      */
01106 /*                       NormTraits                     */
01107 /*                                                      */
01108 /********************************************************/
01109 
01110 struct Error_NormTraits_not_specialized_for_this_case { };
01111 
01112 template<class T>
01113 struct NormTraits
01114 {
01115     typedef T                                                Type;
01116     typedef Error_NormTraits_not_specialized_for_this_case   SquaredNormType;
01117     typedef Error_NormTraits_not_specialized_for_this_case   NormType;
01118 };
01119 
01120 #define VIGRA_DEFINE_NORM_TRAITS(T) \
01121     template <> struct NormTraits<T> { \
01122         typedef T Type; \
01123         typedef NumericTraits<T>::Promote SquaredNormType; \
01124         typedef T NormType; \
01125     };
01126 
01127 VIGRA_DEFINE_NORM_TRAITS(bool)
01128 VIGRA_DEFINE_NORM_TRAITS(signed char)
01129 VIGRA_DEFINE_NORM_TRAITS(unsigned char)
01130 VIGRA_DEFINE_NORM_TRAITS(short)
01131 VIGRA_DEFINE_NORM_TRAITS(unsigned short)
01132 VIGRA_DEFINE_NORM_TRAITS(int)
01133 VIGRA_DEFINE_NORM_TRAITS(unsigned int)
01134 VIGRA_DEFINE_NORM_TRAITS(long)
01135 VIGRA_DEFINE_NORM_TRAITS(unsigned long)
01136 VIGRA_DEFINE_NORM_TRAITS(float)
01137 VIGRA_DEFINE_NORM_TRAITS(double)
01138 VIGRA_DEFINE_NORM_TRAITS(long double)
01139 
01140 #ifdef LLONG_MAX
01141 VIGRA_DEFINE_NORM_TRAITS(long long)
01142 VIGRA_DEFINE_NORM_TRAITS(unsigned long long)
01143 #endif // LLONG_MAX
01144 
01145 #undef VIGRA_DEFINE_NORM_TRAITS
01146 
01147 #ifndef NO_PARTIAL_TEMPLATE_SPECIALIZATION
01148 
01149 template<class T>
01150 struct NormTraits<std::complex<T> >
01151 {
01152     typedef std::complex<T>                                              Type;
01153     typedef typename NormTraits<T>::SquaredNormType                      SquaredNormType;
01154     typedef typename SquareRootTraits<SquaredNormType>::SquareRootResult NormType;
01155 };
01156 
01157 #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION
01158 
01159 /********************************************************/
01160 /*                                                      */
01161 /*                      PromoteTraits                   */
01162 /*                                                      */
01163 /********************************************************/
01164 
01165 namespace detail {
01166 
01167 template <class T, class U>
01168 struct PromoteType
01169 {
01170     static T & t();
01171     static U & u();
01172     // let C++ figure out the promote type by adding a T and an U
01173     typedef typename SizeToType<sizeof(*typeToSize(t() + u()))>::result Promote;
01174     static Promote toPromote(T t) { return Promote(t); }
01175     static Promote toPromote(U u) { return Promote(u); }
01176 };
01177 
01178 
01179 template <class T>
01180 struct PromoteType<T, T>
01181 {
01182     static T & t();
01183     // let C++ figure out the promote type by adding two Ts
01184     typedef typename SizeToType<sizeof(*typeToSize(t() + t()))>::result Promote;
01185     static Promote toPromote(T t) { return Promote(t); }
01186 };
01187 
01188 } // namespace detail
01189 
01190 struct Error_PromoteTraits_not_specialized_for_this_case { };
01191 
01192 template<class A, class B>
01193 struct PromoteTraits
01194 {
01195     typedef Error_PromoteTraits_not_specialized_for_this_case Promote;
01196 };
01197 
01198 #include "promote_traits.hxx"
01199 
01200 #ifndef NO_PARTIAL_TEMPLATE_SPECIALIZATION
01201 
01202 template <class T>
01203 struct PromoteTraits<std::complex<T>, std::complex<T> >
01204 {
01205     typedef std::complex<typename PromoteTraits<T, T>::Promote> Promote;
01206     static Promote toPromote(std::complex<T> const & v) { return v; }
01207 };
01208 
01209 template <class T1, class T2>
01210 struct PromoteTraits<std::complex<T1>, std::complex<T2> >
01211 {
01212     typedef std::complex<typename PromoteTraits<T1, T2>::Promote> Promote;
01213     static Promote toPromote(std::complex<T1> const & v) { return v; }
01214     static Promote toPromote(std::complex<T2> const & v) { return v; }
01215 };
01216 
01217 template <class T1, class T2>
01218 struct PromoteTraits<std::complex<T1>, T2 >
01219 {
01220     typedef std::complex<typename PromoteTraits<T1, T2>::Promote> Promote;
01221     static Promote toPromote(std::complex<T1> const & v) { return v; }
01222     static Promote toPromote(T2 const & v) { return Promote(v); }
01223 };
01224 
01225 template <class T1, class T2>
01226 struct PromoteTraits<T1, std::complex<T2> >
01227 {
01228     typedef std::complex<typename PromoteTraits<T1, T2>::Promote> Promote;
01229     static Promote toPromote(T1 const & v) { return Promote(v); }
01230     static Promote toPromote(std::complex<T2> const & v) { return v; }
01231 };
01232 
01233 #endif
01234 
01235 namespace detail {
01236 
01237 template <class T>
01238 struct RequiresExplicitCast {
01239     template <class U>
01240     static U const & cast(U const & v)
01241         { return v; }
01242 };
01243 
01244 #if !defined(_MSC_VER) || _MSC_VER >= 1300
01245 #  define VIGRA_SPECIALIZED_CAST(type) \
01246     template <> \
01247     struct RequiresExplicitCast<type> { \
01248         static type cast(float v) \
01249             { return NumericTraits<type>::fromRealPromote(v); } \
01250         static type cast(double v) \
01251             { return NumericTraits<type>::fromRealPromote(v); } \
01252         static type cast(type v) \
01253             { return v; } \
01254         template <class U> \
01255         static type cast(U v) \
01256             { return static_cast<type>(v); } \
01257  \
01258     };
01259 #else
01260 #  define VIGRA_SPECIALIZED_CAST(type) \
01261     template <> \
01262     struct RequiresExplicitCast<type> { \
01263         static type cast(float v) \
01264             { return NumericTraits<type>::fromRealPromote(v); } \
01265         static type cast(double v) \
01266             { return NumericTraits<type>::fromRealPromote(v); } \
01267         static type cast(signed char v) \
01268             { return v; } \
01269         static type cast(unsigned char v) \
01270             { return v; } \
01271         static type cast(short v) \
01272             { return v; } \
01273         static type cast(unsigned short v) \
01274             { return v; } \
01275         static type cast(int v) \
01276             { return v; } \
01277         static type cast(unsigned int v) \
01278             { return v; } \
01279         static type cast(long v) \
01280             { return v; } \
01281         static type cast(unsigned long v) \
01282             { return v; } \
01283     };
01284 #endif
01285 
01286 
01287 VIGRA_SPECIALIZED_CAST(signed char)
01288 VIGRA_SPECIALIZED_CAST(unsigned char)
01289 VIGRA_SPECIALIZED_CAST(short)
01290 VIGRA_SPECIALIZED_CAST(unsigned short)
01291 VIGRA_SPECIALIZED_CAST(int)
01292 VIGRA_SPECIALIZED_CAST(unsigned int)
01293 VIGRA_SPECIALIZED_CAST(long)
01294 VIGRA_SPECIALIZED_CAST(unsigned long)
01295 
01296 template <>
01297 struct RequiresExplicitCast<bool> {
01298     template <class U>
01299     static bool cast(U v)
01300     { return v == NumericTraits<U>::zero()
01301                 ? false
01302                 : true; }
01303 };
01304 
01305 template <>
01306 struct RequiresExplicitCast<float> {
01307     static float cast(int v)
01308         { return (float)v; }
01309 
01310     static float cast(unsigned int v)
01311         { return (float)v; }
01312 
01313     static float cast(long v)
01314         { return (float)v; }
01315 
01316     static float cast(unsigned long v)
01317         { return (float)v; }
01318 
01319     static float cast(long long v)
01320         { return (float)v; }
01321 
01322     static float cast(unsigned long long v)
01323         { return (float)v; }
01324 
01325     static float cast(double v)
01326         { return (float)v; }
01327 
01328     static float cast(long double v)
01329         { return (float)v; }
01330 
01331     template <class U>
01332     static U cast(U v)
01333         { return v; }
01334 };
01335 
01336 template <>
01337 struct RequiresExplicitCast<double> {
01338     static double cast(Int64 v)
01339         { return (double)v; }
01340 
01341     static double cast(UInt64 v)
01342         { return (double)v; }
01343 
01344     template <class U>
01345     static U cast(U v)
01346         { return v; }
01347 };
01348 
01349 #undef VIGRA_SPECIALIZED_CAST
01350 
01351 } // namespace detail
01352 
01353 
01354 
01355 } // namespace vigra
01356 
01357 #endif // VIGRA_NUMERICTRAITS_HXX
01358 

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

html generated using doxygen and Python
vigra 1.9.0 (Tue Nov 6 2012)