#ifndef BOOST_INTEGER_STATIC_LOG2_HPP
#define BOOST_INTEGER_STATIC_LOG2_HPP
#include <boost/config.hpp>
#include <boost/integer_fwd.hpp>
namespace boost {
namespace detail {
namespace static_log2_impl {
typedef boost::static_log2_argument_type argument_type;
typedef boost::static_log2_result_type result_type;
template <result_type n>
struct choose_initial_n {
BOOST_STATIC_CONSTANT(bool, c = (argument_type(1) << n << n) != 0);
BOOST_STATIC_CONSTANT(
result_type,
value = !c*n + choose_initial_n<2*c*n>::value
);
};
template <>
struct choose_initial_n<0> {
BOOST_STATIC_CONSTANT(result_type, value = 0);
};
const result_type n_zero = 16;
const result_type initial_n = choose_initial_n<n_zero>::value;
template <argument_type x, result_type n = initial_n>
struct static_log2_impl {
BOOST_STATIC_CONSTANT(bool, c = (x >> n) > 0); BOOST_STATIC_CONSTANT(
result_type,
value = c*n + (static_log2_impl< (x>>c*n), n/2 >::value)
);
};
template <>
struct static_log2_impl<1, 0> {
BOOST_STATIC_CONSTANT(result_type, value = 0);
};
}
}
template <static_log2_argument_type x>
struct static_log2 {
BOOST_STATIC_CONSTANT(
static_log2_result_type,
value = detail::static_log2_impl::static_log2_impl<x>::value
);
};
template <>
struct static_log2<0> { };
}
#endif