Add rive::math::msb() Adds a method that can be used to find the location of the most significant bit of a uint32_t. Diffs= cbc6ba291 Add rive::math::msb() (#5777) Co-authored-by: Chris Dalton <99840794+csmartdalton@users.noreply.github.com>
diff --git a/.rive_head b/.rive_head index 1e13964..1e45a30 100644 --- a/.rive_head +++ b/.rive_head
@@ -1 +1 @@ -58cc495802007c308ee4aa7b27dd755baaff7492 +cbc6ba291319eb8c3f05894c859dfc86cc4dddea
diff --git a/include/rive/math/math_types.hpp b/include/rive/math/math_types.hpp index 1b6db5f..a830408 100644 --- a/include/rive/math/math_types.hpp +++ b/include/rive/math/math_types.hpp
@@ -59,10 +59,31 @@ RIVE_INLINE_MEMCPY(&dst, &src, sizeof(Dst)); return dst; } + +// Returns the 1-based index of the most significat bit in x. +// +// 0 -> 0 +// 1 -> 1 +// 2..3 -> 2 +// 4..7 -> 3 +// ... +// +RIVE_ALWAYS_INLINE static uint32_t msb(uint32_t x) +{ + if (x == 0) + { + return 0; // __builtin_clz is undefined for x=0, and the double method doesn't work either. + } +#if defined(__clang__) || defined(__GNUC__) + return 32 - __builtin_clz(x); +#else + uint64_t doubleBits = bit_cast<uint64_t>(static_cast<double>(x)); + return (doubleBits >> 52) - 1022; +#endif +} } // namespace math template <typename T> T lerp(const T& a, const T& b, float t) { return a + (b - a) * t; } - } // namespace rive #endif
diff --git a/test/math_test.cpp b/test/math_test.cpp index 7057b84..63bfabf 100644 --- a/test/math_test.cpp +++ b/test/math_test.cpp
@@ -60,3 +60,23 @@ CHECK(math::bit_cast<float>((1u << 31) | 0x7f800000) == -kInf); CHECK(std::isnan(math::bit_cast<float>(0x7fc00000))); } + +// Check math::nextlog2. +TEST_CASE("nextlog2", "[math]") +{ + CHECK(math::msb(0) == 0); + CHECK(math::msb(1) == 1); + CHECK(math::msb(2) == 2); + CHECK(math::msb(3) == 2); + CHECK(math::msb(4) == 3); + CHECK(math::msb(5) == 3); + CHECK(math::msb(6) == 3); + CHECK(math::msb(7) == 3); + CHECK(math::msb(8) == 4); + CHECK(math::msb(9) == 4); + for (int i = 0; i < 29; ++i) + { + CHECK(math::msb(10 << i) == 4 + i); + } + CHECK(math::msb(0xffffffff) == 32); +}