factory.js (3014B)
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 evalpoly = require( './evalpoly.js' ); 24 25 26 // MAIN // 27 28 /** 29 * Generates a function for evaluating a polynomial. 30 * 31 * ## Notes 32 * 33 * - The compiled function uses [Horner's rule][horners-method] for efficient computation. 34 * 35 * [horners-method]: http://en.wikipedia.org/wiki/Horner%27s_method 36 * 37 * 38 * @param {NumericArray} c - polynomial coefficients sorted in ascending degree 39 * @returns {Function} function for evaluating a polynomial 40 * 41 * @example 42 * var polyval = factory( [3.0,2.0,1.0] ); 43 * 44 * var v = polyval( 10.0 ); // => 3*10^0 + 2*10^1 + 1*10^2 45 * // returns 123.0 46 * 47 * v = polyval( 5.0 ); // => 3*5^0 + 2*5^1 + 1*5^2 48 * // returns 38.0 49 */ 50 function factory( c ) { 51 var f; 52 var n; 53 var m; 54 var i; 55 56 // Avoid exceeding the maximum stack size on V8 :(. Note that the choice of `500` was empirically determined... 57 if ( c.length > 500 ) { 58 return polyval; 59 } 60 // Code generation. Start with the function definition... 61 f = 'return function evalpoly(x){'; 62 63 // Create the function body... 64 n = c.length; 65 66 // If no coefficients, the function always returns 0... 67 if ( n === 0 ) { 68 f += 'return 0.0;'; 69 } 70 // If only one coefficient, the function always returns that coefficient... 71 else if ( n === 1 ) { 72 f += 'return ' + c[ 0 ] + ';'; 73 } 74 // If more than one coefficient, apply Horner's method... 75 else { 76 // If `x == 0`, return the first coefficient... 77 f += 'if(x===0.0){return ' + c[ 0 ] + ';}'; 78 79 // Otherwise, evaluate the polynomial... 80 f += 'return ' + c[ 0 ]; 81 m = n - 1; 82 for ( i = 1; i < n; i++ ) { 83 f += '+x*'; 84 if ( i < m ) { 85 f += '('; 86 } 87 f += c[ i ]; 88 } 89 // Close all the parentheses... 90 for ( i = 0; i < m-1; i++ ) { 91 f += ')'; 92 } 93 f += ';'; 94 } 95 // Close the function: 96 f += '}'; 97 98 // Add a source directive for debugging: 99 f += '//# sourceURL=evalpoly.factory.js'; 100 101 // Create the function in the global scope: 102 return ( new Function( f ) )(); // eslint-disable-line no-new-func 103 104 /* 105 * function evalpoly( x ) { 106 * if ( x === 0.0 ) { 107 * return c[ 0 ]; 108 * } 109 * return c[0]+x*(c[1]+x*(c[2]+x*(c[3]+...+x*(c[n-2]+x*c[n-1])))); 110 * } 111 */ 112 113 /** 114 * Evaluates a polynomial. 115 * 116 * @private 117 * @param {number} x - value at which to evaluate a polynomial 118 * @returns {number} evaluated polynomial 119 */ 120 function polyval( x ) { 121 return evalpoly( c, x ); 122 } 123 } 124 125 126 // EXPORTS // 127 128 module.exports = factory;