File indexing completed on 2025-01-18 09:38:37
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef BOOST_INTRUSIVE_DETAIL_MATH_HPP
0014 #define BOOST_INTRUSIVE_DETAIL_MATH_HPP
0015
0016 #ifndef BOOST_CONFIG_HPP
0017 # include <boost/config.hpp>
0018 #endif
0019
0020 #if defined(BOOST_HAS_PRAGMA_ONCE)
0021 # pragma once
0022 #endif
0023
0024 #include <cstddef>
0025 #include <climits>
0026 #include <boost/intrusive/detail/mpl.hpp>
0027 #include <cstring>
0028
0029 namespace boost {
0030 namespace intrusive {
0031 namespace detail {
0032
0033
0034
0035
0036
0037 #if defined(_MSC_VER) && (_MSC_VER >= 1300)
0038
0039 }}}
0040
0041
0042
0043 #if defined(_M_X64) || defined(_M_AMD64) || defined(_M_IA64)
0044 #define BOOST_INTRUSIVE_BSR_INTRINSIC_64_BIT
0045 #endif
0046
0047 #ifndef __INTRIN_H_
0048 #ifdef __cplusplus
0049 extern "C" {
0050 #endif
0051
0052 #if defined(BOOST_INTRUSIVE_BSR_INTRINSIC_64_BIT)
0053 unsigned char _BitScanReverse64(unsigned long *index, unsigned __int64 mask);
0054 #pragma intrinsic(_BitScanReverse64)
0055 #else
0056 unsigned char _BitScanReverse(unsigned long *index, unsigned long mask);
0057 #pragma intrinsic(_BitScanReverse)
0058 #endif
0059
0060 #ifdef __cplusplus
0061 }
0062 #endif
0063 #endif
0064
0065 #ifdef BOOST_INTRUSIVE_BSR_INTRINSIC_64_BIT
0066 #define BOOST_INTRUSIVE_BSR_INTRINSIC _BitScanReverse64
0067 #undef BOOST_INTRUSIVE_BSR_INTRINSIC_64_BIT
0068 #else
0069 #define BOOST_INTRUSIVE_BSR_INTRINSIC _BitScanReverse
0070 #endif
0071
0072 namespace boost {
0073 namespace intrusive {
0074 namespace detail {
0075
0076 inline std::size_t floor_log2 (std::size_t x)
0077 {
0078 unsigned long log2;
0079 BOOST_INTRUSIVE_BSR_INTRINSIC( &log2, x );
0080 return static_cast<std::size_t>(log2);
0081 }
0082
0083 #undef BOOST_INTRUSIVE_BSR_INTRINSIC
0084
0085 #elif defined(__GNUC__) && ((__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
0086
0087
0088 template<class Uint>
0089 struct builtin_clz_dispatch;
0090
0091 #if defined(BOOST_HAS_LONG_LONG)
0092 template<>
0093 struct builtin_clz_dispatch< ::boost::ulong_long_type >
0094 {
0095 static ::boost::ulong_long_type call(::boost::ulong_long_type n)
0096 { return (::boost::ulong_long_type)__builtin_clzll(n); }
0097 };
0098 #endif
0099
0100 template<>
0101 struct builtin_clz_dispatch<unsigned long>
0102 {
0103 static unsigned long call(unsigned long n)
0104 { return (unsigned long)__builtin_clzl(n); }
0105 };
0106
0107 template<>
0108 struct builtin_clz_dispatch<unsigned int>
0109 {
0110 static unsigned int call(unsigned int n)
0111 { return (unsigned int)__builtin_clz(n); }
0112 };
0113
0114 inline std::size_t floor_log2(std::size_t n)
0115 {
0116 return sizeof(std::size_t)*CHAR_BIT - std::size_t(1) - builtin_clz_dispatch<std::size_t>::call(n);
0117 }
0118
0119 #else
0120
0121
0122
0123
0124
0125 inline std::size_t floor_log2_get_shift(std::size_t n, true_ )
0126 { return n >> 1; }
0127
0128 inline std::size_t floor_log2_get_shift(std::size_t n, false_ )
0129 { return (n >> 1) + ((n & 1u) & (n != 1)); }
0130
0131 template<std::size_t N>
0132 inline std::size_t floor_log2 (std::size_t x, integral_constant<std::size_t, N>)
0133 {
0134 const std::size_t Bits = N;
0135 const bool Size_t_Bits_Power_2= !(Bits & (Bits-1));
0136
0137 std::size_t n = x;
0138 std::size_t log2 = 0;
0139
0140 std::size_t remaining_bits = Bits;
0141 std::size_t shift = floor_log2_get_shift(remaining_bits, bool_<Size_t_Bits_Power_2>());
0142 while(shift){
0143 std::size_t tmp = n >> shift;
0144 if (tmp){
0145 log2 += shift, n = tmp;
0146 }
0147 shift = floor_log2_get_shift(shift, bool_<Size_t_Bits_Power_2>());
0148 }
0149
0150 return log2;
0151 }
0152
0153 inline std::size_t floor_log2 (std::size_t x)
0154 {
0155 const std::size_t Bits = sizeof(std::size_t)*CHAR_BIT;
0156 return floor_log2(x, integral_constant<std::size_t, Bits>());
0157 }
0158
0159 #endif
0160
0161
0162
0163 inline float fast_log2 (float val)
0164 {
0165 unsigned x;
0166 std::memcpy(&x, &val, sizeof(float));
0167 const int log_2 = int((x >> 23) & 255) - 128;
0168 x &= ~(unsigned(255u) << 23u);
0169 x += unsigned(127) << 23u;
0170 std::memcpy(&val, &x, sizeof(float));
0171
0172
0173
0174 val = ((-1.f/3.f) * val + 2.f) * val - (2.f/3.f);
0175 return val + static_cast<float>(log_2);
0176 }
0177
0178 inline bool is_pow2(std::size_t x)
0179 { return (x & (x-1)) == 0; }
0180
0181 template<std::size_t N>
0182 struct static_is_pow2
0183 {
0184 static const bool value = (N & (N-1)) == 0;
0185 };
0186
0187 inline std::size_t ceil_log2 (std::size_t x)
0188 {
0189 return static_cast<std::size_t>(!(is_pow2)(x)) + floor_log2(x);
0190 }
0191
0192 inline std::size_t ceil_pow2 (std::size_t x)
0193 {
0194 return std::size_t(1u) << (ceil_log2)(x);
0195 }
0196
0197 inline std::size_t previous_or_equal_pow2(std::size_t x)
0198 {
0199 return std::size_t(1u) << floor_log2(x);
0200 }
0201
0202 template<class SizeType, std::size_t N>
0203 struct numbits_eq
0204 {
0205 static const bool value = sizeof(SizeType)*CHAR_BIT == N;
0206 };
0207
0208 template<class SizeType, class Enabler = void >
0209 struct sqrt2_pow_max;
0210
0211 template <class SizeType>
0212 struct sqrt2_pow_max<SizeType, typename voider<typename enable_if< numbits_eq<SizeType, 32> >::type>::type>
0213 {
0214 static const SizeType value = 0xb504f334;
0215 static const std::size_t pow = 31;
0216 };
0217
0218 #ifndef BOOST_NO_INT64_T
0219
0220 template <class SizeType>
0221 struct sqrt2_pow_max<SizeType, typename voider<typename enable_if< numbits_eq<SizeType, 64> >::type>::type>
0222 {
0223 static const SizeType value = 0xb504f333f9de6484ull;
0224 static const std::size_t pow = 63;
0225 };
0226
0227 #endif
0228
0229
0230
0231 inline std::size_t sqrt2_pow_2xplus1 (std::size_t x)
0232 {
0233 const std::size_t value = (std::size_t)sqrt2_pow_max<std::size_t>::value;
0234 const std::size_t pow = (std::size_t)sqrt2_pow_max<std::size_t>::pow;
0235 return (value >> (pow - x)) + 1;
0236 }
0237
0238 }
0239 }
0240 }
0241
0242 #endif