Implement Mathf.sin/cos/tan (#491)

This commit is contained in:
Max Graey 2019-03-05 20:36:22 +02:00 committed by Daniel Wirtz
parent 8e5b9c734b
commit 208dc2f1de
7 changed files with 29448 additions and 20485 deletions

View File

@ -1401,12 +1401,18 @@ interface IMath<T> {
}
interface INativeMath<T> extends IMath<T> {
/** Contains sin value produced after Math/Mathf.sincos */
sincos_sin: T;
/** Contains cos value produced after Math/Mathf.sincos */
sincos_cos: T;
/** Seeds the random number generator. */
seedRandom(value: i64): void;
/** Returns the floating-point remainder of `x / y` (rounded towards zero). */
mod(x: T, y: T): T;
/** Returns the floating-point remainder of `x / y` (rounded to nearest). */
rem(x: T, y: T): T;
/** Returns sin and cos simultaneously for same angle. Results stored to `sincos_s32/64` and `sincos_c32/64` globals */
sincos(x: T): void;
}
/** Double precision math imported from JavaScript. */

View File

@ -22,8 +22,9 @@ import {
//
// Applies to all functions marked with a comment referring here.
// TODO: sin, cos, tan
// TODO: sin, cos, tan for Math namespace
/** @internal */
function R(z: f64): f64 { // Rational approximation of (asin(x)-x)/x^3
const // see: musl/src/math/asin.c and SUN COPYRIGHT NOTICE above
pS0 = reinterpret<f64>(0x3FC5555555555555), // 1.66666666666666657415e-01
@ -49,6 +50,7 @@ function R(z: f64): f64 { // Rational approximation of (asin(x)-x)/x^3
return NativeMath.exp(x - kln2) * scale * scale;
}
/** @internal */
@lazy var random_seeded = false;
@lazy var random_state0_64: u64;
@lazy var random_state1_64: u64;
@ -1092,7 +1094,7 @@ export namespace NativeMath {
}
} else if (n < -1022) {
/* make sure final n < -53 to avoid double
rounding in the subnormal range */
rounding in the subnormal range */
y *= Ox1p_1022 * Ox1p53;
n += 1022 - 53;
if (n < -1022) {
@ -1230,6 +1232,16 @@ export namespace NativeMath {
}
}
/** @internal */
@lazy var rempio2f_y: f64;
@lazy const PIO2_TABLE: u64[] = [
0xA2F9836E4E441529,
0xFC2757D1F534DDC0,
0xDB6295993C439041,
0xFE5163ABDEBBC561
];
/** @internal */
function Rf(z: f32): f32 { // Rational approximation of (asin(x)-x)/x^3
const // see: musl/src/math/asinf.c and SUN COPYRIGHT NOTICE above
pS0 = reinterpret<f32>(0x3E2AAA75), // 1.6666586697e-01f
@ -1242,13 +1254,110 @@ function Rf(z: f32): f32 { // Rational approximation of (asin(x)-x)/x^3
}
@inline function expo2f(x: f32): f32 { // exp(x)/2 for x >= log(DBL_MAX)
const // see: musl/src/math/__expo2f.c
const // see: musl/src/math/__expo2f.c
k = <u32>235,
kln2 = reinterpret<f32>(0x4322E3BC); // 0x1.45c778p+7f
var scale = reinterpret<f32>(<u32>(0x7F + (k >> 1)) << 23);
return NativeMathf.exp(x - kln2) * scale * scale;
}
@inline /** @internal */
function pio2_large_quot(x: f32, u: i32): i32 { // see: jdh8/metallic/blob/master/src/math/float/rem_pio2f.c
const coeff = reinterpret<f64>(0x3BF921FB54442D18); // π * 0x1p-65 = 8.51530395021638647334e-20
const bits = PIO2_TABLE;
var offset = (u >> 23) - 152;
var index = offset >> 6;
var shift = offset & 63;
var b0 = unchecked(bits[index + 0]);
var b1 = unchecked(bits[index + 1]);
var lo: u64;
if (shift > 32) {
let b2 = unchecked(bits[index + 2]);
lo = b2 >> (96 - shift);
lo |= b1 << (shift - 32);
} else {
lo = b1 >> (32 - shift);
}
var hi = (b1 >> (64 - shift)) | (b0 << shift);
var mantissa: u64 = (u & 0x007FFFFF) | 0x00800000;
var product: u64 = mantissa * hi + (mantissa * lo >> 32);
var r: i64 = product << 2;
var q: i32 = <i32>((product >> 62) + (r >>> 63));
rempio2f_y = copysign<f64>(coeff, x) * <f64>r;
return q;
}
@inline /** @internal */
function rempio2f(x: f32, u: u32, sign: i32): i32 { // see: jdh8/metallic/blob/master/src/math/float/rem_pio2f.c
const pi2hi = reinterpret<f64>(0x3FF921FB50000000); // 1.57079631090164184570
const pi2lo = reinterpret<f64>(0x3E5110B4611A6263); // 1.58932547735281966916e-8
const _2_pi = reinterpret<f64>(0x3FE45F306DC9C883); // 0.63661977236758134308
if (u < 0x4DC90FDB) { /* π * 0x1p28 */
let q = nearest(x * _2_pi);
rempio2f_y = x - q * pi2hi - q * pi2lo;
return <i32>q;
}
var q = pio2_large_quot(x, u);
return select(-q, q, sign);
}
/* |sin(x)/x - s(x)| < 2**-37.5 (~[-4.89e-12, 4.824e-12]). */
@inline /** @internal */
function sin_kernf(x: f64): f32 { // see: musl/tree/src/math/__sindf.c
const S1 = reinterpret<f64>(0xBFC5555554CBAC77); // -0x15555554cbac77.0p-55
const S2 = reinterpret<f64>(0x3F811110896EFBB2); // 0x111110896efbb2.0p-59
const S3 = reinterpret<f64>(0xBF2A00F9E2CAE774); // -0x1a00f9e2cae774.0p-65
const S4 = reinterpret<f64>(0x3EC6CD878C3B46A7); // 0x16cd878c3b46a7.0p-71
var z = x * x;
var w = z * z;
var r = S3 + z * S4;
var s = z * x;
return <f32>((x + s * (S1 + z * S2)) + s * w * r);
}
/* |cos(x) - c(x)| < 2**-34.1 (~[-5.37e-11, 5.295e-11]). */
@inline /** @internal */
function cos_kernf(x: f64): f32 { // see: musl/tree/src/math/__cosdf.c
const C0 = reinterpret<f64>(0xBFDFFFFFFD0C5E81); // -0x1ffffffd0c5e81.0p-54
const C1 = reinterpret<f64>(0x3FA55553E1053A42); // 0x155553e1053a42.0p-57
const C2 = reinterpret<f64>(0xBF56C087E80F1E27); // -0x16c087e80f1e27.0p-62
const C3 = reinterpret<f64>(0x3EF99342E0EE5069); // 0x199342e0ee5069.0p-68
var z = x * x;
var w = z * z;
var r = C2 + z * C3;
return <f32>(((1 + z * C0) + w * C1) + (w * z) * r);
}
/* |tan(x)/x - t(x)| < 2**-25.5 (~[-2e-08, 2e-08]). */
@inline /** @internal */
function tan_kernf(x: f64, odd: i32): f32 { // see: musl/tree/src/math/__tandf.c
const T0 = reinterpret<f64>(0x3FD5554D3418C99F); /* 0x15554d3418c99f.0p-54 */
const T1 = reinterpret<f64>(0x3FC112FD38999F72); /* 0x1112fd38999f72.0p-55 */
const T2 = reinterpret<f64>(0x3FAB54C91D865AFE); /* 0x1b54c91d865afe.0p-57 */
const T3 = reinterpret<f64>(0x3F991DF3908C33CE); /* 0x191df3908c33ce.0p-58 */
const T4 = reinterpret<f64>(0x3F685DADFCECF44E); /* 0x185dadfcecf44e.0p-61 */
const T5 = reinterpret<f64>(0x3F8362B9BF971BCD); /* 0x1362b9bf971bcd.0p-59 */
var z = x * x;
var r = T4 + z * T5;
var t = T2 + z * T3;
var w = z * z;
var s = z * x;
var u = T0 + z * T1;
r = (x + s * u) + (s * w) * (t + w * r);
return <f32>(odd ? -1 / r : r);
}
export namespace NativeMathf {
@lazy export const E = <f32>NativeMath.E;
@ -1260,6 +1369,10 @@ export namespace NativeMathf {
@lazy export const SQRT1_2 = <f32>NativeMath.SQRT1_2;
@lazy export const SQRT2 = <f32>NativeMath.SQRT2;
/** Used as return values from Mathf.sincos */
@lazy export var sincos_sin: f32 = 0;
@lazy export var sincos_cos: f32 = 0;
@inline
export function abs(x: f32): f32 {
return builtin_abs<f32>(x);
@ -1508,9 +1621,50 @@ export namespace NativeMathf {
);
}
export function cos(x: f32): f32 { // TODO
unreachable();
return 0;
export function cos(x: f32): f32 { // see: musl/src/math/cosf.c
const c1pio2 = reinterpret<f64>(0x3FF921FB54442D18); // M_PI_2 * 1
const c2pio2 = reinterpret<f64>(0x400921FB54442D18); // M_PI_2 * 2
const c3pio2 = reinterpret<f64>(0x4012D97C7F3321D2); // M_PI_2 * 3
const c4pio2 = reinterpret<f64>(0x401921FB54442D18); // M_PI_2 * 4
var ix = reinterpret<u32>(x);
var sign = ix >> 31;
ix &= 0x7FFFFFFF;
if (ix <= 0x3f490fda) { /* |x| ~<= π/4 */
if (ix < 0x39800000) { /* |x| < 2**-12 */
/* raise inexact if x != 0 */
return 1;
}
return cos_kernf(x);
}
if (ASC_SHRINK_LEVEL < 1) {
if (ix <= 0x407b53d1) { /* |x| ~<= 5π/4 */
if (ix > 0x4016cbe3) { /* |x| ~> 3π/4 */
return -cos_kernf(sign ? x + c2pio2 : x - c2pio2);
} else {
return sign ? sin_kernf(x + c1pio2) : sin_kernf(c1pio2 - x);
}
}
if (ix <= 0x40e231d5) { /* |x| ~<= 9π/4 */
if (ix > 0x40afeddf) { /* |x| ~> 7π/4 */
return cos_kernf(sign ? x + c4pio2 : x - c4pio2);
} else {
return sign ? sin_kernf(-x - c3pio2) : sin_kernf(x - c3pio2);
}
}
}
/* cos(Inf or NaN) is NaN */
if (ix >= 0x7f800000) return x - x;
/* general argument reduction needed */
var n = rempio2f(x, ix, sign);
var y = rempio2f_y;
var t = n & 1 ? sin_kernf(y) : cos_kernf(y);
return (n + 1) & 2 ? -t : t;
}
export function cosh(x: f32): f32 { // see: musl/src/math/coshf.c
@ -2094,9 +2248,47 @@ export namespace NativeMathf {
return <bool>((reinterpret<u32>(x) >>> 31) & (x == x));
}
export function sin(x: f32): f32 { // TODO
unreachable();
return 0;
export function sin(x: f32): f32 { // see: musl/src/math/sinf.c
const s1pio2 = reinterpret<f64>(0x3FF921FB54442D18); // M_PI_2 * 1
const s2pio2 = reinterpret<f64>(0x400921FB54442D18); // M_PI_2 * 2
const s3pio2 = reinterpret<f64>(0x4012D97C7F3321D2); // M_PI_2 * 3
const s4pio2 = reinterpret<f64>(0x401921FB54442D18); // M_PI_2 * 4
var ix = reinterpret<u32>(x);
var sign = ix >> 31;
ix &= 0x7FFFFFFF;
if (ix <= 0x3f490fda) { /* |x| ~<= π/4 */
if (ix < 0x39800000) { /* |x| < 2**-12 */
return x;
}
return sin_kernf(x);
}
if (ASC_SHRINK_LEVEL < 1) {
if (ix <= 0x407b53d1) { /* |x| ~<= 5π/4 */
if (ix <= 0x4016cbe3) { /* |x| ~<= 3π/4 */
return sign ? -cos_kernf(x + s1pio2) : cos_kernf(x - s1pio2);
}
return sin_kernf(-(sign ? x + s2pio2 : x - s2pio2));
}
if (ix <= 0x40e231d5) { /* |x| ~<= 9π/4 */
if (ix <= 0x40afeddf) { /* |x| ~<= 7π/4 */
return sign ? cos_kernf(x + s3pio2) : -cos_kernf(x - s3pio2);
}
return sin_kernf(sign ? x + s4pio2 : x - s4pio2);
}
}
/* sin(Inf or NaN) is NaN */
if (ix >= 0x7f800000) return x - x;
var n = rempio2f(x, ix, sign);
var y = rempio2f_y;
var t = n & 1 ? cos_kernf(y) : sin_kernf(y);
return n & 2 ? -t : t;
}
export function sinh(x: f32): f32 { // see: musl/src/math/sinhf.c
@ -2121,9 +2313,44 @@ export namespace NativeMathf {
return builtin_sqrt<f32>(x);
}
export function tan(x: f32): f32 { // TODO
unreachable();
return 0;
export function tan(x: f32): f32 { // see: musl/src/math/tanf.c
const t1pio2 = reinterpret<f64>(0x3FF921FB54442D18); // 1 * M_PI_2
const t2pio2 = reinterpret<f64>(0x400921FB54442D18); // 2 * M_PI_2
const t3pio2 = reinterpret<f64>(0x4012D97C7F3321D2); // 3 * M_PI_2
const t4pio2 = reinterpret<f64>(0x401921FB54442D18); // 4 * M_PI_2
var ix = reinterpret<u32>(x);
var sign = ix >> 31;
ix &= 0x7FFFFFFF;
if (ix <= 0x3f490fda) { /* |x| ~<= π/4 */
if (ix < 0x39800000) { /* |x| < 2**-12 */
return x;
}
return tan_kernf(x, 0);
}
if (ix <= 0x407b53d1) { /* |x| ~<= 5π/4 */
if (ix <= 0x4016cbe3) { /* |x| ~<= 3π/4 */
return tan_kernf((sign ? x + t1pio2 : x - t1pio2), 1);
} else {
return tan_kernf((sign ? x + t2pio2 : x - t2pio2), 0);
}
}
if (ix <= 0x40e231d5) { /* |x| ~<= 9π/4 */
if (ix <= 0x40afeddf) { /* |x| ~<= 7π/4 */
return tan_kernf((sign ? x + t3pio2 : x - t3pio2), 1);
} else {
return tan_kernf((sign ? x + t4pio2 : x - t4pio2), 0);
}
}
/* tan(Inf or NaN) is NaN */
if (ix >= 0x7f800000) return x - x;
/* argument reduction */
var n = rempio2f(x, ix, sign);
var y = rempio2f_y;
return tan_kernf(y, n & 1);
}
export function tanh(x: f32): f32 { // see: musl/src/math/tanhf.c
@ -2298,6 +2525,101 @@ export namespace NativeMathf {
}
return sx ? -x : x;
}
export function sincos(x: f32): void { // see: musl/tree/src/math/sincosf.c
const s1pio2 = reinterpret<f64>(0x3FF921FB54442D18); // 1 * M_PI_2
const s2pio2 = reinterpret<f64>(0x400921FB54442D18); // 2 * M_PI_2
const s3pio2 = reinterpret<f64>(0x4012D97C7F3321D2); // 3 * M_PI_2
const s4pio2 = reinterpret<f64>(0x401921FB54442D18); // 4 * M_PI_2
var ix = reinterpret<u32>(x);
var sign = ix >> 31;
ix &= 0x7fffffff;
if (ix <= 0x3f490fda) { /* |x| ~<= π/4 */
if (ix < 0x39800000) { /* |x| < 2**-12 */
sincos_s32 = x;
sincos_c32 = 1;
return;
}
sincos_s32 = sin_kernf(x);
sincos_c32 = cos_kernf(x);
return;
}
if (ASC_SHRINK_LEVEL < 1) {
if (ix <= 0x407b53d1) { /* |x| ~<= 5π/4 */
if (ix <= 0x4016cbe3) { /* |x| ~<= 3π/4 */
if (sign) {
sincos_s32 = -cos_kernf(x + s1pio2);
sincos_c32 = sin_kernf(x + s1pio2);
} else {
sincos_s32 = cos_kernf(s1pio2 - x);
sincos_c32 = sin_kernf(s1pio2 - x);
}
return;
}
/* -sin(x + c) is not correct if x+c could be 0: -0 vs +0 */
sincos_s32 = -sin_kernf(sign ? x + s2pio2 : x - s2pio2);
sincos_c32 = -cos_kernf(sign ? x + s2pio2 : x - s2pio2);
return;
}
if (ix <= 0x40e231d5) { /* |x| ~<= 9π/4 */
if (ix <= 0x40afeddf) { /* |x| ~<= 7π/4 */
if (sign) {
sincos_s32 = cos_kernf(x + s3pio2);
sincos_c32 = -sin_kernf(x + s3pio2);
} else {
sincos_s32 = -cos_kernf(x - s3pio2);
sincos_c32 = sin_kernf(x - s3pio2);
}
return;
}
sincos_s32 = sin_kernf(sign ? x + s4pio2 : x - s4pio2);
sincos_c32 = cos_kernf(sign ? x + s4pio2 : x - s4pio2);
return;
}
}
/* sin(Inf or NaN) is NaN */
if (ix >= 0x7f800000) {
let xx = x - x;
sincos_s32 = xx;
sincos_c32 = xx;
return;
}
/* general argument reduction needed */
var n = rempio2f(x, ix, sign);
var y = rempio2f_y;
var s = sin_kernf(y);
var c = cos_kernf(y);
switch (n & 3) {
case 0: {
sincos_s32 = s;
sincos_c32 = c;
break;
}
case 1: {
sincos_s32 = c;
sincos_c32 = -s;
break;
}
case 2: {
sincos_s32 = -s;
sincos_c32 = -c;
break;
}
case 3:
default: {
sincos_s32 = -c;
sincos_c32 = s;
break;
}
}
}
}
export function ipow32(x: i32, e: i32): i32 {

View File

@ -3828,7 +3828,7 @@
if
i32.const 0
i32.const 2896
i32.const 976
i32.const 978
i32.const 4
call $~lib/env/abort
unreachable
@ -5496,7 +5496,7 @@
if
i32.const 0
i32.const 2896
i32.const 985
i32.const 987
i32.const 24
call $~lib/env/abort
unreachable

View File

@ -5502,7 +5502,7 @@
if
i32.const 0
i32.const 2896
i32.const 976
i32.const 978
i32.const 4
call $~lib/env/abort
unreachable
@ -9227,7 +9227,7 @@
if
i32.const 0
i32.const 2896
i32.const 985
i32.const 987
i32.const 24
call $~lib/env/abort
unreachable

File diff suppressed because it is too large Load Diff

View File

@ -1061,6 +1061,7 @@ assert(test_cos(7.5002613322736158, 0.346390176334581135, -0.499621003866195679,
assert(test_cos(9.12173941873158789, -0.954434129754181071, 0.498281508684158325, INEXACT));
assert(test_cos(6.78495402047631568, 0.876733223316664589, -0.498808383941650391, INEXACT));
assert(test_cos(8.77084654266666419, -0.793698411740070497, 0.499968290328979492, INEXACT));
*/
// Mathf.cos ///////////////////////////////////////////////////////////////////////////////////////
@ -1069,23 +1070,79 @@ function test_cosf(value: f32, expected: f32, error: f32, flags: i32): bool {
}
// sanity
assert(test_cosf(-8.0668487548828125, -0.211263164877891541, 0.483285695314407349, INEXACT));
assert(test_cosf(4.34523963928222656, -0.358956217765808105, 0.0425052084028720856, INEXACT));
assert(test_cosf(-8.38143348693847656, -0.503333151340484619, -0.138619571924209595, INEXACT));
assert(test_cosf(-6.53167343139648438, 0.969285368919372559, 0.178695172071456909, INEXACT));
assert(test_cosf(9.26705741882324219, -0.987587869167327881, 0.138960093259811401, INEXACT));
assert(test_cosf(0.661985874176025391, 0.788773119449615479, 0.29895937442779541, INEXACT));
assert(test_cosf(-0.40660393238067627, 0.918469250202178955, 0.242506653070449829, INEXACT));
assert(test_cosf(0.561759769916534424, 0.846319019794464111, -0.240332409739494324, INEXACT));
assert(test_cosf(0.774152278900146484, 0.71501392126083374, -0.337263524532318115, INEXACT));
assert(test_cosf(-0.678763687610626221, 0.778349518775939941, 0.165501534938812256, INEXACT));
assert(test_cosf(-8.066848754882812500,-0.211263164877891541, 0.4832856953144073490, INEXACT));
assert(test_cosf( 4.345239639282226560,-0.358956217765808105, 0.0425052084028720856, INEXACT));
assert(test_cosf(-8.381433486938476560,-0.503333151340484619,-0.1386195719242095950, INEXACT));
assert(test_cosf(-6.531673431396484380, 0.969285368919372559, 0.1786951720714569090, INEXACT));
assert(test_cosf( 9.267057418823242190,-0.987587869167327881, 0.1389600932598114010, INEXACT));
assert(test_cosf( 0.661985874176025391, 0.788773119449615479, 0.2989593744277954100, INEXACT));
assert(test_cosf(-0.406603932380676270, 0.918469250202178955, 0.2425066530704498290, INEXACT));
assert(test_cosf( 0.561759769916534424, 0.846319019794464111,-0.2403324097394943240, INEXACT));
assert(test_cosf( 0.774152278900146484, 0.715013921260833740,-0.3372635245323181150, INEXACT));
assert(test_cosf(-0.678763687610626221, 0.778349518775939941, 0.1655015349388122560, INEXACT));
// special
assert(test_cosf(0.0, 1.0, 0.0, 0));
assert(test_cosf(-0.0, 1.0, 0.0, 0));
assert(test_cosf(Infinity, NaN, 0.0, INVALID));
assert(test_cosf( 0.0, 1.0, 0.0, 0));
assert(test_cosf( -0.0, 1.0, 0.0, 0));
assert(test_cosf( Infinity, NaN, 0.0, INVALID));
assert(test_cosf(-Infinity, NaN, 0.0, INVALID));
assert(test_cosf(NaN, NaN, 0.0, 0)); */
assert(test_cosf( NaN, NaN, 0.0, 0));
// ubc
assert(test_cosf( 1.862645149e-09, 1.0, 1.455191523e-11, INEXACT));
assert(test_cosf(-1.862645149e-09, 1.0, 1.455191523e-11, INEXACT));
assert(test_cosf( 1.175494351e-38, 1.0, 0.0, INEXACT));
assert(test_cosf(-1.175494351e-38, 1.0, 0.0, INEXACT));
assert(test_cosf( 1.401298464e-45, 1.0, 0.0, INEXACT));
assert(test_cosf(-1.401298464e-45, 1.0, 0.0, INEXACT));
assert(test_cosf( 2.802596929e-45, 1.0, 0.0, INEXACT));
assert(test_cosf( 1.261168618e-44, 1.0, 0.0, INEXACT));
assert(test_cosf( 2.938735877e-39, 1.0, 0.0, INEXACT));
assert(test_cosf( 5.877471754e-39, 1.0, 0.0, INEXACT));
assert(test_cosf( 1.175494071e-38, 1.0, 0.0, INEXACT));
assert(test_cosf( 1.175494211e-38, 1.0, 0.0, INEXACT));
assert(test_cosf( 1.175494491e-38, 1.0, 0.0, INEXACT));
assert(test_cosf( 1.175494631e-38, 1.0, 0.0, INEXACT));
assert(test_cosf( 2.350988001e-38, 1.0, 0.0, INEXACT));
assert(test_cosf( 2.350988702e-38, 1.0, 0.0, INEXACT));
assert(test_cosf( 2.350989542e-38, 1.0, 0.0, INEXACT));
assert(test_cosf( 4.701977403e-38, 1.0, 0.0, INEXACT));
assert(test_cosf( 7.450580597e-09, 1.0, 2.328306437e-10, INEXACT));
assert(test_cosf( 2.441406250e-04, 1.0, 2.500000000e-01, INEXACT));
assert(test_cosf( 4.882812500e-04, 9.999998808e-01,-3.973643103e-08, INEXACT));
assert(test_cosf( 9.765625000e-04, 9.999995232e-01,-6.357828397e-07, INEXACT));
assert(test_cosf(-2.802596929e-45, 1.0, 0.0, INEXACT));
assert(test_cosf(-1.261168618e-44, 1.0, 0.0, INEXACT));
assert(test_cosf(-2.938735877e-39, 1.0, 0.0, INEXACT));
assert(test_cosf(-5.877471754e-39, 1.0, 0.0, INEXACT));
assert(test_cosf(-1.175494071e-38, 1.0, 0.0, INEXACT));
assert(test_cosf(-1.175494211e-38, 1.0, 0.0, INEXACT));
assert(test_cosf(-1.175494491e-38, 1.0, 0.0, INEXACT));
assert(test_cosf(-1.175494631e-38, 1.0, 0.0, INEXACT));
assert(test_cosf(-2.350988001e-38, 1.0, 0.0, INEXACT));
assert(test_cosf(-2.350988702e-38, 1.0, 0.0, INEXACT));
assert(test_cosf(-2.350989542e-38, 1.0, 0.0, INEXACT));
assert(test_cosf(-4.701977403e-38, 1.0, 0.0, INEXACT));
assert(test_cosf(-7.450580597e-09, 1.0, 2.328306437e-10, INEXACT));
assert(test_cosf(-2.441406250e-04, 1.0, 2.500000000e-01, INEXACT));
assert(test_cosf(-4.882812500e-04, 9.999998808e-01,-3.973643103e-08, INEXACT));
assert(test_cosf(-9.765625000e-04, 9.999995232e-01,-6.357828397e-07, INEXACT));
// large arguments
assert(test_cosf( 255.99993896484,-0.039851747453212740, 0.0, INEXACT));
assert(test_cosf( 5033165.25, 0.847187161445617700, 0.0, INEXACT));
assert(test_cosf( 421657440.0, 0.672892928123474100, 0.0, INEXACT));
assert(test_cosf( 2147483392.0, 0.961078047752380400, 0.0, INEXACT));
assert(test_cosf( 68719474688.0, 0.169419050216674800, 0.0, INEXACT));
assert(test_cosf( 549755797504.0, 0.207359507679939270, 0.0, INEXACT));
assert(test_cosf( f32.MAX_VALUE, 0.853021025657653800, 0.0, INEXACT));
assert(test_cosf(-255.99993896484,-0.039851747453212740, 0.0, INEXACT));
assert(test_cosf(-5033165.25, 0.847187161445617700, 0.0, INEXACT));
assert(test_cosf(-421657440.0, 0.672892928123474100, 0.0, INEXACT));
assert(test_cosf(-2147483392.0, 0.961078047752380400, 0.0, INEXACT));
assert(test_cosf(-68719474688.0, 0.169419050216674800, 0.0, INEXACT));
assert(test_cosf(-549755797504.0, 0.207359507679939270, 0.0, INEXACT));
assert(test_cosf(-f32.MAX_VALUE, 0.853021025657653800, 0.0, INEXACT));
////////////////////////////////////////////////////////////////////////////////////////////////////
// Math.cosh
@ -2872,6 +2929,7 @@ assert(test_sin(-0.0, -0.0, 0.0, 0));
assert(test_sin(Infinity, NaN, 0.0, INVALID));
assert(test_sin(-Infinity, NaN, 0.0, INVALID));
assert(test_sin(NaN, NaN, 0.0, 0));
*/
// Mathf.sin ///////////////////////////////////////////////////////////////////////////////////////
@ -2880,23 +2938,79 @@ function test_sinf(value: f32, expected: f32, error: f32, flags: i32): bool {
}
// sanity
assert(test_sinf(-8.066848755, -0.9774292111, 0.0801057294, INEXACT));
assert(test_sinf(4.345239639, -0.9333543777, 0.3447562754, INEXACT));
assert(test_sinf(-8.381433487, -0.8640924692, -0.4686599076, INEXACT));
assert(test_sinf(-6.531673431, -0.2459388077, -0.3955177665, INEXACT));
assert(test_sinf(9.267057419, 0.1570674479, -0.2400680929, INEXACT));
assert(test_sinf(0.6619858742, 0.6146844625, -0.07707194239, INEXACT));
assert(test_sinf(-0.4066039324, -0.3954924345, -0.1172061712, INEXACT));
assert(test_sinf(0.5617597699, 0.5326763391, -0.1605911404, INEXACT));
assert(test_sinf(0.7741522789, 0.6991102099, 0.2638436854, INEXACT));
assert(test_sinf(-0.6787636876, -0.6278312206, 0.005127954297, INEXACT));
assert(test_sinf(-8.0668487550,-0.9774292111, 0.080105729400, INEXACT));
assert(test_sinf( 4.3452396390,-0.9333543777, 0.344756275400, INEXACT));
assert(test_sinf(-8.3814334870,-0.8640924692,-0.468659907600, INEXACT));
assert(test_sinf(-6.5316734310,-0.2459388077,-0.395517766500, INEXACT));
assert(test_sinf( 9.2670574190, 0.1570674479,-0.240068092900, INEXACT));
assert(test_sinf( 0.6619858742, 0.6146844625,-0.077071942390, INEXACT));
assert(test_sinf(-0.4066039324,-0.3954924345,-0.117206171200, INEXACT));
assert(test_sinf( 0.5617597699, 0.5326763391,-0.160591140400, INEXACT));
assert(test_sinf( 0.7741522789, 0.6991102099, 0.263843685400, INEXACT));
assert(test_sinf(-0.6787636876,-0.6278312206, 0.005127954297, INEXACT));
// special
assert(test_sinf(0.0, 0.0, 0.0, 0));
assert(test_sinf(-0.0, -0.0, 0.0, 0));
assert(test_sinf(Infinity, NaN, 0.0, INVALID));
assert(test_sinf( 0.0, 0.0, 0.0, 0));
assert(test_sinf( -0.0,-0.0, 0.0, 0));
assert(test_sinf( Infinity, NaN, 0.0, INVALID));
assert(test_sinf(-Infinity, NaN, 0.0, INVALID));
assert(test_sinf(NaN, NaN, 0.0, 0)); */
assert(test_sinf( NaN, NaN, 0.0, 0));
// ubc
assert(test_sinf( 1.862645149e-09, 1.862645149e-09, 4.850638554e-12, INEXACT));
assert(test_sinf(-1.862645149e-09,-1.862645149e-09,-4.850638554e-12, INEXACT));
assert(test_sinf( 1.175494351e-38, 1.175494351e-38, 0.0, INEXACT));
assert(test_sinf(-1.175494351e-38,-1.175494351e-38, 0.0, INEXACT));
assert(test_sinf( 1.401298464e-45, 1.401298464e-45, 0.0, INEXACT | UNDERFLOW));
assert(test_sinf(-1.401298464e-45,-1.401298464e-45, 0.0, INEXACT | UNDERFLOW));
assert(test_sinf( 1.175494491e-38, 1.175494491e-38, 0.0, INEXACT));
assert(test_sinf( 1.175494631e-38, 1.175494631e-38, 0.0, INEXACT));
assert(test_sinf( 2.350988001e-38, 2.350988001e-38, 0.0, INEXACT));
assert(test_sinf( 2.350988702e-38, 2.350988702e-38, 0.0, INEXACT));
assert(test_sinf( 2.350989542e-38, 2.350989542e-38, 0.0, INEXACT));
assert(test_sinf( 4.701977403e-38, 4.701977403e-38, 0.0, INEXACT));
assert(test_sinf( 1.117587090e-08, 1.117587090e-08, 2.619344741e-10, INEXACT));
assert(test_sinf( 1.490116119e-08, 1.490116119e-08, 3.104408675e-10, INEXACT));
assert(test_sinf( 2.441406250e-04, 2.441406250e-04, 8.333333582e-02, INEXACT));
assert(test_sinf( 3.662109375e-04, 3.662109375e-04, 2.812500000e-01, INEXACT));
assert(test_sinf(-1.175494491e-38,-1.175494491e-38, 0.0, INEXACT));
assert(test_sinf(-1.175494631e-38,-1.175494631e-38, 0.0, INEXACT));
assert(test_sinf(-2.350988001e-38,-2.350988001e-38, 0.0, INEXACT));
assert(test_sinf(-2.350988702e-38,-2.350988702e-38, 0.0, INEXACT));
assert(test_sinf(-2.350989542e-38,-2.350989542e-38, 0.0, INEXACT));
assert(test_sinf(-4.701977403e-38,-4.701977403e-38, 0.0, INEXACT));
assert(test_sinf(-1.117587090e-08,-1.117587090e-08,-2.619344741e-10, INEXACT));
assert(test_sinf(-1.490116119e-08,-1.490116119e-08,-3.104408675e-10, INEXACT));
assert(test_sinf(-2.441406250e-04,-2.441406250e-04,-8.333333582e-02, INEXACT));
assert(test_sinf(-3.662109375e-04,-3.662109375e-04,-2.812500000e-01, INEXACT));
assert(test_sinf( 2.802596929e-45, 2.802596929e-45, 0.0, INEXACT | UNDERFLOW));
assert(test_sinf( 1.261168618e-44, 1.261168618e-44, 0.0, INEXACT | UNDERFLOW));
assert(test_sinf( 2.938735877e-39, 2.938735877e-39, 0.0, INEXACT | UNDERFLOW));
assert(test_sinf( 5.877471754e-39, 5.877471754e-39, 0.0, INEXACT | UNDERFLOW));
assert(test_sinf( 1.175494071e-38, 1.175494071e-38, 0.0, INEXACT | UNDERFLOW));
assert(test_sinf( 1.175494211e-38, 1.175494211e-38, 0.0, INEXACT | UNDERFLOW));
assert(test_sinf(-2.802596929e-45,-2.802596929e-45, 0.0, INEXACT | UNDERFLOW));
assert(test_sinf(-1.261168618e-44,-1.261168618e-44, 0.0, INEXACT | UNDERFLOW));
assert(test_sinf(-2.938735877e-39,-2.938735877e-39, 0.0, INEXACT | UNDERFLOW));
assert(test_sinf(-5.877471754e-39,-5.877471754e-39, 0.0, INEXACT | UNDERFLOW));
assert(test_sinf(-1.175494071e-38,-1.175494071e-38, 0.0, INEXACT | UNDERFLOW));
assert(test_sinf(-1.175494211e-38,-1.175494211e-38, 0.0, INEXACT | UNDERFLOW));
// large arguments
assert(test_sinf( 255.9999389645,-0.9992055892944336, 0.0, INEXACT));
assert(test_sinf( 5033165.25, 0.5312945246696472, 0.0, INEXACT));
assert(test_sinf( 421657440.0, -0.7397398948669434, 0.0, INEXACT));
assert(test_sinf( 2147483392.0, 0.2762770354700000, 0.0, INEXACT));
assert(test_sinf( 68719474688.0, 0.9855440855026245, 0.0, INEXACT));
assert(test_sinf( 549755797504.0,-0.9782648086547852, 0.0, INEXACT));
assert(test_sinf( f32.MAX_VALUE, -0.5218765139579773, 0.0, INEXACT));
assert(test_sinf(-255.9999389645, 0.9992055892944336, 0.0, INEXACT));
assert(test_sinf(-5033165.25, -0.5312945246696472, 0.0, INEXACT));
assert(test_sinf(-421657440.0, 0.7397398948669434, 0.0, INEXACT));
assert(test_sinf(-2147483392.0, -0.2762770354700000, 0.0, INEXACT));
assert(test_sinf(-68719474688.0, -0.9855440855026245, 0.0, INEXACT));
assert(test_sinf(-549755797504.0, 0.9782648086547852, 0.0, INEXACT));
assert(test_sinf(-f32.MAX_VALUE, 0.5218765139579773, 0.0, INEXACT));
////////////////////////////////////////////////////////////////////////////////////////////////////
// Math.sinh
@ -3117,39 +3231,78 @@ assert(test_tan(-0.0, -0.0, 0.0, 0));
assert(test_tan(Infinity, NaN, 0.0, INVALID));
assert(test_tan(-Infinity, NaN, 0.0, INVALID));
assert(test_tan(NaN, NaN, 0.0, 0));
*/
// Mathf.tan ///////////////////////////////////////////////////////////////////////////////////////
function test_tanf(value: f32, expected: f32, error: f32, flags: i32): bool {
return check<f32>(NativeMathf.tan(value), expected, error, flags);
return check<f32>(NativeMathf.tan(value), expected, error, flags);
}
// sanity
assert(test_tanf(-8.066848755, 4.626595497, 0.2455666959, INEXACT));
assert(test_tanf(4.345239639, 2.600190163, 0.3652407229, INEXACT));
assert(test_tanf(-8.381433487, 1.716740608, 0.08169349283, INEXACT));
assert(test_tanf(-6.531673431, -0.2537320852, 0.2318651378, INEXACT));
assert(test_tanf(9.267057419, -0.1590414941, -0.009332014248, INEXACT));
assert(test_tanf(0.6619858742, 0.7792918682, -0.06759700924, INEXACT));
assert(test_tanf(-0.4066039324, -0.4305995405, 0.005771996453, INEXACT));
assert(test_tanf(0.5617597699, 0.6294037104, -0.1683816314, INEXACT));
assert(test_tanf(0.7741522789, 0.9777574539, 0.389693886, INEXACT));
assert(test_tanf(-0.6787636876, -0.8066186309, 0.1229405999, INEXACT));
assert(test_tanf(-8.0668487550, 4.6265954970, 0.245566695900, INEXACT));
assert(test_tanf( 4.3452396390, 2.6001901630, 0.365240722900, INEXACT));
assert(test_tanf(-8.3814334870, 1.7167406080, 0.081693492830, INEXACT));
assert(test_tanf(-6.5316734310,-0.2537320852, 0.231865137800, INEXACT));
assert(test_tanf( 9.2670574190,-0.1590414941,-0.009332014248, INEXACT));
assert(test_tanf( 0.6619858742, 0.7792918682,-0.067597009240, INEXACT));
assert(test_tanf(-0.4066039324,-0.4305995405, 0.005771996453, INEXACT));
assert(test_tanf( 0.5617597699, 0.6294037104,-0.168381631400, INEXACT));
assert(test_tanf( 0.7741522789, 0.9777574539, 0.389693886000, INEXACT));
assert(test_tanf(-0.6787636876,-0.8066186309, 0.122940599900, INEXACT));
// special
assert(test_tanf(0.0, 0.0, 0.0, 0));
assert(test_tanf(-0.0, -0.0, 0.0, 0));
assert(test_tanf(Infinity, NaN, 0.0, INVALID));
assert(test_tanf( 0.0, 0.0, 0.0, 0));
assert(test_tanf( -0.0,-0.0, 0.0, 0));
assert(test_tanf( Infinity, NaN, 0.0, INVALID));
assert(test_tanf(-Infinity, NaN, 0.0, INVALID));
assert(test_tanf(NaN, NaN, 0.0, 0)); */
assert(test_tanf( NaN, NaN, 0.0, 0));
// ubc
assert(test_tanf( 1.862645149e-09, 1.862645149e-09,-9.701277108e-12, INEXACT));
assert(test_tanf(-1.862645149e-09,-1.862645149e-09, 9.701277108e-12, INEXACT));
assert(test_tanf( 1.175494351e-38, 1.175494351e-38, 0.0, INEXACT));
assert(test_tanf(-1.175494351e-38,-1.175494351e-38, 0.0, INEXACT));
assert(test_tanf( 1.401298464e-45, 1.401298464e-45, 0.0, INEXACT | UNDERFLOW));
assert(test_tanf(-1.401298464e-45,-1.401298464e-45, 0.0, INEXACT | UNDERFLOW));
assert(test_tanf( 1.175494491e-38, 1.175494491e-38, 0.0, INEXACT));
assert(test_tanf( 1.175494631e-38, 1.175494631e-38, 0.0, INEXACT));
assert(test_tanf( 2.350988001e-38, 2.350988001e-38, 0.0, INEXACT));
assert(test_tanf( 2.350988702e-38, 2.350988702e-38, 0.0, INEXACT));
assert(test_tanf( 2.350989542e-38, 2.350989542e-38, 0.0, INEXACT));
assert(test_tanf( 4.701977403e-38, 4.701977403e-38, 0.0, INEXACT));
assert(test_tanf( 1.117587090e-08, 1.117587090e-08,-5.238689482e-10, INEXACT));
assert(test_tanf( 1.490116119e-08, 1.490116119e-08,-6.208817349e-10, INEXACT));
assert(test_tanf( 2.441406250e-04, 2.441406250e-04,-1.666666716e-01, INEXACT));
assert(test_tanf(-1.175494491e-38,-1.175494491e-38, 0.0, INEXACT));
assert(test_tanf(-1.175494631e-38,-1.175494631e-38, 0.0, INEXACT));
assert(test_tanf(-2.350988001e-38,-2.350988001e-38, 0.0, INEXACT));
assert(test_tanf( 2.350988702e-38, 2.350988702e-38, 0.0, INEXACT));
assert(test_tanf(-2.350989542e-38,-2.350989542e-38, 0.0, INEXACT));
assert(test_tanf(-4.701977403e-38,-4.701977403e-38, 0.0, INEXACT));
assert(test_tanf(-1.117587090e-08,-1.117587090e-08, 5.238689482e-10, INEXACT));
assert(test_tanf(-1.490116119e-08,-1.490116119e-08, 6.208817349e-10, INEXACT));
assert(test_tanf(-2.441406250e-04,-2.441406250e-04, 1.666666716e-01, INEXACT));
assert(test_tanf( 2.802596929e-45, 2.802596929e-45, 0.0, INEXACT | UNDERFLOW));
assert(test_tanf( 1.261168618e-44, 1.261168618e-44, 0.0, INEXACT | UNDERFLOW));
assert(test_tanf( 2.938735877e-39, 2.938735877e-39, 0.0, INEXACT | UNDERFLOW));
assert(test_tanf( 5.877471754e-39, 5.877471754e-39, 0.0, INEXACT | UNDERFLOW));
assert(test_tanf( 1.175494071e-38, 1.175494071e-38, 0.0, INEXACT | UNDERFLOW));
assert(test_tanf( 1.175494211e-38, 1.175494211e-38, 0.0, INEXACT | UNDERFLOW));
assert(test_tanf(-2.802596929e-45,-2.802596929e-45, 0.0, INEXACT | UNDERFLOW));
assert(test_tanf(-1.261168618e-44,-1.261168618e-44, 0.0, INEXACT | UNDERFLOW));
assert(test_tanf(-2.938735877e-39,-2.938735877e-39, 0.0, INEXACT | UNDERFLOW));
assert(test_tanf(-5.877471754e-39,-5.877471754e-39, 0.0, INEXACT | UNDERFLOW));
assert(test_tanf(-1.175494071e-38,-1.175494071e-38, 0.0, INEXACT | UNDERFLOW));
assert(test_tanf(-1.175494211e-38,-1.175494211e-38, 0.0, INEXACT | UNDERFLOW));
////////////////////////////////////////////////////////////////////////////////////////////////////
// Math.tanh
////////////////////////////////////////////////////////////////////////////////////////////////////
function test_tanh(value: f64, expected: f64, error: f64, flags: i32): bool {
return check<f64>(NativeMath.tanh(value), expected, error, flags) &&
(!js || check<f64>( JSMath.tanh(value), expected, error, flags));
return check<f64>(NativeMath.tanh(value), expected, error, flags) &&
(!js || check<f64>( JSMath.tanh(value), expected, error, flags));
}
// sanity

File diff suppressed because it is too large Load Diff