From 08baf8fa64fc7e8096bfe258716e9b8c3fe8dc99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D1=80=D0=B0=D0=BD=D0=B8=D0=BC=D0=B8=D1=80=20=D0=9A?= =?UTF-8?q?=D0=B0=D1=80=D0=B0=D1=9F=D0=B8=D1=9B?= Date: Thu, 23 Nov 2023 09:41:57 -0800 Subject: [PATCH] Cleanup bitwise ops. --- include/bx/inline/math.inl | 170 ++++++++++++++++++++++++++++++++- include/bx/inline/uint32_t.inl | 124 ++++++------------------ include/bx/math.h | 31 +++++- include/bx/uint32_t.h | 18 ++-- tests/math_test.cpp | 131 +++++++++++++++++++++---- tests/uint32_test.cpp | 55 ----------- 6 files changed, 346 insertions(+), 183 deletions(-) diff --git a/include/bx/inline/math.inl b/include/bx/inline/math.inl index 37f512c..14685f8 100644 --- a/include/bx/inline/math.inl +++ b/include/bx/inline/math.inl @@ -212,16 +212,180 @@ namespace bx return pow(2.0f, _a); } - template<> inline BX_CONST_FUNC float log2(float _a) { return log(_a) * kInvLogNat2; } template<> - inline BX_CONST_FUNC int32_t log2(int32_t _a) + inline BX_CONSTEXPR_FUNC uint8_t countBits(uint32_t _val) { - return 31 - uint32_cntlz(_a); +#if BX_COMPILER_GCC || BX_COMPILER_CLANG + return __builtin_popcount(_val); +#else + const uint32_t tmp0 = uint32_srl(_val, 1); + const uint32_t tmp1 = uint32_and(tmp0, 0x55555555); + const uint32_t tmp2 = uint32_sub(_val, tmp1); + const uint32_t tmp3 = uint32_and(tmp2, 0xc30c30c3); + const uint32_t tmp4 = uint32_srl(tmp2, 2); + const uint32_t tmp5 = uint32_and(tmp4, 0xc30c30c3); + const uint32_t tmp6 = uint32_srl(tmp2, 4); + const uint32_t tmp7 = uint32_and(tmp6, 0xc30c30c3); + const uint32_t tmp8 = uint32_add(tmp3, tmp5); + const uint32_t tmp9 = uint32_add(tmp7, tmp8); + const uint32_t tmpA = uint32_srl(tmp9, 6); + const uint32_t tmpB = uint32_add(tmp9, tmpA); + const uint32_t tmpC = uint32_srl(tmpB, 12); + const uint32_t tmpD = uint32_srl(tmpB, 24); + const uint32_t tmpE = uint32_add(tmpB, tmpC); + const uint32_t tmpF = uint32_add(tmpD, tmpE); + const uint32_t result = uint32_and(tmpF, 0x3f); + + return result; +#endif // BX_COMPILER_* + } + + template<> + inline BX_CONSTEXPR_FUNC uint8_t countBits(unsigned long long _val) + { +#if BX_COMPILER_GCC || BX_COMPILER_CLANG + return __builtin_popcountll(_val); +#else + const uint32_t lo = uint32_t(_val&UINT32_MAX); + const uint32_t hi = uint32_t(_val>>32); + + return uint32_cntbits(lo) + + uint32_cntbits(hi) + ; +#endif // BX_COMPILER_* + } + + template<> + inline BX_CONSTEXPR_FUNC uint8_t countBits(unsigned long _val) + { + return countBits(_val); + } + + template<> inline BX_CONSTEXPR_FUNC uint8_t countBits(uint8_t _val) { return countBits(_val); } + template<> inline BX_CONSTEXPR_FUNC uint8_t countBits(int8_t _val) { return countBits(_val); } + template<> inline BX_CONSTEXPR_FUNC uint8_t countBits(uint16_t _val) { return countBits(_val); } + template<> inline BX_CONSTEXPR_FUNC uint8_t countBits(int16_t _val) { return countBits(_val); } + template<> inline BX_CONSTEXPR_FUNC uint8_t countBits(int32_t _val) { return countBits(_val); } + template<> inline BX_CONSTEXPR_FUNC uint8_t countBits(int64_t _val) { return countBits(_val); } + + template<> + inline BX_CONSTEXPR_FUNC uint8_t countLeadingZeros(uint32_t _val) + { +#if BX_COMPILER_GCC || BX_COMPILER_CLANG + return 0 == _val ? 32 : __builtin_clz(_val); +#else + const uint32_t tmp0 = uint32_srl(_val, 1); + const uint32_t tmp1 = uint32_or(tmp0, _val); + const uint32_t tmp2 = uint32_srl(tmp1, 2); + const uint32_t tmp3 = uint32_or(tmp2, tmp1); + const uint32_t tmp4 = uint32_srl(tmp3, 4); + const uint32_t tmp5 = uint32_or(tmp4, tmp3); + const uint32_t tmp6 = uint32_srl(tmp5, 8); + const uint32_t tmp7 = uint32_or(tmp6, tmp5); + const uint32_t tmp8 = uint32_srl(tmp7, 16); + const uint32_t tmp9 = uint32_or(tmp8, tmp7); + const uint32_t tmpA = uint32_not(tmp9); + const uint32_t result = uint32_cntbits(tmpA); + + return result; +#endif // BX_COMPILER_* + } + + template<> + inline BX_CONSTEXPR_FUNC uint8_t countLeadingZeros(unsigned long long _val) + { +#if BX_COMPILER_GCC || BX_COMPILER_CLANG + return 0 == _val ? 64 : __builtin_clzll(_val); +#else + return _val & UINT64_C(0xffffffff00000000) + ? uint32_cntlz(uint32_t(_val>>32) ) + : uint32_cntlz(uint32_t(_val) ) + 32 + ; +#endif // BX_COMPILER_* + } + + template<> + inline BX_CONSTEXPR_FUNC uint8_t countLeadingZeros(unsigned long _val) + { + return countLeadingZeros(_val); + } + + template<> inline BX_CONSTEXPR_FUNC uint8_t countLeadingZeros(uint8_t _val) { return countLeadingZeros(_val)-24; } + template<> inline BX_CONSTEXPR_FUNC uint8_t countLeadingZeros(int8_t _val) { return countLeadingZeros(_val); } + template<> inline BX_CONSTEXPR_FUNC uint8_t countLeadingZeros(uint16_t _val) { return countLeadingZeros(_val)-16; } + template<> inline BX_CONSTEXPR_FUNC uint8_t countLeadingZeros(int16_t _val) { return countLeadingZeros(_val); } + template<> inline BX_CONSTEXPR_FUNC uint8_t countLeadingZeros(int32_t _val) { return countLeadingZeros(_val); } + template<> inline BX_CONSTEXPR_FUNC uint8_t countLeadingZeros(int64_t _val) { return countLeadingZeros(_val); } + + template<> + inline BX_CONSTEXPR_FUNC uint8_t countTrailingZeros(uint32_t _val) + { +#if BX_COMPILER_GCC || BX_COMPILER_CLANG + return 0 == _val ? 32 : __builtin_ctz(_val); +#else + const uint32_t tmp0 = uint32_not(_val); + const uint32_t tmp1 = uint32_dec(_val); + const uint32_t tmp2 = uint32_and(tmp0, tmp1); + const uint32_t result = uint32_cntbits(tmp2); + + return result; +#endif // BX_COMPILER_* + } + + template<> + inline BX_CONSTEXPR_FUNC uint8_t countTrailingZeros(unsigned long long _val) + { +#if BX_COMPILER_GCC || BX_COMPILER_CLANG + return 0 == _val ? 64 : __builtin_ctzll(_val); +#else + return _val & UINT64_C(0xffffffff) + ? uint32_cnttz(uint32_t(_val) ) + : uint32_cnttz(uint32_t(_val>>32) ) + 32 + ; +#endif // BX_COMPILER_* + } + + template<> + inline BX_CONSTEXPR_FUNC uint8_t countTrailingZeros(unsigned long _val) + { + return countTrailingZeros(_val); + } + + template<> inline BX_CONSTEXPR_FUNC uint8_t countTrailingZeros(uint8_t _val) { return bx::min(8u, countTrailingZeros(_val) ); } + template<> inline BX_CONSTEXPR_FUNC uint8_t countTrailingZeros(int8_t _val) { return countTrailingZeros(_val); } + template<> inline BX_CONSTEXPR_FUNC uint8_t countTrailingZeros(uint16_t _val) { return bx::min(16u, countTrailingZeros(_val) ); } + template<> inline BX_CONSTEXPR_FUNC uint8_t countTrailingZeros(int16_t _val) { return countTrailingZeros(_val); } + template<> inline BX_CONSTEXPR_FUNC uint8_t countTrailingZeros(int32_t _val) { return countTrailingZeros(_val); } + template<> inline BX_CONSTEXPR_FUNC uint8_t countTrailingZeros(int64_t _val) { return countTrailingZeros(_val); } + + template + inline BX_CONSTEXPR_FUNC uint8_t findFirstSet(Ty _x) + { + return Ty(0) == _x ? uint8_t(0) : countTrailingZeros(_x) + 1; + } + + template + inline BX_CONSTEXPR_FUNC uint8_t ceilLog2(Ty _a) + { + BX_STATIC_ASSERT(isInteger(), "Type Ty must be of integer type!"); + return Ty(_a) < Ty(1) ? Ty(0) : sizeof(Ty)*8 - countLeadingZeros(_a - 1); + } + + template + inline BX_CONSTEXPR_FUNC Ty nextPow2(Ty _a) + { + const uint8_t log2 = ceilLog2(_a); + BX_ASSERT(log2 < sizeof(Ty)*8 + , "Type Ty cannot represent the next power-of-two value (1<<%u is larger than %u-bit type)." + , log2 + , sizeof(Ty)*8 + ); + return Ty(1)< inline BX_CONSTEXPR_FUNC uint32_t uint32_cntbits(uint32_t _val) { #if BX_COMPILER_GCC || BX_COMPILER_CLANG @@ -335,35 +334,6 @@ namespace bx #endif // BX_COMPILER_* } - template<> - inline BX_CONSTEXPR_FUNC uint32_t uint32_cntbits(unsigned long long _val) - { -#if BX_COMPILER_GCC || BX_COMPILER_CLANG - return __builtin_popcountll(_val); -#else - const uint32_t lo = uint32_t(_val&UINT32_MAX); - const uint32_t hi = uint32_t(_val>>32); - - return uint32_cntbits(lo) - + uint32_cntbits(hi) - ; -#endif // BX_COMPILER_* - } - - template<> - inline BX_CONSTEXPR_FUNC uint32_t uint32_cntbits(unsigned long _val) - { - return uint32_cntbits(_val); - } - - template<> inline BX_CONSTEXPR_FUNC uint32_t uint32_cntbits(uint8_t _val) { return uint32_cntbits(_val); } - template<> inline BX_CONSTEXPR_FUNC uint32_t uint32_cntbits(int8_t _val) { return uint32_cntbits(_val); } - template<> inline BX_CONSTEXPR_FUNC uint32_t uint32_cntbits(uint16_t _val) { return uint32_cntbits(_val); } - template<> inline BX_CONSTEXPR_FUNC uint32_t uint32_cntbits(int16_t _val) { return uint32_cntbits(_val); } - template<> inline BX_CONSTEXPR_FUNC uint32_t uint32_cntbits(int32_t _val) { return uint32_cntbits(_val); } - template<> inline BX_CONSTEXPR_FUNC uint32_t uint32_cntbits(int64_t _val) { return uint32_cntbits(_val); } - - template<> inline BX_CONSTEXPR_FUNC uint32_t uint32_cntlz(uint32_t _val) { #if BX_COMPILER_GCC || BX_COMPILER_CLANG @@ -386,33 +356,6 @@ namespace bx #endif // BX_COMPILER_* } - template<> - inline BX_CONSTEXPR_FUNC uint32_t uint32_cntlz(unsigned long long _val) - { -#if BX_COMPILER_GCC || BX_COMPILER_CLANG - return 0 == _val ? 64 : __builtin_clzll(_val); -#else - return _val & UINT64_C(0xffffffff00000000) - ? uint32_cntlz(uint32_t(_val>>32) ) - : uint32_cntlz(uint32_t(_val) ) + 32 - ; -#endif // BX_COMPILER_* - } - - template<> - inline BX_CONSTEXPR_FUNC uint32_t uint32_cntlz(unsigned long _val) - { - return uint32_cntlz(_val); - } - - template<> inline BX_CONSTEXPR_FUNC uint32_t uint32_cntlz(uint8_t _val) { return uint32_cntlz(_val)-24; } - template<> inline BX_CONSTEXPR_FUNC uint32_t uint32_cntlz(int8_t _val) { return uint32_cntlz(_val); } - template<> inline BX_CONSTEXPR_FUNC uint32_t uint32_cntlz(uint16_t _val) { return uint32_cntlz(_val)-16; } - template<> inline BX_CONSTEXPR_FUNC uint32_t uint32_cntlz(int16_t _val) { return uint32_cntlz(_val); } - template<> inline BX_CONSTEXPR_FUNC uint32_t uint32_cntlz(int32_t _val) { return uint32_cntlz(_val); } - template<> inline BX_CONSTEXPR_FUNC uint32_t uint32_cntlz(int64_t _val) { return uint32_cntlz(_val); } - - template<> inline BX_CONSTEXPR_FUNC uint32_t uint32_cnttz(uint32_t _val) { #if BX_COMPILER_GCC || BX_COMPILER_CLANG @@ -427,39 +370,11 @@ namespace bx #endif // BX_COMPILER_* } - template<> - inline BX_CONSTEXPR_FUNC uint32_t uint32_cnttz(unsigned long long _val) + inline BX_CONSTEXPR_FUNC uint32_t uint32_ffs(uint32_t _x) { -#if BX_COMPILER_GCC || BX_COMPILER_CLANG - return 0 == _val ? 64 : __builtin_ctzll(_val); -#else - return _val & UINT64_C(0xffffffff) - ? uint32_cnttz(uint32_t(_val) ) - : uint32_cnttz(uint32_t(_val>>32) ) + 32 - ; -#endif // BX_COMPILER_* + return 0 == _x ? 0 : uint32_cnttz(_x) + 1; } - template<> - inline BX_CONSTEXPR_FUNC uint32_t uint32_cnttz(unsigned long _val) - { - return uint32_cnttz(_val); - } - - template<> inline BX_CONSTEXPR_FUNC uint32_t uint32_cnttz(uint8_t _val) { return bx::min(8u, uint32_cnttz(_val) ); } - template<> inline BX_CONSTEXPR_FUNC uint32_t uint32_cnttz(int8_t _val) { return uint32_cnttz(_val); } - template<> inline BX_CONSTEXPR_FUNC uint32_t uint32_cnttz(uint16_t _val) { return bx::min(16u, uint32_cnttz(_val) ); } - template<> inline BX_CONSTEXPR_FUNC uint32_t uint32_cnttz(int16_t _val) { return uint32_cnttz(_val); } - template<> inline BX_CONSTEXPR_FUNC uint32_t uint32_cnttz(int32_t _val) { return uint32_cnttz(_val); } - template<> inline BX_CONSTEXPR_FUNC uint32_t uint32_cnttz(int64_t _val) { return uint32_cnttz(_val); } - - template - inline BX_CONSTEXPR_FUNC uint32_t uint32_ffs(Ty _x) - { - return Ty(0) == _x ? uint32_t(0) : uint32_cnttz(_x) + 1; - } - - inline BX_CONSTEXPR_FUNC uint32_t uint32_part1by1(uint32_t _a) { // shuffle: @@ -644,19 +559,42 @@ namespace bx return _a * _b; } - inline BX_CONSTEXPR_FUNC uint32_t uint64_cntbits(uint64_t _val) + inline BX_CONSTEXPR_FUNC uint64_t uint64_cntbits(uint64_t _val) { - return uint32_cntbits(_val); +#if BX_COMPILER_GCC || BX_COMPILER_CLANG + return __builtin_popcountll(_val); +#else + const uint32_t lo = uint32_t(_val&UINT32_MAX); + const uint32_t hi = uint32_t(_val>>32); + + return uint32_cntbits(lo) + + uint32_cntbits(hi) + ; +#endif // BX_COMPILER_* } - inline BX_CONSTEXPR_FUNC uint32_t uint64_cntlz(uint64_t _val) + inline BX_CONSTEXPR_FUNC uint64_t uint64_cntlz(uint64_t _val) { - return uint32_cntlz(_val); +#if BX_COMPILER_GCC || BX_COMPILER_CLANG + return 0 == _val ? 64 : __builtin_clzll(_val); +#else + return _val & UINT64_C(0xffffffff00000000) + ? uint32_cntlz(uint32_t(_val>>32) ) + : uint32_cntlz(uint32_t(_val) ) + 32 + ; +#endif // BX_COMPILER_* } - inline BX_CONSTEXPR_FUNC uint32_t uint64_cnttz(uint64_t _val) + inline BX_CONSTEXPR_FUNC uint64_t uint64_cnttz(uint64_t _val) { - return uint32_cnttz(_val); +#if BX_COMPILER_GCC || BX_COMPILER_CLANG + return 0 == _val ? 64 : __builtin_ctzll(_val); +#else + return _val & UINT64_C(0xffffffff) + ? uint32_cnttz(uint32_t(_val) ) + : uint32_cnttz(uint32_t(_val>>32) ) + 32 + ; +#endif // BX_COMPILER_* } inline BX_CONSTEXPR_FUNC uint32_t uint32_gcd(uint32_t _a, uint32_t _b) diff --git a/include/bx/math.h b/include/bx/math.h index facf64c..d040806 100644 --- a/include/bx/math.h +++ b/include/bx/math.h @@ -270,8 +270,37 @@ namespace bx /// Returns the base 2 logarithm of _a. /// + BX_CONST_FUNC float log2(float _a); + + /// Count number of bits set. + /// template - BX_CONST_FUNC Ty log2(Ty _a); + BX_CONSTEXPR_FUNC uint8_t countBits(Ty _val); + + /// Count number of leading zeros. + /// + template + BX_CONSTEXPR_FUNC uint8_t countLeadingZeros(Ty _val); + + /// Count number of trailing zeros. + /// + template + BX_CONSTEXPR_FUNC uint8_t countTrailingZeros(Ty _val); + + /// Find first set. + /// + template + BX_CONSTEXPR_FUNC uint8_t findFirstSet(Ty _val); + + /// Returns the next smallest integer base 2 logarithm of _a. + /// + template + BX_CONSTEXPR_FUNC uint8_t ceilLog2(Ty _a); + + /// Returns the next smallest power of two value. + /// + template + BX_CONSTEXPR_FUNC Ty nextPow2(Ty _a); /// Returns the square root of _a. /// diff --git a/include/bx/uint32_t.h b/include/bx/uint32_t.h index deb09ca..1c38a0f 100644 --- a/include/bx/uint32_t.h +++ b/include/bx/uint32_t.h @@ -149,23 +149,19 @@ namespace bx /// Count number of bits set. /// - template - BX_CONSTEXPR_FUNC uint32_t uint32_cntbits(Ty _val); + BX_CONSTEXPR_FUNC uint32_t uint32_cntbits(uint32_t _val); /// Count number of leading zeros. /// - template - BX_CONSTEXPR_FUNC uint32_t uint32_cntlz(Ty _val); + BX_CONSTEXPR_FUNC uint32_t uint32_cntlz(uint32_t _val); /// Count number of trailing zeros. /// - template - BX_CONSTEXPR_FUNC uint32_t uint32_cnttz(Ty _val); + BX_CONSTEXPR_FUNC uint32_t uint32_cnttz(uint32_t _val); /// Find first set. /// - template - BX_CONSTEXPR_FUNC uint32_t uint32_ffs(Ty _val); + BX_CONSTEXPR_FUNC uint32_t uint32_ffs(uint32_t _val); /// BX_CONSTEXPR_FUNC uint32_t uint32_part1by1(uint32_t _a); @@ -240,13 +236,13 @@ namespace bx BX_CONSTEXPR_FUNC uint64_t uint64_mul(uint64_t _a, uint64_t _b); /// - BX_CONSTEXPR_FUNC uint32_t uint64_cntbits(uint64_t _val); + BX_CONSTEXPR_FUNC uint64_t uint64_cntbits(uint64_t _val); /// - BX_CONSTEXPR_FUNC uint32_t uint64_cntlz(uint64_t _val); + BX_CONSTEXPR_FUNC uint64_t uint64_cntlz(uint64_t _val); /// - BX_CONSTEXPR_FUNC uint32_t uint64_cnttz(uint64_t _val); + BX_CONSTEXPR_FUNC uint64_t uint64_cnttz(uint64_t _val); /// Greatest common divisor. /// diff --git a/tests/math_test.cpp b/tests/math_test.cpp index f2e5c19..576c958 100644 --- a/tests/math_test.cpp +++ b/tests/math_test.cpp @@ -11,7 +11,6 @@ #include // intXX_t #include // UCHAR_* -#if !BX_PLATFORM_BSD TEST_CASE("isFinite, isInfinite, isNan", "[math]") { for (uint64_t ii = 0; ii < UINT32_MAX; ii += rand()%(1<<13)+1) @@ -19,7 +18,6 @@ TEST_CASE("isFinite, isInfinite, isNan", "[math]") union { uint32_t ui; float f; } u = { uint32_t(ii) }; #if BX_PLATFORM_OSX - BX_UNUSED(u); REQUIRE(::__isnanf(u.f) == bx::isNan(u.f) ); REQUIRE(::__isfinitef(u.f) == bx::isFinite(u.f) ); REQUIRE(::__isinff(u.f) == bx::isInfinite(u.f) ); @@ -34,7 +32,6 @@ TEST_CASE("isFinite, isInfinite, isNan", "[math]") #endif // BX_PLATFORM_OSX } } -#endif // !BX_PLATFORM_BSD bool log2_test(float _a) { @@ -47,31 +44,125 @@ TEST_CASE("log2", "[math][libm]") log2_test(256.0f); REQUIRE(0.0f == bx::log2(1.0f) ); - REQUIRE(0 == bx::log2(1) ); - REQUIRE(1.0f == bx::log2(2.0f) ); - REQUIRE(1 == bx::log2(2) ); - REQUIRE(2.0f == bx::log2(4.0f) ); - REQUIRE(2 == bx::log2(4) ); - REQUIRE(3.0f == bx::log2(8.0f) ); - REQUIRE(3 == bx::log2(8) ); - REQUIRE(4.0f == bx::log2(16.0f) ); - REQUIRE(4 == bx::log2(16) ); - REQUIRE(5.0f == bx::log2(32.0f) ); - REQUIRE(5 == bx::log2(32) ); - REQUIRE(6.0f == bx::log2(64.0f) ); - REQUIRE(6 == bx::log2(64) ); - REQUIRE(7.0f == bx::log2(128.0f) ); - REQUIRE(7 == bx::log2(128) ); - REQUIRE(8.0f == bx::log2(256.0f) ); - REQUIRE(8 == bx::log2(256) ); +} + +TEST_CASE("ceilLog2", "[math]") +{ + REQUIRE(0 == bx::ceilLog2(-1) ); + REQUIRE(0 == bx::ceilLog2(0) ); + REQUIRE(0 == bx::ceilLog2(1) ); + REQUIRE(1 == bx::ceilLog2(2) ); + REQUIRE(2 == bx::ceilLog2(4) ); + REQUIRE(3 == bx::ceilLog2(8) ); + REQUIRE(4 == bx::ceilLog2(16) ); + REQUIRE(5 == bx::ceilLog2(32) ); + REQUIRE(6 == bx::ceilLog2(64) ); + REQUIRE(7 == bx::ceilLog2(128) ); + REQUIRE(8 == bx::ceilLog2(256) ); + + { + uint32_t ii = 0; + for (; ii < 8; ++ii) + { + REQUIRE(ii == bx::ceilLog2(uint8_t(1<(1) ); + REQUIRE( 7 == bx::countTrailingZeros(1<<7) ); + REQUIRE( 8 == bx::countTrailingZeros(0) ); + REQUIRE( 1 == bx::countTrailingZeros(0x3e) ); + REQUIRE( 0 == bx::countTrailingZeros(1) ); + REQUIRE(15 == bx::countTrailingZeros(1<<15) ); + REQUIRE(16 == bx::countTrailingZeros(0) ); + REQUIRE( 0 == bx::countTrailingZeros(1) ); + REQUIRE(32 == bx::countTrailingZeros(0) ); + REQUIRE(31 == bx::countTrailingZeros(1u<<31) ); + REQUIRE( 0 == bx::countTrailingZeros(1) ); + REQUIRE(64 == bx::countTrailingZeros(0) ); +} + +TEST_CASE("countLeadingZeros", "[math]") +{ + REQUIRE( 7 == bx::countLeadingZeros(1) ); + REQUIRE( 8 == bx::countLeadingZeros(0) ); + REQUIRE( 2 == bx::countLeadingZeros(0x3e) ); + REQUIRE(15 == bx::countLeadingZeros(1) ); + REQUIRE(16 == bx::countLeadingZeros(0) ); + REQUIRE(31 == bx::countLeadingZeros(1) ); + REQUIRE(32 == bx::countLeadingZeros(0) ); + REQUIRE(63 == bx::countLeadingZeros(1) ); + REQUIRE(64 == bx::countLeadingZeros(0) ); +} + +TEST_CASE("countBits", "[math]") +{ + REQUIRE( 0 == bx::countBits(0) ); + REQUIRE( 1 == bx::countBits(1) ); + + REQUIRE( 4 == bx::countBits(0x55) ); + REQUIRE( 8 == bx::countBits(0x5555) ); + REQUIRE(16 == bx::countBits(0x55555555) ); + REQUIRE(32 == bx::countBits(0x5555555555555555) ); + + REQUIRE( 8 == bx::countBits(UINT8_MAX) ); + REQUIRE(16 == bx::countBits(UINT16_MAX) ); + REQUIRE(32 == bx::countBits(UINT32_MAX) ); + REQUIRE(64 == bx::countBits(UINT64_MAX) ); +} + +TEST_CASE("findFirstSet", "[math]") +{ + REQUIRE( 1 == bx::findFirstSet(1) ); + REQUIRE( 8 == bx::findFirstSet(1<<7) ); + REQUIRE( 0 == bx::findFirstSet(0) ); + REQUIRE( 2 == bx::findFirstSet(0x3e) ); + REQUIRE( 1 == bx::findFirstSet(1) ); + REQUIRE(16 == bx::findFirstSet(1<<15) ); + REQUIRE( 0 == bx::findFirstSet(0) ); + REQUIRE( 1 == bx::findFirstSet(1) ); + REQUIRE( 0 == bx::findFirstSet(0) ); + REQUIRE(32 == bx::findFirstSet(1u<<31) ); + REQUIRE( 1 == bx::findFirstSet(1) ); + REQUIRE( 0 == bx::findFirstSet(0) ); } BX_PRAGMA_DIAGNOSTIC_PUSH(); diff --git a/tests/uint32_test.cpp b/tests/uint32_test.cpp index 31a4314..a0621bf 100644 --- a/tests/uint32_test.cpp +++ b/tests/uint32_test.cpp @@ -28,61 +28,6 @@ TEST_CASE("StrideAlign", "[uint32_t]") REQUIRE(offset == 48); } -TEST_CASE("uint32_cnt", "[uint32_t]") -{ - REQUIRE( 0 == bx::uint32_cnttz(1) ); - REQUIRE( 7 == bx::uint32_cnttz(1<<7) ); - REQUIRE( 8 == bx::uint32_cnttz(0) ); - REQUIRE( 1 == bx::uint32_cnttz(0x3e) ); - REQUIRE( 0 == bx::uint32_cnttz(1) ); - REQUIRE(15 == bx::uint32_cnttz(1<<15) ); - REQUIRE(16 == bx::uint32_cnttz(0) ); - REQUIRE( 0 == bx::uint32_cnttz(1) ); - REQUIRE(32 == bx::uint32_cnttz(0) ); - REQUIRE(31 == bx::uint32_cnttz(1u<<31) ); - REQUIRE( 0 == bx::uint32_cnttz(1) ); - REQUIRE(64 == bx::uint32_cnttz(0) ); - - REQUIRE( 7 == bx::uint32_cntlz(1) ); - REQUIRE( 8 == bx::uint32_cntlz(0) ); - REQUIRE( 2 == bx::uint32_cntlz(0x3e) ); - REQUIRE(15 == bx::uint32_cntlz(1) ); - REQUIRE(16 == bx::uint32_cntlz(0) ); - REQUIRE(31 == bx::uint32_cntlz(1) ); - REQUIRE(32 == bx::uint32_cntlz(0) ); - REQUIRE(63 == bx::uint32_cntlz(1) ); - REQUIRE(64 == bx::uint32_cntlz(0) ); - - REQUIRE( 0 == bx::uint32_cntbits(0) ); - REQUIRE( 1 == bx::uint32_cntbits(1) ); - - REQUIRE( 4 == bx::uint32_cntbits(0x55) ); - REQUIRE( 8 == bx::uint32_cntbits(0x5555) ); - REQUIRE(16 == bx::uint32_cntbits(0x55555555) ); - REQUIRE(32 == bx::uint32_cntbits(0x5555555555555555) ); - - REQUIRE( 8 == bx::uint32_cntbits(UINT8_MAX) ); - REQUIRE(16 == bx::uint32_cntbits(UINT16_MAX) ); - REQUIRE(32 == bx::uint32_cntbits(UINT32_MAX) ); - REQUIRE(64 == bx::uint32_cntbits(UINT64_MAX) ); -} - -TEST_CASE("uint32_ffs", "[uint32_t]") -{ - REQUIRE( 1 == bx::uint32_ffs(1) ); - REQUIRE( 8 == bx::uint32_ffs(1<<7) ); - REQUIRE( 0 == bx::uint32_ffs(0) ); - REQUIRE( 2 == bx::uint32_ffs(0x3e) ); - REQUIRE( 1 == bx::uint32_ffs(1) ); - REQUIRE(16 == bx::uint32_ffs(1<<15) ); - REQUIRE( 0 == bx::uint32_ffs(0) ); - REQUIRE( 1 == bx::uint32_ffs(1) ); - REQUIRE( 0 == bx::uint32_ffs(0) ); - REQUIRE(32 == bx::uint32_ffs(1u<<31) ); - REQUIRE( 1 == bx::uint32_ffs(1) ); - REQUIRE( 0 == bx::uint32_ffs(0) ); -} - TEST_CASE("uint32_part", "[uint32_t]") { REQUIRE(UINT32_C(0x55555555) == bx::uint32_part1by1(UINT16_MAX) );