@bcts/rand 1.0.0-alpha.9 → 1.0.0-beta.0
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/LICENSE +3 -2
- package/dist/index.cjs +243 -112
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +87 -91
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +87 -91
- package/dist/index.d.mts.map +1 -1
- package/dist/index.iife.js +286 -156
- package/dist/index.iife.js.map +1 -1
- package/dist/index.mjs +225 -110
- package/dist/index.mjs.map +1 -1
- package/package.json +14 -15
- package/src/index.ts +28 -5
- package/src/magnitude.ts +6 -0
- package/src/random-number-generator.ts +309 -159
- package/src/secure-random.ts +28 -18
- package/src/seeded-random.ts +9 -12
- package/src/widening.ts +6 -0
package/LICENSE
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
Copyright © 2023 Blockchain Commons, LLC
|
|
2
|
-
Copyright © 2025
|
|
1
|
+
Copyright © 2023-2026 Blockchain Commons, LLC
|
|
2
|
+
Copyright © 2025-2026 Parity Technologies
|
|
3
|
+
|
|
3
4
|
|
|
4
5
|
Redistribution and use in source and binary forms, with or without modification,
|
|
5
6
|
are permitted provided that the following conditions are met:
|
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
//#region src/widening.ts
|
|
3
3
|
/**
|
|
4
4
|
* Performs wide multiplication for unsigned integers.
|
|
@@ -52,10 +52,14 @@ function wideMulU64(a, b) {
|
|
|
52
52
|
const wide = (a & mask64) * (b & mask64);
|
|
53
53
|
return [wide & mask64, wide >> 64n];
|
|
54
54
|
}
|
|
55
|
-
|
|
56
55
|
//#endregion
|
|
57
56
|
//#region src/magnitude.ts
|
|
58
57
|
/**
|
|
58
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
59
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
60
|
+
*
|
|
61
|
+
*/
|
|
62
|
+
/**
|
|
59
63
|
* Converts a signed integer to its unsigned magnitude.
|
|
60
64
|
* For positive numbers, returns the number unchanged.
|
|
61
65
|
* For negative numbers, returns the absolute value (wrapping for MIN values).
|
|
@@ -108,10 +112,14 @@ function fromMagnitude64(magnitude) {
|
|
|
108
112
|
if ((maskedMag & signBit) !== 0n) return maskedMag - (1n << 64n);
|
|
109
113
|
return maskedMag;
|
|
110
114
|
}
|
|
111
|
-
|
|
112
115
|
//#endregion
|
|
113
116
|
//#region src/random-number-generator.ts
|
|
114
117
|
/**
|
|
118
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
119
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
120
|
+
*
|
|
121
|
+
*/
|
|
122
|
+
/**
|
|
115
123
|
* Returns a Uint8Array of random bytes of the given size.
|
|
116
124
|
*/
|
|
117
125
|
function rngRandomData(rng, size) {
|
|
@@ -126,121 +134,231 @@ function rngFillRandomData(rng, data) {
|
|
|
126
134
|
rng.fillRandomData(data);
|
|
127
135
|
}
|
|
128
136
|
/**
|
|
129
|
-
* Returns a random value
|
|
130
|
-
*
|
|
131
|
-
* Uses Lemire's "nearly divisionless" method for generating random
|
|
132
|
-
* integers in an interval. For a detailed explanation, see:
|
|
133
|
-
* https://arxiv.org/abs/1805.10941
|
|
134
|
-
*
|
|
135
|
-
* @param rng - The random number generator to use
|
|
136
|
-
* @param upperBound - The upper bound for the randomly generated value. Must be non-zero.
|
|
137
|
-
* @returns A random value in the range [0, upperBound). Every value in the range is equally likely.
|
|
137
|
+
* Returns a random `u8` value strictly less than `upperBound`.
|
|
138
138
|
*/
|
|
139
|
-
function
|
|
140
|
-
if (upperBound ===
|
|
141
|
-
const
|
|
142
|
-
let random = rng.nextU64() &
|
|
143
|
-
let m =
|
|
144
|
-
if (m[0] <
|
|
145
|
-
const t = (
|
|
139
|
+
function rngNextWithUpperBoundU8(rng, upperBound) {
|
|
140
|
+
if (upperBound === 0) throw new Error("upperBound must be non-zero");
|
|
141
|
+
const ub = upperBound & 255;
|
|
142
|
+
let random = Number(rng.nextU64() & 255n);
|
|
143
|
+
let m = wideMulU8(random, ub);
|
|
144
|
+
if (m[0] < ub) {
|
|
145
|
+
const t = (256 - ub & 255) % ub;
|
|
146
146
|
while (m[0] < t) {
|
|
147
|
-
random = rng.nextU64() &
|
|
148
|
-
m =
|
|
147
|
+
random = Number(rng.nextU64() & 255n);
|
|
148
|
+
m = wideMulU8(random, ub);
|
|
149
149
|
}
|
|
150
150
|
}
|
|
151
151
|
return m[1];
|
|
152
152
|
}
|
|
153
153
|
/**
|
|
154
|
-
* Returns a random
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
154
|
+
* Returns a random `u16` value strictly less than `upperBound`.
|
|
155
|
+
*/
|
|
156
|
+
function rngNextWithUpperBoundU16(rng, upperBound) {
|
|
157
|
+
if (upperBound === 0) throw new Error("upperBound must be non-zero");
|
|
158
|
+
const ub = upperBound & 65535;
|
|
159
|
+
let random = Number(rng.nextU64() & 65535n);
|
|
160
|
+
let m = wideMulU16(random, ub);
|
|
161
|
+
if (m[0] < ub) {
|
|
162
|
+
const t = (65536 - ub & 65535) % ub;
|
|
163
|
+
while (m[0] < t) {
|
|
164
|
+
random = Number(rng.nextU64() & 65535n);
|
|
165
|
+
m = wideMulU16(random, ub);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return m[1];
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Returns a random `u32` value strictly less than `upperBound`.
|
|
162
172
|
*/
|
|
163
173
|
function rngNextWithUpperBoundU32(rng, upperBound) {
|
|
164
174
|
if (upperBound === 0) throw new Error("upperBound must be non-zero");
|
|
165
|
-
const
|
|
166
|
-
|
|
167
|
-
let
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
const t = (bitmask + 1 - upperBoundU32 >>> 0) % upperBoundU32;
|
|
175
|
+
const ub = upperBound >>> 0;
|
|
176
|
+
let random = Number(rng.nextU64() & 4294967295n);
|
|
177
|
+
let m = wideMulU32(random, ub);
|
|
178
|
+
if (Number(m[0]) < ub) {
|
|
179
|
+
const t = (4294967296 - ub >>> 0) % ub;
|
|
171
180
|
while (Number(m[0]) < t) {
|
|
172
|
-
random = Number(rng.nextU64() &
|
|
173
|
-
m = wideMulU32(random,
|
|
181
|
+
random = Number(rng.nextU64() & 4294967295n);
|
|
182
|
+
m = wideMulU32(random, ub);
|
|
174
183
|
}
|
|
175
184
|
}
|
|
176
185
|
return Number(m[1]);
|
|
177
186
|
}
|
|
178
187
|
/**
|
|
179
|
-
* Returns a random value
|
|
180
|
-
* This matches Rust's behavior when called with i32 types.
|
|
181
|
-
*
|
|
182
|
-
* @param rng - The random number generator to use
|
|
183
|
-
* @param start - The lower bound (inclusive) as i32
|
|
184
|
-
* @param end - The upper bound (exclusive) as i32
|
|
185
|
-
* @returns A random i32 value within the bounds
|
|
188
|
+
* Returns a random `u64` value strictly less than `upperBound`.
|
|
186
189
|
*/
|
|
187
|
-
function
|
|
188
|
-
if (
|
|
189
|
-
const
|
|
190
|
-
const
|
|
191
|
-
|
|
192
|
-
|
|
190
|
+
function rngNextWithUpperBoundU64(rng, upperBound) {
|
|
191
|
+
if (upperBound === 0n) throw new Error("upperBound must be non-zero");
|
|
192
|
+
const mask64 = 18446744073709551615n;
|
|
193
|
+
const ub = upperBound & mask64;
|
|
194
|
+
let random = rng.nextU64() & mask64;
|
|
195
|
+
let m = wideMulU64(random, ub);
|
|
196
|
+
if (m[0] < ub) {
|
|
197
|
+
const t = (mask64 + 1n - ub & mask64) % ub;
|
|
198
|
+
while (m[0] < t) {
|
|
199
|
+
random = rng.nextU64() & mask64;
|
|
200
|
+
m = wideMulU64(random, ub);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return m[1];
|
|
193
204
|
}
|
|
194
205
|
/**
|
|
195
|
-
*
|
|
206
|
+
* Alias of `rngNextWithUpperBoundU64`. Kept for API backwards compatibility.
|
|
196
207
|
*
|
|
197
|
-
* @
|
|
198
|
-
* @param start - The lower bound (inclusive)
|
|
199
|
-
* @param end - The upper bound (exclusive)
|
|
200
|
-
* @returns A random value within the bounds of the range
|
|
208
|
+
* @deprecated Prefer the explicit-width name `rngNextWithUpperBoundU64`.
|
|
201
209
|
*/
|
|
202
|
-
|
|
210
|
+
const rngNextWithUpperBound = rngNextWithUpperBoundU64;
|
|
211
|
+
function fromU64ThrowsIfAbove(value, max) {
|
|
212
|
+
if (value > max) throw new Error("from_u64 conversion overflow");
|
|
213
|
+
return value;
|
|
214
|
+
}
|
|
215
|
+
/** Random `u8` in the half-open range [start, end). */
|
|
216
|
+
function rngNextInRangeU8(rng, start, end) {
|
|
217
|
+
if (start >= end) throw new Error("start must be less than end");
|
|
218
|
+
const lo = start & 255;
|
|
219
|
+
const delta = (end & 255) - lo & 255;
|
|
220
|
+
if (delta === 255) return Number(fromU64ThrowsIfAbove(rng.nextU64(), 255n));
|
|
221
|
+
return lo + rngNextWithUpperBoundU8(rng, delta) & 255;
|
|
222
|
+
}
|
|
223
|
+
/** Random `u16` in the half-open range [start, end). */
|
|
224
|
+
function rngNextInRangeU16(rng, start, end) {
|
|
225
|
+
if (start >= end) throw new Error("start must be less than end");
|
|
226
|
+
const lo = start & 65535;
|
|
227
|
+
const delta = (end & 65535) - lo & 65535;
|
|
228
|
+
if (delta === 65535) return Number(fromU64ThrowsIfAbove(rng.nextU64(), 65535n));
|
|
229
|
+
return lo + rngNextWithUpperBoundU16(rng, delta) & 65535;
|
|
230
|
+
}
|
|
231
|
+
/** Random `u32` in the half-open range [start, end). */
|
|
232
|
+
function rngNextInRangeU32(rng, start, end) {
|
|
203
233
|
if (start >= end) throw new Error("start must be less than end");
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
234
|
+
const lo = start >>> 0;
|
|
235
|
+
const delta = (end >>> 0) - lo >>> 0;
|
|
236
|
+
if (delta === 4294967295) return Number(fromU64ThrowsIfAbove(rng.nextU64(), 4294967295n));
|
|
237
|
+
return lo + rngNextWithUpperBoundU32(rng, delta) >>> 0;
|
|
238
|
+
}
|
|
239
|
+
/** Random `u64` in the half-open range [start, end). */
|
|
240
|
+
function rngNextInRangeU64(rng, start, end) {
|
|
241
|
+
if (start >= end) throw new Error("start must be less than end");
|
|
242
|
+
const mask64 = 18446744073709551615n;
|
|
243
|
+
const delta = end - start & mask64;
|
|
244
|
+
if (delta === mask64) return rng.nextU64();
|
|
245
|
+
return start + rngNextWithUpperBoundU64(rng, delta) & mask64;
|
|
207
246
|
}
|
|
208
247
|
/**
|
|
209
|
-
*
|
|
248
|
+
* Alias of `rngNextInRangeU64`. Kept for API backwards compatibility.
|
|
210
249
|
*
|
|
211
|
-
* @
|
|
212
|
-
* @param start - The lower bound (inclusive)
|
|
213
|
-
* @param end - The upper bound (inclusive)
|
|
214
|
-
* @returns A random value within the bounds of the range
|
|
250
|
+
* @deprecated Prefer the explicit-width name `rngNextInRangeU64`.
|
|
215
251
|
*/
|
|
216
|
-
|
|
252
|
+
const rngNextInRange = rngNextInRangeU64;
|
|
253
|
+
/** Random `i8` in the half-open range [start, end). */
|
|
254
|
+
function rngNextInRangeI8(rng, start, end) {
|
|
255
|
+
if (start >= end) throw new Error("start must be less than end");
|
|
256
|
+
const lo = start << 24 >> 24;
|
|
257
|
+
const delta = toMagnitude((end << 24 >> 24) - lo, 8);
|
|
258
|
+
if (delta === 255) return Number(fromU64ThrowsIfAbove(rng.nextU64(), 127n));
|
|
259
|
+
return lo + rngNextWithUpperBoundU8(rng, delta) << 24 >> 24;
|
|
260
|
+
}
|
|
261
|
+
/** Random `i16` in the half-open range [start, end). */
|
|
262
|
+
function rngNextInRangeI16(rng, start, end) {
|
|
263
|
+
if (start >= end) throw new Error("start must be less than end");
|
|
264
|
+
const lo = start << 16 >> 16;
|
|
265
|
+
const delta = toMagnitude((end << 16 >> 16) - lo, 16);
|
|
266
|
+
if (delta === 65535) return Number(fromU64ThrowsIfAbove(rng.nextU64(), 32767n));
|
|
267
|
+
return lo + rngNextWithUpperBoundU16(rng, delta) << 16 >> 16;
|
|
268
|
+
}
|
|
269
|
+
/** Random `i32` in the half-open range [start, end). */
|
|
270
|
+
function rngNextInRangeI32(rng, start, end) {
|
|
271
|
+
if (start >= end) throw new Error("start must be less than end");
|
|
272
|
+
const lo = start | 0;
|
|
273
|
+
const delta = toMagnitude((end | 0) - lo, 32);
|
|
274
|
+
if (delta === 4294967295) return Number(fromU64ThrowsIfAbove(rng.nextU64(), 2147483647n));
|
|
275
|
+
return lo + rngNextWithUpperBoundU32(rng, delta) | 0;
|
|
276
|
+
}
|
|
277
|
+
/** Random `i64` in the half-open range [start, end). */
|
|
278
|
+
function rngNextInRangeI64(rng, start, end) {
|
|
279
|
+
if (start >= end) throw new Error("start must be less than end");
|
|
280
|
+
const delta = toMagnitude64(end - start);
|
|
281
|
+
const mask64 = 18446744073709551615n;
|
|
282
|
+
if (delta === mask64) return fromU64ThrowsIfAbove(rng.nextU64(), 9223372036854775807n);
|
|
283
|
+
const random = rngNextWithUpperBoundU64(rng, delta);
|
|
284
|
+
return fromMagnitude64(toMagnitude64(start) + random & mask64);
|
|
285
|
+
}
|
|
286
|
+
/** Random `u8` in the closed range [start, end]. */
|
|
287
|
+
function rngNextInClosedRangeU8(rng, start, end) {
|
|
288
|
+
if (start > end) throw new Error("start must be less than or equal to end");
|
|
289
|
+
const lo = start & 255;
|
|
290
|
+
const delta = (end & 255) - lo & 255;
|
|
291
|
+
if (delta === 255) return Number(fromU64ThrowsIfAbove(rng.nextU64(), 255n));
|
|
292
|
+
return lo + rngNextWithUpperBoundU8(rng, delta + 1) & 255;
|
|
293
|
+
}
|
|
294
|
+
/** Random `u16` in the closed range [start, end]. */
|
|
295
|
+
function rngNextInClosedRangeU16(rng, start, end) {
|
|
296
|
+
if (start > end) throw new Error("start must be less than or equal to end");
|
|
297
|
+
const lo = start & 65535;
|
|
298
|
+
const delta = (end & 65535) - lo & 65535;
|
|
299
|
+
if (delta === 65535) return Number(fromU64ThrowsIfAbove(rng.nextU64(), 65535n));
|
|
300
|
+
return lo + rngNextWithUpperBoundU16(rng, delta + 1) & 65535;
|
|
301
|
+
}
|
|
302
|
+
/** Random `u32` in the closed range [start, end]. */
|
|
303
|
+
function rngNextInClosedRangeU32(rng, start, end) {
|
|
304
|
+
if (start > end) throw new Error("start must be less than or equal to end");
|
|
305
|
+
const lo = start >>> 0;
|
|
306
|
+
const delta = (end >>> 0) - lo >>> 0;
|
|
307
|
+
if (delta === 4294967295) return Number(fromU64ThrowsIfAbove(rng.nextU64(), 4294967295n));
|
|
308
|
+
return lo + rngNextWithUpperBoundU32(rng, delta + 1) >>> 0;
|
|
309
|
+
}
|
|
310
|
+
/** Random `u64` in the closed range [start, end]. */
|
|
311
|
+
function rngNextInClosedRangeU64(rng, start, end) {
|
|
217
312
|
if (start > end) throw new Error("start must be less than or equal to end");
|
|
218
|
-
const
|
|
219
|
-
|
|
220
|
-
|
|
313
|
+
const mask64 = 18446744073709551615n;
|
|
314
|
+
const delta = end - start & mask64;
|
|
315
|
+
if (delta === mask64) return rng.nextU64();
|
|
316
|
+
return start + rngNextWithUpperBoundU64(rng, delta + 1n) & mask64;
|
|
221
317
|
}
|
|
222
318
|
/**
|
|
223
|
-
*
|
|
224
|
-
* Convenience function that handles signed 32-bit integers.
|
|
319
|
+
* Alias of `rngNextInClosedRangeU64`. Kept for API backwards compatibility.
|
|
225
320
|
*
|
|
226
|
-
* @
|
|
227
|
-
* @param start - The lower bound (inclusive) as i32
|
|
228
|
-
* @param end - The upper bound (inclusive) as i32
|
|
229
|
-
* @returns A random i32 value within the bounds of the range
|
|
321
|
+
* @deprecated Prefer the explicit-width name `rngNextInClosedRangeU64`.
|
|
230
322
|
*/
|
|
323
|
+
const rngNextInClosedRange = rngNextInClosedRangeU64;
|
|
324
|
+
/** Random `i8` in the closed range [start, end]. */
|
|
325
|
+
function rngNextInClosedRangeI8(rng, start, end) {
|
|
326
|
+
if (start > end) throw new Error("start must be less than or equal to end");
|
|
327
|
+
const lo = start << 24 >> 24;
|
|
328
|
+
const delta = toMagnitude((end << 24 >> 24) - lo, 8);
|
|
329
|
+
if (delta === 255) return Number(fromU64ThrowsIfAbove(rng.nextU64(), 127n));
|
|
330
|
+
return lo + rngNextWithUpperBoundU8(rng, delta + 1) << 24 >> 24;
|
|
331
|
+
}
|
|
332
|
+
/** Random `i16` in the closed range [start, end]. */
|
|
333
|
+
function rngNextInClosedRangeI16(rng, start, end) {
|
|
334
|
+
if (start > end) throw new Error("start must be less than or equal to end");
|
|
335
|
+
const lo = start << 16 >> 16;
|
|
336
|
+
const delta = toMagnitude((end << 16 >> 16) - lo, 16);
|
|
337
|
+
if (delta === 65535) return Number(fromU64ThrowsIfAbove(rng.nextU64(), 32767n));
|
|
338
|
+
return lo + rngNextWithUpperBoundU16(rng, delta + 1) << 16 >> 16;
|
|
339
|
+
}
|
|
340
|
+
/** Random `i32` in the closed range [start, end]. */
|
|
231
341
|
function rngNextInClosedRangeI32(rng, start, end) {
|
|
232
342
|
if (start > end) throw new Error("start must be less than or equal to end");
|
|
233
|
-
const
|
|
234
|
-
const delta = toMagnitude((end | 0) -
|
|
235
|
-
if (delta === 4294967295) return rng.
|
|
236
|
-
return
|
|
343
|
+
const lo = start | 0;
|
|
344
|
+
const delta = toMagnitude((end | 0) - lo, 32);
|
|
345
|
+
if (delta === 4294967295) return Number(fromU64ThrowsIfAbove(rng.nextU64(), 2147483647n));
|
|
346
|
+
return lo + rngNextWithUpperBoundU32(rng, delta + 1) | 0;
|
|
347
|
+
}
|
|
348
|
+
/** Random `i64` in the closed range [start, end]. */
|
|
349
|
+
function rngNextInClosedRangeI64(rng, start, end) {
|
|
350
|
+
if (start > end) throw new Error("start must be less than or equal to end");
|
|
351
|
+
const delta = toMagnitude64(end - start);
|
|
352
|
+
const mask64 = 18446744073709551615n;
|
|
353
|
+
if (delta === mask64) return fromU64ThrowsIfAbove(rng.nextU64(), 9223372036854775807n);
|
|
354
|
+
const random = rngNextWithUpperBoundU64(rng, delta + 1n);
|
|
355
|
+
return fromMagnitude64(toMagnitude64(start) + random & mask64);
|
|
237
356
|
}
|
|
238
357
|
/**
|
|
239
|
-
* Returns a fixed-size array
|
|
358
|
+
* Returns a random fixed-size byte array.
|
|
240
359
|
*
|
|
241
|
-
*
|
|
242
|
-
*
|
|
243
|
-
* @returns A Uint8Array of the specified size filled with random bytes
|
|
360
|
+
* Mirrors Rust's `rng_random_array<const N: usize>()` but takes the size at
|
|
361
|
+
* runtime since JavaScript lacks const generics.
|
|
244
362
|
*/
|
|
245
363
|
function rngRandomArray(rng, size) {
|
|
246
364
|
const data = new Uint8Array(size);
|
|
@@ -248,33 +366,26 @@ function rngRandomArray(rng, size) {
|
|
|
248
366
|
return data;
|
|
249
367
|
}
|
|
250
368
|
/**
|
|
251
|
-
* Returns a random boolean
|
|
252
|
-
*
|
|
253
|
-
* @param rng - The random number generator to use
|
|
254
|
-
* @returns A random boolean
|
|
369
|
+
* Returns a random boolean. Mirrors Rust's `rng_random_bool` which tests
|
|
370
|
+
* whether `next_u32()` is a multiple of 2.
|
|
255
371
|
*/
|
|
256
372
|
function rngRandomBool(rng) {
|
|
257
373
|
return (rng.nextU32() & 1) === 0;
|
|
258
374
|
}
|
|
259
375
|
/**
|
|
260
376
|
* Returns a random 32-bit unsigned integer.
|
|
261
|
-
*
|
|
262
|
-
* @param rng - The random number generator to use
|
|
263
|
-
* @returns A random u32 value
|
|
264
377
|
*/
|
|
265
378
|
function rngRandomU32(rng) {
|
|
266
379
|
return rng.nextU32();
|
|
267
380
|
}
|
|
268
|
-
|
|
269
381
|
//#endregion
|
|
270
382
|
//#region src/secure-random.ts
|
|
271
383
|
/**
|
|
272
|
-
*
|
|
273
|
-
*
|
|
384
|
+
* Returns the Web Crypto API for the current environment. Available natively
|
|
385
|
+
* in browsers and in Node.js >= 15 via `globalThis.crypto`.
|
|
274
386
|
*/
|
|
275
387
|
function getCrypto() {
|
|
276
|
-
if (typeof globalThis !== "undefined" && globalThis.crypto
|
|
277
|
-
if (typeof globalThis.crypto !== "undefined") return globalThis.crypto;
|
|
388
|
+
if (typeof globalThis !== "undefined" && globalThis.crypto != null) return globalThis.crypto;
|
|
278
389
|
throw new Error("No crypto API available in this environment");
|
|
279
390
|
}
|
|
280
391
|
/**
|
|
@@ -293,6 +404,9 @@ function fillRandomData(data) {
|
|
|
293
404
|
}
|
|
294
405
|
/**
|
|
295
406
|
* Returns the next cryptographically strong random 64-bit unsigned integer.
|
|
407
|
+
*
|
|
408
|
+
* This mirrors Rust's module-private `secure_random::next_u64()` and is not
|
|
409
|
+
* re-exported from the package surface (matches Rust `lib.rs` behavior).
|
|
296
410
|
*/
|
|
297
411
|
function nextU64() {
|
|
298
412
|
const data = new Uint8Array(8);
|
|
@@ -309,11 +423,12 @@ function nextU64() {
|
|
|
309
423
|
var SecureRandomNumberGenerator = class {
|
|
310
424
|
/**
|
|
311
425
|
* Returns the next random 32-bit unsigned integer.
|
|
426
|
+
*
|
|
427
|
+
* Mirrors Rust's `next_u32` impl which returns `next_u64() as u32` —
|
|
428
|
+
* the low 32 bits of a 64-bit draw.
|
|
312
429
|
*/
|
|
313
430
|
nextU32() {
|
|
314
|
-
|
|
315
|
-
fillRandomData(data);
|
|
316
|
-
return new DataView(data.buffer).getUint32(0, true) >>> 0;
|
|
431
|
+
return Number(this.nextU64() & 4294967295n) >>> 0;
|
|
317
432
|
}
|
|
318
433
|
/**
|
|
319
434
|
* Returns the next random 64-bit unsigned integer as a bigint.
|
|
@@ -340,7 +455,15 @@ var SecureRandomNumberGenerator = class {
|
|
|
340
455
|
fillRandomData(data);
|
|
341
456
|
}
|
|
342
457
|
};
|
|
343
|
-
|
|
458
|
+
/**
|
|
459
|
+
* Returns a thread-local cryptographically-strong RNG. Mirrors Rust's
|
|
460
|
+
* `thread_rng()`. In TypeScript there are no thread-locals, so this returns
|
|
461
|
+
* a fresh `SecureRandomNumberGenerator` — every instance backs onto the
|
|
462
|
+
* same Web Crypto source, so the effect is equivalent.
|
|
463
|
+
*/
|
|
464
|
+
function threadRng() {
|
|
465
|
+
return new SecureRandomNumberGenerator();
|
|
466
|
+
}
|
|
344
467
|
//#endregion
|
|
345
468
|
//#region src/seeded-random.ts
|
|
346
469
|
/**
|
|
@@ -376,7 +499,7 @@ function xoshiro256StarStar(state) {
|
|
|
376
499
|
* WARNING: This is NOT cryptographically secure and should only be used
|
|
377
500
|
* for testing purposes.
|
|
378
501
|
*/
|
|
379
|
-
var SeededRandomNumberGenerator = class
|
|
502
|
+
var SeededRandomNumberGenerator = class {
|
|
380
503
|
state;
|
|
381
504
|
/**
|
|
382
505
|
* Creates a new seeded random number generator.
|
|
@@ -399,15 +522,6 @@ var SeededRandomNumberGenerator = class SeededRandomNumberGenerator {
|
|
|
399
522
|
};
|
|
400
523
|
}
|
|
401
524
|
/**
|
|
402
|
-
* Creates a new seeded random number generator from a seed array.
|
|
403
|
-
* Convenience method that accepts numbers and converts to bigints.
|
|
404
|
-
*
|
|
405
|
-
* @param seed - Array of 4 64-bit unsigned integers
|
|
406
|
-
*/
|
|
407
|
-
static fromSeed(seed) {
|
|
408
|
-
return new SeededRandomNumberGenerator(seed);
|
|
409
|
-
}
|
|
410
|
-
/**
|
|
411
525
|
* Returns the next random 64-bit unsigned integer as a bigint.
|
|
412
526
|
*/
|
|
413
527
|
nextU64() {
|
|
@@ -448,7 +562,8 @@ var SeededRandomNumberGenerator = class SeededRandomNumberGenerator {
|
|
|
448
562
|
}
|
|
449
563
|
};
|
|
450
564
|
/**
|
|
451
|
-
*
|
|
565
|
+
* Standard test seed for `makeFakeRandomNumberGenerator`. Module-private to
|
|
566
|
+
* mirror Rust where the equivalent constant lives inside `mod tests`.
|
|
452
567
|
*/
|
|
453
568
|
const TEST_SEED = [
|
|
454
569
|
17295166580085024720n,
|
|
@@ -473,29 +588,44 @@ function makeFakeRandomNumberGenerator() {
|
|
|
473
588
|
function fakeRandomData(size) {
|
|
474
589
|
return makeFakeRandomNumberGenerator().randomData(size);
|
|
475
590
|
}
|
|
476
|
-
|
|
477
591
|
//#endregion
|
|
478
592
|
exports.SecureRandomNumberGenerator = SecureRandomNumberGenerator;
|
|
479
593
|
exports.SeededRandomNumberGenerator = SeededRandomNumberGenerator;
|
|
480
|
-
exports.TEST_SEED = TEST_SEED;
|
|
481
594
|
exports.fakeRandomData = fakeRandomData;
|
|
482
595
|
exports.fillRandomData = fillRandomData;
|
|
483
596
|
exports.fromMagnitude = fromMagnitude;
|
|
484
597
|
exports.fromMagnitude64 = fromMagnitude64;
|
|
485
598
|
exports.makeFakeRandomNumberGenerator = makeFakeRandomNumberGenerator;
|
|
486
|
-
exports.nextU64 = nextU64;
|
|
487
599
|
exports.randomData = randomData;
|
|
488
600
|
exports.rngFillRandomData = rngFillRandomData;
|
|
489
601
|
exports.rngNextInClosedRange = rngNextInClosedRange;
|
|
602
|
+
exports.rngNextInClosedRangeI16 = rngNextInClosedRangeI16;
|
|
490
603
|
exports.rngNextInClosedRangeI32 = rngNextInClosedRangeI32;
|
|
604
|
+
exports.rngNextInClosedRangeI64 = rngNextInClosedRangeI64;
|
|
605
|
+
exports.rngNextInClosedRangeI8 = rngNextInClosedRangeI8;
|
|
606
|
+
exports.rngNextInClosedRangeU16 = rngNextInClosedRangeU16;
|
|
607
|
+
exports.rngNextInClosedRangeU32 = rngNextInClosedRangeU32;
|
|
608
|
+
exports.rngNextInClosedRangeU64 = rngNextInClosedRangeU64;
|
|
609
|
+
exports.rngNextInClosedRangeU8 = rngNextInClosedRangeU8;
|
|
491
610
|
exports.rngNextInRange = rngNextInRange;
|
|
611
|
+
exports.rngNextInRangeI16 = rngNextInRangeI16;
|
|
492
612
|
exports.rngNextInRangeI32 = rngNextInRangeI32;
|
|
613
|
+
exports.rngNextInRangeI64 = rngNextInRangeI64;
|
|
614
|
+
exports.rngNextInRangeI8 = rngNextInRangeI8;
|
|
615
|
+
exports.rngNextInRangeU16 = rngNextInRangeU16;
|
|
616
|
+
exports.rngNextInRangeU32 = rngNextInRangeU32;
|
|
617
|
+
exports.rngNextInRangeU64 = rngNextInRangeU64;
|
|
618
|
+
exports.rngNextInRangeU8 = rngNextInRangeU8;
|
|
493
619
|
exports.rngNextWithUpperBound = rngNextWithUpperBound;
|
|
620
|
+
exports.rngNextWithUpperBoundU16 = rngNextWithUpperBoundU16;
|
|
494
621
|
exports.rngNextWithUpperBoundU32 = rngNextWithUpperBoundU32;
|
|
622
|
+
exports.rngNextWithUpperBoundU64 = rngNextWithUpperBoundU64;
|
|
623
|
+
exports.rngNextWithUpperBoundU8 = rngNextWithUpperBoundU8;
|
|
495
624
|
exports.rngRandomArray = rngRandomArray;
|
|
496
625
|
exports.rngRandomBool = rngRandomBool;
|
|
497
626
|
exports.rngRandomData = rngRandomData;
|
|
498
627
|
exports.rngRandomU32 = rngRandomU32;
|
|
628
|
+
exports.threadRng = threadRng;
|
|
499
629
|
exports.toMagnitude = toMagnitude;
|
|
500
630
|
exports.toMagnitude64 = toMagnitude64;
|
|
501
631
|
exports.wideMul = wideMul;
|
|
@@ -503,4 +633,5 @@ exports.wideMulU16 = wideMulU16;
|
|
|
503
633
|
exports.wideMulU32 = wideMulU32;
|
|
504
634
|
exports.wideMulU64 = wideMulU64;
|
|
505
635
|
exports.wideMulU8 = wideMulU8;
|
|
636
|
+
|
|
506
637
|
//# sourceMappingURL=index.cjs.map
|