js/src/tests/ecma_6/Math/shell.js

changeset 0
6474c204b198
     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 +}

mercurial