123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- #ifndef BOOST_INTEGER_INTEGER_LOG2_HPP
- #define BOOST_INTEGER_INTEGER_LOG2_HPP
- #include <climits>
- #include <limits>
- #include <boost/config.hpp>
- #include <boost/assert.hpp>
- #include <boost/cstdint.hpp>
- #include <boost/core/bit.hpp>
- #include <boost/core/enable_if.hpp>
- #include <boost/type_traits/is_integral.hpp>
- #include <boost/type_traits/make_unsigned.hpp>
- namespace boost {
- namespace detail {
- template< unsigned int p, unsigned int n, bool = ((2u * n) < p) >
- struct max_pow2_less :
- public max_pow2_less< p, 2u * n >
- {
- };
- template< unsigned int p, unsigned int n >
- struct max_pow2_less< p, n, false >
- {
- BOOST_STATIC_CONSTANT(unsigned int, value = n);
- };
- template< typename T >
- inline typename boost::disable_if< boost::is_integral< T >, int >::type integer_log2_impl(T x)
- {
- unsigned int n = detail::max_pow2_less<
- std::numeric_limits< T >::digits,
- CHAR_BIT / 2u
- >::value;
- int result = 0;
- while (x != 1)
- {
- T t(x >> n);
- if (t)
- {
- result += static_cast< int >(n);
- #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
- x = static_cast< T&& >(t);
- #else
- x = t;
- #endif
- }
- n >>= 1u;
- }
- return result;
- }
- template< typename T >
- inline typename boost::enable_if< boost::is_integral< T >, int >::type integer_log2_impl(T x)
- {
-
-
-
-
- return static_cast< int >((sizeof(T) * CHAR_BIT - 1u) -
- boost::core::countl_zero(static_cast< typename boost::make_unsigned< T >::type >(x)));
- }
- #if defined(BOOST_HAS_INT128)
- inline int integer_log2_impl(boost::uint128_type x)
- {
- const boost::uint64_t x_hi = static_cast< boost::uint64_t >(x >> 64u);
- if (x_hi != 0u)
- return 127 - boost::core::countl_zero(x_hi);
- else
- return 63 - boost::core::countl_zero(static_cast< boost::uint64_t >(x));
- }
- inline int integer_log2_impl(boost::int128_type x)
- {
- return detail::integer_log2_impl(static_cast< boost::uint128_type >(x));
- }
- #endif
- }
- template< typename T >
- inline int integer_log2(T x)
- {
- BOOST_ASSERT(x > 0);
- return detail::integer_log2_impl(x);
- }
- }
- #endif
|