Browse Source

LibJS: Add special cases for Math.cosh and add spec comments

Although this already works in most cases in non-kvm serenity cases the
cosh and other math function tend to return incorrect values for
Infinity. This makes sure that whatever the underlying cosh function
returns Math.cosh conforms to the spec.
davidot 2 years ago
parent
commit
b79f03182d

+ 13 - 0
Userland/Libraries/LibJS/Runtime/MathObject.cpp

@@ -498,9 +498,22 @@ JS_DEFINE_NATIVE_FUNCTION(MathObject::sinh)
 // 21.3.2.13 Math.cosh ( x ), https://tc39.es/ecma262/#sec-math.cosh
 JS_DEFINE_NATIVE_FUNCTION(MathObject::cosh)
 {
+    // 1. Let n be ? ToNumber(x).
     auto number = TRY(vm.argument(0).to_number(global_object));
+
+    // 2. If n is NaN, return NaN.
     if (number.is_nan())
         return js_nan();
+
+    // 3. If n is +∞𝔽 or n is -∞𝔽, return +∞𝔽.
+    if (number.is_positive_infinity() || number.is_negative_infinity())
+        return js_infinity();
+
+    // 4. If n is +0𝔽 or n is -0𝔽, return 1𝔽.
+    if (number.is_positive_zero() || number.is_negative_zero())
+        return Value(1);
+
+    // 5. Return an implementation-approximated Number value representing the result of the hyperbolic cosine of ℝ(n).
     return Value(::cosh(number.as_double()));
 }
 

+ 17 - 5
Userland/Libraries/LibJS/Tests/builtins/Math/Math.cosh.js

@@ -1,7 +1,19 @@
-test("basic functionality", () => {
-    expect(Math.cosh).toHaveLength(1);
+describe("basic functionality", () => {
+    test("length", () => {
+        expect(Math.cosh).toHaveLength(1);
+    });
 
-    expect(Math.cosh(0)).toBe(1);
-    expect(Math.cosh(1)).toBeCloseTo(1.5430806348152437);
-    expect(Math.cosh(-1)).toBeCloseTo(1.5430806348152437);
+    test("simple values", () => {
+        expect(Math.cosh(1)).toBeCloseTo(1.5430806348152437);
+        expect(Math.cosh(-1)).toBeCloseTo(1.5430806348152437);
+    });
+
+    test("special values", () => {
+        expect(Math.cosh(0)).toBe(1);
+        expect(Math.cosh(-0.0)).toBe(1);
+
+        expect(Math.cosh(NaN)).toBeNaN();
+        expect(Math.cosh(Infinity)).toBe(Infinity);
+        expect(Math.cosh(-Infinity)).toBe(Infinity);
+    });
 });