File indexing completed on 2025-01-18 09:51:37
0001 #ifndef BOOST_NUMERIC_UTILITY_HPP
0002 #define BOOST_NUMERIC_UTILITY_HPP
0003
0004
0005
0006
0007
0008
0009
0010 #include <cstdint> // intmax_t, uintmax_t, uint8_t, ...
0011 #include <algorithm>
0012 #include <type_traits> // conditional
0013 #include <limits>
0014 #include <cassert>
0015 #include <utility> // pair
0016
0017 #include <boost/integer.hpp> // (u)int_t<>::least, exact
0018
0019 namespace boost {
0020 namespace safe_numerics {
0021 namespace utility {
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 template <typename... Ts>
0035 struct [[deprecated]] print_types {};
0036
0037
0038
0039 template<int N>
0040 struct print_value {
0041 enum test : char {
0042 value = N < 0 ? N - 256 : N + 256
0043 };
0044 };
0045
0046
0047
0048 template <typename T>
0049 struct static_test{};
0050
0051 template <>
0052 struct static_test<std::false_type>{
0053 [[deprecated]] static_test(){}
0054 };
0055
0056 template<typename T>
0057 using static_warning = static_test<T>;
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072 template<typename T>
0073 using bits_type = std::integral_constant<
0074 int,
0075 std::numeric_limits<T>::digits
0076 + (std::numeric_limits<T>::is_signed ? 1 : 0)
0077 >;
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110 namespace ilog2_detail {
0111
0112 template<int N>
0113 constexpr inline unsigned int ilog2(const typename boost::uint_t<N>::exact & t){
0114 using half_type = typename boost::uint_t<N/2>::exact;
0115 const half_type upper_half = static_cast<half_type>(t >> N/2);
0116 const half_type lower_half = static_cast<half_type>(t);
0117 return upper_half == 0 ? ilog2<N/2>(lower_half) : N/2 + ilog2<N/2>(upper_half);
0118 }
0119 template<>
0120 constexpr inline unsigned int ilog2<8>(const typename boost::uint_t<8>::exact & t){
0121 #define LT(n) n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n
0122 const char LogTable256[256] = {
0123 static_cast<char>(-1), 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
0124 LT(4), LT(5), LT(5), LT(6), LT(6), LT(6), LT(6),
0125 LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7)
0126 };
0127 return LogTable256[t];
0128 }
0129
0130 }
0131
0132 template<typename T>
0133 constexpr inline unsigned int ilog2(const T & t){
0134
0135
0136 if(t == 0)
0137 return 0;
0138 return ilog2_detail::ilog2<bits_type<T>::value>(
0139 static_cast<
0140 typename boost::uint_t<
0141 bits_type<T>::value
0142 >::least
0143 >(t)
0144 );
0145 }
0146
0147
0148
0149 template<typename T>
0150 constexpr inline unsigned int significant_bits(const T & t){
0151 return 1 + ((t < 0) ? ilog2(~t) : ilog2(t));
0152 }
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175 template <class T>
0176
0177
0178
0179 constexpr inline T max(
0180 const T & lhs,
0181 const T & rhs
0182 ){
0183 return lhs > rhs ? lhs : rhs;
0184 }
0185
0186
0187
0188 template<
0189 std::intmax_t Min,
0190 std::intmax_t Max
0191 >
0192 using signed_stored_type = typename boost::int_t<
0193 max(
0194 significant_bits(Min),
0195 significant_bits(Max)
0196 ) + 1
0197 >::least ;
0198
0199
0200
0201 template<
0202 std::uintmax_t Min,
0203 std::uintmax_t Max
0204 >
0205
0206 using unsigned_stored_type = typename boost::uint_t<
0207 significant_bits(Max)
0208 >::least;
0209
0210
0211
0212
0213
0214
0215
0216 template<typename T>
0217 constexpr inline std::pair<T, T>
0218 minmax(const std::initializer_list<T> & l){
0219 assert(l.size() > 0);
0220 const T * minimum = l.begin();
0221 const T * maximum = l.begin();
0222 for(const T * i = l.begin(); i != l.end(); ++i){
0223 if(*i < * minimum)
0224 minimum = i;
0225 else
0226 if(* maximum < *i)
0227 maximum = i;
0228 }
0229 return std::pair<T, T>{* minimum, * maximum};
0230 }
0231
0232
0233
0234
0235
0236
0237
0238 template<typename T>
0239 constexpr inline T round_out(const T & t){
0240 if(t >= 0){
0241 const std::uint8_t sb = utility::significant_bits(t);
0242 return (sb < sizeof(T) * 8)
0243 ? ((T)1 << sb) - 1
0244 : std::numeric_limits<T>::max();
0245 }
0246 else{
0247 const std::uint8_t sb = utility::significant_bits(~t);
0248 return (sb < sizeof(T) * 8)
0249 ? ~(((T)1 << sb) - 1)
0250 : std::numeric_limits<T>::min();
0251 }
0252 }
0253
0254 }
0255 }
0256 }
0257
0258 #endif