UNPKG

@stdlib/math-base-tools-evalrationalf

Version:

Evaluate a rational function using single-precision floating-point arithmetic.

122 lines (111 loc) 3.61 kB
/** * @license Apache-2.0 * * Copyright (c) 2024 The Stdlib Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * * ## Notice * * The original C++ code and copyright notice are from the [Boost library]{@link http://www.boost.org/doc/libs/1_60_0/boost/math/tools/rational.hpp}. The implementation has been modified for JavaScript. * * ```text * (C) Copyright John Maddock 2006. * * Use, modification and distribution are subject to the * Boost Software License, Version 1.0. (See accompanying file * LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt) * ``` */ 'use strict'; // MODULES // var float64ToFloat32 = require( '@stdlib/number-float64-base-to-float32' ); var absf = require( '@stdlib/math-base-special-absf' ); // MAIN // /** * Evaluates a rational function (i.e., the ratio of two polynomials described by the coefficients stored in \\(P\\) and \\(Q\\)) using single-precision floating-point arithmetic. * * ## Notes * * - Coefficients should be sorted in ascending degree. * - The implementation uses [Horner's rule][horners-method] for efficient computation. * * [horners-method]: https://en.wikipedia.org/wiki/Horner%27s_method * * @param {NumericArray} P - numerator polynomial coefficients sorted in ascending degree * @param {NumericArray} Q - denominator polynomial coefficients sorted in ascending degree * @param {number} x - value at which to evaluate the rational function * @returns {number} evaluated rational function * * @example * var Float32Array = require( '@stdlib/array-float32' ); * * var P = new Float32Array( [ -6.0, -5.0 ] ); * var Q = new Float32Array( [ 3.0, 0.5 ] ); * * var v = evalrationalf( P, Q, 6.0 ); // => ( -6*6^0 - 5*6^1 ) / ( 3*6^0 + 0.5*6^1 ) = (-6-30)/(3+3) * // returns -6.0 * * @example * var Float32Array = require( '@stdlib/array-float32' ); * * // 2x^3 + 4x^2 - 5x^1 - 6x^0 => degree 4 * var P = new Float32Array( [ -6.0, -5.0, 4.0, 2.0 ] ); * * // 0.5x^1 + 3x^0 => degree 2 * var Q = new Float32Array( [ 3.0, 0.5, 0.0, 0.0 ] ); // zero-padded * * var v = evalrationalf( P, Q, 6.0 ); // => ( -6*6^0 - 5*6^1 + 4*6^2 + 2*6^3 ) / ( 3*6^0 + 0.5*6^1 + 0*6^2 + 0*6^3 ) = (-6-30+144+432)/(3+3) * // returns ~90.0 */ function evalrationalf( P, Q, x ) { var len; var s1; var s2; var i; len = P.length; if ( len === 0 ) { return NaN; } if ( len !== Q.length ) { return NaN; } if ( x === 0.0 || len === 1 ) { return float64ToFloat32( P[ 0 ] / Q[ 0 ] ); } // Use Horner's method... if ( absf( x ) <= 1.0 ) { s1 = P[ len-1 ]; s2 = Q[ len-1 ]; for ( i = len-2; i >= 0; --i ) { s1 = float64ToFloat32( s1 * x ); s2 = float64ToFloat32( s2 * x ); s1 = float64ToFloat32( s1 + P[ i ] ); s2 = float64ToFloat32( s2 + Q[ i ] ); } } else { x = float64ToFloat32( 1.0 / x ); // use inverse to avoid overflow s1 = P[ 0 ]; s2 = Q[ 0 ]; for ( i = 1; i < len; ++i ) { s1 = float64ToFloat32( s1 * x ); s2 = float64ToFloat32( s2 * x ); s1 = float64ToFloat32( s1 + P[ i ] ); s2 = float64ToFloat32( s2 + Q[ i ] ); } } return float64ToFloat32( s1 / s2 ); } // EXPORTS // module.exports = evalrationalf;