1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/tests/ecma_6/Math/shell.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,74 @@ 1.4 +// The nearest representable values to +1.0. 1.5 +const ONE_PLUS_EPSILON = 1 + Math.pow(2, -52); // 0.9999999999999999 1.6 +const ONE_MINUS_EPSILON = 1 - Math.pow(2, -53); // 1.0000000000000002 1.7 + 1.8 +{ 1.9 + var fail = function (msg) { 1.10 + var exc = new Error(msg); 1.11 + try { 1.12 + // Try to improve on exc.fileName and .lineNumber; leave exc.stack 1.13 + // alone. We skip two frames: fail() and its caller, an assertX() 1.14 + // function. 1.15 + var frames = exc.stack.trim().split("\n"); 1.16 + if (frames.length > 2) { 1.17 + var m = /@([^@:]*):([0-9]+)$/.exec(frames[2]); 1.18 + if (m) { 1.19 + exc.fileName = m[1]; 1.20 + exc.lineNumber = +m[2]; 1.21 + } 1.22 + } 1.23 + } catch (ignore) { throw ignore;} 1.24 + throw exc; 1.25 + }; 1.26 + 1.27 + var ENDIAN; // 0 for little-endian, 1 for big-endian. 1.28 + 1.29 + // Return the difference between the IEEE 754 bit-patterns for a and b. 1.30 + // 1.31 + // This is meaningful when a and b are both finite and have the same 1.32 + // sign. Then the following hold: 1.33 + // 1.34 + // * If a === b, then diff(a, b) === 0. 1.35 + // 1.36 + // * If a !== b, then diff(a, b) === 1 + the number of representable values 1.37 + // between a and b. 1.38 + // 1.39 + var f = new Float64Array([0, 0]); 1.40 + var u = new Uint32Array(f.buffer); 1.41 + var diff = function (a, b) { 1.42 + f[0] = a; 1.43 + f[1] = b; 1.44 + //print(u[1].toString(16) + u[0].toString(16) + " " + u[3].toString(16) + u[2].toString(16)); 1.45 + return Math.abs((u[3-ENDIAN] - u[1-ENDIAN]) * 0x100000000 + u[2+ENDIAN] - u[0+ENDIAN]); 1.46 + }; 1.47 + 1.48 + // Set ENDIAN to the platform's endianness. 1.49 + ENDIAN = 0; // try little-endian first 1.50 + if (diff(2, 4) === 0x100000) // exact wrong answer we'll get on a big-endian platform 1.51 + ENDIAN = 1; 1.52 + assertEq(diff(2,4), 0x10000000000000); 1.53 + assertEq(diff(0, Number.MIN_VALUE), 1); 1.54 + assertEq(diff(1, ONE_PLUS_EPSILON), 1); 1.55 + assertEq(diff(1, ONE_MINUS_EPSILON), 1); 1.56 + 1.57 + var assertNear = function assertNear(a, b, tolerance=1) { 1.58 + if (!Number.isFinite(b)) { 1.59 + fail("second argument to assertNear (expected value) must be a finite number"); 1.60 + } else if (Number.isNaN(a)) { 1.61 + fail("got NaN, expected a number near " + b); 1.62 + } else if (!Number.isFinite(a)) { 1.63 + if (b * Math.sign(a) < Number.MAX_VALUE) 1.64 + fail("got " + a + ", expected a number near " + b); 1.65 + } else { 1.66 + // When the two arguments do not have the same sign bit, diff() 1.67 + // returns some huge number. So if b is positive or negative 0, 1.68 + // make target the zero that has the same sign bit as a. 1.69 + var target = b === 0 ? a * 0 : b; 1.70 + var err = diff(a, target); 1.71 + if (err > tolerance) { 1.72 + fail("got " + a + ", expected a number near " + b + 1.73 + " (relative error: " + err + ")"); 1.74 + } 1.75 + } 1.76 + }; 1.77 +}