k98kurz

XORShiftPlus.js

Sep 7th, 2020 (edited)
2,093
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /**
  2.  *  XORShiftPlus "non-linear" PRNG
  3.  *  Author: k98kurz (@gmail)
  4.  *  License: MIT
  5.  *  Date: 2020-09-07
  6.  *  Description: Based upon the xorshift128+ generator, one of the fastest generators passing BigCrush.
  7.  *  Methods:
  8.  *      next(n)         returns Uint32Array of n random numbers
  9.  *      nextHex(n)      returns Array of n hexidecimal numbers
  10.  *      bytes(n)        returns Uint8Array of n random bytes
  11.  *      bytesHex(n)     returns Array of n random bytes in hexidecimal
  12.  *      hex(n)          returns hexidecimal string of n bytes
  13.  *  Note: This generates with higher periodicity and better random distribution than the linear XORShift.
  14.  */
  15. class XORShiftPlus {
  16.   #booted = false;
  17.   #x;
  18.   #y;
  19.   #z;
  20.   #w;
  21.  
  22.   constructor (seed) {
  23.     this.#x = new Uint32Array(1);
  24.     this.#y = new Uint32Array(1);
  25.     this.#z = new Uint32Array(1);
  26.     this.#w = new Uint32Array(1);
  27.     this.#x[0] = seed ? seed|0 : 317973455;
  28.     this.#y[0] = this.#x[0]<<362436069;
  29.     this.#z[0] = this.#y[0]+this.#x[0];
  30.     this.#w[0] = this.#z[0]^this.#x[0]+this.#y[0];
  31.   }
  32.  
  33.   #next () {
  34.     let t = new Uint32Array(1);
  35.     t[0] = this.#x[0]^(this.#x[0]<<11);
  36.     this.#x[0] = this.#y[0];
  37.     this.#y[0] = this.#z[0];
  38.     this.#z[0] = this.#w[0];
  39.     this.#w[0] = this.#w[0]^(this.#w[0]>>19)^(t[0]^(t[0]>>8));
  40.     return this.#w[0]+this.#y[0];
  41.   }
  42.  
  43.   #boot () {
  44.     // if not booted, discard the first numbers as they are somewhat predictable
  45.     if (this.#booted)
  46.       return;
  47.     for (let i=0, n=this.#next(), j=this.#next()%256; i<=j; this.#next(), ++i);
  48.     this.#booted = true;
  49.   }
  50.  
  51.   next (n, option) {
  52.     this.#boot();
  53.     n = (n === undefined || typeof n !== 'number') ? 1 : n;
  54.     let t; n |= 0; n = n>0 ? n : 1;
  55.     option = (option === undefined || typeof n !== 'number') ? 0 : option;
  56.  
  57.     // redundant code, but improved performance
  58.     switch (option) {
  59.       // nextHex
  60.       case 1:
  61.         t = [];
  62.         for (let i=0, il=n; i<il; t[i++] = this.#next().toString(16));
  63.         break;
  64.       // bytes
  65.       case 2:
  66.         t = new Uint8Array(n);
  67.         for (let i=0, il=n; i<il; t[i++] = this.#next());
  68.         break;
  69.       // bytesHex
  70.       case 3:
  71.         t = [];
  72.         for (let i=0, il=n; i<il; t[i] = (this.#next()%256).toString(16), t[i] = t[i].length%2 ? '0'+t[i] : t[i], ++i);
  73.         break;
  74.       // hex
  75.       case 4:
  76.         t = [];
  77.         for (let i=0, il=n; i<il; t[i] = (this.#next()%256).toString(16), t[i] = t[i].length%2 ? '0'+t[i] : t[i], ++i);
  78.         t = t.join('');
  79.         break;
  80.       // next
  81.       default:
  82.         t = new Uint32Array(n);
  83.         for (let i=0, il=n; i<il; t[i++] = this.#next());
  84.     }
  85.     return t;
  86.   };
  87.  
  88.   nextHex (n) { return this.next(n, 1); };
  89.  
  90.   bytes (n) { return this.next(n, 2); };
  91.  
  92.   bytesHex (n) { return this.next(n, 3); };
  93.  
  94.   hex (n) { return this.next(n, 4); };
  95. }
Add Comment
Please, Sign In to add comment