1 //  boost integer.hpp header file  -------------------------------------------//
2 
3 //  Copyright Beman Dawes and Daryle Walker 1999.  Distributed under the Boost
4 //  Software License, Version 1.0. (See accompanying file
5 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 
7 //  See http://www.boost.org/libs/integer for documentation.
8 
9 //  Revision History
10 //   22 Sep 01  Added value-based integer templates. (Daryle Walker)
11 //   01 Apr 01  Modified to use new <boost/limits.hpp> header. (John Maddock)
12 //   30 Jul 00  Add typename syntax fix (Jens Maurer)
13 //   28 Aug 99  Initial version
14 
15 #ifndef BOOST_INTEGER_HPP
16 #define BOOST_INTEGER_HPP
17 
18 #include <boost/integer_fwd.hpp>  // self include
19 
20 #include <boost/integer_traits.hpp>  // for boost::::boost::integer_traits
21 #include <boost/limits.hpp>          // for ::std::numeric_limits
22 #include <boost/cstdint.hpp>         // for boost::int64_t and BOOST_NO_INTEGRAL_INT64_T
23 #include <boost/static_assert.hpp>
24 
25 //
26 // We simply cannot include this header on gcc without getting copious warnings of the kind:
27 //
28 // boost/integer.hpp:77:30: warning: use of C99 long long integer constant
29 //
30 // And yet there is no other reasonable implementation, so we declare this a system header
31 // to suppress these warnings.
32 //
33 #if defined(__GNUC__) && (__GNUC__ >= 4)
34 #pragma GCC system_header
35 #endif
36 
37 namespace boost
38 {
39 
40   //  Helper templates  ------------------------------------------------------//
41 
42   //  fast integers from least integers
43   //  int_fast_t<> works correctly for unsigned too, in spite of the name.
44   template< typename LeastInt >
45   struct int_fast_t
46   {
47      typedef LeastInt fast;
48      typedef fast     type;
49   }; // imps may specialize
50 
51   namespace detail{
52 
53   //  convert category to type
54   template< int Category > struct int_least_helper {}; // default is empty
55   template< int Category > struct uint_least_helper {}; // default is empty
56 
57   //  specializatons: 1=long, 2=int, 3=short, 4=signed char,
58   //     6=unsigned long, 7=unsigned int, 8=unsigned short, 9=unsigned char
59   //  no specializations for 0 and 5: requests for a type > long are in error
60 #ifdef BOOST_HAS_LONG_LONG
61   template<> struct int_least_helper<1> { typedef boost::long_long_type least; };
62 #elif defined(BOOST_HAS_MS_INT64)
63   template<> struct int_least_helper<1> { typedef __int64 least; };
64 #endif
65   template<> struct int_least_helper<2> { typedef long least; };
66   template<> struct int_least_helper<3> { typedef int least; };
67   template<> struct int_least_helper<4> { typedef short least; };
68   template<> struct int_least_helper<5> { typedef signed char least; };
69 #ifdef BOOST_HAS_LONG_LONG
70   template<> struct uint_least_helper<1> { typedef boost::ulong_long_type least; };
71 #elif defined(BOOST_HAS_MS_INT64)
72   template<> struct uint_least_helper<1> { typedef unsigned __int64 least; };
73 #endif
74   template<> struct uint_least_helper<2> { typedef unsigned long least; };
75   template<> struct uint_least_helper<3> { typedef unsigned int least; };
76   template<> struct uint_least_helper<4> { typedef unsigned short least; };
77   template<> struct uint_least_helper<5> { typedef unsigned char least; };
78 
79   template <int Bits>
80   struct exact_signed_base_helper{};
81   template <int Bits>
82   struct exact_unsigned_base_helper{};
83 
84   template <> struct exact_signed_base_helper<sizeof(signed char)* CHAR_BIT> { typedef signed char exact; };
85   template <> struct exact_unsigned_base_helper<sizeof(unsigned char)* CHAR_BIT> { typedef unsigned char exact; };
86 #if USHRT_MAX != UCHAR_MAX
87   template <> struct exact_signed_base_helper<sizeof(short)* CHAR_BIT> { typedef short exact; };
88   template <> struct exact_unsigned_base_helper<sizeof(unsigned short)* CHAR_BIT> { typedef unsigned short exact; };
89 #endif
90 #if UINT_MAX != USHRT_MAX
91   template <> struct exact_signed_base_helper<sizeof(int)* CHAR_BIT> { typedef int exact; };
92   template <> struct exact_unsigned_base_helper<sizeof(unsigned int)* CHAR_BIT> { typedef unsigned int exact; };
93 #endif
94 #if ULONG_MAX != UINT_MAX && ( !defined __TI_COMPILER_VERSION__ || \
95     ( __TI_COMPILER_VERSION__ >= 7000000 && !defined __TI_40BIT_LONG__ ) )
96   template <> struct exact_signed_base_helper<sizeof(long)* CHAR_BIT> { typedef long exact; };
97   template <> struct exact_unsigned_base_helper<sizeof(unsigned long)* CHAR_BIT> { typedef unsigned long exact; };
98 #endif
99 #if defined(BOOST_HAS_LONG_LONG) &&\
100    ((defined(ULLONG_MAX) && (ULLONG_MAX != ULONG_MAX)) ||\
101     (defined(ULONG_LONG_MAX) && (ULONG_LONG_MAX != ULONG_MAX)) ||\
102     (defined(ULONGLONG_MAX) && (ULONGLONG_MAX != ULONG_MAX)) ||\
103     (defined(_ULLONG_MAX) && (_ULLONG_MAX != ULONG_MAX)))
104   template <> struct exact_signed_base_helper<sizeof(boost::long_long_type)* CHAR_BIT> { typedef boost::long_long_type exact; };
105   template <> struct exact_unsigned_base_helper<sizeof(boost::ulong_long_type)* CHAR_BIT> { typedef boost::ulong_long_type exact; };
106 #endif
107 
108 
109   } // namespace detail
110 
111   //  integer templates specifying number of bits  ---------------------------//
112 
113   //  signed
114   template< int Bits >   // bits (including sign) required
115   struct int_t : public boost::detail::exact_signed_base_helper<Bits>
116   {
117       BOOST_STATIC_ASSERT_MSG(Bits <= (int)(sizeof(boost::intmax_t) * CHAR_BIT),
118          "No suitable signed integer type with the requested number of bits is available.");
119       typedef typename boost::detail::int_least_helper
120         <
121 #ifdef BOOST_HAS_LONG_LONG
122           (Bits <= (int)(sizeof(boost::long_long_type) * CHAR_BIT)) +
123 #else
124            1 +
125 #endif
126           (Bits-1 <= ::std::numeric_limits<long>::digits) +
127           (Bits-1 <= ::std::numeric_limits<int>::digits) +
128           (Bits-1 <= ::std::numeric_limits<short>::digits) +
129           (Bits-1 <= ::std::numeric_limits<signed char>::digits)
130         >::least  least;
131       typedef typename int_fast_t<least>::type  fast;
132   };
133 
134   //  unsigned
135   template< int Bits >   // bits required
136   struct uint_t : public boost::detail::exact_unsigned_base_helper<Bits>
137   {
138      BOOST_STATIC_ASSERT_MSG(Bits <= (int)(sizeof(boost::uintmax_t) * CHAR_BIT),
139          "No suitable unsigned integer type with the requested number of bits is available.");
140 #if (defined(__BORLANDC__) || defined(__CODEGEAR__)) && defined(BOOST_NO_INTEGRAL_INT64_T)
141      // It's really not clear why this workaround should be needed... shrug I guess!  JM
142      BOOST_STATIC_CONSTANT(int, s =
143            6 +
144           (Bits <= ::std::numeric_limits<unsigned long>::digits) +
145           (Bits <= ::std::numeric_limits<unsigned int>::digits) +
146           (Bits <= ::std::numeric_limits<unsigned short>::digits) +
147           (Bits <= ::std::numeric_limits<unsigned char>::digits));
148      typedef typename detail::int_least_helper< ::boost::uint_t<Bits>::s>::least least;
149 #else
150       typedef typename boost::detail::uint_least_helper
151         <
152 #ifdef BOOST_HAS_LONG_LONG
153           (Bits <= (int)(sizeof(boost::long_long_type) * CHAR_BIT)) +
154 #else
155            1 +
156 #endif
157           (Bits <= ::std::numeric_limits<unsigned long>::digits) +
158           (Bits <= ::std::numeric_limits<unsigned int>::digits) +
159           (Bits <= ::std::numeric_limits<unsigned short>::digits) +
160           (Bits <= ::std::numeric_limits<unsigned char>::digits)
161         >::least  least;
162 #endif
163       typedef typename int_fast_t<least>::type  fast;
164       // int_fast_t<> works correctly for unsigned too, in spite of the name.
165   };
166 
167   //  integer templates specifying extreme value  ----------------------------//
168 
169   //  signed
170 #if !defined(BOOST_NO_INTEGRAL_INT64_T) && !defined(BOOST_NO_INT64_T) && defined(BOOST_HAS_LONG_LONG)
171   template< boost::long_long_type MaxValue >   // maximum value to require support
172 #else
173   template< long MaxValue >   // maximum value to require support
174 #endif
175   struct int_max_value_t
176   {
177       typedef typename boost::detail::int_least_helper
178         <
179 #if !defined(BOOST_NO_INTEGRAL_INT64_T) && !defined(BOOST_NO_INT64_T) && defined(BOOST_HAS_LONG_LONG)
180           (MaxValue <= ::boost::integer_traits<boost::long_long_type>::const_max) +
181 #else
182            1 +
183 #endif
184           (MaxValue <= ::boost::integer_traits<long>::const_max) +
185           (MaxValue <= ::boost::integer_traits<int>::const_max) +
186           (MaxValue <= ::boost::integer_traits<short>::const_max) +
187           (MaxValue <= ::boost::integer_traits<signed char>::const_max)
188         >::least  least;
189       typedef typename int_fast_t<least>::type  fast;
190   };
191 
192 #if !defined(BOOST_NO_INTEGRAL_INT64_T) && !defined(BOOST_NO_INT64_T) && defined(BOOST_HAS_LONG_LONG)
193   template< boost::long_long_type MinValue >   // minimum value to require support
194 #else
195   template< long MinValue >   // minimum value to require support
196 #endif
197   struct int_min_value_t
198   {
199       typedef typename boost::detail::int_least_helper
200         <
201 #if !defined(BOOST_NO_INTEGRAL_INT64_T) && !defined(BOOST_NO_INT64_T) && defined(BOOST_HAS_LONG_LONG)
202           (MinValue >= ::boost::integer_traits<boost::long_long_type>::const_min) +
203 #else
204            1 +
205 #endif
206           (MinValue >= ::boost::integer_traits<long>::const_min) +
207           (MinValue >= ::boost::integer_traits<int>::const_min) +
208           (MinValue >= ::boost::integer_traits<short>::const_min) +
209           (MinValue >= ::boost::integer_traits<signed char>::const_min)
210         >::least  least;
211       typedef typename int_fast_t<least>::type  fast;
212   };
213 
214   //  unsigned
215 #if !defined(BOOST_NO_INTEGRAL_INT64_T) && defined(BOOST_HAS_LONG_LONG)
216   template< boost::ulong_long_type MaxValue >   // minimum value to require support
217 #else
218   template< unsigned long MaxValue >   // minimum value to require support
219 #endif
220   struct uint_value_t
221   {
222 #if (defined(__BORLANDC__) || defined(__CODEGEAR__))
223      // It's really not clear why this workaround should be needed... shrug I guess!  JM
224 #if defined(BOOST_NO_INTEGRAL_INT64_T)
225       BOOST_STATIC_CONSTANT(unsigned, which =
226            1 +
227           (MaxValue <= ::boost::integer_traits<unsigned long>::const_max) +
228           (MaxValue <= ::boost::integer_traits<unsigned int>::const_max) +
229           (MaxValue <= ::boost::integer_traits<unsigned short>::const_max) +
230           (MaxValue <= ::boost::integer_traits<unsigned char>::const_max));
231       typedef typename detail::int_least_helper< ::boost::uint_value_t<MaxValue>::which>::least least;
232 #else // BOOST_NO_INTEGRAL_INT64_T
233       BOOST_STATIC_CONSTANT(unsigned, which =
234            1 +
235           (MaxValue <= ::boost::integer_traits<boost::ulong_long_type>::const_max) +
236           (MaxValue <= ::boost::integer_traits<unsigned long>::const_max) +
237           (MaxValue <= ::boost::integer_traits<unsigned int>::const_max) +
238           (MaxValue <= ::boost::integer_traits<unsigned short>::const_max) +
239           (MaxValue <= ::boost::integer_traits<unsigned char>::const_max));
240       typedef typename detail::uint_least_helper< ::boost::uint_value_t<MaxValue>::which>::least least;
241 #endif // BOOST_NO_INTEGRAL_INT64_T
242 #else
243       typedef typename boost::detail::uint_least_helper
244         <
245 #if !defined(BOOST_NO_INTEGRAL_INT64_T) && defined(BOOST_HAS_LONG_LONG)
246           (MaxValue <= ::boost::integer_traits<boost::ulong_long_type>::const_max) +
247 #else
248            1 +
249 #endif
250           (MaxValue <= ::boost::integer_traits<unsigned long>::const_max) +
251           (MaxValue <= ::boost::integer_traits<unsigned int>::const_max) +
252           (MaxValue <= ::boost::integer_traits<unsigned short>::const_max) +
253           (MaxValue <= ::boost::integer_traits<unsigned char>::const_max)
254         >::least  least;
255 #endif
256       typedef typename int_fast_t<least>::type  fast;
257   };
258 
259 
260 } // namespace boost
261 
262 #endif  // BOOST_INTEGER_HPP
263