summaryrefslogtreecommitdiffstats
path: root/js/src/tests/ecma_6/Math/shell.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/tests/ecma_6/Math/shell.js')
-rw-r--r--js/src/tests/ecma_6/Math/shell.js74
1 files changed, 74 insertions, 0 deletions
diff --git a/js/src/tests/ecma_6/Math/shell.js b/js/src/tests/ecma_6/Math/shell.js
new file mode 100644
index 000000000..d423c0814
--- /dev/null
+++ b/js/src/tests/ecma_6/Math/shell.js
@@ -0,0 +1,74 @@
+// The nearest representable values to +1.0.
+const ONE_PLUS_EPSILON = 1 + Math.pow(2, -52); // 0.9999999999999999
+const ONE_MINUS_EPSILON = 1 - Math.pow(2, -53); // 1.0000000000000002
+
+{
+ 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;
+ };
+
+ 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 + ")");
+ }
+ }
+ };
+}