toosoon-prng 1.4.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # TOOSOON Pseudo-Random Number Generator (PRNG)
2
2
 
3
- This project provides a `PRNG` instance and a set of `Controllers` for generating pseudo-random values using a seed-based approach and various algorithms. These controllers are particularly useful for applications requiring deterministic randomization, such as procedural generation or simulations.
3
+ This project provides PRNG functions for generating pseudo-random values using a seed-based approach and various algorithms. These are particularly useful for applications requiring deterministic randomization, such as procedural generation or simulations.
4
4
 
5
5
  ## Installation
6
6
 
@@ -18,8 +18,6 @@ $ npm install toosoon-prng
18
18
 
19
19
  ## Usage
20
20
 
21
- ##### PRNG
22
-
23
21
  ```ts
24
22
  import prng from 'toosoon-prng';
25
23
 
@@ -27,34 +25,14 @@ prng.setSeed('seed');
27
25
  console.log(prng.randomFloat('angle', 0, Math.PI)); // Pseudo-random number in the interval [0, PI]
28
26
  ```
29
27
 
30
- ##### PRNG Controllers
31
-
32
- ```ts
33
- import { IntController, IntGroupController } from 'toosoon-prng';
34
-
35
- const config = {
36
- count: new IntController('count', 0, Math.PI),
37
- counts: new IntGroupController('counts', 0, Math.PI)
38
- };
39
-
40
- config.count.addGUI(gui, 0, 10);
41
- config.counts.addGUI(gui, 5, 10);
42
-
43
- console.log(config.count.getValue()); // Pseudo-random integer in the interval [0, 10]
44
-
45
- for (let i = 0; i < 5; i++) {
46
- console.log(config.counts.getValueAt(i)); // Pseudo-random integers in the interval [5, 10]
47
- }
48
- ```
49
-
50
28
  ## PRNG Functions
51
29
 
52
- All PRNG functions have a `seed` argument wich allows you to add a sub-seed string to the `PRNG` instance global `seed` in order to get different pseudo-random outputs while using a PRNG function multiple times.
30
+ All PRNG functions have a `seed` parameter wich allows you to add a sub-seed string to the `PRNG` instance global `seed` in order to get different pseudo-random values while using a PRNG function multiple times.
53
31
 
54
32
  ```ts
55
33
  prng.setSeed('global-seed');
56
- console.log(prng.randomBoolean('1')); // Could be true or false
57
- console.log(prng.randomBoolean('2')); // Could be different from the first pseudo-random value
34
+ console.log(prng.randomBoolean('one')); // Could be true or false
35
+ console.log(prng.randomBoolean('two')); // Could be different from the first pseudo-random value
58
36
  ```
59
37
 
60
38
  ##### setSeed(seed)
@@ -67,14 +45,14 @@ Set the `PRNG` instance seed.
67
45
  prng.setSeed(seed: string): void;
68
46
  ```
69
47
 
70
- ##### setAlgorithm(algorithm)
48
+ ##### setAlgorithm(algorithmName)
71
49
 
72
50
  Set the `PRNG` algorithm for generating pseudo-random values.
73
51
 
74
- - `algorithm`: Algorithm name.
52
+ - `algorithmName`: Algorithm name.
75
53
 
76
54
  ```ts
77
- prng.setAlgorithm(algorithm: Algorithm): void;
55
+ prng.setAlgorithm(algorithmName: AlgorithmName): void;
78
56
  ```
79
57
 
80
58
  ##### random(seed)
@@ -163,7 +141,7 @@ Pick a pseudo-random property value from a given object.
163
141
  - `object`: Object to pick the property from.
164
142
 
165
143
  ```ts
166
- prng.randomObjectProperty<T>(seed: string, object: object): T | undefined;
144
+ prng.randomObjectProperty<T>(seed: string, object: Record<string, T>): T | undefined;
167
145
  ```
168
146
 
169
147
  ##### randomIndex(seed, weights)
@@ -177,138 +155,6 @@ Select a pseudo-random index from an array of weighted items.
177
155
  prng.randomIndex(seed: string, weights: number[]): number;
178
156
  ```
179
157
 
180
- ## Controllers
181
-
182
- ### BooleanController
183
-
184
- Generate pseudo-random boolean values.
185
-
186
- ```ts
187
- class BooleanController(seed: string, probability?: number);
188
- ```
189
-
190
- ### SignController
191
-
192
- Generate pseudo-random sign values (-1 or 1).
193
-
194
- ```ts
195
- class SignController(seed: string, probability?: number);
196
- ```
197
-
198
- ### FloatController
199
-
200
- Generate pseudo-random floating-point numbers within a specified range.
201
-
202
- ```ts
203
- class FloatController(seed: string, min?: number, max?: number);
204
- ```
205
-
206
- ### IntController
207
-
208
- ```ts
209
- class IntController(seed: string, min: number, max: number);
210
- ```
211
-
212
- ### HexColorController
213
-
214
- Generates pseudo-random hexadecimal color.
215
-
216
- ```ts
217
- class HexColorController(seed: string);
218
- ```
219
-
220
- ### ItemController
221
-
222
- Pick a pseudo-random item from a given array.
223
-
224
- ```ts
225
- class ItemController<T>(seed: string, items: T[]);
226
- ```
227
-
228
- ### ObjectPropertyController
229
-
230
- Pick a pseudo-random property value from a given object.
231
-
232
- ```ts
233
- class ObjectPropertyController<T>(seed: string, object: object);
234
- ```
235
-
236
- ### WeightsController
237
-
238
- Select a pseudo-random index from an array of weighted items.
239
-
240
- ```ts
241
- class WeightsController<T>(seed: string, items: Array<{ weight: number; value: T }>);
242
- ```
243
-
244
- ## Group Controllers
245
-
246
- Group Controllers manage multiple instances of individual controllers.
247
-
248
- ### BooleanGroupController
249
-
250
- Manage multiple [`BooleanController`](###booleancontroller).
251
-
252
- ```ts
253
- class BooleanGroupController(seed: string, probability: number);
254
- ```
255
-
256
- ### SignGroupController
257
-
258
- Manage multiple [`SignController`](###signcontroller).
259
-
260
- ```ts
261
- class SignGroupController(seed: string, probability: number);
262
- ```
263
-
264
- ### FloatGroupController
265
-
266
- Manage multiple [`FloatController`](###floatcontroller).
267
-
268
- ```ts
269
- class FloatGroupController(seed: string, min: number, max: number);
270
- ```
271
-
272
- ### IntGroupController
273
-
274
- Manage multiple [`IntController`](#intcontroller).
275
-
276
- ```ts
277
- class IntGroupController(seed: string, min: number, max: number);
278
- ```
279
-
280
- ### HexColorGroupController
281
-
282
- Manage multiple [`HexColorController`](#hexcolorcontroller).
283
-
284
- ```ts
285
- class HexColorGroupController(seed: string);
286
- ```
287
-
288
- ### ItemGroupController
289
-
290
- Manage multiple [`ItemController`](#itemcontroller).
291
-
292
- ```ts
293
- class ItemGroupController<T>(seed: string, items: T[]);
294
- ```
295
-
296
- ### ObjectPropertyGroupController
297
-
298
- Manage multiple [`ObjectPropertyController`](#objectpropertycontroller).
299
-
300
- ```ts
301
- class ObjectPropertyGroupController<T>(seed: string, object: object);
302
- ```
303
-
304
- ### WeightsGroupController
305
-
306
- Manage multiple [`WeightsController`](#weightscontroller).
307
-
308
- ```ts
309
- class WeightsGroupController<T>(seed: string, items: Array<{ weight: number; value: T }>);
310
- ```
311
-
312
158
  ## Algorithms
313
159
 
314
160
  By default, the library is using _SplitMix32_ algorithm for generating the pseudo-random values but it is possible to change the algorithm used by one of the following:
@@ -322,10 +168,10 @@ By default, the library is using _SplitMix32_ algorithm for generating the pseud
322
168
  ```ts
323
169
  import prng, { Algorithm } from 'toosoon-prng';
324
170
 
325
- // Set 'Simple Fast Counter' as PRNG instance algorithm
171
+ // Set 'Simple Fast Counter' as the PRNG instance algorithm
326
172
  prng.setAlgorithm(Algorithm.sfc32);
327
173
  ```
328
174
 
329
175
  ## License
330
176
 
331
- MIT License, see [LICENSE](https://github.com/toosoon-dev/toosoon-prng/tree/master/LICENSE) for details
177
+ MIT License, see [LICENSE](https://github.com/toosoon-dev/toosoon-prng/tree/master/LICENSE) for details.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "toosoon-prng",
3
- "version": "1.4.0",
4
- "description": "This project provides a `PRNG` instance and a set of `Controllers` for generating pseudo-random values using a seed-based approach and various algorithms",
3
+ "version": "2.0.0",
4
+ "description": "This project provides PRNG functions for generating pseudo-random values using a seed-based approach and various algorithms",
5
5
  "main": "./lib/index.js",
6
6
  "types": "./lib/index.d.ts",
7
7
  "scripts": {
@@ -27,10 +27,6 @@
27
27
  "url": "https://github.com/toosoon-dev/toosoon-prng/issues"
28
28
  },
29
29
  "homepage": "https://github.com/toosoon-dev/toosoon-prng#readme",
30
- "dependencies": {
31
- "toosoon-gui": "^1.3.0",
32
- "toosoon-utils": "^1.3.0"
33
- },
34
30
  "devDependencies": {
35
31
  "typescript": "^5.3.3"
36
32
  }
package/src/index.ts CHANGED
@@ -1,22 +1,3 @@
1
- export {
2
- BooleanController,
3
- SignController,
4
- IntController,
5
- FloatController,
6
- HexColorController,
7
- ItemController,
8
- ObjectPropertyController,
9
- WeightsController,
10
- BooleanGroupController,
11
- SignGroupController,
12
- IntGroupController,
13
- FloatGroupController,
14
- HexColorGroupController,
15
- ItemGroupController,
16
- ObjectPropertyGroupController,
17
- WeightsGroupController
18
- } from './controllers';
19
-
20
- export { default } from './prng';
1
+ export { default, PRNG } from './prng';
21
2
 
22
3
  export type * from './types';
package/src/prng.ts CHANGED
@@ -1,36 +1,15 @@
1
- import { cyrb128, jsf32, mulberry32, sfc32, splitmix32, xoshiro128ss } from 'toosoon-utils/prng';
2
-
3
- import { PRNGController } from './controllers';
4
- import { Algorithm } from './types';
1
+ import { cyrb128, jsf32, mulberry32, sfc32, splitmix32, xoshiro128ss } from './utils';
2
+ import { AlgorithmName } from './types';
5
3
 
6
4
  /**
7
- * PRNG class
5
+ * Utility class for generating pseudo-random values
8
6
  *
9
7
  * @class PRNG
8
+ * @exports
10
9
  */
11
- class PRNG {
10
+ export class PRNG {
12
11
  public seed: string = '';
13
- public algorithm: Algorithm = Algorithm.splitmix32;
14
- public controllers: PRNGController[] = [];
15
-
16
- /**
17
- * Add a controller to this PRNG
18
- *
19
- * @param {PRNGController} controller
20
- */
21
- public addController(controller: PRNGController): void {
22
- this.controllers.push(controller);
23
- }
24
-
25
- /**
26
- * Remove a controller from this PRNG
27
- *
28
- * @param {PRNGController} controller
29
- */
30
- public removeController(controller: PRNGController): void {
31
- const index = this.controllers.indexOf(controller);
32
- this.controllers.splice(index, 1);
33
- }
12
+ public algorithm: (...args: number[]) => number = splitmix32;
34
13
 
35
14
  /**
36
15
  * Set this PRNG seed
@@ -38,19 +17,16 @@ class PRNG {
38
17
  * @param {string} seed
39
18
  */
40
19
  public setSeed(seed: string): void {
41
- if (this.seed === seed) return;
42
20
  this.seed = seed;
43
- this.controllers.forEach((controller) => controller.getValue());
44
21
  }
45
22
 
46
23
  /**
47
- * Set this PRNG algorithm for generating pseudo-random values
24
+ * Set this PRNG algorithm
48
25
  *
49
- * @param {Algorithm} algorithm Algorithm name
26
+ * @param {AlgorithmName} algorithmName Algorithm name
50
27
  */
51
- public setAlgorithm(algorithm: Algorithm): void {
52
- this.algorithm = algorithm;
53
- this.controllers.forEach((controller) => controller.getValue());
28
+ public setAlgorithm(algorithmName: AlgorithmName): void {
29
+ this.algorithm = this.getAlgorithmByName(algorithmName);
54
30
  }
55
31
 
56
32
  /**
@@ -62,18 +38,7 @@ class PRNG {
62
38
  */
63
39
  public random(seed: string): number {
64
40
  const hashes = cyrb128(this.seed + seed);
65
- switch (this.algorithm) {
66
- case Algorithm.splitmix32:
67
- return splitmix32(hashes[0]);
68
- case Algorithm.jsf32:
69
- return jsf32(hashes[0], hashes[1], hashes[2], hashes[3]);
70
- case Algorithm.mulberry32:
71
- return mulberry32(hashes[0]);
72
- case Algorithm.sfc32:
73
- return sfc32(hashes[0], hashes[1], hashes[2], hashes[3]);
74
- case Algorithm.xoshiro128ss:
75
- return xoshiro128ss(hashes[0], hashes[1], hashes[2], hashes[3]);
76
- }
41
+ return this.algorithm(...hashes);
77
42
  }
78
43
 
79
44
  /**
@@ -152,7 +117,7 @@ class PRNG {
152
117
  * @param {object} object Object to pick the property from
153
118
  * @returns {T|undefined} Random item picked
154
119
  */
155
- public randomObjectProperty<T = unknown>(seed: string, object: { [key: string]: T }): T | undefined {
120
+ public randomObjectProperty<T = unknown>(seed: string, object: Record<string, T>): T | undefined {
156
121
  const keys = Object.keys(object);
157
122
  const key = this.randomItem(seed, keys);
158
123
  if (key && object.hasOwnProperty(key)) {
@@ -177,14 +142,37 @@ class PRNG {
177
142
 
178
143
  if (totalWeight <= 0) console.warn('PRNG.randomIndex()', 'Weights must sum to > 0', totalWeight);
179
144
 
180
- let random = this.random(seed) * totalWeight;
145
+ let weight = this.random(seed) * totalWeight;
181
146
  for (let i = 0; i < weights.length; i++) {
182
- if (random < weights[i]) return i;
183
- random -= weights[i];
147
+ if (weight < weights[i]) return i;
148
+ weight -= weights[i];
184
149
  }
185
150
 
186
151
  return 0;
187
152
  }
153
+
154
+ /**
155
+ * Get the PRNG algorithm function by its name
156
+ *
157
+ * @param {AlgorithmName} algorithmName Algorithm name
158
+ * @returns {Function} PRNG algorithm function
159
+ */
160
+ protected getAlgorithmByName(algorithmName: AlgorithmName): (...args: number[]) => number {
161
+ switch (algorithmName) {
162
+ case AlgorithmName.jsf32:
163
+ return jsf32;
164
+ case AlgorithmName.mulberry32:
165
+ return mulberry32;
166
+ case AlgorithmName.sfc32:
167
+ return sfc32;
168
+ case AlgorithmName.splitmix32:
169
+ return splitmix32;
170
+ case AlgorithmName.xoshiro128ss:
171
+ return xoshiro128ss;
172
+ default:
173
+ return splitmix32;
174
+ }
175
+ }
188
176
  }
189
177
 
190
178
  const prng = new PRNG();
package/src/types.ts CHANGED
@@ -1,6 +1,4 @@
1
- export type { PRNGController, PRNGGroupController } from './controllers';
2
-
3
- export enum Algorithm {
1
+ export enum AlgorithmName {
4
2
  jsf32 = 'jsf32',
5
3
  mulberry32 = 'mulberry32',
6
4
  sfc32 = 'sfc32',
package/src/utils.ts ADDED
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Produce a 128-bit hash value from a seed
3
+ *
4
+ * @param {string} seed Initial seed state
5
+ * @returns {[number, number, number, number]} Hash numbers
6
+ */
7
+ export function cyrb128(seed: string): [number, number, number, number] {
8
+ let h1 = 1779033703;
9
+ let h2 = 3144134277;
10
+ let h3 = 1013904242;
11
+ let h4 = 2773480762;
12
+ for (let i = 0, k; i < seed.length; i++) {
13
+ k = seed.charCodeAt(i);
14
+ h1 = h2 ^ Math.imul(h1 ^ k, 597399067);
15
+ h2 = h3 ^ Math.imul(h2 ^ k, 2869860233);
16
+ h3 = h4 ^ Math.imul(h3 ^ k, 951274213);
17
+ h4 = h1 ^ Math.imul(h4 ^ k, 2716044179);
18
+ }
19
+ h1 = Math.imul(h3 ^ (h1 >>> 18), 597399067);
20
+ h2 = Math.imul(h4 ^ (h2 >>> 22), 2869860233);
21
+ h3 = Math.imul(h1 ^ (h3 >>> 17), 951274213);
22
+ h4 = Math.imul(h2 ^ (h4 >>> 19), 2716044179);
23
+ return [(h1 ^ h2 ^ h3 ^ h4) >>> 0, (h2 ^ h1) >>> 0, (h3 ^ h1) >>> 0, (h4 ^ h1) >>> 0];
24
+ }
25
+
26
+ // *********************
27
+ // PRNG Algorithms
28
+ // *********************
29
+
30
+ /**
31
+ * Simple Fast Counter, Generator with a 128-bit state
32
+ *
33
+ * @param {number} a
34
+ * @param {number} b
35
+ * @param {number} c
36
+ * @param {number} d
37
+ * @returns {number} Pseudo-random number
38
+ */
39
+ export function sfc32(a: number, b: number, c: number, d: number): number {
40
+ a >>>= 0;
41
+ b >>>= 0;
42
+ c >>>= 0;
43
+ d >>>= 0;
44
+ let t = (a + b) | 0;
45
+ a = b ^ (b >>> 9);
46
+ b = (c + (c << 3)) | 0;
47
+ c = (c << 21) | (c >>> 11);
48
+ d = (d + 1) | 0;
49
+ t = (t + d) | 0;
50
+ c = (c + t) | 0;
51
+ return (t >>> 0) / 4294967296;
52
+ }
53
+
54
+ /**
55
+ * SplitMix32, Generator with a 32-bit state
56
+ *
57
+ * @param {number} a
58
+ * @returns {number} Pseudo-random number
59
+ */
60
+ export function splitmix32(a: number): number {
61
+ a |= 0;
62
+ a = (a + 0x9e3779b9) | 0;
63
+ var t = a ^ (a >>> 16);
64
+ t = Math.imul(t, 0x21f0aaad);
65
+ t = t ^ (t >>> 15);
66
+ t = Math.imul(t, 0x735a2d97);
67
+ return ((t = t ^ (t >>> 15)) >>> 0) / 4294967296;
68
+ }
69
+
70
+ /**
71
+ * Mulberry32, Generator with a 32-bit state
72
+ *
73
+ * @param {number} a
74
+ * @returns {number} Pseudo-random number
75
+ */
76
+ export function mulberry32(a: number): number {
77
+ let t = (a += 0x6d2b79f5);
78
+ t = Math.imul(t ^ (t >>> 15), t | 1);
79
+ t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
80
+ return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
81
+ }
82
+
83
+ /**
84
+ * Jenkins' Small Fast, Generator with a 32-bit state
85
+ *
86
+ * @param {number} a
87
+ * @returns {number} Pseudo-random number
88
+ */
89
+ export function jsf32(a: number, b: number, c: number, d: number): number {
90
+ a |= 0;
91
+ b |= 0;
92
+ c |= 0;
93
+ d |= 0;
94
+ let t = (a - ((b << 27) | (b >>> 5))) | 0;
95
+ a = b ^ ((c << 17) | (c >>> 15));
96
+ b = (c + d) | 0;
97
+ c = (d + t) | 0;
98
+ d = (a + t) | 0;
99
+ return (d >>> 0) / 4294967296;
100
+ }
101
+
102
+ /**
103
+ * xoshiro128**, Generator with a 128-bit state
104
+ *
105
+ * @param {number} a
106
+ * @returns {number} Pseudo-random number
107
+ */
108
+ export function xoshiro128ss(a: number, b: number, c: number, d: number): number {
109
+ let t = b << 9;
110
+ let r = a * 5;
111
+ r = ((r << 7) | (r >>> 25)) * 9;
112
+ c ^= a;
113
+ d ^= b;
114
+ b ^= c;
115
+ a ^= d;
116
+ c ^= t;
117
+ d = (d << 11) | (d >>> 21);
118
+ return (r >>> 0) / 4294967296;
119
+ }
package/.prettierrc DELETED
@@ -1,7 +0,0 @@
1
- {
2
- "semi": true,
3
- "singleQuote": true,
4
- "printWidth": 120,
5
- "trailingComma": "none",
6
- "endOfLine": "auto"
7
- }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2024 TOOSOON
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.