Scopira 20080306

limits.h

00001 
00002 /*
00003  *  Copyright (c) 2002    National Research Council
00004  *
00005  *  All rights reserved.
00006  *
00007  *  This material is confidential and proprietary information of
00008  *  National Research Council Canada ("Confidential Information").
00009  *  This Confidential Information may only be used and reproduced
00010  *  in accordance with the terms of the license agreement.
00011  *
00012  */
00013 
00014 #ifndef __INCLUDED_SCOPIRA_TOOL_LIMITS_H__
00015 #define __INCLUDED_SCOPIRA_TOOL_LIMITS_H__
00016 
00017 #if defined(__GNUC__) && (__GNUC__ < 3)
00018 
00019 //
00020 // taken from Boost, because <limits> is missin on gnu c++.
00021 //
00022 
00023 #include <limits.h>
00024 #include <float.h>
00025 
00026 #if defined(__sparc) || defined(__sparc__) || defined(__powerpc__) || defined(__ppc__) || defined(__hppa) || defined(_MIPSEB)
00027 #define BOOST_BIG_ENDIAN
00028 #elif defined(__i386__)
00029 #define BOOST_LITTLE_ENDIAN
00030 #else
00031 #error The file boost/detail/limits.hpp needs to be set up for your CPU type.
00032 #endif
00033 
00034 namespace std {
00035 
00036 enum float_round_style {
00037   round_indeterminate       = -1,
00038   round_toward_zero         =  0,
00039   round_to_nearest          =  1,
00040   round_toward_infinity     =  2,
00041   round_toward_neg_infinity =  3
00042 };
00043 
00044 enum float_denorm_style {
00045   denorm_indeterminate = -1,
00046   denorm_absent        =  0,
00047   denorm_present       =  1
00048 };
00049 
00050 // The C++ standard (section 18.2.1) requires that some of the members of
00051 // numeric_limits be static const data members that are given constant-
00052 // initializers within the class declaration.  On compilers where the
00053 // BOOST_NO_INCLASS_MEMBER_INITIALIZATION macro is defined, it is impossible to write
00054 // a standard-conforming numeric_limits class.
00055 //
00056 // There are two possible workarounds: either initialize the data
00057 // members outside the class, or change them from data members to
00058 // enums.  Neither workaround is satisfactory: the former makes it
00059 // impossible to use the data members in constant-expressions, and the
00060 // latter means they have the wrong type and that it is impossible to
00061 // take their addresses.  We choose the former workaround.
00062 
00063 #ifdef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
00064 # define BOOST_STL_DECLARE_LIMITS_MEMBER(__mem_type, __mem_name, __mem_value) \
00065   enum { __mem_name = __mem_value }
00066 #else /* BOOST_NO_INCLASS_MEMBER_INITIALIZATION */
00067 # define BOOST_STL_DECLARE_LIMITS_MEMBER(__mem_type, __mem_name, __mem_value) \
00068   static const __mem_type __mem_name = __mem_value
00069 #endif /* BOOST_NO_INCLASS_MEMBER_INITIALIZATION */
00070 
00071 // Base class for all specializations of numeric_limits.
00072 
00073 template <class __number>
00074 class _Numeric_limits_base {
00075 public:
00076   BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_specialized, false);
00077 
00078   static __number min() throw() { return __number(); }
00079   static __number max() throw() { return __number(); }
00080 
00081   BOOST_STL_DECLARE_LIMITS_MEMBER(int, digits,   0);
00082   BOOST_STL_DECLARE_LIMITS_MEMBER(int, digits10, 0);
00083 
00084   BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_signed,  false);
00085   BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_integer, false);
00086   BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_exact,   false);
00087 
00088   BOOST_STL_DECLARE_LIMITS_MEMBER(int, radix, 0);
00089 
00090   static __number epsilon() throw()     { return __number(); }
00091   static __number round_error() throw() { return __number(); }
00092 
00093   BOOST_STL_DECLARE_LIMITS_MEMBER(int, min_exponent,   0);
00094   BOOST_STL_DECLARE_LIMITS_MEMBER(int, min_exponent10, 0);
00095   BOOST_STL_DECLARE_LIMITS_MEMBER(int, max_exponent,   0);
00096   BOOST_STL_DECLARE_LIMITS_MEMBER(int, max_exponent10, 0);
00097 
00098   BOOST_STL_DECLARE_LIMITS_MEMBER(bool, has_infinity,      false);
00099   BOOST_STL_DECLARE_LIMITS_MEMBER(bool, has_quiet_NaN,     false);
00100   BOOST_STL_DECLARE_LIMITS_MEMBER(bool, has_signaling_NaN, false);
00101   BOOST_STL_DECLARE_LIMITS_MEMBER(float_denorm_style,
00102                               has_denorm,
00103                               denorm_absent);
00104   BOOST_STL_DECLARE_LIMITS_MEMBER(bool, has_denorm_loss,   false);
00105 
00106   static __number infinity() throw()      { return __number(); }
00107   static __number quiet_NaN() throw()     { return __number(); }
00108   static __number signaling_NaN() throw() { return __number(); }
00109   static __number denorm_min() throw()    { return __number(); }
00110 
00111   BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_iec559,  false);
00112   BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_bounded, false);
00113   BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_modulo,  false);
00114 
00115   BOOST_STL_DECLARE_LIMITS_MEMBER(bool, traps,            false);
00116   BOOST_STL_DECLARE_LIMITS_MEMBER(bool, tinyness_before,  false);
00117   BOOST_STL_DECLARE_LIMITS_MEMBER(float_round_style,
00118                               round_style,
00119                               round_toward_zero);
00120 };
00121 
00122 // Base class for integers.
00123 
00124 template <class _Int,
00125           _Int __imin,
00126           _Int __imax,
00127           int __idigits = -1>
00128 class _Integer_limits : public _Numeric_limits_base<_Int> 
00129 {
00130 public:
00131   BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_specialized, true);
00132 
00133   static _Int min() throw() { return __imin; }
00134   static _Int max() throw() { return __imax; }
00135 
00136   BOOST_STL_DECLARE_LIMITS_MEMBER(int,
00137                               digits,
00138                               (__idigits < 0) ? (int)(sizeof(_Int) * CHAR_BIT)
00139                                                    - (__imin == 0 ? 0 : 1) 
00140                                               : __idigits);
00141   BOOST_STL_DECLARE_LIMITS_MEMBER(int, digits10, (digits * 301) / 1000); 
00142                                 // log 2 = 0.301029995664...
00143 
00144   BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_signed,  __imin != 0);
00145   BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_integer, true);
00146   BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_exact,   true);
00147   BOOST_STL_DECLARE_LIMITS_MEMBER(int,  radix,      2);
00148 
00149   BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_bounded, true);
00150   BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_modulo, true);
00151 };
00152 
00153 #if defined(BOOST_BIG_ENDIAN)
00154 
00155  template<class Number, unsigned int Word>
00156  struct float_helper{
00157   static Number get_word() throw() {
00158     // sizeof(long double) == 16
00159     const unsigned int _S_word[4] = { Word, 0, 0, 0 };
00160     return *reinterpret_cast<const Number*>(&_S_word);
00161   } 
00162 };
00163 
00164 #else
00165 
00166  template<class Number, unsigned int Word>
00167  struct float_helper{
00168   static Number get_word() throw() {
00169     // sizeof(long double) == 12, but only 10 bytes significant
00170     const unsigned int _S_word[4] = { 0, 0, 0, Word };
00171     return *reinterpret_cast<const Number*>(
00172         reinterpret_cast<const char *>(&_S_word)+16-
00173                 (sizeof(Number) == 12 ? 10 : sizeof(Number)));
00174   } 
00175 };
00176 
00177 #endif
00178 
00179 // Base class for floating-point numbers.
00180 template <class __number,
00181          int __Digits, int __Digits10,
00182          int __MinExp, int __MaxExp,
00183          int __MinExp10, int __MaxExp10,
00184          unsigned int __InfinityWord,
00185          unsigned int __QNaNWord, unsigned int __SNaNWord,
00186          bool __IsIEC559,
00187          float_round_style __RoundStyle>
00188 class _Floating_limits : public _Numeric_limits_base<__number>
00189 {
00190 public:
00191   BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_specialized, true);
00192 
00193   BOOST_STL_DECLARE_LIMITS_MEMBER(int, digits,   __Digits);
00194   BOOST_STL_DECLARE_LIMITS_MEMBER(int, digits10, __Digits10);
00195 
00196   BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_signed, true);
00197 
00198   BOOST_STL_DECLARE_LIMITS_MEMBER(int, radix, 2);
00199 
00200   BOOST_STL_DECLARE_LIMITS_MEMBER(int, min_exponent,   __MinExp);
00201   BOOST_STL_DECLARE_LIMITS_MEMBER(int, max_exponent,   __MaxExp);
00202   BOOST_STL_DECLARE_LIMITS_MEMBER(int, min_exponent10, __MinExp10);
00203   BOOST_STL_DECLARE_LIMITS_MEMBER(int, max_exponent10, __MaxExp10);
00204 
00205   BOOST_STL_DECLARE_LIMITS_MEMBER(bool, has_infinity,      true);
00206   BOOST_STL_DECLARE_LIMITS_MEMBER(bool, has_quiet_NaN,     true);
00207   BOOST_STL_DECLARE_LIMITS_MEMBER(bool, has_signaling_NaN, true);
00208   BOOST_STL_DECLARE_LIMITS_MEMBER(float_denorm_style,
00209                               has_denorm,
00210                               denorm_indeterminate);
00211   BOOST_STL_DECLARE_LIMITS_MEMBER(bool, has_denorm_loss,   false);
00212 
00213  
00214   static __number infinity() throw() {
00215     return float_helper<__number, __InfinityWord>::get_word();
00216   }
00217   static __number quiet_NaN() throw() {
00218     return float_helper<__number,__QNaNWord>::get_word();
00219   }
00220   static __number signaling_NaN() throw() {
00221     return float_helper<__number,__SNaNWord>::get_word();
00222   }
00223 
00224   BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_iec559,       __IsIEC559);
00225   BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_bounded,      true);
00226   BOOST_STL_DECLARE_LIMITS_MEMBER(bool, traps,           false /* was: true */ );
00227   BOOST_STL_DECLARE_LIMITS_MEMBER(bool, tinyness_before, false);
00228 
00229   BOOST_STL_DECLARE_LIMITS_MEMBER(float_round_style, round_style, __RoundStyle);
00230 };
00231 
00232 // Class numeric_limits
00233 
00234 // The unspecialized class.
00235 
00236 template<class T> 
00237 class numeric_limits : public _Numeric_limits_base<T> {};
00238 
00239 // Specializations for all built-in integral types.
00240 
00241 template<>
00242 class numeric_limits<bool>
00243   : public _Integer_limits<bool, false, true, 0>
00244 {};
00245 
00246 template<>
00247 class numeric_limits<char>
00248   : public _Integer_limits<char, CHAR_MIN, CHAR_MAX>
00249 {};
00250 
00251 template<>
00252 class numeric_limits<signed char>
00253   : public _Integer_limits<signed char, SCHAR_MIN, SCHAR_MAX>
00254 {};
00255 
00256 template<>
00257 class numeric_limits<unsigned char>
00258   : public _Integer_limits<unsigned char, 0, UCHAR_MAX>
00259 {};
00260 
00261 #ifndef BOOST_NO_INTRINSIC_WCHAR_T
00262 template<>
00263 class numeric_limits<wchar_t>
00264 #if !defined(WCHAR_MAX) || !defined(WCHAR_MIN)
00265 #if defined(_WIN32) || defined(__CYGWIN__)
00266   : public _Integer_limits<wchar_t, 0, USHRT_MAX>
00267 #elif defined(__hppa)
00268 // wchar_t has "unsigned int" as the underlying type
00269   : public _Integer_limits<wchar_t, 0, UINT_MAX>
00270 #else
00271 // assume that wchar_t has "int" as the underlying type
00272   : public _Integer_limits<wchar_t, INT_MIN, INT_MAX>
00273 #endif
00274 #else
00275 // we have WCHAR_MIN and WCHAR_MAX defined, so use it
00276   : public _Integer_limits<wchar_t, WCHAR_MIN, WCHAR_MAX>
00277 #endif
00278 {};
00279 #endif
00280 
00281 template<>
00282 class numeric_limits<short>
00283   : public _Integer_limits<short, SHRT_MIN, SHRT_MAX>
00284 {};
00285 
00286 template<>
00287 class numeric_limits<unsigned short>
00288   : public _Integer_limits<unsigned short, 0, USHRT_MAX>
00289 {};
00290 
00291 template<>
00292 class numeric_limits<int>
00293   : public _Integer_limits<int, INT_MIN, INT_MAX>
00294 {};
00295 
00296 template<>
00297 class numeric_limits<unsigned int>
00298   : public _Integer_limits<unsigned int, 0, UINT_MAX>
00299 {};
00300 
00301 template<>
00302 class numeric_limits<long>
00303   : public _Integer_limits<long, LONG_MIN, LONG_MAX>
00304 {};
00305 
00306 template<>
00307 class numeric_limits<unsigned long>
00308   : public _Integer_limits<unsigned long, 0, ULONG_MAX>
00309 {};
00310 
00311 #ifdef __GNUC__
00312 
00313 // Some compilers have long long, but don't define the
00314 // LONGLONG_MIN and LONGLONG_MAX macros in limits.h.  This
00315 // assumes that long long is 64 bits.
00316 #if !defined(LONGLONG_MIN) && !defined(LONGLONG_MAX) \
00317                            && !defined(ULONGLONG_MAX)
00318 
00319 #define ULONGLONG_MAX 0xffffffffffffffffLLU
00320 #define LONGLONG_MAX 0x7fffffffffffffffLL
00321 #define LONGLONG_MIN (-LONGLONG_MAX - 1)
00322 
00323 #endif
00324 
00325 template<>
00326 class numeric_limits<long long>
00327   : public _Integer_limits<long long, LONGLONG_MIN, LONGLONG_MAX>
00328 {};
00329 
00330 template<>
00331 class numeric_limits<unsigned long long>
00332   : public _Integer_limits<unsigned long long, 0, ULONGLONG_MAX>
00333 {};
00334 
00335 #endif /* __GNUC__ */
00336 
00337 // Specializations for all built-in floating-point type.
00338 
00339 template<> class numeric_limits<float>
00340   : public _Floating_limits<float, 
00341                             FLT_MANT_DIG,   // Binary digits of precision
00342                             FLT_DIG,        // Decimal digits of precision
00343                             FLT_MIN_EXP,    // Minimum exponent
00344                             FLT_MAX_EXP,    // Maximum exponent
00345                             FLT_MIN_10_EXP, // Minimum base 10 exponent
00346                             FLT_MAX_10_EXP, // Maximum base 10 exponent
00347 #if defined(BOOST_BIG_ENDIAN)
00348                             0x7f80 << (sizeof(int)*CHAR_BIT-16),    // Last word of +infinity
00349                             0x7f81 << (sizeof(int)*CHAR_BIT-16),    // Last word of quiet NaN
00350                             0x7fc1 << (sizeof(int)*CHAR_BIT-16),    // Last word of signaling NaN
00351 #else
00352                             0x7f800000u,    // Last word of +infinity
00353                             0x7f810000u,    // Last word of quiet NaN
00354                             0x7fc10000u,    // Last word of signaling NaN
00355 #endif
00356                             true,           // conforms to iec559
00357                             round_to_nearest>
00358 {
00359 public:
00360   static float min() throw() { return FLT_MIN; }
00361   static float denorm_min() throw() { return FLT_MIN; }
00362   static float max() throw() { return FLT_MAX; }
00363   static float epsilon() throw() { return FLT_EPSILON; }
00364   static float round_error() throw() { return 0.5f; } // Units: ulps.
00365 };
00366 
00367 template<> class numeric_limits<double>
00368   : public _Floating_limits<double, 
00369                             DBL_MANT_DIG,   // Binary digits of precision
00370                             DBL_DIG,        // Decimal digits of precision
00371                             DBL_MIN_EXP,    // Minimum exponent
00372                             DBL_MAX_EXP,    // Maximum exponent
00373                             DBL_MIN_10_EXP, // Minimum base 10 exponent
00374                             DBL_MAX_10_EXP, // Maximum base 10 exponent
00375 #if defined(BOOST_BIG_ENDIAN)
00376                             0x7ff0 << (sizeof(int)*CHAR_BIT-16),    // Last word of +infinity
00377                             0x7ff1 << (sizeof(int)*CHAR_BIT-16),    // Last word of quiet NaN
00378                             0x7ff9 << (sizeof(int)*CHAR_BIT-16),    // Last word of signaling NaN
00379 #else
00380                             0x7ff00000u,    // Last word of +infinity
00381                             0x7ff10000u,    // Last word of quiet NaN
00382                             0x7ff90000u,    // Last word of signaling NaN
00383 #endif
00384                             true,           // conforms to iec559
00385                             round_to_nearest>
00386 {
00387 public:
00388   static double min() throw() { return DBL_MIN; }
00389   static double denorm_min() throw() { return DBL_MIN; }
00390   static double max() throw() { return DBL_MAX; }
00391   static double epsilon() throw() { return DBL_EPSILON; }
00392   static double round_error() throw() { return 0.5; } // Units: ulps.
00393 };
00394 
00395 template<> class numeric_limits<long double>
00396   : public _Floating_limits<long double, 
00397                             LDBL_MANT_DIG,  // Binary digits of precision
00398                             LDBL_DIG,       // Decimal digits of precision
00399                             LDBL_MIN_EXP,   // Minimum exponent
00400                             LDBL_MAX_EXP,   // Maximum exponent
00401                             LDBL_MIN_10_EXP,// Minimum base 10 exponent
00402                             LDBL_MAX_10_EXP,// Maximum base 10 exponent
00403 #if defined(BOOST_BIG_ENDIAN)
00404                             0x7ff0 << (sizeof(int)*CHAR_BIT-16),    // Last word of +infinity
00405                             0x7ff1 << (sizeof(int)*CHAR_BIT-16),    // Last word of quiet NaN
00406                             0x7ff9 << (sizeof(int)*CHAR_BIT-16),    // Last word of signaling NaN
00407 #else
00408                             0x7fff8000u,    // Last word of +infinity
00409                             0x7fffc000u,    // Last word of quiet NaN
00410                             0x7fff9000u,    // Last word of signaling NaN
00411 #endif
00412                             false,          // Doesn't conform to iec559
00413                             round_to_nearest>
00414 {
00415 public:
00416   static long double min() throw() { return LDBL_MIN; }
00417   static long double denorm_min() throw() { return LDBL_MIN; }
00418   static long double max() throw() { return LDBL_MAX; }
00419   static long double epsilon() throw() { return LDBL_EPSILON; }
00420   static long double round_error() throw() { return 4; } // Units: ulps.
00421 };
00422 
00423 } // namespace std
00424 
00425 #else
00426 #include <limits>
00427 #endif //__GNUC__
00428 
00429 #endif
00430