Boost GIL


promote_integral.hpp
1 // Boost.GIL (Generic Image Library)
2 //
3 // Copyright (c) 2015, Oracle and/or its affiliates.
4 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
5 //
6 // Licensed under the Boost Software License version 1.0.
7 // http://www.boost.org/users/license.html
8 //
9 // Source: Boost.Geometry (aka GGL, Generic Geometry Library)
10 // Modifications: adapted for Boost.GIL
11 // - Rename namespace boost::geometry to boost::gil
12 // - Rename include guards
13 // - Remove support for boost::multiprecision types
14 // - Remove support for 128-bit integer types
15 //
16 #ifndef BOOST_GIL_PROMOTE_INTEGRAL_HPP
17 #define BOOST_GIL_PROMOTE_INTEGRAL_HPP
18 
19 #include <climits>
20 #include <cstddef>
21 #include <type_traits>
22 
23 #include <boost/mpl/begin.hpp>
24 #include <boost/mpl/deref.hpp>
25 #include <boost/mpl/end.hpp>
26 #include <boost/mpl/list.hpp>
27 #include <boost/mpl/next.hpp>
28 
29 namespace boost { namespace gil
30 {
31 
32 namespace detail { namespace promote_integral
33 {
34 
35 // meta-function that returns the bit size of a type
36 template
37 <
38  typename T,
39  bool IsFundamental = std::is_fundamental<T>::type::value
40 >
41 struct bit_size {};
42 
43 // for fundamental types, just return CHAR_BIT * sizeof(T)
44 template <typename T>
45 struct bit_size<T, true> : std::integral_constant<std::size_t, (CHAR_BIT * sizeof(T))> {};
46 
47 template
48 <
49  typename T,
50  typename Iterator,
51  typename EndIterator,
52  std::size_t MinSize
53 >
54 struct promote_to_larger
55 {
56  typedef typename boost::mpl::deref<Iterator>::type current_type;
57 
58  typedef typename std::conditional
59  <
60  (bit_size<current_type>::type::value >= MinSize),
61  current_type,
62  typename promote_to_larger
63  <
64  T,
65  typename boost::mpl::next<Iterator>::type,
66  EndIterator,
67  MinSize
68  >::type
69  >::type type;
70 };
71 
72 // The following specialization is required to finish the loop over
73 // all list elements
74 template <typename T, typename EndIterator, std::size_t MinSize>
75 struct promote_to_larger<T, EndIterator, EndIterator, MinSize>
76 {
77  // if promotion fails, keep the number T
78  // (and cross fingers that overflow will not occur)
79  typedef T type;
80 };
81 
82 }} // namespace detail::promote_integral
83 
116 template
117 <
118  typename T,
119  bool PromoteUnsignedToUnsigned = false,
120  bool UseCheckedInteger = false,
121  bool IsIntegral = std::is_integral<T>::type::value
122 >
124 {
125 private:
126  static bool const is_unsigned = std::is_unsigned<T>::type::value;
127 
128  typedef detail::promote_integral::bit_size<T> bit_size_type;
129 
130  // Define the minimum size (in bits) needed for the promoted type
131  // If T is the input type and P the promoted type, then the
132  // minimum number of bits for P are (below b stands for the number
133  // of bits of T):
134  // * if T is unsigned and P is unsigned: 2 * b
135  // * if T is signed and P is signed: 2 * b - 1
136  // * if T is unsigned and P is signed: 2 * b + 1
137  typedef typename std::conditional
138  <
139  (PromoteUnsignedToUnsigned && is_unsigned),
140  std::integral_constant<std::size_t, (2 * bit_size_type::value)>,
141  typename std::conditional
142  <
143  is_unsigned,
144  std::integral_constant<std::size_t, (2 * bit_size_type::value + 1)>,
145  std::integral_constant<std::size_t, (2 * bit_size_type::value - 1)>
146  >::type
147  >::type min_bit_size_type;
148 
149  // Define the list of signed integral types we are going to use
150  // for promotion
151  typedef boost::mpl::list
152  <
153  short, int, long
154 #if defined(BOOST_HAS_LONG_LONG)
155  , boost::long_long_type
156 #endif
157  > signed_integral_types;
158 
159  // Define the list of unsigned integral types we are going to use
160  // for promotion
161  typedef boost::mpl::list
162  <
163  unsigned short, unsigned int, unsigned long, std::size_t
164 #if defined(BOOST_HAS_LONG_LONG)
165  , boost::ulong_long_type
166 #endif
167  > unsigned_integral_types;
168 
169  // Define the list of integral types that will be used for
170  // promotion (depending in whether we was to promote unsigned to
171  // unsigned or not)
172  typedef typename std::conditional
173  <
174  (is_unsigned && PromoteUnsignedToUnsigned),
175  unsigned_integral_types,
176  signed_integral_types
177  >::type integral_types;
178 
179 public:
180  typedef typename detail::promote_integral::promote_to_larger
181  <
182  T,
183  typename boost::mpl::begin<integral_types>::type,
184  typename boost::mpl::end<integral_types>::type,
185  min_bit_size_type::value
186  >::type type;
187 };
188 
189 
190 template <typename T, bool PromoteUnsignedToUnsigned, bool UseCheckedInteger>
191 class promote_integral
192  <
193  T, PromoteUnsignedToUnsigned, UseCheckedInteger, false
194  >
195 {
196 public:
197  typedef T type;
198 };
199 
200 }} // namespace boost::gil
201 
202 #endif // BOOST_GIL_PROMOTE_INTEGRAL_HPP
Meta-function to define an integral type with size than is (roughly) twice the bit size of T...
Definition: promote_integral.hpp:123