|
15 | 15 | #ifndef BOOST_INTEGER_INTEGER_LOG2_HPP |
16 | 16 | #define BOOST_INTEGER_INTEGER_LOG2_HPP |
17 | 17 |
|
18 | | -#include <boost/limits.hpp> |
| 18 | +#include <climits> |
19 | 19 | #include <boost/config.hpp> |
20 | 20 | #include <boost/assert.hpp> |
21 | | -#if defined(BOOST_BORLANDC) |
22 | | -#include <climits> |
23 | | -#endif |
24 | | - |
25 | 21 |
|
26 | 22 | namespace boost { |
27 | | - namespace detail { |
28 | | - |
29 | | - template <typename T> |
30 | | - int integer_log2_impl(T x, int n) { |
31 | | - |
32 | | - int result = 0; |
33 | | - |
34 | | - while (x != 1) { |
35 | | - |
36 | | - const T t = static_cast<T>(x >> n); |
37 | | - if (t) { |
38 | | - result += n; |
39 | | - x = t; |
40 | | - } |
41 | | - n /= 2; |
42 | | - |
43 | | - } |
44 | | - |
45 | | - return result; |
46 | | - } |
47 | | - |
48 | | - |
49 | | - |
50 | | - // helper to find the maximum power of two |
51 | | - // less than p (more involved than necessary, |
52 | | - // to avoid PTS) |
53 | | - // |
54 | | - template <int p, int n> |
55 | | - struct max_pow2_less { |
56 | | - |
57 | | - enum { c = 2*n < p }; |
58 | | - |
59 | | - BOOST_STATIC_CONSTANT(int, value = |
60 | | - c ? (max_pow2_less< c*p, 2*c*n>::value) : n); |
61 | | - |
62 | | - }; |
63 | | - |
64 | | - template <> |
65 | | - struct max_pow2_less<0, 0> { |
66 | | - |
67 | | - BOOST_STATIC_CONSTANT(int, value = 0); |
68 | | - }; |
69 | | - |
70 | | - // this template is here just for Borland :( |
71 | | - // we could simply rely on numeric_limits but sometimes |
72 | | - // Borland tries to use numeric_limits<const T>, because |
73 | | - // of its usual const-related problems in argument deduction |
74 | | - // - gps |
75 | | - template <typename T> |
76 | | - struct width { |
77 | | - |
78 | | -#ifdef BOOST_BORLANDC |
79 | | - BOOST_STATIC_CONSTANT(int, value = sizeof(T) * CHAR_BIT); |
80 | | -#else |
81 | | - BOOST_STATIC_CONSTANT(int, value = (std::numeric_limits<T>::digits)); |
82 | | -#endif |
83 | | - |
84 | | - }; |
85 | | - |
86 | | - } // detail |
87 | | - |
88 | | - |
89 | | - // --------- |
90 | | - // integer_log2 |
91 | | - // --------------- |
92 | | - // |
93 | | - template <typename T> |
94 | | - int integer_log2(T x) { |
95 | | - |
96 | | - BOOST_ASSERT(x > 0); |
97 | | - |
98 | | - const int n = detail::max_pow2_less< |
99 | | - detail::width<T> :: value, 4 |
100 | | - > :: value; |
101 | | - |
102 | | - return detail::integer_log2_impl(x, n); |
103 | | - |
104 | | - } |
105 | | - |
106 | | - |
107 | | - |
| 23 | +namespace detail { |
| 24 | + |
| 25 | +template <typename T> |
| 26 | +inline int integer_log2_impl(T x, unsigned int n) |
| 27 | +{ |
| 28 | + int result = 0; |
| 29 | + |
| 30 | + while (x != 1) |
| 31 | + { |
| 32 | + const T t = static_cast<T>(x >> n); |
| 33 | + if (t) |
| 34 | + { |
| 35 | + result += static_cast<int>(n); |
| 36 | + x = t; |
| 37 | + } |
| 38 | + n >>= 1u; |
| 39 | + } |
| 40 | + |
| 41 | + return result; |
108 | 42 | } |
109 | 43 |
|
| 44 | +// helper to find the maximum power of two |
| 45 | +// less than p |
| 46 | +template <unsigned int p, unsigned int n, bool = (2u*n < p)> |
| 47 | +struct max_pow2_less : |
| 48 | + public max_pow2_less< p, 2u*n > |
| 49 | +{ |
| 50 | +}; |
| 51 | + |
| 52 | +template <unsigned int p, unsigned int n> |
| 53 | +struct max_pow2_less<p, n, false> |
| 54 | +{ |
| 55 | + BOOST_STATIC_CONSTANT(unsigned int, value = n); |
| 56 | +}; |
| 57 | + |
| 58 | +} // namespace detail |
| 59 | + |
| 60 | + |
| 61 | +// ------------ |
| 62 | +// integer_log2 |
| 63 | +// ------------ |
| 64 | +template <typename T> |
| 65 | +inline int integer_log2(T x) |
| 66 | +{ |
| 67 | + BOOST_ASSERT(x > 0); |
| 68 | + |
| 69 | + return detail::integer_log2_impl |
| 70 | + ( |
| 71 | + x, |
| 72 | + detail::max_pow2_less< |
| 73 | + // We could simply rely on numeric_limits but sometimes |
| 74 | + // Borland tries to use numeric_limits<const T>, because |
| 75 | + // of its usual const-related problems in argument deduction |
| 76 | + // - gps |
| 77 | + // Also, numeric_limits is not specialized for __int128 in libstdc++. |
| 78 | + sizeof(T) * CHAR_BIT, |
| 79 | + CHAR_BIT / 2u |
| 80 | + >::value |
| 81 | + ); |
| 82 | +} |
110 | 83 |
|
| 84 | +} |
111 | 85 |
|
112 | | -#endif // include guard |
| 86 | +#endif // BOOST_INTEGER_INTEGER_LOG2_HPP |
0 commit comments