Skip to content

Commit

Permalink
Add rive::math::msb()
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
csmartdalton and csmartdalton committed Aug 10, 2023
1 parent ac7d209 commit dcf7998
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .rive_head
Original file line number Diff line number Diff line change
@@ -1 +1 @@
58cc495802007c308ee4aa7b27dd755baaff7492
cbc6ba291319eb8c3f05894c859dfc86cc4dddea
23 changes: 22 additions & 1 deletion include/rive/math/math_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,31 @@ template <typename Dst, typename Src> Dst bit_cast(const Src& src)
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
20 changes: 20 additions & 0 deletions test/math_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,23 @@ TEST_CASE("bit_cast", "[math]")
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);
}

0 comments on commit dcf7998

Please sign in to comment.