Example #1
0
// DOT PRODUCT //

/**
* FUNCTION: dot( x, y[, accessor] )
*	Computes the dot product between two arrays.
*
* @param {Array} x - input array
* @param {Array} y - input array
* @param {Function} [accessor] - accessor function for accessing array values
* @returns {Number|Null} dot product
*/
function dot( x, y, clbk ) {
	if ( !isArray( x ) ) {
		throw new TypeError( 'dot()::invalid input argument. First argument must be an array. Value: `' + x + '`.' );
	}
	if ( !isArray( y ) ) {
		throw new TypeError( 'dot()::invalid input argument. Second argument must be an array. Value: `' + y + '`.' );
	}
	if ( arguments.length > 2 ) {
		if ( !isFunction( clbk ) ) {
			throw new TypeError( 'dot()::invalid input argument. Accessor must be a function. Value: `' + clbk + '`.' );
		}
	}
	var len = x.length,
		sum = 0,
		i;

	if ( len !== y.length ) {
		throw new Error( 'dot()::invalid input argument. Arrays must be of equal length.' );
	}
	if ( !len ) {
		return null;
	}
	if ( clbk ) {
		for ( i = 0; i < len; i++ ) {
			sum += clbk( x[ i ], i, 0 ) * clbk( y[ i ], i, 1 );
		}
	} else {
		for ( i = 0; i < len; i++ ) {
			sum += x[ i ] * y[ i ];
		}
	}
	return sum;
} // end FUNCTION dot()
Example #2
0
// VALIDATE //

/**
* FUNCTION: validate( opts, options )
*	Validates function options.
*
* @param {Object} opts - destination for validated options
* @param {Object} options - function options
* @param {Function} [options.accessor] - accessor function for accessing array values
* @param {Number} [options.dim] - dimension
* @param {String} [options.dtype] - output data type
* @param {Boolean} [options.bias=false] - boolean indicating whether to calculate a biased or unbiased estimate of the variance
* @returns {Null|Error} null or an error
*/
function validate( opts, options ) {
	if ( !isObject( options ) ) {
		return new TypeError( 'variance()::invalid input argument. Options argument must be an object. Value: `' + options + '`.' );
	}
	if ( options.hasOwnProperty( 'accessor' ) ) {
		opts.accessor = options.accessor;
		if ( !isFunction( opts.accessor ) ) {
			return new TypeError( 'variance()::invalid option. Accessor must be a function. Option: `' + opts.accessor + '`.' );
		}
	}
	if ( options.hasOwnProperty( 'dim' ) ) {
		opts.dim = options.dim;
		if ( !isPositiveInteger( opts.dim ) ) {
			return new TypeError( 'variance()::invalid option. Dimension option must be a positive integer. Option: `' + opts.dim + '`.' );
		}
	}
	if ( options.hasOwnProperty( 'dtype' ) ) {
		opts.dtype = options.dtype;
		if ( !isString( opts.dtype ) ) {
			return new TypeError( 'variance()::invalid option. Data type option must be a string primitive. Option: `' + opts.dtype + '`.' );
		}
	}
	if ( options.hasOwnProperty( 'bias' ) ) {
		opts.bias = options.bias;
		if ( !isBoolean( opts.bias ) ) {
			return new TypeError( 'variance()::invalid option. Bias option must be a boolean primitive. Option: `' + opts.dim + '`.' );
		}
	}
	return null;
} // end FUNCTION validate()
Example #3
0
// VALIDATE //

/**
* FUNCTION: validate( opts, options )
*	Validates function options. If an option is not present, a default option value is set.
*
* @private
* @param {Object} opts - destination for validated options
* @param {Object} options - function options
* @param {Array} [opts.encoding=[null] ] - array of values encoding missing values
* @param {Boolean} [opts.copy=true] - boolean indicating if the function should return a new array
* @param {Function} [opts.accessor=null] - accessor function for accessing array values
* @returns {Null|Error} null or an error
*/
function validate( opts, options ) {
	if ( !isObject( options ) ) {
		return new TypeError( 'ismissing()::invalid input argument. Options argument must be an object. Value: `' + opts + '`.' );
	}

	if ( options.hasOwnProperty( 'encoding' ) ) {
		opts.encoding = options.encoding;
		if ( !isArray( opts.encoding ) ) {
			return new TypeError( 'ismissing()::invalid option. Encoding option must be an array. Option: `' + opts.encoding + '`.' );
		}
	}

	if ( options.hasOwnProperty( 'copy' ) ) {
		opts.copy = options.copy;
		if ( !isBoolean( opts.copy ) ) {
			return new TypeError( 'ismissing()::invalid option. Copy option must be a boolean primitive. Option: `' + opts.copy + '`.' );
		}
	}

	if ( options.hasOwnProperty( 'accessor' ) ) {
		opts.accessor = options.accessor;
		if ( !isFunction( opts.accessor ) ) {
			return new TypeError( 'ismissing()::invalid option. Accessor must be a function. Option: `' + opts.accessor + '`.' );
		}
	}

	return null;
} // end FUNCTION validate()
Example #4
0
// DELETE //

/**
* FUNCTION: del( id, options, clbk )
*	Deletes a token.
*
* @param {Number} id - token id
* @param {Object} options - function options
* @param {String} options.username - Github username
* @param {String} options.password - Github password
* @param {String} [options.otp] - Github one-time password
* @param {String} [options.useragent] - user agent string
* @param {Function} clbk - callback to invoke upon query completion
* @returns {Function} function for deleting a token
*/
function del( id, options, clbk ) {
	var opts;
	var err;
	if ( !isNonNegativeInteger( id ) ) {
		throw new TypeError( 'invalid input argument. Token id must be a nonnegative integer. Value: `' + id + '`.' );
	}
	if ( !isFunction( clbk ) ) {
		throw new TypeError( 'invalid input argument. Callback argument must be a function. Value: `' + clbk + '`.' );
	}
	opts = copy( defaults );
	err = validate( opts, options );
	if ( err ) {
		throw err;
	}
	query( id, opts, done );
	/**
	* FUNCTION: done( error, info )
	*	Callback invoked after receiving an API response.
	*
	* @private
	* @param {Error|Null} error - error object
	* @param {Object} info - response info
	* @returns {Void}
	*/
	function done( error, info ) {
		error = error || null;
		info = info || null;
		clbk( error, info );
	} // end FUNCTION done()
} // end FUNCTION del()
Example #5
0
ConceptNet.prototype.getURI = function() {
	var args = arguments;
	var nargs = args.length;
	var path;
	var text;
	var language;
	var callback;

	if ( nargs < 2 ) {
		throw new Error( 'insufficient input arguments. Must provide an input text and a callback function.' );
	}

	text = args[ 0 ];
	if ( !isString( text ) ) {
		throw new TypeError( 'invalid input argument. First argument must be a string primitive. Value: `' + text + '`.' );
	}
	if ( nargs < 3 ) {
		language = 'en';
		callback = args[ 1 ];
	} else {
		language = args[ 1 ];
		if ( !isString( language ) ) {
			throw new TypeError( 'invalid input argument. Language argument must be a string primitive. Value: `' + language + '`.' );
		}
		callback = args[ 2 ];
	}
	if ( !isFunction( callback ) ) {
		throw new TypeError( 'invalid input argument. Last argument must be a callback function. Value: `' + callback + '`.' );
	}

	text = text.replace(/\s+/g, '_');
	path = '/data/' + this.version + '/uri?language=' + language + '&text=' + String( encodeURIComponent( text ) );
	this.makeHtppRequest( this.buildOptions( path ), callback );
}; // end METHOD getURI()
Example #6
0
} // end FUNCTION polyval()


// EVALUATE //

/**
* FUNCTION: evaluate( coef, x[, options] )
*	Evaluates a polynomial.
*
* @param {Number[]} coef - array of coefficients sorted in descending degree
* @param {Array|Number[]|Number} x - value(s) at which to evaluate the polynomial
* @param {Object} [options] - function options
* @param {Boolean} [options.copy=true] - boolean indicating whether to return a new array
* @param {Function} [options.accessor] - accessor function for accessing array values
* @returns {Number|Number[]} evaluated polynomial
*/
function evaluate( c, x, opts ) {
	var copy = true,
		clbk,
		len,
		arr,
		v, i;
	if ( !isNumberArray( c ) ) {
		throw new TypeError( 'polynomial()::invalid input argument. Coefficients must be provided as an array of number primitives. Value: `' + c + '`.' );
	}
	if ( isNumber( x ) ) {
		return polyval( c, x );
	}
	if ( !isArray( x ) ) {
		throw new TypeError( 'polynomial()::invalid input argument. Second argument must be either a single number primitive or an array of values. Value: `' + x + '`.' );
	}
	if ( arguments.length > 2 ) {
		if ( !isObject( opts ) ) {
			throw new TypeError( 'polynomial()::invalid input argument. Options argument must be an object. Value: `' + opts + '`.' );
		}
		if ( opts.hasOwnProperty( 'copy' ) ) {
			copy = opts.copy;
			if ( !isBoolean( copy ) ) {
				throw new TypeError( 'polynomial()::invalid option. Copy option must be a boolean primitive. Option: `' + copy + '`.' );
			}
		}
		if ( opts.hasOwnProperty( 'accessor' ) ) {
			clbk = opts.accessor;
			if ( !isFunction( clbk ) ) {
				throw new TypeError( 'polynomial()::invalid option. Accessor must be a function. Option: `' + clbk + '`.' );
			}
		}
	}
	len = x.length;
	if ( copy ) {
		arr = new Array( len );
	} else {
		arr = x;
	}
	if ( clbk ) {
		for ( i = 0; i < len; i++ ) {
			v = clbk( x[ i ], i );
			if ( !isNumber( v ) ) {
				throw new TypeError( 'polynomial()::invalid input argument. Accessed array values must be number primitives. Value: `' + v + '`.' );
			}
			arr[ i ] = polyval( c, v );
		}
	} else {
		for ( i = 0; i < len; i++ ) {
			v = x[ i ];
			if ( !isNumber( v ) ) {
				throw new TypeError( 'polynomial()::invalid input argument. Array values must be number primitives. Value: `' + v + '`.' );
			}
			arr[ i ] = polyval( c, v );
		}
	}
	return arr;
} // end FUNCTION evaluate()
Example #7
0
// FACTORY //

/**
* FUNCTION: factory( fcns, clbk[, thisArg] )
*	Returns a reusable waterfall function. 
*
* @param {Function[]} fcns - array of functions
* @param {Function} clbk - callback to invoke upon completing all functions
* @param {*} [thisArg] - function context 
* @returns {Function} waterfall function
*/
function factory( fcns, clbk, thisArg ) {
	if ( !isFunctionArray( fcns ) ) {
		throw new TypeError( 'invalid input argument. First argument must be a function array. Value: `' + fcns + '`.' );
	}
	if ( !isFunction( clbk ) ) {
		throw new TypeError( 'invalid input argument. Second argument must be a function. Value: `' + clbk + '`.' );
	}
	/**
	* FUNCTION: waterfall()
	*	Invokes functions in series, passing the results of one function as arguments to the next function. 
	*
	* @returns {Void}
	*/
	return function waterfall() {
		var idx = -1;
		next();
		/**
		* FUNCTION: next( error, ...args )
		*	Invokes the next function in the series.
		*
		* @private
		* @param {Error|Null} error - error object
		* @param {...*} args - results to pass to next callback
		* @returns {Void}
		*/
		function next() {
			var args;
			var len;
			var i;

			// Check for an error...
			if ( arguments[ 0 ] ) {
				return clbk( arguments[ 0 ] );
			}
			// Update the counter and check if we have run all functions...
			idx += 1;
			if ( idx >= fcns.length ) {
				return clbk();
			}
			// Copy the remaining arguments...
			len = arguments.length;
			args = new Array( len );
			for ( i = 0; i < len-1; i++ ) {
				args[ i ] = arguments[ i+1 ];
			}
			// Add the callback:
			args[ i ] = next;

			// Apply the arguments to the next function in the waterfall:
			fcns[ idx ].apply( thisArg, args );
		} // end FUNCTION next()
	}; // end FUNCTION waterfall()
} // end FUNCTION factory()
Example #8
0
// FACTORY //

/**
* FUNCTION: factory( options, clbk )
*	Returns a function for sending a POST request to a Travis CI API endpoint.
*
* @param {Object} options - function options
* @param {String} [options.protocol='https'] - request protocol
* @param {String} [options.hostname='api.travis-ci.org'] - endpoint hostname
* @param {Number} [options.port] - endpoint port
* @param {String} [options.pathname='/'] - resource pathname
* @param {String} [options.query=""] - params portion of a query string
* @param {String} [options.token] - Travis CI access token
* @param {String} [options.accept='application/vnd.travis-ci.2+json'] - media type
* @param {String} [options.useragent] - user agent string
* @param {Function} clbk - callback to invoke upon query completion
* @returns {Function} function for sending a POST request
*/
function factory( options, clbk ) {
	var opts;
	var err;
	opts = copy( defaults );
	err = validate( opts, options );
	if ( err ) {
		throw err;
	}
	if ( opts.port === null ) {
		if ( opts.protocol === 'https' ) {
			opts.port = DEFAULT_HTTPS_PORT;
		} else {
			opts.port = DEFAULT_HTTP_PORT;
		}
	}
	if ( !isFunction( clbk ) ) {
		throw new TypeError( 'invalid input argument. Callback argument must be a function. Value: `' + clbk + '`.' );
	}
	/**
	* FUNCTION: post( [data] )
	*	Sends a POST request to an endpoint.
	*
	* @param {String|Object} [data] - request data
	* @returns {Void}
	*/
	return function post( data ) {
		var d;
		if ( arguments.length && !isString( data ) && !isObject( data ) ) {
			throw new TypeError( 'invalid input argument. Request data must be either a string or an object. Value: `' + data + '`.' );
		}
		d = data || '';
		query( d, opts, done );
	}; // end FUNCTION post()

	/**
	* FUNCTION: done( error, results )
	*	Callback invoked after completing query.
	*
	* @private
	* @param {Error|Null} error - error object
	* @param {Object[]} results - query results
	* @returns {Void}
	*/
	function done( error, results ) {
		if ( error ) {
			return clbk( error );
		}
		clbk( null, results );
	} // end FUNCTION done()
} // end FUNCTION factory()
Example #9
0
ConceptNet.prototype.search = function( params, callback ) {
	if ( !isObject( params ) ) {
		throw new TypeError( 'invalid input argument. First argument must be an parameter object. Value: `' + params + '`.' );
	}
	if ( !isFunction( callback ) ) {
		throw new TypeError( 'invalid input argument. Second argument must be a callback function. Value: `' + callback + '`.' );
	}
	var path = '/data/' + this.version + '/search?';
	var str = querystring.stringify( params );

	str = querystring.unescape( str );
	path += str;
	this.makeHtppRequest( this.buildOptions( path ), callback );
}; // end METHOD search()
Example #10
0
ConceptNet.prototype.association = function() {
	var args = arguments;
	var nargs = args.length;
	var input;
	var params;
	var callback;
	var err;
	var limit;
	var path;

	if ( nargs < 2 ) {
		throw new Error( 'insufficient input arguments. Must provide an input string and a callback function.' );
	}
	input = args[ 0 ];
	if ( nargs < 3 ) {
		params = {};
		callback = args [ 1 ];
	} else {
		params = args[ 1 ];
		if ( !isObject( params ) ) {
			throw new TypeError( 'invalid input argument. Second argument must be an object. Value: `' + params + '`.' );
		}
		callback = args [ 2 ];
	}

	if ( !isFunction( callback ) ) {
		throw new TypeError( 'invalid input argument. Third argument must be a function. Value: `' + callback + '`.' );
	}
	if( !isConceptNetURI( input ) && !isValidTermPath( input ) ) {
		err = new Error( 'The input argument must be either a valid ConceptNet URI or a path of the form ' +
			'/list/<language>/<term list>' );
		throw err;
	}

	limit = params.limit || 10;
	path = '/data/' + this.version + '/assoc' + String( input );

	if ( params.filter ) {
		if ( isConceptNetURI( params.filter ) ) {
			path += '?filter=' + params.filter + '&limit=' + limit;
		} else {
			err = new Error( 'The GET argument filter must be a valid ConceptNet URI.' );
			throw err;
		}
	}
	this.makeHtppRequest( this.buildOptions( path ), callback );
}; // end METHOD association()
Example #11
0
// FACTORY //

/**
* FUNCTION: factory( options, clbk )
*	Returns a function for converting a TeX or LaTeX string to an SVG.
*
* @param {Object} options - function options
* @param {Number} [options.width=100] - container width in `ex`
* @param {Number} [options.ex=6] - `ex` size in pixels
* @param {Boolean} [options.inline=false] - specifies whether to format the input string as an inline equation
* @param {Boolean} [options.linebreaks=true] - enable linebreaking
* @param {Function} clbk - callback to invoke upon converting a string to an SVG
* @returns {Function} function to convert a string to an SVG
*/
function factory( options, clbk ) {
	var opts;
	var err;
	opts = copy( defaults );
	err = validate( opts, options );
	if ( err ) {
		throw err;
	}
	if ( !isFunction( clbk ) ) {
		throw new TypeError( 'invalid input argument. Callback argument must be a function. Value: `' + clbk + '`.' );
	}
	if ( opts.inline === true ) {
		opts.format = 'inline-TeX';
	}
	delete opts.inline;
	/**
	* FUNCTION: tex2svg( str )
	*	Converts a TeX or LaTeX string to an SVG.
	*
	* @param {String} str - string to convert
	* @returns {Void}
	*/
	return function tex2svg( str ) {
		if ( !isString( str ) ) {
			throw new TypeError( 'invalid input argument. Must provide a string primitive. Value: `' + str + '`.' );
		}
		opts.math = str;
		mathjax.typeset( opts, done );
		/**
		* FUNCTION: done( data )
		*	Callback invoked upon converting a string to SVG.
		*
		* @private
		* @param {Object} data - output
		* @returns {Void}
		*/
		function done( data ) {
			var err;
			if ( data.errors ) {
				err = new Error( data.errors[ 0 ] );
				return clbk( err );
			}
			clbk( null, data.svg );
		} // end FUNCTION done()
	}; // end FUNCTION tex2svg()
} // end FUNCTION factory()
Example #12
0
ConceptNet.prototype.lookup = function() {
	var args = arguments;
	var nargs = args.length;
	var uri;
	var params;
	var callback;
	var limit;
	var offset;

	if ( nargs < 2 ) {
		throw new Error( 'insufficient input arguments. Must provide a ConceptNet URI and a callback function.' );
	}

	uri = args[ 0 ];
	if ( !isString( uri ) ) {
		throw new TypeError( 'invalid input argument. First argument must be a string primitive. Value: `' + uri + '`.' );
	}
	if ( nargs < 3 ) {
		limit = 50;
		offset = 0;
		callback = args[ 1 ];
	} else {
		params = args[ 1 ];
		if ( !isObject( params ) ) {
			throw new TypeError( 'invalid input argument. Params argument must be an object. Value: `' + params + '`.' );
		}
		callback = args[ 2 ];
		limit = params.limit || 50;
		offset = params.offset || 0;
	}

	if ( !isFunction( callback ) ) {
		throw new TypeError( 'invalid input argument. Last argument must be a callback function. Value: `' + callback + '`.' );
	}

	var path = '/data/' + this.version + String( encodeURIComponent( uri ) );
	path += '?limit=' + limit + '&offset=' + offset;

	if ( params.filter === 'core' ) {
		path += '&filter=core';
	}

	this.makeHtppRequest( this.buildOptions( path ), callback );
}; // end METHOD lookup()
Example #13
0
// CANBERRA DISTANCE //

/**
* FUNCTION: canberra( x, y[, accessor])
*		Computes the Canberra distance between two arrays.
*
* @param {Number[]|Array} x - input array
* @param {Number[]|Array} y - input array
* @param {Function} [accessor] - accessor function for accessing array values
* @returns {Number|Null} Canberra distance
*/
function canberra( x, y, clbk ) {

	var d, i, v, len, num, denom, xVal, yVal;

	if ( !isArray( x ) ) {
			throw new TypeError( 'invalid input argument. First argument must be an array. Value: `' + x + '`.' );
		}
		if ( !isArray( y ) ) {
			throw new TypeError( 'invalid input argument. Second argument must be an array. Value: `' + y + '`.' );
		}
		if ( arguments.length > 2 ) {
			if ( !isFunction( clbk ) ) {
				throw new TypeError( 'invalid input argument. Accessor must be a function. Value: `' + clbk + '`.' );
			}
		}
		len = x.length;
		if ( len !== y.length ) {
			throw new Error( 'invalid input argument. Input arrays must have the same length.' );
		}
		if ( !len ) {
			return null;
		}

	d = 0;
	if ( clbk ) {
		for ( i = 0; i < len; i++ ) {
			xVal = clbk( x[i], i, 0 );
			yVal = clbk( y[i], i, 1 );
			v = xVal - yVal;
			num = ( v < 0 ) ? -v : v;
			denom = ( ( xVal < 0 ) ? -xVal : xVal ) + ( ( yVal < 0 ) ? -yVal : yVal );
			d += num / denom;
		}
	} else {
		for ( i = 0; i < len; i++ ) {
			v = x[ i ] - y[ i ];
			num = ( v < 0 ) ? -v : v;
			denom = ( ( x[ i ] < 0 ) ? -x[ i ] : x[ i ] ) + ( ( y[ i ] < 0 ) ? -y[ i ] : y[ i ] );
			d += num / denom;
		}
	}
	return d;
} // end FUNCTION canberra()
Example #14
0
// VALIDATE //

/**
* FUNCTION: validate( opts, options )
*	Validates function options.
*
* @param {Object} opts - destination for validated options
* @param {Object} options - function options
* @param {Boolean} [options.copy] - boolean indicating if the function should return a new data structure
* @param {Function} [options.accessor] - accessor function for accessing array values
* @param {String} [options.sep] - deep get/set key path separator
* @param {String} [options.path] - deep get/set key path
* @param {String} [options.dtype] - output data type
* @returns {Null|Error} null or an error
*/
function validate( opts, options ) {
	if ( !isObject( options ) ) {
		return new TypeError( 'erf()::invalid input argument. Options argument must be an object. Value: `' + options + '`.' );
	}
	if ( options.hasOwnProperty( 'copy' ) ) {
		opts.copy = options.copy;
		if ( !isBoolean( opts.copy ) ) {
			return new TypeError( 'erf()::invalid option. Copy option must be a boolean primitive. Option: `' + opts.copy + '`.' );
		}
	}
	if ( options.hasOwnProperty( 'accessor' ) ) {
		opts.accessor = options.accessor;
		if ( !isFunction( opts.accessor ) ) {
			return new TypeError( 'erf()::invalid option. Accessor must be a function. Option: `' + opts.accessor + '`.' );
		}
	}
	if ( options.hasOwnProperty( 'path' ) ) {
		opts.path = options.path;
		if ( !isString( opts.path ) ) {
			return new TypeError( 'erf()::invalid option. Key path option must be a string primitive. Option: `' + opts.path + '`.' );
		}
	}
	if ( options.hasOwnProperty( 'sep' ) ) {
		opts.sep = options.sep;
		if ( !isString( opts.sep ) ) {
			return new TypeError( 'erf()::invalid option. Separator option must be a string primitive. Option: `' + opts.sep + '`.' );
		}
	}
	if ( options.hasOwnProperty( 'dtype' ) ) {
		opts.dtype = options.dtype;
		if ( !isString( opts.dtype ) ) {
			return new TypeError( 'erf()::invalid option. Data type option must be a string primitive. Option: `' + opts.dtype + '`.' );
		}
	}
	return null;
} // end FUNCTION validate()
Example #15
0
// MANHATTAN DISTANCE //

/**
* FUNCTION: manhattan( x, y[, accessor] )
*	Computes the Manhattan distance between two arrays.
*
* @param {Number[]|Array} x - input array
* @param {Number[]|Array} y - input array
* @param {Function} [accessor] - accessor function for accessing array values
* @returns {Number|Null} Manhattan distance or null
*/
function manhattan( x, y, clbk ) {
	var len,
		d, v,
		i;
	if ( !isArray( x ) ) {
		throw new TypeError( 'manhattan()::invalid input argument. First argument must be an array. Value: `' + x + '`.' );
	}
	if ( !isArray( y ) ) {
		throw new TypeError( 'manhattan()::invalid input argument. Second argument must be an array. Value: `' + y + '`.' );
	}
	if ( arguments.length > 2 ) {
		if ( !isFunction( clbk ) ) {
			throw new TypeError( 'manhattan()::invalid input argument. Accessor must be a function. Value: `' + clbk + '`.' );
		}
	}
	len = x.length;
	if ( len !== y.length ) {
		throw new Error( 'manhattan()::invalid input arguments. Input arrays must have the same length.' );
	}
	if ( !len ) {
		return null;
	}
	d = 0;
	if ( clbk ) {
		for ( i = 0; i < len; i++ ) {
			v = clbk( x[i], i, 0 ) - clbk( y[i], i, 1 );
			d += ( v < 0 ) ? -v : v;
		}
	} else {
		for ( i = 0; i < len; i++ ) {
			v = x[ i ] - y[ i ];
			d += ( v < 0 ) ? -v : v;
		}
	}
	return d;
} // end FUNCTION manhattan()
Example #16
0
// SUBSEQUENCE SET //

/**
* FUNCTION: sset( subsequence, value[, thisArg] )
*	Sets matrix elements according to a specified subsequence.
*
* @param {String} subsequence - subsequence string
* @param {Number|Matrix|Function} value - either a single numeric value, a matrix containing the values to set, or a function which returns a numeric value
* @param {Object} [thisArg] - `this` context when executing a callback
* @returns {Matrix} Matrix instance
*/
function sset( seq, val, thisArg ) {
	/* jshint validthis: true */
	var nRows,
		nCols,
		clbk,
		rows,
		cols,
		seqs,
		mat,
		ctx,
		s0, s1, s2, s3,
		o0, o1,
		r0, r1,
		i, j, k;

	if ( !isString( seq ) ) {
		throw new TypeError( 'invalid input argument. Must provide a string primitive. Value: `' + seq + '`.' );
	}
	seqs = seq.split( ',' );
	if ( seqs.length !== 2 ) {
		throw new Error( 'invalid input argument. Subsequence string must specify row and column subsequences. Value: `' + seq + '`.' );
	}
	if ( isFunction( val ) ) {
		clbk = val;
	}
	else if ( !isNumber( val ) ) {
		mat = val;
	}
	rows = ispace( seqs[ 0 ], this.shape[ 0 ] );
	cols = ispace( seqs[ 1 ], this.shape[ 1 ] );

	nRows = rows.length;
	nCols = cols.length;

	if ( !( nRows && nCols ) ) {
		return this;
	}
	s0 = this.strides[ 0 ];
	s1 = this.strides[ 1 ];
	o0 = this.offset;

	// Callback...
	if ( clbk ) {
		if ( arguments.length > 2 ) {
			ctx = thisArg;
		} else {
			ctx = this;
		}
		for ( i = 0; i < nRows; i++ ) {
			r0 = o0 + rows[i]*s0;
			for ( j = 0; j < nCols; j++ ) {
				k = r0 + cols[j]*s1;
				this.data[ k ] = clbk.call( ctx, this.data[ k ], rows[i], cols[j], k );
			}
		}
	}
	// Input matrix...
	else if ( mat ) {
		if ( nRows !== mat.shape[ 0 ] ) {
			throw new Error( 'invalid input arguments. Row subsequence does not match input matrix dimensions. Expected a [' + nRows + ',' + nCols + '] matrix and instead received a [' + mat.shape.join( ',' ) + '] matrix.' );
		}
		if ( nCols !== mat.shape[ 1 ] ) {
			throw new Error( 'invalid input arguments. Column subsequence does not match input matrix dimensions. Expected a [' + nRows + ',' + nCols + '] matrix and instead received a [' + mat.shape.join( ',' ) + '] matrix.' );
		}
		s2 = mat.strides[ 0 ];
		s3 = mat.strides[ 1 ];
		o1 = mat.offset;
		for ( i = 0; i < nRows; i++ ) {
			r0 = o0 + rows[i]*s0;
			r1 = o1 + i*s2;
			for ( j = 0; j < nCols; j++ ) {
				this.data[ r0 + cols[j]*s1 ] = mat.data[ r1 + j*s3 ];
			}
		}
	}
	// Single numeric value...
	else {
		for ( i = 0; i < nRows; i++ ) {
			r0 = o0 + rows[i]*s0;
			for ( j = 0; j < nCols; j++ ) {
				this.data[ r0 + cols[j]*s1 ] = val;
			}
		}
	}
	return this;
} // end FUNCTION sset()
Example #17
0
} // end FUNCTION getIndices()


// MSET //

/**
* FUNCTION: mset( i[, j], value[, thisArg] )
*	Sets multiple matrix elements. If provided a single array, `i` is treated as an array of linear indices.
*
* @param {Number[]|Null} i - linear/row indices
* @param {Number[]|Null} [j] - column indices
* @param {Number|Matrix|Function} value - either a single numeric value, a matrix containing the values to set, or a function which returns a numeric value
* @returns {Matrix} Matrix instance
*/
function mset() {
	/*jshint validthis:true */
	var nargs = arguments.length,
		args,
		rows,
		cols,
		i;

	args = new Array( nargs );
	for ( i = 0; i < nargs; i++ ) {
		args[ i ] = arguments[ i ];
	}

	// 2 input arguments...
	if ( nargs < 3 ) {
		if ( !isNonNegativeIntegerArray( args[ 0 ] ) ) {
			throw new TypeError( 'invalid input argument. First argument must be an array of nonnegative integers. Value: `' + args[ 0 ] + '`.' );
		}
		// indices, clbk
		if ( isFunction( args[ 1 ] ) ) {
			mset2( this, args[ 0 ], args[ 1 ] );
		}
		// indices, number
		else if ( isNumber( args[ 1 ] ) || isnan( args[ 1 ] ) ) {
			mset1( this, args[ 0 ], args[ 1 ] );
		}
		// indices, matrix
		else {
			// NOTE: no validation for Matrix instance.
			mset3( this, args[ 0 ], args[ 1 ] );
		}
	}
	// 3 input arguments...
	else if ( nargs === 3 ) {
		// indices, clbk, context
		if ( isFunction( args[ 1 ] ) ) {
			if ( !isNonNegativeIntegerArray( args[ 0 ] ) ) {
				throw new TypeError( 'invalid input argument. First argument must be an array of nonnegative integers. Value: `' + args[ 0 ] + '`.' );
			}
			mset2( this, args[ 0 ], args[ 1 ], args[ 2 ] );
		}
		// rows, cols, function
		else if ( isFunction( args[ 2 ] ) ) {
			rows = getIndices( args[ 0 ], this.shape[ 0 ] );
			cols = getIndices( args[ 1 ], this.shape[ 1 ] );
			mset4( this, rows, cols, args[ 2 ], this );
		}
		// rows, cols, number
		else if ( isNumber( args[ 2 ] ) ) {
			rows = getIndices( args[ 0 ], this.shape[ 0 ] );
			cols = getIndices( args[ 1 ], this.shape[ 1 ] );
			mset5( this, rows, cols, args[ 2 ] );
		}
		// rows, cols, matrix
		else {
			rows = getIndices( args[ 0 ], this.shape[ 0 ] );
			cols = getIndices( args[ 1 ], this.shape[ 1 ] );

			// NOTE: no validation for Matrix instance.
			mset6( this, rows, cols, args[ 2 ] );
		}
	}
	// 4 input arguments...
	else {
		// rows, cols, function, context
		if ( !isFunction( args[ 2 ] ) ) {
			throw new TypeError( 'invalid input argument. Callback argument must be a function. Value: `' + args[ 2 ] + '`.' );
		}
		rows = getIndices( args[ 0 ], this.shape[ 0 ] );
		cols = getIndices( args[ 1 ], this.shape[ 1 ] );
		mset4( this, rows, cols, args[ 2 ], args[ 3 ] );
	}
	return this;
} // end FUNCTION mset()
Example #18
0
// MOVING SUM //

/**
* FUNCTION: msum( arr, W[, options] )
*	Computes a moving sum over an array.
*
* @param {Array} arr - input array
* @param {Number} W - size of moving window
* @param {Object} [options] - function options
* @param {Function} [options.accessor] - accessor function for accessing numeric values
* @param {Boolean} [options.copy=true] - boolean indicating whether to return a new array of window sums
* @returns {Array} array of window sum values
*/
function msum( arr, W, options ) {
	var copy = true,
		clbk,
		len,
		sum,
		dropVal,
		out,
		i;
	if ( !isArray( arr ) ) {
		throw new TypeError( 'msum()::invalid input argument. Must provide an array. Value: `' + arr + '`.' );
	}
	if ( !isPositiveInteger( W ) ) {
        throw new TypeError( 'msum()::invalid input argument. Window must be a positive integer. Value: `' + W + '`.' );
    }
	if ( arguments.length > 2 ) {
		if ( !isObject( options ) ) {
			throw new TypeError( 'msum()::invalid input argument. Options must be an object. Value: `' + options + '`.' );
		}
		if ( options.hasOwnProperty( 'accessor' ) ) {
			clbk = options.accessor;
			if ( !isFunction( clbk ) ) {
				throw new TypeError( 'msum()::invalid option. Accessor option must be a function. Value: `' + clbk + '`.' );
			}
		}
		if ( options.hasOwnProperty( 'copy' ) ) {
			copy = options.copy;
			if ( !isBoolean( copy ) ) {
				throw new TypeError( 'msum()::invalid option. Copy option must be a boolean primitive. Value: `' + copy + '`.' );
			}
		}
	}
	if ( W > arr.length ) {
		throw new Error( 'msum()::invalid input argument. Window cannot exceed the array length.' );
	}
	len = arr.length;
	sum = 0;

	if ( copy && !clbk ) {
		// Case 1: numeric array and return a copy...
		len = len - W + 1;
		out = new Array( len );

		// Calculate the sum for the first window...
		for ( i = 0; i < W; i++ ) {
			sum += arr[ i ];
		}
		out[ 0 ] = sum;

		// Calculate sums for the remaining windows...
		for ( i = 0; i < len-1; i++ ){
			sum += arr[ i+W ] - arr[ i ];
			out[ i+1 ] = sum;
		}
		return out;
	}
	else if ( clbk ) {
		if ( copy ) {
			// Case 2: non-numeric array and return a copy...
			out = new Array( len );
			for ( i = 0; i < len; i++ ){
				out[ i ] = clbk( arr[i] );
			}
		} else {
			// Case 3: non-numeric array and mutate the input array...
			out = arr;
			for ( i = 0; i < len; i++ ) {
				out[ i ] = clbk( arr[i] );
			}
		}
	}
	else {
		// Case 4: numeric array and mutate the input array...
		out = arr;
	}
	len = len - W + 1;

	// Calculate the sum for the first window...
	for ( i = 0; i < W; i++ ) {
		sum += out[ i ];
	}
	dropVal = out[ 0 ];
	out[ 0 ] = sum;

	// Calculate sums for the remaining windows...
	for ( i = 1; i < len; i++ ){
		sum += out[ i+W-1 ] - dropVal;
		dropVal = out[ i ];
		out[ i ] = sum;
	}
	// Trim the output array:
	out.length = len;
	return out;
} // end FUNCTION msum()
Example #19
0
// MINKOWSKI DISTANCE //

/**
* FUNCTION: minkowski( x, y[, options] )
*	Computes the Minkowski distance between two arrays.
*
* @param {Number[]|Array} x - input array
* @param {Number[]|Array} y - input array
* @param {Object} [options] - function options
* @param {Number} [options.p=2] - norm order
* @param {Function} [options.accessor] - accessor function for accessing array values
* @returns {Number|Null} Minkowski distance or null
*/
function minkowski( x, y, opts ) {
	var p = 2,
		clbk,
		len,
		d, v,
		i;

	if ( arguments.length > 2 ) {
		if ( !isObject( opts ) ) {
			throw new TypeError( 'minkowski()::invalid input argument. Options argument must be an object. Value: `' + opts + '`.' );
		}
		if ( opts.hasOwnProperty( 'p' ) ) {
			p = opts.p;
			if ( !isNumber( p ) || p <= 0 ) {
				throw new TypeError( 'minkowski()::invalid option. `p` option must be a positive number primitive. Option: `' + p + '`.' );
			}
		}
		if ( opts.hasOwnProperty( 'accessor' ) ) {
			clbk = opts.accessor;
			if ( !isFunction( clbk ) ) {
				throw new TypeError( 'minkowski()::invalid option. Accessor must be a function. Option: `' + clbk + '`.' );
			}
		}
	}
	// If norm order corresponds to a known metric, delegate type checking and execution to the respective implementation...
	if ( p === 2 ) {
		return ( clbk ) ? euclidean( x, y, clbk ) : euclidean( x, y );
	}
	else if ( p === 1 ) {
		return ( clbk ) ? manhattan( x, y, clbk ) : manhattan( x, y );
	}
	else if ( p === Number.POSITIVE_INFINITY ) {
		return ( clbk ) ? chebyshev( x, y, clbk ) : chebyshev( x, y );
	}
	// Proceed with the general distance algorithm...
	if ( !isArray( x ) ) {
		throw new TypeError( 'minkowski()::invalid input argument. First argument must be a number array. Value: `' + x + '`.' );
	}
	if ( !isArray( y ) ) {
		throw new TypeError( 'minkowski()::invalid input argument. Second argument must be a number array. Value: `' + y + '`.' );
	}
	len = x.length;
	if ( len !== y.length ) {
		throw new TypeError( 'minkowski()::invalid input arguments. Input arrays must have the same length.' );
	}
	if ( !len ) {
		return null;
	}
	d = 0;
	if ( clbk ) {
		for ( i = 0; i < len; i++ ) {
			v = clbk( x[i], i, 0 ) - clbk( y[i], i, 1 );
			if ( v < 0 ) {
				v = -v;
			}
			d += Math.pow( v, p );
		}
	} else {
		for ( i = 0; i < len; i++ ) {
			v = x[ i ] - y[ i ];
			if ( v < 0 ) {
				v = -v;
			}
			d += Math.pow( v, p );
		}
	}
	return Math.pow( d, 1/p );
} // end FUNCTION minkowski()
Example #20
0
// COPY //

/**
* FUNCTION: cp( dest[, opts ][, clbk ] )
*	Asynchronously creates a .gitignore file.
*
* @param {String} dest - .gitignore destination directory
* @param {Object} [opts] - function options
* @param {String} [opts.template="default"] - .gitignore template to use
* @param {Function} [clbk] - callback to invoke upon attempting to create a .gitignore file
*/
function cp() {
	var args = arguments,
		nargs = args.length,
		tmpl = 'default',
		rStream,
		wStream,
		fpath,
		dpath,
		opts,
		dest,
		clbk;

	if ( !nargs ) {
		throw new Error( 'cp()::insufficient input arguments. Must provide a file destination.' );
	}
	dest = args[ 0 ];
	if ( !isString( dest ) ) {
		throw new TypeError( 'cp()::invalid input argument. First argument must be a string primitive. Value: `' + dest + '`.' );
	}
	if ( nargs === 1 ) {
		clbk = noop;
	}
	else if ( nargs === 2 ) {
		if ( isObject( args[ 1 ] ) ) {
			opts = args[ 1 ];
			clbk = noop;
		}
		else if ( isFunction( args[ 1 ] ) ) {
			clbk = args[ 1 ];
		}
		else {
			throw new TypeError( 'cp()::invalid input argument. Second argument must either be an options object or a callback. Value: `' + args[ 1 ] + '`.' );
		}
	}
	else {
		opts = args[ 1 ];
		clbk = args[ 2 ];
		if ( !isObject( opts ) ) {
			throw new TypeError( 'cp()::invalid input argument. Options argument must be an object. Value: `' + opts + '`.' );
		}
		if ( !isFunction( clbk ) ) {
			throw new TypeError( 'cp()::invalid input argument. Callback argument must be a function. Value: `' + clbk + '`.' );
		}
	}
	if ( opts ) {
		if ( opts.hasOwnProperty( 'template' ) ) {
			tmpl = opts.template;
			if ( !isString( tmpl ) ) {
				throw new TypeError( 'cp()::invalid option. Template option must be a string primitive. Option: `' + tmpl + '`.' );
			}
			if ( !contains( templates, tmpl ) ) {
				throw new Error( 'cp()::invalid option. Unrecognized template name. Must be one of [' + templates.join( ',' ) + '] Option: `' + tmpl + '`.' );
			}
		}
	}
	fpath = path.join( __dirname, tmpl, 'gitignore' );
	dpath = path.join( dest, '.gitignore' );

	rStream = fs.createReadStream( fpath );
	wStream = fs.createWriteStream( dpath );

	wStream.on( 'error', onError );
	wStream.on( 'finish', onFinish );

	rStream.pipe( wStream );

	/**
	* FUNCTION: onError( error )
	*	Callback invoked upon a writeStream error.
	*
	* @private
	* @param {Error} error - error object
	*/
	function onError( error ) {
		clbk( error );
	}

	/**
	* FUNCTION: onFinish()
	*	Callback invoked once a writeStream is finished writing.
	*
	* @private
	*/
	function onFinish() {
		clbk();
	}
} // end FUNCTION cp()
Example #21
0
// DIVIDE //

/**
* FUNCTION: divide( arr, x[, opts] )
*	Computes an element-wise division.
*
* @param {Number[]|Array} arr - input array
* @param {Number[]|Array|Number} x - either an array of equal length or a scalar
* @param {Object} [opts] - function options
* @param {Boolean} [opts.copy=true] - boolean indicating whether to return a new array
* @param {Function} [opts.accessor] - accessor function for accessing array values
* @returns {Number[]} output array
*/
function divide( arr, x, opts ) {
	var isArr = isArray( x ),
		copy = true,
		arity,
		clbk,
		out,
		len,
		i;

	if ( !isArray( arr ) ) {
		throw new TypeError( 'divide()::invalid input argument. Must provide an array. Value: `' + arr + '`.' );
	}
	if ( !isArr && !isNumber( x ) ) {
		throw new TypeError( 'divide()::invalid input argument. Second argument must either be an array or number primitive. Value: `' + x + '`.' );
	}
	if ( arguments.length > 2 ) {
		if ( !isObject( opts ) ) {
			throw new TypeError( 'divide()::invalid input argument. Options argument must be an object. Value: `' + opts + '`.' );
		}
		if ( opts.hasOwnProperty( 'copy' ) ) {
			copy = opts.copy;
			if ( !isBoolean( copy ) ) {
				throw new TypeError( 'divide()::invalid option. Copy option must be a boolean primitive. Option: `' + copy + '`.' );
			}
		}
		if ( opts.hasOwnProperty( 'accessor' ) ) {
			clbk = opts.accessor;
			if ( !isFunction( clbk ) ) {
				throw new TypeError( 'divide()::invalid option. Accessor must be a function. Option: `' + clbk + '`.' );
			}
			arity = clbk.length;
		}
	}
	len = arr.length;
	if ( copy ) {
		out = new Array( len );
	} else {
		out = arr;
	}
	// Case 1: x is an array
	if ( isArr ) {
		if ( len !== x.length ) {
			throw new Error( 'divide()::invalid input argument. Array to be divideed must have a length equal to that of the input array.' );
		}
		if ( arity === 3 ) { // clbk implied
			for ( i = 0; i < len; i++ ) {
				out[ i ] = clbk( arr[i], i, 0 ) / clbk( x[i], i, 1 );
			}
		}
		else if ( clbk ) {
			for ( i = 0; i < len; i++ ) {
				out[ i ] = clbk( arr[i], i ) / x[ i ];
			}
		}
		else {
			for ( i = 0; i < len; i++ ) {
				out[ i ] = arr[ i ] / x[ i ];
			}
		}
	}
	// Case 2: accessor and scalar
	else if ( clbk ) {
		for ( i = 0; i < len; i++ ) {
			out[ i ] = clbk( arr[i], i ) / x;
		}
	}
	// Case 3: scalar
	else {
		for ( i = 0; i < len; i++ ) {
			out[ i ] = arr[ i ] / x;
		}
	}
	return out;
} // end FUNCTION divide()
Example #22
0
// GREATER THAN OR EQUAL TO //

/**
* FUNCTION: geq( arr, x[, opts] )
*	Computes an element-wise comparison (greater than or equal to) of an array.
*
* @param {Number[]|Array} arr - input array
* @param {Number[]|Array|Number|String} x - comparator
* @param {Object} [opts] - function options
* @param {Boolean} [opts.copy=true] - boolean indicating whether to return a new array
* @param {Function} [opts.accessor] - accessor function for accessing array values
* @returns {Number[]} array of 1s and 0s, where a `1` indicates that an input array element is greater than or equal to a compared value and `0` indicates that an input array element is not greater than or equal to a compared value
*/
function geq( arr, x, opts ) {
	var isArr = isArray( x ),
		copy = true,
		arity,
		clbk,
		out,
		len,
		i;

	if ( !isArray( arr ) ) {
		throw new TypeError( 'geq()::invalid input argument. Must provide an array. Value: `' + arr + '`.' );
	}
	if ( !isArr && !isNumber( x ) && !isString( x ) ) {
		throw new TypeError( 'geq()::invalid input argument. Comparison input must either be an array, number primitive, or string primitive. Value: `' + x + '`.' );
	}
	if ( arguments.length > 2 ) {
		if ( !isObject( opts ) ) {
			throw new TypeError( 'geq()::invalid input argument. Options argument must be an object. Value: `' + opts + '`.' );
		}
		if ( opts.hasOwnProperty( 'copy' ) ) {
			copy = opts.copy;
			if ( !isBoolean( copy ) ) {
				throw new TypeError( 'geq()::invalid option. Copy option must be a boolean primitive. Option: `' + copy + '`.' );
			}
		}
		if ( opts.hasOwnProperty( 'accessor' ) ) {
			clbk = opts.accessor;
			if ( !isFunction( clbk ) ) {
				throw new TypeError( 'geq()::invalid option. Accessor must be a function. Option: `' + clbk + '`.' );
			}
			arity = clbk.length;
		}
	}
	len = arr.length;
	if ( copy ) {
		out = new Array( len );
	} else {
		out = arr;
	}
	// Case 1: comparison array
	if ( isArr ) {
		if ( len !== x.length ) {
			throw new Error( 'geq()::invalid input argument. Comparison array must have a length equal to that of the input array.' );
		}
		if ( arity === 3 ) { // clbk implied
			for ( i = 0; i < len; i++ ) {
				if ( clbk( arr[i], i, 0 ) >= clbk( x[i], i, 1 ) ) {
					out[ i ] = 1;
				} else {
					out[ i ] = 0;
				}
			}
		}
		else if ( clbk ) {
			for ( i = 0; i < len; i++ ) {
				if ( clbk( arr[i], i ) >= x[ i ] ) {
					out[ i ] = 1;
				} else {
					out[ i ] = 0;
				}
			}
		}
		else {
			for ( i = 0; i < len; i++ ) {
				if ( arr[ i ] >= x[ i ] ) {
					out[ i ] = 1;
				} else {
					out[ i ] = 0;
				}
			}
		}
	}
	// Case 2: accessor and single comparator
	else if ( clbk ) {
		for ( i = 0; i < len; i++ ) {
			if ( clbk( arr[ i ], i ) >= x ) {
				out[ i ] = 1;
			} else {
				out[ i ] = 0;
			}
		}
	}
	// Case 3: single comparator
	else {
		for ( i = 0; i < len; i++ ) {
			if ( arr[ i ] >= x ) {
				out[ i ] = 1;
			} else {
				out[ i ] = 0;
			}
		}
	}
	return out;
} // end FUNCTION geq()
Example #23
0
// ALPHA //

/**
* FUNCTION: alpha( alphaScale )
*	Wraps a scale and returns a function.
*
* @param {Function} alphaScale - alpha-scale
* @returns {Function} function which maps an alpha-value to an opacity on [0,1]
*/
function alpha( d ) {
	/* jslint validthis:true */
	var alphaValue = this.alphaValue,
		alphaScale = this._alphaScale;
	return isFunction( alphaValue) ? alphaScale( alphaValue( d ) ) : alphaValue;
} // end FUNCTION alpha()
Example #24
0
// COPY //

/**
* FUNCTION: cp( dest[, opts ][, clbk ] )
*	Asynchronously creates a package.json file.
*
* @param {String} dest - package.json destination directory
* @param {Object} [opts] - function options
* @param {String} [opts.template="default"] - package.json template to use
* @param {String} [opts.name=""] - package name
* @param {String} [opts.desc=""] - package description
* @param {String} [opts.author=""] - package author
* @param {String} [opts.email=""] - package author email
* @param {String} [opts.repo=""] - package Github repository
* @param {String} [opts.cmd=""] - package command name, if package is a CLI tool
* @param {String[]} [opts.keywords] - package keywords
* @param {String} [opts.license="MIT"] - package license
* @param {Boolean} [opts.private=false] - boolean indicating whether a package is private
* @param {Function} [clbk] - callback to invoke upon attempting to create a package.json file
* @returns {Void}
*/
function cp() {
	var args = arguments,
		nargs = args.length,
		tmpl = 'default',
		opts = {},
		options,
		fpath,
		dpath,
		dest,
		clbk,
		err,
		flg;

	if ( !nargs ) {
		throw new Error( 'insufficient input arguments. Must provide a file destination.' );
	}
	dest = args[ 0 ];
	if ( !isString( dest ) ) {
		throw new TypeError( 'invalid input argument. First argument must be a string primitive. Value: `' + dest + '`.' );
	}
	if ( nargs === 1 ) {
		clbk = noop;
	}
	else if ( nargs === 2 ) {
		if ( isObject( args[ 1 ] ) ) {
			options = args[ 1 ];
			clbk = noop;
			flg = true;
		}
		else if ( isFunction( args[ 1 ] ) ) {
			clbk = args[ 1 ];
		}
		else {
			throw new TypeError( 'invalid input argument. Second argument must either be an options object or a callback. Value: `' + args[ 1 ] + '`.' );
		}
	}
	else {
		options = args[ 1 ];
		clbk = args[ 2 ];
		flg = true;
		if ( !isFunction( clbk ) ) {
			throw new TypeError( 'invalid input argument. Callback argument must be a function. Value: `' + clbk + '`.' );
		}
	}
	if ( flg ) {
		err = validate( opts, options );
		if ( err ) {
			throw err;
		}
	}
	opts = merge( {}, defaults[ tmpl ], opts );
	tmpl = opts.template || tmpl;

	opts.keywords = keywords( opts.keywords );

	fpath = path.join( __dirname, tmpl, 'package.json' );
	dpath = path.join( dest, 'package.json' );

	// Only check for name availability if a name has been provided...
	if ( opts.name ) {
		packageName( opts.name, isAvailable );
	} else {
		isAvailable( null, true );
	}

	/**
	* FUNCTION: isAvailable( error, bool )
	*	Callback invoked upon checking NPM name availability.
	*
	* @private
	* @param {Error|Null} error - error object
	* @param {Boolean} bool - boolean indicating whether an NPM name is available
	*/
	function isAvailable( error, bool ) {
		if ( error ) {
			return clbk( error );
		}
		if ( !bool ) {
			error = new Error( 'invalid option. Package name is not available on NPM. Option: `' + opts.name + '`.' );
			return clbk( error );
		}
		fs.readFile( fpath, {'encoding':'utf8'}, onRead );
	}

	/**
	* FUNCTION: onRead( error, file )
	*	Callback invoked upon reading a file.
	*
	* @private
	* @param {Error} error - error object
	* @param {String} file - file contents
	*/
	function onRead( error, file ) {
		var out;
		if ( error ) {
			return clbk( error );
		}
		out = mustache.render( file, opts );
		fs.writeFile( dpath, out, onWrite );
	}

	/**
	* FUNCTION: onWrite( error )
	*	Callback invoked upon writing a file.
	*
	* @private
	* @param {Error} error - error object
	*/
	function onWrite( error ) {
		if ( error ) {
			return clbk( error );
		}
		clbk();
	}
} // end FUNCTION cp()
Example #25
0
} // end FUNCTION bitwise()


// GREATEST COMMON DIVISOR //

/**
* FUNCTION: compute( arr[, clbk] )
*	Computes the greatest common divisor.
*
* @param {Number[]|Number} arr - input array of integers
* @param {Function|Number} [clbk] - accessor function for accessing array values
* @returns {Number|Null} greatest common divisor or null
*/
function compute() {
	var nargs = arguments.length,
		args,
		clbk,
		arr,
		len,
		a, b,
		i;

	// Copy the input arguments to an array...
	args = new Array( nargs );
	for ( i = 0; i < nargs; i++ ) {
		args[ i ] = arguments[ i ];
	}
	// Have we been provided with integer arguments?
	if ( isIntegerArray( args ) ) {
		if ( nargs === 2 ) {
			a = args[ 0 ];
			b = args[ 1 ];
			if ( a < 0 ) {
				a = -a;
			}
			if ( b < 0 ) {
				b = -b;
			}
			if ( a <= MAXINT && b <= MAXINT ) {
				return bitwise( a, b );
			} else {
				return gcd( a, b );
			}
		}
		arr = args;
	}
	// If not integers, ensure the first argument is an array...
	else if ( !isArray( args[ 0 ] ) ) {
		throw new TypeError( 'gcd()::invalid input argument. Must provide an array of integers. Value: `' + args[ 0 ] + '`.' );
	}
	// Have we been provided with more than one argument? If so, ensure that the accessor argument is a function...
	else if ( nargs > 1 ) {
		arr = args[ 0 ];
		clbk = args[ 1 ];
		if ( !isFunction( clbk ) ) {
			throw new TypeError( 'gcd()::invalid input argument. Accessor must be a function. Value: `' + clbk + '`.' );
		}
	}
	// We have been provided an array...
	else {
		arr = args[ 0 ];
	}
	len = arr.length;

	// Check if a sufficient number of values have been provided...
	if ( len < 2 ) {
		return null;
	}
	// If an accessor is provided, extract the array values...
	if ( clbk ) {
		a = new Array( len );
		for ( i = 0; i < len; i++ ) {
			a[ i ] = clbk( arr[ i ], i );
		}
		arr = a;
	}
	// Given an input array, ensure all array values are integers...
	if ( nargs < 3 ) {
		if ( !isIntegerArray( arr ) ) {
			throw new TypeError( 'gcd()::invalid input argument. Accessed array values must be integers. Value: `' + arr + '`.' );
		}
	}
	// Convert any negative integers to positive integers...
	for ( i = 0; i < len; i++ ) {
		a = arr[ i ];
		if ( a < 0 ) {
			arr[ i ] = -a;
		}
	}
	// Exploit the fact that the gcd is an associative function...
	a = arr[ 0 ];
	for ( i = 1; i < len; i++ ) {
		b = arr[ i ];
		if ( b <= MAXINT && a <= MAXINT ) {
			a = bitwise( a, b );
		} else {
			a = gcd( a, b );
		}
	}
	return a;
} // end FUNCTION compute()