[ 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> <em>Unary traits for promotion, conversion, creation of arithmetic objects</em> 00061 <LI> \ref PromoteTraits 00062 <BR> <em>Binary traits for promotion of arithmetic objects</em> 00063 <LI> \ref SquareRootTraits 00064 <BR> <em>Unary traits for the calculation of the square root of arithmetic objects</em> 00065 <LI> \ref NormTraits 00066 <BR> <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) |
html generated using doxygen and Python
|