@cloudglides/nox 1.0.1 → 1.1.1
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/package.json +2 -1
- package/src/core.js +2 -0
- package/src/index.browser.js +31 -0
- package/src/presets.js +7 -0
- package/src/utils/entropy.browser.js +63 -0
- package/src/utils/entropy.js +8 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudglides/nox",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Unpredictable random number generator with multiple algorithms and distributions",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
"exports": {
|
|
9
9
|
".": {
|
|
10
10
|
"node": "./src/index.js",
|
|
11
|
+
"browser": "./src/index.browser.js",
|
|
11
12
|
"default": "./src/index.js"
|
|
12
13
|
}
|
|
13
14
|
},
|
package/src/core.js
CHANGED
|
@@ -6,3 +6,5 @@ export { shuffle, pick, sample } from './utils/sequence.js';
|
|
|
6
6
|
export { saveState, restoreState, cloneGenerator } from './utils/state.js';
|
|
7
7
|
export { weightedPick, weightedSample, reservoirSample } from './utils/sampling.js';
|
|
8
8
|
export { meanTest, varianceTest, kolmogorovSmirnovTest } from './utils/statistics.js';
|
|
9
|
+
|
|
10
|
+
export { combined, clearCryptoCache } from './utils/entropy.js';
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export {
|
|
2
|
+
rng,
|
|
3
|
+
RNG,
|
|
4
|
+
deterministic,
|
|
5
|
+
normal,
|
|
6
|
+
exponential,
|
|
7
|
+
uniform,
|
|
8
|
+
poisson,
|
|
9
|
+
shuffle,
|
|
10
|
+
pick,
|
|
11
|
+
sample,
|
|
12
|
+
saveState,
|
|
13
|
+
restoreState,
|
|
14
|
+
cloneGenerator,
|
|
15
|
+
weightedPick,
|
|
16
|
+
weightedSample,
|
|
17
|
+
reservoirSample,
|
|
18
|
+
meanTest,
|
|
19
|
+
varianceTest,
|
|
20
|
+
kolmogorovSmirnovTest
|
|
21
|
+
} from './core.js';
|
|
22
|
+
|
|
23
|
+
export {
|
|
24
|
+
Xorshift64,
|
|
25
|
+
Splitmix64,
|
|
26
|
+
PCG64,
|
|
27
|
+
MT19937,
|
|
28
|
+
Logistic,
|
|
29
|
+
Tent,
|
|
30
|
+
Mixer
|
|
31
|
+
} from './generators/index.js';
|
package/src/presets.js
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { RNG } from './rng.js';
|
|
2
2
|
import { PCG64 } from './generators/index.js';
|
|
3
3
|
|
|
4
|
+
// Use browser or node entropy
|
|
5
|
+
const isNode = typeof process !== 'undefined' && process.versions && process.versions.node;
|
|
6
|
+
const entropyModule = isNode ?
|
|
7
|
+
await import('./utils/entropy.js') :
|
|
8
|
+
await import('./utils/entropy.browser.js');
|
|
9
|
+
const { combined: entropyFunc } = entropyModule;
|
|
10
|
+
|
|
4
11
|
export const deterministic = (seed) => {
|
|
5
12
|
if (seed === null || seed === undefined) {
|
|
6
13
|
throw new TypeError('Deterministic mode requires an explicit seed');
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
let cryptoCache = null;
|
|
2
|
+
let cryptoCacheTime = 0;
|
|
3
|
+
|
|
4
|
+
export const fromPerformance = () => {
|
|
5
|
+
try {
|
|
6
|
+
if (typeof performance !== 'undefined' && performance.now) {
|
|
7
|
+
const t = performance.now();
|
|
8
|
+
return BigInt(Math.floor(t * 1000)) ^ BigInt(Math.floor(t * 1000000) % 1000000);
|
|
9
|
+
}
|
|
10
|
+
} catch {
|
|
11
|
+
// fallback
|
|
12
|
+
}
|
|
13
|
+
return BigInt(Date.now());
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const fromMemory = () => {
|
|
17
|
+
return BigInt(Date.now());
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const fromCrypto = (bytes = 8) => {
|
|
21
|
+
try {
|
|
22
|
+
const now = Date.now();
|
|
23
|
+
|
|
24
|
+
if (cryptoCache && (now - cryptoCacheTime) < 100) {
|
|
25
|
+
return cryptoCache;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
let val = 0n;
|
|
29
|
+
|
|
30
|
+
if (typeof crypto !== 'undefined' && crypto.getRandomValues) {
|
|
31
|
+
const arr = new Uint8Array(Math.max(bytes, 8));
|
|
32
|
+
crypto.getRandomValues(arr);
|
|
33
|
+
for (let i = 0; i < arr.length; i++) {
|
|
34
|
+
val = (val << 8n) | BigInt(arr[i]);
|
|
35
|
+
}
|
|
36
|
+
} else {
|
|
37
|
+
return BigInt(Math.random() * Number.MAX_SAFE_INTEGER);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
cryptoCache = val;
|
|
41
|
+
cryptoCacheTime = now;
|
|
42
|
+
return val;
|
|
43
|
+
} catch {
|
|
44
|
+
return BigInt(Math.random() * Number.MAX_SAFE_INTEGER);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export const combined = () => {
|
|
49
|
+
const perf = fromPerformance();
|
|
50
|
+
const mem = fromMemory();
|
|
51
|
+
const crypto = fromCrypto();
|
|
52
|
+
|
|
53
|
+
let mix = perf ^ mem ^ crypto;
|
|
54
|
+
mix = mix ^ (mix >> 33n);
|
|
55
|
+
mix = (mix * 0xff51afd7ed558ccdn) & ((1n << 64n) - 1n);
|
|
56
|
+
|
|
57
|
+
return mix !== 0n ? mix : 1n;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export const clearCryptoCache = () => {
|
|
61
|
+
cryptoCache = null;
|
|
62
|
+
cryptoCacheTime = 0;
|
|
63
|
+
};
|
package/src/utils/entropy.js
CHANGED
|
@@ -7,14 +7,19 @@ const isBrowser = typeof window !== 'undefined';
|
|
|
7
7
|
let performanceImpl = typeof performance !== 'undefined' ? performance : null;
|
|
8
8
|
let randomBytesImpl = null;
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
// Avoid parsing require() for browser - use indirect method
|
|
11
|
+
if (isNode) {
|
|
11
12
|
try {
|
|
12
|
-
const
|
|
13
|
+
const getRequire = new Function('return require');
|
|
14
|
+
const req = getRequire();
|
|
15
|
+
const perf_hooks = req('perf_hooks');
|
|
13
16
|
performanceImpl = perf_hooks.performance;
|
|
14
17
|
} catch {}
|
|
15
18
|
|
|
16
19
|
try {
|
|
17
|
-
const
|
|
20
|
+
const getRequire = new Function('return require');
|
|
21
|
+
const req = getRequire();
|
|
22
|
+
const crypto_mod = req('crypto');
|
|
18
23
|
randomBytesImpl = crypto_mod.randomBytes;
|
|
19
24
|
} catch {}
|
|
20
25
|
}
|