time-to-botec

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

main.js (4256B)


      1 /**
      2 * @license Apache-2.0
      3 *
      4 * Copyright (c) 2018 The Stdlib Authors.
      5 *
      6 * Licensed under the Apache License, Version 2.0 (the "License");
      7 * you may not use this file except in compliance with the License.
      8 * You may obtain a copy of the License at
      9 *
     10 *    http://www.apache.org/licenses/LICENSE-2.0
     11 *
     12 * Unless required by applicable law or agreed to in writing, software
     13 * distributed under the License is distributed on an "AS IS" BASIS,
     14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15 * See the License for the specific language governing permissions and
     16 * limitations under the License.
     17 */
     18 
     19 'use strict';
     20 
     21 // MODULES //
     22 
     23 var isNumberArray = require( '@stdlib/assert/is-number-array' ).primitives;
     24 var isTypedArrayLike = require( '@stdlib/assert/is-typed-array-like' );
     25 var range = require( './../../base/range' );
     26 var lowess = require( './lowess.js' );
     27 var validate = require( './validate.js' );
     28 
     29 
     30 // FUNCTIONS //
     31 
     32 /**
     33 * Comparator function used to sort (x,y)-pairs in ascending order by the first coordinate.
     34 *
     35 * @private
     36 * @param {Array} a - first pair
     37 * @param {Array} b - second pair
     38 * @returns {number} difference between `a` and `b`
     39 */
     40 function ascending( a, b ) {
     41 	return a[ 0 ] - b[ 0 ];
     42 }
     43 
     44 
     45 // MAIN //
     46 
     47 /**
     48 * Locally-weighted polynomial regression via the LOWESS algorithm.
     49 *
     50 * ## References
     51 *
     52 * -   Cleveland, William S. 1979. "Robust Locally and Smoothing Weighted Regression Scatterplots." _Journal of the American Statistical Association_ 74 (368): 829–36. doi:[10.1080/01621459.1979.10481038](https://doi.org/10.1080/01621459.1979.10481038).
     53 * -   Cleveland, William S. 1981. "Lowess: A program for smoothing scatterplots by robust locally weighted regression." _American Statistician_ 35 (1): 54–55. doi:[10.2307/2683591](https://doi.org/10.2307/2683591).
     54 *
     55 * @param {NumericArray} x - ordered x-axis values (abscissa values)
     56 * @param {NumericArray} y - corresponding y-axis values (ordinate values)
     57 * @param {Options} options - function options
     58 * @param {PositiveNumber} [options.f=2/3] - smoother span (proportion of points which influence smoothing at each value)
     59 * @param {integer} [options.nsteps=3] - number of iterations in the robust fit (fewer iterations translates to faster function execution)
     60 * @param {NonNegativeNumber} [options.delta] - nonnegative parameter which may be used to reduce the number of computations
     61 * @param {boolean} [options.sorted=false] - boolean indicating if the input array `x` is already in sorted order
     62 * @throws {TypeError} first argument must be a numeric array
     63 * @throws {TypeError} second argument must be a numeric array
     64 * @throws {Error} arguments `x` and `y` must have the same length
     65 * @returns {Object} ordered x-values and fitted values
     66 */
     67 function main( x, y, options ) {
     68 	var nsteps;
     69 	var delta;
     70 	var opts;
     71 	var err;
     72 	var xy;
     73 	var f;
     74 	var i;
     75 	var n;
     76 	var r;
     77 
     78 	if ( !isTypedArrayLike( x ) && !isNumberArray( x ) ) {
     79 		throw new TypeError( 'invalid argument. First argument `x` must be a numeric array. Value: `' + x + '`.' );
     80 	}
     81 	if ( !isTypedArrayLike( y ) && !isNumberArray( y ) ) {
     82 		throw new TypeError( 'invalid argument. Second argument `y` must be a numeric array. Value: `' + y + '`.' );
     83 	}
     84 	n = x.length;
     85 	if ( y.length !== n ) {
     86 		throw new Error( 'invalid arguments. Arguments `x` and `y` must have the same length.' );
     87 	}
     88 	opts = {};
     89 	if ( arguments.length > 2 ) {
     90 		err = validate( opts, options );
     91 		if ( err ) {
     92 			throw err;
     93 		}
     94 	}
     95 	// Input data has to be sorted:
     96 	if ( opts.sorted !== true ) {
     97 		// Copy to prevent mutation and sort by x:
     98 		xy = new Array( n );
     99 		for ( i = 0; i < n; i++ ) {
    100 			xy[ i ] = [ x[ i ], y[ i ] ];
    101 		}
    102 		xy.sort( ascending ); // TODO: Revisit once we have function for sorting multiple arrays by the elements of one of the arrays
    103 		x = new Array( n );
    104 		y = new Array( n );
    105 		for ( i = 0; i < n; i++ ) {
    106 			x[ i ] = xy[ i ][ 0 ];
    107 			y[ i ] = xy[ i ][ 1 ];
    108 		}
    109 	}
    110 	if ( opts.nsteps === void 0 ) {
    111 		nsteps = 3;
    112 	} else {
    113 		nsteps = opts.nsteps;
    114 	}
    115 	if ( opts.f === void 0 ) {
    116 		f = 2.0/3.0;
    117 	} else {
    118 		f = opts.f;
    119 	}
    120 	if ( opts.delta === void 0 ) {
    121 		r = range( n, x, 1 );
    122 		delta = 0.01 * r;
    123 	} else {
    124 		delta = opts.delta;
    125 	}
    126 	return lowess( x, y, n, f, nsteps, delta );
    127 }
    128 
    129 
    130 // EXPORTS //
    131 
    132 module.exports = main;