source: NonGTP/Boost/boost/detail/limits.hpp @ 857

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