tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

shell.js (3054B)


      1 /*---
      2 defines: [assertNear]
      3 allow_unused: True
      4 ---*/
      5 
      6 // The nearest representable values to +1.0.
      7 const ONE_PLUS_EPSILON = 1 + Math.pow(2, -52);  // 0.9999999999999999
      8 const ONE_MINUS_EPSILON = 1 - Math.pow(2, -53);  // 1.0000000000000002
      9 
     10 {
     11    const fail = function (msg) {
     12        var exc = new Error(msg);
     13        try {
     14            // Try to improve on exc.fileName and .lineNumber; leave exc.stack
     15            // alone. We skip two frames: fail() and its caller, an assertX()
     16            // function.
     17            var frames = exc.stack.trim().split("\n");
     18            if (frames.length > 2) {
     19                var m = /@([^@:]*):([0-9]+)$/.exec(frames[2]);
     20                if (m) {
     21                    exc.fileName = m[1];
     22                    exc.lineNumber = +m[2];
     23                }
     24            }
     25        } catch (ignore) { throw ignore;}
     26        throw exc;
     27    };
     28 
     29    let ENDIAN;  // 0 for little-endian, 1 for big-endian.
     30 
     31    // Return the difference between the IEEE 754 bit-patterns for a and b.
     32    //
     33    // This is meaningful when a and b are both finite and have the same
     34    // sign. Then the following hold:
     35    //
     36    //   * If a === b, then diff(a, b) === 0.
     37    //
     38    //   * If a !== b, then diff(a, b) === 1 + the number of representable values
     39    //                                         between a and b.
     40    //
     41    const f = new Float64Array([0, 0]);
     42    const u = new Uint32Array(f.buffer);
     43    const diff = function (a, b) {
     44        f[0] = a;
     45        f[1] = b;
     46        //print(u[1].toString(16) + u[0].toString(16) + " " + u[3].toString(16) + u[2].toString(16));
     47        return Math.abs((u[3-ENDIAN] - u[1-ENDIAN]) * 0x100000000 + u[2+ENDIAN] - u[0+ENDIAN]);
     48    };
     49 
     50    // Set ENDIAN to the platform's endianness.
     51    ENDIAN = 0;  // try little-endian first
     52    if (diff(2, 4) === 0x100000)  // exact wrong answer we'll get on a big-endian platform
     53        ENDIAN = 1;
     54    assertEq(diff(2,4), 0x10000000000000);
     55    assertEq(diff(0, Number.MIN_VALUE), 1);
     56    assertEq(diff(1, ONE_PLUS_EPSILON), 1);
     57    assertEq(diff(1, ONE_MINUS_EPSILON), 1);
     58 
     59    var assertNear = function assertNear(a, b, tolerance=1) {
     60        if (!Number.isFinite(b)) {
     61            fail("second argument to assertNear (expected value) must be a finite number");
     62        } else if (Number.isNaN(a)) {
     63            fail("got NaN, expected a number near " + b);
     64        } else if (!Number.isFinite(a)) {
     65            if (b * Math.sign(a) < Number.MAX_VALUE)
     66                fail("got " + a + ", expected a number near " + b);
     67        } else if (a !== b) {
     68            // When the two arguments do not have the same sign bit, diff()
     69            // returns some huge number. So if b is positive or negative 0,
     70            // make target the zero that has the same sign bit as a.
     71            var target = b === 0 ? a * 0 : b;
     72            var err = diff(a, target);
     73            if (err > tolerance) {
     74                fail("got " + a + ", expected a number near " + b +
     75                     " (relative error: " + err + ")");
     76            }
     77        }
     78    };
     79 }