1 /* 2 * Copyright (c) 1998,1999 3 * Silicon Graphics Computer Systems, Inc. 4 * 5 * Copyright (c) 1999 6 * Boris Fomitchev 7 * 8 * This material is provided "as is", with absolutely no warranty expressed 9 * or implied. Any use is at your own risk. 10 * 11 * Permission to use or copy this software for any purpose is hereby granted 12 * without fee, provided the above notices are retained on all copies. 13 * Permission to modify the code and to distribute modified code is granted, 14 * provided the above notices are retained, and a notice that the code was 15 * modified is included with the above copyright notice. 16 * 17 */ 18 19 #ifndef _STLP_LIMITS_C 20 #define _STLP_LIMITS_C 21 22 #ifndef _STLP_INTERNAL_LIMITS 23 # include <stl/_limits.h> 24 #endif 25 26 //========================================================== 27 // numeric_limits static members 28 //========================================================== 29 30 _STLP_BEGIN_NAMESPACE 31 32 _STLP_MOVE_TO_PRIV_NAMESPACE 33 34 #if !defined (_STLP_STATIC_CONST_INIT_BUG) && !defined (_STLP_NO_STATIC_CONST_DEFINITION) 35 36 # define __declare_numeric_base_member(__type, __mem) \ 37 template <class __number> \ 38 const __type _Numeric_limits_base<__number>:: __mem 39 40 __declare_numeric_base_member(bool, is_specialized); 41 __declare_numeric_base_member(int, digits); 42 __declare_numeric_base_member(int, digits10); 43 __declare_numeric_base_member(bool, is_signed); 44 __declare_numeric_base_member(bool, is_integer); 45 __declare_numeric_base_member(bool, is_exact); 46 __declare_numeric_base_member(int, radix); 47 __declare_numeric_base_member(int, min_exponent); 48 __declare_numeric_base_member(int, max_exponent); 49 __declare_numeric_base_member(int, min_exponent10); 50 __declare_numeric_base_member(int, max_exponent10); 51 __declare_numeric_base_member(bool, has_infinity); 52 __declare_numeric_base_member(bool, has_quiet_NaN); 53 __declare_numeric_base_member(bool, has_signaling_NaN); 54 __declare_numeric_base_member(float_denorm_style, has_denorm); 55 __declare_numeric_base_member(bool, has_denorm_loss); 56 __declare_numeric_base_member(bool, is_iec559); 57 __declare_numeric_base_member(bool, is_bounded); 58 __declare_numeric_base_member(bool, is_modulo); 59 __declare_numeric_base_member(bool, traps); 60 __declare_numeric_base_member(bool, tinyness_before); 61 __declare_numeric_base_member(float_round_style, round_style); 62 63 # undef __declare_numeric_base_member 64 65 # define __declare_integer_limits_member(__type, __mem) \ 66 template <class _Int, _STLP_LIMITS_MIN_TYPE __imin, _STLP_LIMITS_MAX_TYPE __imax, int __idigits, bool __ismod> \ 67 const __type _Integer_limits<_Int, __imin, __imax, __idigits, __ismod>:: __mem 68 69 __declare_integer_limits_member(bool, is_specialized); 70 __declare_integer_limits_member(int, digits); 71 __declare_integer_limits_member(int, digits10); 72 __declare_integer_limits_member(bool, is_signed); 73 __declare_integer_limits_member(bool, is_integer); 74 __declare_integer_limits_member(bool, is_exact); 75 __declare_integer_limits_member(int, radix); 76 __declare_integer_limits_member(bool, is_bounded); 77 __declare_integer_limits_member(bool, is_modulo); 78 # undef __declare_integer_limits_member 79 80 # if defined (__GNUC__) && (__GNUC__ != 2 || __GNUC_MINOR__ > 96) && (__GNUC__ != 3 || __GNUC_MINOR__ == 0) && (__GNUC__ <= 3) 81 _STLP_MOVE_TO_STD_NAMESPACE 82 83 # define __declare_numeric_limits_member(__integer) \ 84 _STLP_TEMPLATE_NULL const int numeric_limits<__integer>::digits; \ 85 _STLP_TEMPLATE_NULL const int numeric_limits<__integer>::digits10; \ 86 _STLP_TEMPLATE_NULL const int numeric_limits<__integer>::radix; \ 87 _STLP_TEMPLATE_NULL const bool numeric_limits<__integer>::is_specialized; \ 88 _STLP_TEMPLATE_NULL const bool numeric_limits<__integer>::is_signed; \ 89 _STLP_TEMPLATE_NULL const bool numeric_limits<__integer>::is_integer; \ 90 _STLP_TEMPLATE_NULL const bool numeric_limits<__integer>::is_exact; \ 91 _STLP_TEMPLATE_NULL const bool numeric_limits<__integer>::is_bounded; \ 92 _STLP_TEMPLATE_NULL const bool numeric_limits<__integer>::is_modulo 93 94 __declare_numeric_limits_member(_STLP_LONG_LONG); 95 __declare_numeric_limits_member(unsigned _STLP_LONG_LONG); 96 97 # undef __declare_numeric_limits_member 98 99 _STLP_MOVE_TO_PRIV_NAMESPACE 100 # endif 101 102 # define __declare_float_limits_member(__type, __mem) \ 103 template <class __number, \ 104 int __Digits, int __Digits10, \ 105 int __MinExp, int __MaxExp, \ 106 int __MinExp10, int __MaxExp10, \ 107 bool __IsIEC559, \ 108 float_denorm_style __DenormStyle, \ 109 float_round_style __RoundStyle> \ 110 const __type _Floating_limits< __number, __Digits, __Digits10, \ 111 __MinExp, __MaxExp, __MinExp10, __MaxExp10, \ 112 __IsIEC559, __DenormStyle, __RoundStyle>::\ 113 __mem 114 115 __declare_float_limits_member(bool, is_specialized); 116 __declare_float_limits_member(int, digits); 117 __declare_float_limits_member(int, digits10); 118 __declare_float_limits_member(bool, is_signed); 119 __declare_float_limits_member(int, radix); 120 __declare_float_limits_member(int, min_exponent); 121 __declare_float_limits_member(int, max_exponent); 122 __declare_float_limits_member(int, min_exponent10); 123 __declare_float_limits_member(int, max_exponent10); 124 __declare_float_limits_member(bool, has_infinity); 125 __declare_float_limits_member(bool, has_quiet_NaN); 126 __declare_float_limits_member(bool, has_signaling_NaN); 127 __declare_float_limits_member(float_denorm_style, has_denorm); 128 __declare_float_limits_member(bool, has_denorm_loss); 129 __declare_float_limits_member(bool, is_iec559); 130 __declare_float_limits_member(bool, is_bounded); 131 __declare_float_limits_member(bool, traps); 132 __declare_float_limits_member(bool, tinyness_before); 133 __declare_float_limits_member(float_round_style, round_style); 134 # undef __declare_float_limits_member 135 136 #endif 137 138 139 #if defined (_STLP_EXPOSE_GLOBALS_IMPLEMENTATION) 140 141 # if defined (__GNUC__) || defined (__BORLANDC__) 142 # define _STLP_ADDITIONAL_OPEN_BRACKET { 143 # define _STLP_ADDITIONAL_CLOSE_BRACKET } 144 # else 145 # define _STLP_ADDITIONAL_OPEN_BRACKET 146 # define _STLP_ADDITIONAL_CLOSE_BRACKET 147 # endif 148 149 /* The following code has been extracted from the boost libraries (www.boost.org) and 150 * adapted with the STLport portability macros. Advantage on previous technique is that 151 * computation of infinity and NaN values is only based on big/little endianess, compiler 152 * float, double or long double representation is taken into account thanks to the sizeof 153 * operator. */ 154 template<class _Number, unsigned short _Word> 155 struct float_helper { 156 union _WordsNumber { 157 unsigned short _Words[8]; 158 _Number _num; 159 }; 160 static _Number get_word_higher() _STLP_NOTHROW { 161 _WordsNumber __tmp = { _STLP_ADDITIONAL_OPEN_BRACKET _Word, 0, 0, 0, 0, 0, 0, 0 _STLP_ADDITIONAL_CLOSE_BRACKET }; 162 return __tmp._num; 163 } 164 static _Number get_word_lower() _STLP_NOTHROW { 165 _WordsNumber __tmp = { _STLP_ADDITIONAL_OPEN_BRACKET 0, 0, 0, 0, 0, 0, 0, 0 _STLP_ADDITIONAL_CLOSE_BRACKET }; 166 __tmp._Words[(sizeof(_Number) >= 12 ? 10 : sizeof(_Number)) / sizeof(unsigned short) - 1] = _Word; 167 return __tmp._num; 168 } 169 static _Number get_from_last_word() _STLP_NOTHROW { 170 # if defined (_STLP_BIG_ENDIAN) 171 return get_word_higher(); 172 # else /* _STLP_LITTLE_ENDIAN */ 173 return get_word_lower(); 174 # endif 175 } 176 static _Number get_from_first_word() _STLP_NOTHROW { 177 # if defined (_STLP_BIG_ENDIAN) 178 return get_word_lower(); 179 # else /* _STLP_LITTLE_ENDIAN */ 180 return get_word_higher(); 181 # endif 182 } 183 }; 184 185 # if !defined (_STLP_NO_LONG_DOUBLE) && !defined (_STLP_BIG_ENDIAN) 186 template<class _Number, unsigned short _Word1, unsigned short _Word2> 187 struct float_helper2 { 188 union _WordsNumber { 189 unsigned short _Words[8]; 190 _Number _num; 191 }; 192 //static _Number get_word_higher() _STLP_NOTHROW { 193 // _WordsNumber __tmp = { _STLP_ADDITIONAL_OPEN_BRACKET _Word1, _Word2, 0, 0, 0, 0, 0, 0 _STLP_ADDITIONAL_CLOSE_BRACKET }; 194 // return __tmp._num; 195 //} 196 static _Number get_word_lower() _STLP_NOTHROW { 197 _WordsNumber __tmp = { _STLP_ADDITIONAL_OPEN_BRACKET 0, 0, 0, 0, 0, 0, 0, 0 _STLP_ADDITIONAL_CLOSE_BRACKET }; 198 __tmp._Words[(sizeof(_Number) >= 12 ? 10 : sizeof(_Number)) / sizeof(unsigned short) - 2] = _Word1; 199 __tmp._Words[(sizeof(_Number) >= 12 ? 10 : sizeof(_Number)) / sizeof(unsigned short) - 1] = _Word2; 200 return __tmp._num; 201 } 202 static _Number get_from_last_word() _STLP_NOTHROW { 203 //# if defined (_STLP_BIG_ENDIAN) 204 // return get_word_higher(); 205 //# else /* _STLP_LITTLE_ENDIAN */ 206 return get_word_lower(); 207 //# endif 208 } 209 }; 210 # endif 211 212 /* Former values kept in case moving to boost code has introduce a regression on 213 * some platform. */ 214 #if 0 215 # if defined (_STLP_BIG_ENDIAN) 216 # if defined (__OS400__) 217 # define _STLP_FLOAT_INF_REP { 0x7f80, 0 } 218 # define _STLP_FLOAT_QNAN_REP { 0xffc0, 0 } 219 # define _STLP_FLOAT_SNAN_REP { 0xff80, 0 } 220 # define _STLP_DOUBLE_INF_REP { 0x7ff0, 0, 0, 0 } 221 # define _STLP_DOUBLE_QNAN_REP { 0xfff8, 0, 0, 0 } 222 # define _STLP_DOUBLE_SNAN_REP { 0xfff0, 0, 0, 0 } 223 # define _STLP_LDOUBLE_INF_REP { 0x7ff0, 0, 0, 0, 0, 0, 0, 0 } 224 # define _STLP_LDOUBLE_QNAN_REP { 0xfff8, 0, 0, 0, 0, 0, 0, 0 } 225 # define _STLP_LDOUBLE_SNAN_REP { 0xfff0, 0, 0, 0, 0, 0, 0, 0 } 226 # else /* __OS400__ */ 227 # define _STLP_FLOAT_INF_REP { 0x7f80, 0 } 228 # define _STLP_FLOAT_QNAN_REP { 0x7fc1, 0 } 229 # define _STLP_FLOAT_SNAN_REP { 0x7f81, 0 } 230 # define _STLP_DOUBLE_INF_REP { 0x7ff0, 0, 0, 0 } 231 # define _STLP_DOUBLE_QNAN_REP { 0x7ff9, 0, 0, 0 } 232 # define _STLP_DOUBLE_SNAN_REP { 0x7ff1, 0, 0, 0 } 233 # define _STLP_LDOUBLE_INF_REP { 0x7ff0, 0, 0, 0, 0, 0, 0, 0 } 234 # define _STLP_LDOUBLE_QNAN_REP { 0x7ff1, 0, 0, 0, 0, 0, 0, 0 } 235 # define _STLP_LDOUBLE_SNAN_REP { 0x7ff9, 0, 0, 0, 0, 0, 0, 0 } 236 # endif /* __OS400__ */ 237 # else /* _STLP_LITTLE_ENDIAN */ 238 # if defined(__DECCXX) 239 # define _STLP_FLOAT_INF_REP { 0, 0x7f80 } 240 # define _STLP_FLOAT_QNAN_REP { 0, 0xffc0 } 241 # define _STLP_FLOAT_SNAN_REP { 0x5555, 0x7f85 } 242 # define _STLP_DOUBLE_INF_REP { 0, 0, 0, 0x7ff0 } 243 # define _STLP_DOUBLE_QNAN_REP { 0, 0, 0, 0xfff8 } 244 # define _STLP_DOUBLE_SNAN_REP { 0x5555, 0x5555, 0x5555, 0x7ff5 } 245 # define _STLP_LDOUBLE_INF_REP { 0, 0, 0, 0, 0, 0, 0, 0x7fff } 246 # define _STLP_LDOUBLE_QNAN_REP { 0, 0, 0, 0, 0, 0, 0x8000, 0xffff } 247 # define _STLP_LDOUBLE_SNAN_REP { 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x7fff} 248 # else 249 # define _STLP_FLOAT_INF_REP { 0, 0x7f80 } 250 # define _STLP_FLOAT_QNAN_REP { 0, 0x7fc0 } 251 # define _STLP_FLOAT_SNAN_REP { 0, 0x7fa0 } 252 # define _STLP_DOUBLE_INF_REP { 0, 0, 0, 0x7ff0 } 253 # define _STLP_DOUBLE_QNAN_REP { 0, 0, 0, 0x7ff8 } 254 # define _STLP_DOUBLE_SNAN_REP { 0, 0, 0, 0x7ff4 } 255 # if defined (_STLP_MSVC) || defined (__ICL) 256 # define _STLP_LDOUBLE_INF_REP { 0, 0, 0, 0x7FF0, 0 } 257 # define _STLP_LDOUBLE_QNAN_REP { 0, 0, 0, 0xFFF8, 0 } 258 # define _STLP_LDOUBLE_SNAN_REP { 0, 0, 0, 0xFFF8, 0 } 259 # elif defined (__BORLANDC__) 260 # define _STLP_LDOUBLE_INF_REP { 0, 0, 0, 0x8000, 0x7fff } 261 # define _STLP_LDOUBLE_QNAN_REP { 0, 0, 0, 0xc000, 0x7fff } 262 # define _STLP_LDOUBLE_SNAN_REP { 0, 0, 0, 0xa000, 0x7fff } 263 # else 264 # define _STLP_LDOUBLE_INF_REP { 0, 0, 0, 0x8000, 0x7fff, 0 } 265 # define _STLP_LDOUBLE_QNAN_REP { 0, 0, 0, 0xa000, 0x7fff, 0 } 266 # define _STLP_LDOUBLE_SNAN_REP { 0, 0, 0, 0xc000, 0x7fff, 0 } 267 # endif 268 # endif 269 # endif 270 271 union _F_rep { 272 unsigned short rep[2]; 273 float val; 274 }; 275 union _D_rep { 276 unsigned short rep[4]; 277 double val; 278 }; 279 280 # ifndef _STLP_NO_LONG_DOUBLE 281 union _LD_rep { 282 unsigned short rep[8]; 283 long double val; 284 }; 285 # endif 286 #endif 287 288 template <class __dummy> 289 float _STLP_CALL _LimG<__dummy>::get_F_inf() { 290 typedef float_helper<float, 0x7f80u> _FloatHelper; 291 return _FloatHelper::get_from_last_word(); 292 } 293 template <class __dummy> 294 float _STLP_CALL _LimG<__dummy>::get_F_qNaN() { 295 typedef float_helper<float, 0x7f81u> _FloatHelper; 296 return _FloatHelper::get_from_last_word(); 297 } 298 template <class __dummy> 299 float _STLP_CALL _LimG<__dummy>::get_F_sNaN() { 300 typedef float_helper<float, 0x7fc1u> _FloatHelper; 301 return _FloatHelper::get_from_last_word(); 302 } 303 template <class __dummy> 304 float _STLP_CALL _LimG<__dummy>::get_F_denormMin() { 305 typedef float_helper<float, 0x0001u> _FloatHelper; 306 return _FloatHelper::get_from_first_word(); 307 } 308 309 template <int __use_double_limits> 310 class _NumericLimitsAccess; 311 312 _STLP_TEMPLATE_NULL 313 class _NumericLimitsAccess<1> { 314 public: 315 static double get_inf() { 316 typedef float_helper<double, 0x7ff0u> _FloatHelper; 317 return _FloatHelper::get_from_last_word(); 318 } 319 static double get_qNaN() { 320 typedef float_helper<double, 0x7ff1u> _FloatHelper; 321 return _FloatHelper::get_from_last_word(); 322 } 323 static double get_sNaN() { 324 typedef float_helper<double, 0x7ff9u> _FloatHelper; 325 return _FloatHelper::get_from_last_word(); 326 } 327 }; 328 329 template <class __dummy> 330 double _STLP_CALL _LimG<__dummy>::get_D_inf() 331 { return _NumericLimitsAccess<1>::get_inf(); } 332 template <class __dummy> 333 double _STLP_CALL _LimG<__dummy>::get_D_qNaN() 334 { return _NumericLimitsAccess<1>::get_qNaN(); } 335 template <class __dummy> 336 double _STLP_CALL _LimG<__dummy>::get_D_sNaN() 337 { return _NumericLimitsAccess<1>::get_sNaN(); } 338 template <class __dummy> 339 double _STLP_CALL _LimG<__dummy>::get_D_denormMin() { 340 typedef float_helper<double, 0x0001u> _FloatHelper; 341 return _FloatHelper::get_from_first_word(); 342 } 343 344 # if !defined (_STLP_NO_LONG_DOUBLE) 345 _STLP_TEMPLATE_NULL 346 class _NumericLimitsAccess<0> { 347 public: 348 static long double get_inf() { 349 # if defined (_STLP_BIG_ENDIAN) 350 typedef float_helper<long double, 0x7ff0u> _FloatHelper; 351 # else 352 typedef float_helper2<long double, 0x8000u, 0x7fffu> _FloatHelper; 353 # endif 354 return _FloatHelper::get_from_last_word(); 355 } 356 static long double get_qNaN() { 357 # if defined (_STLP_BIG_ENDIAN) 358 typedef float_helper<long double, 0x7ff1u> _FloatHelper; 359 # else 360 typedef float_helper2<long double, 0xc000u, 0x7fffu> _FloatHelper; 361 # endif 362 return _FloatHelper::get_from_last_word(); 363 } 364 static long double get_sNaN() { 365 # if defined (_STLP_BIG_ENDIAN) 366 typedef float_helper<long double, 0x7ff9u> _FloatHelper; 367 # else 368 typedef float_helper2<long double, 0x9000u, 0x7fffu> _FloatHelper; 369 # endif 370 return _FloatHelper::get_from_last_word(); 371 } 372 }; 373 374 template <class __dummy> 375 long double _STLP_CALL _LimG<__dummy>::get_LD_inf() { 376 const int __use_double_limits = sizeof(double) == sizeof(long double) ? 1 : 0; 377 return _NumericLimitsAccess<__use_double_limits>::get_inf(); 378 } 379 template <class __dummy> 380 long double _STLP_CALL _LimG<__dummy>::get_LD_qNaN() { 381 const int __use_double_limits = sizeof(double) == sizeof(long double) ? 1 : 0; 382 return _NumericLimitsAccess<__use_double_limits>::get_qNaN(); 383 } 384 template <class __dummy> 385 long double _STLP_CALL _LimG<__dummy>::get_LD_sNaN() { 386 const int __use_double_limits = sizeof(double) == sizeof(long double) ? 1 : 0; 387 return _NumericLimitsAccess<__use_double_limits>::get_sNaN(); 388 } 389 template <class __dummy> 390 long double _STLP_CALL _LimG<__dummy>::get_LD_denormMin() { 391 typedef float_helper<long double, 0x0001u> _FloatHelper; 392 return _FloatHelper::get_from_first_word(); 393 } 394 # endif 395 396 #endif /* _STLP_EXPOSE_GLOBALS_IMPLEMENTATION */ 397 398 #undef _STLP_LIMITS_MIN_TYPE 399 #undef _STLP_LIMITS_MAX_TYPE 400 401 _STLP_MOVE_TO_STD_NAMESPACE 402 403 _STLP_END_NAMESPACE 404 405 #endif /* _STLP_LIMITS_C_INCLUDED */ 406