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