From 35e3e3d483ddbdb2aa18ce1484d48e9b0eebd901 Mon Sep 17 00:00:00 2001 From: Hendiadyoin1 Date: Sun, 3 Sep 2023 18:46:31 +0200 Subject: [PATCH] AK: Make FixedPoint work on platforms without __int128 --- AK/FixedPoint.h | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/AK/FixedPoint.h b/AK/FixedPoint.h index 144f697914..708aefdabb 100644 --- a/AK/FixedPoint.h +++ b/AK/FixedPoint.h @@ -15,6 +15,10 @@ #ifndef KERNEL # include #endif +#ifndef __SIZEOF_INT128__ +# include +# include +#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; - 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(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; 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; + DivRes value = raw(); + value <<= precision; + value /= other.raw(); + + return create_raw(value); +#endif } template