From 0f7ed495e199f7158295c6a61ea0e0080a5b4339 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 2 Mar 2021 22:58:36 -0800 Subject: Use a fast native type for the backup popcount --- common/albit.h | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/common/albit.h b/common/albit.h index 2c83ca08..f60e7b1b 100644 --- a/common/albit.h +++ b/common/albit.h @@ -1,6 +1,7 @@ #ifndef AL_BIT_H #define AL_BIT_H +#include #include #include #if !defined(__GNUC__) && (defined(_WIN32) || defined(_WIN64)) @@ -73,6 +74,17 @@ int> countr_zero(T val) noexcept * they're good enough if the GCC built-ins aren't available. */ namespace detail_ { + template::digits> + struct fast_utype { }; + template + struct fast_utype { using type = std::uint_fast8_t; }; + template + struct fast_utype { using type = std::uint_fast16_t; }; + template + struct fast_utype { using type = std::uint_fast32_t; }; + template + struct fast_utype { using type = std::uint_fast64_t; }; + template constexpr T repbits(unsigned char bits) noexcept { @@ -85,17 +97,18 @@ namespace detail_ { template constexpr std::enable_if_t::value && std::is_unsigned::value, -int> popcount(T v) noexcept +int> popcount(T val) noexcept { - constexpr T m55{detail_::repbits(0x55)}; - constexpr T m33{detail_::repbits(0x33)}; - constexpr T m0f{detail_::repbits(0x0f)}; - constexpr T m01{detail_::repbits(0x01)}; + using fast_type = typename detail_::fast_utype::type; + constexpr fast_type m55{detail_::repbits(0x55)}; + constexpr fast_type m33{detail_::repbits(0x33)}; + constexpr fast_type m0f{detail_::repbits(0x0f)}; + constexpr fast_type m01{detail_::repbits(0x01)}; - v = v - ((v >> 1) & m55); + auto v = val - ((fast_type{val} >> 1) & m55); v = (v & m33) + ((v >> 2) & m33); v = (v + (v >> 4)) & m0f; - return static_cast((v * m01) >> ((sizeof(T)-1)*8)); + return static_cast(((v * m01) >> ((sizeof(T)-1)*8)) & 0xff); } #if defined(_WIN64) -- cgit v1.2.3