@cloudglides/nox 1.1.3 → 1.1.5
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/example/package.json +1 -1
- package/example/pnpm-lock.yaml +1006 -0
- package/example/src/App.css +63 -55
- package/example/src/index.css +13 -19
- package/example/vite.config.js +1 -1
- package/package.json +13 -8
- package/src/generators/logistic.js +30 -18
- package/src/generators/mixer.js +43 -19
- package/src/generators/mt19937.js +5 -1
- package/src/generators/pcg64.js +11 -6
- package/src/generators/splitmix64.js +11 -6
- package/src/generators/tent.js +35 -23
- package/src/generators/xorshift64.js +11 -6
- package/src/index.d.ts +5 -5
- package/src/rng.browser.js +81 -75
- package/src/rng.js +79 -73
- package/src/utils/distributions.js +21 -19
- package/src/utils/sampling.js +64 -56
- package/src/utils/sequence.js +45 -36
- package/src/utils/statistics.js +61 -45
- package/example/package-lock.json +0 -1636
package/example/src/App.css
CHANGED
|
@@ -3,133 +3,137 @@
|
|
|
3
3
|
min-height: 100vh;
|
|
4
4
|
display: flex;
|
|
5
5
|
flex-direction: column;
|
|
6
|
-
background:
|
|
6
|
+
background: #ffffff;
|
|
7
|
+
color: #000000;
|
|
7
8
|
}
|
|
8
9
|
|
|
9
10
|
header {
|
|
10
|
-
padding:
|
|
11
|
+
padding: 2rem 2rem;
|
|
11
12
|
text-align: center;
|
|
12
|
-
border-bottom:
|
|
13
|
+
border-bottom: 1px solid #000000;
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
header h1 {
|
|
16
|
-
font-size:
|
|
17
|
+
font-size: 2rem;
|
|
17
18
|
margin-bottom: 0.5rem;
|
|
18
|
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
background-clip: text;
|
|
19
|
+
color: #000000;
|
|
20
|
+
font-weight: 600;
|
|
21
|
+
letter-spacing: -0.5px;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
header p {
|
|
25
|
-
font-size:
|
|
26
|
-
color: #
|
|
25
|
+
font-size: 0.95rem;
|
|
26
|
+
color: #333333;
|
|
27
|
+
margin: 0;
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
.tabs {
|
|
30
31
|
display: flex;
|
|
31
32
|
gap: 1rem;
|
|
32
|
-
padding: 2rem;
|
|
33
|
+
padding: 1.5rem 2rem;
|
|
33
34
|
justify-content: center;
|
|
34
35
|
flex-wrap: wrap;
|
|
35
|
-
border-bottom: 1px solid #
|
|
36
|
+
border-bottom: 1px solid #e0e0e0;
|
|
36
37
|
}
|
|
37
38
|
|
|
38
39
|
.tabs button {
|
|
39
|
-
padding: 0.
|
|
40
|
-
font-size:
|
|
41
|
-
border:
|
|
42
|
-
border-radius:
|
|
40
|
+
padding: 0.6rem 1.2rem;
|
|
41
|
+
font-size: 0.9rem;
|
|
42
|
+
border: 1px solid #000000;
|
|
43
|
+
border-radius: 0;
|
|
43
44
|
cursor: pointer;
|
|
44
|
-
transition: all 0.
|
|
45
|
-
color: #
|
|
46
|
-
background: #
|
|
45
|
+
transition: all 0.2s;
|
|
46
|
+
color: #000000;
|
|
47
|
+
background: #ffffff;
|
|
48
|
+
font-weight: 500;
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
.tabs button:hover {
|
|
50
|
-
|
|
51
|
-
border-color: #646cff;
|
|
52
|
+
background: #f5f5f5;
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
.tabs button.active {
|
|
55
|
-
color: #
|
|
56
|
-
|
|
57
|
-
background: #1a1a2e;
|
|
56
|
+
color: #ffffff;
|
|
57
|
+
background: #000000;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
.content {
|
|
61
61
|
flex: 1;
|
|
62
62
|
padding: 2rem;
|
|
63
|
-
max-width:
|
|
63
|
+
max-width: 800px;
|
|
64
64
|
margin: 0 auto;
|
|
65
65
|
width: 100%;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
.section {
|
|
69
|
-
background: #
|
|
70
|
-
padding:
|
|
71
|
-
border
|
|
72
|
-
border: 1px solid #444;
|
|
69
|
+
background: #ffffff;
|
|
70
|
+
padding: 1.5rem;
|
|
71
|
+
border: 1px solid #e0e0e0;
|
|
73
72
|
}
|
|
74
73
|
|
|
75
74
|
.section h2 {
|
|
76
75
|
margin-bottom: 1.5rem;
|
|
77
|
-
color: #
|
|
76
|
+
color: #000000;
|
|
77
|
+
font-size: 1.3rem;
|
|
78
|
+
font-weight: 600;
|
|
78
79
|
}
|
|
79
80
|
|
|
80
81
|
.action-btn {
|
|
81
|
-
background:
|
|
82
|
-
color:
|
|
83
|
-
padding: 0.8rem
|
|
84
|
-
font-size:
|
|
82
|
+
background: #000000;
|
|
83
|
+
color: #ffffff;
|
|
84
|
+
padding: 0.7rem 1.8rem;
|
|
85
|
+
font-size: 0.9rem;
|
|
85
86
|
border: none;
|
|
86
|
-
border-radius:
|
|
87
|
+
border-radius: 0;
|
|
87
88
|
cursor: pointer;
|
|
88
|
-
font-weight:
|
|
89
|
-
transition:
|
|
89
|
+
font-weight: 500;
|
|
90
|
+
transition: all 0.2s;
|
|
90
91
|
margin-bottom: 1.5rem;
|
|
91
92
|
}
|
|
92
93
|
|
|
93
94
|
.action-btn:hover {
|
|
94
|
-
|
|
95
|
-
box-shadow: 0 10px 25px rgba(100, 108, 255, 0.3);
|
|
95
|
+
background: #333333;
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
.action-btn:active {
|
|
99
|
-
|
|
99
|
+
background: #000000;
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
.results {
|
|
103
|
-
background: #
|
|
103
|
+
background: #f8f8f8;
|
|
104
104
|
padding: 1.5rem;
|
|
105
|
-
border
|
|
106
|
-
border-left:
|
|
105
|
+
border: 1px solid #e0e0e0;
|
|
106
|
+
border-left: 3px solid #000000;
|
|
107
107
|
margin-top: 1rem;
|
|
108
108
|
font-family: 'Courier New', monospace;
|
|
109
|
+
font-size: 0.9rem;
|
|
109
110
|
word-break: break-all;
|
|
110
111
|
}
|
|
111
112
|
|
|
112
113
|
.results p {
|
|
113
|
-
margin: 0.
|
|
114
|
-
line-height: 1.
|
|
114
|
+
margin: 0.6rem 0;
|
|
115
|
+
line-height: 1.5;
|
|
116
|
+
color: #000000;
|
|
115
117
|
}
|
|
116
118
|
|
|
117
119
|
.results strong {
|
|
118
|
-
color: #
|
|
120
|
+
color: #000000;
|
|
119
121
|
font-weight: 600;
|
|
120
122
|
}
|
|
121
123
|
|
|
122
124
|
footer {
|
|
123
125
|
text-align: center;
|
|
124
|
-
padding: 2rem;
|
|
125
|
-
border-top: 1px solid #
|
|
126
|
-
color: #
|
|
126
|
+
padding: 1.5rem 2rem;
|
|
127
|
+
border-top: 1px solid #e0e0e0;
|
|
128
|
+
color: #666666;
|
|
129
|
+
font-size: 0.9rem;
|
|
127
130
|
}
|
|
128
131
|
|
|
129
132
|
footer a {
|
|
130
|
-
color: #
|
|
133
|
+
color: #000000;
|
|
131
134
|
text-decoration: none;
|
|
132
|
-
margin: 0 0.
|
|
135
|
+
margin: 0 0.3rem;
|
|
136
|
+
font-weight: 500;
|
|
133
137
|
}
|
|
134
138
|
|
|
135
139
|
footer a:hover {
|
|
@@ -138,7 +142,11 @@ footer a:hover {
|
|
|
138
142
|
|
|
139
143
|
@media (max-width: 768px) {
|
|
140
144
|
header h1 {
|
|
141
|
-
font-size:
|
|
145
|
+
font-size: 1.5rem;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
header {
|
|
149
|
+
padding: 1.5rem 1rem;
|
|
142
150
|
}
|
|
143
151
|
|
|
144
152
|
.tabs {
|
|
@@ -147,8 +155,8 @@ footer a:hover {
|
|
|
147
155
|
}
|
|
148
156
|
|
|
149
157
|
.tabs button {
|
|
150
|
-
padding: 0.
|
|
151
|
-
font-size: 0.
|
|
158
|
+
padding: 0.5rem 1rem;
|
|
159
|
+
font-size: 0.85rem;
|
|
152
160
|
}
|
|
153
161
|
|
|
154
162
|
.content {
|
|
@@ -156,6 +164,6 @@ footer a:hover {
|
|
|
156
164
|
}
|
|
157
165
|
|
|
158
166
|
.section {
|
|
159
|
-
padding: 1.
|
|
167
|
+
padding: 1.2rem;
|
|
160
168
|
}
|
|
161
169
|
}
|
package/example/src/index.css
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
:root {
|
|
2
|
-
font-family:
|
|
2
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
|
3
3
|
line-height: 1.5;
|
|
4
4
|
font-weight: 400;
|
|
5
|
-
color:
|
|
6
|
-
background-color: #
|
|
5
|
+
color: #000000;
|
|
6
|
+
background-color: #ffffff;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
* {
|
|
@@ -16,6 +16,8 @@ body {
|
|
|
16
16
|
margin: 0;
|
|
17
17
|
min-width: 320px;
|
|
18
18
|
min-height: 100vh;
|
|
19
|
+
background-color: #ffffff;
|
|
20
|
+
color: #000000;
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
#root {
|
|
@@ -24,32 +26,24 @@ body {
|
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
button {
|
|
27
|
-
border-radius:
|
|
28
|
-
border: 1px solid
|
|
29
|
+
border-radius: 0;
|
|
30
|
+
border: 1px solid #000000;
|
|
29
31
|
padding: 0.6em 1.2em;
|
|
30
32
|
font-size: 1em;
|
|
31
33
|
font-weight: 500;
|
|
32
34
|
font-family: inherit;
|
|
33
|
-
background-color: #
|
|
35
|
+
background-color: #ffffff;
|
|
36
|
+
color: #000000;
|
|
34
37
|
cursor: pointer;
|
|
35
|
-
transition:
|
|
38
|
+
transition: all 0.2s;
|
|
36
39
|
}
|
|
37
40
|
|
|
38
41
|
button:hover {
|
|
39
|
-
|
|
42
|
+
background-color: #f5f5f5;
|
|
40
43
|
}
|
|
41
44
|
|
|
42
45
|
button:focus,
|
|
43
46
|
button:focus-visible {
|
|
44
|
-
outline:
|
|
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
|
-
}
|
|
47
|
+
outline: 2px solid #000000;
|
|
48
|
+
outline-offset: 2px;
|
|
55
49
|
}
|
package/example/vite.config.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudglides/nox",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.5",
|
|
4
4
|
"description": "Unpredictable random number generator with multiple algorithms and distributions",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -12,15 +12,20 @@
|
|
|
12
12
|
"default": "./src/index.js"
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
"keywords": [
|
|
16
|
+
"random",
|
|
17
|
+
"rng",
|
|
18
|
+
"generator",
|
|
19
|
+
"chaotic",
|
|
20
|
+
"stochastic"
|
|
21
|
+
],
|
|
20
22
|
"author": "",
|
|
21
23
|
"license": "ISC",
|
|
22
|
-
"packageManager": "pnpm@10.24.0",
|
|
23
24
|
"publishConfig": {
|
|
24
25
|
"access": "public"
|
|
26
|
+
},
|
|
27
|
+
"scripts": {
|
|
28
|
+
"test": "node test/basic.js",
|
|
29
|
+
"bench": "node test/benchmark.js"
|
|
25
30
|
}
|
|
26
|
-
}
|
|
31
|
+
}
|
|
@@ -1,19 +1,31 @@
|
|
|
1
1
|
export class Logistic {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
2
|
+
constructor(seed = 0.5, r = 3.99) {
|
|
3
|
+
if (typeof seed !== 'number' || seed < 0 || seed > 1) {
|
|
4
|
+
throw new Error('seed must be between 0 and 1');
|
|
5
|
+
}
|
|
6
|
+
if (typeof r !== 'number' || r <= 0 || r > 4) {
|
|
7
|
+
throw new Error('r must be between 0 and 4');
|
|
8
|
+
}
|
|
9
|
+
this.x = seed;
|
|
10
|
+
this.r = r;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
next() {
|
|
14
|
+
this.x = this.r * this.x * (1 - this.x);
|
|
15
|
+
return this.x;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
nextInt(max = 2147483647) {
|
|
19
|
+
if (max <= 0) {
|
|
20
|
+
throw new Error('max must be positive');
|
|
21
|
+
}
|
|
22
|
+
if (!Number.isInteger(max)) {
|
|
23
|
+
throw new TypeError('max must be an integer');
|
|
24
|
+
}
|
|
25
|
+
return Math.floor(this.next() * max);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
nextFloat() {
|
|
29
|
+
return this.next();
|
|
30
|
+
}
|
|
31
|
+
}
|
package/src/generators/mixer.js
CHANGED
|
@@ -1,20 +1,44 @@
|
|
|
1
1
|
export class Mixer {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
2
|
+
constructor(rng1, rng2) {
|
|
3
|
+
if (!rng1 || typeof rng1.next !== 'function') {
|
|
4
|
+
throw new TypeError('rng1 must be a valid RNG instance');
|
|
5
|
+
}
|
|
6
|
+
if (!rng2 || typeof rng2.next !== 'function') {
|
|
7
|
+
throw new TypeError('rng2 must be a valid RNG instance');
|
|
8
|
+
}
|
|
9
|
+
this.rng1 = rng1;
|
|
10
|
+
this.rng2 = rng2;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
next() {
|
|
14
|
+
const v1 = this.rng1.next();
|
|
15
|
+
const v2 = this.rng2.next();
|
|
16
|
+
|
|
17
|
+
if (typeof v1 === 'bigint' && typeof v2 === 'bigint') {
|
|
18
|
+
return v1 ^ v2;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const b1 = typeof v1 === 'bigint' ? v1 : BigInt(v1);
|
|
22
|
+
const b2 = typeof v2 === 'bigint' ? v2 : BigInt(v2);
|
|
23
|
+
return b1 ^ b2;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
nextInt(max = 2147483647) {
|
|
27
|
+
if (max <= 0) {
|
|
28
|
+
throw new Error('max must be positive');
|
|
29
|
+
}
|
|
30
|
+
if (!Number.isInteger(max)) {
|
|
31
|
+
throw new TypeError('max must be an integer');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const v1 = this.rng1.nextInt(max);
|
|
35
|
+
const v2 = this.rng2.nextInt(max);
|
|
36
|
+
return (v1 + v2) % max;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
nextFloat() {
|
|
40
|
+
const f1 = this.rng1.nextFloat();
|
|
41
|
+
const f2 = this.rng2.nextFloat();
|
|
42
|
+
return Math.abs(f1 - f2);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -56,7 +56,11 @@ export class MT19937 {
|
|
|
56
56
|
throw new Error('max must be positive');
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
if (max < 65536) {
|
|
60
|
+
return this.next() & 0xFFFF % max;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const limit = Math.floor((0x100000000 / max)) * max;
|
|
60
64
|
let val;
|
|
61
65
|
|
|
62
66
|
do {
|
package/src/generators/pcg64.js
CHANGED
|
@@ -27,18 +27,23 @@ export class PCG64 {
|
|
|
27
27
|
throw new Error('max must be positive');
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
if (max < 65536) {
|
|
31
|
+
return Number(this.next() & 0xFFFFn) % max;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const maxBig = BigInt(max);
|
|
35
|
+
const limit = ((1n << 64n) / maxBig) * maxBig;
|
|
32
36
|
|
|
37
|
+
let val = this.next();
|
|
33
38
|
while (val >= limit) {
|
|
34
|
-
val = this.next()
|
|
39
|
+
val = this.next();
|
|
35
40
|
}
|
|
36
41
|
|
|
37
|
-
return Number(val %
|
|
42
|
+
return Number(val % maxBig);
|
|
38
43
|
}
|
|
39
44
|
|
|
40
45
|
nextFloat() {
|
|
41
|
-
const val = this.next() &
|
|
42
|
-
return Number(val) / 9007199254740992.0;
|
|
46
|
+
const val = this.next() & 0x1FFFFFFFFFFFFFn;
|
|
47
|
+
return Number(val) * (1.0 / 9007199254740992.0);
|
|
43
48
|
}
|
|
44
49
|
}
|
|
@@ -15,18 +15,23 @@ export class Splitmix64 {
|
|
|
15
15
|
throw new Error('max must be positive');
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
if (max < 65536) {
|
|
19
|
+
return Number(this.next() & 0xFFFFn) % max;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const maxBig = BigInt(max);
|
|
23
|
+
const limit = ((1n << 64n) / maxBig) * maxBig;
|
|
20
24
|
|
|
25
|
+
let val = this.next();
|
|
21
26
|
while (val >= limit) {
|
|
22
|
-
val = this.next()
|
|
27
|
+
val = this.next();
|
|
23
28
|
}
|
|
24
29
|
|
|
25
|
-
return Number(val %
|
|
30
|
+
return Number(val % maxBig);
|
|
26
31
|
}
|
|
27
32
|
|
|
28
33
|
nextFloat() {
|
|
29
|
-
const val = this.next() &
|
|
30
|
-
return Number(val) / 9007199254740992.0;
|
|
34
|
+
const val = this.next() & 0x1FFFFFFFFFFFFFn;
|
|
35
|
+
return Number(val) * (1.0 / 9007199254740992.0);
|
|
31
36
|
}
|
|
32
37
|
}
|
package/src/generators/tent.js
CHANGED
|
@@ -1,24 +1,36 @@
|
|
|
1
1
|
export class Tent {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
2
|
+
constructor(seed = 0.5, mu = 1.95) {
|
|
3
|
+
if (typeof seed !== 'number' || seed < 0 || seed > 1) {
|
|
4
|
+
throw new Error('seed must be between 0 and 1');
|
|
5
|
+
}
|
|
6
|
+
if (typeof mu !== 'number' || mu <= 0 || mu > 2) {
|
|
7
|
+
throw new Error('mu must be between 0 and 2');
|
|
8
|
+
}
|
|
9
|
+
this.x = Math.max(0.00001, Math.min(0.99999, seed));
|
|
10
|
+
this.mu = mu;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
next() {
|
|
14
|
+
if (this.x < 0.5) {
|
|
15
|
+
this.x = this.mu * this.x;
|
|
16
|
+
} else {
|
|
17
|
+
this.x = this.mu * (1 - this.x);
|
|
18
|
+
}
|
|
19
|
+
this.x = Math.max(0.00001, Math.min(0.99999, this.x));
|
|
20
|
+
return this.x;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
nextInt(max = 2147483647) {
|
|
24
|
+
if (max <= 0) {
|
|
25
|
+
throw new Error('max must be positive');
|
|
26
|
+
}
|
|
27
|
+
if (!Number.isInteger(max)) {
|
|
28
|
+
throw new TypeError('max must be an integer');
|
|
29
|
+
}
|
|
30
|
+
return Math.floor(this.next() * max);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
nextFloat() {
|
|
34
|
+
return this.next();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -21,18 +21,23 @@ export class Xorshift64 {
|
|
|
21
21
|
throw new Error('max must be positive');
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
if (max < 65536) {
|
|
25
|
+
return Number(this.next() & 0xFFFFn) % max;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const maxBig = BigInt(max);
|
|
29
|
+
const limit = ((1n << 64n) / maxBig) * maxBig;
|
|
26
30
|
|
|
31
|
+
let val = this.next();
|
|
27
32
|
while (val >= limit) {
|
|
28
|
-
val = this.next()
|
|
33
|
+
val = this.next();
|
|
29
34
|
}
|
|
30
35
|
|
|
31
|
-
return Number(val %
|
|
36
|
+
return Number(val % maxBig);
|
|
32
37
|
}
|
|
33
38
|
|
|
34
39
|
nextFloat() {
|
|
35
|
-
const val = this.next() &
|
|
36
|
-
return Number(val) / 9007199254740992.0;
|
|
40
|
+
const val = this.next() & 0x1FFFFFFFFFFFFFn;
|
|
41
|
+
return Number(val) * (1.0 / 9007199254740992.0);
|
|
37
42
|
}
|
|
38
43
|
}
|
package/src/index.d.ts
CHANGED
|
@@ -7,11 +7,11 @@ export interface IGenerator {
|
|
|
7
7
|
export type GeneratorConstructor = new (seed?: number | bigint) => IGenerator;
|
|
8
8
|
|
|
9
9
|
export class RNG {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
gen: IGenerator;
|
|
11
|
+
constructor(generator?: GeneratorConstructor | IGenerator, seed?: number | bigint);
|
|
12
|
+
next(): number | bigint;
|
|
13
|
+
nextInt(max?: number): number;
|
|
14
|
+
nextFloat(): number;
|
|
15
15
|
int(min: number, max: number): number;
|
|
16
16
|
bool(probability?: number): boolean;
|
|
17
17
|
range(min: number, max: number, step?: number): number;
|