annotate DEPENDENCIES/generic/include/boost/intrusive/detail/math.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents f46d142149f5
children
rev   line source
Chris@102 1 /////////////////////////////////////////////////////////////////////////////
Chris@102 2 //
Chris@102 3 // (C) Copyright Ion Gaztanaga 2014-2014
Chris@102 4 //
Chris@102 5 // Distributed under the Boost Software License, Version 1.0.
Chris@102 6 // (See accompanying file LICENSE_1_0.txt or copy at
Chris@102 7 // http://www.boost.org/LICENSE_1_0.txt)
Chris@102 8 //
Chris@102 9 // See http://www.boost.org/libs/intrusive for documentation.
Chris@102 10 //
Chris@102 11 /////////////////////////////////////////////////////////////////////////////
Chris@102 12
Chris@102 13 #ifndef BOOST_INTRUSIVE_DETAIL_MATH_HPP
Chris@102 14 #define BOOST_INTRUSIVE_DETAIL_MATH_HPP
Chris@102 15
Chris@102 16 #ifndef BOOST_CONFIG_HPP
Chris@102 17 # include <boost/config.hpp>
Chris@102 18 #endif
Chris@102 19
Chris@102 20 #if defined(BOOST_HAS_PRAGMA_ONCE)
Chris@102 21 # pragma once
Chris@102 22 #endif
Chris@102 23
Chris@102 24 #include <cstddef>
Chris@102 25 #include <climits>
Chris@102 26
Chris@102 27 namespace boost {
Chris@102 28 namespace intrusive {
Chris@102 29 namespace detail {
Chris@102 30
Chris@102 31 ///////////////////////////
Chris@102 32 // floor_log2 Dispatcher
Chris@102 33 ////////////////////////////
Chris@102 34
Chris@102 35 #if defined(_MSC_VER) && (_MSC_VER >= 1300)
Chris@102 36
Chris@102 37 }}} //namespace boost::intrusive::detail
Chris@102 38
Chris@102 39 //Use _BitScanReverseXX intrinsics
Chris@102 40
Chris@102 41 #if defined(_M_X64) || defined(_M_AMD64) || defined(_M_IA64) //64 bit target
Chris@102 42 #define BOOST_INTRUSIVE_BSR_INTRINSIC_64_BIT
Chris@102 43 #endif
Chris@102 44
Chris@102 45 #ifndef __INTRIN_H_ // Avoid including any windows system header
Chris@102 46 #ifdef __cplusplus
Chris@102 47 extern "C" {
Chris@102 48 #endif // __cplusplus
Chris@102 49
Chris@102 50 #if defined(BOOST_INTRUSIVE_BSR_INTRINSIC_64_BIT) //64 bit target
Chris@102 51 unsigned char _BitScanReverse64(unsigned long *index, unsigned __int64 mask);
Chris@102 52 #pragma intrinsic(_BitScanReverse64)
Chris@102 53 #else //32 bit target
Chris@102 54 unsigned char _BitScanReverse(unsigned long *index, unsigned long mask);
Chris@102 55 #pragma intrinsic(_BitScanReverse)
Chris@102 56 #endif
Chris@102 57
Chris@102 58 #ifdef __cplusplus
Chris@102 59 }
Chris@102 60 #endif // __cplusplus
Chris@102 61 #endif // __INTRIN_H_
Chris@102 62
Chris@102 63 #ifdef BOOST_INTRUSIVE_BSR_INTRINSIC_64_BIT
Chris@102 64 #define BOOST_INTRUSIVE_BSR_INTRINSIC _BitScanReverse64
Chris@102 65 #undef BOOST_INTRUSIVE_BSR_INTRINSIC_64_BIT
Chris@102 66 #else
Chris@102 67 #define BOOST_INTRUSIVE_BSR_INTRINSIC _BitScanReverse
Chris@102 68 #endif
Chris@102 69
Chris@102 70 namespace boost {
Chris@102 71 namespace intrusive {
Chris@102 72 namespace detail {
Chris@102 73
Chris@102 74 inline std::size_t floor_log2 (std::size_t x)
Chris@102 75 {
Chris@102 76 unsigned long log2;
Chris@102 77 BOOST_INTRUSIVE_BSR_INTRINSIC( &log2, (unsigned long)x );
Chris@102 78 return log2;
Chris@102 79 }
Chris@102 80
Chris@102 81 #undef BOOST_INTRUSIVE_BSR_INTRINSIC
Chris@102 82
Chris@102 83 #elif defined(__GNUC__) && ((__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) //GCC >=3.4
Chris@102 84
Chris@102 85 //Compile-time error in case of missing specialization
Chris@102 86 template<class Uint>
Chris@102 87 struct builtin_clz_dispatch;
Chris@102 88
Chris@102 89 #if defined(BOOST_HAS_LONG_LONG)
Chris@102 90 template<>
Chris@102 91 struct builtin_clz_dispatch< ::boost::ulong_long_type >
Chris@102 92 {
Chris@102 93 static ::boost::ulong_long_type call(::boost::ulong_long_type n)
Chris@102 94 { return __builtin_clzll(n); }
Chris@102 95 };
Chris@102 96 #endif
Chris@102 97
Chris@102 98 template<>
Chris@102 99 struct builtin_clz_dispatch<unsigned long>
Chris@102 100 {
Chris@102 101 static unsigned long call(unsigned long n)
Chris@102 102 { return __builtin_clzl(n); }
Chris@102 103 };
Chris@102 104
Chris@102 105 template<>
Chris@102 106 struct builtin_clz_dispatch<unsigned int>
Chris@102 107 {
Chris@102 108 static unsigned int call(unsigned int n)
Chris@102 109 { return __builtin_clz(n); }
Chris@102 110 };
Chris@102 111
Chris@102 112 inline std::size_t floor_log2(std::size_t n)
Chris@102 113 {
Chris@102 114 return sizeof(std::size_t)*CHAR_BIT - std::size_t(1) - builtin_clz_dispatch<std::size_t>::call(n);
Chris@102 115 }
Chris@102 116
Chris@102 117 #else //Portable methods
Chris@102 118
Chris@102 119 ////////////////////////////
Chris@102 120 // Generic method
Chris@102 121 ////////////////////////////
Chris@102 122
Chris@102 123 inline std::size_t floor_log2_get_shift(std::size_t n, true_ )//power of two size_t
Chris@102 124 { return n >> 1; }
Chris@102 125
Chris@102 126 inline std::size_t floor_log2_get_shift(std::size_t n, false_ )//non-power of two size_t
Chris@102 127 { return (n >> 1) + ((n & 1u) & (n != 1)); }
Chris@102 128
Chris@102 129 template<std::size_t N>
Chris@102 130 inline std::size_t floor_log2 (std::size_t x, integer<std::size_t, N>)
Chris@102 131 {
Chris@102 132 const std::size_t Bits = N;
Chris@102 133 const bool Size_t_Bits_Power_2= !(Bits & (Bits-1));
Chris@102 134
Chris@102 135 std::size_t n = x;
Chris@102 136 std::size_t log2 = 0;
Chris@102 137
Chris@102 138 std::size_t remaining_bits = Bits;
Chris@102 139 std::size_t shift = floor_log2_get_shift(remaining_bits, bool_<Size_t_Bits_Power_2>());
Chris@102 140 while(shift){
Chris@102 141 std::size_t tmp = n >> shift;
Chris@102 142 if (tmp){
Chris@102 143 log2 += shift, n = tmp;
Chris@102 144 }
Chris@102 145 shift = floor_log2_get_shift(shift, bool_<Size_t_Bits_Power_2>());
Chris@102 146 }
Chris@102 147
Chris@102 148 return log2;
Chris@102 149 }
Chris@102 150
Chris@102 151 ////////////////////////////
Chris@102 152 // DeBruijn method
Chris@102 153 ////////////////////////////
Chris@102 154
Chris@102 155 //Taken from:
Chris@102 156 //http://stackoverflow.com/questions/11376288/fast-computing-of-log2-for-64-bit-integers
Chris@102 157 //Thanks to Desmond Hume
Chris@102 158
Chris@102 159 inline std::size_t floor_log2 (std::size_t v, integer<std::size_t, 32>)
Chris@102 160 {
Chris@102 161 static const int MultiplyDeBruijnBitPosition[32] =
Chris@102 162 {
Chris@102 163 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
Chris@102 164 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
Chris@102 165 };
Chris@102 166
Chris@102 167 v |= v >> 1;
Chris@102 168 v |= v >> 2;
Chris@102 169 v |= v >> 4;
Chris@102 170 v |= v >> 8;
Chris@102 171 v |= v >> 16;
Chris@102 172
Chris@102 173 return MultiplyDeBruijnBitPosition[(std::size_t)(v * 0x07C4ACDDU) >> 27];
Chris@102 174 }
Chris@102 175
Chris@102 176 inline std::size_t floor_log2 (std::size_t v, integer<std::size_t, 64>)
Chris@102 177 {
Chris@102 178 static const std::size_t MultiplyDeBruijnBitPosition[64] = {
Chris@102 179 63, 0, 58, 1, 59, 47, 53, 2,
Chris@102 180 60, 39, 48, 27, 54, 33, 42, 3,
Chris@102 181 61, 51, 37, 40, 49, 18, 28, 20,
Chris@102 182 55, 30, 34, 11, 43, 14, 22, 4,
Chris@102 183 62, 57, 46, 52, 38, 26, 32, 41,
Chris@102 184 50, 36, 17, 19, 29, 10, 13, 21,
Chris@102 185 56, 45, 25, 31, 35, 16, 9, 12,
Chris@102 186 44, 24, 15, 8, 23, 7, 6, 5};
Chris@102 187
Chris@102 188 v |= v >> 1;
Chris@102 189 v |= v >> 2;
Chris@102 190 v |= v >> 4;
Chris@102 191 v |= v >> 8;
Chris@102 192 v |= v >> 16;
Chris@102 193 v |= v >> 32;
Chris@102 194 return MultiplyDeBruijnBitPosition[((std::size_t)((v - (v >> 1))*0x07EDD5E59A4E28C2ULL)) >> 58];
Chris@102 195 }
Chris@102 196
Chris@102 197
Chris@102 198 inline std::size_t floor_log2 (std::size_t x)
Chris@102 199 {
Chris@102 200 const std::size_t Bits = sizeof(std::size_t)*CHAR_BIT;
Chris@102 201 return floor_log2(x, integer<std::size_t, Bits>());
Chris@102 202 }
Chris@102 203
Chris@102 204 #endif
Chris@102 205
Chris@102 206 //Thanks to Laurent de Soras in
Chris@102 207 //http://www.flipcode.com/archives/Fast_log_Function.shtml
Chris@102 208 inline float fast_log2 (float val)
Chris@102 209 {
Chris@102 210 union caster_t
Chris@102 211 {
Chris@102 212 unsigned x;
Chris@102 213 float val;
Chris@102 214 } caster;
Chris@102 215
Chris@102 216 caster.val = val;
Chris@102 217 unsigned x = caster.x;
Chris@102 218 const int log_2 = int((x >> 23) & 255) - 128;
Chris@102 219 x &= ~(unsigned(255u) << 23u);
Chris@102 220 x += unsigned(127) << 23u;
Chris@102 221 caster.x = x;
Chris@102 222 val = caster.val;
Chris@102 223 //1+log2(m), m ranging from 1 to 2
Chris@102 224 //3rd degree polynomial keeping first derivate continuity.
Chris@102 225 //For less precision the line can be commented out
Chris@102 226 val = ((-1.f/3.f) * val + 2.f) * val - (2.f/3.f);
Chris@102 227 return val + static_cast<float>(log_2);
Chris@102 228 }
Chris@102 229
Chris@102 230 inline std::size_t ceil_log2 (std::size_t x)
Chris@102 231 {
Chris@102 232 return static_cast<std::size_t>((x & (x-1)) != 0) + floor_log2(x);
Chris@102 233 }
Chris@102 234
Chris@102 235 template<class SizeType, std::size_t N>
Chris@102 236 struct numbits_eq
Chris@102 237 {
Chris@102 238 static const bool value = sizeof(SizeType)*CHAR_BIT == N;
Chris@102 239 };
Chris@102 240
Chris@102 241 template<class SizeType, class Enabler = void >
Chris@102 242 struct sqrt2_pow_max;
Chris@102 243
Chris@102 244 template <class SizeType>
Chris@102 245 struct sqrt2_pow_max<SizeType, typename enable_if< numbits_eq<SizeType, 32> >::type>
Chris@102 246 {
Chris@102 247 static const SizeType value = 0xb504f334;
Chris@102 248 static const std::size_t pow = 31;
Chris@102 249 };
Chris@102 250
Chris@102 251 #ifndef BOOST_NO_INT64_T
Chris@102 252
Chris@102 253 template <class SizeType>
Chris@102 254 struct sqrt2_pow_max<SizeType, typename enable_if< numbits_eq<SizeType, 64> >::type>
Chris@102 255 {
Chris@102 256 static const SizeType value = 0xb504f333f9de6484ull;
Chris@102 257 static const std::size_t pow = 63;
Chris@102 258 };
Chris@102 259
Chris@102 260 #endif //BOOST_NO_INT64_T
Chris@102 261
Chris@102 262 // Returns floor(pow(sqrt(2), x * 2 + 1)).
Chris@102 263 // Defined for X from 0 up to the number of bits in size_t minus 1.
Chris@102 264 inline std::size_t sqrt2_pow_2xplus1 (std::size_t x)
Chris@102 265 {
Chris@102 266 const std::size_t value = (std::size_t)sqrt2_pow_max<std::size_t>::value;
Chris@102 267 const std::size_t pow = (std::size_t)sqrt2_pow_max<std::size_t>::pow;
Chris@102 268 return (value >> (pow - x)) + 1;
Chris@102 269 }
Chris@102 270
Chris@102 271 } //namespace detail
Chris@102 272 } //namespace intrusive
Chris@102 273 } //namespace boost
Chris@102 274
Chris@102 275 #endif //BOOST_INTRUSIVE_DETAIL_MATH_HPP