time-to-botec

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

main.js (3333B)


      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 join = require( 'path' ).join;
     24 var readFile = require( '@stdlib/fs/read-file' ).sync;
     25 var replace = require( '@stdlib/string/replace' );
     26 var isInteger = require( '@stdlib/assert/is-integer' ).isPrimitive;
     27 
     28 
     29 // VARIABLES //
     30 
     31 var opts = {
     32 	'encoding': 'utf8'
     33 };
     34 var dir = join( __dirname, 'templates' );
     35 
     36 // Templates:
     37 var SINGLE_COEFFICIENT_TEMPLATE = readFile( join( dir, 'single_coefficient.js.txt' ), opts ); // eslint-disable-line id-length
     38 var EVALPOLY_TEMPLATE = readFile( join( dir, 'evalpoly.js.txt' ), opts );
     39 var EMPTY_TEMPLATE = readFile( join( dir, 'empty.js.txt' ), opts );
     40 var LOOP_TEMPLATE = readFile( join( dir, 'loop.js.txt' ), opts );
     41 var MAX_CHARS = 68; // max-len (80) - chars already in line ('tab': 4, 'return ': 7, ';': 1)
     42 
     43 
     44 // MAIN //
     45 
     46 /**
     47 * Compiles a module string which exports a function for evaluating a polynomial.
     48 *
     49 * @param {NumericArray} c - polynomial coefficients sorted in ascending degree
     50 * @returns {string} module string exporting a function for evaluating a polynomial
     51 *
     52 * @example
     53 * var str = compile( [ 3.0, 2.0, 1.0 ] );
     54 * // returns <string>
     55 */
     56 function compile( c ) {
     57 	var horner;
     58 	var str;
     59 	var n;
     60 	var m;
     61 	var i;
     62 
     63 	n = c.length;
     64 
     65 	// If no coefficients, the function always returns 0...
     66 	if ( n === 0 ) {
     67 		return EMPTY_TEMPLATE;
     68 	}
     69 	// If only one coefficient, the function always returns that coefficient...
     70 	if ( n === 1 ) {
     71 		str = c[ 0 ].toString();
     72 		if ( isInteger( c[ 0 ] ) ) {
     73 			str += '.0';
     74 		}
     75 		return replace( SINGLE_COEFFICIENT_TEMPLATE, '{{coefficient}}', str );
     76 	}
     77 	m = n - 1;
     78 
     79 	// Avoid exceeding the maximum stack size on V8 by using a simple loop :(. Note that the choice of `500` was empirically determined...
     80 	if ( n > 500 ) {
     81 		str = '';
     82 		for ( i = 0; i < n; i++ ) {
     83 			str += '\t' + c[ i ].toString();
     84 			if ( isInteger( c[ i ] ) ) {
     85 				str += '.0';
     86 			}
     87 			if ( i < m ) {
     88 				str += ',\n';
     89 			}
     90 		}
     91 		return replace( LOOP_TEMPLATE, '{{coefficients}}', str );
     92 	}
     93 	// If more than one coefficient, apply Horner's method...
     94 	horner = c[ 0 ].toString();
     95 	if ( isInteger( c[ 0 ] ) ) {
     96 		horner += '.0';
     97 	}
     98 	for ( i = 1; i < n; i++ ) {
     99 		horner += ' + (x * ';
    100 		if ( i < m ) {
    101 			horner += '(';
    102 		}
    103 		horner += c[ i ].toString();
    104 		if ( isInteger( c[ i ] ) ) {
    105 			horner += '.0';
    106 		}
    107 	}
    108 	// Close all the parentheses...
    109 	for ( i = 0; i < (2*(n-1))-1; i++ ) {
    110 		horner += ')';
    111 	}
    112 	str = c[ 0 ].toString();
    113 	if ( isInteger( c[ 0 ] ) ) {
    114 		str += '.0';
    115 	}
    116 	str = replace( EVALPOLY_TEMPLATE, '{{coefficient}}', str );
    117 	str = replace( str, '{{horner}}', horner );
    118 	return replace( str, '{{eslint}}', ( horner.length > MAX_CHARS ) ? ' // eslint-disable-line max-len' : '' );
    119 }
    120 
    121 
    122 // EXPORTS //
    123 
    124 module.exports = compile;