williamr@2
|
1 |
// -------------------------------------
|
williamr@2
|
2 |
// integer_log2.hpp
|
williamr@2
|
3 |
//
|
williamr@2
|
4 |
// Gives the integer part of the logarithm, in base 2, of a
|
williamr@2
|
5 |
// given number. Behavior is undefined if the argument is <= 0.
|
williamr@2
|
6 |
//
|
williamr@2
|
7 |
//
|
williamr@2
|
8 |
// (C) Copyright Gennaro Prota 2003 - 2004.
|
williamr@2
|
9 |
//
|
williamr@2
|
10 |
// Distributed under the Boost Software License, Version 1.0.
|
williamr@2
|
11 |
// (See accompanying file LICENSE_1_0.txt or copy at
|
williamr@2
|
12 |
// http://www.boost.org/LICENSE_1_0.txt)
|
williamr@2
|
13 |
//
|
williamr@2
|
14 |
// ------------------------------------------------------
|
williamr@2
|
15 |
|
williamr@2
|
16 |
|
williamr@2
|
17 |
|
williamr@2
|
18 |
#ifndef BOOST_INTEGER_LOG2_HPP_GP_20030301
|
williamr@2
|
19 |
#define BOOST_INTEGER_LOG2_HPP_GP_20030301
|
williamr@2
|
20 |
|
williamr@2
|
21 |
#include <cassert>
|
williamr@2
|
22 |
#include <climits> // actually used for Borland only
|
williamr@2
|
23 |
#include "boost/limits.hpp"
|
williamr@2
|
24 |
#include "boost/config.hpp"
|
williamr@2
|
25 |
|
williamr@2
|
26 |
|
williamr@2
|
27 |
namespace boost {
|
williamr@2
|
28 |
namespace detail {
|
williamr@2
|
29 |
|
williamr@2
|
30 |
template <typename T>
|
williamr@2
|
31 |
int integer_log2_impl(T x, int n) {
|
williamr@2
|
32 |
|
williamr@2
|
33 |
int result = 0;
|
williamr@2
|
34 |
|
williamr@2
|
35 |
while (x != 1) {
|
williamr@2
|
36 |
|
williamr@2
|
37 |
const T t = x >> n;
|
williamr@2
|
38 |
if (t) {
|
williamr@2
|
39 |
result += n;
|
williamr@2
|
40 |
x = t;
|
williamr@2
|
41 |
}
|
williamr@2
|
42 |
n /= 2;
|
williamr@2
|
43 |
|
williamr@2
|
44 |
}
|
williamr@2
|
45 |
|
williamr@2
|
46 |
return result;
|
williamr@2
|
47 |
}
|
williamr@2
|
48 |
|
williamr@2
|
49 |
|
williamr@2
|
50 |
|
williamr@2
|
51 |
// helper to find the maximum power of two
|
williamr@2
|
52 |
// less than p (more involved than necessary,
|
williamr@2
|
53 |
// to avoid PTS)
|
williamr@2
|
54 |
//
|
williamr@2
|
55 |
template <int p, int n>
|
williamr@2
|
56 |
struct max_pow2_less {
|
williamr@2
|
57 |
|
williamr@2
|
58 |
enum { c = 2*n < p };
|
williamr@2
|
59 |
|
williamr@2
|
60 |
BOOST_STATIC_CONSTANT(int, value =
|
williamr@2
|
61 |
c ? (max_pow2_less< c*p, 2*c*n>::value) : n);
|
williamr@2
|
62 |
|
williamr@2
|
63 |
};
|
williamr@2
|
64 |
|
williamr@2
|
65 |
template <>
|
williamr@2
|
66 |
struct max_pow2_less<0, 0> {
|
williamr@2
|
67 |
|
williamr@2
|
68 |
BOOST_STATIC_CONSTANT(int, value = 0);
|
williamr@2
|
69 |
};
|
williamr@2
|
70 |
|
williamr@2
|
71 |
// this template is here just for Borland :(
|
williamr@2
|
72 |
// we could simply rely on numeric_limits but sometimes
|
williamr@2
|
73 |
// Borland tries to use numeric_limits<const T>, because
|
williamr@2
|
74 |
// of its usual const-related problems in argument deduction
|
williamr@2
|
75 |
// - gps
|
williamr@2
|
76 |
template <typename T>
|
williamr@2
|
77 |
struct width {
|
williamr@2
|
78 |
|
williamr@2
|
79 |
#ifdef __BORLANDC__
|
williamr@2
|
80 |
BOOST_STATIC_CONSTANT(int, value = sizeof(T) * CHAR_BIT);
|
williamr@2
|
81 |
#else
|
williamr@2
|
82 |
BOOST_STATIC_CONSTANT(int, value = (std::numeric_limits<T>::digits));
|
williamr@2
|
83 |
#endif
|
williamr@2
|
84 |
|
williamr@2
|
85 |
};
|
williamr@2
|
86 |
|
williamr@2
|
87 |
} // detail
|
williamr@2
|
88 |
|
williamr@2
|
89 |
|
williamr@2
|
90 |
// ---------
|
williamr@2
|
91 |
// integer_log2
|
williamr@2
|
92 |
// ---------------
|
williamr@2
|
93 |
//
|
williamr@2
|
94 |
template <typename T>
|
williamr@2
|
95 |
int integer_log2(T x) {
|
williamr@2
|
96 |
|
williamr@2
|
97 |
assert(x > 0);
|
williamr@2
|
98 |
|
williamr@2
|
99 |
const int n = detail::max_pow2_less<
|
williamr@2
|
100 |
detail::width<T> :: value, 4
|
williamr@2
|
101 |
> :: value;
|
williamr@2
|
102 |
|
williamr@2
|
103 |
return detail::integer_log2_impl(x, n);
|
williamr@2
|
104 |
|
williamr@2
|
105 |
}
|
williamr@2
|
106 |
|
williamr@2
|
107 |
|
williamr@2
|
108 |
|
williamr@2
|
109 |
}
|
williamr@2
|
110 |
|
williamr@2
|
111 |
|
williamr@2
|
112 |
|
williamr@2
|
113 |
#endif // include guard
|