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 <boost/mpl/begin.hpp> 20 #include <boost/mpl/deref.hpp> 21 #include <boost/mpl/end.hpp> 22 #include <boost/mpl/list.hpp> 23 #include <boost/mpl/next.hpp> 24 25 #include <climits> 26 #include <cstddef> 27 #include <type_traits> 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 84 /*! 85 \brief Meta-function to define an integral type with size 86 than is (roughly) twice the bit size of T 87 \ingroup utility 88 \details 89 This meta-function tries to promote the fundamental integral type T 90 to a another integral type with size (roughly) twice the bit size of T. 91 92 To do this, two times the bit size of T is tested against the bit sizes of: 93 short, int, long, boost::long_long_type, boost::int128_t 94 and the one that first matches is chosen. 95 96 For unsigned types the bit size of T is tested against the bit 97 sizes of the types above, if T is promoted to a signed type, or 98 the bit sizes of 99 unsigned short, unsigned int, unsigned long, std::size_t, 100 boost::ulong_long_type, boost::uint128_t 101 if T is promoted to an unsigned type. 102 103 By default an unsigned type is promoted to a signed type. 104 This behavior is controlled by the PromoteUnsignedToUnsigned 105 boolean template parameter, whose default value is "false". 106 To promote an unsigned type to an unsigned type set the value of 107 this template parameter to "true". 108 109 Finally, if the passed type is either a floating-point type or a 110 user-defined type it is returned as is. 111 112 \note boost::long_long_type and boost::ulong_long_type are 113 considered only if the macro BOOST_HAS_LONG_LONG is defined 114 115 */ 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 203