source: NonGTP/Boost/boost/detail/numeric_traits.hpp @ 857

Revision 857, 6.8 KB checked in by igarcia, 19 years ago (diff)
Line 
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 <boost/config.hpp>
62# include <boost/cstdint.hpp>
63# include <boost/static_assert.hpp>
64# include <boost/type_traits.hpp>
65# include <boost/detail/select_type.hpp>
66# include <boost/limits.hpp>
67
68namespace boost { namespace detail {
69
70  // Template class is_signed -- determine whether a numeric type is signed
71  // Requires that T is constructable from the literals -1 and 0.  Compile-time
72  // error results if that requirement is not met (and thus signedness is not
73  // likely to have meaning for that type).
74  template <class Number>
75  struct is_signed
76  {
77#if defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) || defined(BOOST_MSVC) && BOOST_MSVC <= 1300
78    BOOST_STATIC_CONSTANT(bool, value = (Number(-1) < Number(0)));
79#else
80    BOOST_STATIC_CONSTANT(bool, value = std::numeric_limits<Number>::is_signed);
81#endif
82  };
83
84# ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
85  // digit_traits - compute the number of digits in a built-in integer
86  // type. Needed for implementations on which numeric_limits is not specialized
87  // for intmax_t (e.g. VC6).
88  template <bool is_specialized> struct digit_traits_select;
89
90  // numeric_limits is specialized; just select that version of digits
91  template <> struct digit_traits_select<true>
92  {
93      template <class T> struct traits
94      {
95          BOOST_STATIC_CONSTANT(int, digits = std::numeric_limits<T>::digits);
96      };
97  };
98
99  // numeric_limits is not specialized; compute digits from sizeof(T)
100  template <> struct digit_traits_select<false>
101  {
102      template <class T> struct traits
103      {
104          BOOST_STATIC_CONSTANT(int, digits = (
105              sizeof(T) * std::numeric_limits<unsigned char>::digits
106              - (is_signed<T>::value ? 1 : 0))
107              );
108      };
109  };
110
111  // here's the "usable" template
112  template <class T> struct digit_traits
113  {
114      typedef digit_traits_select<
115                ::std::numeric_limits<T>::is_specialized> selector;
116      typedef typename selector::template traits<T> traits;
117      BOOST_STATIC_CONSTANT(int, digits = traits::digits);
118  };
119#endif
120
121  // Template class integer_traits<Integer> -- traits of various integer types
122  // This should probably be rolled into boost::integer_traits one day, but I
123  // need it to work without <limits>
124  template <class Integer>
125  struct integer_traits
126  {
127# ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
128   private:
129      typedef Integer integer_type;
130      typedef std::numeric_limits<integer_type> x;
131#   if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
132      // for some reason, MSVC asserts when it shouldn't unless we make these
133      // local definitions
134      BOOST_STATIC_CONSTANT(bool, is_integer = x::is_integer);
135      BOOST_STATIC_CONSTANT(bool, is_specialized = x::is_specialized);
136     
137      BOOST_STATIC_ASSERT(is_integer);
138      BOOST_STATIC_ASSERT(is_specialized);
139#   endif
140   public:
141      typedef typename
142      if_true<(int(x::is_signed)
143              && (!int(x::is_bounded)
144                 // digits is the number of no-sign bits
145                  || (int(x::digits) + 1 >= digit_traits<boost::intmax_t>::digits)))>::template then<
146        Integer,
147         
148      typename if_true<(int(x::digits) + 1 < digit_traits<signed int>::digits)>::template then<
149        signed int,
150
151      typename if_true<(int(x::digits) + 1 < digit_traits<signed long>::digits)>::template then<
152        signed long,
153
154   // else
155        intmax_t
156      >::type>::type>::type difference_type;
157#else
158      BOOST_STATIC_ASSERT(boost::is_integral<Integer>::value);
159
160      typedef typename
161      if_true<(sizeof(Integer) >= sizeof(intmax_t))>::template then<
162               
163        typename if_true<(is_signed<Integer>::value)>::template then<
164          Integer,
165          intmax_t
166        >::type,
167
168        typename if_true<(sizeof(Integer) < sizeof(std::ptrdiff_t))>::template then<
169          std::ptrdiff_t,
170          intmax_t
171        >::type
172      >::type difference_type;
173# endif
174  };
175
176  // Right now, only supports integers, but should be expanded.
177  template <class Number>
178  struct numeric_traits
179  {
180      typedef typename integer_traits<Number>::difference_type difference_type;
181  };
182
183  template <class Number>
184  typename numeric_traits<Number>::difference_type numeric_distance(Number x, Number y)
185  {
186      typedef typename numeric_traits<Number>::difference_type difference_type;
187      return difference_type(y) - difference_type(x);
188  }
189}}
190
191#endif // BOOST_NUMERIC_TRAITS_HPP_DWA20001901
Note: See TracBrowser for help on using the repository browser.