time-to-botec

Benchmark sampling in different programming languages
Log | Files | Refs | README

main.js (5614B)


      1 /**
      2 * @license Apache-2.0
      3 *
      4 * Copyright (c) 2018 The Stdlib Authors.
      5 *
      6 * Licensed under the Apache License, Version 2.0 (the "License");
      7 * you may not use this file except in compliance with the License.
      8 * You may obtain a copy of the License at
      9 *
     10 *    http://www.apache.org/licenses/LICENSE-2.0
     11 *
     12 * Unless required by applicable law or agreed to in writing, software
     13 * distributed under the License is distributed on an "AS IS" BASIS,
     14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15 * See the License for the specific language governing permissions and
     16 * limitations under the License.
     17 */
     18 
     19 'use strict';
     20 
     21 // MODULES //
     22 
     23 var setReadOnly = require( '@stdlib/utils/define-nonenumerable-read-only-property' );
     24 var setReadOnlyAccessor = require( '@stdlib/utils/define-nonenumerable-read-only-accessor' );
     25 var setReadWriteAccessor = require( '@stdlib/utils/define-nonenumerable-read-write-accessor' );
     26 var copy = require( '@stdlib/utils/copy' );
     27 var isObject = require( '@stdlib/assert/is-plain-object' );
     28 var isNonNegativeInteger = require( '@stdlib/assert/is-nonnegative-integer' ).isPrimitive;
     29 var hasOwnProp = require( '@stdlib/assert/has-own-property' );
     30 var MAX_VALUE = require( '@stdlib/constants/float64/max' );
     31 var randi = require( './../../../base/randi' ).factory;
     32 var iteratorSymbol = require( '@stdlib/symbol/iterator' );
     33 
     34 
     35 // MAIN //
     36 
     37 /**
     38 * Returns an iterator for generating pseudorandom numbers having integer values.
     39 *
     40 * @param {Options} [options] - function options
     41 * @param {string} [options.name='mt19937'] - name of a supported pseudorandom number generator (PRNG), which will serve as the underlying source of pseudorandom numbers
     42 * @param {*} [options.seed] - pseudorandom number generator seed
     43 * @param {*} [options.state] - pseudorandom number generator state
     44 * @param {boolean} [options.copy=true] - boolean indicating whether to copy a provided pseudorandom number generator state
     45 * @param {NonNegativeInteger} [options.iter] - number of iterations
     46 * @throws {TypeError} options argument must be an object
     47 * @throws {TypeError} must provide valid options
     48 * @throws {Error} must provide a valid state
     49 * @returns {Iterator} iterator
     50 *
     51 * @example
     52 * var iter = iterator();
     53 *
     54 * var r = iter.next().value;
     55 * // returns <number>
     56 *
     57 * r = iter.next().value;
     58 * // returns <number>
     59 *
     60 * r = iter.next().value;
     61 * // returns <number>
     62 *
     63 * // ...
     64 */
     65 function iterator( options ) {
     66 	var opts;
     67 	var iter;
     68 	var rand;
     69 	var FLG;
     70 	var i;
     71 	if ( arguments.length > 0 ) {
     72 		if ( !isObject( options ) ) {
     73 			throw new TypeError( 'invalid argument. Options argument must be an object. Value: `'+options+'`.' );
     74 		}
     75 		opts = copy( options, 1 );
     76 		if ( hasOwnProp( opts, 'iter' ) ) {
     77 			if ( !isNonNegativeInteger( opts.iter ) ) {
     78 				throw new TypeError( 'invalid option. `iter` option must be a nonnegative integer. Option: `'+opts.iter+'`.' );
     79 			}
     80 		} else {
     81 			opts.iter = MAX_VALUE;
     82 		}
     83 		rand = randi( opts );
     84 		if ( opts.copy !== false ) {
     85 			opts.state = rand.state; // cache a copy of the PRNG state
     86 		}
     87 	} else {
     88 		rand = randi();
     89 		opts = {
     90 			'iter': MAX_VALUE,
     91 			'state': rand.state // cache a copy of the PRNG state
     92 		};
     93 	}
     94 	i = 0;
     95 
     96 	// Create an iterator protocol-compliant object:
     97 	iter = {};
     98 	setReadOnly( iter, 'next', next );
     99 	setReadOnly( iter, 'return', end );
    100 	setReadOnlyAccessor( iter, 'seed', getSeed );
    101 	setReadOnlyAccessor( iter, 'seedLength', getSeedLength );
    102 	setReadWriteAccessor( iter, 'state', getState, setState );
    103 	setReadOnlyAccessor( iter, 'stateLength', getStateLength );
    104 	setReadOnlyAccessor( iter, 'byteLength', getStateSize );
    105 	setReadOnly( iter, 'PRNG', rand.PRNG );
    106 
    107 	// If an environment supports `Symbol.iterator`, make the iterator iterable:
    108 	if ( iteratorSymbol ) {
    109 		setReadOnly( iter, iteratorSymbol, factory );
    110 	}
    111 	return iter;
    112 
    113 	/**
    114 	* Returns an iterator protocol-compliant object containing the next iterated value.
    115 	*
    116 	* @private
    117 	* @returns {Object} iterator protocol-compliant object
    118 	*/
    119 	function next() {
    120 		i += 1;
    121 		if ( FLG || i > opts.iter ) {
    122 			return {
    123 				'done': true
    124 			};
    125 		}
    126 		return {
    127 			'value': rand(),
    128 			'done': false
    129 		};
    130 	}
    131 
    132 	/**
    133 	* Finishes an iterator.
    134 	*
    135 	* @private
    136 	* @param {*} [value] - value to return
    137 	* @returns {Object} iterator protocol-compliant object
    138 	*/
    139 	function end( value ) {
    140 		FLG = true;
    141 		if ( arguments.length ) {
    142 			return {
    143 				'value': value,
    144 				'done': true
    145 			};
    146 		}
    147 		return {
    148 			'done': true
    149 		};
    150 	}
    151 
    152 	/**
    153 	* Returns a new iterator.
    154 	*
    155 	* @private
    156 	* @returns {Iterator} iterator
    157 	*/
    158 	function factory() {
    159 		return iterator( opts );
    160 	}
    161 
    162 	/**
    163 	* Returns the PRNG seed.
    164 	*
    165 	* @private
    166 	* @returns {*} seed
    167 	*/
    168 	function getSeed() {
    169 		return rand.PRNG.seed;
    170 	}
    171 
    172 	/**
    173 	* Returns the PRNG seed length.
    174 	*
    175 	* @private
    176 	* @returns {PositiveInteger} seed length
    177 	*/
    178 	function getSeedLength() {
    179 		return rand.PRNG.seedLength;
    180 	}
    181 
    182 	/**
    183 	* Returns the PRNG state length.
    184 	*
    185 	* @private
    186 	* @returns {PositiveInteger} state length
    187 	*/
    188 	function getStateLength() {
    189 		return rand.PRNG.stateLength;
    190 	}
    191 
    192 	/**
    193 	* Returns the PRNG state size (in bytes).
    194 	*
    195 	* @private
    196 	* @returns {PositiveInteger} state size (in bytes)
    197 	*/
    198 	function getStateSize() {
    199 		return rand.PRNG.byteLength;
    200 	}
    201 
    202 	/**
    203 	* Returns the current pseudorandom number generator state.
    204 	*
    205 	* @private
    206 	* @returns {*} current state
    207 	*/
    208 	function getState() {
    209 		return rand.PRNG.state;
    210 	}
    211 
    212 	/**
    213 	* Sets the pseudorandom number generator state.
    214 	*
    215 	* @private
    216 	* @param {*} s - generator state
    217 	* @throws {Error} must provide a valid state
    218 	*/
    219 	function setState( s ) {
    220 		rand.PRNG.state = s;
    221 	}
    222 }
    223 
    224 
    225 // EXPORTS //
    226 
    227 module.exports = iterator;