103 lines
2.9 KiB
C++
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
|