1 | /**
|
2 | * Fast Pseudo Random Number Generators.
|
3 | *
|
4 | * Given a seed a PRNG generates a sequence of numbers that cannot be reasonably predicted.
|
5 | * Two PRNGs must generate the same random sequence of numbers if given the same seed.
|
6 | *
|
7 | * @module prng
|
8 | */
|
9 |
|
10 | import * as binary from './binary.js'
|
11 | import { fromCharCode, fromCodePoint } from './string.js'
|
12 | import * as math from './math.js'
|
13 | import { Xoroshiro128plus } from './prng/Xoroshiro128plus.js'
|
14 | import * as buffer from './buffer.js'
|
15 |
|
16 | /**
|
17 | * Description of the function
|
18 | * @callback generatorNext
|
19 | * @return {number} A random float in the cange of [0,1)
|
20 | */
|
21 |
|
22 | /**
|
23 | * A random type generator.
|
24 | *
|
25 | * @typedef {Object} PRNG
|
26 | * @property {generatorNext} next Generate new number
|
27 | */
|
28 |
|
29 | export const DefaultPRNG = Xoroshiro128plus
|
30 |
|
31 | /**
|
32 | * Create a Xoroshiro128plus Pseudo-Random-Number-Generator.
|
33 | * This is the fastest full-period generator passing BigCrush without systematic failures.
|
34 | * But there are more PRNGs available in ./PRNG/.
|
35 | *
|
36 | * @param {number} seed A positive 32bit integer. Do not use negative numbers.
|
37 | * @return {PRNG}
|
38 | */
|
39 | export const create = seed => new DefaultPRNG(seed)
|
40 |
|
41 | /**
|
42 | * Generates a single random bool.
|
43 | *
|
44 | * @param {PRNG} gen A random number generator.
|
45 | * @return {Boolean} A random boolean
|
46 | */
|
47 | export const bool = gen => (gen.next() >= 0.5)
|
48 |
|
49 | /**
|
50 | * Generates a random integer with 53 bit resolution.
|
51 | *
|
52 | * @param {PRNG} gen A random number generator.
|
53 | * @param {Number} min The lower bound of the allowed return values (inclusive).
|
54 | * @param {Number} max The upper bound of the allowed return values (inclusive).
|
55 | * @return {Number} A random integer on [min, max]
|
56 | */
|
57 | export const int53 = (gen, min, max) => math.floor(gen.next() * (max + 1 - min) + min)
|
58 |
|
59 | /**
|
60 | * Generates a random integer with 53 bit resolution.
|
61 | *
|
62 | * @param {PRNG} gen A random number generator.
|
63 | * @param {Number} min The lower bound of the allowed return values (inclusive).
|
64 | * @param {Number} max The upper bound of the allowed return values (inclusive).
|
65 | * @return {Number} A random integer on [min, max]
|
66 | */
|
67 | export const uint53 = (gen, min, max) => math.abs(int53(gen, min, max))
|
68 |
|
69 | /**
|
70 | * Generates a random integer with 32 bit resolution.
|
71 | *
|
72 | * @param {PRNG} gen A random number generator.
|
73 | * @param {Number} min The lower bound of the allowed return values (inclusive).
|
74 | * @param {Number} max The upper bound of the allowed return values (inclusive).
|
75 | * @return {Number} A random integer on [min, max]
|
76 | */
|
77 | export const int32 = (gen, min, max) => math.floor(gen.next() * (max + 1 - min) + min)
|
78 |
|
79 | /**
|
80 | * Generates a random integer with 53 bit resolution.
|
81 | *
|
82 | * @param {PRNG} gen A random number generator.
|
83 | * @param {Number} min The lower bound of the allowed return values (inclusive).
|
84 | * @param {Number} max The upper bound of the allowed return values (inclusive).
|
85 | * @return {Number} A random integer on [min, max]
|
86 | */
|
87 | export const uint32 = (gen, min, max) => int32(gen, min, max) >>> 0
|
88 |
|
89 | /**
|
90 | * @deprecated
|
91 | * Optimized version of prng.int32. It has the same precision as prng.int32, but should be preferred when
|
92 | * openaring on smaller ranges.
|
93 | *
|
94 | * @param {PRNG} gen A random number generator.
|
95 | * @param {Number} min The lower bound of the allowed return values (inclusive).
|
96 | * @param {Number} max The upper bound of the allowed return values (inclusive). The max inclusive number is `binary.BITS31-1`
|
97 | * @return {Number} A random integer on [min, max]
|
98 | */
|
99 | export const int31 = (gen, min, max) => int32(gen, min, max)
|
100 |
|
101 | /**
|
102 | * Generates a random real on [0, 1) with 53 bit resolution.
|
103 | *
|
104 | * @param {PRNG} gen A random number generator.
|
105 | * @return {Number} A random real number on [0, 1).
|
106 | */
|
107 | export const real53 = gen => gen.next() // (((gen.next() >>> 5) * binary.BIT26) + (gen.next() >>> 6)) / MAX_SAFE_INTEGER
|
108 |
|
109 | /**
|
110 | * Generates a random character from char code 32 - 126. I.e. Characters, Numbers, special characters, and Space:
|
111 | *
|
112 | * @param {PRNG} gen A random number generator.
|
113 | * @return {string}
|
114 | *
|
115 | * (Space)!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[/]^_`abcdefghijklmnopqrstuvwxyz{|}~
|
116 | */
|
117 | export const char = gen => fromCharCode(int31(gen, 32, 126))
|
118 |
|
119 | /**
|
120 | * @param {PRNG} gen
|
121 | * @return {string} A single letter (a-z)
|
122 | */
|
123 | export const letter = gen => fromCharCode(int31(gen, 97, 122))
|
124 |
|
125 | /**
|
126 | * @param {PRNG} gen
|
127 | * @param {number} [minLen=0]
|
128 | * @param {number} [maxLen=20]
|
129 | * @return {string} A random word (0-20 characters) without spaces consisting of letters (a-z)
|
130 | */
|
131 | export const word = (gen, minLen = 0, maxLen = 20) => {
|
132 | const len = int31(gen, minLen, maxLen)
|
133 | let str = ''
|
134 | for (let i = 0; i < len; i++) {
|
135 | str += letter(gen)
|
136 | }
|
137 | return str
|
138 | }
|
139 |
|
140 | /**
|
141 | * TODO: this function produces invalid runes. Does not cover all of utf16!!
|
142 | *
|
143 | * @param {PRNG} gen
|
144 | * @return {string}
|
145 | */
|
146 | export const utf16Rune = gen => {
|
147 | const codepoint = int31(gen, 0, 256)
|
148 | return fromCodePoint(codepoint)
|
149 | }
|
150 |
|
151 | /**
|
152 | * @param {PRNG} gen
|
153 | * @param {number} [maxlen = 20]
|
154 | */
|
155 | export const utf16String = (gen, maxlen = 20) => {
|
156 | const len = int31(gen, 0, maxlen)
|
157 | let str = ''
|
158 | for (let i = 0; i < len; i++) {
|
159 | str += utf16Rune(gen)
|
160 | }
|
161 | return str
|
162 | }
|
163 |
|
164 | /**
|
165 | * Returns one element of a given array.
|
166 | *
|
167 | * @param {PRNG} gen A random number generator.
|
168 | * @param {Array<T>} array Non empty Array of possible values.
|
169 | * @return {T} One of the values of the supplied Array.
|
170 | * @template T
|
171 | */
|
172 | export const oneOf = (gen, array) => array[int31(gen, 0, array.length - 1)]
|
173 |
|
174 | /**
|
175 | * @param {PRNG} gen
|
176 | * @param {number} len
|
177 | * @return {Uint8Array}
|
178 | */
|
179 | export const uint8Array = (gen, len) => {
|
180 | const buf = buffer.createUint8ArrayFromLen(len)
|
181 | for (let i = 0; i < buf.length; i++) {
|
182 | buf[i] = int32(gen, 0, binary.BITS8)
|
183 | }
|
184 | return buf
|
185 | }
|
186 |
|
187 | /**
|
188 | * @param {PRNG} gen
|
189 | * @param {number} len
|
190 | * @return {Uint16Array}
|
191 | */
|
192 | export const uint16Array = (gen, len) => new Uint16Array(uint8Array(gen, len * 2).buffer)
|
193 |
|
194 | /**
|
195 | * @param {PRNG} gen
|
196 | * @param {number} len
|
197 | * @return {Uint32Array}
|
198 | */
|
199 | export const uint32Array = (gen, len) => new Uint32Array(uint8Array(gen, len * 4).buffer)
|