Files
jeanlemotan 8297b0b45f First
2024-07-02 18:06:33 +02:00

103 lines
2.9 KiB
C++

#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<T, T>, "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<T, T>, "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<T, T>, "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<T, T>, "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<T, T>, "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<T, T>, "no-builtin function found for this compiler);");
#endif
}
//////////////////////////////////////////////////////////////////////////
} // namespace algorithm
} // namespace tl