1 // (C) Copyright David Abrahams 2001, Howard Hinnant 2001. 2 // 3 // Distributed under the Boost Software License, Version 1.0. (See 4 // accompanying file LICENSE_1_0.txt or copy at 5 // http://www.boost.org/LICENSE_1_0.txt) 6 // 7 // Template class numeric_traits<Number> -- 8 // 9 // Supplies: 10 // 11 // typedef difference_type -- a type used to represent the difference 12 // between any two values of Number. 13 // 14 // Support: 15 // 1. Not all specializations are supplied 16 // 17 // 2. Use of specializations that are not supplied will cause a 18 // compile-time error 19 // 20 // 3. Users are free to specialize numeric_traits for any type. 21 // 22 // 4. Right now, specializations are only supplied for integer types. 23 // 24 // 5. On implementations which do not supply compile-time constants in 25 // std::numeric_limits<>, only specializations for built-in integer types 26 // are supplied. 27 // 28 // 6. Handling of numbers whose range of representation is at least as 29 // great as boost::intmax_t can cause some differences to be 30 // unrepresentable in difference_type: 31 // 32 // Number difference_type 33 // ------ --------------- 34 // signed Number 35 // unsigned intmax_t 36 // 37 // template <class Number> typename numeric_traits<Number>::difference_type 38 // numeric_distance(Number x, Number y) 39 // computes (y - x), attempting to avoid overflows. 40 // 41 42 // See http://www.boost.org for most recent version including documentation. 43 44 // Revision History 45 // 11 Feb 2001 - Use BOOST_STATIC_CONSTANT (David Abrahams) 46 // 11 Feb 2001 - Rolled back ineffective Borland-specific code 47 // (David Abrahams) 48 // 10 Feb 2001 - Rolled in supposed Borland fixes from John Maddock, but 49 // not seeing any improvement yet (David Abrahams) 50 // 06 Feb 2001 - Factored if_true out into boost/detail/select_type.hpp 51 // (David Abrahams) 52 // 23 Jan 2001 - Fixed logic of difference_type selection, which was 53 // completely wack. In the process, added digit_traits<> 54 // to compute the number of digits in intmax_t even when 55 // not supplied by numeric_limits<>. (David Abrahams) 56 // 21 Jan 2001 - Created (David Abrahams) 57 58 #ifndef BOOST_NUMERIC_TRAITS_HPP_DWA20001901 59 #define BOOST_NUMERIC_TRAITS_HPP_DWA20001901 60 61 #include <cstddef> 62 #include <boost/config.hpp> 63 #include <boost/limits.hpp> 64 #include <boost/cstdint.hpp> 65 #include <boost/type_traits/is_signed.hpp> 66 #include <boost/type_traits/conditional.hpp> 67 #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS 68 #include <boost/static_assert.hpp> 69 #include <boost/type_traits/is_integral.hpp> 70 #endif 71 72 namespace boost { namespace detail { 73 74 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS 75 // digit_traits - compute the number of digits in a built-in integer 76 // type. Needed for implementations on which numeric_limits is not specialized 77 // for some integer types, like __int128 in libstdc++ (gcc). 78 template <class T, bool IsSpecialized = std::numeric_limits<T>::is_specialized> 79 struct digit_traits 80 { 81 BOOST_STATIC_CONSTANT(int, digits = std::numeric_limits<T>::digits); 82 }; 83 84 // numeric_limits is not specialized; compute digits from sizeof(T) 85 template <class T> 86 struct digit_traits<T, false> 87 { 88 BOOST_STATIC_CONSTANT(int, digits = ( 89 sizeof(T) * std::numeric_limits<unsigned char>::digits 90 - (boost::is_signed<T>::value ? 1 : 0)) 91 ); 92 }; 93 #endif 94 95 // Template class integer_traits<Integer> -- traits of various integer types 96 // This should probably be rolled into boost::integer_traits one day, but I 97 // need it to work without <limits> 98 template <class Integer> 99 struct integer_traits 100 { 101 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS 102 private: 103 typedef Integer integer_type; 104 typedef std::numeric_limits<integer_type> x; 105 public: 106 typedef typename boost::conditional< 107 (int(x::is_signed) 108 && (!int(x::is_bounded) 109 // digits is the number of no-sign bits 110 || (int(x::digits) + 1 >= digit_traits<boost::intmax_t>::digits))), 111 Integer, 112 113 typename boost::conditional< 114 (int(x::digits) + 1 < digit_traits<signed int>::digits), 115 signed int, 116 117 typename boost::conditional< 118 (int(x::digits) + 1 < digit_traits<signed long>::digits), 119 signed long, 120 boost::intmax_t 121 >::type 122 >::type 123 >::type difference_type; 124 #else 125 BOOST_STATIC_ASSERT(boost::is_integral<Integer>::value); 126 127 typedef typename boost::conditional< 128 (sizeof(Integer) >= sizeof(intmax_t)), 129 130 boost::conditional< 131 (boost::is_signed<Integer>::value), 132 Integer, 133 boost::intmax_t 134 >, 135 136 boost::conditional< 137 (sizeof(Integer) < sizeof(std::ptrdiff_t)), 138 std::ptrdiff_t, 139 boost::intmax_t 140 > 141 >::type::type difference_type; 142 #endif 143 }; 144 145 // Right now, only supports integers, but should be expanded. 146 template <class Number> 147 struct numeric_traits 148 { 149 typedef typename integer_traits<Number>::difference_type difference_type; 150 }; 151 152 template <class Number> numeric_distance(Number x,Number y)153 inline BOOST_CONSTEXPR typename numeric_traits<Number>::difference_type numeric_distance(Number x, Number y) 154 { 155 typedef typename numeric_traits<Number>::difference_type difference_type; 156 return difference_type(y) - difference_type(x); 157 } 158 }} 159 160 #endif // BOOST_NUMERIC_TRAITS_HPP_DWA20001901 161