You are on page 1of 28

2.

Algebraic Evaluations
All procedures in this chapter are class methods of the following Algebraic_eval
class.

package numal;

import numal.*;

public class Algebraic_eval extends Object {


// all procedures in this chapter are to be inserted here
}

2.1 Evaluation of polynomials in Grunert form

A. pol

Computes the sum of the polynomial


n
p( x) = ∑ ai x i
i =0
using Horner's rule. The error growth is given by a linear function of the degree of
the polynomial [Wi63].

Procedure parameters:
double pol (n,x,a)
pol: given the value of p(x) above;
n: int; the degree of the polynomial;
x: double; the argument of the polynomial;
a: double a[0:n];
entry: the coefficients of the polynomial.

public static double pol(int n, double x, double a[])


{
double r;

r=0.0;
for (; n>=0; n--) r=r*x+a[n];
return (r);
}

© 2004 by Chapman & Hall/CRC


B. taypol

Computes the values of the terms xjDjp(x)/j! (j=0,...,k≤n) where


n
p(x) = ∑ ai x i .
i=0

Procedure parameters:
void taypol (n,k,x,a)
n: int; the degree of the polynomial;
k: int; the first k terms of the above are to be calculated;
x: double; the argument of the polynomial;
a: double a[0:n];
entry: the coefficients of the polynomial;
exit: the j-th term xj*(j-th derivative)/j! is delivered in a[j], j=0,1,...,k≤n,
the other elements of a are generally altered.

Remark: The method of evaluation is given in [ShT74]. The more sophisticated


algorithm based on divisors of n+1 in [ShT74] was not implemented
because of the more complex appearance of the implementation and
because of the difficulty in choosing the most efficient divisor. In this
implementation of the one-parameter family of algorithms, the linear
number of multiplications is preserved. See [Wo74] for the k-th
normalized derivative.

public static void taypol(int n, int k, double x, double a[])


{
int i,j,nm1;
double xj,aa,h;

if (x != 0.0) {
xj=1;
for (j=1; j<=n; j++) {
xj *= x;
a[j] *= xj;
}
aa=a[n];
nm1=n-1;
for (j=0; j<=k; j++) {
h=aa;
for (i=nm1; i>=j; i--) h = a[i] += h;
}
} else {
for (; k>=1; n--) a[k]=0;
}
}

© 2004 by Chapman & Hall/CRC


C. norderpol

Computes the first k normalized derivatives Djp(x)/j!, (j=0,...,k≤n) of the polynomial


n
p(x) = ∑ ai x i .
i=0

Procedure parameters:
void norderpol (n,k,x,a)
n: int; the degree of the polynomial;
k: int; the first k normalized derivatives (j-th derivative / j factorial) are to be
calculated;
x: double; the argument of the polynomial;
a: double a[0:n];
entry: the coefficients of the polynomial;
exit: the j-th normalized derivative is delivered in a[j], j=0,1,...,k≤n, the
other elements of a are generally altered.

Remark: See the procedure taypol.

public static void norderpol(int n, int k, double x, double a[])


{
int i,j,nm1;
double xj,aa,h;

if (x != 0.0) {
double xx[] = new double[n+1];
xj=1;
for (j=1; j<=n; j++) {
xx[j] = xj *= x;
a[j] *= xj;
}
h=aa=a[n];
nm1=n-1;
for (i=nm1; i>=0; i--) h = a[i] += h;
for (j=1; j<=k; j++) {
h=aa;
for (i=nm1; i>=j; i--) h = a[i] += h;
a[j]=h/xx[j];
}
}
}

D. derpol

Computes the first k derivatives Djp(x) (j=0,...,k≤n) of the polynomial

© 2004 by Chapman & Hall/CRC


n
p(x) = ∑ ai x i .
i=0

Procedure parameters:
void derpol (n,k,x,a)
n: int; the degree of the polynomial;
k: int; the first k derivatives are to be calculated;
x: double; the argument of the polynomial;
a: double a[0:n];
entry: the coefficients of the polynomial;
exit: the j-th derivative is delivered in a[j], j=0,1,...,k≤n, the other
elements of a are generally altered.

Procedure used: norderpol.

Remark: See the procedure taypol.

public static void derpol(int n, int k, double x, double a[])


{
int j;
double fac;

fac=1.0;
norderpol(n,k,x,a);
for (j=2; j<=k; j++) {
fac *= j;
a[j] *=fac;
}
}

2.2 Evaluation of general orthogonal polynomials


This section contains six procedures for evaluating orthogonal polynomials
[AbS65, Lu69]. The procedures ending with sym are versions for symmetric
polynomials.

A. ortpol

Evaluates the single polynomial pn(x), where


p0(x) = 1, p1(x) = x-b0,
pk+1(x) = (x-bk)pk(x) - ckpk-1(x), k=1,...,n-1
with given bk and ck.

Procedure parameters:

© 2004 by Chapman & Hall/CRC


double ortpol (n,x,b,c)
ortpol: given the value of the orthogonal polynomial in the above;
n: int; the degree of the polynomial;
x: double; the argument of the orthogonal polynomial;
b,c: double b[0:n-1], c[1:n-1];
entry: the recurrence coefficients of the polynomial.

public static double ortpol(int n, double x, double b[], double c[])


{
int k,l;
double r,s,h;

if (n == 0) return (1.0);
r=x-b[0];
s=1.0;
l=n-1;
for (k=1; k<=l; k++) {
h=r;
r=(x-b[k])*r-c[k]*s;
s=h;
}
return (r);
}

B. ortpolsym

Given the ck and x, evaluates the single polynomial pn(x), where


p0(x) = 1, p1(x) = x,
pk+1(x) = xpk(x) - ckpk-1(x), k=1,...,n-1.

Procedure parameters:
double ortpolsym (n,x,c)
ortpolsym: given the value of the orthogonal polynomial in the above;
n: int; the degree of the polynomial;
x: double; the argument of the orthogonal polynomial;
c: double c[1:n-1];
entry: the recurrence coefficients of the polynomial.

public static double ortpolsym(int n, double x, double c[])


{
int k,l;
double r,s,h;

if (n == 0) return (1.0);
r=x;
s=1.0;
l=n-1;

© 2004 by Chapman & Hall/CRC


for (k=1; k<=l; k++) {
h=r;
r=x*r-c[k]*s;
s=h;
}
return (r);
}

C. allortpol

Evaluates the sequence of polynomials pk(x) for k=0,...,n, where


p0(x) = 1, p1(x) = x-b0,
pk+1(x) = (x-bk)pk(x) - ckpk-1(x), k=1,...,n-1
with given bk and ck.

Procedure parameters:
void allortpol (n,x,b,c,p)
n: int; the degree of the polynomial;
x: double; the argument of the orthogonal polynomial;
b,c: double b[0:n-1], c[1:n-1];
entry: the recurrence coefficients of the polynomial;
p: double p[0:n];
exit: p[k] contains, for the argument, the value of the k-th orthogonal
polynomial as defined by the recurrence coefficients.

public static void allortpol(int n, double x, double b[], double c[], double p[])
{
int k,k1;
double r,s,h;

if (n == 0) {
p[0]=1.0;
return;
}
r=p[1]=x-b[0];
s=p[0]=1.0;
k=1;
for (k1=2; k1<=n; k1++) {
h=r;
p[k1]=r=(x-b[k])*r-c[k]*s;
s=h;
k=k1;
}
}

© 2004 by Chapman & Hall/CRC


D. allortpolsym

Given the ck and x, evaluates the sequence of polynomials pk(x) for k=0,...,n, where
p0(x) = 1, p1(x) = x,
pk+1(x) = xpk(x) - ckpk-1(x), k=1,...,n-1.

Procedure parameters:
void allortpolsym (n,x,c,p)
n: int; the degree of the polynomial;
x: double; the argument of the orthogonal polynomial;
c: double c[1:n-1];
entry: the recurrence coefficients of the polynomial;
p: double p[0:n];
exit: p[k] contains, for the argument, the value of the k-th orthogonal
polynomial as defined by the recurrence coefficients.

public static void allortpolsym(int n, double x, double c[], double p[])


{
int k;
double r,s,h;

if (n == 0) {
p[0]=1.0;
return;
}
r=p[1]=x;
s=p[0]=1.0;
for (k=2; k<=n; k++) {
h=r;
p[k]=r=x*r-c[k-1]*s;
s=h;
}
}

E. sumortpol

Evaluates the sum


n
s = ∑ a k p k (x)
k =0
where p0(x) = 1, p1(x) = x-b0,
pk+1(x) = (x-bk)pk(x) - ckpk-1(x), k=1,...,n-1,
with given ak, bk, and ck.

Procedure parameters:
double sumortpol (n,x,b,c,a)
sumortpol: given the value of the sum s in the above;

© 2004 by Chapman & Hall/CRC


n: int; the degree of the polynomial;
x: double; the argument of the orthogonal polynomial;
b,c: double b[0:n-1], c[1:n-1];
entry: the recurrence coefficients of the polynomial;
a: double a[0:n];
entry: the value of ak in the above.

public static double sumortpol(int n, double x, double b[], double c[], double a[])
{
int k;
double h,r,s;

if (n == 0) return (a[0]);
r=a[n];
s=0.0;
for (k=n-1; k>=1; k--) {
h=r;
r=a[k]+(x-b[k])*r+s;
s = -c[k]*h;
}
return (a[0]+(x-b[0])*r+s);
}

F. sumortpolsym

Given the ak, ck, and x, evaluates the sum


n
s = ∑ a k p k (x)
k =0
where p0(x) = 1, p1(x) = x,
pk+1(x) = xpk(x) - ckpk-1(x), k=1,...,n-1.

Procedure parameters:
double sumortpolsym (n,x,c,a)
sumortpolsym: given the value of the sum s in the above;
n: int; the degree of the polynomial;
x: double; the argument of the orthogonal polynomial;
c: double c[1:n-1];
entry: the recurrence coefficients of the polynomial;
a: double a[0:n];
entry: the values of ak in the above.

public static double sumortpolsym(int n, double x, double c[], double a[])


{
int k;
double h,r,s;

© 2004 by Chapman & Hall/CRC


if (n == 0) return (a[0]);
r=a[n];
s=0.0;
for (k=n-1; k>=1; k--) {
h=r;
r=a[k]+x*r+s;
s = -c[k]*h;
}
return (a[0]+x*r+s);
}

2.3 Evaluation of Chebyshev polynomials


This section contains four procedures for evaluating Chebyshev polynomials of the
first kind [FoP68, Riv74].

A. chepolsum

Uses the Clenshaw or generalized Horner algorithm [Cle62] to evaluate a sum of


Chebyshev polynomials
n
S = ∑ ai Ti (x)
i=0
where Ti(x) is a Chebyshev polynomial, by use of the backward recursion
Sn+1 = 0, Sn = an,
Sk = ak + 2xSk+1 - Sk+2, k=n-2,n-3,...,1;
S = a0 + S1x - S2
for n≥2.

Procedure parameters:
double chepolsum (n,x,a)
chepolsum: given the value of the Chebyshev sum S in the above;
n: int; the degree of the polynomial represented by the Chebyshev sum,
n≥0;
x: double; the argument of the Chebyshev polynomials, x≤1;
a: double a[0:n];
entry: a[k] is the coefficient of the Chebyshev polynomial of degree k,
0≤k≤n.

public static double chepolsum(int n, double x, double a[])


{
int k;
double h,r,s,tx;

if (n == 0) return (a[0]);
if (n == 1) return (a[0]+a[1]*x);

© 2004 by Chapman & Hall/CRC


tx=x+x;
r=a[n];
h=a[n-1]+r*tx;
for (k=n-2; k>=1; k--) {
s=r;
r=h;
h=a[k]+r*tx-s;
}
return (a[0]-r+h*x);
}

B. oddchepolsum

Given the ai and x, uses the Clenshaw or generalized Horner algorithm [Cle62] to
evaluate a sum of Chebyshev polynomials of odd degree
n
S = ∑ ai T2i +1 ( x) ;
i=0
the Ti being Chebyshev polynomials.

Procedure parameters:
double oddchepolsum (n,x,a)
oddchepolsum: given the value of the Chebyshev sum S in the above;
n: int; the degree of the polynomial represented by the Chebyshev
sum is 2n+1, n≥0;
x: double; the argument of the Chebyshev polynomials, x≤1;
a: double a[0:n];
entry: a[k] is the coefficient of the Chebyshev polynomial of
degree 2k+1, 0≤k≤n.

public static double oddchepolsum(int n, double x, double a[])


{
int k;
double h,r,s,y;

if (n == 0) return (x*a[0]);
if (n == 1) return (x*(a[0]+a[1]*(4.0*x*x-3.0)));
y=4.0*x*x-2.0;
r=a[n];
h=a[n-1]+r*y;
for (k=n-2; k>=0; k--) {
s=r;
r=h;
h=a[k]+r*y-s;
}
return (x*(h-r));
}

© 2004 by Chapman & Hall/CRC


C. chepol

Computes the value of the Chebyshev polynomial Tn(x) by use of the recursion
[St72]
T0(x) = 1, T1(x) = x,
Ti(x) = 2xTi-1(x) - Ti-2(x), i=2,...,n.

Procedure parameters:
double chepol (n,x)
chepol: given the value of the Chebyshev polynomial of the first kind, Tn(x)
above;
n: int; the degree of the polynomial, n≥0;
x: double; the argument of the Chebyshev polynomial, x≤1.

public static double chepol(int n, double x)


{
int i;
double t1,t2,h,x2;

if (n == 0) return (1.0);
if (n == 1) return (x);
t2=x;
t1=1.0;
x2=x+x;
h=0.0;
for (i=2; i<=n; i++) {
h=x2*t2-t1;
t1=t2;
t2=h;;
}
return (h);
}

D. allchepol

Computes the values of the Chebyshev polynomials Ti(x), i=1,...,n, by use of the
recursion [St72]
T0(x) = 1, T1(x) = x,
Ti(x) = 2xTi-1(x) - Ti-2(x), i=2,...,n.

Procedure parameters:
void allchepol (n,x,t)
n: int; the degree of the last polynomial, n≥0;
x: double; the argument of the Chebyshev polynomials, x≤1;
t: double t[0:n];
exit: the value of the Chebyshev polynomial of the first kind of degree k,
for the argument x, is delivered in t[k], k=0,...,n.

© 2004 by Chapman & Hall/CRC


public static void allchepol(int n, double x, double t[])
{
int i;
double t1,t2,h,x2;

if (n == 0) {
t[0]=1.0;
return;
}
if (n == 1) {
t[0]=1.0;
t[1]=x;
return;
}
t[0]=t1=1.0;
t[1]=t2=x;
x2=x+x;
for (i=2; i<=n; i++) {
t[i]=h=x2*t2-t1;
t1=t2;
t2=h;;
}
}

2.4 Evaluation of Fourier series

A. sinser

Computes the value of a sine series


n
s = ∑ b j sin(jθ )
j=1

where θ and the bj are real. When -½ ≤ cos(θ) ≤ ½, the recursion


un+2 = un+1 = 0,
uk = 2cos(θ)uk+1 - uk+2 + bk, k=n,...,1
is used. When cos(θ) < -½, the equivalent recursion
un+1 = dn+1 = 0,
dk = 2(1 + cos(θ))uk+1 - dk+1 + bk, k=n,...,1
uk = dk - uk+1,
and when cos(θ) > ½, the further recursion
un+1 = en+1 = 0,
ek = 2(cos(θ) - 1)uk+1 - ek+1 + bk, k=n,...,1
uk = ek - uk+1
are used. In each case s = u1sin(θ).

© 2004 by Chapman & Hall/CRC


Procedure parameters:
double sinser (n,theta,b)
sinser: given the value of the sine series, the value of s above;
n: int;
entry: the number of terms in the sine series;
theta: double;
entry: the argument of the sine series;
b: double b[1:n];
entry: the coefficients of the sine series.

Remark: See the procedure comfouser2.

public static double sinser(int n, double theta, double b[])


{
int k;
double c,cc,lambda,h,dun,un,un1,temp;

c=Math.cos(theta);
if (c < -0.5) {
temp=Math.cos(theta/2.0);
lambda=4.0*temp*temp;
un=dun=0.0;
for (k=n; k>=1; k--) {
dun=lambda*un-dun+b[k];
un=dun-un;
}
} else {
if (c > 0.5) {
temp=Math.sin(theta/2.0);
lambda = -4.0*temp*temp;
un=dun=0.0;
for (k=n; k>=1; k--) {
dun += lambda*un+b[k];
un += dun;
}
} else {
cc=c+c;
un=un1=0.0;
for (k=n; k>=1; k--) {
h=cc*un-un1+b[k];
un1=un;
un=h;
}
}
}
return (un*Math.sin(theta));
}

© 2004 by Chapman & Hall/CRC


B. cosser

Computes the value of a cosine series


n
s = ∑ a j cos(jθ )
j=0
where θ and the aj are real. The method used is based upon recursion of the
documentation to sinser, where now s = a0 + 2u1cos(θ) - u2, and upon further
recursions similar to those given in that documentation.

Procedure parameters:
double cosser (n,theta,a)
cosser: given the value of the cosine series, value of s above;
n: int;
entry: the degree of the trigonometric polynomial;
theta: double;
entry: the argument of the cosine series;
a: double a[0:n];
entry: the coefficients of the cosine series.

Remark: See the procedure comfouser2.

public static double cosser(int n, double theta, double a[])


{
int k;
double c,cc,lambda,h,dun,un,un1,temp;

c=Math.cos(theta);
if (c < -0.5) {
temp=Math.cos(theta/2.0);
lambda=4.0*temp*temp;
un=dun=0.0;
for (k=n; k>=0; k--) {
un=dun-un;
dun=lambda*un-dun+a[k];
}
return (dun-lambda/2.0*un);
} else {
if (c > 0.5) {
temp=Math.sin(theta/2.0);
lambda = -4.0*temp*temp;
un=dun=0.0;
for (k=n; k>=0; k--) {
un += dun;
dun += lambda*un+a[k];
}
return (dun-lambda/2.0*un);
} else {
cc=c+c;

© 2004 by Chapman & Hall/CRC


un=un1=0.0;
for (k=n; k>=1; k--) {
h=cc*un-un1+a[k];
un1=un;
un=h;
}
return (a[0]+un*c-un1);
}
}
}

C. fouser

Computes the value of


n n
s = ∑ a j cos(jθ ) + ∑ a j sin(jθ )
j=0 j=1
where θ and the aj are real, by methods similar to those described in the
documentations to sinser and cosser.

Procedure parameters:
double fouser (n,theta,a)
fouser: given the value of the fourier series, value of s above;
n: int;
entry: the degree of the trigonometric polynomial;
theta: double;
entry: the argument of the fourier series;
a: double a[0:n];
entry: the coefficients of the (finite) fourier series.

public static double fouser(int n, double theta, double a[])


{
int k;
double c,cc,lambda,h,dun,un,un1,c2,s2;

c=Math.cos(theta);
if (c < -0.5) {
c2=Math.cos(theta/2.0);
lambda=4.0*c2*c2;
un=dun=0.0;
for (k=n; k>=0; k--) {
un=dun-un;
dun=lambda*un-dun+a[k];
}
return (dun+2.0*c2*(Math.sin(theta/2.0)-c2)*un);
} else {
if (c > 0.5) {

© 2004 by Chapman & Hall/CRC


s2=Math.sin(theta/2.0);
lambda = -4.0*s2*s2;
un=dun=0.0;
for (k=n; k>=0; k--) {
un += dun;
dun += lambda*un+a[k];
}
return (dun+2.0*s2*(s2+Math.cos(theta/2.0))*un);
} else {
cc=c+c;
un=un1=0.0;
for (k=n; k>=1; k--) {
h=cc*un-un1+a[k];
un1=un;
un=h;
}
return (a[0]-un1+(c+Math.sin(theta))*un);
}
}
}

D. fouser1

Computes the value of


n n
s = ∑ a j cos(jθ ) + ∑ b j sin(jθ )
j=0 j=1
where θ, aj, and bj are real, using a Horner scheme.

Procedure parameters:
double fouser1 (n,theta,a,b)
fouser1: given the value of the fourier series, value of s above;
n: int;
entry: the degree of the trigonometric polynomial;
theta: double;
entry: the argument of the fourier series;
a,b: double a[0:n], b[1:n];
entry: the coefficients of the (finite) fourier series,
with ak coefficient of cos(k*θ), k=0,...,n,
and bk coefficient of sin(k*θ), k=1,...,n.

Remark: See the procedure comfouser2.

public static double fouser1(int n, double theta, double a[], double b[])
{
int i;
double r,s,h,co,si;

© 2004 by Chapman & Hall/CRC


r=s=0.0;
co=Math.cos(theta);
si=Math.sin(theta);
for (i=n; i>=1; i--) {
h=co*r+si*s+a[i];
s=co*s-si*r+b[i];
r=h;
}
return (co*r+si*s+a[0]);
}

E. fouser2

Computes the value of


n n
s = ∑ a j cos(jθ ) + ∑ b j sin(jθ )
j=0 j=1
where θ, aj, and bj are real, by methods similar to those described in the
documentations to sinser and cosser.

Procedure parameters:
double fouser2 (n,theta,a,b)
fouser2: given the value of the fourier series, value of s above;
n: int;
entry: the degree of the trigonometric polynomial;
theta: double;
entry: the argument of the fourier series;
a,b: double a[0:n], b[1:n];
entry: the coefficients of the (finite) fourier series,
with ak coefficient of cos(k*θ), k=0,...,n,
and bk coefficient of sin(k*θ), k=1,...,n.

Procedures used: sinser, cosser.

Remark: See the procedure comfouser2.

public static double fouser2(int n, double theta, double a[], double b[])
{
return (cosser(n,theta,a)+sinser(n,theta,b));
}

F. comfouser

Computes the value of

© 2004 by Chapman & Hall/CRC


n
s = ∑ a j eijθ
j=0
where θ and the aj are real, by methods similar to those described in the
documentations to sinser and cosser.

Procedure parameters:
void comfouser (n,theta,a,rr,ri)
n: int;
entry: the degree of the polynomial in eiθ;
theta: double;
entry: the argument of the fourier series;
a: double a[0:n];
entry: the real coefficients in the series;
rr,ri: double rr[0:0], ri[0:0];
exit: the real part and the imaginary part of s above are delivered in rr[0]
and ri[0], respectively.

public static void comfouser(int n, double theta, double a[], double rr[],
double ri[])
{
int k;
double c,cc,lambda,h,dun,un,un1,temp;

c=Math.cos(theta);
if (c < -0.5) {
temp=Math.cos(theta/2.0);
lambda=4.0*temp*temp;
un=dun=0.0;
for (k=n; k>=0; k--) {
un=dun-un;
dun=lambda*un-dun+a[k];
}
rr[0]=dun-lambda/2.0*un;
} else {
if (c > 0.5) {
temp=Math.sin(theta/2.0);
lambda = -4.0*temp*temp;
un=dun=0.0;
for (k=n; k>=0; k--) {
un += dun;
dun += lambda*un+a[k];
}
rr[0]=dun-lambda/2.0*un;
} else {
cc=c+c;
un=un1=0.0;
for (k=n; k>=1; k--) {
h=cc*un-un1+a[k];
un1=un;

© 2004 by Chapman & Hall/CRC


un=h;
}
rr[0]=a[0]+un*c-un1;
}
}
ri[0]=un*Math.sin(theta);
}

G. comfouser1

Computes the value of


n
s = ∑ a j eijθ
j=0
where θ is real and the aj are complex, using a Horner scheme.

Procedure parameters:
void comfouser1 (n,theta,ar,ai,rr,ri)
n: int;
entry: the degree of the polynomial in eiθ;
theta: double;
entry: the argument of the fourier series;
ar,ai: double ar[0:n], ai[0:n];
entry: the real part and the imaginary part of the complex coefficients in
the series must be given in arrays ar and ai, respectively;
rr,ri: double rr[0:0], ri[0:0];
exit: the real part and the imaginary part of s above are delivered in rr[0]
and ri[0], respectively.

Remark: See the procedure comfouser2.

public static void comfouser1(int n, double theta, double ar[], double ai[],
double rr[], double ri[])
{
int k;
double h,hr,hi,co,si;

hr=hi=0.0;
co=Math.cos(theta);
si=Math.sin(theta);
for (k=n; k>=1; k--) {
h=co*hr-si*hi+ar[k];
hi=co*hi+si*hr+ai[k];
hr=h;
}
rr[0]=co*hr-si*hi+ar[0];
ri[0]=co*hi+si*hr+ai[0];
}

© 2004 by Chapman & Hall/CRC


H. comfouser2

Computes the value of


n
s = ∑ a j e ijθ
j=0
where θ is real and the aj are complex, by methods similar to those described in
the documentations to sinser and cosser.

Procedure parameters:
void comfouser2 (n,theta,ar,ai,rr,ri)
n: int;
entry: the degree of the polynomial in eiθ;
theta: double;
entry: the argument of the fourier series;
ar,ai: double ar[0:n], ai[0:n];
entry: the real part and the imaginary part of the complex coefficients in
the series must be given in arrays ar and ai, respectively;
rr,ri: double rr[0:0], ri[0:0];
exit: the real part and the imaginary part of s above are delivered in rr[0]
and ri[0], respectively.

Procedure used: comfouser.

Remark: For the evaluation of a finite fourier series two algorithms are used:
(a) the Horner scheme in the procedure fouser1, and (b) a combination of
the Clenshaw algorithm [Ge69, Lu69, St72] and the modification of
Reinsch [Re67, St72] in the procedures sinser, cosser, fouser, and
fouser2. A modification of the idea of Newbery is not implemented
because of the introduction of sine (cosine) terms in a cosine (sine) series
and the inefficiency of the algorithm [N73]. For the evaluation of a finite
complex fourier series, two algorithms, in real arithmetic, are used:
(a) the Horner scheme in the procedure comfouser1, and (b) a
combination of the Clenshaw algorithm and the modification of Reinsch
in procedures comfouser and comfouser2. The Horner scheme is
implemented because of the simplicity of the algorithm (although this
algorithm is less efficient than the Goertzel-Watt-Clenshaw-Reinsch
algorithm) and the stable nature of orthogonal transformations. A
combination of the algorithm of Goertzel-Watt-Clensaw and the
modification of Reinsch is implemented because of the efficiency of the
Goertzel-Watt-Clensaw algorithm and the stability of the modification of
Reinsch, especially for small values of the argument. An upper bound for
the error growth is given by a linear function of the degree for both
implemented algorithms.

public static void comfouser2(int n, double theta, double ar[], double ai[],
double rr[], double ri[])
{
double car[] = new double[1];

© 2004 by Chapman & Hall/CRC


double cai[] = new double[1];
double sar[] = new double[1];
double sai[] = new double[1];

comfouser(n,theta,ar,car,sar);
comfouser(n,theta,ai,cai,sai);
rr[0]=car[0]-sai[0];
ri[0]=cai[0]+sar[0];
}

2.5 Evaluation of continued fractions

jfrac

Computes the value of the convergent


a1 a 2 a n
C n = b0 + ...
b1 + b2 + bn
by use of the recursion
D1 = bn,
Di+1 = bn-i + an-i+1/Di, i=1,...,n,
when Cn = Dn+1.

Procedure parameters:
double jfrac (n,a,b)
jfrac: delivers the value of the terminating continued fraction, the value of Cn
above;
n: int; the upper index of the arrays a and b;
a,b: double a[1:n],b[0:n]; the elements of the continued fraction, ai and bi above.

public static double jfrac(int n, double a[], double b[])


{
int i;
double d;

d=0.0;
for (i=n; i>=1; i--) d=a[i]/(b[i]+d);
return (d+b[0]);
}

© 2004 by Chapman & Hall/CRC


2.6 Transformation of polynomial representation

A. polchs

Given the ak, derives the bk occurring in the relationship


n n

∑ak x k = ∑ bk Tk (x) ;
k =0 k =0
the Tk(x) being Chebyshev polynomials.

Procedure parameters:
void polchs (n,a)
n: int; the degree of the polynomial;
a: double a[0:n];
entry: the coefficients of the power sum;
exit: the coefficients of the Chebyshev sum.

Remark: Although the transformation of representations of polynomials could


have been obtained by fast evaluation and fast interpolation, the
algorithm of Hamming [H73] was implemented here because of its simple
appearance.

public static void polchs(int n, double a[])


{
int k,l,twopow;

if (n > 1) {
twopow=2;
for (k=1; k<=n-2; k++) {
a[k] /= twopow;
twopow *= 2;
}
a[n-1]=2.0*a[n-1]/twopow;
a[n] /= twopow;
a[n-2] += a[n];
for (k=n-2; k>=1; k--) {
a[k-1] += a[k+1];
a[k]=2.0*a[k]+a[k+2];
for (l=k+1; l<=n-2; l++) a[l] += a[l+2];
}
}
}

© 2004 by Chapman & Hall/CRC


B. chspol

Given the bk, derives the ak occurring in the relationship


n n

∑ bk Tk ( x) = ∑ ak x k ;
k =0 k =0
the Tk(x) being Chebyshev polynomials.

Procedure parameters:
void chspol (n,a)
n: int; the degree of the polynomial;
a: double a[0:n];
entry: the coefficients of the Chebyshev sum;
exit: the coefficients of the power sum.

Remark: See the procedure polchs.

public static void chspol(int n, double a[])


{
int k,l,twopow;

if (n > 1) {
for (k=0; k<=n-2; k++) {
for (l=n-2; l>=k; l--) a[l] -= a[l+2];
a[k+1] /= 2.0;
}
twopow=2;
for (k=1; k<=n-2; k++) {
a[k] *= twopow;
twopow *= 2;
}
a[n-1] *= twopow;
a[n] *= twopow;
}
}

C. polshtchs

Given the ak, derives the bk occurring in the relationship


n n

∑ ak x k = ∑ bk S k (x) ;
k =0 k =0
the Sk(x) being shifted Chebyshev polynomials defined by Sk(x)=Tk(2x-1),
Tk(x) being a Chebyshev polynomial.

Procedure parameters:

© 2004 by Chapman & Hall/CRC


void polshtchs (n,a)
n: int; the degree of the polynomial;
a: double a[0:n];
entry: the coefficients of the power sum;
exit: the coefficients of the shifted Chebyshev sum.

Procedures used: lintfmpol, polchs.

Remark: See the procedure polchs.

public static void polshtchs(int n, double a[])


{
lintfmpol(0.5,0.5,n,a);
polchs(n,a);
}

D. shtchspol

Given the bk, derives the ak occurring in the relationship


n n

∑ bk S k ( x) = ∑ ak x k ;
k =0 k =0
the Sk(x) being shifted Chebyshev polynomials defined by Sk(x)=Tk(2x-1), and
Tk(x) being a Chebyshev polynomial.

Procedure parameters:
void shtchspol (n,a)
n: int; the degree of the polynomial;
a: double a[0:n];
entry: the coefficients of the shifted Chebyshev sum;
exit: the coefficients of the power sum.

Procedures used: lintfmpol, chspol.

Remark: See the procedure polchs.

public static void shtchspol(int n, double a[])


{
chspol(n,a);
lintfmpol(2.0,-1.0,n,a);
}

E. grnnew

Given the coefficients ai occurring in the polynomial

© 2004 by Chapman & Hall/CRC


n
P(x) = ∑ ai x i
i=0
and the tabulation points xv, computes the divided differences δj in the equivalent
Newton series representation
n
 j -1 
P(x) = ∑  ∏ ( x − xν )  δ j .
j= 0  ν =0 

Procedure parameters:
void grnnew (n,x,a)
n: int; the degree of the polynomial;
x: double x[0:n-1];
entry: the interpolation points, values of xv above;
a: double a[0:n];
entry: the coefficients of the power sum;
exit: the coefficients of the Newton sum, values of δj above.

Remark: See the procedure polchs.

public static void grnnew(int n, double x[], double a[])


{
int k,l;

for (k=n-1; k>=0; k--)


for (l=n-1; l>=n-1-k; l--) a[l] += a[l+1]*x[n-1-k];
}

F. newgrn

Given the coefficients δjf(x0), together with the values of the arguments xi from
which they are formed, in the truncated Newton interpolation series
n
 j −1 
f n ( x) = ∑  ∏ ( x − xυ ) δ j f ( x0 )
j =0  υ =0 
computes the coefficients ci, i=0,...,n, in the equivalent polynomial form
n
f n (x) = ∑ ci x i .
i=0
Procedure parameters:
void newgrn (n,x,a)
n: int; the degree of the polynomial;
x: double x[0:n-1];
entry: the interpolation points, values of xi above;
a: double a[0:n];
entry: the coefficients of the Newton sum, values of δjf(x0);
exit: the coefficients of the power sum, values of ci above.

© 2004 by Chapman & Hall/CRC


Procedure used: elmvec.

Remark: See the procedure polchs.

public static void newgrn(int n, double x[], double a[])


{
int k;

for (k=n-1; k>=0; k--)


Basic.elmvec(k,n-1,1,a,a,-x[k]);
}

G. lintfmpol

Given the ai occurring in the polynomial expression


n
P(x) = ∑ ai x i
i=0
and p, q, derives the bj occurring in the equivalent expression
n
P(x) = ∑ b j y j
j=0
where x=py+q.

Procedure parameters:
void lintfmpol (p,q,n,a)
p,q: double;
entry: defining the linear transformation of the independent variable
x=py+q; p=0 gives the value of the polynomial with argument q;
n: int; the degree of the polynomial;
a: double a[0:n];
entry: the coefficients of the power sum in x, values of ai above;
exit: the coefficients of the power sum in y, values of bj above.

Procedure used: norderpol.

Remark: See the procedure polchs.

public static void lintfmpol(double p, double q, int n, double a[])


{
int k;
double ppower;

norderpol(n,n,q,a);
ppower=p;
for (k=1; k<=n; k++) {

© 2004 by Chapman & Hall/CRC


a[k] *= ppower;
ppower *= p;
}
}

2.7 Operations on orthogonal polynomials

intchs

Given the real coefficients aj in the expansion


n
f(x) = ∑ a j T j (x)
j=0
where Tj(x) is the Chebyshev polynomial of the first kind of degree j, those in the
expansion
x n+1

∫ f(x)dx = ∑ b j T j ( x)
0 j=1
are derived.

Procedure parameters:
void intchs (n,a,b)
n: int; the degree of the polynomial represented by the Chebyshev series;
a,b: double a[0:n], b[1:n+1];
entry: the coefficients of the Chebyshev series, values of aj above;
exit: the coefficients of the integral Chebyshev series, values of bj
above.

Remark: For a description of the algorithm see [Cle62, FoP68].

public static void intchs(int n, double a[], double b[])


{
int i;
double h,l,dum;

if (n == 0) {
b[1]=a[0];
return;
}
if (n == 1) {
b[2]=a[1]/4.0;
b[1]=a[0];
return;
}
h=a[n];

© 2004 by Chapman & Hall/CRC


dum=a[n-1];
b[n+1]=h/((n+1)*2);
b[n]=dum/(n*2);
for (i=n-1; i>=2; i--) {
l=a[i-1];
b[i]=(l-h)/(2*i);
h=dum;
dum=l;
}
b[1]=a[0]-h/2.0;
}

© 2004 by Chapman & Hall/CRC

You might also like