Skip to content

Commit 5b0f62a

Browse files
authored
fix(math): correct Math.acosh for large finite inputs (boa-dev#5230)
This Pull Request fixes/closes boa-dev#5229. It changes the following: - When the input is finite and greater than `1/√f64::EPSILON` (`67_108_864.0`), fall back to `n.ln() + LN_2` instead of calling `f64::acosh()` directly, avoiding an internal `x²` overflow that produces `Infinity`. Threshold follows the [Boost math library convention](https://www.boost.org/doc/libs/latest/libs/math/doc/html/math_toolkit/inv_hyper/acosh.html). - Add regression tests for `Math.acosh(1e308)` and `Math.acosh(Number.MAX_VALUE)`. Testing: ```bash cargo test -p boa_engine math -- --nocapture ``` Spec reference: https://tc39.es/ecma262/#sec-math.acosh
1 parent 66a1cd2 commit 5b0f62a

File tree

2 files changed

+16
-10
lines changed

2 files changed

+16
-10
lines changed

core/engine/src/builtins/math/mod.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -153,16 +153,20 @@ impl Math {
153153
/// [spec]: https://tc39.es/ecma262/#sec-math.acosh
154154
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/acosh
155155
pub(crate) fn acosh(_: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
156-
Ok(args
157-
.get_or_undefined(0)
158-
// 1. Let n be ? ToNumber(x).
159-
.to_number(context)?
160-
// 4. If n < 1𝔽, return NaN.
161-
// 2. If n is NaN or n is +∞𝔽, return n.
162-
// 3. If n is 1𝔽, return +0𝔽.
163-
// 5. Return an implementation-approximated value representing the result of the inverse hyperbolic cosine of ℝ(n).
164-
.acosh()
165-
.into())
156+
// 1/√f64::EPSILON, as established by the Boost math library.
157+
const ACOSH_LARGE_INPUT_THRESHOLD: f64 = 67_108_864.0;
158+
159+
// 1. Let n be ? ToNumber(x).
160+
let n = args.get_or_undefined(0).to_number(context)?;
161+
if n.is_finite() && n > ACOSH_LARGE_INPUT_THRESHOLD {
162+
return Ok((n.ln() + std::f64::consts::LN_2).into());
163+
}
164+
165+
// 4. If n < 1𝔽, return NaN.
166+
// 2. If n is NaN or n is +∞𝔽, return n.
167+
// 3. If n is 1𝔽, return +0𝔽.
168+
// 5. Return an implementation-approximated value representing the result of the inverse hyperbolic cosine of ℝ(n).
169+
Ok(n.acosh().into())
166170
}
167171

168172
/// Get the arcsine of a number.

core/engine/src/builtins/math/tests.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ fn acosh() {
2424
TestAction::assert_eq("Math.acosh(2)", 1.316_957_896_924_816_6),
2525
TestAction::assert_eq("Math.acosh(-1)", f64::NAN),
2626
TestAction::assert_eq("Math.acosh(0.5)", f64::NAN),
27+
TestAction::assert_eq("Math.acosh(1e308)", 709.889_355_822_726_f64),
28+
TestAction::assert_eq("Math.acosh(Number.MAX_VALUE)", 710.475_860_073_943_9_f64),
2729
]);
2830
}
2931

0 commit comments

Comments
 (0)