Interpolation and Approximation: 7.1 Real Data in One Dimension
Interpolation and Approximation: 7.1 Real Data in One Dimension
package numal;
import numal.*;
newton
Procedure parameters:
void newton (n,x,f)
n: int;
entry: the degree of the polynomial;
x: double x[0:n];
entry: the interpolation points;
f: double f[0:n];
entry: the function values at the interpolation points;
exit: the coefficients of the Newton polynomial.
im1=0;
for (i=1; i<=n; i++) {
fim1=f[im1];
xim1=x[im1];
for (k=i; k<=n; k++) f[k]=(f[k]-fim1)/(x[k]-xim1);
im1=i;
}
}
A. ini
Selects a set of integers out of a given set of integers. With integers m,n (m > n),
ini determines a sequence of integer approximations s(j), j=0,...,n; s(j) > s(j-1), to the
points in the range [0,m] at which Tn((2x-m)/m), where
Tn(y) = cos{n arc cos(y)}
being a Chebyshev polynomial and (2x-m)/m maps x∈[-1,1] onto [0,m], assumes
its maximal absolute values.
ini is an auxiliary procedure used in minmaxpol.
Procedure parameters:
void ini (n,m,s)
n,m: int;
entry: the number of points to be selected equals n+1; the reference set
contains the numbers 0,1,...,m, (m ≥ n);
s: int s[0:n];
exit: the selected integers are delivered in s.
pin2=Math.atan(1.0)*2.0/n;
k=1;
l=n-1;
j=s[0]=0;
s[n]=m;
while (k < l) {
temp=Math.sin(k*pin2);
i=(int)(temp*temp*m);
j = s[k] = ((i <= j) ? j+1 : i);
s[l]=m-j;
l--;
k++;
}
if (l*2 == n) s[l]=m/2;
}
B. sndremez
Exchanges at most n+1 numbers with numbers out of a reference set (see
[Me64]). Given a sequence of real numbers gi, i=0,...,m, which contains a
subsequence gs(j), j=0,1,...,n<m; s(j) > s(j-1), for which a)
gs(j) = G, j=0,...,n,
and b)
sign gs(j) = -sign gs(j-1), j=1,...,n,
a sequence of integers S(j), j=0,1,...,n;
S(j) > S(j-1); S(0) ≥ 0, S(n) ≤ m,
is determined such that A)
gS(j) ≥ G, j=0,...,n,
B)
sign gS(j) = -sign gS(j-1), j=1,...,n,
and C) gS(j) > G for at least one j in the range 0 ≤ j ≤ n if gi > G for at least one i
in the range 0 ≤ i ≤ n.
The process used is as follows: let
H(1) = maxgi for s(0) < i < s(1)
and gI(1) = H(1) (H(1) is zero if s(0) = s(1) and I(1) is then undefined; a similar
convention is adopted below). If H(1) ≤ G then
S(0) = s(0), S(1) = s(1);
otherwise if
sign gI(1) = sign gs(0)
then
S(0) = I(1), S(1)=s(1),
whereas if
sign gI(1) ≠ sign gs(0),
then
S(0) = s(0), S(1) = I(1).
Let
H(2) = maxgi for s(1) < i < s(2) and gI(2) = H(2).
If H(2) ≤ G then S(2) = s(2); otherwise if sign gI(2) = sign gS(1) then S(1) is replaced by
I(2) and S(2) = s(2), whereas if sign gI(2) ≠ sign gS(1) then S(2) = I(2). The numbers gi,
s(2)<i<s(3), are inspected, S(2) is possibly replaced, and S(3) is determined as
before. In this way S(0),...,S(n) are determined. Let
H' = maxgi for 0 ≤ i < s(0) with gI'=H',
and
H" = maxgi for s(n) < i ≤ m, with gI" = H".
If H', H" < G, the numbers S(j) are left as they stand.
If not, then if H' > H" then a) if sign gI' = sign gS(0) then a') if H'>gs(0), S(0) is
replaced by I' and a") if sign gI" = gs(n) and H" > gs(n), S(n) is replaced by I"; b) if
sign gI' ≠ sign gS(0) then b') if H' > gs(n), S(k) is replaced by S(k-1), k=n,...,1, and
S(0) is replaced by I' and b") (with the new value of S(n)) if sign gI" = sign gS(n) and
H" > gs(n), S(n) is replaced by I". If H" ≥ H' then similar modifications take place.
sndremez is an auxiliary procedure used in minmaxpol.
Procedure parameters:
void sndremez (n,m,s,g,em)
n,m: int;
entry: the number of points to be exchanged is smaller than or equal to
n+1;
the reference set contains the numbers 0,1,...,m, (m ≥ n);
s: int s[0:n];
entry: in s one must give n+1 (strictly) monotone increasing numbers out
of 0,1,...,m;
exit: n+1 (strictly) monotone increasing numbers out of the numbers
0,1,...,m;
g: double g[0:m];
entry: in array g[0:m] one must give the function values;
em: double em[0:1];
entry: 0 < em[0] ≤ g[i], i=0,...,m;
exit: em[1] = infinity norm of array g[0:m].
public static void sndremez(int n, int m, int s[], double g[], double em[])
{
int s0,sn,sjp1,i,j,k,up,low,nm1;
double max,msjp1,hi,hj,he,abse,h,temp1,temp2;
int itmp[] = new int[1];
int jtmp[] = new int[1];
s0=sjp1=s[0];
he=em[0];
low=s0+1;
max=msjp1=abse=Math.abs(he);
nm1=n-1;
for (j=0; j<=nm1; j++) {
up=s[j+1]-1;
h=Basic.infnrmvec(low,up,itmp,g);
i=itmp[0];
if (h > max) max=h;
if (h > abse)
if (he*g[i] > 0.0) {
s[j] = (msjp1 < h) ? i : sjp1;
sjp1=s[j+1];
msjp1=abse;
} else {
s[j]=sjp1;
sjp1=i;
msjp1=h;
}
else {
s[j]=sjp1;
sjp1=s[j+1];
msjp1=abse;
}
he = -he;
low=up+2;
}
sn=s[n];
s[n]=sjp1;
hi=Basic.infnrmvec(0,s0-1,itmp,g);
i=itmp[0];
hj=Basic.infnrmvec(sn+1,m,jtmp,g);
j=jtmp[0];
if (j > m) j=m;
if (hi > hj) {
if (hi > max) max=hi;
temp1 = (g[i] == 0.0) ? 0.0 : ((g[i] > 0.0) ? 1.0 : -1.0);
temp2 = (g[s[0]]==0.0) ? 0.0 : ((g[s[0]]>0.0) ? 1.0 : -1.0);
if (temp1 == temp2) {
if (hi > Math.abs(g[s[0]])) {
s[0]=i;
if (g[j]/g[s[n]] > 1.0) s[n]=j;
}
}
else {
if (hi > Math.abs(g[s[n]])) {
s[n] = (g[j]/g[s[nm1]] > 1.0) ? j : s[nm1];
for (k=nm1; k>=1; k--) s[k]=s[k-1];
s[0]=i;
}
}
} else {
if (hj > max) max=hj;
temp1 = (g[j] == 0.0) ? 0.0 : ((g[j] > 0.0) ? 1.0 : -1.0);
temp2 = (g[s[n]]==0.0) ? 0.0 : ((g[s[n]]>0.0) ? 1.0 : -1.0);
if (temp1 == temp2) {
if (hj > Math.abs(g[s[n]])) {
s[n]=j;
if (g[i]/g[s[0]] > 1.0) s[0]=i;
}
} else
if (hj > Math.abs(g[s[0]])) {
s[0] = (g[i]/g[s[1]] > 1.0) ? i : s[1];
for (k=1; k<=nm1; k++) s[k]=s[k+1];
s[n]=j;
}
}
em[1]=max;
}
C. minmaxpol
∑c y
i =0
i
i
for which
n −1
max f ( y j ) − ∑ ci y ij (1)
i =0
is a minimum as j ranges over the values 0,...,m (m > n).
The method used [Me64] involves the iterative construction of polynomials
n −1
∑c
i =0
k ,i yi
for which
n −1
f ( y s ( k , j ) ) − ∑ c k ,i y si ( k , j ) = (−1) j λ k ( j = 0,K, n ) (2)
i =0
where s(k,j), j=0,...,n, is a strictly increasing sequence selected from 0,1,...,m. The
discrepancies
n −1
g k′ , j = f ( y j ) − ∑ ck ,i y ij
i =0
at all points j=0,...,m are then inspected, and from these a sequence
gk+1,j = gk,s(k+1,j)', j=0,...,n, is constructed which a) possesses the alternating
property sign gk+1,j = -sign gk+1,j-1, j=1,...,n, and b) for which gk+1,j ≥ gk,j,
j=0,...,n, with (unless the process is to be terminated) gk+1,j>gk,j for at least one
j (for the details of this construction, see the documentation to sndremez). The
coefficients {ck+1,i} in the succeeding polynomial are determined (by use of Newton's
interpolation formula, and subsequent reduction to the given polynomial form)
from condition (2) with k replaced by k+1.
Initially s(0,j), j=0,...,n, is a sequence of integer approximations to the
points at which Tn((2x-m)/m), where Tn(y) = cos{n arc cos(y)} being a Chebyshev
polynomial (see the documentation of ini) assumes its maximal absolute values in
the range 0 ≤ x ≤ m. The procedure ini is used to set the s(0,j).
Procedure parameters:
void minmaxpol (n,m,y,fy,co,em)
n: int;
entry: the degree of the approximating polynomial; n ≥ 0;
m: int;
public static void minmaxpol(int n, int m, double y[], double fy[], double co[],
double em[])
{
int np1,k,pomk,count,cnt,j,mi,sjm1,sj,s0,up;
double e,abse,abseh;
int s[] = new int[n+2];
double x[] = new double[n+2];
double b[] = new double[n+2];
double coef[] = new double[n+2];
double g[] = new double[m+1];
sj=0;
np1=n+1;
ini(np1,m,s);
mi=(int)em[2];
abse=0.0;
count=1;
do {
pomk=1;
for (k=0; k<=np1; k++) {
x[k]=y[s[k]];
coef[k]=fy[s[k]];
b[k]=pomk;
pomk = -pomk;
}
newton(np1,x,coef);
newton(np1,x,b);
em[0]=e=coef[np1]/b[np1];
Basic.elmvec(0,n,0,coef,b,-e);
Algebraic_eval.newgrn(n,x,coef);
s0=sjm1=s[0];
g[s0]=e;
for (j=1; j<=np1; j++) {
sj=s[j];
up=sj-1;
for (k=sjm1+1; k<=up; k++)
g[k]=fy[k]-Algebraic_eval.pol(n,y[k],coef);
g[sj] = e = -e;
sjm1=sj;
}
for (k=s0-1; k>=0; k--)
g[k]=fy[k]-Algebraic_eval.pol(n,y[k],coef);
for (k=sj+1; k<=m; k++)
g[k]=fy[k]-Algebraic_eval.pol(n,y[k],coef);
sndremez(np1,m,s,g,em);
abseh=abse;
abse=Math.abs(e);
cnt=count;
count++;
} while (count <= mi && abse > abseh);
em[2]=mi;
em[3]=cnt;
Basic.dupvec(0,n,0,co,coef);
}