import seedrandom from 'seedrandom'; function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } var RNG = /*#__PURE__*/function () { function RNG() {} var _proto = RNG.prototype; // eslint-disable-next-line @typescript-eslint/no-unused-vars _proto._seed = function _seed(seed, _opts) { // TODO: add entropy and stuff if (seed === (seed || 0)) { return seed; } else { var strSeed = '' + seed; var s = 0; for (var k = 0; k < strSeed.length; ++k) { s ^= strSeed.charCodeAt(k) | 0; } return s; } }; return RNG; }(); var RNGFunction = /*#__PURE__*/function (_RNG) { _inheritsLoose(RNGFunction, _RNG); function RNGFunction(thunk, opts) { var _this; _this = _RNG.call(this) || this; _this._rng = void 0; _this.seed(thunk, opts); return _this; } var _proto = RNGFunction.prototype; _proto.next = function next() { return this._rng(); } // eslint-disable-next-line @typescript-eslint/no-unused-vars ; _proto.seed = function seed(thunk, _opts) { this._rng = thunk; }; _proto.clone = function clone(_, opts) { return new RNGFunction(this._rng, opts); }; _createClass(RNGFunction, [{ key: "name", get: function get() { return 'function'; } }]); return RNGFunction; }(RNG); /** * Construct an RNG with variable inputs. Used in calls to Random constructor * @param {...*} args - Distribution-specific arguments * @return RNG * * @example * new Random(RNGFactory(...args)) */ var RNGFactory = (function () { var args = [].slice.call(arguments); var _args = args, _args$ = _args[0], arg0 = _args$ === void 0 ? 'default' : _args$; switch (typeof arg0) { case 'object': if (arg0 instanceof RNG) { return arg0; } break; case 'function': return new RNGFunction(arg0); case 'number': case 'string': default: return new RNGFunction(seedrandom.apply(void 0, args)); } throw new Error("invalid RNG \"" + arg0 + "\""); }); var uniform = (function (random, min, max) { if (min === void 0) { min = 0; } if (max === void 0) { max = 1; } return function () { return random.next() * (max - min) + min; }; }); function numberValidator(num) { return new NumberValidator(num); } var NumberValidator = function NumberValidator(num) { var _this = this; this.n = void 0; this.isInt = function () { if (Number.isInteger(_this.n)) { return _this; } throw new Error("Expected number to be an integer, got " + _this.n); }; this.isPositive = function () { if (_this.n > 0) { return _this; } throw new Error("Expected number to be positive, got " + _this.n); }; this.lessThan = function (v) { if (_this.n < v) { return _this; } throw new Error("Expected number to be less than " + v + ", got " + _this.n); }; this.greaterThanOrEqual = function (v) { if (_this.n >= v) { return _this; } throw new Error("Expected number to be greater than or equal to " + v + ", got " + _this.n); }; this.greaterThan = function (v) { if (_this.n > v) { return _this; } throw new Error("Expected number to be greater than " + v + ", got " + _this.n); }; this.n = num; }; var uniformInt = (function (random, min, max) { if (min === void 0) { min = 0; } if (max === void 0) { max = 1; } if (max === undefined) { max = min === undefined ? 1 : min; min = 0; } numberValidator(min).isInt(); numberValidator(max).isInt(); return function () { return Math.floor(random.next() * (max - min + 1) + min); }; }); var uniformBoolean = (function (random) { return function () { return random.next() >= 0.5; }; }); var normal = (function (random, mu, sigma) { if (mu === void 0) { mu = 0; } if (sigma === void 0) { sigma = 1; } return function () { var x, y, r; do { x = random.next() * 2 - 1; y = random.next() * 2 - 1; r = x * x + y * y; } while (!r || r > 1); return mu + sigma * y * Math.sqrt(-2 * Math.log(r) / r); }; }); var logNormal = (function (random, mu, sigma) { if (mu === void 0) { mu = 0; } if (sigma === void 0) { sigma = 1; } var normal = random.normal(mu, sigma); return function () { return Math.exp(normal()); }; }); var bernoulli = (function (random, p) { if (p === void 0) { p = 0.5; } numberValidator(p).greaterThanOrEqual(0).lessThan(1); return function () { return Math.floor(random.next() + p); }; }); var binomial = (function (random, n, p) { if (n === void 0) { n = 1; } if (p === void 0) { p = 0.5; } numberValidator(n).isInt().isPositive(); numberValidator(p).greaterThanOrEqual(0).lessThan(1); return function () { var i = 0; var x = 0; while (i++ < n) { if (random.next() < p) { x++; } } return x; }; }); var geometric = (function (random, p) { if (p === void 0) { p = 0.5; } numberValidator(p).greaterThan(0).lessThan(1); var invLogP = 1.0 / Math.log(1.0 - p); return function () { return Math.floor(1 + Math.log(random.next()) * invLogP); }; }); var logFactorialTable = [0.0, 0.0, 0.69314718055994529, 1.791759469228055, 3.1780538303479458, 4.7874917427820458, 6.5792512120101012, 8.5251613610654147, 10.604602902745251, 12.801827480081469]; var logFactorial = function logFactorial(k) { return logFactorialTable[k]; }; var logSqrt2PI = 0.91893853320467267; var poisson = (function (random, lambda) { if (lambda === void 0) { lambda = 1; } numberValidator(lambda).isPositive(); if (lambda < 10) { // inversion method var expMean = Math.exp(-lambda); return function () { var p = expMean; var x = 0; var u = random.next(); while (u > p) { u = u - p; p = lambda * p / ++x; } return x; }; } else { // generative method var smu = Math.sqrt(lambda); var b = 0.931 + 2.53 * smu; var a = -0.059 + 0.02483 * b; var invAlpha = 1.1239 + 1.1328 / (b - 3.4); var vR = 0.9277 - 3.6224 / (b - 2); return function () { while (true) { var u = void 0; var v = random.next(); if (v <= 0.86 * vR) { u = v / vR - 0.43; return Math.floor((2 * a / (0.5 - Math.abs(u)) + b) * u + lambda + 0.445); } if (v >= vR) { u = random.next() - 0.5; } else { u = v / vR - 0.93; u = (u < 0 ? -0.5 : 0.5) - u; v = random.next() * vR; } var us = 0.5 - Math.abs(u); if (us < 0.013 && v > us) { continue; } var k = Math.floor((2 * a / us + b) * u + lambda + 0.445); v = v * invAlpha / (a / (us * us) + b); if (k >= 10) { var t = (k + 0.5) * Math.log(lambda / k) - lambda - logSqrt2PI + k - (1 / 12.0 - (1 / 360.0 - 1 / (1260.0 * k * k)) / (k * k)) / k; if (Math.log(v * smu) <= t) { return k; } } else if (k >= 0) { var _logFactorial; var f = (_logFactorial = logFactorial(k)) != null ? _logFactorial : 0; if (Math.log(v) <= k * Math.log(lambda) - lambda - f) { return k; } } } }; } }); var exponential = (function (random, lambda) { if (lambda === void 0) { lambda = 1; } numberValidator(lambda).isPositive(); return function () { return -Math.log(1 - random.next()) / lambda; }; }); var irwinHall = (function (random, n) { if (n === void 0) { n = 1; } numberValidator(n).isInt().greaterThanOrEqual(0); return function () { var sum = 0; for (var i = 0; i < n; ++i) { sum += random.next(); } return sum; }; }); var bates = (function (random, n) { if (n === void 0) { n = 1; } numberValidator(n).isInt().isPositive(); var irwinHall = random.irwinHall(n); return function () { return irwinHall() / n; }; }); var pareto = (function (random, alpha) { if (alpha === void 0) { alpha = 1; } numberValidator(alpha).greaterThanOrEqual(0); var invAlpha = 1.0 / alpha; return function () { return 1.0 / Math.pow(1.0 - random.next(), invAlpha); }; }); var RNGMathRandom = /*#__PURE__*/function (_RNG) { _inheritsLoose(RNGMathRandom, _RNG); function RNGMathRandom() { return _RNG.apply(this, arguments) || this; } var _proto = RNGMathRandom.prototype; _proto.next = function next() { return Math.random(); } // eslint-disable-next-line @typescript-eslint/no-unused-vars ; _proto.seed = function seed(_seed, _opts) { // intentionally empty }; _proto.clone = function clone() { return new RNGMathRandom(); }; _createClass(RNGMathRandom, [{ key: "name", get: function get() { return 'default'; } }]); return RNGMathRandom; }(RNG); /** * Seedable random number generator supporting many common distributions. * * Defaults to Math.random as its underlying pseudorandom number generator. * * @name Random * @class * * @param {RNG|function} [rng=Math.random] - Underlying pseudorandom number generator. */ var Random = /*#__PURE__*/function () { function Random(rng) { var _this = this; this._rng = void 0; this._patch = void 0; this._cache = {}; this.next = function () { return _this._rng.next(); }; this["float"] = function (min, max) { return _this.uniform(min, max)(); }; this["int"] = function (min, max) { return _this.uniformInt(min, max)(); }; this.integer = function (min, max) { return _this.uniformInt(min, max)(); }; this.bool = function () { return _this.uniformBoolean()(); }; this["boolean"] = function () { return _this.uniformBoolean()(); }; this.uniform = function (min, max) { return _this._memoize('uniform', uniform, min, max); }; this.uniformInt = function (min, max) { return _this._memoize('uniformInt', uniformInt, min, max); }; this.uniformBoolean = function () { return _this._memoize('uniformBoolean', uniformBoolean); }; this.normal = function (mu, sigma) { return normal(_this, mu, sigma); }; this.logNormal = function (mu, sigma) { return logNormal(_this, mu, sigma); }; this.bernoulli = function (p) { return bernoulli(_this, p); }; this.binomial = function (n, p) { return binomial(_this, n, p); }; this.geometric = function (p) { return geometric(_this, p); }; this.poisson = function (lambda) { return poisson(_this, lambda); }; this.exponential = function (lambda) { return exponential(_this, lambda); }; this.irwinHall = function (n) { return irwinHall(_this, n); }; this.bates = function (n) { return bates(_this, n); }; this.pareto = function (alpha) { return pareto(_this, alpha); }; if (rng && rng instanceof RNG) { this.use(rng); } else { this.use(new RNGMathRandom()); } this._cache = {}; } /** * @member {RNG} Underlying pseudo-random number generator */ var _proto = Random.prototype; /** * Creates a new `Random` instance, optionally specifying parameters to * set a new seed. * * @see RNG.clone * * @param {string} [seed] - Optional seed for new RNG. * @param {object} [opts] - Optional config for new RNG options. * @return {Random} */ _proto.clone = function clone() { var args = [].slice.call(arguments); if (args.length) { return new Random(RNGFactory.apply(void 0, args)); } else { return new Random(this.rng.clone()); } } /** * Sets the underlying pseudorandom number generator used via * either an instance of `seedrandom`, a custom instance of RNG * (for PRNG plugins), or a string specifying the PRNG to use * along with an optional `seed` and `opts` to initialize the * RNG. * * @example * import random from 'random' * * random.use('example_seedrandom_string') * // or * random.use(seedrandom('kittens')) * // or * random.use(Math.random) * * @param {...*} args */; _proto.use = function use() { this._rng = RNGFactory.apply(void 0, [].slice.call(arguments)); } /** * Patches `Math.random` with this Random instance's PRNG. */; _proto.patch = function patch() { if (this._patch) { throw new Error('Math.random already patched'); } this._patch = Math.random; Math.random = this.uniform(); } /** * Restores a previously patched `Math.random` to its original value. */; _proto.unpatch = function unpatch() { if (this._patch) { Math.random = this._patch; delete this._patch; } } // -------------------------------------------------------------------------- // Uniform utility functions // -------------------------------------------------------------------------- /** * Convenience wrapper around `this.rng.next()` * * Returns a floating point number in [0, 1). * * @return {number} */; /** * Returns an item chosen uniformly at trandom from the given array. * * Convence wrapper around `random.uniformInt()` * * @param {Array} [array] - Lower bound (integer, inclusive) * @return {T | undefined} */ _proto.choice = function choice(array) { if (!Array.isArray(array)) { throw new Error("Random.choice expected input to be an array, got " + typeof array); } var length = array == null ? void 0 : array.length; if (length > 0) { var index = this.uniformInt(0, length - 1)(); return array[index]; } else { return undefined; } } // -------------------------------------------------------------------------- // Uniform distributions // -------------------------------------------------------------------------- /** * Generates a [Continuous uniform distribution](https://en.wikipedia.org/wiki/Uniform_distribution_(continuous)). * * @param {number} [min=0] - Lower bound (float, inclusive) * @param {number} [max=1] - Upper bound (float, exclusive) * @return {function} */; // -------------------------------------------------------------------------- // Internal // -------------------------------------------------------------------------- /** * Memoizes distributions to ensure they're only created when necessary. * * Returns a thunk which that returns independent, identically distributed * samples from the specified distribution. * * @private * * @param {string} label - Name of distribution * @param {function} getter - Function which generates a new distribution * @param {...*} args - Distribution-specific arguments * * @return {function} */ _proto._memoize = function _memoize(label, getter) { var args = [].slice.call(arguments, 2); var key = "" + args.join(';'); var value = this._cache[label]; if (value === undefined || value.key !== key) { value = { key: key, distribution: getter.apply(void 0, [this].concat(args)) }; this._cache[label] = value; } return value.distribution; }; _createClass(Random, [{ key: "rng", get: function get() { return this._rng; } }]); return Random; }(); // defaults to Math.random as its RNG var random = new Random(); export { RNG, RNGFactory, Random, random as default }; //# sourceMappingURL=random.module.js.map