diff --git a/js/src/tests/ecma_6/Math/acosh-approx.js b/js/src/tests/ecma_6/Math/acosh-approx.js index 630303fe8d5..53800e2ebe6 100644 --- a/js/src/tests/ecma_6/Math/acosh-approx.js +++ b/js/src/tests/ecma_6/Math/acosh-approx.js @@ -262,20 +262,22 @@ var cosh_data = [ [1875817529344, 28.953212876533797] ]; +var sloppy_tolerance = 1000; // FIXME + for (var [x, y] of cosh_data) - assertNear(Math.acosh(x), y); + assertNear(Math.acosh(x), y, sloppy_tolerance); + +assertNear(Math.acosh(1e300), 691.4686750787737, sloppy_tolerance); +assertNear(Math.acosh(1.0000000001), 0.000014142136208675862, sloppy_tolerance); for (var i = 0; i <= 100; i++) { var x = (i - 50) / 5; var y = Math.cosh(x); var z = Math.acosh(y); - assertNear(z, Math.abs(x)); + assertNear(z, Math.abs(x), sloppy_tolerance); } for (var i = 1; i < 20; i++) - assertNear(Math.acosh(Math.cosh(i)), i); - -assertNear(Math.acosh(1e300), 691.4686750787737); -assertNear(Math.acosh(1.0000000001), 0.000014142136208675862); + assertNear(Math.acosh(Math.cosh(i)), i, sloppy_tolerance); reportCompare(0, 0, "ok"); diff --git a/js/src/tests/ecma_6/Math/asinh-approx.js b/js/src/tests/ecma_6/Math/asinh-approx.js index bfb8eb47935..daf60ed8dbb 100644 --- a/js/src/tests/ecma_6/Math/asinh-approx.js +++ b/js/src/tests/ecma_6/Math/asinh-approx.js @@ -282,24 +282,24 @@ var sinh_data = [ [1581915832320, 28.78280496108106] ]; +var sloppy_tolerance = 1000; // FIXME + for (var [x, y] of sinh_data) - assertNear(Math.asinh(x), y); + assertNear(Math.asinh(x), y, sloppy_tolerance); + +assertNear(Math.asinh(1e300), 691.4686750787737, sloppy_tolerance); +assertNear(Math.asinh(1e-300), 1e-300, sloppy_tolerance); +assertNear(Math.asinh(1e-5), 0.000009999999999833334, sloppy_tolerance); +assertNear(Math.asinh(0.3), 0.29567304756342244, sloppy_tolerance); +assertNear(Math.asinh(1), 0.881373587019543, sloppy_tolerance); for (var i = 0; i <= 80; i++) { var x = (i - 40) / 4; - var y = Math.sinh(x); - var z = Math.asinh(y); - assertNear(z, x); + assertNear(Math.asinh(Math.sinh(x)), x, sloppy_tolerance); } for (var i = -20; i < 20; i++) - assertNear(Math.asinh(Math.sinh(i)), i); - -assertNear(Math.asinh(1e300), 691.4686750787737); -assertNear(Math.asinh(1e-300), 1e-300); -assertNear(Math.asinh(1e-5), 0.000009999999999833334); -assertNear(Math.asinh(0.3), 0.29567304756342244); -assertNear(Math.asinh(1), 0.881373587019543); + assertNear(Math.asinh(Math.sinh(i)), i, sloppy_tolerance); reportCompare(0, 0, "ok"); diff --git a/js/src/tests/ecma_6/Math/atanh-approx.js b/js/src/tests/ecma_6/Math/atanh-approx.js index 41d4fd1ca95..998db4e7f2c 100644 --- a/js/src/tests/ecma_6/Math/atanh-approx.js +++ b/js/src/tests/ecma_6/Math/atanh-approx.js @@ -1,6 +1,3 @@ -for (var i = -1; i < 1; i += 0.05) - assertNear(Math.atanh(Math.tanh(i)), i); - var tanh_data = [ [-0.9999983310699463, -6.998237084679027], [-0.9999978542327881, -6.87257975132917], @@ -269,10 +266,15 @@ var tanh_data = [ [1e-10, 1e-10], ]; -for (var [x, y] of tanh_data) - assertNear(Math.atanh(x), y); +var sloppy_tolerance = 10; // FIXME -assertNear(Math.atanh(+3 / 5), +Math.log(2)); -assertNear(Math.atanh(-3 / 5), -Math.log(2)); +for (var [x, y] of tanh_data) + assertNear(Math.atanh(x), y, sloppy_tolerance); + +assertNear(Math.atanh(+3 / 5), +Math.log(2), sloppy_tolerance); +assertNear(Math.atanh(-3 / 5), -Math.log(2), sloppy_tolerance); + +for (var i = -1; i < 1; i += 0.05) + assertNear(Math.atanh(Math.tanh(i)), i, sloppy_tolerance); reportCompare(0, 0, "ok"); diff --git a/js/src/tests/ecma_6/Math/cbrt-approx.js b/js/src/tests/ecma_6/Math/cbrt-approx.js index b5511753756..2c7f26fafc2 100644 --- a/js/src/tests/ecma_6/Math/cbrt-approx.js +++ b/js/src/tests/ecma_6/Math/cbrt-approx.js @@ -1,8 +1,10 @@ assertEq(Math.cbrt(1), 1); assertEq(Math.cbrt(-1), -1); -assertNear(Math.cbrt(1e-300), 1e-100); -assertNear(Math.cbrt(-1e-300), -1e-100); +var sloppy_tolerance = 200; // FIXME + +assertNear(Math.cbrt(1e-300), 1e-100, sloppy_tolerance); +assertNear(Math.cbrt(-1e-300), -1e-100, sloppy_tolerance); var cbrt_data = [ [ Math.E, 1.3956124250860895 ], @@ -12,7 +14,6 @@ var cbrt_data = [ ]; for (var [x, y] of cbrt_data) - assertNear(Math.cbrt(x), y); + assertNear(Math.cbrt(x), y, sloppy_tolerance); reportCompare(0, 0, "ok"); - diff --git a/js/src/tests/ecma_6/Math/cosh-approx.js b/js/src/tests/ecma_6/Math/cosh-approx.js index acf18668df9..b701bb1df98 100644 --- a/js/src/tests/ecma_6/Math/cosh-approx.js +++ b/js/src/tests/ecma_6/Math/cosh-approx.js @@ -1,9 +1,9 @@ -for (var i = -20; i < 20; i++) - assertNear(Math.cosh(i), (Math.exp(i) + Math.exp(-i)) / 2); +var sloppy_tolerance = 100; -assertNear(Math.cosh(1e5), Infinity); -assertNear(Math.cosh(1e-30), 1); -assertNear(Math.cosh(1e-10), 1); +assertEq(Math.cosh(1000), Infinity); +assertEq(Math.cosh(Number.MAX_VALUE), Infinity); +assertNear(Math.cosh(1e-30), 1, sloppy_tolerance); +assertNear(Math.cosh(1e-10), 1, sloppy_tolerance); var cosh_data = [ [0.0016914556651292944, 1.0000014305114746], @@ -270,6 +270,9 @@ var cosh_data = [ ]; for (var [x, y] of cosh_data) - assertNear(Math.cosh(x), y); + assertNear(Math.cosh(x), y, sloppy_tolerance); + +for (var i = -20; i < 20; i++) + assertNear(Math.cosh(i), (Math.exp(i) + Math.exp(-i)) / 2, sloppy_tolerance); reportCompare(0, 0, "ok"); diff --git a/js/src/tests/ecma_6/Math/hypot-approx.js b/js/src/tests/ecma_6/Math/hypot-approx.js index 9960d55d2ea..45c22afb9e5 100644 --- a/js/src/tests/ecma_6/Math/hypot-approx.js +++ b/js/src/tests/ecma_6/Math/hypot-approx.js @@ -1,17 +1,16 @@ // |reftest| skip // Math.hypot is disabled pending the resolution of spec issues (bug 896264). -for (var i = -20; i < 20; i++) +for (var i = -20; i < 20; i++) { assertEq(Math.hypot(+0, i), Math.abs(i)); - -for (var i = -20; i < 20; i++) assertEq(Math.hypot(-0, i), Math.abs(i)); - -for (var i = 1, j = 1; i < 2; i += 0.05, j += 0.05) - assertNear(Math.hypot(i, j), Math.sqrt(i * i + j * j)); +} assertNear(Math.hypot(1e300, 1e300), 1.4142135623730952e+300); assertNear(Math.hypot(1e-300, 1e-300), 1.414213562373095e-300); assertNear(Math.hypot(1e3, 1e-3), 1000.0000000005); +for (var i = 1, j = 1; i < 2; i += 0.05, j += 0.05) + assertNear(Math.hypot(i, j), Math.sqrt(i * i + j * j)); + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/ecma_6/Math/log10-approx.js b/js/src/tests/ecma_6/Math/log10-approx.js index d6919efa523..04894485130 100644 --- a/js/src/tests/ecma_6/Math/log10-approx.js +++ b/js/src/tests/ecma_6/Math/log10-approx.js @@ -1,9 +1,9 @@ -for (var i = -10; i < 10; i++) - assertNear(Math.log10(Math.pow(10, i)), i); - assertNear(Math.log10(2), 0.3010299956639812); assertNear(Math.log10(7), 0.8450980400142568); assertNear(Math.log10(Math.E), Math.LOG10E); +for (var i = -10; i < 10; i++) + assertNear(Math.log10(Math.pow(10, i)), i); + reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/ecma_6/Math/shell.js b/js/src/tests/ecma_6/Math/shell.js index deed2bd9262..d423c0814c6 100644 --- a/js/src/tests/ecma_6/Math/shell.js +++ b/js/src/tests/ecma_6/Math/shell.js @@ -2,10 +2,73 @@ const ONE_PLUS_EPSILON = 1 + Math.pow(2, -52); // 0.9999999999999999 const ONE_MINUS_EPSILON = 1 - Math.pow(2, -53); // 1.0000000000000002 -function assertNear(actual, expected) { - var error = Math.abs(actual - expected); +{ + var fail = function (msg) { + var exc = new Error(msg); + try { + // Try to improve on exc.fileName and .lineNumber; leave exc.stack + // alone. We skip two frames: fail() and its caller, an assertX() + // function. + var frames = exc.stack.trim().split("\n"); + if (frames.length > 2) { + var m = /@([^@:]*):([0-9]+)$/.exec(frames[2]); + if (m) { + exc.fileName = m[1]; + exc.lineNumber = +m[2]; + } + } + } catch (ignore) { throw ignore;} + throw exc; + }; - if (error > 1e-300 && error > Math.abs(actual) * 1e-12) - throw 'Assertion failed: got "' + actual + '", expected "' + expected + '" (rel error = ' + (error / Math.abs(actual)) + ')'; + var ENDIAN; // 0 for little-endian, 1 for big-endian. + + // Return the difference between the IEEE 754 bit-patterns for a and b. + // + // This is meaningful when a and b are both finite and have the same + // sign. Then the following hold: + // + // * If a === b, then diff(a, b) === 0. + // + // * If a !== b, then diff(a, b) === 1 + the number of representable values + // between a and b. + // + var f = new Float64Array([0, 0]); + var u = new Uint32Array(f.buffer); + var diff = function (a, b) { + f[0] = a; + f[1] = b; + //print(u[1].toString(16) + u[0].toString(16) + " " + u[3].toString(16) + u[2].toString(16)); + return Math.abs((u[3-ENDIAN] - u[1-ENDIAN]) * 0x100000000 + u[2+ENDIAN] - u[0+ENDIAN]); + }; + + // Set ENDIAN to the platform's endianness. + ENDIAN = 0; // try little-endian first + if (diff(2, 4) === 0x100000) // exact wrong answer we'll get on a big-endian platform + ENDIAN = 1; + assertEq(diff(2,4), 0x10000000000000); + assertEq(diff(0, Number.MIN_VALUE), 1); + assertEq(diff(1, ONE_PLUS_EPSILON), 1); + assertEq(diff(1, ONE_MINUS_EPSILON), 1); + + var assertNear = function assertNear(a, b, tolerance=1) { + if (!Number.isFinite(b)) { + fail("second argument to assertNear (expected value) must be a finite number"); + } else if (Number.isNaN(a)) { + fail("got NaN, expected a number near " + b); + } else if (!Number.isFinite(a)) { + if (b * Math.sign(a) < Number.MAX_VALUE) + fail("got " + a + ", expected a number near " + b); + } else { + // When the two arguments do not have the same sign bit, diff() + // returns some huge number. So if b is positive or negative 0, + // make target the zero that has the same sign bit as a. + var target = b === 0 ? a * 0 : b; + var err = diff(a, target); + if (err > tolerance) { + fail("got " + a + ", expected a number near " + b + + " (relative error: " + err + ")"); + } + } + }; } - diff --git a/js/src/tests/ecma_6/Math/sinh-approx.js b/js/src/tests/ecma_6/Math/sinh-approx.js index 415110d92ea..91eda049acb 100644 --- a/js/src/tests/ecma_6/Math/sinh-approx.js +++ b/js/src/tests/ecma_6/Math/sinh-approx.js @@ -1,9 +1,11 @@ +var sloppy_tolerance = 100; for (var i = -20; i < 20; i++) - assertNear(Math.sinh(i), (Math.exp(i) - Math.exp(-i)) / 2); + assertNear(Math.sinh(i), (Math.exp(i) - Math.exp(-i)) / 2, sloppy_tolerance); -assertNear(Math.sinh(1e5), Infinity); -assertNear(Math.sinh(1e-30), 1e-30); -assertNear(Math.sinh(1e-10), 1e-10); +assertEq(Math.sinh(1000), Infinity); +assertEq(Math.sinh(Number.MAX_VALUE), Infinity); +assertNear(Math.sinh(1e-30), 1e-30, sloppy_tolerance); +assertNear(Math.sinh(1e-10), 1e-10, sloppy_tolerance); var sinh_data = [ [-6.902103625349695, -497.1816406250001], @@ -290,7 +292,7 @@ var sinh_data = [ ]; for (var [x, y] of sinh_data) - assertNear(Math.sinh(x), y); + assertNear(Math.sinh(x), y, sloppy_tolerance); reportCompare(0, 0, "ok"); diff --git a/js/src/tests/ecma_6/Math/tanh-approx.js b/js/src/tests/ecma_6/Math/tanh-approx.js index dd9bf0e91cc..b41427c30c3 100644 --- a/js/src/tests/ecma_6/Math/tanh-approx.js +++ b/js/src/tests/ecma_6/Math/tanh-approx.js @@ -1,5 +1,10 @@ -for (var i = -20; i < 20; i++) - assertNear(Math.tanh(i), (Math.exp(i) - Math.exp(-i)) / (Math.exp(i) + Math.exp(-i))); +var sloppy_tolerance = 4; + +for (var i = -20; i < 20; i++) { + assertNear(Math.tanh(i), + (Math.exp(i) - Math.exp(-i)) / (Math.exp(i) + Math.exp(-i)), + sloppy_tolerance); +} assertEq(Math.tanh(1e300), 1); @@ -272,6 +277,6 @@ var tanh_data = [ ]; for (var [x, y] of tanh_data) - assertNear(Math.tanh(y), x); + assertNear(Math.tanh(y), x, sloppy_tolerance); reportCompare(0, 0, "ok");