###  | #  |

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>
121 class promote_integral
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
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:122
boost
defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE)
Definition: algorithm.hpp:36