Home
Manual
Packages
Global Index
Keywords
Quick Reference
|
/*
FITRAT.I
Polynomial and rational function interpolators.
$Id$
*/
/* Copyright (c) 1994. The Regents of the University of California.
All rights reserved. */
func fitpol (y, x, xp, keep=)
/* DOCUMENT yp= fitpol(y, x, xp)
-or- yp= fitpol(y, x, xp, keep=1)
is an interpolation routine similar to interp, except that fitpol
returns the polynomial of degree numberof(X)-1 which passes through
the given points (X,Y), evaluated at the requested points XP.
The X must either increase or decrease monotonically.
If the KEEP keyword is present and non-zero, the external variable
yperr will contain a list of error estimates for the returned values
yp on exit.
The algorithm is taken from Numerical Recipes (Press, et. al.,
Cambridge University Press, 1988); it is called Neville's algorithm.
The rational function interpolator fitrat is better for "typical"
functions. The Yorick implementaion requires numberof(X)*numberof(XP)
temporary arrays, so the X and Y arrays should be reasonably small.
SEE ALSO: fitrat, interp
*/
{
/* find lower and upper indices in x of the interval containing xp */
nx= numberof(x);
u= digitize(xp, x);
l= max(u-1, 1);
u= min(u, nx);
/* initialize yp to the y(x) closest to xp */
mask= (abs(x(l)-xp)<=abs(x(u)-xp));
ns= l*mask + u*(!mask);
yp= y(ns);
ns--;
c= d= y= array(double(y), dimsof(xp));
dx= x - xp(-,);
if (dimsof(ns)(1)) {
is= ns;
is(*)= nx*indgen(0:numberof(xp)-1);
} else {
is= 0;
}
for (m=1 ; m<nx ; m++) {
ho= dx(1:nx-m,..);
hp= dx(1+m:nx,..);
den= (c(2:nx-m+1,..)-d(1:nx-m,..))/(ho-hp);
d(1:nx-m,..)= hp*den;
c(1:nx-m,..)= ho*den;
mask= (2*ns>=(nx-m));
y= d(max(ns,1)+is)*mask + c(ns+1+is)*(!mask); /* this is error estimate */
yp+= y;
ns-= mask;
}
if (keep) {
extern yperr;
yperr= y;
}
return yp;
}
func fitrat (y, x, xp, keep=)
/* DOCUMENT yp= fitrat(y, x, xp)
-or- yp= fitrat(y, x, xp, keep=1)
is an interpolation routine similar to interp, except that fitpol
returns the diagonal rational function of degree numberof(X)-1 which
passes through the given points (X,Y), evaluated at the requested
points XP. (The numerator and denominator polynomials have equal
degree, or the denominator has one larger degree.)
The X must either increase or decrease monotonically. Also, this
algorithm works by recursion, fitting successively to consecutive
pairs of points, then consecutive triples, and so forth.
If there is a pole in any of these fits to subsets, the algorithm
fails even though the rational function for the final fit is non-
singular. In particular, if any of the Y values is zero, the
algorithm fails, and you should be very wary of lists for which
Y changes sign. Note that if numberof(X) is even, the rational
function is Y-translation invariant, while numberof(X) odd generally
results in a non-translatable fit (because it decays to y=0).
If the KEEP keyword is present and non-zero, the external variable
yperr will contain a list of error estimates for the returned values
yp on exit.
The algorithm is taken from Numerical Recipes (Press, et. al.,
Cambridge University Press, 1988); it is called the Bulirsch-Stoer
algorithm. The Yorick implementaion requires numberof(X)*numberof(XP)
temporary arrays, so the X and Y arrays should be reasonably small.
SEE ALSO: fitpol, interp
*/
{
/* find lower and upper indices in x of the interval containing xp */
nx= numberof(x);
u= digitize(xp, x);
l= max(u-1, 1);
u= min(u, nx);
/* initialize yp to the y(x) closest to xp */
mask= (abs(x(l)-xp)<=abs(x(u)-xp));
ns= l*mask + u*(!mask);
yp= y(ns);
exact= (x(ns)==xp);
list= where(exact);
if (numberof(list)) {
yexact= yp(list);
yerr= 0.0*yexact;
}
list= where(!exact);
if (numberof(list)) {
yp= yp(list);
xp= xp(list);
ns= ns(list);
c= d= y= array(double(y), numberof(xp));
d+= fitrat_tiny; /* I question whether this ever rescues a
failed fit, but I'll leave it here anyway. */
dx= x - xp(-,);
ns--;
is= nx*indgen(0:numberof(xp)-1);
for (m=1 ; m<nx ; m++) {
di= d(1:nx-m,);
ci= c(2:nx-m+1,);
t= dx(1:nx-m,)*di/dx(1+m:nx,);
dd= (ci-di)/(t-ci);
d(1:nx-m,)= ci*dd;
c(1:nx-m,)= t*dd;
mask= (2*ns>=(nx-m));
y= d(max(ns,1)+is)*mask + c(ns+1+is)*(!mask);
yp+= y;
ns-= mask;
}
} else {
yp= [];
}
if (keep) {
extern yperr;
yperr= merge(yerr, y, exact);
}
return merge(yexact, yp, exact);
}
fitrat_tiny= 1.e-30;
|