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