UNPKG

math-evalrational

Version:
159 lines (140 loc) 3.71 kB
/* jshint evil:true */ 'use strict'; // EVAL RATIONAL FACTORY // /** * FUNCTION: factory( P, Q ) * Returns a function for evaluating a rational function. * * @param {Number[]|Int8Array|Uint8Array|Uint8ClampedArray|Int16Array|Uint16Array|Int32Array|Uint32Array|Float32Array|Float64Array} P - numerator polynomial coefficients sorted in ascending degree * @param {Number[]|Int8Array|Uint8Array|Uint8ClampedArray|Int16Array|Uint16Array|Int32Array|Uint32Array|Float32Array|Float64Array} Q - denominator polynomial coefficients sorted in ascending degree * @returns {Function} function for evaluating a rational function */ function factory( P, Q ) { var f; var r; var n; var m; var i; // Code generation. Start with the function definition... f = 'return function evalrational(x){'; // Create the function body... n = P.length; // Declare variables... f += 'var ax,s1,s2;'; // If no coefficients, the function always returns NaN... if ( n === 0 ) { f += 'return NaN;'; } // If P and Q have different lengths, the function always returns NaN... else if ( n !== Q.length ) { f += 'return NaN;'; } // If P and Q have only one coefficient, the function always returns the ratio of the first coefficients... else if ( n === 1 ) { r = P[ 0 ] / Q[ 0 ]; f += 'return ' + r + ';'; } // If more than one coefficient, apply Horner's method to both the numerator and denominator... else { // If `x == 0`, return the ratio of the first coefficients... r = P[ 0 ] / Q[ 0 ]; f += 'if(x===0){return ' + r + ';}'; // Compute the absolute value of `x`... f += 'if(x<0){ax=-x;}else{ax=x;}'; // If `abs(x) <= 1`, evaluate the numerator and denominator of the rational function using Horner's method... f += 'if(ax<=1){'; f += 's1 = ' + P[ 0 ]; m = n - 1; for ( i = 1; i < n; i++ ) { f += '+x*'; if ( i < m ) { f += '('; } f += P[ i ]; } // Close all the parentheses... for ( i = 0; i < m-1; i++ ) { f += ')'; } f += ';'; f += 's2 = ' + Q[ 0 ]; m = n - 1; for ( i = 1; i < n; i++ ) { f += '+x*'; if ( i < m ) { f += '('; } f += Q[ i ]; } // Close all the parentheses... for ( i = 0; i < m-1; i++ ) { f += ')'; } f += ';'; // Close the if statement... f += '}else{'; // If `abs(x) > 1`, evaluate the numerator and denominator via the inverse to avoid overflow... f += 'x = 1/x;'; m = n - 1; f += 's1 = ' + P[ m ]; for ( i = m - 1; i >= 0; i-- ) { f += '+x*'; if ( i > 0 ) { f += '('; } f += P[ i ]; } // Close all the parentheses... for ( i = 0; i < m-1; i++ ) { f += ')'; } f += ';'; m = n - 1; f += 's2 = ' + Q[ m ]; for ( i = m - 1; i >= 0; i-- ) { f += '+x*'; if ( i > 0 ) { f += '('; } f += Q[ i ]; } // Close all the parentheses... for ( i = 0; i < m-1; i++ ) { f += ')'; } f += ';'; // Close the else statement... f += '}'; // Return the ratio of the two sums... f += 'return s1/s2;'; } // Close the function: f += '}'; // Create the function in the global scope: return ( new Function( f ) )(); /** * returns * function evalrational( x ) { * var ax, s1, s2; * if ( x === 0 ) { * return P[0] / Q[0]; * } * if ( x < 0 ) { * ax = -x; * } else { * ax = x; * } * if ( ax <= 1 ) { * s1 = P[0]+x*(P[1]+x*(P[2]+x*(P[3]+...+x*(P[n-2]+x*P[n-1])))); * s2 = Q[0]+x*(Q[1]+x*(Q[2]+x*(Q[3]+...+x*(Q[n-2]+x*Q[n-1])))); * } else { * x = 1/x; * s1 = P[n-1]+x*(P[n-2]+x*(P[n-3]+x*(P[n-4]+...+x*(P[1]+x*P[0])))); * s2 = Q[n-1]+x*(Q[n-2]+x*(Q[n-3]+x*(Q[n-4]+...+x*(Q[1]+x*Q[0])))); * } * return s1 / s2; * } */ } // end FUNCTION factory() // EXPORTS // module.exports = factory;