Chris@16
|
1 // -------------- Boost static_log2.hpp header file ----------------------- //
|
Chris@16
|
2 //
|
Chris@16
|
3 // Copyright (C) 2001 Daryle Walker.
|
Chris@16
|
4 // Copyright (C) 2003 Vesa Karvonen.
|
Chris@16
|
5 // Copyright (C) 2003 Gennaro Prota.
|
Chris@16
|
6 //
|
Chris@16
|
7 // Distributed under the Boost Software License, Version 1.0.
|
Chris@16
|
8 // (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
9 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
10 //
|
Chris@16
|
11 // ---------------------------------------------------
|
Chris@16
|
12 // See http://www.boost.org/libs/integer for documentation.
|
Chris@16
|
13 // ------------------------------------------------------------------------- //
|
Chris@16
|
14
|
Chris@16
|
15
|
Chris@16
|
16 #ifndef BOOST_INTEGER_STATIC_LOG2_HPP
|
Chris@16
|
17 #define BOOST_INTEGER_STATIC_LOG2_HPP
|
Chris@16
|
18
|
Chris@16
|
19 #include "boost/integer_fwd.hpp" // for boost::intmax_t
|
Chris@16
|
20
|
Chris@16
|
21 namespace boost {
|
Chris@16
|
22
|
Chris@16
|
23 namespace detail {
|
Chris@16
|
24
|
Chris@16
|
25 namespace static_log2_impl {
|
Chris@16
|
26
|
Chris@16
|
27 // choose_initial_n<>
|
Chris@16
|
28 //
|
Chris@16
|
29 // Recursively doubles its integer argument, until it
|
Chris@16
|
30 // becomes >= of the "width" (C99, 6.2.6.2p4) of
|
Chris@16
|
31 // static_log2_argument_type.
|
Chris@16
|
32 //
|
Chris@16
|
33 // Used to get the maximum power of two less then the width.
|
Chris@16
|
34 //
|
Chris@16
|
35 // Example: if on your platform argument_type has 48 value
|
Chris@16
|
36 // bits it yields n=32.
|
Chris@16
|
37 //
|
Chris@16
|
38 // It's easy to prove that, starting from such a value
|
Chris@16
|
39 // of n, the core algorithm works correctly for any width
|
Chris@16
|
40 // of static_log2_argument_type and that recursion always
|
Chris@16
|
41 // terminates with x = 1 and n = 0 (see the algorithm's
|
Chris@16
|
42 // invariant).
|
Chris@16
|
43
|
Chris@16
|
44 typedef boost::static_log2_argument_type argument_type;
|
Chris@16
|
45 typedef boost::static_log2_result_type result_type;
|
Chris@16
|
46
|
Chris@16
|
47 template <result_type n>
|
Chris@16
|
48 struct choose_initial_n {
|
Chris@16
|
49
|
Chris@16
|
50 BOOST_STATIC_CONSTANT(bool, c = (argument_type(1) << n << n) != 0);
|
Chris@16
|
51 BOOST_STATIC_CONSTANT(
|
Chris@16
|
52 result_type,
|
Chris@16
|
53 value = !c*n + choose_initial_n<2*c*n>::value
|
Chris@16
|
54 );
|
Chris@16
|
55
|
Chris@16
|
56 };
|
Chris@16
|
57
|
Chris@16
|
58 template <>
|
Chris@16
|
59 struct choose_initial_n<0> {
|
Chris@16
|
60 BOOST_STATIC_CONSTANT(result_type, value = 0);
|
Chris@16
|
61 };
|
Chris@16
|
62
|
Chris@16
|
63
|
Chris@16
|
64
|
Chris@16
|
65 // start computing from n_zero - must be a power of two
|
Chris@16
|
66 const result_type n_zero = 16;
|
Chris@16
|
67 const result_type initial_n = choose_initial_n<n_zero>::value;
|
Chris@16
|
68
|
Chris@16
|
69 // static_log2_impl<>
|
Chris@16
|
70 //
|
Chris@16
|
71 // * Invariant:
|
Chris@16
|
72 // 2n
|
Chris@16
|
73 // 1 <= x && x < 2 at the start of each recursion
|
Chris@16
|
74 // (see also choose_initial_n<>)
|
Chris@16
|
75 //
|
Chris@16
|
76 // * Type requirements:
|
Chris@16
|
77 //
|
Chris@16
|
78 // argument_type maybe any unsigned type with at least n_zero + 1
|
Chris@16
|
79 // value bits. (Note: If larger types will be standardized -e.g.
|
Chris@16
|
80 // unsigned long long- then the argument_type typedef can be
|
Chris@16
|
81 // changed without affecting the rest of the code.)
|
Chris@16
|
82 //
|
Chris@16
|
83
|
Chris@16
|
84 template <argument_type x, result_type n = initial_n>
|
Chris@16
|
85 struct static_log2_impl {
|
Chris@16
|
86
|
Chris@16
|
87 BOOST_STATIC_CONSTANT(bool, c = (x >> n) > 0); // x >= 2**n ?
|
Chris@16
|
88 BOOST_STATIC_CONSTANT(
|
Chris@16
|
89 result_type,
|
Chris@16
|
90 value = c*n + (static_log2_impl< (x>>c*n), n/2 >::value)
|
Chris@16
|
91 );
|
Chris@16
|
92
|
Chris@16
|
93 };
|
Chris@16
|
94
|
Chris@16
|
95 template <>
|
Chris@16
|
96 struct static_log2_impl<1, 0> {
|
Chris@16
|
97 BOOST_STATIC_CONSTANT(result_type, value = 0);
|
Chris@16
|
98 };
|
Chris@16
|
99
|
Chris@16
|
100 }
|
Chris@16
|
101 } // detail
|
Chris@16
|
102
|
Chris@16
|
103
|
Chris@16
|
104
|
Chris@16
|
105 // --------------------------------------
|
Chris@16
|
106 // static_log2<x>
|
Chris@16
|
107 // ----------------------------------------
|
Chris@16
|
108
|
Chris@16
|
109 template <static_log2_argument_type x>
|
Chris@16
|
110 struct static_log2 {
|
Chris@16
|
111
|
Chris@16
|
112 BOOST_STATIC_CONSTANT(
|
Chris@16
|
113 static_log2_result_type,
|
Chris@16
|
114 value = detail::static_log2_impl::static_log2_impl<x>::value
|
Chris@16
|
115 );
|
Chris@16
|
116
|
Chris@16
|
117 };
|
Chris@16
|
118
|
Chris@16
|
119
|
Chris@16
|
120 template <>
|
Chris@16
|
121 struct static_log2<0> { };
|
Chris@16
|
122
|
Chris@16
|
123 }
|
Chris@16
|
124
|
Chris@16
|
125
|
Chris@16
|
126
|
Chris@16
|
127 #endif // include guard
|