From f589bedb0dee8babeab43c1e15651f091042a26f Mon Sep 17 00:00:00 2001 From: Shannon Booth Date: Tue, 2 Jan 2024 19:24:36 +1300 Subject: [PATCH] LibJS: Improve JS::modulo precision for large floating values JS::modulo was yielding a result of '0' for the input: ``` modulo(1., 18446744073709551616.) ``` Instead of the expected '1'. As far as I can tell the reason for this is that the repeated calls to fmod is losing precision in the calculation, leading to the wrong result. Fix this by only calling fmod once, and preserving the negative value behaviour by an 'if' check. Without this, the LibWeb text test: `/Streams/ReadableByteStream-enqueue-respond.html` Would hang forever after using this function in the IDL conversion of a u64 in ConvertToInt. This should also be more efficient :^) --- Userland/Libraries/LibJS/Runtime/AbstractOperations.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Userland/Libraries/LibJS/Runtime/AbstractOperations.h b/Userland/Libraries/LibJS/Runtime/AbstractOperations.h index daf2a5ecd7..f73d3bcdaf 100644 --- a/Userland/Libraries/LibJS/Runtime/AbstractOperations.h +++ b/Userland/Libraries/LibJS/Runtime/AbstractOperations.h @@ -300,7 +300,8 @@ auto modulo(T x, U y) if constexpr (IsFloatingPoint || IsFloatingPoint) { if constexpr (IsFloatingPoint) VERIFY(isfinite(y)); - return fmod(fmod(x, y) + y, y); + auto r = fmod(x, y); + return r < 0 ? r + y : r; } else { return ((x % y) + y) % y; }