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   };
get_word_higherfloat_helper160   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   }
get_word_lowerfloat_helper164   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   }
get_from_last_wordfloat_helper169   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   }
get_from_first_wordfloat_helper176   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   //}
get_word_lowerfloat_helper2196   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   }
get_from_last_wordfloat_helper2202   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>
get_F_inf()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>
get_F_qNaN()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>
get_F_sNaN()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>
get_F_denormMin()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:
get_inf()315   static double get_inf() {
316     typedef float_helper<double, 0x7ff0u> _FloatHelper;
317     return _FloatHelper::get_from_last_word();
318   }
get_qNaN()319   static double get_qNaN() {
320     typedef float_helper<double, 0x7ff1u> _FloatHelper;
321     return _FloatHelper::get_from_last_word();
322   }
get_sNaN()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>
get_D_inf()330 double _STLP_CALL _LimG<__dummy>::get_D_inf()
331 { return _NumericLimitsAccess<1>::get_inf(); }
332 template <class __dummy>
get_D_qNaN()333 double _STLP_CALL _LimG<__dummy>::get_D_qNaN()
334 { return _NumericLimitsAccess<1>::get_qNaN(); }
335 template <class __dummy>
get_D_sNaN()336 double _STLP_CALL _LimG<__dummy>::get_D_sNaN()
337 { return _NumericLimitsAccess<1>::get_sNaN(); }
338 template <class __dummy>
get_D_denormMin()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:
get_inf()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   }
get_qNaN()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   }
get_sNaN()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>
get_LD_inf()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>
get_LD_qNaN()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>
get_LD_sNaN()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>
get_LD_denormMin()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