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) \ 37template <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) \ 66template <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) \ 103template <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> \ 110const __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. */ 154template<class _Number, unsigned short _Word> 155struct 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) 186template<class _Number, unsigned short _Word1, unsigned short _Word2> 187struct 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 271union _F_rep { 272 unsigned short rep[2]; 273 float val; 274}; 275union _D_rep { 276 unsigned short rep[4]; 277 double val; 278}; 279 280# ifndef _STLP_NO_LONG_DOUBLE 281union _LD_rep { 282 unsigned short rep[8]; 283 long double val; 284}; 285# endif 286#endif 287 288template <class __dummy> 289float _STLP_CALL _LimG<__dummy>::get_F_inf() { 290 typedef float_helper<float, 0x7f80u> _FloatHelper; 291 return _FloatHelper::get_from_last_word(); 292} 293template <class __dummy> 294float _STLP_CALL _LimG<__dummy>::get_F_qNaN() { 295 typedef float_helper<float, 0x7f81u> _FloatHelper; 296 return _FloatHelper::get_from_last_word(); 297} 298template <class __dummy> 299float _STLP_CALL _LimG<__dummy>::get_F_sNaN() { 300 typedef float_helper<float, 0x7fc1u> _FloatHelper; 301 return _FloatHelper::get_from_last_word(); 302} 303template <class __dummy> 304float _STLP_CALL _LimG<__dummy>::get_F_denormMin() { 305 typedef float_helper<float, 0x0001u> _FloatHelper; 306 return _FloatHelper::get_from_first_word(); 307} 308 309template <int __use_double_limits> 310class _NumericLimitsAccess; 311 312_STLP_TEMPLATE_NULL 313class _NumericLimitsAccess<1> { 314public: 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 329template <class __dummy> 330double _STLP_CALL _LimG<__dummy>::get_D_inf() 331{ return _NumericLimitsAccess<1>::get_inf(); } 332template <class __dummy> 333double _STLP_CALL _LimG<__dummy>::get_D_qNaN() 334{ return _NumericLimitsAccess<1>::get_qNaN(); } 335template <class __dummy> 336double _STLP_CALL _LimG<__dummy>::get_D_sNaN() 337{ return _NumericLimitsAccess<1>::get_sNaN(); } 338template <class __dummy> 339double _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 346class _NumericLimitsAccess<0> { 347public: 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 374template <class __dummy> 375long 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} 379template <class __dummy> 380long 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} 384template <class __dummy> 385long 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} 389template <class __dummy> 390long 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