#pragma once #include "tl/detail/prologue.h" #include "tl/functional.h" namespace tl { namespace algorithm { ////////////////////////////////////////////////////////////////////////// /** * @brief Count the number of bit set for the given value. */ inline uint8_t bits_count(uint32_t i_value) noexcept { #if defined(_MSC_VER) return uint8_t(__popcnt(i_value)); #elif defined(__clang__) || defined(__GNUC__) return uint8_t(__builtin_popcount(i_value)); #else static_assert(!std::is_same_v, "no-builtin function found for this compiler"); #endif } ////////////////////////////////////////////////////////////////////////// /** * @brief Count the number of bit set for the given value. */ inline uint64_t bits_count(uint64_t i_value) noexcept { #if defined(_MSC_VER) #if defined(TL_PLATFORM_64) return uint8_t(__popcnt64(i_value)); #elif defined(TL_PLATFORM_32) return bits_count(uint32_t(i_value >> 32)) + bits_count(uint32_t(i_value & 0xffffffff)); #else static_assert(!std::is_same_v, "no-builtin function found for this compiler);"); #endif // TL_PLATFORM_XX #elif defined(__clang__) || defined(__GNUC__) return uint8_t(__builtin_popcountl(i_value)); #else static_assert(!std::is_same_v, "no-builtin function found for this compiler"); #endif } ////////////////////////////////////////////////////////////////////////// /** * @brief Position of the top bit set to 1. * @param the given value * @return -1 in case value is 0 otherwise the position. */ inline int8_t top_bit(uint32_t i_value) noexcept { #if defined(_MSC_VER) unsigned long index = 0; return _BitScanReverse(&index, (unsigned long)i_value) ? uint8_t(index) : -1; #elif defined(__clang__) || defined(__GNUC__) return i_value ? 31u - __builtin_clzl(i_value) : -1; #else static_assert(!std::is_same_v, "no-builtin function found for this compiler);"); #endif } ////////////////////////////////////////////////////////////////////////// /** * @brief Position of the top bit set to 1. * @param the given value * @return -1 in case value is 0 otherwise the position. */ inline int8_t top_bit(uint64_t i_value) noexcept { #if defined(_MSC_VER) unsigned long index = 0; #if defined(TL_PLATFORM_64) return _BitScanReverse64(&index, (unsigned long long)i_value) ? uint8_t(index) : -1; #elif defined(TL_PLATFORM_32) const int8_t position = top_bit(uint32_t(i_value >> 32)); if (position > -1) { return position + 32; } return top_bit(uint32_t(i_value & 0xffffffff)); #else static_assert(!std::is_same_v, "no-builtin function found for this compiler);"); #endif // TL_PLATFORM_XX #elif defined(__clang__) || defined(__GNUC__) return i_value ? 63u - __builtin_clzll(i_value) : -1; #else static_assert(!std::is_same_v, "no-builtin function found for this compiler);"); #endif } ////////////////////////////////////////////////////////////////////////// } // namespace algorithm } // namespace tl