sl@0: // (C) Copyright David Abrahams 2001, Howard Hinnant 2001. sl@0: // sl@0: // Distributed under the Boost Software License, Version 1.0. (See sl@0: // accompanying file LICENSE_1_0.txt or copy at sl@0: // http://www.boost.org/LICENSE_1_0.txt) sl@0: // sl@0: // Template class numeric_traits -- sl@0: // sl@0: // Supplies: sl@0: // sl@0: // typedef difference_type -- a type used to represent the difference sl@0: // between any two values of Number. sl@0: // sl@0: // Support: sl@0: // 1. Not all specializations are supplied sl@0: // sl@0: // 2. Use of specializations that are not supplied will cause a sl@0: // compile-time error sl@0: // sl@0: // 3. Users are free to specialize numeric_traits for any type. sl@0: // sl@0: // 4. Right now, specializations are only supplied for integer types. sl@0: // sl@0: // 5. On implementations which do not supply compile-time constants in sl@0: // std::numeric_limits<>, only specializations for built-in integer types sl@0: // are supplied. sl@0: // sl@0: // 6. Handling of numbers whose range of representation is at least as sl@0: // great as boost::intmax_t can cause some differences to be sl@0: // unrepresentable in difference_type: sl@0: // sl@0: // Number difference_type sl@0: // ------ --------------- sl@0: // signed Number sl@0: // unsigned intmax_t sl@0: // sl@0: // template typename numeric_traits::difference_type sl@0: // numeric_distance(Number x, Number y) sl@0: // computes (y - x), attempting to avoid overflows. sl@0: // sl@0: sl@0: // See http://www.boost.org for most recent version including documentation. sl@0: sl@0: // Revision History sl@0: // 11 Feb 2001 - Use BOOST_STATIC_CONSTANT (David Abrahams) sl@0: // 11 Feb 2001 - Rolled back ineffective Borland-specific code sl@0: // (David Abrahams) sl@0: // 10 Feb 2001 - Rolled in supposed Borland fixes from John Maddock, but sl@0: // not seeing any improvement yet (David Abrahams) sl@0: // 06 Feb 2001 - Factored if_true out into boost/detail/select_type.hpp sl@0: // (David Abrahams) sl@0: // 23 Jan 2001 - Fixed logic of difference_type selection, which was sl@0: // completely wack. In the process, added digit_traits<> sl@0: // to compute the number of digits in intmax_t even when sl@0: // not supplied by numeric_limits<>. (David Abrahams) sl@0: // 21 Jan 2001 - Created (David Abrahams) sl@0: sl@0: #ifndef BOOST_NUMERIC_TRAITS_HPP_DWA20001901 sl@0: # define BOOST_NUMERIC_TRAITS_HPP_DWA20001901 sl@0: sl@0: # include sl@0: # include sl@0: # include sl@0: # include sl@0: # include sl@0: # include sl@0: sl@0: namespace boost { namespace detail { sl@0: sl@0: // Template class is_signed -- determine whether a numeric type is signed sl@0: // Requires that T is constructable from the literals -1 and 0. Compile-time sl@0: // error results if that requirement is not met (and thus signedness is not sl@0: // likely to have meaning for that type). sl@0: template sl@0: struct is_signed sl@0: { sl@0: #if defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) || defined(BOOST_MSVC) && BOOST_MSVC <= 1300 sl@0: BOOST_STATIC_CONSTANT(bool, value = (Number(-1) < Number(0))); sl@0: #else sl@0: BOOST_STATIC_CONSTANT(bool, value = std::numeric_limits::is_signed); sl@0: #endif sl@0: }; sl@0: sl@0: # ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS sl@0: // digit_traits - compute the number of digits in a built-in integer sl@0: // type. Needed for implementations on which numeric_limits is not specialized sl@0: // for intmax_t (e.g. VC6). sl@0: template struct digit_traits_select; sl@0: sl@0: // numeric_limits is specialized; just select that version of digits sl@0: template <> struct digit_traits_select sl@0: { sl@0: template struct traits sl@0: { sl@0: BOOST_STATIC_CONSTANT(int, digits = std::numeric_limits::digits); sl@0: }; sl@0: }; sl@0: sl@0: // numeric_limits is not specialized; compute digits from sizeof(T) sl@0: template <> struct digit_traits_select sl@0: { sl@0: template struct traits sl@0: { sl@0: BOOST_STATIC_CONSTANT(int, digits = ( sl@0: sizeof(T) * std::numeric_limits::digits sl@0: - (is_signed::value ? 1 : 0)) sl@0: ); sl@0: }; sl@0: }; sl@0: sl@0: // here's the "usable" template sl@0: template struct digit_traits sl@0: { sl@0: typedef digit_traits_select< sl@0: ::std::numeric_limits::is_specialized> selector; sl@0: typedef typename selector::template traits traits; sl@0: BOOST_STATIC_CONSTANT(int, digits = traits::digits); sl@0: }; sl@0: #endif sl@0: sl@0: // Template class integer_traits -- traits of various integer types sl@0: // This should probably be rolled into boost::integer_traits one day, but I sl@0: // need it to work without sl@0: template sl@0: struct integer_traits sl@0: { sl@0: # ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS sl@0: private: sl@0: typedef Integer integer_type; sl@0: typedef std::numeric_limits x; sl@0: # if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 sl@0: // for some reason, MSVC asserts when it shouldn't unless we make these sl@0: // local definitions sl@0: BOOST_STATIC_CONSTANT(bool, is_integer = x::is_integer); sl@0: BOOST_STATIC_CONSTANT(bool, is_specialized = x::is_specialized); sl@0: sl@0: BOOST_STATIC_ASSERT(is_integer); sl@0: BOOST_STATIC_ASSERT(is_specialized); sl@0: # endif sl@0: public: sl@0: typedef typename sl@0: if_true<(int(x::is_signed) sl@0: && (!int(x::is_bounded) sl@0: // digits is the number of no-sign bits sl@0: || (int(x::digits) + 1 >= digit_traits::digits)))>::template then< sl@0: Integer, sl@0: sl@0: typename if_true<(int(x::digits) + 1 < digit_traits::digits)>::template then< sl@0: signed int, sl@0: sl@0: typename if_true<(int(x::digits) + 1 < digit_traits::digits)>::template then< sl@0: signed long, sl@0: sl@0: // else sl@0: intmax_t sl@0: >::type>::type>::type difference_type; sl@0: #else sl@0: BOOST_STATIC_ASSERT(boost::is_integral::value); sl@0: sl@0: typedef typename sl@0: if_true<(sizeof(Integer) >= sizeof(intmax_t))>::template then< sl@0: sl@0: typename if_true<(is_signed::value)>::template then< sl@0: Integer, sl@0: intmax_t sl@0: >::type, sl@0: sl@0: typename if_true<(sizeof(Integer) < sizeof(std::ptrdiff_t))>::template then< sl@0: std::ptrdiff_t, sl@0: intmax_t sl@0: >::type sl@0: >::type difference_type; sl@0: # endif sl@0: }; sl@0: sl@0: // Right now, only supports integers, but should be expanded. sl@0: template sl@0: struct numeric_traits sl@0: { sl@0: typedef typename integer_traits::difference_type difference_type; sl@0: }; sl@0: sl@0: template sl@0: typename numeric_traits::difference_type numeric_distance(Number x, Number y) sl@0: { sl@0: typedef typename numeric_traits::difference_type difference_type; sl@0: return difference_type(y) - difference_type(x); sl@0: } sl@0: }} sl@0: sl@0: #endif // BOOST_NUMERIC_TRAITS_HPP_DWA20001901