mirror of https://github.com/tc39/test262.git
80 lines
3.0 KiB
JavaScript
80 lines
3.0 KiB
JavaScript
/*---
|
|
defines: [assertNear]
|
|
allow_unused: True
|
|
---*/
|
|
|
|
// 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
|
|
|
|
{
|
|
const 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;
|
|
};
|
|
|
|
let 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.
|
|
//
|
|
const f = new Float64Array([0, 0]);
|
|
const u = new Uint32Array(f.buffer);
|
|
const 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 + ")");
|
|
}
|
|
}
|
|
};
|
|
}
|