mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 17:07:46 +00:00
AK: Add FixedPoint base 2 logarithm
The log base 2 is implemented using the binary logarithm algorithm by Clay Turner (see the link in the comment)
This commit is contained in:
parent
30002c2ccb
commit
98058f7efe
2 changed files with 48 additions and 0 deletions
|
@ -8,7 +8,9 @@
|
||||||
|
|
||||||
#include <AK/Concepts.h>
|
#include <AK/Concepts.h>
|
||||||
#include <AK/Format.h>
|
#include <AK/Format.h>
|
||||||
|
#include <AK/IntegralMath.h>
|
||||||
#include <AK/Math.h>
|
#include <AK/Math.h>
|
||||||
|
#include <AK/NumericLimits.h>
|
||||||
#include <AK/Types.h>
|
#include <AK/Types.h>
|
||||||
|
|
||||||
namespace AK {
|
namespace AK {
|
||||||
|
@ -116,6 +118,39 @@ public:
|
||||||
: 0);
|
: 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// http://www.claysturner.com/dsp/BinaryLogarithm.pdf
|
||||||
|
constexpr This log2() const
|
||||||
|
{
|
||||||
|
// 0.5
|
||||||
|
This b = create_raw(1 << (precision - 1));
|
||||||
|
This y = 0;
|
||||||
|
This x = *this;
|
||||||
|
|
||||||
|
// FIXME: There's no negative infinity.
|
||||||
|
if (x.raw() <= 0)
|
||||||
|
return create_raw(NumericLimits<Underlying>::min());
|
||||||
|
|
||||||
|
if (x != 1) {
|
||||||
|
i32 shift_amount = AK::log2<Underlying>(x.raw()) - precision;
|
||||||
|
if (shift_amount > 0)
|
||||||
|
x >>= shift_amount;
|
||||||
|
else
|
||||||
|
x <<= -shift_amount;
|
||||||
|
y += shift_amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < precision; ++i) {
|
||||||
|
x *= x;
|
||||||
|
if (x >= 2) {
|
||||||
|
x >>= 1;
|
||||||
|
y += b;
|
||||||
|
}
|
||||||
|
b >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
constexpr bool signbit() const requires(IsSigned<Underlying>)
|
constexpr bool signbit() const requires(IsSigned<Underlying>)
|
||||||
{
|
{
|
||||||
return m_value >> (sizeof(Underlying) * 8 - 1);
|
return m_value >> (sizeof(Underlying) * 8 - 1);
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <LibTest/TestCase.h>
|
#include <LibTest/TestCase.h>
|
||||||
|
|
||||||
#include <AK/FixedPoint.h>
|
#include <AK/FixedPoint.h>
|
||||||
|
#include <AK/NumericLimits.h>
|
||||||
|
|
||||||
using Type = FixedPoint<4>;
|
using Type = FixedPoint<4>;
|
||||||
|
|
||||||
|
@ -73,6 +74,18 @@ TEST_CASE(rounding)
|
||||||
EXPECT_EQ(Type(-1.5).ltrunk(), -1);
|
EXPECT_EQ(Type(-1.5).ltrunk(), -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE(logarithm)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(Type(0).log2().raw(), NumericLimits<int>::min());
|
||||||
|
EXPECT_EQ(Type(1).log2(), Type(0));
|
||||||
|
EXPECT_EQ(Type(2).log2(), Type(1));
|
||||||
|
EXPECT_EQ(Type(8).log2(), Type(3));
|
||||||
|
EXPECT_EQ(Type(0.5).log2(), Type(-1));
|
||||||
|
|
||||||
|
EXPECT_EQ(Type(22.627416997969520780827019587355).log2(), Type(4.4375));
|
||||||
|
EXPECT_EQ(Type(3088).log2(), Type(11.592457037268080419637304576833));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE(comparison)
|
TEST_CASE(comparison)
|
||||||
{
|
{
|
||||||
EXPECT(Type(0) < 1);
|
EXPECT(Type(0) < 1);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue