1
0
mirror of https://github.com/SerenityOS/serenity synced 2024-07-01 11:59:23 +00:00

AK: Make FixedPoint work on platforms without __int128

This commit is contained in:
Hendiadyoin1 2023-09-03 18:46:31 +02:00 committed by Andrew Kaster
parent de6664c0cb
commit 35e3e3d483

View File

@ -15,6 +15,10 @@
#ifndef KERNEL
# include <AK/Math.h>
#endif
#ifndef __SIZEOF_INT128__
# include <AK/UFixedBigInt.h>
# include <AK/UFixedBigIntDivision.h>
#endif
// Solaris' definition of signbit in math_c99.h conflicts with our implementation.
#ifdef AK_OS_SOLARIS
@ -208,13 +212,22 @@ public:
}
constexpr This operator*(This const& other) const
{
// FIXME: Figure out a way to use more narrow types and avoid __int128
#ifdef __SIZEOF_INT128__
// FIXME: Figure out a nicer way to use more narrow types and avoid __int128
using MulRes = Conditional<sizeof(Underlying) < sizeof(i64), i64, __int128>;
MulRes value = raw();
value *= other.raw();
This ret = create_raw(value >> precision);
#else
// Note: We sign extend the raw value to a u128 to emulate the signed multiplication
// done in the version above
// FIXME: Provide narrower intermediate results types
u128 value = { (u64)(i64)raw(), ~0ull * (raw() < 0) };
value *= (u64)(i64)other.raw();
This ret = create_raw((value >> precision).low());
#endif
// Rounding:
// If last bit cut off is 1:
if (value & (static_cast<Underlying>(1) << (precision - 1))) {
@ -232,7 +245,8 @@ public:
}
constexpr This operator/(This const& other) const
{
// FIXME: Figure out a way to use more narrow types and avoid __int128
#ifdef __SIZEOF_INT128__
// FIXME: Figure out a nicer way to use more narrow types and avoid __int128
using DivRes = Conditional<sizeof(Underlying) < sizeof(i64), i64, __int128>;
DivRes value = raw();
@ -240,6 +254,25 @@ public:
value /= other.raw();
return create_raw(value);
#else
// Note: We sign extend the raw value to a u128 to emulate the wide division
// done in the version above
if constexpr (sizeof(Underlying) > sizeof(u32)) {
u128 value = { (u64)(i64)raw(), ~0ull * (raw() < 0) };
value <<= precision;
value /= (u64)(i64)other.raw();
return create_raw(value.low());
}
// FIXME: Maybe allow going even narrower
using DivRes = Conditional<sizeof(Underlying) < sizeof(i32), i32, i64>;
DivRes value = raw();
value <<= precision;
value /= other.raw();
return create_raw(value);
#endif
}
template<Integral I>