Implement Math/Mathf.exp; Initial math test suite

This commit is contained in:
dcodeIO 2018-03-25 17:42:56 +02:00
parent 70d2a0a425
commit e26734ef90
12 changed files with 7292 additions and 105 deletions

2
dist/asc.js vendored

File diff suppressed because one or more lines are too long

2
dist/asc.js.map vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

37
scripts/hexfloat.html Normal file
View File

@ -0,0 +1,37 @@
<style>
html, body { margin: 0; }
body { font-family: sans-serif; border-top: 5px solid #0074C1; }
form { margin: 10px; }
label { cursor: pointer; }
</style>
<script src="hexfloat.js"></script>
<form onsubmit="convert(this); return false">
<h1>Hexadecimal float to decimal float converter</h1>
<p>
<label for="f64"><input id="f64" name="precision" value="f64" type="radio" checked /> f64</label>
<label for="f32"><input id="f32" name="precision" value="f32" type="radio" /> f32</label>
<input id="name" type="text" value="test(" />
<button>Convert</button>
</p>
<p><textarea cols="120" rows="20" id="input"></textarea></p>
<p><textarea cols="120" rows="20" id="output" readonly></textarea></p>
</form>
<script>
function convert(form) {
var isF64 = document.getElementById("f64").checked;
var name = document.getElementById("name").value;
var input = document.getElementById("input").value;
document.getElementById("output").value = input
.replace(/\b(\-?0x[0-9a-fA-F]*(?:\.[0-9a-fA-F]+)?[pP][+-]?[0-9]+\b)/g, ($0, $1) => {
var val = parse($1);
return val.toPrecision(isF64 ? 18 : 10);
})
.replace(/\bnan\b/g, "NaN")
.replace(/\inf\b/g, "Infinity")
.replace(/^T\(RN, */mg, name + "(")
.replace(/\)$/mg, ");")
.replace(/ +/g, " ");
}
</script>

82
scripts/hexfloat.js Normal file
View File

@ -0,0 +1,82 @@
/*
MIT License
Copyright (c) 2017 Mauro Bringolf
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// see: https://github.com/maurobringolf/webassembly-floating-point-hex-parser
function parse(input) {
input = input.toUpperCase();
const splitIndex = input.indexOf('P');
let mantissa, exponent;
if (splitIndex !== -1) {
mantissa = input.substring(0, splitIndex);
exponent = parseInt(input.substring(splitIndex + 1));
} else {
mantissa = input;
exponent = 0;
}
const dotIndex = mantissa.indexOf('.');
if (dotIndex !== -1) {
let integerPart = parseInt(mantissa.substring(0,dotIndex), 16);
let sign = Math.sign(integerPart);
integerPart = sign * integerPart;
const fractionLength = mantissa.length - dotIndex - 1;
const fractionalPart = parseInt(mantissa.substring(dotIndex + 1), 16);
const fraction = fractionLength > 0 ? fractionalPart / Math.pow(16, fractionLength) : 0;
if (sign === 0) {
if (fraction === 0) {
mantissa = sign;
} else {
if (Object.is(sign, -0)) {
mantissa = - fraction;
} else {
mantissa = fraction;
}
}
} else {
mantissa = sign * (integerPart + fraction);
}
} else {
mantissa = parseInt(mantissa, 16);
}
return mantissa * (splitIndex !== -1 ? Math.pow(2, exponent) : 1);
}
if (typeof process !== "undefined") {
if (process.argv.length < 3) {
console.error("Usage: hexfloat 0x1p1023");
process.exit(1);
}
var output = parse(process.argv[2]);
var double = output.toPrecision(18); // 17
var single = output.toPrecision(10); // 9
console.log("<f64>" + double);
console.log("<f32>" + single);
if (!(parseFloat(double) === output)) throw Error("double precision error");
if (!(Math.fround(parseFloat(single)) === Math.fround(output))) throw Error("single precision error");
}

View File

@ -1269,6 +1269,20 @@ export class Tokenizer extends DiagnosticEmitter {
}
readFloat(): f64 {
// var text = this.source.text;
// if (text.charCodeAt(this.pos) == CharCode._0 && this.pos + 2 < this.end) {
// switch (text.charCodeAt(this.pos + 1)) {
// case CharCode.X:
// case CharCode.x: {
// this.pos += 2;
// return this.readHexFloat();
// }
// }
// }
return this.readDecimalFloat();
}
readDecimalFloat(): f64 {
var start = this.pos;
var text = this.source.text;
while (this.pos < this.end && isDecimalDigit(text.charCodeAt(this.pos))) {
@ -1300,6 +1314,10 @@ export class Tokenizer extends DiagnosticEmitter {
return parseFloat(text.substring(start, this.pos));
}
readHexFloat(): f64 {
throw new Error("not implemented"); // TBD
}
readUnicodeEscape(): string {
var remain = 4;
var value = 0;

2
std/assembly.d.ts vendored
View File

@ -411,6 +411,7 @@ declare namespace Math {
export function abs(x: f64): f64;
export function ceil(x: f64): f64;
export function clz32(x: f64): i32;
export function exp(x: f64): f64;
export function floor(x: f64): f64;
export function fround(x: f64): f32;
export function imul(a: f64, b: f64): i32;
@ -433,6 +434,7 @@ declare namespace Mathf {
export const SQRT1_2: f32;
export const SQRT2: f32;
export function abs(x: f32): f32;
export function exp(x: f32): f32;
export function ceil(x: f32): f32;
export function clz32(x: f32): i32;
export function floor(x: f32): f32;

View File

@ -58,6 +58,13 @@ import {
trunc as builtin_trunc
} from "./builtins";
// Math/Mathf.log/exp
// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
// Developed at SunPro, a Sun Microsystems, Inc. business.
// Permission to use, copy, modify, and distribute this
// software is freely granted, provided that this notice
// is preserved.
export namespace Math {
export const E = 2.7182818284590452354;
@ -81,6 +88,67 @@ export namespace Math {
return builtin_clz(<i32>x);
}
export function exp(x: f64): f64 {
// based on musl's implementation of exp:
const
half = <f64[]>[0.5,-0.5],
ln2hi = 6.93147180369123816490e-01, // 0x3fe62e42, 0xfee00000
ln2lo = 1.90821492927058770002e-10, // 0x3dea39ef, 0x35793c76
invln2 = 1.44269504088896338700e+00, // 0x3ff71547, 0x652b82fe
P1 = 1.66666666666666019037e-01, // 0x3FC55555, 0x5555553E
P2 = -2.77777777770155933842e-03, // 0xBF66C16C, 0x16BEBD93
P3 = 6.61375632143793436117e-05, // 0x3F11566A, 0xAF25DE2C
P4 = -1.65339022054652515390e-06, // 0xBEBBBD41, 0xC5D26BF1
P5 = 4.13813679705723846039e-08, // 0x3E663769, 0x72BEA4D0
Ox1p1023 = 8.98846567431157954e+307;
var hx = <u32>(reinterpret<u64>(x) >> 32);
var sign_ = hx >> 31;
hx &= 0x7fffffff; // high word of |x|
// special cases
if (hx >= 0x4086232b) { // if |x| >= 708.39...
if (isNaN(x)) return x;
if (x > 709.782712893383973096) {
// overflow if x!=inf
x *= Ox1p1023;
return x;
}
if (x < -708.39641853226410622) {
// underflow if x!=-inf
if (x < -745.13321910194110842) return 0;
}
}
// argument reduction
var hi: f64, lo: f64;
var k: i32;
if (hx > 0x3fd62e42) { // if |x| > 0.5 ln2
if (hx >= 0x3ff0a2b2) { // if |x| >= 1.5 ln2
k = <i32>(invln2 * x + half[sign_]);
} else {
k = 1 - sign_ - sign_;
}
hi = x - k * ln2hi; // k * ln2hi is exact here
lo = k * ln2lo;
x = hi - lo;
} else if (hx > 0x3e300000) { // if |x| > 2**-28
k = 0;
hi = x;
lo = 0;
} else {
// inexact if x != 0
return 1 + x;
}
// x is now in primary range
var xx = x * x;
var c = x - xx * (P1 + xx * (P2 + xx * (P3 + xx * (P4 + xx * P5))));
var y: f64 = 1 + (x * c / (2 - c) - lo + hi);
if (k == 0) return y;
return scalbn(y, k);
}
export function floor(x: f64): f64 {
return builtin_floor(x);
}
@ -93,13 +161,7 @@ export namespace Math {
return <i32>x * <i32>y;
}
export function log(x: f64): f64 {
// based on musl's implementation of log:
// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
// Developed at SunPro, a Sun Microsystems, Inc. business.
// Permission to use, copy, modify, and distribute this
// software is freely granted, provided that this notice
// is preserved.
export function log(x: f64): f64 { // based on musl's implementation of log
const
ln2_hi = 6.93147180369123816490e-01, // 3fe62e42 fee00000
ln2_lo = 1.90821492927058770002e-10, // 3dea39ef 35793c76
@ -109,7 +171,8 @@ export namespace Math {
Lg4 = 2.222219843214978396e-01, // 3FCC71C5 1D8E78AF
Lg5 = 1.818357216161805012e-01, // 3FC74664 96CB03DE
Lg6 = 1.531383769920937332e-01, // 3FC39A09 D078C69F
Lg7 = 1.479819860511658591e-01; // 3FC2F112 DF3E5244
Lg7 = 1.479819860511658591e-01, // 3FC2F112 DF3E5244
Ox1p54 = 18014398509481984.0;
var Ux = reinterpret<u64>(x);
var hx = <u32>(Ux >> 32);
@ -119,7 +182,7 @@ export namespace Math {
if (hx >> 31) return (x - x) / 0.0; // log(-#) = NaN
// subnormal number, scale x up
k -= 54;
x *= 1.8014398509481984e16; // 0x1p54
x *= Ox1p54;
Ux = reinterpret<u64>(x);
hx = <u32>(Ux >> 32);
} else if (hx >= 0x7ff00000) return x;
@ -204,24 +267,79 @@ export namespace Mathf {
return builtin_floor(x);
}
export function exp(x: f32): f32 { // based on musl's implementation of expf
const
half = <f32[]>[0.5,-0.5],
ln2hi = <f32>6.9314575195e-1, // 0x3f317200
ln2lo = <f32>1.4286067653e-6, // 0x35bfbe8e
invln2 = <f32>1.4426950216e+0, // 0x3fb8aa3b
// Domain [-0.34568, 0.34568], range ~[-4.278e-9, 4.447e-9]:
// |x*(exp(x)+1)/(exp(x)-1) - p(x)| < 2**-27.74
P1 = <f32>1.6666625440e-1, // 0xaaaa8f.0p-26
P2 = <f32>-2.7667332906e-3, // -0xb55215.0p-32
Ox1p127f = <f32>1.701411835e+38;
var hx = reinterpret<u32>(x);
var sign_ = <i32>(hx >> 31); // sign bit of x
hx &= 0x7fffffff; // high word of |x|
// special cases
if (hx >= 0x42aeac50) { // if |x| >= -87.33655f or NaN
if (hx >= 0x42b17218 && !sign_) { // x >= 88.722839f
// overflow
x *= Ox1p127f;
return x;
}
if (sign_) {
// underflow
if (hx >= 0x42cff1b5) { // x <= -103.972084f */
return 0;
}
}
}
// argument reduction
var hi: f32, lo: f32;
var k: i32;
if (hx > 0x3eb17218) { // if |x| > 0.5 ln2
if (hx > 0x3f851592) { // if |x| > 1.5 ln2
k = <i32>(invln2 * x + half[sign_]);
} else {
k = 1 - sign_ - sign_;
}
hi = x - <f32>k * ln2hi; // k * ln2hi is exact here
lo = <f32>k * ln2lo;
x = hi - lo;
} else if (hx > 0x39000000) { // |x| > 2**-14
k = 0;
hi = x;
lo = 0;
} else {
// raise inexact
return 1 + x;
}
// x is now in primary range
var xx = x * x;
var c = x - xx * (P1 + xx * P2);
var y: f32 = 1 + (x * c / (2 - c) - lo + hi);
if (k == 0) return y;
return scalbnf(y, k);
}
export function imul(x: f32, y: f32): i32 {
return <i32>x * <i32>y;
}
export function log(x: f32): f32 {
// based on musl's implementaion of logf:
// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
// Developed at SunPro, a Sun Microsystems, Inc. business.
// Permission to use, copy, modify, and distribute this
// software is freely granted, provided that this notice
// is preserved.
export function log(x: f32): f32 { // based on musl's implementaion of logf
const
ln2_hi = <f32>6.9313812256e-01, // 0x3f317180
ln2_lo = <f32>9.0580006145e-06, // 0x3717f7d1
Lg1 = <f32>0.66666662693, // 0xaaaaaa.0p-24
Lg2 = <f32>0.40000972152, // 0xccce13.0p-25
Lg3 = <f32>0.28498786688, // 0x91e9ee.0p-25
Lg4 = <f32>0.24279078841; // 0xf89e26.0p-26
Lg4 = <f32>0.24279078841, // 0xf89e26.0p-26
Ox1p25f = <f32>33554432.0;
var ux = reinterpret<u32>(x);
var k = 0;
@ -230,7 +348,7 @@ export namespace Mathf {
if (ux >> 31) return (x - x) / 0; // log(-#) = NaN
// subnormal number, scale up x
k -= 25;
x *= 3.3554432; // 0x1p25f;
x *= Ox1p25f;
ux = reinterpret<u32>(x);
} else if (ux >= 0x7f800000) return x;
else if (ux == 0x3f800000) return 0;
@ -285,3 +403,55 @@ export namespace Mathf {
return builtin_trunc(x);
}
}
function scalbn(x: f64, n: i32): f64 { // based on musl's implementation of scalbn
const
Ox1p1023 = 8.98846567431157954e+307,
Ox1p_1022 = 2.22507385850720138e-308;
var y = x;
if (n > 1023) {
y *= Ox1p1023;
n -= 1023;
if (n > 1023) {
y *= Ox1p1023;
n -= 1023;
if (n > 1023) n = 1023;
}
} else if (n < -1022) {
y *= Ox1p_1022;
n += 1022;
if (n < -1022) {
y *= Ox1p_1022;
n += 1022;
if (n < -1022) n = -1022;
}
}
return y * reinterpret<f64>(<u64>(0x3ff + n) << 52);
}
function scalbnf(x: f32, n: i32): f32 { // based on musl's implementation of scalbnf
const
Ox1p127f = <f32>1.701411835e+38,
Ox1p_126f = <f32>1.175494351e-38;
var y = x;
if (n > 127) {
y *= Ox1p127f;
n -= 127;
if (n > 127) {
y *= Ox1p127f;
n -= 127;
if (n > 127) n = 127;
}
} else if (n < -126) {
y *= Ox1p_126f;
n += 126;
if (n < -126) {
y *= Ox1p_126f;
n += 126;
if (n < -126) n = -126;
}
}
return y * reinterpret<f32>(<u32>(0x7f + n) << 23);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,311 @@
// TODO
assert(Math.log(123) == JSMath.log(123));
assert(Mathf.log(123) == JSMath.fround(JSMath.log(123)));
// based on http://nsz.repo.hu/git/?p=libc-test
// mostly generated from their tests using scripts/hexfloat.html
const INEXACT = 1 << 0;
const INVALID = 1 << 1;
const DIVBYZERO = 1 << 2;
const UNDERFLOW = 1 << 3;
const OVERFLOW = 1 << 4;
function check<T>(actual: T, expected: T, error: T, flags: i32): void { // TODO: is this correct? -0?
if (isNaN(expected)) {
if (!isNaN(actual)) unreachable();
} else if (actual != expected) {
if (!(flags & INEXACT) || abs<T>(actual - expected) > abs<T>(error)) unreachable();
}
}
// ================================ built-in fmod ================================
function builtin_fmod(left: f64, right: f64, expected: f64, error: f64, flags: i32): void {
check<f64>(fmod(left, right), expected, error, flags);
check<f64>(left % right, expected, error, flags);
}
// sanity
builtin_fmod(-8.06684839057968084, 4.53566256067686879, -3.53118582990281205, 0.00000000000000000, 0);
builtin_fmod(4.34523984933830487, -8.88799136300345083, 4.34523984933830487, 0.00000000000000000, 0);
builtin_fmod(-8.38143342755524934, -2.76360733737958819, -0.0906114154164847641, 0.00000000000000000, 0);
builtin_fmod(-6.53167358191348413, 4.56753527684274374, -1.96413830507074039, 0.00000000000000000, 0);
builtin_fmod(9.26705696697258574, 4.81139208435979615, 4.45566488261278959, 0.00000000000000000, 0);
builtin_fmod(-6.45004555606023633, 0.662071792337673881, -0.491399425021171399, 0.00000000000000000, 0);
builtin_fmod(7.85889025304169664, 0.0521545267500622481, 0.0357112405323594256, 0.00000000000000000, 0);
builtin_fmod(-0.792054511984895959, 7.67640268511753998, -0.792054511984895959, 0.00000000000000000, 0);
builtin_fmod(0.615702673197924044, 2.01190257903248026, 0.615702673197924044, 0.00000000000000000, 0);
builtin_fmod(-0.558758682360915193, 0.0322398306026380407, -0.0106815621160685006, 0.00000000000000000, 0);
// special
builtin_fmod(0.00000000000000000, 1.00000000000000000, 0.00000000000000000, 0.00000000000000000, 0);
builtin_fmod(-0.00000000000000000, 1.00000000000000000, -0.00000000000000000, 0.00000000000000000, 0);
builtin_fmod(0.500000000000000000, 1.00000000000000000, 0.500000000000000000, 0.00000000000000000, 0);
builtin_fmod(-0.500000000000000000, 1.00000000000000000, -0.500000000000000000, 0.00000000000000000, 0);
builtin_fmod(1.00000000000000000, 1.00000000000000000, 0.00000000000000000, 0.00000000000000000, 0);
builtin_fmod(-1.00000000000000000, 1.00000000000000000, -0.00000000000000000, 0.00000000000000000, 0);
builtin_fmod(1.50000000000000000, 1.00000000000000000, 0.500000000000000000, 0.00000000000000000, 0);
builtin_fmod(-1.50000000000000000, 1.00000000000000000, -0.500000000000000000, 0.00000000000000000, 0);
builtin_fmod(2.00000000000000000, 1.00000000000000000, 0.00000000000000000, 0.00000000000000000, 0);
builtin_fmod(-2.00000000000000000, 1.00000000000000000, -0.00000000000000000, 0.00000000000000000, 0);
builtin_fmod(Infinity, 1.00000000000000000, NaN, 0.00000000000000000, INVALID);
builtin_fmod(-Infinity, 1.00000000000000000, NaN, 0.00000000000000000, INVALID);
builtin_fmod(NaN, 1.00000000000000000, NaN, 0.00000000000000000, 0);
builtin_fmod(0.00000000000000000, -1.00000000000000000, 0.00000000000000000, 0.00000000000000000, 0);
builtin_fmod(-0.00000000000000000, -1.00000000000000000, -0.00000000000000000, 0.00000000000000000, 0);
builtin_fmod(0.500000000000000000, -1.00000000000000000, 0.500000000000000000, 0.00000000000000000, 0);
builtin_fmod(-0.500000000000000000, -1.00000000000000000, -0.500000000000000000, 0.00000000000000000, 0);
builtin_fmod(1.00000000000000000, -1.00000000000000000, 0.00000000000000000, 0.00000000000000000, 0);
builtin_fmod(-1.00000000000000000, -1.00000000000000000, -0.00000000000000000, 0.00000000000000000, 0);
builtin_fmod(1.50000000000000000, -1.00000000000000000, 0.500000000000000000, 0.00000000000000000, 0);
builtin_fmod(-1.50000000000000000, -1.00000000000000000, -0.500000000000000000, 0.00000000000000000, 0);
builtin_fmod(2.00000000000000000, -1.00000000000000000, 0.00000000000000000, 0.00000000000000000, 0);
builtin_fmod(-2.00000000000000000, -1.00000000000000000, -0.00000000000000000, 0.00000000000000000, 0);
builtin_fmod(Infinity, -1.00000000000000000, NaN, 0.00000000000000000, INVALID);
builtin_fmod(-Infinity, -1.00000000000000000, NaN, 0.00000000000000000, INVALID);
builtin_fmod(NaN, -1.00000000000000000, NaN, 0.00000000000000000, 0);
builtin_fmod(0.00000000000000000, 0.00000000000000000, NaN, 0.00000000000000000, INVALID);
builtin_fmod(0.00000000000000000, -0.00000000000000000, NaN, 0.00000000000000000, INVALID);
builtin_fmod(0.00000000000000000, Infinity, 0.00000000000000000, 0.00000000000000000, 0);
builtin_fmod(0.00000000000000000, -Infinity, 0.00000000000000000, 0.00000000000000000, 0);
builtin_fmod(0.00000000000000000, NaN, NaN, 0.00000000000000000, 0);
builtin_fmod(-0.00000000000000000, 0.00000000000000000, NaN, 0.00000000000000000, INVALID);
builtin_fmod(-0.00000000000000000, -0.00000000000000000, NaN, 0.00000000000000000, INVALID);
builtin_fmod(-0.00000000000000000, Infinity, -0.00000000000000000, 0.00000000000000000, 0);
builtin_fmod(-0.00000000000000000, -Infinity, -0.00000000000000000, 0.00000000000000000, 0);
builtin_fmod(-0.00000000000000000, NaN, NaN, 0.00000000000000000, 0);
builtin_fmod(1.00000000000000000, 0.00000000000000000, NaN, 0.00000000000000000, INVALID);
builtin_fmod(-1.00000000000000000, 0.00000000000000000, NaN, 0.00000000000000000, INVALID);
builtin_fmod(Infinity, 0.00000000000000000, NaN, 0.00000000000000000, INVALID);
builtin_fmod(-Infinity, 0.00000000000000000, NaN, 0.00000000000000000, INVALID);
builtin_fmod(NaN, 0.00000000000000000, NaN, 0.00000000000000000, 0);
builtin_fmod(-1.00000000000000000, -0.00000000000000000, NaN, 0.00000000000000000, INVALID);
builtin_fmod(Infinity, -0.00000000000000000, NaN, 0.00000000000000000, INVALID);
builtin_fmod(-Infinity, -0.00000000000000000, NaN, 0.00000000000000000, INVALID);
builtin_fmod(NaN, -0.00000000000000000, NaN, 0.00000000000000000, 0);
builtin_fmod(Infinity, 2.00000000000000000, NaN, 0.00000000000000000, INVALID);
builtin_fmod(Infinity, -0.500000000000000000, NaN, 0.00000000000000000, INVALID);
builtin_fmod(Infinity, NaN, NaN, 0.00000000000000000, 0);
builtin_fmod(-Infinity, 2.00000000000000000, NaN, 0.00000000000000000, INVALID);
builtin_fmod(-Infinity, -0.500000000000000000, NaN, 0.00000000000000000, INVALID);
builtin_fmod(-Infinity, NaN, NaN, 0.00000000000000000, 0);
builtin_fmod(NaN, NaN, NaN, 0.00000000000000000, 0);
builtin_fmod(1.00000000000000000, NaN, NaN, 0.00000000000000000, 0);
builtin_fmod(-1.00000000000000000, NaN, NaN, 0.00000000000000000, 0);
builtin_fmod(1.00000000000000000, Infinity, 1.00000000000000000, 0.00000000000000000, 0);
builtin_fmod(-1.00000000000000000, Infinity, -1.00000000000000000, 0.00000000000000000, 0);
builtin_fmod(Infinity, Infinity, NaN, 0.00000000000000000, INVALID);
builtin_fmod(-Infinity, Infinity, NaN, 0.00000000000000000, INVALID);
builtin_fmod(1.00000000000000000, -Infinity, 1.00000000000000000, 0.00000000000000000, 0);
builtin_fmod(-1.00000000000000000, -Infinity, -1.00000000000000000, 0.00000000000000000, 0);
builtin_fmod(Infinity, -Infinity, NaN, 0.00000000000000000, INVALID);
builtin_fmod(-Infinity, -Infinity, NaN, 0.00000000000000000, INVALID);
builtin_fmod(1.75000000000000000, 0.500000000000000000, 0.250000000000000000, 0.00000000000000000, 0);
builtin_fmod(-1.75000000000000000, 0.500000000000000000, -0.250000000000000000, 0.00000000000000000, 0);
builtin_fmod(1.75000000000000000, -0.500000000000000000, 0.250000000000000000, 0.00000000000000000, 0);
builtin_fmod(-1.75000000000000000, -0.500000000000000000, -0.250000000000000000, 0.00000000000000000, 0);
// ================================ built-in fmodf ================================
function builtin_fmodf(left: f32, right: f32, expected: f32, error: f32, flags: i32): void {
check<f32>(fmodf(left, right), expected, error, flags);
check<f32>(left % right, expected, error, flags);
}
// sanity
builtin_fmodf(-8.066848755, 4.535662651, -3.531186104, 0.000000000, 0);
builtin_fmodf(4.345239639, -8.887990952, 4.345239639, 0.000000000, 0);
builtin_fmodf(-8.381433487, -2.763607264, -0.09061169624, 0.000000000, 0);
builtin_fmodf(-6.531673431, 4.567535400, -1.964138031, 0.000000000, 0);
builtin_fmodf(9.267057419, 4.811392307, 4.455665112, 0.000000000, 0);
builtin_fmodf(-6.450045586, 0.6620717645, -0.4913997054, 0.000000000, 0);
builtin_fmodf(7.858890057, 0.05215452611, 0.03571113944, 0.000000000, 0);
builtin_fmodf(-0.7920545340, 7.676402569, -0.7920545340, 0.000000000, 0);
builtin_fmodf(0.6157026887, 2.011902571, 0.6157026887, 0.000000000, 0);
builtin_fmodf(-0.5587586761, 0.03223983198, -0.01068153232, 0.000000000, 0);
// special
builtin_fmodf(0.000000000, 1.000000000, 0.000000000, 0.000000000, 0);
builtin_fmodf(-0.000000000, 1.000000000, -0.000000000, 0.000000000, 0);
builtin_fmodf(0.5000000000, 1.000000000, 0.5000000000, 0.000000000, 0);
builtin_fmodf(-0.5000000000, 1.000000000, -0.5000000000, 0.000000000, 0);
builtin_fmodf(1.000000000, 1.000000000, 0.000000000, 0.000000000, 0);
builtin_fmodf(-1.000000000, 1.000000000, -0.000000000, 0.000000000, 0);
builtin_fmodf(1.500000000, 1.000000000, 0.5000000000, 0.000000000, 0);
builtin_fmodf(-1.500000000, 1.000000000, -0.5000000000, 0.000000000, 0);
builtin_fmodf(2.000000000, 1.000000000, 0.000000000, 0.000000000, 0);
builtin_fmodf(-2.000000000, 1.000000000, -0.000000000, 0.000000000, 0);
builtin_fmodf(Infinity, 1.000000000, NaN, 0.000000000, INVALID);
builtin_fmodf(-Infinity, 1.000000000, NaN, 0.000000000, INVALID);
builtin_fmodf(NaN, 1.000000000, NaN, 0.000000000, 0);
builtin_fmodf(0.000000000, -1.000000000, 0.000000000, 0.000000000, 0);
builtin_fmodf(-0.000000000, -1.000000000, -0.000000000, 0.000000000, 0);
builtin_fmodf(0.5000000000, -1.000000000, 0.5000000000, 0.000000000, 0);
builtin_fmodf(-0.5000000000, -1.000000000, -0.5000000000, 0.000000000, 0);
builtin_fmodf(1.000000000, -1.000000000, 0.000000000, 0.000000000, 0);
builtin_fmodf(-1.000000000, -1.000000000, -0.000000000, 0.000000000, 0);
builtin_fmodf(1.500000000, -1.000000000, 0.5000000000, 0.000000000, 0);
builtin_fmodf(-1.500000000, -1.000000000, -0.5000000000, 0.000000000, 0);
builtin_fmodf(2.000000000, -1.000000000, 0.000000000, 0.000000000, 0);
builtin_fmodf(-2.000000000, -1.000000000, -0.000000000, 0.000000000, 0);
builtin_fmodf(Infinity, -1.000000000, NaN, 0.000000000, INVALID);
builtin_fmodf(-Infinity, -1.000000000, NaN, 0.000000000, INVALID);
builtin_fmodf(NaN, -1.000000000, NaN, 0.000000000, 0);
builtin_fmodf(0.000000000, 0.000000000, NaN, 0.000000000, INVALID);
builtin_fmodf(0.000000000, -0.000000000, NaN, 0.000000000, INVALID);
builtin_fmodf(0.000000000, Infinity, 0.000000000, 0.000000000, 0);
builtin_fmodf(0.000000000, -Infinity, 0.000000000, 0.000000000, 0);
builtin_fmodf(0.000000000, NaN, NaN, 0.000000000, 0);
builtin_fmodf(-0.000000000, 0.000000000, NaN, 0.000000000, INVALID);
builtin_fmodf(-0.000000000, -0.000000000, NaN, 0.000000000, INVALID);
builtin_fmodf(-0.000000000, Infinity, -0.000000000, 0.000000000, 0);
builtin_fmodf(-0.000000000, -Infinity, -0.000000000, 0.000000000, 0);
builtin_fmodf(-0.000000000, NaN, NaN, 0.000000000, 0);
builtin_fmodf(1.000000000, 0.000000000, NaN, 0.000000000, INVALID);
builtin_fmodf(-1.000000000, 0.000000000, NaN, 0.000000000, INVALID);
builtin_fmodf(Infinity, 0.000000000, NaN, 0.000000000, INVALID);
builtin_fmodf(-Infinity, 0.000000000, NaN, 0.000000000, INVALID);
builtin_fmodf(NaN, 0.000000000, NaN, 0.000000000, 0);
builtin_fmodf(-1.000000000, -0.000000000, NaN, 0.000000000, INVALID);
builtin_fmodf(Infinity, -0.000000000, NaN, 0.000000000, INVALID);
builtin_fmodf(-Infinity, -0.000000000, NaN, 0.000000000, INVALID);
builtin_fmodf(NaN, -0.000000000, NaN, 0.000000000, 0);
builtin_fmodf(Infinity, 2.000000000, NaN, 0.000000000, INVALID);
builtin_fmodf(Infinity, -0.5000000000, NaN, 0.000000000, INVALID);
builtin_fmodf(Infinity, NaN, NaN, 0.000000000, 0);
builtin_fmodf(-Infinity, 2.000000000, NaN, 0.000000000, INVALID);
builtin_fmodf(-Infinity, -0.5000000000, NaN, 0.000000000, INVALID);
builtin_fmodf(-Infinity, NaN, NaN, 0.000000000, 0);
builtin_fmodf(NaN, NaN, NaN, 0.000000000, 0);
builtin_fmodf(1.000000000, NaN, NaN, 0.000000000, 0);
builtin_fmodf(-1.000000000, NaN, NaN, 0.000000000, 0);
builtin_fmodf(1.000000000, Infinity, 1.000000000, 0.000000000, 0);
builtin_fmodf(-1.000000000, Infinity, -1.000000000, 0.000000000, 0);
builtin_fmodf(Infinity, Infinity, NaN, 0.000000000, INVALID);
builtin_fmodf(-Infinity, Infinity, NaN, 0.000000000, INVALID);
builtin_fmodf(1.000000000, -Infinity, 1.000000000, 0.000000000, 0);
builtin_fmodf(-1.000000000, -Infinity, -1.000000000, 0.000000000, 0);
builtin_fmodf(Infinity, -Infinity, NaN, 0.000000000, INVALID);
builtin_fmodf(-Infinity, -Infinity, NaN, 0.000000000, INVALID);
builtin_fmodf(1.750000000, 0.5000000000, 0.2500000000, 0.000000000, 0);
builtin_fmodf(-1.750000000, 0.5000000000, -0.2500000000, 0.000000000, 0);
builtin_fmodf(1.750000000, -0.5000000000, 0.2500000000, 0.000000000, 0);
builtin_fmodf(-1.750000000, -0.5000000000, -0.2500000000, 0.000000000, 0);
// ================================ Math.log ================================
function Math_log(value: f64, expected: f64, error: f64, flags: i32): void {
check<f64>(Math.log(value), expected, error, flags);
check<f64>(JSMath.log(value), expected, error, flags);
}
// sanity
Math_log(-8.06684839057968084, NaN, 0.00000000000000000, INVALID);
Math_log(4.34523984933830487, 1.46908095842243225, -0.341253340244293213, INEXACT);
Math_log(-8.38143342755524934, NaN, 0.00000000000000000, INVALID);
Math_log(-6.53167358191348413, NaN, 0.00000000000000000, INVALID);
Math_log(9.26705696697258574, 2.22646584987956153, 0.363811403512954712, INEXACT);
Math_log(0.661985898099504477, -0.412511025236513673, -0.291087478399276733, INEXACT);
Math_log(-0.406603922385355310, NaN, 0.00000000000000000, INVALID);
Math_log(0.561759746220724110, -0.576681018319586181, -0.109831996262073517, INEXACT);
Math_log(0.774152296591303690, -0.255986659126386518, -0.0579900443553924561, INEXACT);
Math_log(-0.678763702639402444, NaN, 0.00000000000000000, INVALID);
// special
Math_log(0.00000000000000000, -Infinity, 0.00000000000000000, DIVBYZERO);
Math_log(-0.00000000000000000, -Infinity, 0.00000000000000000, DIVBYZERO);
Math_log(-7.88860905221011805e-31, NaN, 0.00000000000000000, INVALID);
Math_log(1.00000000000000000, 0.00000000000000000, 0.00000000000000000, 0);
Math_log(-1.00000000000000000, NaN, 0.00000000000000000, INVALID);
Math_log(Infinity, Infinity, 0.00000000000000000, 0);
Math_log(-Infinity, NaN, 0.00000000000000000, INVALID);
Math_log(NaN, NaN, 0.00000000000000000, 0);
// ================================ Mathf.log ================================
function Mathf_log(value: f32, expected: f32, error: f32, flags: i32): void {
check<f32>(Mathf.log(value), expected, error, flags);
}
// sanity
Mathf_log(0.000000000, -Infinity, 0.000000000, DIVBYZERO);
Mathf_log(-0.000000000, -Infinity, 0.000000000, DIVBYZERO);
Mathf_log(-7.888609052e-31, NaN, 0.000000000, INVALID);
Mathf_log(1.000000000, 0.000000000, 0.000000000, 0);
Mathf_log(-1.000000000, NaN, 0.000000000, INVALID);
Mathf_log(Infinity, Infinity, 0.000000000, 0);
Mathf_log(-Infinity, NaN, 0.000000000, INVALID);
Mathf_log(NaN, NaN, 0.000000000, 0);
// special
Mathf_log(0.000000000, -Infinity, 0.000000000, DIVBYZERO);
Mathf_log(-0.000000000, -Infinity, 0.000000000, DIVBYZERO);
Mathf_log(-7.888609052e-31, NaN, 0.000000000, INVALID);
Mathf_log(1.000000000, 0.000000000, 0.000000000, 0);
Mathf_log(-1.000000000, NaN, 0.000000000, INVALID);
Mathf_log(Infinity, Infinity, 0.000000000, 0);
Mathf_log(-Infinity, NaN, 0.000000000, INVALID);
Mathf_log(NaN, NaN, 0.000000000, 0);
// ================================ Math.exp ================================
function Math_exp(value: f64, expected: f64, error: f64, flags: i32): void {
check<f64>(Math.exp(value), expected, error, flags);
check<f64>(JSMath.exp(value), expected, error, flags);
}
// sanity
Math_exp(-8.06684839057968084, 0.000313770606816174511, -0.259919732809066772, INEXACT);
Math_exp(4.34523984933830487, 77.1105301711214111, -0.0279267579317092896, INEXACT);
Math_exp(-8.38143342755524934, 0.000229081338491632304, -0.249743342399597168, INEXACT);
Math_exp(-6.53167358191348413, 0.00145656612609315877, -0.481682240962982178, INEXACT);
Math_exp(9.26705696697258574, 10583.5582455249933, 0.176967620849609375, INEXACT);
Math_exp(0.661985898099504477, 1.93863845255719980, -0.496424645185470581, INEXACT);
Math_exp(-0.406603922385355310, 0.665907889283802512, -0.106083184480667114, INEXACT);
Math_exp(0.561759746220724110, 1.75375595186263111, -0.391621112823486328, INEXACT);
Math_exp(0.774152296591303690, 2.16875288851292458, -0.299612581729888916, INEXACT);
Math_exp(-0.678763702639402444, 0.507243708940284255, 0.472617387771606445, INEXACT);
// special
Math_exp(0.00000000000000000, 1.00000000000000000, 0.00000000000000000, 0);
Math_exp(-0.00000000000000000, 1.00000000000000000, 0.00000000000000000, 0);
Math_exp(1.00000000000000000, 2.71828182845904509, -0.325530737638473511, INEXACT);
Math_exp(-1.00000000000000000, 0.367879441171442334, 0.223896518349647522, INEXACT);
Math_exp(Infinity, Infinity, 0.00000000000000000, 0);
Math_exp(-Infinity, 0.00000000000000000, 0.00000000000000000, 0);
Math_exp(NaN, NaN, 0.00000000000000000, 0);
Math_exp(1.03972148895263650, 2.82842915587641119, 0.188030809164047241, INEXACT);
Math_exp(-1.03972148895263650, 0.353553136702178472, 0.252727240324020386, INEXACT);
Math_exp(1.03972101211547852, 2.82842780717661224, -0.418413937091827393, INEXACT);
Math_exp(1.03972148895263672, 2.82842915587641164, -0.226183772087097168, INEXACT);
// ================================ Mathf.exp ================================
function Mathf_exp(value: f32, expected: f32, error: f32, flags: i32): void {
check<f32>(Mathf.exp(value), expected, error, flags);
}
// sanity
Mathf_exp(-8.066848755, 0.0003137704916, -0.03019333631, INEXACT);
Mathf_exp(4.345239639, 77.11051178, -0.2875460684, INEXACT);
Mathf_exp(-8.381433487, 0.0002290813281, 0.2237040401, INEXACT);
Mathf_exp(-6.531673431, 0.001456566388, 0.3646970391, INEXACT);
Mathf_exp(9.267057419, 10583.56348, 0.4596210420, INEXACT);
Mathf_exp(0.6619858742, 1.938638449, 0.3568260968, INEXACT);
Mathf_exp(-0.4066039324, 0.6659078598, -0.3829499185, INEXACT);
Mathf_exp(0.5617597699, 1.753756046, 0.4435549080, INEXACT);
Mathf_exp(0.7741522789, 2.168752909, 0.2456246912, INEXACT);
Mathf_exp(-0.6787636876, 0.5072436929, -0.3974292278, INEXACT);
// special
Mathf_exp(0.000000000, 1.000000000, 0.000000000, 0);
Mathf_exp(-0.000000000, 1.000000000, 0.000000000, 0);
Mathf_exp(1.000000000, 2.718281746, -0.3462330997, INEXACT);
Mathf_exp(-1.000000000, 0.3678794503, 0.3070148528, INEXACT);
Mathf_exp(Infinity, Infinity, 0.000000000, 0);
Mathf_exp(-Infinity, 0.000000000, 0.000000000, 0);
Mathf_exp(NaN, NaN, 0.000000000, 0);
Mathf_exp(88.72283173, 3.402798519e+38, -0.09067153931, INEXACT);
Mathf_exp(88.72283936, Infinity, 0.000000000, INEXACT|OVERFLOW);
Mathf_exp(-103.9720764, 1.401298464e-45, 0.4999996722, INEXACT|UNDERFLOW);
Mathf_exp(-103.9720840, 0.000000000, -0.4999965131, INEXACT|UNDERFLOW);
Mathf_exp(0.3465735614, 1.414213538, 0.1392242163, INEXACT);
Mathf_exp(0.3465735912, 1.414213538, -0.2143291682, INEXACT);
Mathf_exp(0.3465736210, 1.414213657, 0.4321174324, INEXACT);

File diff suppressed because it is too large Load Diff