function factory() {
		var Random;
		var random;
		var param1;
		var param2;
		var assign;
		var nargs;
		var base;
		var opts;
		var rand;
		var dt;

		nargs = arguments.length;
		if ( nargs < 1 ) {                              // e.g., factory()
			opts = {};
			base = prng;
			rand = rand1;
		} else if ( nargs === 1 ) {                     // e.g., factory( {} )
			opts = arguments[ 0 ];
			base = prng.factory( opts );
			rand = rand1;
		} else if ( nargs === 2 ) {                     // e.g., factory( param1, param2 )
			param1 = arguments[ 0 ];
			param2 = arguments[ 1 ];
			opts = {};
			base = prng.factory( param1, param2 );
			rand = rand2;
		} else {                                        // e.g., factory( param1, param2, {} )
			param1 = arguments[ 0 ];
			param2 = arguments[ 1 ];
			opts = arguments[ 2 ];
			base = prng.factory( param1, param2, opts );
			rand = rand2;
		}
		if ( hasOwnProp( opts, 'dtype' ) ) {
			dt = opts.dtype;
			if ( !isValidDataType( dt ) ) {
				throw new TypeError( format( 'invalid option. `%s` option must be one of the following: "%s". Option: `%s`.', 'dtype', dtypes.join( '", "' ), dt ) );
			}
		} else {
			dt = dtype;
		}
		if ( rand === rand1 ) {
			assign = assign1;
			Random = BinaryRandom;
		} else {
			assign = assign2;
			Random = NullaryRandom;
		}
		random = new Random( base, dtypes, dt );
		if ( opts && opts.prng ) {
			setReadOnly( rand, 'seed', null );
			setReadOnly( rand, 'seedLength', null );
			setReadWriteAccessor( rand, 'state', constantFunction( null ), noop );
			setReadOnly( rand, 'stateLength', null );
			setReadOnly( rand, 'byteLength', null );
		} else {
			setReadOnlyAccessor( rand, 'seed', getSeed );
			setReadOnlyAccessor( rand, 'seedLength', getSeedLength );
			setReadWriteAccessor( rand, 'state', getState, setState );
			setReadOnlyAccessor( rand, 'stateLength', getStateLength );
			setReadOnlyAccessor( rand, 'byteLength', getStateSize );
		}
		setReadOnly( rand, 'PRNG', base.PRNG );
		setReadOnly( rand, 'assign', assign );
		return rand;

		/**
		* Returns an array of pseudorandom values drawn from a PRNG.
		*
		* @private
		* @param {NonNegativeInteger} len - output array length
		* @param {*} param1 - first PRNG parameter
		* @param {*} param2 - second PRNG parameter
		* @param {Options} [options] - function options
		* @param {string} [options.dtype] - output array data type
		* @throws {TypeError} first argument must be a nonnegative integer
		* @throws {TypeError} options argument must be an object
		* @throws {TypeError} must provide valid options
		* @returns {Collection} output array
		*/
		function rand1( len, param1, param2, options ) {
			if ( arguments.length < 4 ) {
				return random.generate( len, param1, param2 );
			}
			return random.generate( len, param1, param2, options );
		}

		/**
		* Returns an array of pseudorandom values drawn from a PRNG.
		*
		* @private
		* @param {NonNegativeInteger} len - output array length
		* @param {Options} [options] - function options
		* @param {string} [options.dtype] - output array data type
		* @throws {TypeError} first argument must be a nonnegative integer
		* @throws {TypeError} options argument must be an object
		* @throws {TypeError} must provide valid options
		* @returns {Collection} output array
		*/
		function rand2( len, options ) {
			if ( arguments.length < 2 ) {
				return random.generate( len );
			}
			return random.generate( len, options );
		}

		/**
		* Fills an array with pseudorandom values drawn from a PRNG.
		*
		* @private
		* @param {*} param1 - first PRNG parameter
		* @param {*} param2 - second PRNG parameter
		* @param {Collection} out - output array
		* @throws {TypeError} third argument must be a collection
		* @returns {Collection} output array
		*/
		function assign1( param1, param2, out ) {
			return random.assign( param1, param2, out );
		}

		/**
		* Fills an array with pseudorandom values drawn from a PRNG.
		*
		* @private
		* @param {Collection} out - output array
		* @throws {TypeError} first argument must be a collection
		* @returns {Collection} output array
		*/
		function assign2( out ) {
			return random.assign( out );
		}

		/**
		* Returns the PRNG seed.
		*
		* @private
		* @returns {*} seed
		*/
		function getSeed() {
			return rand.PRNG.seed;
		}

		/**
		* Returns the PRNG seed length.
		*
		* @private
		* @returns {PositiveInteger} seed length
		*/
		function getSeedLength() {
			return rand.PRNG.seedLength;
		}

		/**
		* Returns the PRNG state length.
		*
		* @private
		* @returns {PositiveInteger} state length
		*/
		function getStateLength() {
			return rand.PRNG.stateLength;
		}

		/**
		* Returns the PRNG state size (in bytes).
		*
		* @private
		* @returns {PositiveInteger} state size (in bytes)
		*/
		function getStateSize() {
			return rand.PRNG.byteLength;
		}

		/**
		* Returns the current pseudorandom number generator state.
		*
		* @private
		* @returns {*} current state
		*/
		function getState() {
			return rand.PRNG.state;
		}

		/**
		* Sets the pseudorandom number generator state.
		*
		* @private
		* @param {*} s - generator state
		* @throws {Error} must provide a valid state
		*/
		function setState( s ) {
			rand.PRNG.state = s;
		}
	}
Returns a function for generating pseudorandom values drawn from a PRNG.

@private
@param {*} [param1] - first PRNG parameter
@param {*} [param2] - second PRNG parameter
@param {Options} [options] - function options
@param {PRNG} [options.prng] - pseudorandom number generator which generates uniformly distributed pseudorandom numbers
@param {*} [options.seed] - pseudorandom value generator seed
@param {*} [options.state] - pseudorandom value generator state
@param {boolean} [options.copy] - boolean indicating whether to copy a provided pseudorandom value generator state
@param {string} [options.dtype] - default output array data type
@throws {TypeError} options argument must be an object
@throws {TypeError} must provide valid options
@throws {Error} must provide a valid state
@returns {Function} function for creating arrays