@cloudglides/nox 1.0.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.
Files changed (49) hide show
  1. package/.github/workflows/build-on-tag.yml +67 -0
  2. package/IMPROVEMENTS.md +58 -0
  3. package/LICENSE +15 -0
  4. package/README.md +119 -0
  5. package/docs/API.md +70 -0
  6. package/example/README.md +26 -0
  7. package/example/index.html +13 -0
  8. package/example/package-lock.json +1636 -0
  9. package/example/package.json +20 -0
  10. package/example/src/App.css +161 -0
  11. package/example/src/App.jsx +176 -0
  12. package/example/src/index.css +55 -0
  13. package/example/src/main.jsx +10 -0
  14. package/example/vite.config.js +11 -0
  15. package/package.json +25 -0
  16. package/src/core.js +8 -0
  17. package/src/generators/index.js +7 -0
  18. package/src/generators/logistic.js +19 -0
  19. package/src/generators/mixer.js +20 -0
  20. package/src/generators/mt19937.js +74 -0
  21. package/src/generators/pcg64.js +44 -0
  22. package/src/generators/splitmix64.js +32 -0
  23. package/src/generators/tent.js +24 -0
  24. package/src/generators/xorshift64.js +38 -0
  25. package/src/index.d.ts +114 -0
  26. package/src/index.js +32 -0
  27. package/src/presets.js +15 -0
  28. package/src/rng.js +142 -0
  29. package/src/utils/bits.js +25 -0
  30. package/src/utils/categorical.js +57 -0
  31. package/src/utils/combinatorics.js +85 -0
  32. package/src/utils/distributions-extra.js +32 -0
  33. package/src/utils/distributions-special.js +21 -0
  34. package/src/utils/distributions.js +69 -0
  35. package/src/utils/entropy.js +95 -0
  36. package/src/utils/index.js +30 -0
  37. package/src/utils/noise.js +81 -0
  38. package/src/utils/sampling.js +106 -0
  39. package/src/utils/seed.js +14 -0
  40. package/src/utils/seeding.js +37 -0
  41. package/src/utils/sequence.js +53 -0
  42. package/src/utils/state.js +39 -0
  43. package/src/utils/statistics.js +127 -0
  44. package/src/utils/stochastic.js +32 -0
  45. package/test/advanced.js +71 -0
  46. package/test/basic.js +13 -0
  47. package/test/benchmark.js +35 -0
  48. package/test/comprehensive.js +100 -0
  49. package/test/profile.js +73 -0
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "nox-demo",
3
+ "private": true,
4
+ "version": "0.0.1",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "vite build",
9
+ "preview": "vite preview"
10
+ },
11
+ "dependencies": {
12
+ "@cloudglides/nox": "latest",
13
+ "react": "^18.2.0",
14
+ "react-dom": "^18.2.0"
15
+ },
16
+ "devDependencies": {
17
+ "@vitejs/plugin-react": "^4.2.1",
18
+ "vite": "^5.0.8"
19
+ }
20
+ }
@@ -0,0 +1,161 @@
1
+ .app {
2
+ width: 100%;
3
+ min-height: 100vh;
4
+ display: flex;
5
+ flex-direction: column;
6
+ background: linear-gradient(135deg, #1e1e2e 0%, #2d2d44 100%);
7
+ }
8
+
9
+ header {
10
+ padding: 3rem 2rem;
11
+ text-align: center;
12
+ border-bottom: 2px solid #646cff;
13
+ }
14
+
15
+ header h1 {
16
+ font-size: 3rem;
17
+ margin-bottom: 0.5rem;
18
+ background: linear-gradient(45deg, #646cff, #0ea5e9);
19
+ -webkit-background-clip: text;
20
+ -webkit-text-fill-color: transparent;
21
+ background-clip: text;
22
+ }
23
+
24
+ header p {
25
+ font-size: 1.1rem;
26
+ color: #a0a0a0;
27
+ }
28
+
29
+ .tabs {
30
+ display: flex;
31
+ gap: 1rem;
32
+ padding: 2rem;
33
+ justify-content: center;
34
+ flex-wrap: wrap;
35
+ border-bottom: 1px solid #444;
36
+ }
37
+
38
+ .tabs button {
39
+ padding: 0.8rem 1.6rem;
40
+ font-size: 1rem;
41
+ border: 2px solid transparent;
42
+ border-radius: 8px;
43
+ cursor: pointer;
44
+ transition: all 0.3s;
45
+ color: #a0a0a0;
46
+ background: #2d2d44;
47
+ }
48
+
49
+ .tabs button:hover {
50
+ color: #646cff;
51
+ border-color: #646cff;
52
+ }
53
+
54
+ .tabs button.active {
55
+ color: #fff;
56
+ border-color: #646cff;
57
+ background: #1a1a2e;
58
+ }
59
+
60
+ .content {
61
+ flex: 1;
62
+ padding: 2rem;
63
+ max-width: 900px;
64
+ margin: 0 auto;
65
+ width: 100%;
66
+ }
67
+
68
+ .section {
69
+ background: #2d2d44;
70
+ padding: 2rem;
71
+ border-radius: 12px;
72
+ border: 1px solid #444;
73
+ }
74
+
75
+ .section h2 {
76
+ margin-bottom: 1.5rem;
77
+ color: #646cff;
78
+ }
79
+
80
+ .action-btn {
81
+ background: linear-gradient(45deg, #646cff, #0ea5e9);
82
+ color: white;
83
+ padding: 0.8rem 2rem;
84
+ font-size: 1rem;
85
+ border: none;
86
+ border-radius: 8px;
87
+ cursor: pointer;
88
+ font-weight: 600;
89
+ transition: transform 0.2s, box-shadow 0.2s;
90
+ margin-bottom: 1.5rem;
91
+ }
92
+
93
+ .action-btn:hover {
94
+ transform: translateY(-2px);
95
+ box-shadow: 0 10px 25px rgba(100, 108, 255, 0.3);
96
+ }
97
+
98
+ .action-btn:active {
99
+ transform: translateY(0);
100
+ }
101
+
102
+ .results {
103
+ background: #1a1a2e;
104
+ padding: 1.5rem;
105
+ border-radius: 8px;
106
+ border-left: 4px solid #646cff;
107
+ margin-top: 1rem;
108
+ font-family: 'Courier New', monospace;
109
+ word-break: break-all;
110
+ }
111
+
112
+ .results p {
113
+ margin: 0.8rem 0;
114
+ line-height: 1.6;
115
+ }
116
+
117
+ .results strong {
118
+ color: #646cff;
119
+ font-weight: 600;
120
+ }
121
+
122
+ footer {
123
+ text-align: center;
124
+ padding: 2rem;
125
+ border-top: 1px solid #444;
126
+ color: #a0a0a0;
127
+ }
128
+
129
+ footer a {
130
+ color: #646cff;
131
+ text-decoration: none;
132
+ margin: 0 0.5rem;
133
+ }
134
+
135
+ footer a:hover {
136
+ text-decoration: underline;
137
+ }
138
+
139
+ @media (max-width: 768px) {
140
+ header h1 {
141
+ font-size: 2rem;
142
+ }
143
+
144
+ .tabs {
145
+ gap: 0.5rem;
146
+ padding: 1rem;
147
+ }
148
+
149
+ .tabs button {
150
+ padding: 0.6rem 1rem;
151
+ font-size: 0.9rem;
152
+ }
153
+
154
+ .content {
155
+ padding: 1rem;
156
+ }
157
+
158
+ .section {
159
+ padding: 1.5rem;
160
+ }
161
+ }
@@ -0,0 +1,176 @@
1
+ import { useState } from 'react'
2
+ import { rng, deterministic, normal, exponential, meanTest, varianceTest, kolmogorovSmirnovTest } from '@cloudglides/nox'
3
+ import './App.css'
4
+
5
+ export default function App() {
6
+ const [tab, setTab] = useState('basic')
7
+ const [results, setResults] = useState({})
8
+
9
+ const runBasic = () => {
10
+ const r = rng()
11
+ setResults({
12
+ float: r.nextFloat().toFixed(6),
13
+ int: r.int(1, 100),
14
+ bool: r.bool(0.5),
15
+ range: r.range(10, 20, 2),
16
+ choice: r.choice(['apple', 'banana', 'cherry'])
17
+ })
18
+ }
19
+
20
+ const runBatch = () => {
21
+ const r = rng()
22
+ setResults({
23
+ floats: r.floats(5).map(x => x.toFixed(4)).join(', '),
24
+ ints: r.ints(5, 100).join(', '),
25
+ bools: r.bools(5).join(', ')
26
+ })
27
+ }
28
+
29
+ const runDistributions = () => {
30
+ const r = rng()
31
+ const samples = r.floats(100)
32
+ setResults({
33
+ normal: Array.from({length: 5}, () => normal(r).toFixed(4)).join(', '),
34
+ exponential: Array.from({length: 5}, () => exponential(r).toFixed(4)).join(', ')
35
+ })
36
+ }
37
+
38
+ const runStats = () => {
39
+ const r = rng()
40
+ const data = r.floats(1000)
41
+ const mean = meanTest(data)
42
+ const variance = varianceTest(data)
43
+ const ks = kolmogorovSmirnovTest(data)
44
+ setResults({
45
+ mean: mean.mean.toFixed(6),
46
+ variance: variance.variance.toFixed(6),
47
+ ksPass: ks.pass_0_05 ? 'PASS' : 'FAIL'
48
+ })
49
+ }
50
+
51
+ const runDeterministic = () => {
52
+ const r1 = deterministic(42)
53
+ const seq1 = r1.floats(5)
54
+ const r2 = deterministic(42)
55
+ const seq2 = r2.floats(5)
56
+ setResults({
57
+ seq1: seq1.map(x => x.toFixed(4)).join(', '),
58
+ seq2: seq2.map(x => x.toFixed(4)).join(', '),
59
+ identical: JSON.stringify(seq1) === JSON.stringify(seq2) ? 'YES' : 'NO'
60
+ })
61
+ }
62
+
63
+ return (
64
+ <div className="app">
65
+ <header>
66
+ <h1>nox - RNG Demo</h1>
67
+ <p>Unpredictable random number generator with multiple algorithms</p>
68
+ </header>
69
+
70
+ <div className="tabs">
71
+ <button className={tab === 'basic' ? 'active' : ''} onClick={() => setTab('basic')}>
72
+ Basic
73
+ </button>
74
+ <button className={tab === 'batch' ? 'active' : ''} onClick={() => setTab('batch')}>
75
+ Batch
76
+ </button>
77
+ <button className={tab === 'distributions' ? 'active' : ''} onClick={() => setTab('distributions')}>
78
+ Distributions
79
+ </button>
80
+ <button className={tab === 'stats' ? 'active' : ''} onClick={() => setTab('stats')}>
81
+ Statistics
82
+ </button>
83
+ <button className={tab === 'deterministic' ? 'active' : ''} onClick={() => setTab('deterministic')}>
84
+ Deterministic
85
+ </button>
86
+ </div>
87
+
88
+ <div className="content">
89
+ {tab === 'basic' && (
90
+ <div className="section">
91
+ <h2>Basic RNG Operations</h2>
92
+ <button onClick={runBasic} className="action-btn">Run</button>
93
+ <div className="results">
94
+ {results.float && (
95
+ <div>
96
+ <p><strong>nextFloat():</strong> {results.float}</p>
97
+ <p><strong>int(1, 100):</strong> {results.int}</p>
98
+ <p><strong>bool(0.5):</strong> {results.bool ? 'true' : 'false'}</p>
99
+ <p><strong>range(10, 20, 2):</strong> {results.range}</p>
100
+ <p><strong>choice():</strong> {results.choice}</p>
101
+ </div>
102
+ )}
103
+ </div>
104
+ </div>
105
+ )}
106
+
107
+ {tab === 'batch' && (
108
+ <div className="section">
109
+ <h2>Batch Operations</h2>
110
+ <button onClick={runBatch} className="action-btn">Run</button>
111
+ <div className="results">
112
+ {results.floats && (
113
+ <div>
114
+ <p><strong>floats(5):</strong> [{results.floats}]</p>
115
+ <p><strong>ints(5, 100):</strong> [{results.ints}]</p>
116
+ <p><strong>bools(5):</strong> [{results.bools}]</p>
117
+ </div>
118
+ )}
119
+ </div>
120
+ </div>
121
+ )}
122
+
123
+ {tab === 'distributions' && (
124
+ <div className="section">
125
+ <h2>Statistical Distributions</h2>
126
+ <button onClick={runDistributions} className="action-btn">Run</button>
127
+ <div className="results">
128
+ {results.normal && (
129
+ <div>
130
+ <p><strong>Normal(0, 1):</strong> [{results.normal}]</p>
131
+ <p><strong>Exponential(1):</strong> [{results.exponential}]</p>
132
+ </div>
133
+ )}
134
+ </div>
135
+ </div>
136
+ )}
137
+
138
+ {tab === 'stats' && (
139
+ <div className="section">
140
+ <h2>Statistical Tests</h2>
141
+ <button onClick={runStats} className="action-btn">Run on 1000 samples</button>
142
+ <div className="results">
143
+ {results.mean && (
144
+ <div>
145
+ <p><strong>Mean (expected 0.5):</strong> {results.mean}</p>
146
+ <p><strong>Variance (expected 0.083333):</strong> {results.variance}</p>
147
+ <p><strong>KS Test (α=0.05):</strong> {results.ksPass}</p>
148
+ </div>
149
+ )}
150
+ </div>
151
+ </div>
152
+ )}
153
+
154
+ {tab === 'deterministic' && (
155
+ <div className="section">
156
+ <h2>Deterministic Mode</h2>
157
+ <button onClick={runDeterministic} className="action-btn">Run with seed=42</button>
158
+ <div className="results">
159
+ {results.seq1 && (
160
+ <div>
161
+ <p><strong>Sequence 1:</strong> [{results.seq1}]</p>
162
+ <p><strong>Sequence 2:</strong> [{results.seq2}]</p>
163
+ <p><strong>Identical:</strong> {results.identical}</p>
164
+ </div>
165
+ )}
166
+ </div>
167
+ </div>
168
+ )}
169
+ </div>
170
+
171
+ <footer>
172
+ <p>Visit <a href="https://github.com/cloudglides/nox" target="_blank" rel="noreferrer">GitHub</a> | <a href="https://npmjs.com/package/@cloudglides/nox" target="_blank" rel="noreferrer">npm</a></p>
173
+ </footer>
174
+ </div>
175
+ )
176
+ }
@@ -0,0 +1,55 @@
1
+ :root {
2
+ font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
3
+ line-height: 1.5;
4
+ font-weight: 400;
5
+ color: rgba(255, 255, 255, 0.87);
6
+ background-color: #242424;
7
+ }
8
+
9
+ * {
10
+ margin: 0;
11
+ padding: 0;
12
+ box-sizing: border-box;
13
+ }
14
+
15
+ body {
16
+ margin: 0;
17
+ min-width: 320px;
18
+ min-height: 100vh;
19
+ }
20
+
21
+ #root {
22
+ width: 100%;
23
+ min-height: 100vh;
24
+ }
25
+
26
+ button {
27
+ border-radius: 8px;
28
+ border: 1px solid transparent;
29
+ padding: 0.6em 1.2em;
30
+ font-size: 1em;
31
+ font-weight: 500;
32
+ font-family: inherit;
33
+ background-color: #1a1a1a;
34
+ cursor: pointer;
35
+ transition: border-color 0.25s;
36
+ }
37
+
38
+ button:hover {
39
+ border-color: #646cff;
40
+ }
41
+
42
+ button:focus,
43
+ button:focus-visible {
44
+ outline: 4px auto -webkit-focus-ring-color;
45
+ }
46
+
47
+ @media (prefers-color-scheme: light) {
48
+ :root {
49
+ color: #213547;
50
+ background-color: #ffffff;
51
+ }
52
+ button {
53
+ background-color: #f9f9f9;
54
+ }
55
+ }
@@ -0,0 +1,10 @@
1
+ import React from 'react'
2
+ import ReactDOM from 'react-dom/client'
3
+ import App from './App.jsx'
4
+ import './index.css'
5
+
6
+ ReactDOM.createRoot(document.getElementById('root')).render(
7
+ <React.StrictMode>
8
+ <App />
9
+ </React.StrictMode>,
10
+ )
@@ -0,0 +1,11 @@
1
+ import { defineConfig } from 'vite'
2
+ import react from '@vitejs/plugin-react'
3
+
4
+ export default defineConfig({
5
+ plugins: [react()],
6
+ build: {
7
+ rollupOptions: {
8
+ external: ['perf_hooks', 'crypto']
9
+ }
10
+ }
11
+ })
package/package.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "@cloudglides/nox",
3
+ "version": "1.0.1",
4
+ "description": "Unpredictable random number generator with multiple algorithms and distributions",
5
+ "type": "module",
6
+ "main": "src/index.js",
7
+ "types": "src/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "node": "./src/index.js",
11
+ "default": "./src/index.js"
12
+ }
13
+ },
14
+ "scripts": {
15
+ "test": "node test/basic.js",
16
+ "bench": "node test/benchmark.js"
17
+ },
18
+ "keywords": ["random", "rng", "generator", "chaotic", "stochastic"],
19
+ "author": "",
20
+ "license": "ISC",
21
+ "packageManager": "pnpm@10.24.0",
22
+ "publishConfig": {
23
+ "access": "public"
24
+ }
25
+ }
package/src/core.js ADDED
@@ -0,0 +1,8 @@
1
+ export { rng, RNG } from './rng.js';
2
+ export { deterministic } from './presets.js';
3
+
4
+ export { normal, exponential, uniform, poisson } from './utils/distributions.js';
5
+ export { shuffle, pick, sample } from './utils/sequence.js';
6
+ export { saveState, restoreState, cloneGenerator } from './utils/state.js';
7
+ export { weightedPick, weightedSample, reservoirSample } from './utils/sampling.js';
8
+ export { meanTest, varianceTest, kolmogorovSmirnovTest } from './utils/statistics.js';
@@ -0,0 +1,7 @@
1
+ export { Xorshift64 } from './xorshift64.js';
2
+ export { Logistic } from './logistic.js';
3
+ export { Tent } from './tent.js';
4
+ export { Splitmix64 } from './splitmix64.js';
5
+ export { PCG64 } from './pcg64.js';
6
+ export { MT19937 } from './mt19937.js';
7
+ export { Mixer } from './mixer.js';
@@ -0,0 +1,19 @@
1
+ export class Logistic {
2
+ constructor(seed = 0.5, r = 3.99) {
3
+ this.x = seed;
4
+ this.r = r;
5
+ }
6
+
7
+ next() {
8
+ this.x = this.r * this.x * (1 - this.x);
9
+ return this.x;
10
+ }
11
+
12
+ nextInt(max = 2147483647) {
13
+ return Math.floor(this.next() * max);
14
+ }
15
+
16
+ nextFloat() {
17
+ return this.next();
18
+ }
19
+ }
@@ -0,0 +1,20 @@
1
+ export class Mixer {
2
+ constructor(rng1, rng2) {
3
+ this.rng1 = rng1;
4
+ this.rng2 = rng2;
5
+ }
6
+
7
+ next() {
8
+ return this.rng1.next() ^ this.rng2.next();
9
+ }
10
+
11
+ nextInt(max = 2147483647) {
12
+ const v1 = this.rng1.nextInt(max);
13
+ const v2 = this.rng2.nextInt(max);
14
+ return (v1 + v2) % max;
15
+ }
16
+
17
+ nextFloat() {
18
+ return (this.rng1.nextFloat() + this.rng2.nextFloat()) / 2;
19
+ }
20
+ }
@@ -0,0 +1,74 @@
1
+ export class MT19937 {
2
+ constructor(seed = 5489) {
3
+ this.N = 624;
4
+ this.M = 397;
5
+ this.MATRIX_A = 0x9908b0df;
6
+ this.UPPER_MASK = 0x80000000;
7
+ this.LOWER_MASK = 0x7fffffff;
8
+
9
+ this.mt = new Array(this.N);
10
+ this.mti = this.N + 1;
11
+
12
+ this.init(seed);
13
+ }
14
+
15
+ init(seed) {
16
+ const s = typeof seed === 'bigint' ? Number(seed) : seed;
17
+ this.mt[0] = (s >>> 0) & 0xffffffff;
18
+
19
+ for (let i = 1; i < this.N; i++) {
20
+ const x = this.mt[i - 1] ^ (this.mt[i - 1] >>> 30);
21
+ this.mt[i] = (((((x & 0xffff0000) >>> 16) * 1812433253) << 16) + (x & 0xffff) * 1812433253) + i;
22
+ this.mt[i] = this.mt[i] >>> 0;
23
+ }
24
+ }
25
+
26
+ twist() {
27
+ for (let i = 0; i < this.N - this.M; i++) {
28
+ const y = (this.mt[i] & this.UPPER_MASK) | (this.mt[i + 1] & this.LOWER_MASK);
29
+ this.mt[i] = this.mt[i + this.M] ^ (y >>> 1) ^ (y & 1 ? this.MATRIX_A : 0);
30
+ }
31
+ for (let i = this.N - this.M; i < this.N - 1; i++) {
32
+ const y = (this.mt[i] & this.UPPER_MASK) | (this.mt[i + 1] & this.LOWER_MASK);
33
+ this.mt[i] = this.mt[i + (this.M - this.N)] ^ (y >>> 1) ^ (y & 1 ? this.MATRIX_A : 0);
34
+ }
35
+ const y = (this.mt[this.N - 1] & this.UPPER_MASK) | (this.mt[0] & this.LOWER_MASK);
36
+ this.mt[this.N - 1] = this.mt[this.M - 1] ^ (y >>> 1) ^ (y & 1 ? this.MATRIX_A : 0);
37
+ this.mti = 0;
38
+ }
39
+
40
+ next() {
41
+ if (this.mti >= this.N) {
42
+ this.twist();
43
+ }
44
+
45
+ let y = this.mt[this.mti++];
46
+ y ^= y >>> 11;
47
+ y ^= (y << 7) & 0x9d2c5680;
48
+ y ^= (y << 15) & 0xefc60000;
49
+ y ^= y >>> 18;
50
+
51
+ return y >>> 0;
52
+ }
53
+
54
+ nextInt(max = 2147483647) {
55
+ if (max <= 0) {
56
+ throw new Error('max must be positive');
57
+ }
58
+
59
+ const limit = Math.floor(0xffffffff / max) * max;
60
+ let val;
61
+
62
+ do {
63
+ val = this.next();
64
+ } while (val >= limit);
65
+
66
+ return val % max;
67
+ }
68
+
69
+ nextFloat() {
70
+ const a = this.next() >>> 5;
71
+ const b = this.next() >>> 6;
72
+ return (a * 67108864.0 + b) * (1.0 / 9007199254740992.0);
73
+ }
74
+ }
@@ -0,0 +1,44 @@
1
+ export class PCG64 {
2
+ constructor(seed = 1n, inc = 1n) {
3
+ this.state = 0n;
4
+ this.inc = ((typeof inc === 'number' ? BigInt(inc) : inc) << 1n) | 1n;
5
+ this.step();
6
+ this.state += (typeof seed === 'number' ? BigInt(seed) : seed);
7
+ this.step();
8
+ }
9
+
10
+ step() {
11
+ this.state = (this.state * 6364136223846793005n + this.inc) & ((1n << 64n) - 1n);
12
+ }
13
+
14
+ next() {
15
+ const oldState = this.state;
16
+ this.step();
17
+
18
+ const xorShifted = ((oldState >> 18n) ^ oldState) >> 27n;
19
+ const rot = oldState >> 59n;
20
+ const result = (xorShifted >> rot) | ((xorShifted << (64n - rot)) & ((1n << 64n) - 1n));
21
+
22
+ return result;
23
+ }
24
+
25
+ nextInt(max = 2147483647) {
26
+ if (max <= 0) {
27
+ throw new Error('max must be positive');
28
+ }
29
+
30
+ let val = this.next() & 0x7fffffffffffffffn;
31
+ const limit = (0xffffffffffffffffn / BigInt(max)) * BigInt(max);
32
+
33
+ while (val >= limit) {
34
+ val = this.next() & 0x7fffffffffffffffn;
35
+ }
36
+
37
+ return Number(val % BigInt(max));
38
+ }
39
+
40
+ nextFloat() {
41
+ const val = this.next() & ((1n << 53n) - 1n);
42
+ return Number(val) / 9007199254740992.0;
43
+ }
44
+ }
@@ -0,0 +1,32 @@
1
+ export class Splitmix64 {
2
+ constructor(seed = 1) {
3
+ this.state = BigInt(seed);
4
+ }
5
+
6
+ next() {
7
+ let z = (this.state += 0x9e3779b97f4a7c15n);
8
+ z = (z ^ (z >> 30n)) * 0xbf58476d1ce4e5b9n;
9
+ z = z ^ (z >> 27n);
10
+ return z;
11
+ }
12
+
13
+ nextInt(max = 2147483647) {
14
+ if (max <= 0) {
15
+ throw new Error('max must be positive');
16
+ }
17
+
18
+ let val = this.next() & 0x7fffffffffffffffn;
19
+ const limit = (0xffffffffffffffffn / BigInt(max)) * BigInt(max);
20
+
21
+ while (val >= limit) {
22
+ val = this.next() & 0x7fffffffffffffffn;
23
+ }
24
+
25
+ return Number(val % BigInt(max));
26
+ }
27
+
28
+ nextFloat() {
29
+ const val = this.next() & ((1n << 53n) - 1n);
30
+ return Number(val) / 9007199254740992.0;
31
+ }
32
+ }
@@ -0,0 +1,24 @@
1
+ export class Tent {
2
+ constructor(seed = 0.5, mu = 1.95) {
3
+ this.x = Math.max(0.00001, Math.min(0.99999, seed));
4
+ this.mu = mu;
5
+ }
6
+
7
+ next() {
8
+ if (this.x < 0.5) {
9
+ this.x = this.mu * this.x;
10
+ } else {
11
+ this.x = this.mu * (1 - this.x);
12
+ }
13
+ this.x = Math.max(0.00001, Math.min(0.99999, this.x));
14
+ return this.x;
15
+ }
16
+
17
+ nextInt(max = 2147483647) {
18
+ return Math.floor(this.next() * max);
19
+ }
20
+
21
+ nextFloat() {
22
+ return this.next();
23
+ }
24
+ }