vigra - vigra/numerictraits.hxx Source File

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

vigra/numerictraits.hxx |

    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)