Skip to content

Commit c5df07c

Browse files
committed
Simplified integer_log2 implementation.
Removed unnecessary template specializations, removed workaround for compilers not supporting partial template specializations. Use unsigned integers for bit counting, which allows to replace the division with a shift.
1 parent a832e8f commit c5df07c

File tree

1 file changed

+61
-87
lines changed

1 file changed

+61
-87
lines changed

include/boost/integer/integer_log2.hpp

Lines changed: 61 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -15,98 +15,72 @@
1515
#ifndef BOOST_INTEGER_INTEGER_LOG2_HPP
1616
#define BOOST_INTEGER_INTEGER_LOG2_HPP
1717

18-
#include <boost/limits.hpp>
18+
#include <climits>
1919
#include <boost/config.hpp>
2020
#include <boost/assert.hpp>
21-
#if defined(BOOST_BORLANDC)
22-
#include <climits>
23-
#endif
24-
2521

2622
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;
10842
}
10943

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+
}
11083

84+
}
11185

112-
#endif // include guard
86+
#endif // BOOST_INTEGER_INTEGER_LOG2_HPP

0 commit comments

Comments
 (0)