diff --git a/std/assembly/math.ts b/std/assembly/math.ts index 97883c503b..1d79beeff6 100644 --- a/std/assembly/math.ts +++ b/std/assembly/math.ts @@ -63,12 +63,13 @@ function R(z: f64): f64 { // Rational approximation of (asin(x)-x)/x^3 /** @internal */ // @ts-ignore: decorator @inline -function expo2(x: f64): f64 { // exp(x)/2 for x >= log(DBL_MAX) +function expo2(x: f64, sign: f64): f64 { // exp(x)/2 for x >= log(DBL_MAX) const // see: musl/src/math/__expo2.c k = 2043, kln2 = reinterpret(0x40962066151ADD8B); // 0x1.62066151add8bp+10 var scale = reinterpret(((0x3FF + k / 2) << 20) << 32); - return NativeMath.exp(x - kln2) * scale * scale; + // in directed rounding correct sign before rounding or overflow is important + return NativeMath.exp(x - kln2) * (sign * scale) * scale; } /** @internal */ @@ -759,7 +760,7 @@ export namespace NativeMath { t = exp(x); return 0.5 * (t + 1 / t); } - t = expo2(x); + t = expo2(x, 1); return t; } @@ -1470,18 +1471,16 @@ export namespace NativeMath { var u = reinterpret(x) & 0x7FFFFFFFFFFFFFFF; var absx = reinterpret(u); var w = (u >> 32); - var t: f64; var h = builtin_copysign(0.5, x); if (w < 0x40862E42) { - t = expm1(absx); + let t = expm1(absx); if (w < 0x3FF00000) { if (w < 0x3FF00000 - (26 << 20)) return x; return h * (2 * t - t * t / (t + 1)); } return h * (t + t / (t + 1)); } - t = 2 * h * expo2(absx); - return t; + return expo2(absx, 2 * h); } // @ts-ignore: decorator @@ -1760,12 +1759,13 @@ function Rf(z: f32): f32 { // Rational approximation of (asin(x)-x)/x^3 // @ts-ignore: decorator @inline -function expo2f(x: f32): f32 { // exp(x)/2 for x >= log(DBL_MAX) +function expo2f(x: f32, sign: f32): f32 { // exp(x)/2 for x >= log(DBL_MAX) const // see: musl/src/math/__expo2f.c k = 235, kln2 = reinterpret(0x4322E3BC); // 0x1.45c778p+7f var scale = reinterpret((0x7F + (k >> 1)) << 23); - return NativeMathf.exp(x - kln2) * scale * scale; + // in directed rounding correct sign before rounding or overflow is important + return NativeMathf.exp(x - kln2) * (sign * scale) * scale; } // @ts-ignore: decorator @@ -2253,7 +2253,7 @@ export namespace NativeMathf { // return 0.5 * (t + 1 / t); return 0.5 * t + 0.5 / t; } - return expo2f(x); + return expo2f(x, 1); } // @ts-ignore: decorator @@ -2758,18 +2758,16 @@ export namespace NativeMathf { export function sinh(x: f32): f32 { // see: musl/src/math/sinhf.c var u = reinterpret(x) & 0x7FFFFFFF; var absx = reinterpret(u); - var t: f32; var h = builtin_copysign(0.5, x); if (u < 0x42B17217) { - t = expm1(absx); + let t = expm1(absx); if (u < 0x3F800000) { if (u < 0x3F800000 - (12 << 23)) return x; return h * (2 * t - t * t / (t + 1)); } return h * (t + t / (t + 1)); } - t = 2 * h * expo2f(absx); - return t; + return expo2f(absx, 2 * h); } // @ts-ignore: decorator @@ -3225,4 +3223,4 @@ switch (e) { ... case 63: } -*/ \ No newline at end of file +*/ diff --git a/tests/compiler/std/array.optimized.wat b/tests/compiler/std/array.optimized.wat index 43e72c0efc..94c9216dca 100644 --- a/tests/compiler/std/array.optimized.wat +++ b/tests/compiler/std/array.optimized.wat @@ -4236,7 +4236,7 @@ if i32.const 0 i32.const 6464 - i32.const 1398 + i32.const 1399 i32.const 5 call $~lib/builtins/abort unreachable diff --git a/tests/compiler/std/array.untouched.wat b/tests/compiler/std/array.untouched.wat index 6386143d5e..4c51579c86 100644 --- a/tests/compiler/std/array.untouched.wat +++ b/tests/compiler/std/array.untouched.wat @@ -7415,7 +7415,7 @@ if i32.const 0 i32.const 5456 - i32.const 1398 + i32.const 1399 i32.const 5 call $~lib/builtins/abort unreachable diff --git a/tests/compiler/std/math.optimized.wat b/tests/compiler/std/math.optimized.wat index e8b26cb48a..900b694d99 100644 --- a/tests/compiler/std/math.optimized.wat +++ b/tests/compiler/std/math.optimized.wat @@ -8432,7 +8432,7 @@ if i32.const 0 i32.const 3616 - i32.const 1398 + i32.const 1399 i32.const 5 call $~lib/builtins/abort unreachable @@ -9672,18 +9672,18 @@ f64.mul return end - f64.const 2 - local.get $2 - f64.mul local.get $1 f64.const 1416.0996898839683 f64.sub call $~lib/math/NativeMath.exp - f64.const 2247116418577894884661631e283 + f64.const 2 + local.get $2 f64.mul f64.const 2247116418577894884661631e283 f64.mul f64.mul + f64.const 2247116418577894884661631e283 + f64.mul ) (func $std/math/test_sinh (param $0 f64) (param $1 f64) (param $2 f64) (result i32) local.get $0 @@ -9760,18 +9760,18 @@ f32.mul return end - f32.const 2 - local.get $3 - f32.mul local.get $1 f32.const 162.88958740234375 f32.sub call $~lib/math/NativeMathf.exp - f32.const 1661534994731144841129758e11 + f32.const 2 + local.get $3 f32.mul f32.const 1661534994731144841129758e11 f32.mul f32.mul + f32.const 1661534994731144841129758e11 + f32.mul ) (func $std/math/test_sinhf (param $0 f32) (param $1 f32) (param $2 f32) (result i32) local.get $0 diff --git a/tests/compiler/std/math.untouched.wat b/tests/compiler/std/math.untouched.wat index 6035f6844a..24502947e0 100644 --- a/tests/compiler/std/math.untouched.wat +++ b/tests/compiler/std/math.untouched.wat @@ -6435,6 +6435,7 @@ (local $3 f64) (local $4 f64) (local $5 f64) + (local $6 f64) local.get $0 i64.reinterpret_f64 local.set $1 @@ -6498,6 +6499,8 @@ return end local.get $0 + local.set $5 + f64.const 1 local.set $4 i32.const 1023 i32.const 2043 @@ -6510,14 +6513,16 @@ i64.const 32 i64.shl f64.reinterpret_i64 - local.set $5 - local.get $4 + local.set $6 + local.get $5 f64.const 1416.0996898839683 f64.sub call $~lib/math/NativeMath.exp - local.get $5 + local.get $4 + local.get $6 f64.mul - local.get $5 + f64.mul + local.get $6 f64.mul local.set $3 local.get $3 @@ -6980,6 +6985,7 @@ (local $1 i32) (local $2 f32) (local $3 f32) + (local $4 f32) local.get $0 i32.reinterpret_f32 local.set $1 @@ -7038,6 +7044,8 @@ return end local.get $0 + local.set $3 + f32.const 1 local.set $2 i32.const 127 i32.const 235 @@ -7047,14 +7055,16 @@ i32.const 23 i32.shl f32.reinterpret_i32 - local.set $3 - local.get $2 + local.set $4 + local.get $3 f32.const 162.88958740234375 f32.sub call $~lib/math/NativeMathf.exp - local.get $3 + local.get $2 + local.get $4 f32.mul - local.get $3 + f32.mul + local.get $4 f32.mul ) (func $std/math/test_coshf (param $0 f32) (param $1 f32) (param $2 f32) (param $3 i32) (result i32) @@ -11422,7 +11432,7 @@ if i32.const 0 i32.const 13360 - i32.const 1398 + i32.const 1399 i32.const 5 call $~lib/builtins/abort unreachable @@ -13489,14 +13499,14 @@ f64.const 0.5 local.get $0 f64.copysign - local.set $5 + local.set $4 local.get $3 i32.const 1082535490 i32.lt_u if local.get $2 call $~lib/math/NativeMath.expm1 - local.set $4 + local.set $5 local.get $3 i32.const 1072693248 i32.lt_u @@ -13512,14 +13522,14 @@ local.get $0 return end - local.get $5 - f64.const 2 local.get $4 + f64.const 2 + local.get $5 f64.mul - local.get $4 - local.get $4 + local.get $5 + local.get $5 f64.mul - local.get $4 + local.get $5 f64.const 1 f64.add f64.div @@ -13527,10 +13537,10 @@ f64.mul return end - local.get $5 - local.get $4 - local.get $4 local.get $4 + local.get $5 + local.get $5 + local.get $5 f64.const 1 f64.add f64.div @@ -13538,11 +13548,12 @@ f64.mul return end - f64.const 2 - local.get $5 - f64.mul local.get $2 local.set $6 + f64.const 2 + local.get $4 + f64.mul + local.set $5 i32.const 1023 i32.const 2043 i32.const 2 @@ -13559,13 +13570,12 @@ f64.const 1416.0996898839683 f64.sub call $~lib/math/NativeMath.exp + local.get $5 local.get $7 f64.mul - local.get $7 f64.mul + local.get $7 f64.mul - local.set $4 - local.get $4 ) (func $std/math/test_sinh (param $0 f64) (param $1 f64) (param $2 f64) (param $3 i32) (result i32) local.get $0 @@ -13609,14 +13619,14 @@ f32.const 0.5 local.get $0 f32.copysign - local.set $4 + local.set $3 local.get $1 i32.const 1118925335 i32.lt_u if local.get $2 call $~lib/math/NativeMathf.expm1 - local.set $3 + local.set $4 local.get $1 i32.const 1065353216 i32.lt_u @@ -13632,14 +13642,14 @@ local.get $0 return end - local.get $4 - f32.const 2 local.get $3 + f32.const 2 + local.get $4 f32.mul - local.get $3 - local.get $3 + local.get $4 + local.get $4 f32.mul - local.get $3 + local.get $4 f32.const 1 f32.add f32.div @@ -13647,10 +13657,10 @@ f32.mul return end - local.get $4 - local.get $3 - local.get $3 local.get $3 + local.get $4 + local.get $4 + local.get $4 f32.const 1 f32.add f32.div @@ -13658,11 +13668,12 @@ f32.mul return end - f32.const 2 - local.get $4 - f32.mul local.get $2 local.set $5 + f32.const 2 + local.get $3 + f32.mul + local.set $4 i32.const 127 i32.const 235 i32.const 1 @@ -13676,13 +13687,12 @@ f32.const 162.88958740234375 f32.sub call $~lib/math/NativeMathf.exp + local.get $4 local.get $6 f32.mul - local.get $6 f32.mul + local.get $6 f32.mul - local.set $3 - local.get $3 ) (func $std/math/test_sinhf (param $0 f32) (param $1 f32) (param $2 f32) (param $3 i32) (result i32) local.get $0 diff --git a/tests/compiler/wasi/seed.optimized.wat b/tests/compiler/wasi/seed.optimized.wat index dd3bf9beee..1d8aa7d06c 100644 --- a/tests/compiler/wasi/seed.optimized.wat +++ b/tests/compiler/wasi/seed.optimized.wat @@ -297,7 +297,7 @@ (local $4 i32) i32.const 5 local.set $1 - i32.const 1398 + i32.const 1399 local.set $0 i32.const 0 i32.const 12 @@ -318,7 +318,7 @@ local.tee $2 i32.const 40 i32.store8 - i32.const 1398 + i32.const 1399 call $~lib/util/number/decimalCount32 local.tee $4 local.get $2 diff --git a/tests/compiler/wasi/seed.untouched.wat b/tests/compiler/wasi/seed.untouched.wat index 1b3bec1e6b..1dec2cce96 100644 --- a/tests/compiler/wasi/seed.untouched.wat +++ b/tests/compiler/wasi/seed.untouched.wat @@ -612,7 +612,7 @@ if i32.const 0 i32.const 32 - i32.const 1398 + i32.const 1399 i32.const 5 call $~lib/wasi/index/abort unreachable