diff options
author | Anonymous <anon@mous.org> | 2022-02-16 02:14:57 -0800 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2022-02-16 11:18:41 +0000 |
commit | 1e0facb7ee71a8611052b4f87bd36a435d35050a (patch) | |
tree | 5d79ed00f44e5d4927a35c373dcc0514ba29bc95 | |
parent | 602190f66f7d74bba019b42870d1fc93e5a26a51 (diff) | |
download | serenity-1e0facb7ee71a8611052b4f87bd36a435d35050a.zip |
LibJS: Implement the Number::remainder AO using fmod
The ECMA verbiage for modulus is the mathematical definition implemented
by fmod, so let's just use that rather than trying to reimplement all
the edge cases.
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/Value.cpp | 35 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Tests/operators/modulo-basic.js | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Tests/test-common.js | 3 |
3 files changed, 9 insertions, 30 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/Value.cpp b/Userland/Libraries/LibJS/Runtime/Value.cpp index 01f14e2be3..60e59714d4 100644 --- a/Userland/Libraries/LibJS/Runtime/Value.cpp +++ b/Userland/Libraries/LibJS/Runtime/Value.cpp @@ -1178,36 +1178,11 @@ ThrowCompletionOr<Value> mod(GlobalObject& global_object, Value lhs, Value rhs) auto rhs_numeric = TRY(rhs.to_numeric(global_object)); if (both_number(lhs_numeric, rhs_numeric)) { // 6.1.6.1.6 Number::remainder ( n, d ), https://tc39.es/ecma262/#sec-numeric-types-number-remainder - - // 1. If n is NaN or d is NaN, return NaN. - if (lhs_numeric.is_nan() || rhs_numeric.is_nan()) - return js_nan(); - - // 2. If n is +∞𝔽 or n is -∞𝔽, return NaN. - if (lhs_numeric.is_positive_infinity() || lhs_numeric.is_negative_infinity()) - return js_nan(); - - // 3. If d is +∞𝔽 or d is -∞𝔽, return n. - if (rhs_numeric.is_positive_infinity() || rhs_numeric.is_negative_infinity()) - return lhs_numeric; - - // 4. If d is +0𝔽 or d is -0𝔽, return NaN. - if (rhs_numeric.is_positive_zero() || rhs_numeric.is_negative_zero()) - return js_nan(); - - // 5. If n is +0𝔽 or n is -0𝔽, return n. - if (lhs_numeric.is_positive_zero() || lhs_numeric.is_negative_zero()) - return lhs_numeric; - - // 6. Assert: n and d are finite and non-zero. - - auto index = lhs_numeric.as_double(); - auto period = rhs_numeric.as_double(); - auto trunc = (double)(i32)(index / period); - - // 7. Let r be ℝ(n) - (ℝ(d) × q) where q is an integer that is negative if and only if n and d have opposite sign, and whose magnitude is as large as possible without exceeding the magnitude of ℝ(n) / ℝ(d). - // 8. Return 𝔽(r). - return Value(index - trunc * period); + // The ECMA specification is describing the mathematical definition of modulus + // implemented by fmod. + auto n = lhs_numeric.as_double(); + auto d = rhs_numeric.as_double(); + return Value(fmod(n, d)); } if (both_bigint(lhs_numeric, rhs_numeric)) { if (rhs_numeric.as_bigint().big_integer() == BIGINT_ZERO) diff --git a/Userland/Libraries/LibJS/Tests/operators/modulo-basic.js b/Userland/Libraries/LibJS/Tests/operators/modulo-basic.js index c364feaddb..0c30123be9 100644 --- a/Userland/Libraries/LibJS/Tests/operators/modulo-basic.js +++ b/Userland/Libraries/LibJS/Tests/operators/modulo-basic.js @@ -23,6 +23,7 @@ test("basic functionality", () => { expect(1 % -0).toBeNaN(); expect(0 % 5).toBe(0); expect(-0 % 5).toBe(-0); + expect((-1) % -1).toBe(-0); // test262 examples expect(1 % null).toBeNaN(); diff --git a/Userland/Libraries/LibJS/Tests/test-common.js b/Userland/Libraries/LibJS/Tests/test-common.js index 1f9e3af979..b02c9cb287 100644 --- a/Userland/Libraries/LibJS/Tests/test-common.js +++ b/Userland/Libraries/LibJS/Tests/test-common.js @@ -53,6 +53,9 @@ class ExpectationError extends Error { const valueToString = value => { try { + if (value === 0 && 1 / value < 0) { + return "-0"; + } return String(value); } catch { // e.g for objects without a prototype, the above throws. |