1 // Copyright 2001 John Maddock 2 // Distributed under the Boost Software License, Version 1.0. (See accompany- 3 // ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 4 5 /* 6 * Copyright (c) 1997 7 * Silicon Graphics Computer Systems, Inc. 8 * 9 * Permission to use, copy, modify, distribute and sell this software 10 * and its documentation for any purpose is hereby granted without fee, 11 * provided that the above copyright notice appear in all copies and 12 * that both that copyright notice and this permission notice appear 13 * in supporting documentation. Silicon Graphics makes no 14 * representations about the suitability of this software for any 15 * purpose. It is provided "as is" without express or implied warranty. 16 */ 17 18 /* NOTE: This is not portable code. Parts of numeric_limits<> are 19 * inherently machine-dependent, and this file is written for the MIPS 20 * architecture and the SGI MIPSpro C++ compiler. Parts of it (in 21 * particular, some of the characteristics of floating-point types) 22 * are almost certainly incorrect for any other platform. 23 */ 24 25 /* The above comment is almost certainly out of date. This file works 26 * on systems other than SGI MIPSpro C++ now. 27 */ 28 29 /* 30 * Revision history: 31 * 21 Sep 2001: 32 * Only include <cwchar> if BOOST_NO_CWCHAR is defined. (Darin Adler) 33 * 10 Aug 2001: 34 * Added MIPS (big endian) to the big endian family. (Jens Maurer) 35 * 13 Apr 2001: 36 * Added powerpc to the big endian family. (Jeremy Siek) 37 * 5 Apr 2001: 38 * Added sparc (big endian) processor support (John Maddock). 39 * Initial sub: 40 * Modified by Jens Maurer for gcc 2.95 on x86. 41 */ 42 43 #ifndef BOOST_SGI_CPP_LIMITS 44 #define BOOST_SGI_CPP_LIMITS 45 46 #include <climits> 47 #include <cfloat> 48 #include <boost/config.hpp> 49 #include <boost/detail/endian.hpp> 50 51 #ifndef BOOST_NO_CWCHAR 52 #include <cwchar> // for WCHAR_MIN and WCHAR_MAX 53 #endif 54 55 namespace std { 56 57 enum float_round_style { 58 round_indeterminate = -1, 59 round_toward_zero = 0, 60 round_to_nearest = 1, 61 round_toward_infinity = 2, 62 round_toward_neg_infinity = 3 63 }; 64 65 enum float_denorm_style { 66 denorm_indeterminate = -1, 67 denorm_absent = 0, 68 denorm_present = 1 69 }; 70 71 // The C++ standard (section 18.2.1) requires that some of the members of 72 // numeric_limits be static const data members that are given constant- 73 // initializers within the class declaration. On compilers where the 74 // BOOST_NO_INCLASS_MEMBER_INITIALIZATION macro is defined, it is impossible to write 75 // a standard-conforming numeric_limits class. 76 // 77 // There are two possible workarounds: either initialize the data 78 // members outside the class, or change them from data members to 79 // enums. Neither workaround is satisfactory: the former makes it 80 // impossible to use the data members in constant-expressions, and the 81 // latter means they have the wrong type and that it is impossible to 82 // take their addresses. We choose the former workaround. 83 84 #ifdef BOOST_NO_INCLASS_MEMBER_INITIALIZATION 85 # define BOOST_STL_DECLARE_LIMITS_MEMBER(__mem_type, __mem_name, __mem_value) \ 86 enum { __mem_name = __mem_value } 87 #else /* BOOST_NO_INCLASS_MEMBER_INITIALIZATION */ 88 # define BOOST_STL_DECLARE_LIMITS_MEMBER(__mem_type, __mem_name, __mem_value) \ 89 static const __mem_type __mem_name = __mem_value 90 #endif /* BOOST_NO_INCLASS_MEMBER_INITIALIZATION */ 91 92 // Base class for all specializations of numeric_limits. 93 template <class __number> 94 class _Numeric_limits_base { 95 public: 96 BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_specialized, false); 97 BOOST_PREVENT_MACRO_SUBSTITUTION()98 static __number min BOOST_PREVENT_MACRO_SUBSTITUTION () throw() { return __number(); } BOOST_PREVENT_MACRO_SUBSTITUTION()99 static __number max BOOST_PREVENT_MACRO_SUBSTITUTION () throw() { return __number(); } 100 101 BOOST_STL_DECLARE_LIMITS_MEMBER(int, digits, 0); 102 BOOST_STL_DECLARE_LIMITS_MEMBER(int, digits10, 0); 103 104 BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_signed, false); 105 BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_integer, false); 106 BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_exact, false); 107 108 BOOST_STL_DECLARE_LIMITS_MEMBER(int, radix, 0); 109 epsilon()110 static __number epsilon() throw() { return __number(); } round_error()111 static __number round_error() throw() { return __number(); } 112 113 BOOST_STL_DECLARE_LIMITS_MEMBER(int, min_exponent, 0); 114 BOOST_STL_DECLARE_LIMITS_MEMBER(int, min_exponent10, 0); 115 BOOST_STL_DECLARE_LIMITS_MEMBER(int, max_exponent, 0); 116 BOOST_STL_DECLARE_LIMITS_MEMBER(int, max_exponent10, 0); 117 118 BOOST_STL_DECLARE_LIMITS_MEMBER(bool, has_infinity, false); 119 BOOST_STL_DECLARE_LIMITS_MEMBER(bool, has_quiet_NaN, false); 120 BOOST_STL_DECLARE_LIMITS_MEMBER(bool, has_signaling_NaN, false); 121 BOOST_STL_DECLARE_LIMITS_MEMBER(float_denorm_style, 122 has_denorm, 123 denorm_absent); 124 BOOST_STL_DECLARE_LIMITS_MEMBER(bool, has_denorm_loss, false); 125 infinity()126 static __number infinity() throw() { return __number(); } quiet_NaN()127 static __number quiet_NaN() throw() { return __number(); } signaling_NaN()128 static __number signaling_NaN() throw() { return __number(); } denorm_min()129 static __number denorm_min() throw() { return __number(); } 130 131 BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_iec559, false); 132 BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_bounded, false); 133 BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_modulo, false); 134 135 BOOST_STL_DECLARE_LIMITS_MEMBER(bool, traps, false); 136 BOOST_STL_DECLARE_LIMITS_MEMBER(bool, tinyness_before, false); 137 BOOST_STL_DECLARE_LIMITS_MEMBER(float_round_style, 138 round_style, 139 round_toward_zero); 140 }; 141 142 // Base class for integers. 143 144 template <class _Int, 145 _Int __imin, 146 _Int __imax, 147 int __idigits = -1> 148 class _Integer_limits : public _Numeric_limits_base<_Int> 149 { 150 public: 151 BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_specialized, true); 152 BOOST_PREVENT_MACRO_SUBSTITUTION()153 static _Int min BOOST_PREVENT_MACRO_SUBSTITUTION () throw() { return __imin; } BOOST_PREVENT_MACRO_SUBSTITUTION()154 static _Int max BOOST_PREVENT_MACRO_SUBSTITUTION () throw() { return __imax; } 155 156 BOOST_STL_DECLARE_LIMITS_MEMBER(int, 157 digits, 158 (__idigits < 0) ? (int)(sizeof(_Int) * CHAR_BIT) 159 - (__imin == 0 ? 0 : 1) 160 : __idigits); 161 BOOST_STL_DECLARE_LIMITS_MEMBER(int, digits10, (digits * 301) / 1000); 162 // log 2 = 0.301029995664... 163 164 BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_signed, __imin != 0); 165 BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_integer, true); 166 BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_exact, true); 167 BOOST_STL_DECLARE_LIMITS_MEMBER(int, radix, 2); 168 169 BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_bounded, true); 170 BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_modulo, true); 171 }; 172 173 #if defined(BOOST_BIG_ENDIAN) 174 175 template<class Number, unsigned int Word> 176 struct float_helper{ get_wordstd::float_helper177 static Number get_word() throw() { 178 // sizeof(long double) == 16 179 const unsigned int _S_word[4] = { Word, 0, 0, 0 }; 180 return *reinterpret_cast<const Number*>(&_S_word); 181 } 182 }; 183 184 #else 185 186 template<class Number, unsigned int Word> 187 struct float_helper{ get_wordstd::float_helper188 static Number get_word() throw() { 189 // sizeof(long double) == 12, but only 10 bytes significant 190 const unsigned int _S_word[4] = { 0, 0, 0, Word }; 191 return *reinterpret_cast<const Number*>( 192 reinterpret_cast<const char *>(&_S_word)+16- 193 (sizeof(Number) == 12 ? 10 : sizeof(Number))); 194 } 195 }; 196 197 #endif 198 199 // Base class for floating-point numbers. 200 template <class __number, 201 int __Digits, int __Digits10, 202 int __MinExp, int __MaxExp, 203 int __MinExp10, int __MaxExp10, 204 unsigned int __InfinityWord, 205 unsigned int __QNaNWord, unsigned int __SNaNWord, 206 bool __IsIEC559, 207 float_round_style __RoundStyle> 208 class _Floating_limits : public _Numeric_limits_base<__number> 209 { 210 public: 211 BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_specialized, true); 212 213 BOOST_STL_DECLARE_LIMITS_MEMBER(int, digits, __Digits); 214 BOOST_STL_DECLARE_LIMITS_MEMBER(int, digits10, __Digits10); 215 216 BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_signed, true); 217 218 BOOST_STL_DECLARE_LIMITS_MEMBER(int, radix, 2); 219 220 BOOST_STL_DECLARE_LIMITS_MEMBER(int, min_exponent, __MinExp); 221 BOOST_STL_DECLARE_LIMITS_MEMBER(int, max_exponent, __MaxExp); 222 BOOST_STL_DECLARE_LIMITS_MEMBER(int, min_exponent10, __MinExp10); 223 BOOST_STL_DECLARE_LIMITS_MEMBER(int, max_exponent10, __MaxExp10); 224 225 BOOST_STL_DECLARE_LIMITS_MEMBER(bool, has_infinity, true); 226 BOOST_STL_DECLARE_LIMITS_MEMBER(bool, has_quiet_NaN, true); 227 BOOST_STL_DECLARE_LIMITS_MEMBER(bool, has_signaling_NaN, true); 228 BOOST_STL_DECLARE_LIMITS_MEMBER(float_denorm_style, 229 has_denorm, 230 denorm_indeterminate); 231 BOOST_STL_DECLARE_LIMITS_MEMBER(bool, has_denorm_loss, false); 232 233 infinity()234 static __number infinity() throw() { 235 return float_helper<__number, __InfinityWord>::get_word(); 236 } quiet_NaN()237 static __number quiet_NaN() throw() { 238 return float_helper<__number,__QNaNWord>::get_word(); 239 } signaling_NaN()240 static __number signaling_NaN() throw() { 241 return float_helper<__number,__SNaNWord>::get_word(); 242 } 243 244 BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_iec559, __IsIEC559); 245 BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_bounded, true); 246 BOOST_STL_DECLARE_LIMITS_MEMBER(bool, traps, false /* was: true */ ); 247 BOOST_STL_DECLARE_LIMITS_MEMBER(bool, tinyness_before, false); 248 249 BOOST_STL_DECLARE_LIMITS_MEMBER(float_round_style, round_style, __RoundStyle); 250 }; 251 252 // Class numeric_limits 253 254 // The unspecialized class. 255 256 template<class T> 257 class numeric_limits : public _Numeric_limits_base<T> {}; 258 259 // Specializations for all built-in integral types. 260 261 template<> 262 class numeric_limits<bool> 263 : public _Integer_limits<bool, false, true, 0> 264 {}; 265 266 template<> 267 class numeric_limits<char> 268 : public _Integer_limits<char, CHAR_MIN, CHAR_MAX> 269 {}; 270 271 template<> 272 class numeric_limits<signed char> 273 : public _Integer_limits<signed char, SCHAR_MIN, SCHAR_MAX> 274 {}; 275 276 template<> 277 class numeric_limits<unsigned char> 278 : public _Integer_limits<unsigned char, 0, UCHAR_MAX> 279 {}; 280 281 #ifndef BOOST_NO_INTRINSIC_WCHAR_T 282 template<> 283 class numeric_limits<wchar_t> 284 #if !defined(WCHAR_MAX) || !defined(WCHAR_MIN) 285 #if defined(_WIN32) || defined(__CYGWIN__) 286 : public _Integer_limits<wchar_t, 0, USHRT_MAX> 287 #elif defined(__hppa) 288 // wchar_t has "unsigned int" as the underlying type 289 : public _Integer_limits<wchar_t, 0, UINT_MAX> 290 #else 291 // assume that wchar_t has "int" as the underlying type 292 : public _Integer_limits<wchar_t, INT_MIN, INT_MAX> 293 #endif 294 #else 295 // we have WCHAR_MIN and WCHAR_MAX defined, so use it 296 : public _Integer_limits<wchar_t, WCHAR_MIN, WCHAR_MAX> 297 #endif 298 {}; 299 #endif 300 301 template<> 302 class numeric_limits<short> 303 : public _Integer_limits<short, SHRT_MIN, SHRT_MAX> 304 {}; 305 306 template<> 307 class numeric_limits<unsigned short> 308 : public _Integer_limits<unsigned short, 0, USHRT_MAX> 309 {}; 310 311 template<> 312 class numeric_limits<int> 313 : public _Integer_limits<int, INT_MIN, INT_MAX> 314 {}; 315 316 template<> 317 class numeric_limits<unsigned int> 318 : public _Integer_limits<unsigned int, 0, UINT_MAX> 319 {}; 320 321 template<> 322 class numeric_limits<long> 323 : public _Integer_limits<long, LONG_MIN, LONG_MAX> 324 {}; 325 326 template<> 327 class numeric_limits<unsigned long> 328 : public _Integer_limits<unsigned long, 0, ULONG_MAX> 329 {}; 330 331 #ifdef __GNUC__ 332 333 // Some compilers have long long, but don't define the 334 // LONGLONG_MIN and LONGLONG_MAX macros in limits.h. This 335 // assumes that long long is 64 bits. 336 #if !defined(LONGLONG_MAX) && !defined(ULONGLONG_MAX) 337 338 # define ULONGLONG_MAX 0xffffffffffffffffLLU 339 # define LONGLONG_MAX 0x7fffffffffffffffLL 340 341 #endif 342 343 #if !defined(LONGLONG_MIN) 344 # define LONGLONG_MIN (-LONGLONG_MAX - 1) 345 #endif 346 347 348 #if !defined(ULONGLONG_MIN) 349 # define ULONGLONG_MIN 0 350 #endif 351 352 #endif /* __GNUC__ */ 353 354 // Specializations for all built-in floating-point type. 355 356 template<> class numeric_limits<float> 357 : public _Floating_limits<float, 358 FLT_MANT_DIG, // Binary digits of precision 359 FLT_DIG, // Decimal digits of precision 360 FLT_MIN_EXP, // Minimum exponent 361 FLT_MAX_EXP, // Maximum exponent 362 FLT_MIN_10_EXP, // Minimum base 10 exponent 363 FLT_MAX_10_EXP, // Maximum base 10 exponent 364 #if defined(BOOST_BIG_ENDIAN) 365 0x7f80 << (sizeof(int)*CHAR_BIT-16), // Last word of +infinity 366 0x7f81 << (sizeof(int)*CHAR_BIT-16), // Last word of quiet NaN 367 0x7fc1 << (sizeof(int)*CHAR_BIT-16), // Last word of signaling NaN 368 #else 369 0x7f800000u, // Last word of +infinity 370 0x7f810000u, // Last word of quiet NaN 371 0x7fc10000u, // Last word of signaling NaN 372 #endif 373 true, // conforms to iec559 374 round_to_nearest> 375 { 376 public: BOOST_PREVENT_MACRO_SUBSTITUTION()377 static float min BOOST_PREVENT_MACRO_SUBSTITUTION () throw() { return FLT_MIN; } denorm_min()378 static float denorm_min() throw() { return FLT_MIN; } BOOST_PREVENT_MACRO_SUBSTITUTION()379 static float max BOOST_PREVENT_MACRO_SUBSTITUTION () throw() { return FLT_MAX; } epsilon()380 static float epsilon() throw() { return FLT_EPSILON; } round_error()381 static float round_error() throw() { return 0.5f; } // Units: ulps. 382 }; 383 384 template<> class numeric_limits<double> 385 : public _Floating_limits<double, 386 DBL_MANT_DIG, // Binary digits of precision 387 DBL_DIG, // Decimal digits of precision 388 DBL_MIN_EXP, // Minimum exponent 389 DBL_MAX_EXP, // Maximum exponent 390 DBL_MIN_10_EXP, // Minimum base 10 exponent 391 DBL_MAX_10_EXP, // Maximum base 10 exponent 392 #if defined(BOOST_BIG_ENDIAN) 393 0x7ff0 << (sizeof(int)*CHAR_BIT-16), // Last word of +infinity 394 0x7ff1 << (sizeof(int)*CHAR_BIT-16), // Last word of quiet NaN 395 0x7ff9 << (sizeof(int)*CHAR_BIT-16), // Last word of signaling NaN 396 #else 397 0x7ff00000u, // Last word of +infinity 398 0x7ff10000u, // Last word of quiet NaN 399 0x7ff90000u, // Last word of signaling NaN 400 #endif 401 true, // conforms to iec559 402 round_to_nearest> 403 { 404 public: BOOST_PREVENT_MACRO_SUBSTITUTION()405 static double min BOOST_PREVENT_MACRO_SUBSTITUTION () throw() { return DBL_MIN; } denorm_min()406 static double denorm_min() throw() { return DBL_MIN; } BOOST_PREVENT_MACRO_SUBSTITUTION()407 static double max BOOST_PREVENT_MACRO_SUBSTITUTION () throw() { return DBL_MAX; } epsilon()408 static double epsilon() throw() { return DBL_EPSILON; } round_error()409 static double round_error() throw() { return 0.5; } // Units: ulps. 410 }; 411 412 template<> class numeric_limits<long double> 413 : public _Floating_limits<long double, 414 LDBL_MANT_DIG, // Binary digits of precision 415 LDBL_DIG, // Decimal digits of precision 416 LDBL_MIN_EXP, // Minimum exponent 417 LDBL_MAX_EXP, // Maximum exponent 418 LDBL_MIN_10_EXP,// Minimum base 10 exponent 419 LDBL_MAX_10_EXP,// Maximum base 10 exponent 420 #if defined(BOOST_BIG_ENDIAN) 421 0x7ff0 << (sizeof(int)*CHAR_BIT-16), // Last word of +infinity 422 0x7ff1 << (sizeof(int)*CHAR_BIT-16), // Last word of quiet NaN 423 0x7ff9 << (sizeof(int)*CHAR_BIT-16), // Last word of signaling NaN 424 #else 425 0x7fff8000u, // Last word of +infinity 426 0x7fffc000u, // Last word of quiet NaN 427 0x7fff9000u, // Last word of signaling NaN 428 #endif 429 false, // Doesn't conform to iec559 430 round_to_nearest> 431 { 432 public: BOOST_PREVENT_MACRO_SUBSTITUTION()433 static long double min BOOST_PREVENT_MACRO_SUBSTITUTION () throw() { return LDBL_MIN; } denorm_min()434 static long double denorm_min() throw() { return LDBL_MIN; } BOOST_PREVENT_MACRO_SUBSTITUTION()435 static long double max BOOST_PREVENT_MACRO_SUBSTITUTION () throw() { return LDBL_MAX; } epsilon()436 static long double epsilon() throw() { return LDBL_EPSILON; } round_error()437 static long double round_error() throw() { return 4; } // Units: ulps. 438 }; 439 440 } // namespace std 441 442 #endif /* BOOST_SGI_CPP_LIMITS */ 443 444 // Local Variables: 445 // mode:C++ 446 // End: 447 448 449 450