UNPKG

33.3 kBJavaScriptView Raw
1(function (global, factory) {
2 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
3 typeof define === 'function' && define.amd ? define(['exports'], factory) :
4 (global = global || self, factory(global.Random = {}));
5}(this, function (exports) { 'use strict';
6
7 var SMALLEST_UNSAFE_INTEGER = 0x20000000000000;
8 var LARGEST_SAFE_INTEGER = SMALLEST_UNSAFE_INTEGER - 1;
9 var UINT32_MAX = -1 >>> 0;
10 var UINT32_SIZE = UINT32_MAX + 1;
11 var INT32_SIZE = UINT32_SIZE / 2;
12 var INT32_MAX = INT32_SIZE - 1;
13 var UINT21_SIZE = 1 << 21;
14 var UINT21_MAX = UINT21_SIZE - 1;
15
16 /**
17 * Returns a value within [-0x80000000, 0x7fffffff]
18 */
19 function int32(engine) {
20 return engine.next() | 0;
21 }
22
23 function add(distribution, addend) {
24 if (addend === 0) {
25 return distribution;
26 }
27 else {
28 return function (engine) { return distribution(engine) + addend; };
29 }
30 }
31
32 /**
33 * Returns a value within [-0x20000000000000, 0x1fffffffffffff]
34 */
35 function int53(engine) {
36 var high = engine.next() | 0;
37 var low = engine.next() >>> 0;
38 return ((high & UINT21_MAX) * UINT32_SIZE +
39 low +
40 (high & UINT21_SIZE ? -SMALLEST_UNSAFE_INTEGER : 0));
41 }
42
43 /**
44 * Returns a value within [-0x20000000000000, 0x20000000000000]
45 */
46 function int53Full(engine) {
47 while (true) {
48 var high = engine.next() | 0;
49 if (high & 0x400000) {
50 if ((high & 0x7fffff) === 0x400000 && (engine.next() | 0) === 0) {
51 return SMALLEST_UNSAFE_INTEGER;
52 }
53 }
54 else {
55 var low = engine.next() >>> 0;
56 return ((high & UINT21_MAX) * UINT32_SIZE +
57 low +
58 (high & UINT21_SIZE ? -SMALLEST_UNSAFE_INTEGER : 0));
59 }
60 }
61 }
62
63 /**
64 * Returns a value within [0, 0xffffffff]
65 */
66 function uint32(engine) {
67 return engine.next() >>> 0;
68 }
69
70 /**
71 * Returns a value within [0, 0x1fffffffffffff]
72 */
73 function uint53(engine) {
74 var high = engine.next() & UINT21_MAX;
75 var low = engine.next() >>> 0;
76 return high * UINT32_SIZE + low;
77 }
78
79 /**
80 * Returns a value within [0, 0x20000000000000]
81 */
82 function uint53Full(engine) {
83 while (true) {
84 var high = engine.next() | 0;
85 if (high & UINT21_SIZE) {
86 if ((high & UINT21_MAX) === 0 && (engine.next() | 0) === 0) {
87 return SMALLEST_UNSAFE_INTEGER;
88 }
89 }
90 else {
91 var low = engine.next() >>> 0;
92 return (high & UINT21_MAX) * UINT32_SIZE + low;
93 }
94 }
95 }
96
97 function isPowerOfTwoMinusOne(value) {
98 return ((value + 1) & value) === 0;
99 }
100 function bitmask(masking) {
101 return function (engine) { return engine.next() & masking; };
102 }
103 function downscaleToLoopCheckedRange(range) {
104 var extendedRange = range + 1;
105 var maximum = extendedRange * Math.floor(UINT32_SIZE / extendedRange);
106 return function (engine) {
107 var value = 0;
108 do {
109 value = engine.next() >>> 0;
110 } while (value >= maximum);
111 return value % extendedRange;
112 };
113 }
114 function downscaleToRange(range) {
115 if (isPowerOfTwoMinusOne(range)) {
116 return bitmask(range);
117 }
118 else {
119 return downscaleToLoopCheckedRange(range);
120 }
121 }
122 function isEvenlyDivisibleByMaxInt32(value) {
123 return (value | 0) === 0;
124 }
125 function upscaleWithHighMasking(masking) {
126 return function (engine) {
127 var high = engine.next() & masking;
128 var low = engine.next() >>> 0;
129 return high * UINT32_SIZE + low;
130 };
131 }
132 function upscaleToLoopCheckedRange(extendedRange) {
133 var maximum = extendedRange * Math.floor(SMALLEST_UNSAFE_INTEGER / extendedRange);
134 return function (engine) {
135 var ret = 0;
136 do {
137 var high = engine.next() & UINT21_MAX;
138 var low = engine.next() >>> 0;
139 ret = high * UINT32_SIZE + low;
140 } while (ret >= maximum);
141 return ret % extendedRange;
142 };
143 }
144 function upscaleWithinU53(range) {
145 var extendedRange = range + 1;
146 if (isEvenlyDivisibleByMaxInt32(extendedRange)) {
147 var highRange = ((extendedRange / UINT32_SIZE) | 0) - 1;
148 if (isPowerOfTwoMinusOne(highRange)) {
149 return upscaleWithHighMasking(highRange);
150 }
151 }
152 return upscaleToLoopCheckedRange(extendedRange);
153 }
154 function upscaleWithinI53AndLoopCheck(min, max) {
155 return function (engine) {
156 var ret = 0;
157 do {
158 var high = engine.next() | 0;
159 var low = engine.next() >>> 0;
160 ret =
161 (high & UINT21_MAX) * UINT32_SIZE +
162 low +
163 (high & UINT21_SIZE ? -SMALLEST_UNSAFE_INTEGER : 0);
164 } while (ret < min || ret > max);
165 return ret;
166 };
167 }
168 /**
169 * Returns a Distribution to return a value within [min, max]
170 * @param min The minimum integer value, inclusive. No less than -0x20000000000000.
171 * @param max The maximum integer value, inclusive. No greater than 0x20000000000000.
172 */
173 function integer(min, max) {
174 min = Math.floor(min);
175 max = Math.floor(max);
176 if (min < -SMALLEST_UNSAFE_INTEGER || !isFinite(min)) {
177 throw new RangeError("Expected min to be at least " + -SMALLEST_UNSAFE_INTEGER);
178 }
179 else if (max > SMALLEST_UNSAFE_INTEGER || !isFinite(max)) {
180 throw new RangeError("Expected max to be at most " + SMALLEST_UNSAFE_INTEGER);
181 }
182 var range = max - min;
183 if (range <= 0 || !isFinite(range)) {
184 return function () { return min; };
185 }
186 else if (range === UINT32_MAX) {
187 if (min === 0) {
188 return uint32;
189 }
190 else {
191 return add(int32, min + INT32_SIZE);
192 }
193 }
194 else if (range < UINT32_MAX) {
195 return add(downscaleToRange(range), min);
196 }
197 else if (range === LARGEST_SAFE_INTEGER) {
198 return add(uint53, min);
199 }
200 else if (range < LARGEST_SAFE_INTEGER) {
201 return add(upscaleWithinU53(range), min);
202 }
203 else if (max - 1 - min === LARGEST_SAFE_INTEGER) {
204 return add(uint53Full, min);
205 }
206 else if (min === -SMALLEST_UNSAFE_INTEGER &&
207 max === SMALLEST_UNSAFE_INTEGER) {
208 return int53Full;
209 }
210 else if (min === -SMALLEST_UNSAFE_INTEGER && max === LARGEST_SAFE_INTEGER) {
211 return int53;
212 }
213 else if (min === -LARGEST_SAFE_INTEGER && max === SMALLEST_UNSAFE_INTEGER) {
214 return add(int53, 1);
215 }
216 else if (max === SMALLEST_UNSAFE_INTEGER) {
217 return add(upscaleWithinI53AndLoopCheck(min - 1, max - 1), 1);
218 }
219 else {
220 return upscaleWithinI53AndLoopCheck(min, max);
221 }
222 }
223
224 function isLeastBitTrue(engine) {
225 return (engine.next() & 1) === 1;
226 }
227 function lessThan(distribution, value) {
228 return function (engine) { return distribution(engine) < value; };
229 }
230 function probability(percentage) {
231 if (percentage <= 0) {
232 return function () { return false; };
233 }
234 else if (percentage >= 1) {
235 return function () { return true; };
236 }
237 else {
238 var scaled = percentage * UINT32_SIZE;
239 if (scaled % 1 === 0) {
240 return lessThan(int32, (scaled - INT32_SIZE) | 0);
241 }
242 else {
243 return lessThan(uint53, Math.round(percentage * SMALLEST_UNSAFE_INTEGER));
244 }
245 }
246 }
247 function bool(numerator, denominator) {
248 if (denominator == null) {
249 if (numerator == null) {
250 return isLeastBitTrue;
251 }
252 return probability(numerator);
253 }
254 else {
255 if (numerator <= 0) {
256 return function () { return false; };
257 }
258 else if (numerator >= denominator) {
259 return function () { return true; };
260 }
261 return lessThan(integer(0, denominator - 1), numerator);
262 }
263 }
264
265 /**
266 * Returns a Distribution that returns a random `Date` within the inclusive
267 * range of [`start`, `end`].
268 * @param start The minimum `Date`
269 * @param end The maximum `Date`
270 */
271 function date(start, end) {
272 var distribution = integer(+start, +end);
273 return function (engine) { return new Date(distribution(engine)); };
274 }
275
276 /**
277 * Returns a Distribution to return a value within [1, sideCount]
278 * @param sideCount The number of sides of the die
279 */
280 function die(sideCount) {
281 return integer(1, sideCount);
282 }
283
284 /**
285 * Returns a distribution that returns an array of length `dieCount` of values
286 * within [1, `sideCount`]
287 * @param sideCount The number of sides of each die
288 * @param dieCount The number of dice
289 */
290 function dice(sideCount, dieCount) {
291 var distribution = die(sideCount);
292 return function (engine) {
293 var result = [];
294 for (var i = 0; i < dieCount; ++i) {
295 result.push(distribution(engine));
296 }
297 return result;
298 };
299 }
300
301 // tslint:disable:unified-signatures
302 // has 2**x chars, for faster uniform distribution
303 var DEFAULT_STRING_POOL = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-";
304 function string(pool) {
305 if (pool === void 0) { pool = DEFAULT_STRING_POOL; }
306 var poolLength = pool.length;
307 if (!poolLength) {
308 throw new Error("Expected pool not to be an empty string");
309 }
310 var distribution = integer(0, poolLength - 1);
311 return function (engine, length) {
312 var result = "";
313 for (var i = 0; i < length; ++i) {
314 var j = distribution(engine);
315 result += pool.charAt(j);
316 }
317 return result;
318 };
319 }
320
321 var LOWER_HEX_POOL = "0123456789abcdef";
322 var lowerHex = string(LOWER_HEX_POOL);
323 var upperHex = string(LOWER_HEX_POOL.toUpperCase());
324 /**
325 * Returns a Distribution that returns a random string comprised of numbers
326 * or the characters `abcdef` (or `ABCDEF`) of length `length`.
327 * @param length Length of the result string
328 * @param uppercase Whether the string should use `ABCDEF` instead of `abcdef`
329 */
330 function hex(uppercase) {
331 if (uppercase) {
332 return upperHex;
333 }
334 else {
335 return lowerHex;
336 }
337 }
338
339 function convertSliceArgument(value, length) {
340 if (value < 0) {
341 return Math.max(value + length, 0);
342 }
343 else {
344 return Math.min(value, length);
345 }
346 }
347
348 function toInteger(value) {
349 var num = +value;
350 if (num < 0) {
351 return Math.ceil(num);
352 }
353 else {
354 return Math.floor(num);
355 }
356 }
357
358 /**
359 * Returns a random value within the provided `source` within the sliced
360 * bounds of `begin` and `end`.
361 * @param source an array of items to pick from
362 * @param begin the beginning slice index (defaults to `0`)
363 * @param end the ending slice index (defaults to `source.length`)
364 */
365 function pick(engine, source, begin, end) {
366 var length = source.length;
367 if (length === 0) {
368 throw new RangeError("Cannot pick from an empty array");
369 }
370 var start = begin == null ? 0 : convertSliceArgument(toInteger(begin), length);
371 var finish = end === void 0 ? length : convertSliceArgument(toInteger(end), length);
372 if (start >= finish) {
373 throw new RangeError("Cannot pick between bounds " + start + " and " + finish);
374 }
375 var distribution = integer(start, finish - 1);
376 return source[distribution(engine)];
377 }
378
379 function multiply(distribution, multiplier) {
380 if (multiplier === 1) {
381 return distribution;
382 }
383 else if (multiplier === 0) {
384 return function () { return 0; };
385 }
386 else {
387 return function (engine) { return distribution(engine) * multiplier; };
388 }
389 }
390
391 /**
392 * Returns a floating-point value within [0.0, 1.0)
393 */
394 function realZeroToOneExclusive(engine) {
395 return uint53(engine) / SMALLEST_UNSAFE_INTEGER;
396 }
397
398 /**
399 * Returns a floating-point value within [0.0, 1.0]
400 */
401 function realZeroToOneInclusive(engine) {
402 return uint53Full(engine) / SMALLEST_UNSAFE_INTEGER;
403 }
404
405 /**
406 * Returns a floating-point value within [min, max) or [min, max]
407 * @param min The minimum floating-point value, inclusive.
408 * @param max The maximum floating-point value.
409 * @param inclusive If true, `max` will be inclusive.
410 */
411 function real(min, max, inclusive) {
412 if (inclusive === void 0) { inclusive = false; }
413 if (!isFinite(min)) {
414 throw new RangeError("Expected min to be a finite number");
415 }
416 else if (!isFinite(max)) {
417 throw new RangeError("Expected max to be a finite number");
418 }
419 return add(multiply(inclusive ? realZeroToOneInclusive : realZeroToOneExclusive, max - min), min);
420 }
421
422 var sliceArray = Array.prototype.slice;
423
424 /**
425 * Shuffles an array in-place
426 * @param engine The Engine to use when choosing random values
427 * @param array The array to shuffle
428 * @param downTo minimum index to shuffle. Only used internally.
429 */
430 function shuffle(engine, array, downTo) {
431 if (downTo === void 0) { downTo = 0; }
432 var length = array.length;
433 if (length) {
434 for (var i = (length - 1) >>> 0; i > downTo; --i) {
435 var distribution = integer(0, i);
436 var j = distribution(engine);
437 if (i !== j) {
438 var tmp = array[i];
439 array[i] = array[j];
440 array[j] = tmp;
441 }
442 }
443 }
444 return array;
445 }
446
447 /**
448 * From the population array, produce an array with sampleSize elements that
449 * are randomly chosen without repeats.
450 * @param engine The Engine to use when choosing random values
451 * @param population An array that has items to choose a sample from
452 * @param sampleSize The size of the result array
453 */
454 function sample(engine, population, sampleSize) {
455 if (sampleSize < 0 ||
456 sampleSize > population.length ||
457 !isFinite(sampleSize)) {
458 throw new RangeError("Expected sampleSize to be within 0 and the length of the population");
459 }
460 if (sampleSize === 0) {
461 return [];
462 }
463 var clone = sliceArray.call(population);
464 var length = clone.length;
465 if (length === sampleSize) {
466 return shuffle(engine, clone, 0);
467 }
468 var tailLength = length - sampleSize;
469 return shuffle(engine, clone, tailLength - 1).slice(tailLength);
470 }
471
472 var stringRepeat = (function () {
473 try {
474 if ("x".repeat(3) === "xxx") {
475 return function (pattern, count) {
476 return pattern.repeat(count);
477 };
478 }
479 }
480 catch (_) {
481 // nothing to do here
482 }
483 return function (pattern, count) {
484 var result = "";
485 while (count > 0) {
486 if (count & 1) {
487 result += pattern;
488 }
489 count >>= 1;
490 pattern += pattern;
491 }
492 return result;
493 };
494 })();
495
496 function zeroPad(text, zeroCount) {
497 return stringRepeat("0", zeroCount - text.length) + text;
498 }
499 /**
500 * Returns a Universally Unique Identifier Version 4.
501 *
502 * See http://en.wikipedia.org/wiki/Universally_unique_identifier
503 */
504 function uuid4(engine) {
505 var a = engine.next() >>> 0;
506 var b = engine.next() | 0;
507 var c = engine.next() | 0;
508 var d = engine.next() >>> 0;
509 return (zeroPad(a.toString(16), 8) +
510 "-" +
511 zeroPad((b & 0xffff).toString(16), 4) +
512 "-" +
513 zeroPad((((b >> 4) & 0x0fff) | 0x4000).toString(16), 4) +
514 "-" +
515 zeroPad(((c & 0x3fff) | 0x8000).toString(16), 4) +
516 "-" +
517 zeroPad(((c >> 4) & 0xffff).toString(16), 4) +
518 zeroPad(d.toString(16), 8));
519 }
520
521 /**
522 * An int32-producing Engine that uses `Math.random()`
523 */
524 var nativeMath = {
525 next: function () {
526 return (Math.random() * UINT32_SIZE) | 0;
527 }
528 };
529
530 // tslint:disable:unified-signatures
531 /**
532 * A wrapper around an Engine that provides easy-to-use methods for
533 * producing values based on known distributions
534 */
535 var Random = /** @class */ (function () {
536 /**
537 * Creates a new Random wrapper
538 * @param engine The engine to use (defaults to a `Math.random`-based implementation)
539 */
540 function Random(engine) {
541 if (engine === void 0) { engine = nativeMath; }
542 this.engine = engine;
543 }
544 /**
545 * Returns a value within [-0x80000000, 0x7fffffff]
546 */
547 Random.prototype.int32 = function () {
548 return int32(this.engine);
549 };
550 /**
551 * Returns a value within [0, 0xffffffff]
552 */
553 Random.prototype.uint32 = function () {
554 return uint32(this.engine);
555 };
556 /**
557 * Returns a value within [0, 0x1fffffffffffff]
558 */
559 Random.prototype.uint53 = function () {
560 return uint53(this.engine);
561 };
562 /**
563 * Returns a value within [0, 0x20000000000000]
564 */
565 Random.prototype.uint53Full = function () {
566 return uint53Full(this.engine);
567 };
568 /**
569 * Returns a value within [-0x20000000000000, 0x1fffffffffffff]
570 */
571 Random.prototype.int53 = function () {
572 return int53(this.engine);
573 };
574 /**
575 * Returns a value within [-0x20000000000000, 0x20000000000000]
576 */
577 Random.prototype.int53Full = function () {
578 return int53Full(this.engine);
579 };
580 /**
581 * Returns a value within [min, max]
582 * @param min The minimum integer value, inclusive. No less than -0x20000000000000.
583 * @param max The maximum integer value, inclusive. No greater than 0x20000000000000.
584 */
585 Random.prototype.integer = function (min, max) {
586 return integer(min, max)(this.engine);
587 };
588 /**
589 * Returns a floating-point value within [0.0, 1.0]
590 */
591 Random.prototype.realZeroToOneInclusive = function () {
592 return realZeroToOneInclusive(this.engine);
593 };
594 /**
595 * Returns a floating-point value within [0.0, 1.0)
596 */
597 Random.prototype.realZeroToOneExclusive = function () {
598 return realZeroToOneExclusive(this.engine);
599 };
600 /**
601 * Returns a floating-point value within [min, max) or [min, max]
602 * @param min The minimum floating-point value, inclusive.
603 * @param max The maximum floating-point value.
604 * @param inclusive If true, `max` will be inclusive.
605 */
606 Random.prototype.real = function (min, max, inclusive) {
607 if (inclusive === void 0) { inclusive = false; }
608 return real(min, max, inclusive)(this.engine);
609 };
610 Random.prototype.bool = function (numerator, denominator) {
611 return bool(numerator, denominator)(this.engine);
612 };
613 /**
614 * Return a random value within the provided `source` within the sliced
615 * bounds of `begin` and `end`.
616 * @param source an array of items to pick from
617 * @param begin the beginning slice index (defaults to `0`)
618 * @param end the ending slice index (defaults to `source.length`)
619 */
620 Random.prototype.pick = function (source, begin, end) {
621 return pick(this.engine, source, begin, end);
622 };
623 /**
624 * Shuffles an array in-place
625 * @param array The array to shuffle
626 */
627 Random.prototype.shuffle = function (array) {
628 return shuffle(this.engine, array);
629 };
630 /**
631 * From the population array, returns an array with sampleSize elements that
632 * are randomly chosen without repeats.
633 * @param population An array that has items to choose a sample from
634 * @param sampleSize The size of the result array
635 */
636 Random.prototype.sample = function (population, sampleSize) {
637 return sample(this.engine, population, sampleSize);
638 };
639 /**
640 * Returns a value within [1, sideCount]
641 * @param sideCount The number of sides of the die
642 */
643 Random.prototype.die = function (sideCount) {
644 return die(sideCount)(this.engine);
645 };
646 /**
647 * Returns an array of length `dieCount` of values within [1, sideCount]
648 * @param sideCount The number of sides of each die
649 * @param dieCount The number of dice
650 */
651 Random.prototype.dice = function (sideCount, dieCount) {
652 return dice(sideCount, dieCount)(this.engine);
653 };
654 /**
655 * Returns a Universally Unique Identifier Version 4.
656 *
657 * See http://en.wikipedia.org/wiki/Universally_unique_identifier
658 */
659 Random.prototype.uuid4 = function () {
660 return uuid4(this.engine);
661 };
662 Random.prototype.string = function (length, pool) {
663 return string(pool)(this.engine, length);
664 };
665 /**
666 * Returns a random string comprised of numbers or the characters `abcdef`
667 * (or `ABCDEF`) of length `length`.
668 * @param length Length of the result string
669 * @param uppercase Whether the string should use `ABCDEF` instead of `abcdef`
670 */
671 Random.prototype.hex = function (length, uppercase) {
672 return hex(uppercase)(this.engine, length);
673 };
674 /**
675 * Returns a random `Date` within the inclusive range of [`start`, `end`].
676 * @param start The minimum `Date`
677 * @param end The maximum `Date`
678 */
679 Random.prototype.date = function (start, end) {
680 return date(start, end)(this.engine);
681 };
682 return Random;
683 }());
684
685 /**
686 * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int32Array
687 */
688 var I32Array = (function () {
689 try {
690 var buffer = new ArrayBuffer(4);
691 var view = new Int32Array(buffer);
692 view[0] = INT32_SIZE;
693 if (view[0] === -INT32_SIZE) {
694 return Int32Array;
695 }
696 }
697 catch (_) {
698 // nothing to do here
699 }
700 return Array;
701 })();
702
703 var data = null;
704 var COUNT = 128;
705 var index = COUNT;
706 /**
707 * An Engine that relies on the globally-available `crypto.getRandomValues`,
708 * which is typically available in modern browsers.
709 *
710 * See https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues
711 *
712 * If unavailable or otherwise non-functioning, then `browserCrypto` will
713 * likely `throw` on the first call to `next()`.
714 */
715 var browserCrypto = {
716 next: function () {
717 if (index >= COUNT) {
718 if (data === null) {
719 data = new I32Array(COUNT);
720 }
721 crypto.getRandomValues(data);
722 index = 0;
723 }
724 return data[index++] | 0;
725 }
726 };
727
728 /**
729 * Returns an array of random int32 values, based on current time
730 * and a random number engine
731 *
732 * @param engine an Engine to pull random values from, default `nativeMath`
733 * @param length the length of the Array, minimum 1, default 16
734 */
735 function createEntropy(engine, length) {
736 if (engine === void 0) { engine = nativeMath; }
737 if (length === void 0) { length = 16; }
738 var array = [];
739 array.push(new Date().getTime() | 0);
740 for (var i = 1; i < length; ++i) {
741 array[i] = engine.next() | 0;
742 }
743 return array;
744 }
745
746 /**
747 * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul
748 */
749 var imul = (function () {
750 try {
751 if (Math.imul(UINT32_MAX, 5) === -5) {
752 return Math.imul;
753 }
754 }
755 catch (_) {
756 // nothing to do here
757 }
758 var UINT16_MAX = 0xffff;
759 return function (a, b) {
760 var ah = (a >>> 16) & UINT16_MAX;
761 var al = a & UINT16_MAX;
762 var bh = (b >>> 16) & UINT16_MAX;
763 var bl = b & UINT16_MAX;
764 // the shift by 0 fixes the sign on the high part
765 // the final |0 converts the unsigned value into a signed value
766 return (al * bl + (((ah * bl + al * bh) << 16) >>> 0)) | 0;
767 };
768 })();
769
770 var ARRAY_SIZE = 624;
771 var ARRAY_MAX = ARRAY_SIZE - 1;
772 var M = 397;
773 var ARRAY_SIZE_MINUS_M = ARRAY_SIZE - M;
774 var A = 0x9908b0df;
775 /**
776 * An Engine that is a pseudorandom number generator using the Mersenne
777 * Twister algorithm based on the prime 2**19937 − 1
778 *
779 * See http://en.wikipedia.org/wiki/Mersenne_twister
780 */
781 var MersenneTwister19937 = /** @class */ (function () {
782 /**
783 * MersenneTwister19937 should not be instantiated directly.
784 * Instead, use the static methods `seed`, `seedWithArray`, or `autoSeed`.
785 */
786 function MersenneTwister19937() {
787 this.data = new I32Array(ARRAY_SIZE);
788 this.index = 0; // integer within [0, 624]
789 this.uses = 0;
790 }
791 /**
792 * Returns a MersenneTwister19937 seeded with an initial int32 value
793 * @param initial the initial seed value
794 */
795 MersenneTwister19937.seed = function (initial) {
796 return new MersenneTwister19937().seed(initial);
797 };
798 /**
799 * Returns a MersenneTwister19937 seeded with zero or more int32 values
800 * @param source A series of int32 values
801 */
802 MersenneTwister19937.seedWithArray = function (source) {
803 return new MersenneTwister19937().seedWithArray(source);
804 };
805 /**
806 * Returns a MersenneTwister19937 seeded with the current time and
807 * a series of natively-generated random values
808 */
809 MersenneTwister19937.autoSeed = function () {
810 return MersenneTwister19937.seedWithArray(createEntropy());
811 };
812 /**
813 * Returns the next int32 value of the sequence
814 */
815 MersenneTwister19937.prototype.next = function () {
816 if ((this.index | 0) >= ARRAY_SIZE) {
817 refreshData(this.data);
818 this.index = 0;
819 }
820 var value = this.data[this.index];
821 this.index = (this.index + 1) | 0;
822 this.uses += 1;
823 return temper(value) | 0;
824 };
825 /**
826 * Returns the number of times that the Engine has been used.
827 *
828 * This can be provided to an unused MersenneTwister19937 with the same
829 * seed, bringing it to the exact point that was left off.
830 */
831 MersenneTwister19937.prototype.getUseCount = function () {
832 return this.uses;
833 };
834 /**
835 * Discards one or more items from the engine
836 * @param count The count of items to discard
837 */
838 MersenneTwister19937.prototype.discard = function (count) {
839 if (count <= 0) {
840 return this;
841 }
842 this.uses += count;
843 if ((this.index | 0) >= ARRAY_SIZE) {
844 refreshData(this.data);
845 this.index = 0;
846 }
847 while (count + this.index > ARRAY_SIZE) {
848 count -= ARRAY_SIZE - this.index;
849 refreshData(this.data);
850 this.index = 0;
851 }
852 this.index = (this.index + count) | 0;
853 return this;
854 };
855 MersenneTwister19937.prototype.seed = function (initial) {
856 var previous = 0;
857 this.data[0] = previous = initial | 0;
858 for (var i = 1; i < ARRAY_SIZE; i = (i + 1) | 0) {
859 this.data[i] = previous =
860 (imul(previous ^ (previous >>> 30), 0x6c078965) + i) | 0;
861 }
862 this.index = ARRAY_SIZE;
863 this.uses = 0;
864 return this;
865 };
866 MersenneTwister19937.prototype.seedWithArray = function (source) {
867 this.seed(0x012bd6aa);
868 seedWithArray(this.data, source);
869 return this;
870 };
871 return MersenneTwister19937;
872 }());
873 function refreshData(data) {
874 var k = 0;
875 var tmp = 0;
876 for (; (k | 0) < ARRAY_SIZE_MINUS_M; k = (k + 1) | 0) {
877 tmp = (data[k] & INT32_SIZE) | (data[(k + 1) | 0] & INT32_MAX);
878 data[k] = data[(k + M) | 0] ^ (tmp >>> 1) ^ (tmp & 0x1 ? A : 0);
879 }
880 for (; (k | 0) < ARRAY_MAX; k = (k + 1) | 0) {
881 tmp = (data[k] & INT32_SIZE) | (data[(k + 1) | 0] & INT32_MAX);
882 data[k] =
883 data[(k - ARRAY_SIZE_MINUS_M) | 0] ^ (tmp >>> 1) ^ (tmp & 0x1 ? A : 0);
884 }
885 tmp = (data[ARRAY_MAX] & INT32_SIZE) | (data[0] & INT32_MAX);
886 data[ARRAY_MAX] = data[M - 1] ^ (tmp >>> 1) ^ (tmp & 0x1 ? A : 0);
887 }
888 function temper(value) {
889 value ^= value >>> 11;
890 value ^= (value << 7) & 0x9d2c5680;
891 value ^= (value << 15) & 0xefc60000;
892 return value ^ (value >>> 18);
893 }
894 function seedWithArray(data, source) {
895 var i = 1;
896 var j = 0;
897 var sourceLength = source.length;
898 var k = Math.max(sourceLength, ARRAY_SIZE) | 0;
899 var previous = data[0] | 0;
900 for (; (k | 0) > 0; --k) {
901 data[i] = previous =
902 ((data[i] ^ imul(previous ^ (previous >>> 30), 0x0019660d)) +
903 (source[j] | 0) +
904 (j | 0)) |
905 0;
906 i = (i + 1) | 0;
907 ++j;
908 if ((i | 0) > ARRAY_MAX) {
909 data[0] = data[ARRAY_MAX];
910 i = 1;
911 }
912 if (j >= sourceLength) {
913 j = 0;
914 }
915 }
916 for (k = ARRAY_MAX; (k | 0) > 0; --k) {
917 data[i] = previous =
918 ((data[i] ^ imul(previous ^ (previous >>> 30), 0x5d588b65)) - i) | 0;
919 i = (i + 1) | 0;
920 if ((i | 0) > ARRAY_MAX) {
921 data[0] = data[ARRAY_MAX];
922 i = 1;
923 }
924 }
925 data[0] = INT32_SIZE;
926 }
927
928 var data$1 = null;
929 var COUNT$1 = 128;
930 var index$1 = COUNT$1;
931 /**
932 * An Engine that relies on the node-available
933 * `require('crypto').randomBytes`, which has been available since 0.58.
934 *
935 * See https://nodejs.org/api/crypto.html#crypto_crypto_randombytes_size_callback
936 *
937 * If unavailable or otherwise non-functioning, then `nodeCrypto` will
938 * likely `throw` on the first call to `next()`.
939 */
940 var nodeCrypto = {
941 next: function () {
942 if (index$1 >= COUNT$1) {
943 data$1 = new Int32Array(new Int8Array(require("crypto").randomBytes(4 * COUNT$1)).buffer);
944 index$1 = 0;
945 }
946 return data$1[index$1++] | 0;
947 }
948 };
949
950 /**
951 * Returns a Distribution to random value within the provided `source`
952 * within the sliced bounds of `begin` and `end`.
953 * @param source an array of items to pick from
954 * @param begin the beginning slice index (defaults to `0`)
955 * @param end the ending slice index (defaults to `source.length`)
956 */
957 function picker(source, begin, end) {
958 var clone = sliceArray.call(source, begin, end);
959 if (clone.length === 0) {
960 throw new RangeError("Cannot pick from a source with no items");
961 }
962 var distribution = integer(0, clone.length - 1);
963 return function (engine) { return clone[distribution(engine)]; };
964 }
965
966 exports.Random = Random;
967 exports.browserCrypto = browserCrypto;
968 exports.nativeMath = nativeMath;
969 exports.MersenneTwister19937 = MersenneTwister19937;
970 exports.nodeCrypto = nodeCrypto;
971 exports.bool = bool;
972 exports.date = date;
973 exports.dice = dice;
974 exports.die = die;
975 exports.hex = hex;
976 exports.int32 = int32;
977 exports.int53 = int53;
978 exports.int53Full = int53Full;
979 exports.integer = integer;
980 exports.pick = pick;
981 exports.picker = picker;
982 exports.real = real;
983 exports.realZeroToOneExclusive = realZeroToOneExclusive;
984 exports.realZeroToOneInclusive = realZeroToOneInclusive;
985 exports.sample = sample;
986 exports.shuffle = shuffle;
987 exports.string = string;
988 exports.uint32 = uint32;
989 exports.uint53 = uint53;
990 exports.uint53Full = uint53Full;
991 exports.uuid4 = uuid4;
992 exports.createEntropy = createEntropy;
993
994 Object.defineProperty(exports, '__esModule', { value: true });
995
996}));
997//# sourceMappingURL=random-js.umd.js.map