AK: Make FixedPoint work on platforms without __int128
This commit is contained in:
parent
de6664c0cb
commit
35e3e3d483
Notes:
sideshowbarker
2024-07-17 05:06:13 +09:00
Author: https://github.com/Hendiadyoin1 Commit: https://github.com/SerenityOS/serenity/commit/35e3e3d483 Pull-request: https://github.com/SerenityOS/serenity/pull/20939 Reviewed-by: https://github.com/ADKaster ✅ Reviewed-by: https://github.com/BertalanD Reviewed-by: https://github.com/bugaevc ✅
1 changed files with 36 additions and 3 deletions
|
@ -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>
|
||||
|
|
Loading…
Add table
Reference in a new issue