diff --git a/include/boost/detail/limits.hpp b/include/boost/detail/limits.hpp new file mode 100644 index 00000000..54ef2364 --- /dev/null +++ b/include/boost/detail/limits.hpp @@ -0,0 +1,386 @@ +/* + * 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. + */ + +/* + * Modified by Jens Maurer for gcc 2.95 on x86. + */ + +#ifndef BOOST_SGI_CPP_LIMITS +#define BOOST_SGI_CPP_LIMITS + +#include +#include +#include + +#ifndef __i386__ +#error This file is intended to be used with x86 CPUs. +#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 _Numeric_limits_base { +public: + BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_specialized, false); + + static __number min() throw() { return __number(); } + static __number max() 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 _Integer_limits : public _Numeric_limits_base<_Int> +{ +public: + BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_specialized, true); + + static _Int min() throw() { return __imin; } + static _Int max() 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); +}; + +// Base class for floating-point numbers. +template +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); + + template + 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( + reinterpret_cast(&_S_word)+16- + (sizeof(__number) == 12 ? 10 : sizeof(__number))); + } + + static __number infinity() throw() { + return __get_word<__InfinityWord>(); + } + static __number quiet_NaN() throw() { + return __get_word<__QNaNWord>(); + } + static __number signaling_NaN() throw() { + return __get_word<__SNaNWord>(); + } + + 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 numeric_limits : public _Numeric_limits_base {}; + +// Specializations for all built-in integral types. + +template<> +class numeric_limits + : public _Integer_limits +{}; + +template<> +class numeric_limits + : public _Integer_limits +{}; + +template<> +class numeric_limits + : public _Integer_limits +{}; + +template<> +class numeric_limits + : public _Integer_limits +{}; + +#ifndef _WIN32 +template<> +class numeric_limits + : public _Integer_limits +{}; +#else +class numeric_limits + : public _Integer_limits +{}; +#endif + +template<> +class numeric_limits + : public _Integer_limits +{}; + +template<> +class numeric_limits + : public _Integer_limits +{}; + +template<> +class numeric_limits + : public _Integer_limits +{}; + +template<> +class numeric_limits + : public _Integer_limits +{}; + +template<> +class numeric_limits + : public _Integer_limits +{}; + +template<> +class numeric_limits + : public _Integer_limits +{}; + +#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_MIN) && !defined(LONGLONG_MAX) \ + && !defined(ULONGLONG_MAX) + +#define ULONGLONG_MAX 0xffffffffffffffffLLU +#define LONGLONG_MAX 0x7fffffffffffffffLL +#define LONGLONG_MIN (-LONGLONG_MAX - 1) + +#endif + +template<> +class numeric_limits + : public _Integer_limits +{}; + +template<> +class numeric_limits + : public _Integer_limits +{}; + +#endif /* __GNUC__ */ + +// Specializations for all built-in floating-point type. + +template<> class numeric_limits + : public _Floating_limits +{ +public: + static float min() throw() { return FLT_MIN; } + static float denorm_min() throw() { return FLT_MIN; } + static float max() 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 + : public _Floating_limits +{ +public: + static double min() throw() { return DBL_MIN; } + static double denorm_min() throw() { return DBL_MIN; } + static double max() 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 + : public _Floating_limits +{ +public: + static long double min() throw() { return LDBL_MIN; } + static long double denorm_min() throw() { return LDBL_MIN; } + static long double max() 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: \ No newline at end of file diff --git a/include/boost/limits.hpp b/include/boost/limits.hpp new file mode 100644 index 00000000..d982c11d --- /dev/null +++ b/include/boost/limits.hpp @@ -0,0 +1,12 @@ +// (C) Copyright Boost.org 1999. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +#include + +#ifdef BOOST_NO_LIMITS +#include +#else +#include +#endif \ No newline at end of file diff --git a/limits_test.cpp b/limits_test.cpp new file mode 100644 index 00000000..37af9bc5 --- /dev/null +++ b/limits_test.cpp @@ -0,0 +1,126 @@ +/* boost limits_test.cpp test your file for important + * + * Copyright Jens Maurer 2000 + * Permission to use, copy, modify, sell, and distribute this software + * is hereby granted without free provided that the above copyright notice + * appears in all copies and that both that copyright notice and this + * permission notice appear in supporting documentation, + * + * Jens Maurer makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * $Id$ + */ + +#include +#include +#include + +#ifdef NDEBUG +#error This test relies on assert() and thus makes no sense with NDEBUG defined +#endif + +/* + * General portability note: + * MSVC mis-compiles explicit function template instantiations. + * For example, f() and f() are both compiled to call f(). + * BCC is unable to implicitly convert a "const char *" to a std::string + * when using explicit function template instantiations. + * + * Therefore, avoid explicit function template instantiations. + */ + +template +void test_integral_limits(const T &, const char * msg) +{ + std::cout << "Testing " << msg << " (size " << sizeof(T) << ")" << std::endl; + typedef std::numeric_limits lim; + + assert(lim::is_specialized); + assert(lim::is_integer); + // assert(lim::is_modulo); + + std::cout << "min: " << lim::min() << ", max: " << lim::max() << '\n'; +} + +template +void test_float_limits(const T &, const char * msg) +{ + std::cout << "Testing " << msg << std::endl; + typedef std::numeric_limits lim; + + assert(lim::is_specialized); + assert(!lim::is_modulo); + assert(!lim::is_integer); + assert(lim::is_signed); + + assert(lim::epsilon() > 0); + + assert(lim::has_infinity); + assert(lim::has_quiet_NaN); + assert(lim::has_signaling_NaN); + + const T infinity = lim::infinity(); + const T qnan = lim::quiet_NaN(); + const T snan = lim::signaling_NaN(); + (void) snan; + + // make sure those values are not 0 or similar nonsense + + std::cout << "IEEE-compatible: " << lim::is_iec559 + << ", traps: " << lim::traps + << ", bounded: " << lim::is_bounded + << ", exact: " << lim::is_exact << '\n' + << "min: " << lim::min() << ", max: " << lim::max() << '\n' + << "infinity: " << infinity << ", QNaN: " << qnan << '\n'; + // infinity is beyond the representable range + assert(lim::max() > 1000); + assert(infinity > lim::max()); + assert(-infinity < -lim::max()); + assert(lim::min() < 0.001); + assert(lim::min() > 0); + + // NaNs shall always compare "false" + // If one of these fail, your compiler may be optimizing incorrectly + assert(! (qnan < 42)); + assert(! (qnan > 42)); + assert(! (qnan <= 42)); + assert(! (qnan >= 42)); + assert(! (qnan == qnan)); +} + + +int main() +{ + test_integral_limits(bool(), "bool"); + test_integral_limits(char(), "char"); + typedef signed char signed_char; + test_integral_limits(signed_char(), "signed char"); + typedef unsigned char unsigned_char; + test_integral_limits(unsigned_char(), "unsigned char"); + test_integral_limits(wchar_t(), "wchar_t"); + test_integral_limits(short(), "short"); + typedef unsigned short unsigned_short; + test_integral_limits(unsigned_short(), "unsigned short"); + test_integral_limits(int(), "int"); + typedef unsigned int unsigned_int; + test_integral_limits(unsigned_int(), "unsigned int"); + test_integral_limits(long(), "long"); + typedef unsigned long unsigned_long; + test_integral_limits(unsigned_long(), "unsigned long"); +#ifdef __GNUC__ + typedef long long long_long; + test_integral_limits(long_long(), "long long"); + typedef unsigned long long unsigned_long_long; + test_integral_limits(unsigned_long_long(), "unsigned long long"); +#endif + + test_float_limits(float(), "float"); + test_float_limits(double(), "double"); + typedef long double long_double; + test_float_limits(long_double(), "long double"); + // Some compilers don't pay attention to std:3.6.1/5 and issue a + // warning here if "return 0;" is omitted. + return 0; +}