Generic Image Library: promote_integral.hpp Source File

###  | #  |

- Main Page
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

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 >
123 class promote_integral
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
boost::gil::promote_integral
Meta-function to define an integral type with size than is (roughly) twice the bit size of T...
Definition: promote_integral.hpp:123