/* Translated into C++ by SciPy developers in 2024. | |
* Original header with Copyright information appears below. | |
*/ | |
/* polevl.c | |
* p1evl.c | |
* | |
* Evaluate polynomial | |
* | |
* | |
* | |
* SYNOPSIS: | |
* | |
* int N; | |
* double x, y, coef[N+1], polevl[]; | |
* | |
* y = polevl( x, coef, N ); | |
* | |
* | |
* | |
* DESCRIPTION: | |
* | |
* Evaluates polynomial of degree N: | |
* | |
* 2 N | |
* y = C + C x + C x +...+ C x | |
* 0 1 2 N | |
* | |
* Coefficients are stored in reverse order: | |
* | |
* coef[0] = C , ..., coef[N] = C . | |
* N 0 | |
* | |
* The function p1evl() assumes that c_N = 1.0 so that coefficent | |
* is omitted from the array. Its calling arguments are | |
* otherwise the same as polevl(). | |
* | |
* | |
* SPEED: | |
* | |
* In the interest of speed, there are no checks for out | |
* of bounds arithmetic. This routine is used by most of | |
* the functions in the library. Depending on available | |
* equipment features, the user may wish to rewrite the | |
* program in microcode or assembly language. | |
* | |
*/ | |
/* | |
* Cephes Math Library Release 2.1: December, 1988 | |
* Copyright 1984, 1987, 1988 by Stephen L. Moshier | |
* Direct inquiries to 30 Frost Street, Cambridge, MA 02140 | |
*/ | |
/* Sources: | |
* [1] Holin et. al., "Polynomial and Rational Function Evaluation", | |
* https://www.boost.org/doc/libs/1_61_0/libs/math/doc/html/math_toolkit/roots/rational.html | |
*/ | |
/* Scipy changes: | |
* - 06-23-2016: add code for evaluating rational functions | |
*/ | |
namespace xsf { | |
namespace cephes { | |
XSF_HOST_DEVICE inline double polevl(double x, const double coef[], int N) { | |
double ans; | |
int i; | |
const double *p; | |
p = coef; | |
ans = *p++; | |
i = N; | |
do { | |
ans = ans * x + *p++; | |
} while (--i); | |
return (ans); | |
} | |
/* p1evl() */ | |
/* N | |
* Evaluate polynomial when coefficient of x is 1.0. | |
* That is, C_{N} is assumed to be 1, and that coefficient | |
* is not included in the input array coef. | |
* coef must have length N and contain the polynomial coefficients | |
* stored as | |
* coef[0] = C_{N-1} | |
* coef[1] = C_{N-2} | |
* ... | |
* coef[N-2] = C_1 | |
* coef[N-1] = C_0 | |
* Otherwise same as polevl. | |
*/ | |
XSF_HOST_DEVICE inline double p1evl(double x, const double coef[], int N) { | |
double ans; | |
const double *p; | |
int i; | |
p = coef; | |
ans = x + *p++; | |
i = N - 1; | |
do | |
ans = ans * x + *p++; | |
while (--i); | |
return (ans); | |
} | |
/* Evaluate a rational function. See [1]. */ | |
/* The function ratevl is only used once in cephes/lanczos.h. */ | |
XSF_HOST_DEVICE inline double ratevl(double x, const double num[], int M, const double denom[], int N) { | |
int i, dir; | |
double y, num_ans, denom_ans; | |
double absx = std::abs(x); | |
const double *p; | |
if (absx > 1) { | |
/* Evaluate as a polynomial in 1/x. */ | |
dir = -1; | |
p = num + M; | |
y = 1 / x; | |
} else { | |
dir = 1; | |
p = num; | |
y = x; | |
} | |
/* Evaluate the numerator */ | |
num_ans = *p; | |
p += dir; | |
for (i = 1; i <= M; i++) { | |
num_ans = num_ans * y + *p; | |
p += dir; | |
} | |
/* Evaluate the denominator */ | |
if (absx > 1) { | |
p = denom + N; | |
} else { | |
p = denom; | |
} | |
denom_ans = *p; | |
p += dir; | |
for (i = 1; i <= N; i++) { | |
denom_ans = denom_ans * y + *p; | |
p += dir; | |
} | |
if (absx > 1) { | |
i = M - N; | |
return std::pow(x, i) * num_ans / denom_ans; | |
} else { | |
return num_ans / denom_ans; | |
} | |
} | |
} // namespace cephes | |
} // namespace xsf | |