tor-browser

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

mod-double-power-of-two.js (4955B)


      1 const isLittleEndian = new Uint8Array(new Uint16Array([1]).buffer)[0] === 1;
      2 
      3 function fromRawBits(s) {
      4  let bits = s.split(" ").map(n => parseInt(n, 16));
      5  assertEq(bits.length, 8);
      6  if (isLittleEndian) {
      7    bits.reverse();
      8  }
      9  return new Float64Array(new Uint8Array(bits).buffer)[0];
     10 }
     11 
     12 function toRawBits(d) {
     13  let bits = [...new Uint8Array(new Float64Array([d]).buffer)];
     14  if (isLittleEndian) {
     15    bits.reverse();
     16  }
     17  return bits.map(n => n.toString(16).padStart(2, "0")).join(" ");
     18 }
     19 
     20 assertEq(fromRawBits("7f ef ff ff ff ff ff ff"), Number.MAX_VALUE);
     21 assertEq(toRawBits(Number.MAX_VALUE), "7f ef ff ff ff ff ff ff");
     22 
     23 assertEq(fromRawBits("00 00 00 00 00 00 00 01"), Number.MIN_VALUE);
     24 assertEq(toRawBits(Number.MIN_VALUE), "00 00 00 00 00 00 00 01");
     25 
     26 let values = [
     27  0, 0.000001, 0.1, 0.125, 1/6, 0.25, 0.3, 1/3, 0.5, 2/3, 0.8, 0.9,
     28  1, 2, 3, 4, 5, 10, 14, 15, 16,
     29  100.1, 100.2,
     30 
     31  Number.MAX_SAFE_INTEGER + 4,
     32  Number.MAX_SAFE_INTEGER + 3,
     33  Number.MAX_SAFE_INTEGER + 2,
     34  Number.MAX_SAFE_INTEGER + 1,
     35  Number.MAX_SAFE_INTEGER,
     36  Number.MAX_SAFE_INTEGER - 1,
     37  Number.MAX_SAFE_INTEGER - 2,
     38  Number.MAX_SAFE_INTEGER - 3,
     39  Number.MAX_SAFE_INTEGER - 4,
     40 
     41  // Largest normal (Number.MAX_VALUE)
     42  fromRawBits("7f ef ff ff ff ff ff ff"),
     43  fromRawBits("7f ef ff ff ff ff ff fe"),
     44  fromRawBits("7f ef ff ff ff ff ff fd"),
     45  fromRawBits("7f ef ff ff ff ff ff fc"),
     46  fromRawBits("7f ef ff ff ff ff ff fb"),
     47  fromRawBits("7f ef ff ff ff ff ff fa"),
     48  fromRawBits("7f ef ff ff ff ff ff f9"),
     49  fromRawBits("7f ef ff ff ff ff ff f8"),
     50  fromRawBits("7f ef ff ff ff ff ff f7"),
     51  fromRawBits("7f ef ff ff ff ff ff f6"),
     52  fromRawBits("7f ef ff ff ff ff ff f5"),
     53  fromRawBits("7f ef ff ff ff ff ff f4"),
     54  fromRawBits("7f ef ff ff ff ff ff f3"),
     55  fromRawBits("7f ef ff ff ff ff ff f2"),
     56  fromRawBits("7f ef ff ff ff ff ff f1"),
     57  fromRawBits("7f ef ff ff ff ff ff f0"),
     58 
     59  // Smallest subnormal (Number.MIN_VALUE)
     60  fromRawBits("00 00 00 00 00 00 00 01"),
     61  fromRawBits("00 00 00 00 00 00 00 02"),
     62  fromRawBits("00 00 00 00 00 00 00 03"),
     63  fromRawBits("00 00 00 00 00 00 00 04"),
     64  fromRawBits("00 00 00 00 00 00 00 05"),
     65  fromRawBits("00 00 00 00 00 00 00 06"),
     66  fromRawBits("00 00 00 00 00 00 00 07"),
     67  fromRawBits("00 00 00 00 00 00 00 08"),
     68  fromRawBits("00 00 00 00 00 00 00 09"),
     69  fromRawBits("00 00 00 00 00 00 00 0a"),
     70  fromRawBits("00 00 00 00 00 00 00 0b"),
     71  fromRawBits("00 00 00 00 00 00 00 0c"),
     72  fromRawBits("00 00 00 00 00 00 00 0d"),
     73  fromRawBits("00 00 00 00 00 00 00 0e"),
     74  fromRawBits("00 00 00 00 00 00 00 0f"),
     75 
     76  // Largest subnormal
     77  fromRawBits("00 0f ff ff ff ff ff ff"),
     78  fromRawBits("00 0f ff ff ff ff ff fe"),
     79  fromRawBits("00 0f ff ff ff ff ff fd"),
     80  fromRawBits("00 0f ff ff ff ff ff fc"),
     81  fromRawBits("00 0f ff ff ff ff ff fb"),
     82  fromRawBits("00 0f ff ff ff ff ff fa"),
     83  fromRawBits("00 0f ff ff ff ff ff f9"),
     84  fromRawBits("00 0f ff ff ff ff ff f8"),
     85  fromRawBits("00 0f ff ff ff ff ff f7"),
     86  fromRawBits("00 0f ff ff ff ff ff f6"),
     87  fromRawBits("00 0f ff ff ff ff ff f5"),
     88  fromRawBits("00 0f ff ff ff ff ff f4"),
     89  fromRawBits("00 0f ff ff ff ff ff f3"),
     90  fromRawBits("00 0f ff ff ff ff ff f2"),
     91  fromRawBits("00 0f ff ff ff ff ff f1"),
     92  fromRawBits("00 0f ff ff ff ff ff f0"),
     93 
     94  // Least positive normal
     95  fromRawBits("00 10 00 00 00 00 00 00"),
     96  fromRawBits("00 10 00 00 00 00 00 01"),
     97  fromRawBits("00 10 00 00 00 00 00 02"),
     98  fromRawBits("00 10 00 00 00 00 00 03"),
     99  fromRawBits("00 10 00 00 00 00 00 04"),
    100  fromRawBits("00 10 00 00 00 00 00 05"),
    101  fromRawBits("00 10 00 00 00 00 00 06"),
    102  fromRawBits("00 10 00 00 00 00 00 07"),
    103  fromRawBits("00 10 00 00 00 00 00 08"),
    104  fromRawBits("00 10 00 00 00 00 00 09"),
    105  fromRawBits("00 10 00 00 00 00 00 0a"),
    106  fromRawBits("00 10 00 00 00 00 00 0b"),
    107  fromRawBits("00 10 00 00 00 00 00 0c"),
    108  fromRawBits("00 10 00 00 00 00 00 0d"),
    109  fromRawBits("00 10 00 00 00 00 00 0e"),
    110  fromRawBits("00 10 00 00 00 00 00 0f"),
    111 
    112  Infinity,
    113  NaN,
    114 
    115  Math.E, Math.LN10, Math.LN2, Math.LOG10E, Math.LOG2E,
    116  Math.PI, Math.SQRT1_2, Math.SQRT2,
    117 ];
    118 
    119 // Also test with sign bit set.
    120 values = values.concat(values.map(x => -x));
    121 
    122 function mod(n, d) {
    123  with ({}); // disable Ion
    124  return n % d;
    125 }
    126 
    127 function makeTest(divisor) {
    128  function test() {
    129    let expected = values.map(x => mod(x, divisor));
    130 
    131    for (let i = 0; i < 2000; ++i) {
    132      let j = i % values.length;
    133      assertEq(values[j] % divisor, expected[j]);
    134    }
    135  }
    136 
    137  // Create a new function for each divisor to ensure we have proper compile-time constants.
    138  return Function(`return ${test.toString().replaceAll("divisor", divisor)}`)();
    139 }
    140 
    141 // The optimisation is used for power of two values up to 2^31.
    142 for (let i = 0; i <= 31; ++i) {
    143  let divisor = 2 ** i;
    144  let f = makeTest(divisor);
    145  f();
    146 }
    147 
    148 // Also cover some cases which don't trigger the optimisation
    149 for (let divisor of [-3, -2, -1, -0.5, 0, 0.5, 3, 5, 10]) {
    150  let f = makeTest(divisor);
    151  f();
    152 }