@cloudglides/nox 1.1.3 → 1.1.4

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.
@@ -3,133 +3,137 @@
3
3
  min-height: 100vh;
4
4
  display: flex;
5
5
  flex-direction: column;
6
- background: linear-gradient(135deg, #1e1e2e 0%, #2d2d44 100%);
6
+ background: #ffffff;
7
+ color: #000000;
7
8
  }
8
9
 
9
10
  header {
10
- padding: 3rem 2rem;
11
+ padding: 2rem 2rem;
11
12
  text-align: center;
12
- border-bottom: 2px solid #646cff;
13
+ border-bottom: 1px solid #000000;
13
14
  }
14
15
 
15
16
  header h1 {
16
- font-size: 3rem;
17
+ font-size: 2rem;
17
18
  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;
19
+ color: #000000;
20
+ font-weight: 600;
21
+ letter-spacing: -0.5px;
22
22
  }
23
23
 
24
24
  header p {
25
- font-size: 1.1rem;
26
- color: #a0a0a0;
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 #444;
36
+ border-bottom: 1px solid #e0e0e0;
36
37
  }
37
38
 
38
39
  .tabs button {
39
- padding: 0.8rem 1.6rem;
40
- font-size: 1rem;
41
- border: 2px solid transparent;
42
- border-radius: 8px;
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.3s;
45
- color: #a0a0a0;
46
- background: #2d2d44;
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
- color: #646cff;
51
- border-color: #646cff;
52
+ background: #f5f5f5;
52
53
  }
53
54
 
54
55
  .tabs button.active {
55
- color: #fff;
56
- border-color: #646cff;
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: 900px;
63
+ max-width: 800px;
64
64
  margin: 0 auto;
65
65
  width: 100%;
66
66
  }
67
67
 
68
68
  .section {
69
- background: #2d2d44;
70
- padding: 2rem;
71
- border-radius: 12px;
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: #646cff;
76
+ color: #000000;
77
+ font-size: 1.3rem;
78
+ font-weight: 600;
78
79
  }
79
80
 
80
81
  .action-btn {
81
- background: linear-gradient(45deg, #646cff, #0ea5e9);
82
- color: white;
83
- padding: 0.8rem 2rem;
84
- font-size: 1rem;
82
+ background: #000000;
83
+ color: #ffffff;
84
+ padding: 0.7rem 1.8rem;
85
+ font-size: 0.9rem;
85
86
  border: none;
86
- border-radius: 8px;
87
+ border-radius: 0;
87
88
  cursor: pointer;
88
- font-weight: 600;
89
- transition: transform 0.2s, box-shadow 0.2s;
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
- transform: translateY(-2px);
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
- transform: translateY(0);
99
+ background: #000000;
100
100
  }
101
101
 
102
102
  .results {
103
- background: #1a1a2e;
103
+ background: #f8f8f8;
104
104
  padding: 1.5rem;
105
- border-radius: 8px;
106
- border-left: 4px solid #646cff;
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.8rem 0;
114
- line-height: 1.6;
114
+ margin: 0.6rem 0;
115
+ line-height: 1.5;
116
+ color: #000000;
115
117
  }
116
118
 
117
119
  .results strong {
118
- color: #646cff;
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 #444;
126
- color: #a0a0a0;
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: #646cff;
133
+ color: #000000;
131
134
  text-decoration: none;
132
- margin: 0 0.5rem;
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: 2rem;
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.6rem 1rem;
151
- font-size: 0.9rem;
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.5rem;
167
+ padding: 1.2rem;
160
168
  }
161
169
  }
@@ -1,9 +1,9 @@
1
1
  :root {
2
- font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
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: rgba(255, 255, 255, 0.87);
6
- background-color: #242424;
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: 8px;
28
- border: 1px solid transparent;
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: #1a1a1a;
35
+ background-color: #ffffff;
36
+ color: #000000;
34
37
  cursor: pointer;
35
- transition: border-color 0.25s;
38
+ transition: all 0.2s;
36
39
  }
37
40
 
38
41
  button:hover {
39
- border-color: #646cff;
42
+ background-color: #f5f5f5;
40
43
  }
41
44
 
42
45
  button:focus,
43
46
  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
- }
47
+ outline: 2px solid #000000;
48
+ outline-offset: 2px;
55
49
  }
@@ -5,7 +5,7 @@ export default defineConfig({
5
5
  plugins: [react()],
6
6
  build: {
7
7
  rollupOptions: {
8
- external: ['perf_hooks', 'crypto']
8
+ external: ['crypto']
9
9
  }
10
10
  }
11
11
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudglides/nox",
3
- "version": "1.1.3",
3
+ "version": "1.1.4",
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
- "scripts": {
16
- "test": "node test/basic.js",
17
- "bench": "node test/benchmark.js"
18
- },
19
- "keywords": ["random", "rng", "generator", "chaotic", "stochastic"],
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
- 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
- }
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
+ }
@@ -1,20 +1,44 @@
1
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
- }
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
+ }
@@ -55,8 +55,15 @@ export class MT19937 {
55
55
  if (max <= 0) {
56
56
  throw new Error('max must be positive');
57
57
  }
58
+ if (!Number.isInteger(max)) {
59
+ throw new TypeError('max must be an integer');
60
+ }
61
+
62
+ if (max > 0x100000000) {
63
+ throw new Error('max must be <= 2^32');
64
+ }
58
65
 
59
- const limit = Math.floor(0xffffffff / max) * max;
66
+ const limit = Math.floor((0x100000000 - (0x100000000 % max)) / max) * max;
60
67
  let val;
61
68
 
62
69
  do {
@@ -26,15 +26,20 @@ export class PCG64 {
26
26
  if (max <= 0) {
27
27
  throw new Error('max must be positive');
28
28
  }
29
+ if (!Number.isInteger(max)) {
30
+ throw new TypeError('max must be an integer');
31
+ }
29
32
 
30
- let val = this.next() & 0x7fffffffffffffffn;
31
- const limit = (0xffffffffffffffffn / BigInt(max)) * BigInt(max);
33
+ const maxBig = BigInt(max);
34
+ const mask = (1n << 64n) - 1n;
35
+ const limit = (mask / maxBig) * maxBig;
32
36
 
37
+ let val = this.next() & mask;
33
38
  while (val >= limit) {
34
- val = this.next() & 0x7fffffffffffffffn;
39
+ val = this.next() & mask;
35
40
  }
36
41
 
37
- return Number(val % BigInt(max));
42
+ return Number(val % maxBig);
38
43
  }
39
44
 
40
45
  nextFloat() {
@@ -14,15 +14,20 @@ export class Splitmix64 {
14
14
  if (max <= 0) {
15
15
  throw new Error('max must be positive');
16
16
  }
17
+ if (!Number.isInteger(max)) {
18
+ throw new TypeError('max must be an integer');
19
+ }
17
20
 
18
- let val = this.next() & 0x7fffffffffffffffn;
19
- const limit = (0xffffffffffffffffn / BigInt(max)) * BigInt(max);
21
+ const maxBig = BigInt(max);
22
+ const mask = (1n << 64n) - 1n;
23
+ const limit = (mask / maxBig) * maxBig;
20
24
 
25
+ let val = this.next() & mask;
21
26
  while (val >= limit) {
22
- val = this.next() & 0x7fffffffffffffffn;
27
+ val = this.next() & mask;
23
28
  }
24
29
 
25
- return Number(val % BigInt(max));
30
+ return Number(val % maxBig);
26
31
  }
27
32
 
28
33
  nextFloat() {
@@ -1,24 +1,36 @@
1
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
- }
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
+ }
@@ -20,15 +20,20 @@ export class Xorshift64 {
20
20
  if (max <= 0) {
21
21
  throw new Error('max must be positive');
22
22
  }
23
+ if (!Number.isInteger(max)) {
24
+ throw new TypeError('max must be an integer');
25
+ }
23
26
 
24
- let val = this.next() & 0x7fffffffffffffffn;
25
- const limit = (0xffffffffffffffffn / BigInt(max)) * BigInt(max);
27
+ const maxBig = BigInt(max);
28
+ const mask = (1n << 64n) - 1n;
29
+ const limit = (mask / maxBig) * maxBig;
26
30
 
31
+ let val = this.next() & mask;
27
32
  while (val >= limit) {
28
- val = this.next() & 0x7fffffffffffffffn;
33
+ val = this.next() & mask;
29
34
  }
30
35
 
31
- return Number(val % BigInt(max));
36
+ return Number(val % maxBig);
32
37
  }
33
38
 
34
39
  nextFloat() {
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
- gen: IGenerator;
11
- constructor(generator?: GeneratorConstructor | IGenerator, seed?: number | bigint);
12
- next(): any;
13
- nextInt(max?: number): number;
14
- nextFloat(): number;
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;
@@ -28,15 +28,17 @@ export class RNG {
28
28
  }
29
29
 
30
30
  int(min, max) {
31
- if (typeof min !== 'number' || typeof max !== 'number') {
32
- throw new TypeError('int() requires two number arguments');
33
- }
34
- if (!Number.isInteger(min) || !Number.isInteger(max)) {
35
- throw new TypeError('int() arguments must be integers');
36
- }
37
- if (min > max) [min, max] = [max, min];
38
- return Math.floor(this.nextFloat() * (max - min + 1)) + min;
39
- }
31
+ if (typeof min !== 'number' || typeof max !== 'number') {
32
+ throw new TypeError('int() requires two number arguments');
33
+ }
34
+ if (!Number.isInteger(min) || !Number.isInteger(max)) {
35
+ throw new TypeError('int() arguments must be integers');
36
+ }
37
+ if (min > max) [min, max] = [max, min];
38
+ const range = max - min + 1;
39
+ let val = Math.floor(this.nextFloat() * range);
40
+ return val + min;
41
+ }
40
42
 
41
43
  bool(probability = 0.5) {
42
44
  if (typeof probability !== 'number') {
package/src/rng.js CHANGED
@@ -28,15 +28,17 @@ export class RNG {
28
28
  }
29
29
 
30
30
  int(min, max) {
31
- if (typeof min !== 'number' || typeof max !== 'number') {
32
- throw new TypeError('int() requires two number arguments');
33
- }
34
- if (!Number.isInteger(min) || !Number.isInteger(max)) {
35
- throw new TypeError('int() arguments must be integers');
36
- }
37
- if (min > max) [min, max] = [max, min];
38
- return Math.floor(this.nextFloat() * (max - min + 1)) + min;
39
- }
31
+ if (typeof min !== 'number' || typeof max !== 'number') {
32
+ throw new TypeError('int() requires two number arguments');
33
+ }
34
+ if (!Number.isInteger(min) || !Number.isInteger(max)) {
35
+ throw new TypeError('int() arguments must be integers');
36
+ }
37
+ if (min > max) [min, max] = [max, min];
38
+ const range = max - min + 1;
39
+ let val = Math.floor(this.nextFloat() * range);
40
+ return val + min;
41
+ }
40
42
 
41
43
  bool(probability = 0.5) {
42
44
  if (typeof probability !== 'number') {