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