From c5df07cb21ee71ddf994b24100304de16e21c89f Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Tue, 21 Dec 2021 20:39:22 +0300 Subject: [PATCH] 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. --- include/boost/integer/integer_log2.hpp | 132 ++++++++++--------------- 1 file changed, 53 insertions(+), 79 deletions(-) diff --git a/include/boost/integer/integer_log2.hpp b/include/boost/integer/integer_log2.hpp index 9b022c6..9f79f76 100644 --- a/include/boost/integer/integer_log2.hpp +++ b/include/boost/integer/integer_log2.hpp @@ -15,98 +15,72 @@ #ifndef BOOST_INTEGER_INTEGER_LOG2_HPP #define BOOST_INTEGER_INTEGER_LOG2_HPP -#include +#include #include #include -#if defined(BOOST_BORLANDC) -#include -#endif - namespace boost { - namespace detail { +namespace detail { - template - int integer_log2_impl(T x, int n) { +template +inline int integer_log2_impl(T x, unsigned int n) +{ + int result = 0; - int result = 0; + while (x != 1) + { + const T t = static_cast(x >> n); + if (t) + { + result += static_cast(n); + x = t; + } + n >>= 1u; + } - while (x != 1) { + return result; +} - const T t = static_cast(x >> n); - if (t) { - result += n; - x = t; - } - n /= 2; +// helper to find the maximum power of two +// less than p +template +struct max_pow2_less : + public max_pow2_less< p, 2u*n > +{ +}; - } +template +struct max_pow2_less +{ + BOOST_STATIC_CONSTANT(unsigned int, value = n); +}; - return result; - } +} // namespace detail +// ------------ +// integer_log2 +// ------------ +template +inline int integer_log2(T x) +{ + BOOST_ASSERT(x > 0); - // helper to find the maximum power of two - // less than p (more involved than necessary, - // to avoid PTS) - // - template - struct max_pow2_less { - - enum { c = 2*n < p }; - - BOOST_STATIC_CONSTANT(int, value = - c ? (max_pow2_less< c*p, 2*c*n>::value) : n); - - }; - - template <> - struct max_pow2_less<0, 0> { - - BOOST_STATIC_CONSTANT(int, value = 0); - }; - - // this template is here just for Borland :( - // we could simply rely on numeric_limits but sometimes - // Borland tries to use numeric_limits, because - // of its usual const-related problems in argument deduction - // - gps - template - struct width { - -#ifdef BOOST_BORLANDC - BOOST_STATIC_CONSTANT(int, value = sizeof(T) * CHAR_BIT); -#else - BOOST_STATIC_CONSTANT(int, value = (std::numeric_limits::digits)); -#endif - - }; - - } // detail - - - // --------- - // integer_log2 - // --------------- - // - template - int integer_log2(T x) { - - BOOST_ASSERT(x > 0); - - const int n = detail::max_pow2_less< - detail::width :: value, 4 - > :: value; - - return detail::integer_log2_impl(x, n); - - } - - + return detail::integer_log2_impl + ( + x, + detail::max_pow2_less< + // We could simply rely on numeric_limits but sometimes + // Borland tries to use numeric_limits, because + // of its usual const-related problems in argument deduction + // - gps + // Also, numeric_limits is not specialized for __int128 in libstdc++. + sizeof(T) * CHAR_BIT, + CHAR_BIT / 2u + >::value + ); +} } - - -#endif // include guard +#endif // BOOST_INTEGER_INTEGER_LOG2_HPP