github.com/moontrade/unsafe@v0.9.1/memory/hash/hash.js (about)

     1  class WyF3 {
     2      static DefaultSeed = BigInt.asUintN(64, 0xa0761d6478bd642fn);
     3      static s1 = BigInt.asUintN(64, 0xe7037ed1a0b428dbn);
     4      static s2 = BigInt.asUintN(64, 0x8ebc6af09c88c6e3n);
     5      static s3 = BigInt.asUintN(64, 0x589965cc75374cc3n);
     6      static s4 = BigInt.asUintN(64, 0x1d8e4e27c47d124fn);
     7      static mask64 = BigInt.asUintN(64, 0xFFFFFFFFFFFFFFFFn);
     8      static mask128 = BigInt.asUintN(128, 0xFFFFFFFFFFFFFFFFn);
     9      static uint64hi = BigInt.asUintN(64, WyF3.s1 ^ BigInt.asUintN(64, 8n));
    10      static numberBuffer = Uint8Array.of(0, 0, 0, 0, 0, 0, 0, 0);
    11      static numberBufferView = new DataView(WyF3.numberBuffer.buffer);
    12  
    13      static mix(x, y) {
    14          // mul128
    15          let r = BigInt.asUintN(128, x) * BigInt.asUintN(128, y);
    16          let hi = BigInt.asUintN(64, (r >> 64n) & WyF3.mask128);
    17          let lo = BigInt.asUintN(64, r & WyF3.mask128);
    18          return hi ^ lo;
    19      }
    20  
    21      static read32(d, offset) {
    22          return BigInt.asUintN(64, BigInt(d.getUint32(offset, true)));
    23      }
    24  
    25      static uint64(value = 0n, seed = WyF3.DefaultSeed) {
    26          WyF3.numberBufferView.setBigUint64(0, BigInt.asUintN(64, BigInt(value)), true);
    27          return WyF3.uint64Internal(seed);
    28      }
    29  
    30      static number(value = 0, seed = WyF3.DefaultSeed) {
    31          WyF3.numberBufferView.setFloat64(0, value, true);
    32          return WyF3.uint64Internal(seed);
    33      }
    34  
    35      static uint64Internal(seed = WyF3.DefaultSeed) {
    36          const v = WyF3.numberBufferView.getBigUint64(0, true);
    37          let hi = BigInt.asUintN(64, (v >> 32n) & WyF3.mask64);
    38          let lo = BigInt.asUintN(64, v & WyF3.mask64);
    39          return WyF3.mix(WyF3.uint64hi, WyF3.mix(hi ^ WyF3.s1, lo ^ seed));
    40      }
    41  
    42      static string(data = '', seed = WyF3.DefaultSeed) {
    43          const d = new TextEncoder().encode(data);
    44          return WyF3.hashBytes(new DataView(d.buffer), seed);
    45      }
    46  
    47      static hash(value, seed = WyF3.DefaultSeed) {
    48          if (typeof value === 'string') {
    49              return WyF3.string(value, seed);
    50          }
    51          if (typeof value === 'bigint') {
    52              return WyF3.uint64(value, seed);
    53          }
    54          if (typeof value === 'number') {
    55              return WyF3.number(value, seed);
    56          }
    57          if (value instanceof DataView) {
    58              return WyF3.hashBytes(value, seed);
    59          }
    60          if (value instanceof ArrayBuffer) {
    61              return WyF3.hashBytes(new DataView(value), seed);
    62          }
    63          if (value instanceof Uint8Array) {
    64              return WyF3.hashBytes(new DataView(value.buffer), seed);
    65          }
    66          throw 'WyF3.hash supports string, bigint, number, DataView, ArrayBuffer, Uint8Array';
    67      }
    68  
    69      /**
    70       *
    71       * @param d DataView
    72       * @param seed
    73       * @returns {*}
    74       */
    75      static hashBytes(d, seed = WyF3.DefaultSeed) {
    76          let length = d.byteLength;
    77          let a;
    78          let b;
    79  
    80          if (length <= 16) {
    81              if (length >= 4) {
    82                  a = (WyF3.read32(d, 0) << BigInt.asUintN(64, 32n)) | WyF3.read32(d, (length >> 3) << 2);
    83                  b = (WyF3.read32(d, length - 4) << BigInt.asUintN(64, 32n)) | WyF3.read32(d, length - 4 - ((length >> 3) << 2));
    84              } else if (length > 0) {
    85                  a = BigInt.asUintN(64, BigInt(d.getUint8(0) << 16 |
    86                      d.getUint8(length >> 1) << 8 |
    87                      d.getUint8(length - 1)));
    88                  b = 0n;
    89              }
    90          } else {
    91              let index = length;
    92              let start = 0;
    93              if (length > 48) {
    94                  let see1 = seed;
    95                  let see2 = seed;
    96                  for (; index > 48;) {
    97                      seed = WyF3.mix(d.getBigUint64(start, true) ^ WyF3.s1, d.getBigUint64(start + 8, true) ^ seed);
    98                      see1 = WyF3.mix(d.getBigUint64(start + 16, true) ^ WyF3.s2, d.getBigUint64(start + 24, true) ^ see1);
    99                      see2 = WyF3.mix(d.getBigUint64(start + 32, true) ^ WyF3.s3, d.getBigUint64(start + 40, true) ^ see2);
   100                      index -= 48;
   101                      start += 48;
   102                  }
   103                  seed ^= see1 ^ see2;
   104              }
   105  
   106              for (; index > 16;) {
   107                  seed = WyF3.mix(d.getBigUint64(start, true) ^ WyF3.s1, d.getBigUint64(start + 8, true) ^ seed);
   108                  index -= 16;
   109                  start += 16;
   110              }
   111  
   112              a = d.getBigUint64(start + index - 16, true);
   113              b = d.getBigUint64(start + index - 8, true);
   114          }
   115  
   116          return WyF3.mix(WyF3.s1 ^ BigInt(length), WyF3.mix(a ^ WyF3.s1, b ^ seed));
   117      }
   118  }
   119  
   120  class WyF3Rand {
   121      static DEFAULT = new WyF3Rand(new Date().getTime());
   122  
   123      constructor(seed) {
   124          this.seed = BigInt.asUintN(64, BigInt(seed));
   125      }
   126  
   127      static RAND_C0 = BigInt.asUintN(64, 0xa0761d6478bd642fn);
   128      static RAND_C1 = BigInt.asUintN(64, 0xe7037ed1a0b428dbn);
   129  
   130  
   131      next() {
   132          this.seed += WyF3Rand.RAND_C0;
   133          return WyF3.mix(this.seed, this.seed ^ WyF3Rand.RAND_C1);
   134      }
   135  
   136      // static NORM_01 = 1.0 / (1.0 << 52);
   137      // static GAUSSIAN_NORM = 1.0 / (1.0 << 20);
   138      //
   139      // next01() {
   140      //     WyF3.numberBufferView.setBigUint64(0, this.next(), true);
   141      //     let r = WyF3.numberBufferView.getFloat64(0, true);
   142      //     return (r >> 12) * WyF3Rand.NORM_01;
   143      // }
   144      //
   145      // nextGaussian() {
   146      //     WyF3.numberBufferView.setBigUint64(0, this.next(), true);
   147      //     let r = WyF3.numberBufferView.getBigUint64(0, true);
   148      //     WyF3.numberBufferView.setBigUint64(0, (r & 0x1fffffn) + ((r >> 21n) & 0x1fffffn) + ((r >> 42n) & 0x1fffffn), true);
   149      //     return WyF3.numberBufferView.getFloat64(0, true) * WyF3Rand.GAUSSIAN_NORM
   150      //     // return ((r & 0x1fffff) + ((r >> 21) & 0x1fffff) + ((r >> 42) & 0x1fffff)) * WyF3Rand.GAUSSIAN_NORM - 3.0;
   151      // }
   152  }