Skip to content

Commit c286e06

Browse files
authored
Align sinh with musl on overflows in non-nearest rounding (#1421)
1 parent b622400 commit c286e06

File tree

7 files changed

+78
-70
lines changed

7 files changed

+78
-70
lines changed

Diff for: std/assembly/math.ts

+13-15
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,13 @@ function R(z: f64): f64 { // Rational approximation of (asin(x)-x)/x^3
6363
/** @internal */
6464
// @ts-ignore: decorator
6565
@inline
66-
function expo2(x: f64): f64 { // exp(x)/2 for x >= log(DBL_MAX)
66+
function expo2(x: f64, sign: f64): f64 { // exp(x)/2 for x >= log(DBL_MAX)
6767
const // see: musl/src/math/__expo2.c
6868
k = <u32>2043,
6969
kln2 = reinterpret<f64>(0x40962066151ADD8B); // 0x1.62066151add8bp+10
7070
var scale = reinterpret<f64>(<u64>((<u32>0x3FF + k / 2) << 20) << 32);
71-
return NativeMath.exp(x - kln2) * scale * scale;
71+
// in directed rounding correct sign before rounding or overflow is important
72+
return NativeMath.exp(x - kln2) * (sign * scale) * scale;
7273
}
7374

7475
/** @internal */
@@ -759,7 +760,7 @@ export namespace NativeMath {
759760
t = exp(x);
760761
return 0.5 * (t + 1 / t);
761762
}
762-
t = expo2(x);
763+
t = expo2(x, 1);
763764
return t;
764765
}
765766

@@ -1470,18 +1471,16 @@ export namespace NativeMath {
14701471
var u = reinterpret<u64>(x) & 0x7FFFFFFFFFFFFFFF;
14711472
var absx = reinterpret<f64>(u);
14721473
var w = <u32>(u >> 32);
1473-
var t: f64;
14741474
var h = builtin_copysign(0.5, x);
14751475
if (w < 0x40862E42) {
1476-
t = expm1(absx);
1476+
let t = expm1(absx);
14771477
if (w < 0x3FF00000) {
14781478
if (w < 0x3FF00000 - (26 << 20)) return x;
14791479
return h * (2 * t - t * t / (t + 1));
14801480
}
14811481
return h * (t + t / (t + 1));
14821482
}
1483-
t = 2 * h * expo2(absx);
1484-
return t;
1483+
return expo2(absx, 2 * h);
14851484
}
14861485

14871486
// @ts-ignore: decorator
@@ -1760,12 +1759,13 @@ function Rf(z: f32): f32 { // Rational approximation of (asin(x)-x)/x^3
17601759

17611760
// @ts-ignore: decorator
17621761
@inline
1763-
function expo2f(x: f32): f32 { // exp(x)/2 for x >= log(DBL_MAX)
1762+
function expo2f(x: f32, sign: f32): f32 { // exp(x)/2 for x >= log(DBL_MAX)
17641763
const // see: musl/src/math/__expo2f.c
17651764
k = <u32>235,
17661765
kln2 = reinterpret<f32>(0x4322E3BC); // 0x1.45c778p+7f
17671766
var scale = reinterpret<f32>(<u32>(0x7F + (k >> 1)) << 23);
1768-
return NativeMathf.exp(x - kln2) * scale * scale;
1767+
// in directed rounding correct sign before rounding or overflow is important
1768+
return NativeMathf.exp(x - kln2) * (sign * scale) * scale;
17691769
}
17701770

17711771
// @ts-ignore: decorator
@@ -2253,7 +2253,7 @@ export namespace NativeMathf {
22532253
// return 0.5 * (t + 1 / t);
22542254
return 0.5 * t + 0.5 / t;
22552255
}
2256-
return expo2f(x);
2256+
return expo2f(x, 1);
22572257
}
22582258

22592259
// @ts-ignore: decorator
@@ -2758,18 +2758,16 @@ export namespace NativeMathf {
27582758
export function sinh(x: f32): f32 { // see: musl/src/math/sinhf.c
27592759
var u = reinterpret<u32>(x) & 0x7FFFFFFF;
27602760
var absx = reinterpret<f32>(u);
2761-
var t: f32;
27622761
var h = builtin_copysign<f32>(0.5, x);
27632762
if (u < 0x42B17217) {
2764-
t = expm1(absx);
2763+
let t = expm1(absx);
27652764
if (u < 0x3F800000) {
27662765
if (u < 0x3F800000 - (12 << 23)) return x;
27672766
return h * (2 * t - t * t / (t + 1));
27682767
}
27692768
return h * (t + t / (t + 1));
27702769
}
2771-
t = 2 * h * expo2f(absx);
2772-
return t;
2770+
return expo2f(absx, 2 * h);
27732771
}
27742772

27752773
// @ts-ignore: decorator
@@ -3225,4 +3223,4 @@ switch (e) {
32253223
...
32263224
case 63:
32273225
}
3228-
*/
3226+
*/

Diff for: tests/compiler/std/array.optimized.wat

+1-1
Original file line numberDiff line numberDiff line change
@@ -4236,7 +4236,7 @@
42364236
if
42374237
i32.const 0
42384238
i32.const 6464
4239-
i32.const 1398
4239+
i32.const 1399
42404240
i32.const 5
42414241
call $~lib/builtins/abort
42424242
unreachable

Diff for: tests/compiler/std/array.untouched.wat

+1-1
Original file line numberDiff line numberDiff line change
@@ -7412,7 +7412,7 @@
74127412
if
74137413
i32.const 0
74147414
i32.const 5456
7415-
i32.const 1398
7415+
i32.const 1399
74167416
i32.const 5
74177417
call $~lib/builtins/abort
74187418
unreachable

Diff for: tests/compiler/std/math.optimized.wat

+9-9
Original file line numberDiff line numberDiff line change
@@ -8432,7 +8432,7 @@
84328432
if
84338433
i32.const 0
84348434
i32.const 3616
8435-
i32.const 1398
8435+
i32.const 1399
84368436
i32.const 5
84378437
call $~lib/builtins/abort
84388438
unreachable
@@ -9672,18 +9672,18 @@
96729672
f64.mul
96739673
return
96749674
end
9675-
f64.const 2
9676-
local.get $2
9677-
f64.mul
96789675
local.get $1
96799676
f64.const 1416.0996898839683
96809677
f64.sub
96819678
call $~lib/math/NativeMath.exp
9682-
f64.const 2247116418577894884661631e283
9679+
f64.const 2
9680+
local.get $2
96839681
f64.mul
96849682
f64.const 2247116418577894884661631e283
96859683
f64.mul
96869684
f64.mul
9685+
f64.const 2247116418577894884661631e283
9686+
f64.mul
96879687
)
96889688
(func $std/math/test_sinh (param $0 f64) (param $1 f64) (param $2 f64) (result i32)
96899689
local.get $0
@@ -9760,18 +9760,18 @@
97609760
f32.mul
97619761
return
97629762
end
9763-
f32.const 2
9764-
local.get $3
9765-
f32.mul
97669763
local.get $1
97679764
f32.const 162.88958740234375
97689765
f32.sub
97699766
call $~lib/math/NativeMathf.exp
9770-
f32.const 1661534994731144841129758e11
9767+
f32.const 2
9768+
local.get $3
97719769
f32.mul
97729770
f32.const 1661534994731144841129758e11
97739771
f32.mul
97749772
f32.mul
9773+
f32.const 1661534994731144841129758e11
9774+
f32.mul
97759775
)
97769776
(func $std/math/test_sinhf (param $0 f32) (param $1 f32) (param $2 f32) (result i32)
97779777
local.get $0

0 commit comments

Comments
 (0)