'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.RNGFactory = exports.RNG = undefined; var _createClass = function () { 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, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _owLite = require('ow-lite'); var _owLite2 = _interopRequireDefault(_owLite); var _rng = require('./rng'); var _rng2 = _interopRequireDefault(_rng); var _rngFactory = require('./rng-factory'); var _rngFactory2 = _interopRequireDefault(_rngFactory); var _uniform2 = require('./distributions/uniform'); var _uniform3 = _interopRequireDefault(_uniform2); var _uniformInt2 = require('./distributions/uniform-int'); var _uniformInt3 = _interopRequireDefault(_uniformInt2); var _uniformBoolean2 = require('./distributions/uniform-boolean'); var _uniformBoolean3 = _interopRequireDefault(_uniformBoolean2); var _normal2 = require('./distributions/normal'); var _normal3 = _interopRequireDefault(_normal2); var _logNormal2 = require('./distributions/log-normal'); var _logNormal3 = _interopRequireDefault(_logNormal2); var _bernoulli2 = require('./distributions/bernoulli'); var _bernoulli3 = _interopRequireDefault(_bernoulli2); var _binomial2 = require('./distributions/binomial'); var _binomial3 = _interopRequireDefault(_binomial2); var _geometric2 = require('./distributions/geometric'); var _geometric3 = _interopRequireDefault(_geometric2); var _poisson2 = require('./distributions/poisson'); var _poisson3 = _interopRequireDefault(_poisson2); var _exponential2 = require('./distributions/exponential'); var _exponential3 = _interopRequireDefault(_exponential2); var _irwinHall2 = require('./distributions/irwin-hall'); var _irwinHall3 = _interopRequireDefault(_irwinHall2); var _bates2 = require('./distributions/bates'); var _bates3 = _interopRequireDefault(_bates2); var _pareto2 = require('./distributions/pareto'); var _pareto3 = _interopRequireDefault(_pareto2); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } exports.RNG = _rng2.default; exports.RNGFactory = _rngFactory2.default; /** * 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 = function () { function Random(rng) { _classCallCheck(this, Random); if (rng) (0, _owLite2.default)(rng, _owLite2.default.object.instanceOf(_rng2.default)); this._cache = {}; this.use(rng); } /** * @member {RNG} Underlying pseudo-random number generator */ _createClass(Random, [{ key: 'clone', /** * 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} */ value: function clone() { if (arguments.length) { return new Random(_rngFactory2.default.apply(undefined, arguments)); } 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 * const random = require('random') * * random.use('example_seedrandom_string') * // or * random.use(seedrandom('kittens')) * // or * random.use(Math.random) * * @param {...*} args */ }, { key: 'use', value: function use() { this._rng = _rngFactory2.default.apply(undefined, arguments); } /** * Patches `Math.random` with this Random instance's PRNG. */ }, { key: 'patch', value: 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. */ }, { key: 'unpatch', value: 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} */ }, { key: 'next', value: function next() { return this._rng.next(); } /** * Samples a uniform random floating point number, optionally specifying * lower and upper bounds. * * Convence wrapper around `random.uniform()` * * @param {number} [min=0] - Lower bound (float, inclusive) * @param {number} [max=1] - Upper bound (float, exclusive) * @return {number} */ }, { key: 'float', value: function float(min, max) { return this.uniform(min, max)(); } /** * Samples a uniform random integer, optionally specifying lower and upper * bounds. * * Convence wrapper around `random.uniformInt()` * * @param {number} [min=0] - Lower bound (integer, inclusive) * @param {number} [max=1] - Upper bound (integer, inclusive) * @return {number} */ }, { key: 'int', value: function int(min, max) { return this.uniformInt(min, max)(); } /** * Samples a uniform random integer, optionally specifying lower and upper * bounds. * * Convence wrapper around `random.uniformInt()` * * @alias `random.int` * * @param {number} [min=0] - Lower bound (integer, inclusive) * @param {number} [max=1] - Upper bound (integer, inclusive) * @return {number} */ }, { key: 'integer', value: function integer(min, max) { return this.uniformInt(min, max)(); } /** * Samples a uniform random boolean value. * * Convence wrapper around `random.uniformBoolean()` * * @alias `random.boolean` * * @return {boolean} */ }, { key: 'bool', value: function bool() { return this.uniformBoolean()(); } /** * Samples a uniform random boolean value. * * Convence wrapper around `random.uniformBoolean()` * * @return {boolean} */ }, { key: 'boolean', value: function boolean() { return this.uniformBoolean()(); } // -------------------------------------------------------------------------- // 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} */ }, { key: 'uniform', value: function uniform(min, max) { return this._memoize('uniform', _uniform3.default, min, max); } /** * Generates a [Discrete uniform distribution](https://en.wikipedia.org/wiki/Discrete_uniform_distribution). * * @param {number} [min=0] - Lower bound (integer, inclusive) * @param {number} [max=1] - Upper bound (integer, inclusive) * @return {function} */ }, { key: 'uniformInt', value: function uniformInt(min, max) { return this._memoize('uniformInt', _uniformInt3.default, min, max); } /** * Generates a [Discrete uniform distribution](https://en.wikipedia.org/wiki/Discrete_uniform_distribution), * with two possible outcomes, `true` or `false. * * This method is analogous to flipping a coin. * * @return {function} */ }, { key: 'uniformBoolean', value: function uniformBoolean() { return this._memoize('uniformBoolean', _uniformBoolean3.default); } // -------------------------------------------------------------------------- // Normal distributions // -------------------------------------------------------------------------- /** * Generates a [Normal distribution](https://en.wikipedia.org/wiki/Normal_distribution). * * @param {number} [mu=0] - Mean * @param {number} [sigma=1] - Standard deviation * @return {function} */ }, { key: 'normal', value: function normal(mu, sigma) { return (0, _normal3.default)(this, mu, sigma); } /** * Generates a [Log-normal distribution](https://en.wikipedia.org/wiki/Log-normal_distribution). * * @param {number} [mu=0] - Mean of underlying normal distribution * @param {number} [sigma=1] - Standard deviation of underlying normal distribution * @return {function} */ }, { key: 'logNormal', value: function logNormal(mu, sigma) { return (0, _logNormal3.default)(this, mu, sigma); } // -------------------------------------------------------------------------- // Bernoulli distributions // -------------------------------------------------------------------------- /** * Generates a [Bernoulli distribution](https://en.wikipedia.org/wiki/Bernoulli_distribution). * * @param {number} [p=0.5] - Success probability of each trial. * @return {function} */ }, { key: 'bernoulli', value: function bernoulli(p) { return (0, _bernoulli3.default)(this, p); } /** * Generates a [Binomial distribution](https://en.wikipedia.org/wiki/Binomial_distribution). * * @param {number} [n=1] - Number of trials. * @param {number} [p=0.5] - Success probability of each trial. * @return {function} */ }, { key: 'binomial', value: function binomial(n, p) { return (0, _binomial3.default)(this, n, p); } /** * Generates a [Geometric distribution](https://en.wikipedia.org/wiki/Geometric_distribution). * * @param {number} [p=0.5] - Success probability of each trial. * @return {function} */ }, { key: 'geometric', value: function geometric(p) { return (0, _geometric3.default)(this, p); } // -------------------------------------------------------------------------- // Poisson distributions // -------------------------------------------------------------------------- /** * Generates a [Poisson distribution](https://en.wikipedia.org/wiki/Poisson_distribution). * * @param {number} [lambda=1] - Mean (lambda > 0) * @return {function} */ }, { key: 'poisson', value: function poisson(lambda) { return (0, _poisson3.default)(this, lambda); } /** * Generates an [Exponential distribution](https://en.wikipedia.org/wiki/Exponential_distribution). * * @param {number} [lambda=1] - Inverse mean (lambda > 0) * @return {function} */ }, { key: 'exponential', value: function exponential(lambda) { return (0, _exponential3.default)(this, lambda); } // -------------------------------------------------------------------------- // Misc distributions // -------------------------------------------------------------------------- /** * Generates an [Irwin Hall distribution](https://en.wikipedia.org/wiki/Irwin%E2%80%93Hall_distribution). * * @param {number} [n=1] - Number of uniform samples to sum (n >= 0) * @return {function} */ }, { key: 'irwinHall', value: function irwinHall(n) { return (0, _irwinHall3.default)(this, n); } /** * Generates a [Bates distribution](https://en.wikipedia.org/wiki/Bates_distribution). * * @param {number} [n=1] - Number of uniform samples to average (n >= 1) * @return {function} */ }, { key: 'bates', value: function bates(n) { return (0, _bates3.default)(this, n); } /** * Generates a [Pareto distribution](https://en.wikipedia.org/wiki/Pareto_distribution). * * @param {number} [alpha=1] - Alpha * @return {function} */ }, { key: 'pareto', value: function pareto(alpha) { return (0, _pareto3.default)(this, alpha); } // -------------------------------------------------------------------------- // 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} */ }, { key: '_memoize', value: function _memoize(label, getter) { for (var _len = arguments.length, args = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { args[_key - 2] = arguments[_key]; } var key = '' + args.join(';'); var value = this._cache[label]; if (value === undefined || value.key !== key) { value = { key: key, distribution: getter.apply(undefined, [this].concat(args)) }; this._cache[label] = value; } return value.distribution; } }, { key: 'rng', get: function get() { return this._rng; } }]); return Random; }(); // defaults to Math.random as its RNG exports.default = new Random(); //# sourceMappingURL=random.js.map