time-to-botec

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

main.js (4933B)


      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 isFunction = require( '@stdlib/assert/is-function' );
     25 var isCollection = require( '@stdlib/assert/is-collection' );
     26 var isNonNegativeInteger = require( '@stdlib/assert/is-nonnegative-integer' ).isPrimitive;
     27 var isInteger = require( '@stdlib/assert/is-integer' ).isPrimitive;
     28 var iteratorSymbol = require( '@stdlib/symbol/iterator' );
     29 
     30 
     31 // MAIN //
     32 
     33 /**
     34 * Returns an iterator which iterates over elements in an array-like object according to specified stride parameters.
     35 *
     36 * @param {NonNegativeInteger} N - number of values to iterate
     37 * @param {Collection} src - input value
     38 * @param {integer} stride - stride length
     39 * @param {NonNegativeInteger} offset - starting index
     40 * @param {Function} [mapFcn] - function to invoke for each iterated value
     41 * @param {*} [thisArg] - execution context
     42 * @throws {TypeError} first argument must be a nonnegative integer
     43 * @throws {TypeError} second argument must be an array-like object
     44 * @throws {TypeError} third argument must be an integer
     45 * @throws {TypeError} fourth argument must be a nonnegative integer
     46 * @throws {TypeError} fifth argument must be a function
     47 * @returns {Iterator} iterator
     48 *
     49 * @example
     50 * var values = [ 1, 2, 3, 4, 5, 6, 7, 8 ];
     51 *
     52 * var N = 4;
     53 * var stride = -2;
     54 * var offset = 6;
     55 *
     56 * var iter = stridedarray2iterator( N, values, stride, offset );
     57 *
     58 * var v = iter.next().value;
     59 * // returns 7
     60 *
     61 * v = iter.next().value;
     62 * // returns 5
     63 *
     64 * v = iter.next().value;
     65 * // returns 3
     66 *
     67 * // ...
     68 */
     69 function stridedarray2iterator( N, src, stride, offset ) {
     70 	var thisArg;
     71 	var iter;
     72 	var FLG;
     73 	var fcn;
     74 	var idx;
     75 	var i;
     76 	if ( !isNonNegativeInteger( N ) ) {
     77 		throw new TypeError( 'invalid argument. First argument must be a nonnegative integer. Value: `' + N + '`.' );
     78 	}
     79 	if ( !isCollection( src ) ) {
     80 		throw new TypeError( 'invalid argument. Second argument must be an array-like object. Value: `' + src + '`.' );
     81 	}
     82 	if ( !isInteger( stride ) ) {
     83 		throw new TypeError( 'invalid argument. Third argument must be an integer. Value: `' + stride + '`.' );
     84 	}
     85 	if ( !isNonNegativeInteger( offset ) ) {
     86 		throw new TypeError( 'invalid argument. Fourth argument must be a nonnegative integer. Value: `' + offset + '`.' );
     87 	}
     88 	if ( arguments.length > 4 ) {
     89 		fcn = arguments[ 4 ];
     90 		if ( !isFunction( fcn ) ) {
     91 			throw new TypeError( 'invalid argument. Fifth argument must be a function. Value: `' + fcn + '`.' );
     92 		}
     93 		thisArg = arguments[ 5 ];
     94 	}
     95 	idx = offset;
     96 	i = -1;
     97 
     98 	// Create an iterator protocol-compliant object:
     99 	iter = {};
    100 	if ( fcn ) {
    101 		setReadOnly( iter, 'next', next1 );
    102 	} else {
    103 		setReadOnly( iter, 'next', next2 );
    104 	}
    105 	setReadOnly( iter, 'return', end );
    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 next1() {
    120 		var v;
    121 		i += 1;
    122 		if ( FLG || i >= N ) {
    123 			return {
    124 				'done': true
    125 			};
    126 		}
    127 		v = fcn.call( thisArg, src[ idx ], idx, i, src );
    128 		idx += stride;
    129 		return {
    130 			'value': v,
    131 			'done': false
    132 		};
    133 	}
    134 
    135 	/**
    136 	* Returns an iterator protocol-compliant object containing the next iterated value.
    137 	*
    138 	* @private
    139 	* @returns {Object} iterator protocol-compliant object
    140 	*/
    141 	function next2() {
    142 		var v;
    143 		i += 1;
    144 		if ( FLG || i >= N ) {
    145 			return {
    146 				'done': true
    147 			};
    148 		}
    149 		v = src[ idx ];
    150 		idx += stride;
    151 		return {
    152 			'value': v,
    153 			'done': false
    154 		};
    155 	}
    156 
    157 	/**
    158 	* Finishes an iterator.
    159 	*
    160 	* @private
    161 	* @param {*} [value] - value to return
    162 	* @returns {Object} iterator protocol-compliant object
    163 	*/
    164 	function end( value ) {
    165 		FLG = true;
    166 		if ( arguments.length ) {
    167 			return {
    168 				'value': value,
    169 				'done': true
    170 			};
    171 		}
    172 		return {
    173 			'done': true
    174 		};
    175 	}
    176 
    177 	/**
    178 	* Returns a new iterator.
    179 	*
    180 	* @private
    181 	* @returns {Iterator} iterator
    182 	*/
    183 	function factory() {
    184 		if ( fcn ) {
    185 			return stridedarray2iterator( N, src, stride, offset, fcn, thisArg ); // eslint-disable-line max-len
    186 		}
    187 		return stridedarray2iterator( N, src, stride, offset );
    188 	}
    189 }
    190 
    191 
    192 // EXPORTS //
    193 
    194 module.exports = stridedarray2iterator;