You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
449 lines
16 KiB
449 lines
16 KiB
// Copyright 2001 John Maddock |
|
// Distributed under the Boost Software License, Version 1.0. (See accompany- |
|
// ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
|
|
|
/* |
|
* Copyright (c) 1997 |
|
* Silicon Graphics Computer Systems, Inc. |
|
* |
|
* Permission to use, copy, modify, distribute and sell this software |
|
* and its documentation for any purpose is hereby granted without fee, |
|
* provided that the above copyright notice appear in all copies and |
|
* that both that copyright notice and this permission notice appear |
|
* in supporting documentation. Silicon Graphics makes no |
|
* representations about the suitability of this software for any |
|
* purpose. It is provided "as is" without express or implied warranty. |
|
*/ |
|
|
|
/* NOTE: This is not portable code. Parts of numeric_limits<> are |
|
* inherently machine-dependent, and this file is written for the MIPS |
|
* architecture and the SGI MIPSpro C++ compiler. Parts of it (in |
|
* particular, some of the characteristics of floating-point types) |
|
* are almost certainly incorrect for any other platform. |
|
*/ |
|
|
|
/* The above comment is almost certainly out of date. This file works |
|
* on systems other than SGI MIPSpro C++ now. |
|
*/ |
|
|
|
/* |
|
* Revision history: |
|
* 21 Sep 2001: |
|
* Only include <cwchar> if BOOST_NO_CWCHAR is defined. (Darin Adler) |
|
* 10 Aug 2001: |
|
* Added MIPS (big endian) to the big endian family. (Jens Maurer) |
|
* 13 Apr 2001: |
|
* Added powerpc to the big endian family. (Jeremy Siek) |
|
* 5 Apr 2001: |
|
* Added sparc (big endian) processor support (John Maddock). |
|
* Initial sub: |
|
* Modified by Jens Maurer for gcc 2.95 on x86. |
|
*/ |
|
|
|
#ifndef BOOST_SGI_CPP_LIMITS |
|
#define BOOST_SGI_CPP_LIMITS |
|
|
|
#include <climits> |
|
#include <cfloat> |
|
#include <boost/config.hpp> |
|
#include <boost/detail/endian.hpp> |
|
|
|
#ifndef BOOST_NO_CWCHAR |
|
#include <cwchar> // for WCHAR_MIN and WCHAR_MAX |
|
#endif |
|
|
|
namespace std { |
|
|
|
enum float_round_style { |
|
round_indeterminate = -1, |
|
round_toward_zero = 0, |
|
round_to_nearest = 1, |
|
round_toward_infinity = 2, |
|
round_toward_neg_infinity = 3 |
|
}; |
|
|
|
enum float_denorm_style { |
|
denorm_indeterminate = -1, |
|
denorm_absent = 0, |
|
denorm_present = 1 |
|
}; |
|
|
|
// The C++ standard (section 18.2.1) requires that some of the members of |
|
// numeric_limits be static const data members that are given constant- |
|
// initializers within the class declaration. On compilers where the |
|
// BOOST_NO_INCLASS_MEMBER_INITIALIZATION macro is defined, it is impossible to write |
|
// a standard-conforming numeric_limits class. |
|
// |
|
// There are two possible workarounds: either initialize the data |
|
// members outside the class, or change them from data members to |
|
// enums. Neither workaround is satisfactory: the former makes it |
|
// impossible to use the data members in constant-expressions, and the |
|
// latter means they have the wrong type and that it is impossible to |
|
// take their addresses. We choose the former workaround. |
|
|
|
#ifdef BOOST_NO_INCLASS_MEMBER_INITIALIZATION |
|
# define BOOST_STL_DECLARE_LIMITS_MEMBER(__mem_type, __mem_name, __mem_value) \ |
|
enum { __mem_name = __mem_value } |
|
#else /* BOOST_NO_INCLASS_MEMBER_INITIALIZATION */ |
|
# define BOOST_STL_DECLARE_LIMITS_MEMBER(__mem_type, __mem_name, __mem_value) \ |
|
static const __mem_type __mem_name = __mem_value |
|
#endif /* BOOST_NO_INCLASS_MEMBER_INITIALIZATION */ |
|
|
|
// Base class for all specializations of numeric_limits. |
|
template <class __number> |
|
class _Numeric_limits_base { |
|
public: |
|
BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_specialized, false); |
|
|
|
static __number min BOOST_PREVENT_MACRO_SUBSTITUTION () throw() { return __number(); } |
|
static __number max BOOST_PREVENT_MACRO_SUBSTITUTION () throw() { return __number(); } |
|
|
|
BOOST_STL_DECLARE_LIMITS_MEMBER(int, digits, 0); |
|
BOOST_STL_DECLARE_LIMITS_MEMBER(int, digits10, 0); |
|
|
|
BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_signed, false); |
|
BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_integer, false); |
|
BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_exact, false); |
|
|
|
BOOST_STL_DECLARE_LIMITS_MEMBER(int, radix, 0); |
|
|
|
static __number epsilon() throw() { return __number(); } |
|
static __number round_error() throw() { return __number(); } |
|
|
|
BOOST_STL_DECLARE_LIMITS_MEMBER(int, min_exponent, 0); |
|
BOOST_STL_DECLARE_LIMITS_MEMBER(int, min_exponent10, 0); |
|
BOOST_STL_DECLARE_LIMITS_MEMBER(int, max_exponent, 0); |
|
BOOST_STL_DECLARE_LIMITS_MEMBER(int, max_exponent10, 0); |
|
|
|
BOOST_STL_DECLARE_LIMITS_MEMBER(bool, has_infinity, false); |
|
BOOST_STL_DECLARE_LIMITS_MEMBER(bool, has_quiet_NaN, false); |
|
BOOST_STL_DECLARE_LIMITS_MEMBER(bool, has_signaling_NaN, false); |
|
BOOST_STL_DECLARE_LIMITS_MEMBER(float_denorm_style, |
|
has_denorm, |
|
denorm_absent); |
|
BOOST_STL_DECLARE_LIMITS_MEMBER(bool, has_denorm_loss, false); |
|
|
|
static __number infinity() throw() { return __number(); } |
|
static __number quiet_NaN() throw() { return __number(); } |
|
static __number signaling_NaN() throw() { return __number(); } |
|
static __number denorm_min() throw() { return __number(); } |
|
|
|
BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_iec559, false); |
|
BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_bounded, false); |
|
BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_modulo, false); |
|
|
|
BOOST_STL_DECLARE_LIMITS_MEMBER(bool, traps, false); |
|
BOOST_STL_DECLARE_LIMITS_MEMBER(bool, tinyness_before, false); |
|
BOOST_STL_DECLARE_LIMITS_MEMBER(float_round_style, |
|
round_style, |
|
round_toward_zero); |
|
}; |
|
|
|
// Base class for integers. |
|
|
|
template <class _Int, |
|
_Int __imin, |
|
_Int __imax, |
|
int __idigits = -1> |
|
class _Integer_limits : public _Numeric_limits_base<_Int> |
|
{ |
|
public: |
|
BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_specialized, true); |
|
|
|
static _Int min BOOST_PREVENT_MACRO_SUBSTITUTION () throw() { return __imin; } |
|
static _Int max BOOST_PREVENT_MACRO_SUBSTITUTION () throw() { return __imax; } |
|
|
|
BOOST_STL_DECLARE_LIMITS_MEMBER(int, |
|
digits, |
|
(__idigits < 0) ? (int)(sizeof(_Int) * CHAR_BIT) |
|
- (__imin == 0 ? 0 : 1) |
|
: __idigits); |
|
BOOST_STL_DECLARE_LIMITS_MEMBER(int, digits10, (digits * 301) / 1000); |
|
// log 2 = 0.301029995664... |
|
|
|
BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_signed, __imin != 0); |
|
BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_integer, true); |
|
BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_exact, true); |
|
BOOST_STL_DECLARE_LIMITS_MEMBER(int, radix, 2); |
|
|
|
BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_bounded, true); |
|
BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_modulo, true); |
|
}; |
|
|
|
#if defined(BOOST_BIG_ENDIAN) |
|
|
|
template<class Number, unsigned int Word> |
|
struct float_helper{ |
|
static Number get_word() throw() { |
|
// sizeof(long double) == 16 |
|
const unsigned int _S_word[4] = { Word, 0, 0, 0 }; |
|
return *reinterpret_cast<const Number*>(&_S_word); |
|
} |
|
}; |
|
|
|
#else |
|
|
|
template<class Number, unsigned int Word> |
|
struct float_helper{ |
|
static Number get_word() throw() { |
|
// sizeof(long double) == 12, but only 10 bytes significant |
|
const unsigned int _S_word[4] = { 0, 0, 0, Word }; |
|
return *reinterpret_cast<const Number*>( |
|
reinterpret_cast<const char *>(&_S_word)+16- |
|
(sizeof(Number) == 12 ? 10 : sizeof(Number))); |
|
} |
|
}; |
|
|
|
#endif |
|
|
|
// Base class for floating-point numbers. |
|
template <class __number, |
|
int __Digits, int __Digits10, |
|
int __MinExp, int __MaxExp, |
|
int __MinExp10, int __MaxExp10, |
|
unsigned int __InfinityWord, |
|
unsigned int __QNaNWord, unsigned int __SNaNWord, |
|
bool __IsIEC559, |
|
float_round_style __RoundStyle> |
|
class _Floating_limits : public _Numeric_limits_base<__number> |
|
{ |
|
public: |
|
BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_specialized, true); |
|
|
|
BOOST_STL_DECLARE_LIMITS_MEMBER(int, digits, __Digits); |
|
BOOST_STL_DECLARE_LIMITS_MEMBER(int, digits10, __Digits10); |
|
|
|
BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_signed, true); |
|
|
|
BOOST_STL_DECLARE_LIMITS_MEMBER(int, radix, 2); |
|
|
|
BOOST_STL_DECLARE_LIMITS_MEMBER(int, min_exponent, __MinExp); |
|
BOOST_STL_DECLARE_LIMITS_MEMBER(int, max_exponent, __MaxExp); |
|
BOOST_STL_DECLARE_LIMITS_MEMBER(int, min_exponent10, __MinExp10); |
|
BOOST_STL_DECLARE_LIMITS_MEMBER(int, max_exponent10, __MaxExp10); |
|
|
|
BOOST_STL_DECLARE_LIMITS_MEMBER(bool, has_infinity, true); |
|
BOOST_STL_DECLARE_LIMITS_MEMBER(bool, has_quiet_NaN, true); |
|
BOOST_STL_DECLARE_LIMITS_MEMBER(bool, has_signaling_NaN, true); |
|
BOOST_STL_DECLARE_LIMITS_MEMBER(float_denorm_style, |
|
has_denorm, |
|
denorm_indeterminate); |
|
BOOST_STL_DECLARE_LIMITS_MEMBER(bool, has_denorm_loss, false); |
|
|
|
|
|
static __number infinity() throw() { |
|
return float_helper<__number, __InfinityWord>::get_word(); |
|
} |
|
static __number quiet_NaN() throw() { |
|
return float_helper<__number,__QNaNWord>::get_word(); |
|
} |
|
static __number signaling_NaN() throw() { |
|
return float_helper<__number,__SNaNWord>::get_word(); |
|
} |
|
|
|
BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_iec559, __IsIEC559); |
|
BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_bounded, true); |
|
BOOST_STL_DECLARE_LIMITS_MEMBER(bool, traps, false /* was: true */ ); |
|
BOOST_STL_DECLARE_LIMITS_MEMBER(bool, tinyness_before, false); |
|
|
|
BOOST_STL_DECLARE_LIMITS_MEMBER(float_round_style, round_style, __RoundStyle); |
|
}; |
|
|
|
// Class numeric_limits |
|
|
|
// The unspecialized class. |
|
|
|
template<class T> |
|
class numeric_limits : public _Numeric_limits_base<T> {}; |
|
|
|
// Specializations for all built-in integral types. |
|
|
|
template<> |
|
class numeric_limits<bool> |
|
: public _Integer_limits<bool, false, true, 0> |
|
{}; |
|
|
|
template<> |
|
class numeric_limits<char> |
|
: public _Integer_limits<char, CHAR_MIN, CHAR_MAX> |
|
{}; |
|
|
|
template<> |
|
class numeric_limits<signed char> |
|
: public _Integer_limits<signed char, SCHAR_MIN, SCHAR_MAX> |
|
{}; |
|
|
|
template<> |
|
class numeric_limits<unsigned char> |
|
: public _Integer_limits<unsigned char, 0, UCHAR_MAX> |
|
{}; |
|
|
|
#ifndef BOOST_NO_INTRINSIC_WCHAR_T |
|
template<> |
|
class numeric_limits<wchar_t> |
|
#if !defined(WCHAR_MAX) || !defined(WCHAR_MIN) |
|
#if defined(_WIN32) || defined(__CYGWIN__) |
|
: public _Integer_limits<wchar_t, 0, USHRT_MAX> |
|
#elif defined(__hppa) |
|
// wchar_t has "unsigned int" as the underlying type |
|
: public _Integer_limits<wchar_t, 0, UINT_MAX> |
|
#else |
|
// assume that wchar_t has "int" as the underlying type |
|
: public _Integer_limits<wchar_t, INT_MIN, INT_MAX> |
|
#endif |
|
#else |
|
// we have WCHAR_MIN and WCHAR_MAX defined, so use it |
|
: public _Integer_limits<wchar_t, WCHAR_MIN, WCHAR_MAX> |
|
#endif |
|
{}; |
|
#endif |
|
|
|
template<> |
|
class numeric_limits<short> |
|
: public _Integer_limits<short, SHRT_MIN, SHRT_MAX> |
|
{}; |
|
|
|
template<> |
|
class numeric_limits<unsigned short> |
|
: public _Integer_limits<unsigned short, 0, USHRT_MAX> |
|
{}; |
|
|
|
template<> |
|
class numeric_limits<int> |
|
: public _Integer_limits<int, INT_MIN, INT_MAX> |
|
{}; |
|
|
|
template<> |
|
class numeric_limits<unsigned int> |
|
: public _Integer_limits<unsigned int, 0, UINT_MAX> |
|
{}; |
|
|
|
template<> |
|
class numeric_limits<long> |
|
: public _Integer_limits<long, LONG_MIN, LONG_MAX> |
|
{}; |
|
|
|
template<> |
|
class numeric_limits<unsigned long> |
|
: public _Integer_limits<unsigned long, 0, ULONG_MAX> |
|
{}; |
|
|
|
#ifdef __GNUC__ |
|
|
|
// Some compilers have long long, but don't define the |
|
// LONGLONG_MIN and LONGLONG_MAX macros in limits.h. This |
|
// assumes that long long is 64 bits. |
|
#if !defined(LONGLONG_MAX) && !defined(ULONGLONG_MAX) |
|
|
|
# define ULONGLONG_MAX 0xffffffffffffffffLLU |
|
# define LONGLONG_MAX 0x7fffffffffffffffLL |
|
|
|
#endif |
|
|
|
#if !defined(LONGLONG_MIN) |
|
# define LONGLONG_MIN (-LONGLONG_MAX - 1) |
|
#endif |
|
|
|
|
|
#if !defined(ULONGLONG_MIN) |
|
# define ULONGLONG_MIN 0 |
|
#endif |
|
|
|
#endif /* __GNUC__ */ |
|
|
|
// Specializations for all built-in floating-point type. |
|
|
|
template<> class numeric_limits<float> |
|
: public _Floating_limits<float, |
|
FLT_MANT_DIG, // Binary digits of precision |
|
FLT_DIG, // Decimal digits of precision |
|
FLT_MIN_EXP, // Minimum exponent |
|
FLT_MAX_EXP, // Maximum exponent |
|
FLT_MIN_10_EXP, // Minimum base 10 exponent |
|
FLT_MAX_10_EXP, // Maximum base 10 exponent |
|
#if defined(BOOST_BIG_ENDIAN) |
|
0x7f80 << (sizeof(int)*CHAR_BIT-16), // Last word of +infinity |
|
0x7f81 << (sizeof(int)*CHAR_BIT-16), // Last word of quiet NaN |
|
0x7fc1 << (sizeof(int)*CHAR_BIT-16), // Last word of signaling NaN |
|
#else |
|
0x7f800000u, // Last word of +infinity |
|
0x7f810000u, // Last word of quiet NaN |
|
0x7fc10000u, // Last word of signaling NaN |
|
#endif |
|
true, // conforms to iec559 |
|
round_to_nearest> |
|
{ |
|
public: |
|
static float min BOOST_PREVENT_MACRO_SUBSTITUTION () throw() { return FLT_MIN; } |
|
static float denorm_min() throw() { return FLT_MIN; } |
|
static float max BOOST_PREVENT_MACRO_SUBSTITUTION () throw() { return FLT_MAX; } |
|
static float epsilon() throw() { return FLT_EPSILON; } |
|
static float round_error() throw() { return 0.5f; } // Units: ulps. |
|
}; |
|
|
|
template<> class numeric_limits<double> |
|
: public _Floating_limits<double, |
|
DBL_MANT_DIG, // Binary digits of precision |
|
DBL_DIG, // Decimal digits of precision |
|
DBL_MIN_EXP, // Minimum exponent |
|
DBL_MAX_EXP, // Maximum exponent |
|
DBL_MIN_10_EXP, // Minimum base 10 exponent |
|
DBL_MAX_10_EXP, // Maximum base 10 exponent |
|
#if defined(BOOST_BIG_ENDIAN) |
|
0x7ff0 << (sizeof(int)*CHAR_BIT-16), // Last word of +infinity |
|
0x7ff1 << (sizeof(int)*CHAR_BIT-16), // Last word of quiet NaN |
|
0x7ff9 << (sizeof(int)*CHAR_BIT-16), // Last word of signaling NaN |
|
#else |
|
0x7ff00000u, // Last word of +infinity |
|
0x7ff10000u, // Last word of quiet NaN |
|
0x7ff90000u, // Last word of signaling NaN |
|
#endif |
|
true, // conforms to iec559 |
|
round_to_nearest> |
|
{ |
|
public: |
|
static double min BOOST_PREVENT_MACRO_SUBSTITUTION () throw() { return DBL_MIN; } |
|
static double denorm_min() throw() { return DBL_MIN; } |
|
static double max BOOST_PREVENT_MACRO_SUBSTITUTION () throw() { return DBL_MAX; } |
|
static double epsilon() throw() { return DBL_EPSILON; } |
|
static double round_error() throw() { return 0.5; } // Units: ulps. |
|
}; |
|
|
|
template<> class numeric_limits<long double> |
|
: public _Floating_limits<long double, |
|
LDBL_MANT_DIG, // Binary digits of precision |
|
LDBL_DIG, // Decimal digits of precision |
|
LDBL_MIN_EXP, // Minimum exponent |
|
LDBL_MAX_EXP, // Maximum exponent |
|
LDBL_MIN_10_EXP,// Minimum base 10 exponent |
|
LDBL_MAX_10_EXP,// Maximum base 10 exponent |
|
#if defined(BOOST_BIG_ENDIAN) |
|
0x7ff0 << (sizeof(int)*CHAR_BIT-16), // Last word of +infinity |
|
0x7ff1 << (sizeof(int)*CHAR_BIT-16), // Last word of quiet NaN |
|
0x7ff9 << (sizeof(int)*CHAR_BIT-16), // Last word of signaling NaN |
|
#else |
|
0x7fff8000u, // Last word of +infinity |
|
0x7fffc000u, // Last word of quiet NaN |
|
0x7fff9000u, // Last word of signaling NaN |
|
#endif |
|
false, // Doesn't conform to iec559 |
|
round_to_nearest> |
|
{ |
|
public: |
|
static long double min BOOST_PREVENT_MACRO_SUBSTITUTION () throw() { return LDBL_MIN; } |
|
static long double denorm_min() throw() { return LDBL_MIN; } |
|
static long double max BOOST_PREVENT_MACRO_SUBSTITUTION () throw() { return LDBL_MAX; } |
|
static long double epsilon() throw() { return LDBL_EPSILON; } |
|
static long double round_error() throw() { return 4; } // Units: ulps. |
|
}; |
|
|
|
} // namespace std |
|
|
|
#endif /* BOOST_SGI_CPP_LIMITS */ |
|
|
|
// Local Variables: |
|
// mode:C++ |
|
// End: |
|
|
|
|
|
|
|
|