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