@thi.ng/random 3.6.16 → 3.6.18
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/CHANGELOG.md +1 -1
- package/api.js +0 -1
- package/arandom.js +30 -27
- package/coin.js +12 -28
- package/constants.js +12 -4
- package/crypto.js +30 -39
- package/distributions/exponential.js +4 -11
- package/distributions/gaussian.js +9 -22
- package/distributions/geometric.js +4 -19
- package/distributions/normal.js +20 -29
- package/distributions/uniform.js +4 -12
- package/package.json +10 -8
- package/pick-random.js +6 -18
- package/random-bytes.js +10 -26
- package/random-id.js +9 -29
- package/sfc32.js +29 -33
- package/smush32.js +25 -29
- package/system.js +15 -19
- package/unique-indices.js +23 -63
- package/uuid.js +11 -23
- package/weighted-random.js +28 -50
- package/xorshift128.js +31 -32
- package/xorwow.js +34 -35
- package/xoshiro128.js +34 -37
- package/xsadd.js +39 -40
package/CHANGELOG.md
CHANGED
package/api.js
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/arandom.js
CHANGED
|
@@ -1,29 +1,32 @@
|
|
|
1
1
|
const INV_MAX = 1 / 2 ** 32;
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
2
|
+
class ARandom {
|
|
3
|
+
float(norm = 1) {
|
|
4
|
+
return this.int() * INV_MAX * norm;
|
|
5
|
+
}
|
|
6
|
+
probability(p) {
|
|
7
|
+
return this.float() < p;
|
|
8
|
+
}
|
|
9
|
+
norm(norm = 1) {
|
|
10
|
+
return (this.int() * INV_MAX - 0.5) * 2 * norm;
|
|
11
|
+
}
|
|
12
|
+
normMinMax(min, max) {
|
|
13
|
+
const x = this.minmax(min, max);
|
|
14
|
+
return this.float() < 0.5 ? x : -x;
|
|
15
|
+
}
|
|
16
|
+
minmax(min, max) {
|
|
17
|
+
return this.float() * (max - min) + min;
|
|
18
|
+
}
|
|
19
|
+
minmaxInt(min, max) {
|
|
20
|
+
min |= 0;
|
|
21
|
+
const range = (max | 0) - min;
|
|
22
|
+
return range ? min + this.int() % range : min;
|
|
23
|
+
}
|
|
24
|
+
minmaxUint(min, max) {
|
|
25
|
+
min >>>= 0;
|
|
26
|
+
const range = (max >>> 0) - min;
|
|
27
|
+
return range ? min + this.int() % range : min;
|
|
28
|
+
}
|
|
29
29
|
}
|
|
30
|
+
export {
|
|
31
|
+
ARandom
|
|
32
|
+
};
|
package/coin.js
CHANGED
|
@@ -1,30 +1,14 @@
|
|
|
1
1
|
import { SYSTEM } from "./system.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
export
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
* manner as long as both results are equal (and discarding results). Otherwise
|
|
15
|
-
* returns result of first call.
|
|
16
|
-
*
|
|
17
|
-
* @remarks
|
|
18
|
-
* Reference:
|
|
19
|
-
* https://en.m.wikipedia.org/wiki/Fair_coin#Fair_results_from_a_biased_coin
|
|
20
|
-
*
|
|
21
|
-
* @param rnd -
|
|
22
|
-
*/
|
|
23
|
-
export const fairCoin = (rnd = SYSTEM) => {
|
|
24
|
-
let a, b;
|
|
25
|
-
do {
|
|
26
|
-
a = coin(rnd);
|
|
27
|
-
b = coin(rnd);
|
|
28
|
-
} while (a === b);
|
|
29
|
-
return a;
|
|
2
|
+
const coin = (rnd = SYSTEM) => rnd.float() < 0.5;
|
|
3
|
+
const fairCoin = (rnd = SYSTEM) => {
|
|
4
|
+
let a, b;
|
|
5
|
+
do {
|
|
6
|
+
a = coin(rnd);
|
|
7
|
+
b = coin(rnd);
|
|
8
|
+
} while (a === b);
|
|
9
|
+
return a;
|
|
10
|
+
};
|
|
11
|
+
export {
|
|
12
|
+
coin,
|
|
13
|
+
fairCoin
|
|
30
14
|
};
|
package/constants.js
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
const DEFAULT_SEED_32 = 3737844653;
|
|
2
|
+
const DEFAULT_SEED_128 = [
|
|
3
|
+
3737844653,
|
|
4
|
+
799659867,
|
|
5
|
+
3827263459,
|
|
6
|
+
1552149530
|
|
4
7
|
];
|
|
5
|
-
|
|
8
|
+
const DEFAULT_SEED_160 = [...DEFAULT_SEED_128, 4137311345];
|
|
9
|
+
export {
|
|
10
|
+
DEFAULT_SEED_128,
|
|
11
|
+
DEFAULT_SEED_160,
|
|
12
|
+
DEFAULT_SEED_32
|
|
13
|
+
};
|
package/crypto.js
CHANGED
|
@@ -1,43 +1,34 @@
|
|
|
1
1
|
import { ARandom } from "./arandom.js";
|
|
2
2
|
import { randomBytes } from "./random-bytes.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
copy() {
|
|
27
|
-
return new Crypto(this.buffer.length);
|
|
28
|
-
}
|
|
29
|
-
bytes() {
|
|
30
|
-
return new Uint8Array(this.buffer.buffer);
|
|
31
|
-
}
|
|
32
|
-
int() {
|
|
33
|
-
if (this.i >= this.u32.length) {
|
|
34
|
-
randomBytes(this.buffer);
|
|
35
|
-
this.i = 0;
|
|
36
|
-
}
|
|
37
|
-
return this.u32[this.i++];
|
|
3
|
+
class Crypto extends ARandom {
|
|
4
|
+
buffer;
|
|
5
|
+
u32;
|
|
6
|
+
i;
|
|
7
|
+
/**
|
|
8
|
+
* @param size - buffer size in bytes (will be rounded to next multiple of 4)
|
|
9
|
+
*/
|
|
10
|
+
constructor(size = 1024) {
|
|
11
|
+
super();
|
|
12
|
+
this.buffer = new Uint8Array(size + 3 & ~3);
|
|
13
|
+
this.u32 = new Uint32Array(this.buffer.buffer);
|
|
14
|
+
this.i = size >>> 2;
|
|
15
|
+
}
|
|
16
|
+
copy() {
|
|
17
|
+
return new Crypto(this.buffer.length);
|
|
18
|
+
}
|
|
19
|
+
bytes() {
|
|
20
|
+
return new Uint8Array(this.buffer.buffer);
|
|
21
|
+
}
|
|
22
|
+
int() {
|
|
23
|
+
if (this.i >= this.u32.length) {
|
|
24
|
+
randomBytes(this.buffer);
|
|
25
|
+
this.i = 0;
|
|
38
26
|
}
|
|
27
|
+
return this.u32[this.i++];
|
|
28
|
+
}
|
|
39
29
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
30
|
+
const CRYPTO = new Crypto();
|
|
31
|
+
export {
|
|
32
|
+
CRYPTO,
|
|
33
|
+
Crypto
|
|
34
|
+
};
|
|
@@ -1,12 +1,5 @@
|
|
|
1
1
|
import { SYSTEM } from "../system.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
* @remarks
|
|
7
|
-
* https://en.wikipedia.org/wiki/Exponential_distribution
|
|
8
|
-
*
|
|
9
|
-
* @param rnd -
|
|
10
|
-
* @param lambda - event interval [0,Inf)
|
|
11
|
-
*/
|
|
12
|
-
export const exponential = (rnd = SYSTEM, lambda = 10) => lambda === 0 ? () => Infinity : () => -Math.log(1 - rnd.float(1)) / lambda;
|
|
2
|
+
const exponential = (rnd = SYSTEM, lambda = 10) => lambda === 0 ? () => Infinity : () => -Math.log(1 - rnd.float(1)) / lambda;
|
|
3
|
+
export {
|
|
4
|
+
exponential
|
|
5
|
+
};
|
|
@@ -1,24 +1,11 @@
|
|
|
1
1
|
import { SYSTEM } from "../system.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
* Reference: https://en.wikipedia.org/wiki/Central_limit_theorem
|
|
12
|
-
*
|
|
13
|
-
* @param rnd - default `SYSTEM`
|
|
14
|
-
* @param n - num samples, default 24
|
|
15
|
-
* @param offset - center offset / bias, default 0
|
|
16
|
-
* @param scale - scale, default 1
|
|
17
|
-
*/
|
|
18
|
-
export const gaussian = (rnd = SYSTEM, n = 24, offset = 0, scale = 1) => () => {
|
|
19
|
-
let sum = 0;
|
|
20
|
-
let m = n;
|
|
21
|
-
while (m-- > 0)
|
|
22
|
-
sum += rnd.norm(scale);
|
|
23
|
-
return sum / n + offset;
|
|
2
|
+
const gaussian = (rnd = SYSTEM, n = 24, offset = 0, scale = 1) => () => {
|
|
3
|
+
let sum = 0;
|
|
4
|
+
let m = n;
|
|
5
|
+
while (m-- > 0)
|
|
6
|
+
sum += rnd.norm(scale);
|
|
7
|
+
return sum / n + offset;
|
|
8
|
+
};
|
|
9
|
+
export {
|
|
10
|
+
gaussian
|
|
24
11
|
};
|
|
@@ -1,20 +1,5 @@
|
|
|
1
1
|
import { SYSTEM } from "../system.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
*
|
|
7
|
-
* @remarks
|
|
8
|
-
* Returns 0 for p <= 0 and 1 for p >= 1.
|
|
9
|
-
*
|
|
10
|
-
* Reference: https://en.wikipedia.org/wiki/Geometric_distribution
|
|
11
|
-
*
|
|
12
|
-
* @param rnd -
|
|
13
|
-
* @param p - probability (0,1]
|
|
14
|
-
*/
|
|
15
|
-
export const geometric = (rnd = SYSTEM, p = 0.5) => p <= 0
|
|
16
|
-
? () => Infinity
|
|
17
|
-
: p >= 1
|
|
18
|
-
? () => 1
|
|
19
|
-
: ((p = Math.log(1 - p)),
|
|
20
|
-
() => Math.floor(Math.log(1 - rnd.float(1)) / p) + 1);
|
|
2
|
+
const geometric = (rnd = SYSTEM, p = 0.5) => p <= 0 ? () => Infinity : p >= 1 ? () => 1 : (p = Math.log(1 - p), () => Math.floor(Math.log(1 - rnd.float(1)) / p) + 1);
|
|
3
|
+
export {
|
|
4
|
+
geometric
|
|
5
|
+
};
|
package/distributions/normal.js
CHANGED
|
@@ -1,31 +1,22 @@
|
|
|
1
1
|
import { SYSTEM } from "../system.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
return ()
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
else {
|
|
23
|
-
do {
|
|
24
|
-
a = rnd.norm();
|
|
25
|
-
b = rnd.norm();
|
|
26
|
-
r = a * a + b * b;
|
|
27
|
-
} while (r > 1 || r === 0);
|
|
28
|
-
}
|
|
29
|
-
return bias + sigma * b * Math.sqrt((-2 * Math.log(r)) / r);
|
|
30
|
-
};
|
|
2
|
+
const normal = (rnd = SYSTEM, bias = 0, sigma = 1) => {
|
|
3
|
+
let a;
|
|
4
|
+
let b;
|
|
5
|
+
let r;
|
|
6
|
+
return () => {
|
|
7
|
+
if (a != null) {
|
|
8
|
+
b = a;
|
|
9
|
+
a = null;
|
|
10
|
+
} else {
|
|
11
|
+
do {
|
|
12
|
+
a = rnd.norm();
|
|
13
|
+
b = rnd.norm();
|
|
14
|
+
r = a * a + b * b;
|
|
15
|
+
} while (r > 1 || r === 0);
|
|
16
|
+
}
|
|
17
|
+
return bias + sigma * b * Math.sqrt(-2 * Math.log(r) / r);
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
export {
|
|
21
|
+
normal
|
|
31
22
|
};
|
package/distributions/uniform.js
CHANGED
|
@@ -1,13 +1,5 @@
|
|
|
1
1
|
import { SYSTEM } from "../system.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
* @remarks
|
|
7
|
-
* This function is syntax sugar for `rnd.minmax()`.
|
|
8
|
-
*
|
|
9
|
-
* @param rnd -
|
|
10
|
-
* @param min -
|
|
11
|
-
* @param max -
|
|
12
|
-
*/
|
|
13
|
-
export const uniform = (rnd = SYSTEM, min = 0, max = 1) => () => rnd.minmax(min, max);
|
|
2
|
+
const uniform = (rnd = SYSTEM, min = 0, max = 1) => () => rnd.minmax(min, max);
|
|
3
|
+
export {
|
|
4
|
+
uniform
|
|
5
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/random",
|
|
3
|
-
"version": "3.6.
|
|
3
|
+
"version": "3.6.18",
|
|
4
4
|
"description": "Pseudo-random number generators w/ unified API, distributions, weighted choices, ID generation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./index.js",
|
|
@@ -24,7 +24,9 @@
|
|
|
24
24
|
"author": "Karsten Schmidt (https://thi.ng)",
|
|
25
25
|
"license": "Apache-2.0",
|
|
26
26
|
"scripts": {
|
|
27
|
-
"build": "yarn
|
|
27
|
+
"build": "yarn build:esbuild && yarn build:decl",
|
|
28
|
+
"build:decl": "tsc --declaration --emitDeclarationOnly",
|
|
29
|
+
"build:esbuild": "esbuild --format=esm --platform=neutral --target=es2022 --tsconfig=tsconfig.json --outdir=. src/**/*.ts",
|
|
28
30
|
"clean": "rimraf --glob '*.js' '*.d.ts' '*.map' doc distributions",
|
|
29
31
|
"doc": "typedoc --excludePrivate --excludeInternal --out doc src/index.ts",
|
|
30
32
|
"doc:ae": "mkdir -p .ae/doc .ae/temp && api-extractor run --local --verbose",
|
|
@@ -33,14 +35,14 @@
|
|
|
33
35
|
"test": "bun test"
|
|
34
36
|
},
|
|
35
37
|
"dependencies": {
|
|
36
|
-
"@thi.ng/api": "^8.9.
|
|
37
|
-
"@thi.ng/checks": "^3.4.
|
|
38
|
-
"@thi.ng/errors": "^2.4.
|
|
39
|
-
"@thi.ng/hex": "^2.3.
|
|
38
|
+
"@thi.ng/api": "^8.9.12",
|
|
39
|
+
"@thi.ng/checks": "^3.4.12",
|
|
40
|
+
"@thi.ng/errors": "^2.4.6",
|
|
41
|
+
"@thi.ng/hex": "^2.3.24"
|
|
40
42
|
},
|
|
41
43
|
"devDependencies": {
|
|
42
44
|
"@microsoft/api-extractor": "^7.38.3",
|
|
43
|
-
"
|
|
45
|
+
"esbuild": "^0.19.8",
|
|
44
46
|
"rimraf": "^5.0.5",
|
|
45
47
|
"tools": "^0.0.1",
|
|
46
48
|
"typedoc": "^0.25.4",
|
|
@@ -155,5 +157,5 @@
|
|
|
155
157
|
"ksuid"
|
|
156
158
|
]
|
|
157
159
|
},
|
|
158
|
-
"gitHead": "
|
|
160
|
+
"gitHead": "5e7bafedfc3d53bc131469a28de31dd8e5b4a3ff\n"
|
|
159
161
|
}
|
package/pick-random.js
CHANGED
|
@@ -1,19 +1,7 @@
|
|
|
1
1
|
import { SYSTEM } from "./system.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
* @param rnd -
|
|
9
|
-
* @param start -
|
|
10
|
-
* @param end -
|
|
11
|
-
*/
|
|
12
|
-
export const pickRandom = (src, rnd = SYSTEM, start = 0, end = src.length) => src[rnd.minmax(start, end) | 0];
|
|
13
|
-
/**
|
|
14
|
-
* Returns a random key from given `object`.
|
|
15
|
-
*
|
|
16
|
-
* @param obj
|
|
17
|
-
* @param rnd
|
|
18
|
-
*/
|
|
19
|
-
export const pickRandomKey = (obj, rnd = SYSTEM) => pickRandom(Object.keys(obj), rnd);
|
|
2
|
+
const pickRandom = (src, rnd = SYSTEM, start = 0, end = src.length) => src[rnd.minmax(start, end) | 0];
|
|
3
|
+
const pickRandomKey = (obj, rnd = SYSTEM) => pickRandom(Object.keys(obj), rnd);
|
|
4
|
+
export {
|
|
5
|
+
pickRandom,
|
|
6
|
+
pickRandomKey
|
|
7
|
+
};
|
package/random-bytes.js
CHANGED
|
@@ -1,29 +1,13 @@
|
|
|
1
1
|
import { hasCrypto } from "@thi.ng/checks/has-crypto";
|
|
2
2
|
import { SYSTEM } from "./system.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
for (let i = start; i < end; i++) {
|
|
14
|
-
buf[i] = rnd.int() & 0xff;
|
|
15
|
-
}
|
|
16
|
-
return buf;
|
|
3
|
+
const randomBytesFrom = (rnd, buf, start = 0, end = buf.length) => {
|
|
4
|
+
for (let i = start; i < end; i++) {
|
|
5
|
+
buf[i] = rnd.int() & 255;
|
|
6
|
+
}
|
|
7
|
+
return buf;
|
|
8
|
+
};
|
|
9
|
+
const randomBytes = hasCrypto() ? (buf, start = 0, end = buf.length) => (window.crypto.getRandomValues(buf.subarray(start, end)), buf) : (buf, start, end) => randomBytesFrom(SYSTEM, buf, start, end);
|
|
10
|
+
export {
|
|
11
|
+
randomBytes,
|
|
12
|
+
randomBytesFrom
|
|
17
13
|
};
|
|
18
|
-
/**
|
|
19
|
-
* Fills given byte array with random values. Wrapper for
|
|
20
|
-
* `crypto.getRandomValues()` with automatic fallback to using `Math.random` if
|
|
21
|
-
* platform doesn't provide global crypto instance.
|
|
22
|
-
*
|
|
23
|
-
* @param buf -
|
|
24
|
-
* @param start -
|
|
25
|
-
* @param end -
|
|
26
|
-
*/
|
|
27
|
-
export const randomBytes = hasCrypto()
|
|
28
|
-
? (buf, start = 0, end = buf.length) => (window.crypto.getRandomValues(buf.subarray(start, end)), buf)
|
|
29
|
-
: (buf, start, end) => randomBytesFrom(SYSTEM, buf, start, end);
|
package/random-id.js
CHANGED
|
@@ -1,31 +1,11 @@
|
|
|
1
1
|
import { SYSTEM } from "./system.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
* @example
|
|
12
|
-
* ```ts
|
|
13
|
-
* randomID()
|
|
14
|
-
* "qgdt"
|
|
15
|
-
*
|
|
16
|
-
* randomID(8, "id-", "0123456789ABCDEF")
|
|
17
|
-
* "id-94EF6E1A"
|
|
18
|
-
* ```
|
|
19
|
-
*
|
|
20
|
-
* @param len -
|
|
21
|
-
* @param prefix -
|
|
22
|
-
* @param syms -
|
|
23
|
-
* @param rnd -
|
|
24
|
-
*/
|
|
25
|
-
export const randomID = (len = 4, prefix = "", syms = "abcdefghijklmnopqrstuvwxyz", rnd = SYSTEM) => {
|
|
26
|
-
const n = syms.length;
|
|
27
|
-
for (; len-- > 0;) {
|
|
28
|
-
prefix += syms[rnd.int() % n];
|
|
29
|
-
}
|
|
30
|
-
return prefix;
|
|
2
|
+
const randomID = (len = 4, prefix = "", syms = "abcdefghijklmnopqrstuvwxyz", rnd = SYSTEM) => {
|
|
3
|
+
const n = syms.length;
|
|
4
|
+
for (; len-- > 0; ) {
|
|
5
|
+
prefix += syms[rnd.int() % n];
|
|
6
|
+
}
|
|
7
|
+
return prefix;
|
|
8
|
+
};
|
|
9
|
+
export {
|
|
10
|
+
randomID
|
|
31
11
|
};
|
package/sfc32.js
CHANGED
|
@@ -1,36 +1,32 @@
|
|
|
1
1
|
import { ARandom } from "./arandom.js";
|
|
2
2
|
import { DEFAULT_SEED_128 } from "./constants.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
buffer;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
s[2] = (((s[2] << 21) | (s[2] >>> 11)) + t) >>> 0;
|
|
30
|
-
return t;
|
|
31
|
-
}
|
|
32
|
-
seed(seed) {
|
|
33
|
-
this.buffer.set(seed);
|
|
34
|
-
return this;
|
|
35
|
-
}
|
|
3
|
+
class SFC32 extends ARandom {
|
|
4
|
+
buffer;
|
|
5
|
+
constructor(seed = DEFAULT_SEED_128) {
|
|
6
|
+
super();
|
|
7
|
+
this.buffer = new Uint32Array(4);
|
|
8
|
+
this.seed(seed);
|
|
9
|
+
}
|
|
10
|
+
copy() {
|
|
11
|
+
return new SFC32(this.buffer);
|
|
12
|
+
}
|
|
13
|
+
bytes() {
|
|
14
|
+
return new Uint8Array(this.buffer.buffer);
|
|
15
|
+
}
|
|
16
|
+
int() {
|
|
17
|
+
const s = this.buffer;
|
|
18
|
+
const t = (s[0] + s[1] >>> 0) + s[3] >>> 0;
|
|
19
|
+
s[3] = s[3] + 1 >>> 0;
|
|
20
|
+
s[0] = s[1] ^ s[1] >>> 9;
|
|
21
|
+
s[1] = s[2] + (s[2] << 3) >>> 0;
|
|
22
|
+
s[2] = (s[2] << 21 | s[2] >>> 11) + t >>> 0;
|
|
23
|
+
return t;
|
|
24
|
+
}
|
|
25
|
+
seed(seed) {
|
|
26
|
+
this.buffer.set(seed);
|
|
27
|
+
return this;
|
|
28
|
+
}
|
|
36
29
|
}
|
|
30
|
+
export {
|
|
31
|
+
SFC32
|
|
32
|
+
};
|
package/smush32.js
CHANGED
|
@@ -1,32 +1,28 @@
|
|
|
1
1
|
import { ARandom } from "./arandom.js";
|
|
2
2
|
import { DEFAULT_SEED_32 } from "./constants.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
buffer;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
int() {
|
|
26
|
-
const b = this.buffer;
|
|
27
|
-
const m = 0x5bd1e995;
|
|
28
|
-
const k = (b[1]++ * m) >>> 0;
|
|
29
|
-
const s = (b[0] = ((k ^ (k >> 24) ^ ((b[0] * m) >>> 0)) * m) >>> 0);
|
|
30
|
-
return (s ^ (s >>> 13)) >>> 0;
|
|
31
|
-
}
|
|
3
|
+
class Smush32 extends ARandom {
|
|
4
|
+
buffer;
|
|
5
|
+
constructor(seed = DEFAULT_SEED_32) {
|
|
6
|
+
super();
|
|
7
|
+
this.buffer = new Uint32Array([seed, 0]);
|
|
8
|
+
}
|
|
9
|
+
copy() {
|
|
10
|
+
const gen = new Smush32();
|
|
11
|
+
gen.buffer.set(this.buffer);
|
|
12
|
+
return gen;
|
|
13
|
+
}
|
|
14
|
+
seed(s) {
|
|
15
|
+
this.buffer.set([s, 0]);
|
|
16
|
+
return this;
|
|
17
|
+
}
|
|
18
|
+
int() {
|
|
19
|
+
const b = this.buffer;
|
|
20
|
+
const m = 1540483477;
|
|
21
|
+
const k = b[1]++ * m >>> 0;
|
|
22
|
+
const s = b[0] = (k ^ k >> 24 ^ b[0] * m >>> 0) * m >>> 0;
|
|
23
|
+
return (s ^ s >>> 13) >>> 0;
|
|
24
|
+
}
|
|
32
25
|
}
|
|
26
|
+
export {
|
|
27
|
+
Smush32
|
|
28
|
+
};
|
package/system.js
CHANGED
|
@@ -1,22 +1,18 @@
|
|
|
1
1
|
import { ARandom } from "./arandom.js";
|
|
2
2
|
const random = Math.random;
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
*
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
norm(norm = 1) {
|
|
15
|
-
return (random() - 0.5) * 2 * norm;
|
|
16
|
-
}
|
|
3
|
+
class SystemRandom extends ARandom {
|
|
4
|
+
int() {
|
|
5
|
+
return random() * 4294967296 >>> 0;
|
|
6
|
+
}
|
|
7
|
+
float(norm = 1) {
|
|
8
|
+
return random() * norm;
|
|
9
|
+
}
|
|
10
|
+
norm(norm = 1) {
|
|
11
|
+
return (random() - 0.5) * 2 * norm;
|
|
12
|
+
}
|
|
17
13
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
14
|
+
const SYSTEM = new SystemRandom();
|
|
15
|
+
export {
|
|
16
|
+
SYSTEM,
|
|
17
|
+
SystemRandom
|
|
18
|
+
};
|
package/unique-indices.js
CHANGED
|
@@ -1,67 +1,27 @@
|
|
|
1
1
|
import { assert } from "@thi.ng/errors/assert";
|
|
2
2
|
import { SYSTEM } from "./system.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
export const uniqueValuesFrom = (k, fn, existing = [], maxTrials = 100) => {
|
|
18
|
-
let n = 0;
|
|
19
|
-
while (n < k) {
|
|
20
|
-
let i;
|
|
21
|
-
let trials = maxTrials;
|
|
22
|
-
do {
|
|
23
|
-
i = fn();
|
|
24
|
-
} while (existing.includes(i) && --trials > 0);
|
|
25
|
-
if (trials <= 0)
|
|
26
|
-
break;
|
|
27
|
-
existing.push(i);
|
|
28
|
-
n++;
|
|
29
|
-
}
|
|
30
|
-
return existing;
|
|
3
|
+
const uniqueValuesFrom = (k, fn, existing = [], maxTrials = 100) => {
|
|
4
|
+
let n = 0;
|
|
5
|
+
while (n < k) {
|
|
6
|
+
let i;
|
|
7
|
+
let trials = maxTrials;
|
|
8
|
+
do {
|
|
9
|
+
i = fn();
|
|
10
|
+
} while (existing.includes(i) && --trials > 0);
|
|
11
|
+
if (trials <= 0)
|
|
12
|
+
break;
|
|
13
|
+
existing.push(i);
|
|
14
|
+
n++;
|
|
15
|
+
}
|
|
16
|
+
return existing;
|
|
31
17
|
};
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
*
|
|
42
|
-
* @param k -
|
|
43
|
-
* @param max -
|
|
44
|
-
* @param existing -
|
|
45
|
-
* @param maxTrials -
|
|
46
|
-
* @param rnd -
|
|
47
|
-
*/
|
|
48
|
-
export const uniqueIndices = (k, max, existing, maxTrials = max, rnd = SYSTEM) => {
|
|
49
|
-
assert(k >= 0 && k <= max, `k must be in [0, ${max}] interval`);
|
|
50
|
-
return uniqueValuesFrom(k, () => rnd.int() % max, existing, maxTrials);
|
|
18
|
+
const uniqueIndices = (k, max, existing, maxTrials = max, rnd = SYSTEM) => {
|
|
19
|
+
assert(k >= 0 && k <= max, `k must be in [0, ${max}] interval`);
|
|
20
|
+
return uniqueValuesFrom(k, () => rnd.int() % max, existing, maxTrials);
|
|
21
|
+
};
|
|
22
|
+
const pickRandomUnique = (k, src, existing, maxTrials = 100, rnd = SYSTEM) => uniqueValuesFrom(k, () => src[rnd.int() % src.length], existing, maxTrials);
|
|
23
|
+
export {
|
|
24
|
+
pickRandomUnique,
|
|
25
|
+
uniqueIndices,
|
|
26
|
+
uniqueValuesFrom
|
|
51
27
|
};
|
|
52
|
-
/**
|
|
53
|
-
* Combination of {@link pickRandom} and {@link uniqueValuesFrom}. Picks up to
|
|
54
|
-
* `k` unique values from `src` array (each with `maxTrials`) and adds them to
|
|
55
|
-
* given `existing` array (or creates a new one by default) and returns it. Uses
|
|
56
|
-
* given `rnd` instance (default: {@link SYSTEM} to randomly select candidates.
|
|
57
|
-
*
|
|
58
|
-
* @remarks
|
|
59
|
-
* Internally uses `Array.includes()` to check for duplicates.
|
|
60
|
-
*
|
|
61
|
-
* @param k
|
|
62
|
-
* @param src
|
|
63
|
-
* @param existing
|
|
64
|
-
* @param maxTrials
|
|
65
|
-
* @param rnd
|
|
66
|
-
*/
|
|
67
|
-
export const pickRandomUnique = (k, src, existing, maxTrials = 100, rnd = SYSTEM) => uniqueValuesFrom(k, () => src[rnd.int() % src.length], existing, maxTrials);
|
package/uuid.js
CHANGED
|
@@ -1,27 +1,15 @@
|
|
|
1
1
|
import { uuid as $uuid } from "@thi.ng/hex";
|
|
2
2
|
import { randomBytes, randomBytesFrom } from "./random-bytes.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
* @param rnd -
|
|
10
|
-
*/
|
|
11
|
-
export const uuidv4Bytes = (buf, rnd) => {
|
|
12
|
-
buf = buf || new Uint8Array(16);
|
|
13
|
-
buf = rnd ? randomBytesFrom(rnd, buf) : randomBytes(buf);
|
|
14
|
-
buf[6] = 0x40 | (buf[6] & 0x0f);
|
|
15
|
-
buf[8] = 0x80 | (buf[8] & 0x3f);
|
|
16
|
-
return buf;
|
|
3
|
+
const uuidv4Bytes = (buf, rnd) => {
|
|
4
|
+
buf = buf || new Uint8Array(16);
|
|
5
|
+
buf = rnd ? randomBytesFrom(rnd, buf) : randomBytes(buf);
|
|
6
|
+
buf[6] = 64 | buf[6] & 15;
|
|
7
|
+
buf[8] = 128 | buf[8] & 63;
|
|
8
|
+
return buf;
|
|
17
9
|
};
|
|
18
|
-
/** @internal */
|
|
19
10
|
const __buf = new Uint8Array(16);
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
* @param i - start index
|
|
26
|
-
*/
|
|
27
|
-
export const uuid = (id, i = 0) => $uuid(id || uuidv4Bytes(__buf), i);
|
|
11
|
+
const uuid = (id, i = 0) => $uuid(id || uuidv4Bytes(__buf), i);
|
|
12
|
+
export {
|
|
13
|
+
uuid,
|
|
14
|
+
uuidv4Bytes
|
|
15
|
+
};
|
package/weighted-random.js
CHANGED
|
@@ -1,54 +1,32 @@
|
|
|
1
1
|
import { assert } from "@thi.ng/errors/assert";
|
|
2
2
|
import { SYSTEM } from "./system.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
*/
|
|
21
|
-
export const weightedRandom = (choices, weights, rnd = SYSTEM) => {
|
|
22
|
-
const n = choices.length;
|
|
23
|
-
assert(n > 0, "no choices given");
|
|
24
|
-
const opts = weights
|
|
25
|
-
? choices
|
|
26
|
-
.map((x, i) => [weights[i] || 0, x])
|
|
27
|
-
.sort((a, b) => b[0] - a[0])
|
|
28
|
-
: choices.map((x) => [1, x]);
|
|
29
|
-
const total = opts.reduce((acc, o) => acc + o[0], 0);
|
|
30
|
-
total <= 0 && console.warn("total weights <= 0");
|
|
31
|
-
return () => {
|
|
32
|
-
const r = rnd.float(total);
|
|
33
|
-
let sum = total;
|
|
34
|
-
for (let i = 0; i < n; i++) {
|
|
35
|
-
sum -= opts[i][0];
|
|
36
|
-
if (sum <= r) {
|
|
37
|
-
return opts[i][1];
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
return undefined;
|
|
41
|
-
};
|
|
3
|
+
const weightedRandom = (choices, weights, rnd = SYSTEM) => {
|
|
4
|
+
const n = choices.length;
|
|
5
|
+
assert(n > 0, "no choices given");
|
|
6
|
+
const opts = weights ? choices.map((x, i) => [weights[i] || 0, x]).sort((a, b) => b[0] - a[0]) : choices.map((x) => [1, x]);
|
|
7
|
+
const total = opts.reduce((acc, o) => acc + o[0], 0);
|
|
8
|
+
total <= 0 && console.warn("total weights <= 0");
|
|
9
|
+
return () => {
|
|
10
|
+
const r = rnd.float(total);
|
|
11
|
+
let sum = total;
|
|
12
|
+
for (let i = 0; i < n; i++) {
|
|
13
|
+
sum -= opts[i][0];
|
|
14
|
+
if (sum <= r) {
|
|
15
|
+
return opts[i][1];
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return void 0;
|
|
19
|
+
};
|
|
42
20
|
};
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
export
|
|
52
|
-
|
|
53
|
-
|
|
21
|
+
const weightedRandomKey = (choices, rnd = SYSTEM) => {
|
|
22
|
+
const keys = Object.keys(choices);
|
|
23
|
+
return weightedRandom(
|
|
24
|
+
keys,
|
|
25
|
+
keys.map((x) => choices[x]),
|
|
26
|
+
rnd
|
|
27
|
+
);
|
|
28
|
+
};
|
|
29
|
+
export {
|
|
30
|
+
weightedRandom,
|
|
31
|
+
weightedRandomKey
|
|
54
32
|
};
|
package/xorshift128.js
CHANGED
|
@@ -1,35 +1,34 @@
|
|
|
1
1
|
import { ARandom } from "./arandom.js";
|
|
2
2
|
import { DEFAULT_SEED_128 } from "./constants.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
s[2] = s[1];
|
|
32
|
-
w = s[1] = s[0];
|
|
33
|
-
return (s[0] = (t ^ w ^ (w >>> 19)) >>> 0);
|
|
34
|
-
}
|
|
3
|
+
class XorShift128 extends ARandom {
|
|
4
|
+
buffer;
|
|
5
|
+
constructor(seed = DEFAULT_SEED_128) {
|
|
6
|
+
super();
|
|
7
|
+
this.buffer = new Uint32Array(4);
|
|
8
|
+
this.seed(seed);
|
|
9
|
+
}
|
|
10
|
+
copy() {
|
|
11
|
+
return new XorShift128(this.buffer);
|
|
12
|
+
}
|
|
13
|
+
bytes() {
|
|
14
|
+
return new Uint8Array(this.buffer.buffer);
|
|
15
|
+
}
|
|
16
|
+
seed(seed) {
|
|
17
|
+
this.buffer.set(seed);
|
|
18
|
+
return this;
|
|
19
|
+
}
|
|
20
|
+
int() {
|
|
21
|
+
const s = this.buffer;
|
|
22
|
+
let t = s[3];
|
|
23
|
+
let w;
|
|
24
|
+
t ^= t << 11;
|
|
25
|
+
t ^= t >>> 8;
|
|
26
|
+
s[3] = s[2];
|
|
27
|
+
s[2] = s[1];
|
|
28
|
+
w = s[1] = s[0];
|
|
29
|
+
return s[0] = (t ^ w ^ w >>> 19) >>> 0;
|
|
30
|
+
}
|
|
35
31
|
}
|
|
32
|
+
export {
|
|
33
|
+
XorShift128
|
|
34
|
+
};
|
package/xorwow.js
CHANGED
|
@@ -1,38 +1,37 @@
|
|
|
1
1
|
import { ARandom } from "./arandom.js";
|
|
2
2
|
import { DEFAULT_SEED_160 } from "./constants.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
t ^= w << 4;
|
|
35
|
-
s[0] = t;
|
|
36
|
-
return (t + (s[4] += 0x587c5)) >>> 0;
|
|
37
|
-
}
|
|
3
|
+
class XorWow extends ARandom {
|
|
4
|
+
buffer;
|
|
5
|
+
constructor(seed = DEFAULT_SEED_160) {
|
|
6
|
+
super();
|
|
7
|
+
this.buffer = new Uint32Array(5);
|
|
8
|
+
this.seed(seed);
|
|
9
|
+
}
|
|
10
|
+
copy() {
|
|
11
|
+
return new XorWow(this.buffer);
|
|
12
|
+
}
|
|
13
|
+
seed(seed) {
|
|
14
|
+
this.buffer.set(seed);
|
|
15
|
+
return this;
|
|
16
|
+
}
|
|
17
|
+
bytes() {
|
|
18
|
+
return new Uint8Array(this.buffer.buffer);
|
|
19
|
+
}
|
|
20
|
+
int() {
|
|
21
|
+
const s = this.buffer;
|
|
22
|
+
let t = s[3];
|
|
23
|
+
let w;
|
|
24
|
+
t ^= t >>> 2;
|
|
25
|
+
t ^= t << 1;
|
|
26
|
+
s[3] = s[2];
|
|
27
|
+
s[2] = s[1];
|
|
28
|
+
w = s[1] = s[0];
|
|
29
|
+
t ^= w;
|
|
30
|
+
t ^= w << 4;
|
|
31
|
+
s[0] = t;
|
|
32
|
+
return t + (s[4] += 362437) >>> 0;
|
|
33
|
+
}
|
|
38
34
|
}
|
|
35
|
+
export {
|
|
36
|
+
XorWow
|
|
37
|
+
};
|
package/xoshiro128.js
CHANGED
|
@@ -1,40 +1,37 @@
|
|
|
1
1
|
import { ARandom } from "./arandom.js";
|
|
2
2
|
import { DEFAULT_SEED_128 } from "./constants.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
s[0] ^= s[3];
|
|
35
|
-
s[2] ^= t;
|
|
36
|
-
t = s[3];
|
|
37
|
-
s[3] = ((t << 11) | (t >>> 21)) >>> 0;
|
|
38
|
-
return res;
|
|
39
|
-
}
|
|
3
|
+
class Xoshiro128 extends ARandom {
|
|
4
|
+
buffer;
|
|
5
|
+
constructor(seed = DEFAULT_SEED_128) {
|
|
6
|
+
super();
|
|
7
|
+
this.buffer = new Uint32Array(4);
|
|
8
|
+
this.seed(seed);
|
|
9
|
+
}
|
|
10
|
+
copy() {
|
|
11
|
+
return new Xoshiro128(this.buffer);
|
|
12
|
+
}
|
|
13
|
+
bytes() {
|
|
14
|
+
return new Uint8Array(this.buffer.buffer);
|
|
15
|
+
}
|
|
16
|
+
seed(seed) {
|
|
17
|
+
this.buffer.set(seed);
|
|
18
|
+
return this;
|
|
19
|
+
}
|
|
20
|
+
int() {
|
|
21
|
+
const s = this.buffer;
|
|
22
|
+
let t = s[0] + s[3];
|
|
23
|
+
const res = (t << 7 | t >>> 25) >>> 0;
|
|
24
|
+
t = s[1] << 9;
|
|
25
|
+
s[2] ^= s[0];
|
|
26
|
+
s[3] ^= s[1];
|
|
27
|
+
s[1] ^= s[2];
|
|
28
|
+
s[0] ^= s[3];
|
|
29
|
+
s[2] ^= t;
|
|
30
|
+
t = s[3];
|
|
31
|
+
s[3] = (t << 11 | t >>> 21) >>> 0;
|
|
32
|
+
return res;
|
|
33
|
+
}
|
|
40
34
|
}
|
|
35
|
+
export {
|
|
36
|
+
Xoshiro128
|
|
37
|
+
};
|
package/xsadd.js
CHANGED
|
@@ -1,44 +1,43 @@
|
|
|
1
1
|
import { ARandom } from "./arandom.js";
|
|
2
2
|
import { DEFAULT_SEED_32 } from "./constants.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
for (let j = 0, i = 1; i < 8; j = i++) {
|
|
26
|
-
let x = (s[j & 3] ^ (s[j & 3] >>> 30)) >>> 0;
|
|
27
|
-
x = (0x8965 * x + (((0x6c07 * x) & 0xffff) << 16)) >>> 0;
|
|
28
|
-
s[i & 3] ^= (i + x) >>> 0;
|
|
29
|
-
}
|
|
30
|
-
return this;
|
|
31
|
-
}
|
|
32
|
-
int() {
|
|
33
|
-
const s = this.buffer;
|
|
34
|
-
let t = s[0];
|
|
35
|
-
t ^= t << 15;
|
|
36
|
-
t ^= t >>> 18;
|
|
37
|
-
t ^= s[3] << 11;
|
|
38
|
-
s[0] = s[1];
|
|
39
|
-
s[1] = s[2];
|
|
40
|
-
s[2] = s[3];
|
|
41
|
-
s[3] = t;
|
|
42
|
-
return (t + s[2]) >>> 0;
|
|
3
|
+
class XsAdd extends ARandom {
|
|
4
|
+
buffer;
|
|
5
|
+
constructor(seed = DEFAULT_SEED_32) {
|
|
6
|
+
super();
|
|
7
|
+
this.buffer = new Uint32Array(4);
|
|
8
|
+
this.seed(seed);
|
|
9
|
+
}
|
|
10
|
+
bytes() {
|
|
11
|
+
return new Uint8Array(this.buffer.buffer);
|
|
12
|
+
}
|
|
13
|
+
copy() {
|
|
14
|
+
const gen = new XsAdd();
|
|
15
|
+
gen.buffer.set(this.buffer);
|
|
16
|
+
return gen;
|
|
17
|
+
}
|
|
18
|
+
seed(seed) {
|
|
19
|
+
const s = this.buffer;
|
|
20
|
+
s.set([seed, 0, 0, 0]);
|
|
21
|
+
for (let j = 0, i = 1; i < 8; j = i++) {
|
|
22
|
+
let x = (s[j & 3] ^ s[j & 3] >>> 30) >>> 0;
|
|
23
|
+
x = 35173 * x + ((27655 * x & 65535) << 16) >>> 0;
|
|
24
|
+
s[i & 3] ^= i + x >>> 0;
|
|
43
25
|
}
|
|
26
|
+
return this;
|
|
27
|
+
}
|
|
28
|
+
int() {
|
|
29
|
+
const s = this.buffer;
|
|
30
|
+
let t = s[0];
|
|
31
|
+
t ^= t << 15;
|
|
32
|
+
t ^= t >>> 18;
|
|
33
|
+
t ^= s[3] << 11;
|
|
34
|
+
s[0] = s[1];
|
|
35
|
+
s[1] = s[2];
|
|
36
|
+
s[2] = s[3];
|
|
37
|
+
s[3] = t;
|
|
38
|
+
return t + s[2] >>> 0;
|
|
39
|
+
}
|
|
44
40
|
}
|
|
41
|
+
export {
|
|
42
|
+
XsAdd
|
|
43
|
+
};
|