Brian Silverman | 2987761 | 2018-08-05 00:42:41 -0700 | [diff] [blame^] | 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> |
| 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 |