/** * XORShiftPlus "non-linear" PRNG * Author: k98kurz (@gmail) * License: MIT * Date: 2020-09-07 * Description: Based upon the xorshift128+ generator, one of the fastest generators passing BigCrush. * Methods: * next(n) returns Uint32Array of n random numbers * nextHex(n) returns Array of n hexidecimal numbers * bytes(n) returns Uint8Array of n random bytes * bytesHex(n) returns Array of n random bytes in hexidecimal * hex(n) returns hexidecimal string of n bytes * Note: This generates with higher periodicity and better random distribution than the linear XORShift. */ class XORShiftPlus { #booted = false; #x; #y; #z; #w; constructor (seed) { this.#x = new Uint32Array(1); this.#y = new Uint32Array(1); this.#z = new Uint32Array(1); this.#w = new Uint32Array(1); this.#x[0] = seed ? seed|0 : 317973455; this.#y[0] = this.#x[0]<<362436069; this.#z[0] = this.#y[0]+this.#x[0]; this.#w[0] = this.#z[0]^this.#x[0]+this.#y[0]; } #next () { let t = new Uint32Array(1); t[0] = this.#x[0]^(this.#x[0]<<11); this.#x[0] = this.#y[0]; this.#y[0] = this.#z[0]; this.#z[0] = this.#w[0]; this.#w[0] = this.#w[0]^(this.#w[0]>>19)^(t[0]^(t[0]>>8)); return this.#w[0]+this.#y[0]; } #boot () { // if not booted, discard the first numbers as they are somewhat predictable if (this.#booted) return; for (let i=0, n=this.#next(), j=this.#next()%256; i<=j; this.#next(), ++i); this.#booted = true; } next (n, option) { this.#boot(); n = (n === undefined || typeof n !== 'number') ? 1 : n; let t; n |= 0; n = n>0 ? n : 1; option = (option === undefined || typeof n !== 'number') ? 0 : option; // redundant code, but improved performance switch (option) { // nextHex case 1: t = []; for (let i=0, il=n; i