// 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()
// 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()
// 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()
// 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()
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()
} // 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()
// 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()
// 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()
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()
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()
// 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()
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()
// 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()
// 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()
// 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()
// 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()
} // 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()
// 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()
// 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()
// 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()
// 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()
// 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()
// 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()
// 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()
} // 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()