aboutsummaryrefslogtreecommitdiff
path: root/math/interp
diff options
context:
space:
mode:
Diffstat (limited to 'math/interp')
-rw-r--r--math/interp/Iinterp.hlp293
-rw-r--r--math/interp/README7
-rw-r--r--math/interp/arbpix.x203
-rw-r--r--math/interp/arider.x214
-rw-r--r--math/interp/arival.x124
-rw-r--r--math/interp/asidef.h16
-rw-r--r--math/interp/asider.x121
-rw-r--r--math/interp/asieva.x38
-rw-r--r--math/interp/asifit.x75
-rw-r--r--math/interp/asigrl.x201
-rw-r--r--math/interp/asiset.x20
-rw-r--r--math/interp/asival.x49
-rw-r--r--math/interp/bench.x55
-rw-r--r--math/interp/cubspl.f119
-rw-r--r--math/interp/iieval.x137
-rw-r--r--math/interp/iif_spline.x67
-rw-r--r--math/interp/iimail213
-rw-r--r--math/interp/iipol_terp.x41
-rw-r--r--math/interp/interp.h19
-rw-r--r--math/interp/interpdef.h19
-rw-r--r--math/interp/mkpkg21
-rw-r--r--math/interp/noteari64
-rw-r--r--math/interp/noteasi101
-rw-r--r--math/interp/notes3216
-rw-r--r--math/interp/overview43
-rw-r--r--math/interp/usernote118
26 files changed, 2594 insertions, 0 deletions
diff --git a/math/interp/Iinterp.hlp b/math/interp/Iinterp.hlp
new file mode 100644
index 00000000..527f0375
--- /dev/null
+++ b/math/interp/Iinterp.hlp
@@ -0,0 +1,293 @@
+
+.help INTERP Jan83 "Image Interpolation Package"
+.sh
+Introduction
+
+ One of the most common operations in image processing is interpolation.
+Due to the very large amount of data involved, efficiency is quite important,
+and the general purpose routines available from many sources cannot be used.
+
+
+The task of interpolating image data is simplified by the following
+considerations:
+.ls 4
+.ls o
+The pixels (data points) are equally spaced along a line or on a rectangular
+grid.
+.le
+.ls o
+There is no need for coordinate transformations. The coordinates of a pixel
+or point to be interpolated are the same as the subscript of the pixel in the
+data array. The coordinate of the first pixel in the array may be assumed
+to be 1.0, and the spacing between pixels is also 1.0.
+.le
+.le
+
+
+The task of interpolating image data is complicated by the following
+considerations:
+.ls
+.ls o
+We would like the "quality" of the interpolator to be something that can
+be set at run time by the user. This is done by permitting the user to
+select the type of interpolator to be used, and the order of interpolation.
+The following interpolators will be provided:
+
+.nf
+ - nearest neighbor
+ - linear
+ - natural cubic spline
+ - divided differences, either 3rd or 5th order.
+.fi
+.le
+.ls o
+The interpolator must be able to deal with indefinite valued pixels.
+In the IRAF, an indefinite valued pixel has the special value INDEF.
+If the interpolator cannot return a meaningful interpolated value
+(due to the presence of indefinite pixels in the data, or because the
+coordinates of the point to be interpolated are out of bounds) the value
+INDEF should be returned instead.
+.le
+.le
+
+.sh
+Sequential Interpolation of One Dimensional Arrays
+
+ Ideally, we should be able to define a single set of procedures
+which can perform interpolation by any of the techniques mentioned above.
+The procedures for interpolating one dimensional arrays are optimized
+for the case where the entire array is to be sampled, probably in a sequential
+fashion.
+
+The following calls should suffice. The package prefix is "asi", meaning
+array sequential interpolate, and the last three letters of each procedure
+name are used to describe the action performed by the procedure. The
+interpolator is restricted to single precision real data, so there is no
+need for a type suffix.
+
+.ks
+.nf
+ asiset (coeff, interpolator_type, boundary_type)
+ asifit (data, npts, coeff)
+ y = asival (x, coeff) # evaluate y(x)
+ asider (x, derivs, nderiv, coeff) # derivatives
+ v = asigrl (x1, x2, coeff) # take integral
+.fi
+.ke
+
+Here, COEFF is a structure used to describe the interpolant, and
+the interpolator type is chosen from the following set of options:
+
+.ks
+.nf
+ NEAREST return value of nearest neighbor
+ LINEAR linear interpolation
+ DIVDIF3 third order divided differences
+ DIVDIF5 fifth order divided differences
+ SPLINE3 cubic spline
+.fi
+.ke
+
+When the VAL procedure is called to evaluate the interpolant at a point X,
+the code must check to see if X is out of bounds. If so, the type of value
+returned may be specified by the third and final argument to the SET procedure.
+
+.ks
+.nf
+ B_NEAREST return nearest boundary (nb) value
+ B_INDEF (default; return indefinite)
+ B_REFLECT interpolate at abs(x)
+ B_WRAP wrap around to opposite boundary
+ B_PROJECT return y(nb) - (y(abs(x)) - y(nb))
+.fi
+.ke
+
+For example, the following subset preprocessor code fragment uses
+the array interpolation routines to shift a data array by a constant
+amount:
+
+
+.ks
+.nf
+ real shift, coeff[NPIX+SZ_ASIHDR]
+ real inrow[NPIX], outrow[NPIX], asival()
+ int i, interpolator_type, boundary_type, clgeti()
+
+ begin
+ # get parameters from CL, setup interpolator
+ interpolator_type = clgeti ("interpolator")
+ boundary_type = clgeti ("boundary_type")
+ call asiset (coeff, interpolator_type, boundary_type)
+
+ [code to read pixels into inrow]
+ call asifit (inrow, NPIX, coeff)
+
+ do i = 1, NPIX # do the interpolation
+ outrow[i] = asival (i + shift, coeff)
+.fi
+.ke
+
+
+The array COEFF is actually a simple structure. An initial call to ASISET
+is required to save the interpolator parameters in the COEFF structure.
+ASIFIT computes the coefficients of the interpolator curve, leaving the
+coefficients in the appropriate part of the COEFF structure. Thereafter,
+COEFF is read only. ASIVAL evaluates the zeroth derivative of the curve
+at the given X coordinate. ASIDER evaluates the first NDERIV derivatives
+at X, writing the values of these derivatives into the DERIVS output array.
+ASIGRL integrates the interpolant over the indicated range (returning INDEF
+if there are any indefinite pixels in that range).
+
+.ks
+.nf
+ element usage
+
+ 1 type of interpolator
+ 2 type of boundary condition
+ 3 number of pixels in x
+ 4 number of pixels in y
+ 5-9 reserved for future use
+ 10-N coefficients
+
+ The COEFF structure
+.fi
+.ke
+
+
+In the case of the nearest neighbor and linear interpolation algorithms,
+the coefficient array will contain the same data as the input data array.
+The cubic spline algorithm requires space for NPIX+2 b-spline coefficients.
+The space requirements of the divided differences algorithm are similar.
+The constant SZ_ASIHDR should allow enough space for the worst case.
+
+Note that both 3rd and 5th order divided differences interpolators are
+provided, but only the 3rd order (cubic) spline. This is because the
+5th order spline is considerably harder than the cubic spline. We can easily
+add a 5th order spline, or indeed a completely new algorithm such as the sinc
+function interpolator, without changing the calling sequences or data
+structures.
+
+.sh
+Random Interpolation of One Dimensional Arrays
+
+ If we wish only to interpolate a small region of an array, or a few
+points scattered along the array at random, or if memory space is more
+precious than execution speed, then a different sort of interpolator is
+desirable. We can dispense with the coefficient array in this case, and
+operate directly on the data array.
+
+.ks
+.nf
+ ariset (interpolator_type, boundary_type)
+ arifit (data, npts)
+ y = arival (x, data)
+ arider (x, derivs, nderiv, data)
+.fi
+.ke
+
+Since the number of points required to interpolate at a given X value
+is fixed, these routines are internally quite different than the sequential
+procedures.
+
+.sh
+Sequential Interpolation of Two Dimensional Arrays
+
+ None of the interpolation algorithms mentioned above are difficult
+to generalize to two dimensions. The calling sequences should be kept as
+similar as possible. The sequential two dimensional procedures are limited
+by the size of the two dimensional array which can be kept in memory, and
+therefore are most useful for subrasters. The COEFF array should be
+declared as a one dimensional array, even though it used to store a two
+dimensional array of coefficients.
+
+.ks
+.nf
+ msiset (coeff, interpolator_type), boundary_type)
+ msifit (data, nx, ny, coeff)
+ y = msival (x, y, coeff)
+ msider (x, y, derivs, nderiv, coeff)
+.fi
+.ke
+
+Note that the coefficients of the bicubic spline are obtained by first
+doing a one dimensional spline fit to the rows of the data array, leaving
+the resultant coefficients in the rows of the coeff array, followed by
+a series of one dimensional fits to the coefficients in the coeff array.
+The row coefficients are overwritten by the coefficients of the tensor
+product spline. Since all the work is done by the one dimensional spline
+fitting routine, little extra code is required to handle the two dimensional
+case.
+
+The bicubic spline is evaluated by summing the product C(i,j)*Bi(x)*Bj(y)
+at each of the sixteen coefficients contributing to the point (x,y).
+Once again, the one dimensional routines for evaluating the b-spline
+(the functions Bi(x) and Bj(y)) do most of the work.
+
+Although it is not required by very many applications, it would also
+be useful to be able to compute the surface integral of the interpolant
+over an arbitrary surface (this is useful for surface photometry
+applications). Never having done this, I do not have any recommendations
+on how to set up the calling sequence.
+
+.sh
+Random Interpolation of Two Dimensional Arrays
+
+ The random interpolation procedures are particularly useful for two
+dimensional arrays due to the increased size of the arrays. Also, if an
+application generally finds linear interpolation to be sufficient, and rarely
+uses a more expensive interpolator, the random routines will be more
+efficient overall.
+
+.ks
+.nf
+ mriset (interpolator_type, boundary_type)
+ msifit (data, nx, ny)
+ y = mrival (x, y, data)
+ mrider (x, y, derivs, nderiv, data)
+.fi
+.ke
+
+.sh
+Cardinal B-Splines
+
+ There are many different kinds of splines. One of the best
+for the case where the data points are equally spaced is the cardinal spline.
+The so called "natural" end point conditions are probably the best one can
+do with noisy data. Other end point conditions, such as not-a-knot, may be
+best for approximating analytic functions, but they are unreliable with
+noisy data. The natural cubic cardinal spline is fitted by solving the
+following tridiagonal system of equations (Prenter, 1975).
+
+
+.ks
+.nf
+ / : \
+ | 6 -12 6 : 0 |
+ | 1 4 1 : y(1) |
+ | 1 4 1 : y(2) |
+ | ... : |
+ | 1 4 1 : y(n-1) |
+ | 1 4 1 : y(n) |
+ | 6 -12 6 : 0 |
+ \ : /
+.fi
+.ke
+
+
+This matrix can most efficiently be solved by hardwiring the appropriate
+recursion relations into a procedure. The problem of what to do when some
+of the Y(i) are indefinite has not yet been solved.
+
+The b-spline basis function used above is defined by
+
+.ks
+.nf
+ B(x) = (x-x1)**3 x:[x1,x2]
+ B(x) = 1 + 3(x-x2) + 3(x-x2)**2 - 3(x-x2)**3 x:[x2,x3]
+ B(x) = 1 + 3(x3-x) + 3(x3-x)**2 - 3(x3-x)**3 x:[x3,x4]
+ B(x) = (x4-x)**3 x:[x4,x5]
+.fi
+.ke
+
+where X1 through X4 are the X coordinates of the four b-spline
+coefficients contributing to the b-spline function at X.
diff --git a/math/interp/README b/math/interp/README
new file mode 100644
index 00000000..915afd6e
--- /dev/null
+++ b/math/interp/README
@@ -0,0 +1,7 @@
+Image interpolation package. Contains interpolator routines specially
+designed to interpolate image data. This interpolator task is characterized
+by data arrays in which the data points are equally spaced. Data points
+and interpolation points are referenced simply by array index. Indefinite
+valued pixels may be present in the data. Since the interpolation routines
+will be applied to very large data arrays, efficiency is emphasized in these
+routines.
diff --git a/math/interp/arbpix.x b/math/interp/arbpix.x
new file mode 100644
index 00000000..0b61f3d2
--- /dev/null
+++ b/math/interp/arbpix.x
@@ -0,0 +1,203 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+.help
+ arbpix -- fix bad data
+
+Takes care of bad pixels by replacing the indef's with interpolated values.
+
+In order to replace bad points, the spline interpolator uses a limited
+data array, the maximum total length is given by SPLPTS.
+
+The process is divided as follows:
+ 1. Take care of points below first good point and above last good
+ good point.
+ 2. Load an array with only good points.
+ 3. Interpolate that array.
+
+.endhelp
+
+procedure arbpix(datain,n,dataout,terptype)
+include "interpdef.h"
+include "asidef.h"
+
+real datain[ARB] # data in array
+int n # no. of data points
+real dataout[ARB] # data out array - cannot be same as data in
+int terptype # interpolator type - see interpdef.h
+
+int i, badnc
+int k, ka, kb
+
+real iirbfval()
+
+begin
+
+ # count bad points
+ badnc = 0
+ do i = 1,n
+ if (IS_INDEFR (datain[i]))
+ badnc = badnc + 1
+
+ # return if all bad or all good
+ if(badnc == n || badnc == 0)
+ return
+
+
+ # find first good point
+ for (ka = 1; IS_INDEFR (datain[ka]); ka = ka + 1)
+ ;
+
+ # bad points below first good point are set at first value
+ do k = 1,ka-1
+ dataout[k] = datain[ka]
+
+ # find last good point
+ for (kb = n; IS_INDEFR (datain[kb]); kb = kb - 1)
+ ;
+
+ # bad points beyond last good point get set at last value
+ do k = n, kb+1, -1
+ dataout[k] = datain[kb]
+
+ # load the other points interpolating the bad points as needed
+ do k = ka, kb {
+ if (!IS_INDEFR (datain[k])) # good point
+ dataout[k] = datain[k]
+
+ else # bad point -- generate interpolated value
+ dataout[k] = iirbfval(datain[ka],kb-ka+1,k-ka+1,terptype)
+ }
+
+end
+
+# This part fills a temporary array with good points that bracket the
+# bad point and calls the interpolating routine.
+
+real procedure iirbfval(y, n, k, terptype)
+
+real y[ARB] # data_in array, y[1] and y[n] guaranteed to be good.
+int n # length of data_in array.
+int k # index of bad point to replace.
+int terptype
+
+int j, jj, pd, pu, tk, pns
+real td[SPLPTS], tx[SPLPTS] # temporary arrays for interpolation
+
+real iirbint()
+
+begin
+ # The following test is done to improve speed.
+ # This code will work only if subroutines are implemented by
+ # using static storage - i.e. the old internal values survive.
+ # This avoids reloading of temporary arrays if
+ # there are consequetive bad points.
+
+ if (!IS_INDEFR (y[k-1])) {
+ # set number of good points needed on each side of bad point
+ switch (terptype) {
+ case IT_NEAREST :
+ pns = 1
+ case IT_LINEAR :
+ pns = 1
+ case IT_POLY3 :
+ pns = 2
+ case IT_POLY5 :
+ pns = 3
+ case IT_SPLINE3 :
+ pns = SPLPTS / 2
+ }
+
+ # search down
+ pd = 0
+ for (j = k-1; j >= 1 && pd < pns; j = j-1)
+ if (!IS_INDEFR (y[j]))
+ pd = pd + 1
+
+ # load temp. arrays for values below our indef.
+ tk = 0
+ for(jj = j + 1; jj < k; jj = jj + 1)
+ if (!IS_INDEFR (y[jj])) {
+ tk = tk + 1
+ td[tk] = y[jj]
+ tx[tk] = jj
+ }
+
+ # search and load up from indef.
+ pu = 0
+ for (j = k + 1; j <= n && pu < pns; j = j + 1)
+ if (!IS_INDEFR (y[j])) {
+ pu = pu + 1
+ tk = tk + 1
+ td[tk] = y[j]
+ tx[tk] = j
+ }
+ }
+
+ # return value interpolated from these arrays.
+ return(iirbint(real(k), tx, td, tk, pd, terptype))
+
+end
+
+
+# This part interpolates the temporary arrays.
+# It does not represent a general purpose routine because the
+# previous part has determined the proper indices etc. so that
+# effort is not duplicated here.
+
+real procedure iirbint (x, tx, td, tk, pd, terptype)
+
+real x # point to interpolate
+real tx[ARB] # xvalues
+real td[ARB] # data values
+int tk # size of data array
+int pd # index such that tx[pd] < x < tx[pd+1]
+int terptype
+
+int i, ks, tpol
+real cc[4,SPLPTS]
+real h
+
+real iipol_terp()
+
+begin
+ switch (terptype) {
+
+ case IT_NEAREST :
+ if (x - tx[1] > tx[2] - x)
+ return(td[2])
+ else
+ return(td[1])
+
+ case IT_LINEAR :
+ return(td[1] + (x - tx[1]) *
+ (td[2] - td[1]) / (tx[2] - tx[1]))
+
+ case IT_SPLINE3 :
+ do i = 1,tk
+ cc[1,i] = td[i]
+ cc[2,1] = 0.
+ cc[2,tk] = 0.
+
+ # use spline routine from C. de Boor's book
+ # A Practical Guide to Splines
+ call cubspl(tx,cc,tk,2,2)
+ h = x - tx[pd]
+ return(cc[1,pd] + h * (cc[2,pd] + h *
+ (cc[3,pd] + h * cc[4,pd]/3.)/2.))
+
+ default : # one of the polynomial types
+ # allow lower order if not enough points on one side
+ tpol = tk
+ ks = 1
+ if (tk - pd < pd) {
+ tpol = 2 * (tk - pd)
+ ks = 2 * pd - tk + 1
+ }
+ if (tk - pd > pd)
+ tpol = 2 * pd
+
+ # finally polynomial interpolate
+ return(iipol_terp(tx[ks], td[ks], tpol, x))
+ }
+
+end
diff --git a/math/interp/arider.x b/math/interp/arider.x
new file mode 100644
index 00000000..fef55e0e
--- /dev/null
+++ b/math/interp/arider.x
@@ -0,0 +1,214 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+.help
+ arider -- random interpolator returns derivatives
+
+First looks at type of interpolator requested, then calls routine
+to evaluate.
+No error traps are included -- unreasonable values for the number of
+data points or the x position will either produce hard errors or garbage.
+
+.endhelp
+
+procedure arider(x, datain, n, derivs, nderiv, interptype)
+include "interpdef.h"
+
+real x # need 1 <= x <= n
+real datain[ARB] # data values
+int n # number of data values
+real derivs[ARB] # derivatives out -- beware derivs[1] is
+ # function value
+int nderiv # total number of values returned in derivs
+int interptype
+
+int i, j, k, nt, nd, nx
+real pc[6], ac, s
+
+begin
+ if(nderiv <= 0)
+ return
+
+ # zero out derivs array
+ do i = 1, nderiv
+ derivs[i] = 0.
+
+ switch (interptype) {
+ case IT_NEAREST :
+ derivs[1] = datain[int(x + 0.5)]
+ return
+ case IT_LINEAR :
+ nx = x
+ if( nx >= n )
+ nx = nx - 1
+ derivs[1] = (x - nx) * datain[nx+1] + (nx + 1 - x) * datain[nx]
+ if(nderiv >= 2)
+ derivs[2] = datain[nx+1] - datain[nx]
+ return
+ # The other cases call subroutines to generate polynomial coeff.
+ case IT_POLY3 :
+ call iidr_poly3(x, datain, n, pc)
+ nt = 4
+ case IT_POLY5 :
+ call iidr_poly5(x, datain, n, pc)
+ nt = 6
+ case IT_SPLINE3 :
+ call iidr_spline3(x, datain, n, pc)
+ nt = 4
+ }
+
+ nx = x
+ s = x - nx
+ nd = nderiv
+ if (nderiv > nt)
+ nd = nt
+
+ do k = 1,nd {
+ ac = pc[nt - k + 1] # evluate using nested multiplication
+ do j = nt - k, 1, -1
+ ac = pc[j] + s * ac
+
+ derivs[k] = ac
+
+ do j = 1, nt - k # differentiate
+ pc[j] = j * pc[j + 1]
+ }
+end
+
+procedure iidr_poly3(x, datain, n, pc)
+
+real x
+real datain[ARB]
+int n
+real pc[ARB]
+
+int i, k, nx, nt
+real a[4]
+
+begin
+
+ nx = x
+
+ # The major complication is that near the edge interior polynomial
+ # must somehow be defined.
+ k = 0
+ for(i = nx - 1; i <= nx + 2; i = i + 1){
+ k = k + 1
+ # project data points into temporary array
+ if ( i < 1 )
+ a[k] = 2. * datain[1] - datain[2 - i]
+ else if ( i > n )
+ a[k] = 2. * datain[n] - datain[2 * n - i]
+ else
+ a[k] = datain[i]
+ }
+
+ nt = 4
+
+ # generate diffrence table for Newton's form
+ do k = 1, nt-1
+ do i = 1, nt-k
+ a[i] = (a[i+1] - a[i]) / k
+
+ # shift to generate polynomial coefficients
+ do k = nt,2,-1
+ do i = 2,k
+ a[i] = a[i] + a[i-1] * (k - i - nt/2)
+
+ do i = 1,nt
+ pc[i] = a[nt+1-i]
+
+ return
+
+end
+
+procedure iidr_poly5(x, datain, n, pc)
+
+real x
+real datain[ARB]
+int n
+real pc[ARB]
+
+int i, k, nx, nt
+real a[6]
+
+begin
+
+ nx = x
+
+ # The major complication is that near the edge interior polynomial
+ # must somehow be defined.
+ k = 0
+ for(i = nx - 2; i <= nx + 3; i = i + 1){
+ k = k + 1
+ # project data points into temporary array
+ if ( i < 1 )
+ a[k] = 2. * datain[1] - datain[2 - i]
+ else if ( i > n )
+ a[k] = 2. * datain[n] - datain[2 * n - i]
+ else
+ a[k] = datain[i]
+ }
+
+ nt = 6
+
+ # generate diffrence table for Newton's form
+ do k = 1, nt-1
+ do i = 1, nt-k
+ a[i] = (a[i+1] - a[i]) / k
+
+ # shift to generate polynomial coefficients
+ do k = nt,2,-1
+ do i = 2,k
+ a[i] = a[i] + a[i-1] * (k - i - nt/2)
+
+ do i = 1,nt
+ pc[i] = a[nt+1-i]
+
+ return
+
+end
+
+procedure iidr_spline3(x, datain, n, pc)
+
+real x
+real datain[ARB]
+int n
+real pc[ARB]
+
+int i, k, nx, px
+real temp[SPLPTS+2], bcoeff[SPLPTS+2], h
+
+begin
+
+ nx = x
+
+ h = x - nx
+ k = 0
+ # maximum number of points used is SPLPTS
+ for(i = nx - SPLPTS/2 + 1; i <= nx + SPLPTS/2; i = i + 1){
+ if(i < 1 || i > n)
+ ;
+ else {
+ k = k + 1
+ if(k == 1)
+ px = nx - i + 1
+ bcoeff[k+1] = datain[i]
+ }
+ }
+
+ bcoeff[1] = 0.
+ bcoeff[k+2] = 0.
+
+ # Use special routine for cardinal splines.
+ call iif_spline(bcoeff, temp, k)
+
+ px = px + 1
+
+ pc[1] = bcoeff[px-1] + 4. * bcoeff[px] + bcoeff[px+1]
+ pc[2] = 3. * (bcoeff[px+1] - bcoeff[px-1])
+ pc[3] = 3. * (bcoeff[px-1] - 2. * bcoeff[px] + bcoeff[px+1])
+ pc[4] = -bcoeff[px-1] + 3. * bcoeff[px] - 3. * bcoeff[px+1] +
+ bcoeff[px+2]
+
+ return
+end
diff --git a/math/interp/arival.x b/math/interp/arival.x
new file mode 100644
index 00000000..50ee1c3e
--- /dev/null
+++ b/math/interp/arival.x
@@ -0,0 +1,124 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+.help
+ arival -- random interpolator returns value
+
+No error traps are included -- unreasonable values for the number of
+data points or the x position will either produce hard errors or garbage.
+This version is written in-line for speed.
+
+.endhelp
+
+real procedure arival(x, datain, n, interptype)
+include "interpdef.h"
+
+real x # need 1 <= x <= n
+real datain[ARB] # data values
+int n # number of data values
+int interptype
+
+int i, k, nx, px
+real a[6], cd20, cd21, cd40, cd41, s, t, h
+real bcoeff[SPLPTS+2], temp[SPLPTS+2], pc[4]
+
+begin
+ switch (interptype) {
+ case IT_NEAREST :
+ return(datain[int(x + 0.5)])
+ case IT_LINEAR :
+ nx = x
+ # protect against x = n case
+ # else it will reference datain[n + 1]
+ if(nx >= n)
+ nx = nx - 1
+ return((x - nx) * datain[nx+1] + (nx + 1 - x) * datain[nx])
+ case IT_POLY3 :
+ nx = x
+
+ # The major complication is that near the edge interior polynomial
+ # must somehow be defined.
+ k = 0
+ for(i = nx - 1; i <= nx + 2; i = i + 1){
+ k = k + 1
+ # project data points into temporary array
+ if ( i < 1 )
+ a[k] = 2. * datain[1] - datain[2 - i]
+ else if ( i > n )
+ a[k] = 2. * datain[n] - datain[2 * n - i]
+ else
+ a[k] = datain[i]
+ }
+
+ s = x - nx
+ t = 1. - s
+
+ # second central differences
+ cd20 = 1./6. * (a[3] - 2. * a[2] + a[1])
+ cd21 = 1./6. * (a[4] - 2. * a[3] + a[2])
+
+ return( s * (a[3] + (s * s - 1.) * cd21) +
+ t * (a[2] + (t * t - 1.) * cd20) )
+ case IT_POLY5 :
+ nx = x
+
+ # The major complication is that near the edge interior polynomial
+ # must somehow be defined.
+ k = 0
+ for(i = nx - 2; i <= nx + 3; i = i + 1){
+ k = k + 1
+ # project data points into temporary array
+ if ( i < 1 )
+ a[k] = 2. * datain[1] - datain[2 - i]
+ else if ( i > n )
+ a[k] = 2. * datain[n] - datain[2 * n - i]
+ else
+ a[k] = datain[i]
+ }
+
+ s = x - nx
+ t = 1. - s
+
+ # second central differences
+ cd20 = 1./6. * (a[4] - 2. * a[3] + a[2])
+ cd21 = 1./6. * (a[5] - 2. * a[4] + a[3])
+
+ # fourth central differences
+ cd40 = 1./120. * (a[1] - 4. * a[2] + 6. * a[3] - 4. * a[4] + a[5])
+ cd41 = 1./120. * (a[2] - 4. * a[3] + 6. * a[4] - 4. * a[5] + a[6])
+
+ return( s * (a[4] + (s * s - 1.) * (cd21 + (s * s - 4.) * cd41)) +
+ t * (a[3] + (t * t - 1.) * (cd20 + (t * t - 4.) * cd40)) )
+ case IT_SPLINE3 :
+ nx = x
+
+ h = x - nx
+ k = 0
+ # maximum number of points used is SPLPTS
+ for(i = nx - SPLPTS/2 + 1; i <= nx + SPLPTS/2; i = i + 1){
+ if(i < 1 || i > n)
+ ;
+ else {
+ k = k + 1
+ if(k == 1)
+ px = nx - i + 1
+ bcoeff[k+1] = datain[i]
+ }
+ }
+
+ bcoeff[1] = 0.
+ bcoeff[k+2] = 0.
+
+ # Use special routine for cardinal splines.
+ call iif_spline(bcoeff, temp, k)
+
+ px = px + 1
+
+ pc[1] = bcoeff[px-1] + 4. * bcoeff[px] + bcoeff[px+1]
+ pc[2] = 3. * (bcoeff[px+1] - bcoeff[px-1])
+ pc[3] = 3. * (bcoeff[px-1] - 2. * bcoeff[px] + bcoeff[px+1])
+ pc[4] = -bcoeff[px-1] + 3. * bcoeff[px] - 3. * bcoeff[px+1] +
+ bcoeff[px+2]
+
+ return(pc[1] + h * (pc[2] + h * (pc[3] + h * pc[4])))
+ }
+end
diff --git a/math/interp/asidef.h b/math/interp/asidef.h
new file mode 100644
index 00000000..9fd06084
--- /dev/null
+++ b/math/interp/asidef.h
@@ -0,0 +1,16 @@
+# defines for use with interpolator package
+# intended for internal consumption only
+# used to set up storage in coeff array
+
+define TYPEI coeff[1] # code for interpolator type
+define NPTS coeff[2] # no. of data points
+
+define ITYPEI int(coeff[1])
+define INPTS int(coeff[2])
+
+define ASITYPEERR 1
+define ASIFITERR 2
+
+define COFF 10 # offset into coeff array
+ # beware coeff[COFF - 2] is first
+ # location used !!
diff --git a/math/interp/asider.x b/math/interp/asider.x
new file mode 100644
index 00000000..2c9a2819
--- /dev/null
+++ b/math/interp/asider.x
@@ -0,0 +1,121 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+.help
+ procedure asider
+
+ This procedure finds derivatives assuming that x lands in
+array i.e. 1 <= x <= npts.
+It must be called by a routine that checks for out of bound references
+and takes care of bad points and checks to make sure that the number
+of derivatives requested is reasonable (max. is 5 derivatives or nder
+can be 6 at most and min. nder is 1)
+
+ This version assumes interior polynomial interpolants are stored as
+the data points with corections for bad points, and the spline interpolant
+is stored as a series of b-spline coefficients.
+
+ The storage and evaluation for nearest neighbor and linear interpolation
+are simpler so they are evaluated separately from other piecewise
+polynomials.
+.endhelp
+
+procedure asider(x,der,nder,coeff)
+include "interpdef.h"
+include "asidef.h"
+
+real x
+real coeff[ARB]
+int nder # no. items returned = 1 + no. of deriv.
+
+real der[ARB] # der[1] is value der[2] is f prime etc.
+
+int nx,n0,i,j,k,nt,nd
+real s,ac,pc[6],d[6]
+
+begin
+ do i = 1, nder # return zero for derivatives that are zero
+ der[i] = 0.
+
+ nt = 0 # nt is number of terms in case polynomial type
+
+ switch (ITYPEI) { # switch on interpolator type
+
+ case IT_NEAREST :
+ der[1] = (coeff[COFF + nint(x)])
+ return
+
+ case IT_LINEAR :
+ nx = x
+ der[1] = (x - nx) * coeff[COFF + nx + 1] +
+ (nx + 1 - x) * coeff[COFF + nx]
+ if ( nder > 1 ) # try to return exact number requested
+ der[2] = coeff[COFF + nx + 1] - coeff[COFF + nx]
+ return
+
+ case IT_POLY3 :
+ nt = 4
+
+ case IT_POLY5 :
+ nt = 6
+
+ case IT_SPLINE3 :
+ nt = 4
+
+ }
+
+ # falls through to here if interpolant is one of
+ # the higher order polynomial types or third order spline
+
+ nx = x
+ n0 = COFF + nx
+ s = x - nx
+
+ nd = nder # no. of derivatives needed
+ if ( nder > nt )
+ nd = nt
+
+ # generate polynomial coefficients, first for spline.
+ if (ITYPEI == IT_SPLINE3) {
+ pc[1] = coeff[n0-1] + 4. * coeff[n0] + coeff[n0+1]
+ pc[2] = 3. * (coeff[n0+1] - coeff[n0-1])
+ pc[3] = 3. * (coeff[n0-1] - 2. * coeff[n0] + coeff[n0+1])
+ pc[4] = -coeff[n0-1] + 3. * coeff[n0] - 3. * coeff[n0+1] +
+ coeff[n0+2]
+
+ } else {
+
+ # Newton's form written in line to get polynomial from data
+ # load data
+ do i = 1,nt
+ d[i] = coeff[n0 - nt/2 + i]
+
+ # generate difference table
+ do k = 1, nt-1
+ do i = 1,nt-k
+ d[i] = (d[i+1] - d[i]) / k
+
+ # shift to generate polynomial coefficients of (x - n0)
+ do k = nt,2,-1
+ do i = 2,k
+ d[i] = d[i] + d[i-1] * (k - i - nt/2)
+
+ do i = 1,nt
+ pc[i] = d[nt + 1 - i]
+ }
+
+ do k = 1,nd { # as loop progresses pc contains coefficients of
+ # higher and higher derivatives
+
+ ac = pc[nt - k + 1]
+ do j = nt - k, 1, -1 # evaluate using nested mult.
+ ac = pc[j] + s * ac
+
+ der[k] = ac
+
+ do j = 1,nt - k # differentiate polynomial
+ pc[j] = j * pc[j + 1]
+ }
+
+ return
+
+end
diff --git a/math/interp/asieva.x b/math/interp/asieva.x
new file mode 100644
index 00000000..bc5fcbb3
--- /dev/null
+++ b/math/interp/asieva.x
@@ -0,0 +1,38 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+# procedure to evaluate interpolator at a sequence of ordered points
+# aasumes that all x_values land within [1,n].
+
+procedure asieva(x, y, n, coeff)
+include "interpdef.h"
+include "asidef.h"
+
+real x[ARB] # ordered x array
+int n # no. of points in x
+real coeff[ARB]
+
+real y[ARB] # interpolated values
+
+begin
+ switch (ITYPEI) { # switch on interpolator type
+
+ case IT_NEAREST :
+ call iievne(x, y, n, coeff[COFF + 1])
+
+ case IT_LINEAR :
+ call iievli(x, y, n, coeff[COFF + 1])
+
+ case IT_POLY3 :
+ call iievp3(x, y, n, coeff[COFF + 1])
+
+ case IT_POLY5 :
+ call iievp5(x, y, n, coeff[COFF + 1])
+
+ case IT_SPLINE3 :
+ call iievs3(x, y, n, coeff[COFF + 1])
+
+ }
+
+ return
+
+end
diff --git a/math/interp/asifit.x b/math/interp/asifit.x
new file mode 100644
index 00000000..12b16b0f
--- /dev/null
+++ b/math/interp/asifit.x
@@ -0,0 +1,75 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+.help
+ asifit -- fit interpolator to data
+
+This version uses the "basis-spline" representation for the spline.
+It stores the data array itself for the polynomial interpolants.
+
+.endhelp
+
+procedure asifit(datain,n,coeff)
+include "interpdef.h"
+include "asidef.h"
+
+real datain[ARB] # data array
+int n # no. of data points
+real coeff[ARB]
+
+int i
+
+begin
+ NPTS = n
+
+ # error trap - check data array for size
+ switch (ITYPEI) {
+ case IT_SPLINE3:
+ if(n < 4)
+ call error(ASIFITERR,"too few points for spline")
+ case IT_POLY5:
+ if(n < 6)
+ call error(ASIFITERR,"too few points for poly5")
+ case IT_POLY3:
+ if(n < 4)
+ call error(ASIFITERR,"too few points for poly3")
+ case IT_LINEAR:
+ if(n < 2)
+ call error(ASIFITERR,"too few points for linear")
+ default:
+ if(n < 1)
+ call error(ASIFITERR,"too few points for interpolation")
+
+ }
+
+ do i = 1,n
+ coeff[COFF + i] = datain[i]
+
+
+ if (ITYPEI == IT_SPLINE3) {
+
+ # specify natural end conditions - second deriv. zero
+ coeff[COFF] = 0.
+ coeff[COFF+n+1] = 0.
+
+ # fit spline - generate b-spline coefficients.
+ call iif_spline(coeff[COFF],coeff[COFF + n + 2],n)
+
+
+ } else { # not the spline
+ # We extend array to take care of values near edge.
+
+ # Assign arbitrary values in case there are only a few points.
+ for(i = n + 1; i < 5; i = i + 1)
+ coeff[COFF + i] = coeff[COFF + n]
+
+ # Extend for worst case - poly 5 may need 3 extra points.
+ do i = 1,3 { # same recipe as project
+ coeff[COFF+1 - i] = 2. * coeff[COFF + 1] -
+ coeff[COFF + 1 + i]
+ coeff[COFF+n + i] = 2. * coeff[COFF + n] -
+ coeff[COFF + n - i]
+ }
+ }
+
+ return
+end
diff --git a/math/interp/asigrl.x b/math/interp/asigrl.x
new file mode 100644
index 00000000..d528d0be
--- /dev/null
+++ b/math/interp/asigrl.x
@@ -0,0 +1,201 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+.help
+ procedure asigrl
+
+ This procedure finds the integral of the interpolant from a to b
+assuming both a and b land in the array.
+.endhelp
+
+real procedure asigrl(a,b,coeff) # returns value of integral
+include "interpdef.h"
+include "asidef.h"
+
+real a,b # integral limits
+real coeff[ARB]
+
+int na,nb,i,j,n0,nt
+real s,t,ac,xa,xb,pc[6]
+
+begin
+ xa = a
+ xb = b
+ if ( a > b ) { # flip order and sign at end
+ xa = b
+ xb = a
+ }
+
+ na = xa
+ nb = xb
+ ac = 0. # zero accumulator
+
+ # set number of terms
+ switch (ITYPEI) { # switch on interpolator type
+ case IT_NEAREST :
+ nt = 0
+ case IT_LINEAR :
+ nt = 1
+ case IT_POLY3 :
+ nt = 4
+ case IT_POLY5 :
+ nt = 6
+ case IT_SPLINE3 :
+ nt = 4
+ }
+
+ # NEAREST_NEIGHBOR and LINEAR are handled differently because of
+ # storage. Also probably good for speed.
+
+ if (nt == 0) { # NEAREST_NEIGHBOR
+ # reset segment to center values
+ na = xa + 0.5
+ nb = xb + 0.5
+
+ # set up for first segment
+ s = xa - na
+
+ # for clarity one segment case is handled separately
+ if ( nb == na ) { # only one segment involved
+ t = xb - nb
+ n0 = COFF + na
+ ac = ac + (t - s) * coeff[n0]
+ } else { # more than one segment
+
+ # first segment
+ n0 = COFF + na
+ ac = ac + (0.5 - s) * coeff[n0]
+
+ # middle segments
+ do j = na+1, nb-1 {
+ n0 = COFF + j
+ ac = ac + coeff[n0]
+ }
+
+ # last segment
+ n0 = COFF + nb
+ t = xb - nb
+ ac = ac + (t + 0.5) * coeff[n0]
+ }
+
+ } else if (nt == 1) { # LINEAR
+ # set up for first segment
+ s = xa - na
+
+ # for clarity one segment case is handled separately
+ if ( nb == na ) { # only one segment involved
+ t = xb - nb
+ n0 = COFF + na
+ ac = ac + (t - s) * coeff[n0] +
+ 0.5 * (coeff[n0+1] - coeff[n0]) * (t*t - s*s)
+ } else { # more than one segment
+
+ # first segment
+ n0 = COFF + na
+ ac = ac + (1. - s) * coeff[n0] +
+ 0.5 * (coeff[n0+1] - coeff[n0]) * (1. - s*s)
+
+ # middle segments
+ do j = na+1, nb-1 {
+ n0 = COFF + j
+ ac = ac + 0.5 * (coeff[n0+1] + coeff[n0])
+ }
+
+ # last segment
+ n0 = COFF + nb
+ t = xb - nb
+ ac = ac + coeff[n0] * t + 0.5 *
+ (coeff[n0+1] - coeff[n0]) * t * t
+ }
+
+ } else { # A higher order interpolant
+
+ # set up for first segment
+ s = xa - na
+
+ # for clarity one segment case is handled separately
+ if ( nb == na ) { # only one segment involved
+ t = xb - nb
+ n0 = COFF + na
+ call iigetpc(n0,pc,coeff)
+ do i = 1,nt
+ ac = ac + (1./i) * pc[i] * (t ** i - s ** i)
+ } else { # more than one segment
+
+ # first segment
+ n0 = COFF + na
+ call iigetpc(n0,pc,coeff)
+ do i = 1,nt
+ ac = ac + (1./i) * pc[i] * (1. - s ** i)
+
+ # middle segments
+ do j = na+1, nb-1 {
+ n0 = COFF + j
+ call iigetpc(n0,pc,coeff)
+ do i = 1,nt
+ ac = ac + (1./i) * pc[i]
+ }
+
+ # last segment
+ n0 = COFF + nb
+ t = xb - nb
+ call iigetpc(n0,pc,coeff)
+ do i = 1,nt
+ ac = ac + (1./i) * pc[i] * t ** i
+ }
+ }
+
+ if ( a < b )
+ return(ac)
+ else
+ return(-ac)
+end
+
+
+procedure iigetpc(n0, pc, coeff) # generates polynomial coefficients
+ # if spline or poly3 or poly5
+
+int n0 # coefficients wanted for n0 < x n0 + 1
+real coeff[ARB]
+
+real pc[ARB]
+
+int i,k,nt
+real d[6]
+
+begin
+ # generate polynomial coefficients, first for spline.
+ if (ITYPEI == IT_SPLINE3) {
+ pc[1] = coeff[n0-1] + 4. * coeff[n0] + coeff[n0+1]
+ pc[2] = 3. * (coeff[n0+1] - coeff[n0-1])
+ pc[3] = 3. * (coeff[n0-1] - 2. * coeff[n0] + coeff[n0+1])
+ pc[4] = -coeff[n0-1] + 3. * coeff[n0] - 3. * coeff[n0+1] +
+ coeff[n0+2]
+
+ } else {
+ if (ITYPEI == IT_POLY5)
+ nt = 6
+ else # must be POLY3
+ nt = 4
+
+ # Newton's form written in line to get polynomial from data
+
+ # load data
+ do i = 1,nt
+ d[i] = coeff[n0 - nt/2 + i]
+
+ # generate difference table
+ do k = 1, nt-1
+ do i = 1,nt-k
+ d[i] = (d[i+1] - d[i]) / k
+
+ # shift to generate polynomial coefficients of (x - n0)
+ do k = nt,2,-1
+ do i = 2,k
+ d[i] = d[i] + d[i-1] * (k - i - 2)
+
+ do i = 1,nt
+ pc[i] = d[nt + 1 - i]
+ }
+
+ return
+end
diff --git a/math/interp/asiset.x b/math/interp/asiset.x
new file mode 100644
index 00000000..126f4e39
--- /dev/null
+++ b/math/interp/asiset.x
@@ -0,0 +1,20 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+# sets sequential interpolator type
+
+procedure asiset(coeff,interptype)
+include "interpdef.h"
+include "asidef.h"
+
+int interptype
+real coeff[ARB]
+
+begin
+
+ if(interptype <= 0 || interptype > ITNIT)
+ call error(ASITYPEERR,"illegal interpolator type")
+ else
+ TYPEI = interptype
+
+ return
+end
diff --git a/math/interp/asival.x b/math/interp/asival.x
new file mode 100644
index 00000000..56f18938
--- /dev/null
+++ b/math/interp/asival.x
@@ -0,0 +1,49 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+.help
+ procedure asival
+
+ This procedure finds interpolated value assuming that x lands in
+array i.e. 1 <= x < npts.
+It must be called by a routine that checks for out of bound references
+and takes care of bad pixels.
+ This version assumes that the data are stored for polynomials and
+the spline appears as basis-spline coefficients.
+ Also the sequential evaluators are used to obtain the values in
+order to reduce the amount of duplicated code.
+.endhelp
+
+real procedure asival(x,coeff)
+include "interpdef.h"
+include "asidef.h"
+
+real x
+real coeff[ARB]
+
+real t
+
+begin
+ switch (ITYPEI) { # switch on interpolator type
+
+ case IT_NEAREST :
+ call iievne(x,t,1,coeff[COFF+1])
+ return(t)
+
+ case IT_LINEAR :
+ call iievli(x,t,1,coeff[COFF+1])
+ return(t)
+
+ case IT_POLY3 :
+ call iievp3(x,t,1,coeff[COFF+1])
+ return(t)
+
+ case IT_POLY5 :
+ call iievp5(x,t,1,coeff[COFF+1])
+ return(t)
+
+ case IT_SPLINE3 :
+ call iievs3(x,t,1,coeff[COFF+1])
+ return(t)
+
+ }
+end
diff --git a/math/interp/bench.x b/math/interp/bench.x
new file mode 100644
index 00000000..539ddf67
--- /dev/null
+++ b/math/interp/bench.x
@@ -0,0 +1,55 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+
+include "/usr/vesa/spec/terpdef.h"
+
+# Quickie benchmark, 1-d sequential image interpolators.
+
+define MAX_PIXELS 2048
+define SZ_NAME 20
+
+
+task interp
+
+
+procedure interp()
+
+real data[MAX_PIXELS], x[MAX_PIXELS], y[MAX_PIXELS]
+real coeff[2 * MAX_PIXELS + SZ_ASI]
+char interp_name[SZ_NAME]
+int i, j, npix, nlines, interpolant
+bool streq()
+int clgeti()
+
+begin
+ npix = min (MAX_PIXELS, clgeti ("npix"))
+ nlines = npix # square image
+ call clgstr ("interpolant", interp_name, SZ_NAME)
+
+ if (streq (interp_name, "nearest"))
+ interpolant = IT_NEAR
+ else if (streq (interp_name, "linear"))
+ interpolant = IT_LINEAR
+ else if (streq (interp_name, "poly3"))
+ interpolant = IT_POLY3
+ else if (streq (interp_name, "poly5"))
+ interpolant = IT_POLY5
+ else if (streq (interp_name, "spline3"))
+ interpolant = IT_SPLINE3
+ else
+ call error (0, "Unknown interpolant keyword")
+
+ call asiset (coeff, II_INIT, 0)
+ call asiset (coeff, II_INTERPOLANT, interpolant)
+ call asiset (coeff, II_ALLGOODPIX, YES)
+
+ do i = 1, npix { # initialize data, x arrays
+ data[i] = max(1.0, min(real(npix), real(i) + 0.15151))
+ x[i] = i
+ }
+
+ do j = 1, nlines { # interpolate npix ** 2
+ call asifit (data, npix, coeff)
+ call asieva (x, y, npix, coeff)
+ }
+end
diff --git a/math/interp/cubspl.f b/math/interp/cubspl.f
new file mode 100644
index 00000000..4bb54964
--- /dev/null
+++ b/math/interp/cubspl.f
@@ -0,0 +1,119 @@
+ subroutine cubspl ( tau, c, n, ibcbeg, ibcend )
+c from * a practical guide to splines * by c. de boor
+c ************************ input ***************************
+c n = number of data points. assumed to be .ge. 2.
+c (tau(i), c(1,i), i=1,...,n) = abscissae and ordinates of the
+c data points. tau is assumed to be strictly increasing.
+c ibcbeg, ibcend = boundary condition indicators, and
+c c(2,1), c(2,n) = boundary condition information. specifically,
+c ibcbeg = 0 means no boundary condition at tau(1) is given.
+c in this case, the not-a-knot condition is used, i.e. the
+c jump in the third derivative across tau(2) is forced to
+c zero, thus the first and the second cubic polynomial pieces
+c are made to coincide.)
+c ibcbeg = 1 means that the slope at tau(1) is made to equal
+c c(2,1), supplied by input.
+c ibcbeg = 2 means that the second derivative at tau(1) is
+c made to equal c(2,1), supplied by input.
+c ibcend = 0, 1, or 2 has analogous meaning concerning the
+c boundary condition at tau(n), with the additional infor-
+c mation taken from c(2,n).
+c *********************** output **************************
+c c(j,i), j=1,...,4; i=1,...,l (= n-1) = the polynomial coefficients
+c of the cubic interpolating spline with interior knots (or
+c joints) tau(2), ..., tau(n-1). precisely, in the interval
+c interval (tau(i), tau(i+1)), the spline f is given by
+c f(x) = c(1,i)+h*(c(2,i)+h*(c(3,i)+h*c(4,i)/3.)/2.)
+c where h = x - tau(i). the function program *ppvalu* may be
+c used to evaluate f or its derivatives from tau,c, l = n-1,
+c and k=4.
+ integer ibcbeg,ibcend,n, i,j,l,m
+ real c(4,n),tau(n), divdf1,divdf3,dtau,g
+c****** a tridiagonal linear system for the unknown slopes s(i) of
+c f at tau(i), i=1,...,n, is generated and then solved by gauss elim-
+c ination, with s(i) ending up in c(2,i), all i.
+c c(3,.) and c(4,.) are used initially for temporary storage.
+ l = n-1
+compute first differences of tau sequence and store in c(3,.). also,
+compute first divided difference of data and store in c(4,.).
+ do 10 m=2,n
+ c(3,m) = tau(m) - tau(m-1)
+ 10 c(4,m) = (c(1,m) - c(1,m-1))/c(3,m)
+construct first equation from the boundary condition, of the form
+c c(4,1)*s(1) + c(3,1)*s(2) = c(2,1)
+ if (ibcbeg-1) 11,15,16
+ 11 if (n .gt. 2) go to 12
+c no condition at left end and n = 2.
+ c(4,1) = 1.
+ c(3,1) = 1.
+ c(2,1) = 2.*c(4,2)
+ go to 25
+c not-a-knot condition at left end and n .gt. 2.
+ 12 c(4,1) = c(3,3)
+ c(3,1) = c(3,2) + c(3,3)
+ c(2,1) =((c(3,2)+2.*c(3,1))*c(4,2)*c(3,3)+c(3,2)**2*c(4,3))/c(3,1)
+ go to 19
+c slope prescribed at left end.
+ 15 c(4,1) = 1.
+ c(3,1) = 0.
+ go to 18
+c second derivative prescribed at left end.
+ 16 c(4,1) = 2.
+ c(3,1) = 1.
+ c(2,1) = 3.*c(4,2) - c(3,2)/2.*c(2,1)
+ 18 if(n .eq. 2) go to 25
+c if there are interior knots, generate the corresp. equations and car-
+c ry out the forward pass of gauss elimination, after which the m-th
+c equation reads c(4,m)*s(m) + c(3,m)*s(m+1) = c(2,m).
+ 19 do 20 m=2,l
+ g = -c(3,m+1)/c(4,m-1)
+ c(2,m) = g*c(2,m-1) + 3.*(c(3,m)*c(4,m+1)+c(3,m+1)*c(4,m))
+ 20 c(4,m) = g*c(3,m-1) + 2.*(c(3,m) + c(3,m+1))
+construct last equation from the second boundary condition, of the form
+c (-g*c(4,n-1))*s(n-1) + c(4,n)*s(n) = c(2,n)
+c if slope is prescribed at right end, one can go directly to back-
+c substitution, since c array happens to be set up just right for it
+c at this point.
+ if (ibcend-1) 21,30,24
+ 21 if (n .eq. 3 .and. ibcbeg .eq. 0) go to 22
+c not-a-knot and n .ge. 3, and either n.gt.3 or also not-a-knot at
+c left end point.
+ g = c(3,n-1) + c(3,n)
+ c(2,n) = ((c(3,n)+2.*g)*c(4,n)*c(3,n-1)
+ * + c(3,n)**2*(c(1,n-1)-c(1,n-2))/c(3,n-1))/g
+ g = -g/c(4,n-1)
+ c(4,n) = c(3,n-1)
+ go to 29
+c either (n=3 and not-a-knot also at left) or (n=2 and not not-a-
+c knot at left end point).
+ 22 c(2,n) = 2.*c(4,n)
+ c(4,n) = 1.
+ go to 28
+c second derivative prescribed at right endpoint.
+ 24 c(2,n) = 3.*c(4,n) + c(3,n)/2.*c(2,n)
+ c(4,n) = 2.
+ go to 28
+ 25 if (ibcend-1) 26,30,24
+ 26 if (ibcbeg .gt. 0) go to 22
+c not-a-knot at right endpoint and at left endpoint and n = 2.
+ c(2,n) = c(4,n)
+ go to 30
+ 28 g = -1./c(4,n-1)
+complete forward pass of gauss elimination.
+ 29 c(4,n) = g*c(3,n-1) + c(4,n)
+ c(2,n) = (g*c(2,n-1) + c(2,n))/c(4,n)
+carry out back substitution
+ 30 j = l
+ 40 c(2,j) = (c(2,j) - c(3,j)*c(2,j+1))/c(4,j)
+ j = j - 1
+ if (j .gt. 0) go to 40
+c****** generate cubic coefficients in each interval, i.e., the deriv.s
+c at its left endpoint, from value and slope at its endpoints.
+ do 50 i=2,n
+ dtau = c(3,i)
+ divdf1 = (c(1,i) - c(1,i-1))/dtau
+ divdf3 = c(2,i-1) + c(2,i) - 2.*divdf1
+ c(3,i-1) = 2.*(divdf1 - c(2,i-1) - divdf3)/dtau
+ 50 c(4,i-1) = (divdf3/dtau)*(6./dtau)
+ return
+ end
diff --git a/math/interp/iieval.x b/math/interp/iieval.x
new file mode 100644
index 00000000..87538525
--- /dev/null
+++ b/math/interp/iieval.x
@@ -0,0 +1,137 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+.help
+ procedures to evaluate interpolants
+
+ These procedures are seperated from the other programs in order
+to make it easier to optimise these in case it becomes necessary to
+obtain the fastest possible interpolants. The interpolation package
+spends most of its time in these routines.
+.endhelp
+
+procedure iievne(x,y,n,a) # nearest neighbor
+
+real x[ARB] # x values, must be within [1,n]
+real y[ARB] # interpolated values returned to user
+int n # number of x values
+real a[ARB] # data to be interpolated
+
+int i
+
+begin
+ do i = 1, n
+ y[i] = a[int(x[i] + 0.5)]
+ return
+end
+
+procedure iievli(x,y,n,a) # linear
+
+real x[ARB] # x values, must be within [1,n]
+real y[ARB] # interpolated values returned to user
+int n # number of x values
+real a[ARB] # data to be interpolated
+
+int i,nx
+
+begin
+
+ do i = 1,n {
+ nx = x[i]
+ y[i] = (x[i] - nx) * a[nx + 1] + (nx + 1 - x[i]) * a[nx]
+ }
+ return
+end
+
+procedure iievp3(x,y,n,a) # interior third order polynomial
+
+real x[ARB] # x values, must be within [1,n]
+real y[ARB] # interpolated values returned to user
+int n # number of x values
+real a[ARB] # data to be interpolated from a[0] to a[n+2]
+
+int i,nx,nxold
+real s,t,cd20,cd21
+
+begin
+ nxold = -1
+ do i = 1,n {
+ nx = x[i]
+ s = x[i] - nx
+ t = 1. - s
+ if (nx != nxold) {
+
+ # second central differences:
+ cd20 = 1./6. * (a[nx+1] - 2. * a[nx] + a[nx-1])
+ cd21 = 1./6. * (a[nx+2] - 2. * a[nx+1] + a[nx])
+ nxold = nx
+ }
+ y[i] = s * (a[nx+1] + (s * s - 1.) * cd21) +
+ t * (a[nx] + (t * t - 1.) * cd20)
+
+ }
+ return
+end
+
+procedure iievp5(x,y,n,a) # interior fifth order polynomial
+
+real x[ARB] # x values, must be within [1,n]
+real y[ARB] # interpolated values returned to user
+int n # number of x values
+real a[ARB] # data to be interpolated - from a[-1] to a[n+3]
+
+int i,nx,nxold
+real s,t,cd20,cd21,cd40,cd41
+
+begin
+ nxold = -1
+ do i = 1,n {
+ nx = x[i]
+ s = x[i] - nx
+ t = 1. - s
+ if (nx != nxold) {
+ cd20 = 1./6. * (a[nx+1] - 2. * a[nx] + a[nx-1])
+ cd21 = 1./6. * (a[nx+2] - 2. * a[nx+1] + a[nx])
+
+ # fourth central differences
+ cd40 = 1./120. * (a[nx-2] - 4. * a[nx-1] +
+ 6. * a[nx] - 4. * a[nx+1] + a[nx+2])
+ cd41 = 1./120. * (a[nx-1] - 4. * a[nx] +
+ 6. * a[nx+1] - 4. * a[nx+2] + a[nx+3])
+ nxold = nx
+ }
+ y[i] = s * (a[nx+1] + (s * s - 1.) *
+ (cd21 + (s * s - 4.) * cd41)) +
+ t * (a[nx] + (t * t - 1.) *
+ (cd20 + (t * t - 4.) * cd40))
+ }
+ return
+end
+
+procedure iievs3(x,y,n,a) # cubic spline evaluator
+
+real x[ARB] # x values, must be within [1,n]
+real y[ARB] # interpolated values returned to user
+int n # number of x values
+real a[ARB] # basis spline coefficients - from a[0] to a[n+1]
+
+int i,nx,nxold
+real s,c0,c1,c2,c3
+
+begin
+ nxold = -1
+ do i = 1,n {
+ nx = x[i]
+ s = x[i] - nx
+ if (nx != nxold) {
+
+ # convert b-spline coeff's to poly. coeff's
+ c0 = a[nx-1] + 4. * a[nx] + a[nx+1]
+ c1 = 3. * (a[nx+1] - a[nx-1])
+ c2 = 3. * (a[nx-1] - 2. * a[nx] + a[nx+1])
+ c3 = -a[nx-1] + 3. * a[nx] - 3. * a[nx+1] + a[nx+2]
+ nxold = nx
+ }
+ y[i] = c0 + s * (c1 + s * (c2 + s * c3) )
+ }
+ return
+end
diff --git a/math/interp/iif_spline.x b/math/interp/iif_spline.x
new file mode 100644
index 00000000..a8574e0b
--- /dev/null
+++ b/math/interp/iif_spline.x
@@ -0,0 +1,67 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+.help
+ procedure iif_spline
+
+ This fits uniformly spaced data with a cubic spline. The spline is
+given as basis-spline coefficients that replace the data values.
+
+Storage at call time:
+
+b[1] = second derivative at x = 1
+b[2] = first data point y[1]
+b[3] = y[2]
+.
+.
+.
+b[n+1] = y[n]
+b[n+2] = second derivative at x = n
+
+Storage after call:
+
+b[1] ... b[n+2] = the n + 2 basis-spline coefficients for the basis splines
+ as defined in P. M. Prenter's book Splines and Variational Methods,
+ Wiley, 1975.
+
+.endhelp
+
+procedure iif_spline(b,d,n)
+
+real b[ARB] # data in and also bspline coefficients out
+real d[ARB] # needed for offdiagnol matrix elements
+int n # number of data points
+
+int i
+
+begin
+
+ d[1] = -2.
+ b[1] = b[1] / 6.
+
+ d[2] = 0.
+ b[2] = (b[2] - b[1]) / 6.
+
+ # Gaussian elimination - diagnol below main is made zero
+ # and main diagnol is made all 1's
+ do i = 3,n+1 {
+ d[i] = 1. / (4. - d[i-1])
+ b[i] = d[i] * (b[i] - b[i-1])
+ }
+
+ # Find last b spline coefficient first - overlay r.h.s.'s
+ b[n+2] = ( (d[n] + 2.) * b[n+1] - b[n] + b[n+2]/6.) / (1. +
+ d[n+1] * (d[n] + 2.))
+
+ # back substitute filling in coefficients for b splines
+ do i = n+1, 3, -1
+ b[i] = b[i] - d[i] * b[i+1]
+
+ # note b[n+1] is evaluated correctly as can be checked
+
+ # b[2] is already set since offdiagnol is 0.
+
+ # evaluate b[1]
+ b[1] = b[1] + 2. * b[2] - b[3]
+
+ return
+end
diff --git a/math/interp/iimail b/math/interp/iimail
new file mode 100644
index 00000000..69c19e9f
--- /dev/null
+++ b/math/interp/iimail
@@ -0,0 +1,213 @@
+From tody Wed Apr 20 18:50:45 1983
+Date: 20 Apr 1983 18:50-MST
+To: vesa
+Subject: ii comments
+Cc: tody
+
+I read through "tnotes1", and felt that enough information was conveyed
+to explain how the asi___ routines work, and how to use them. It is
+good documentation for the package, though some sections are probably
+to technical for the general user, and should probably be moved to an
+appendix in the final documentation.
+
+I only have one minor suggestion, and that is that there seems little
+reason to abbreviate NEAR, REFL, and PROJ, since only three characters
+are saved in each case, and the other parameter names are all spelled out.
+
+I also looked at the code for ASIFIT. I noticed that the recursion
+relations for the cubic spline are coded inline. I suspect that this
+is actually LESS efficient than using a separate procedure, due to
+the complex coeff offset expressions appearing in the inner loops
+(unless the Fortran compiler does a very good job of optimizing loops).
+
+By using a separate procedure, for example, the statement
+
+ coeff[COFF+i] = coeff[off2+i] * (coeff[COFF+i] - coeff[COFF+i-1])
+
+can be converted to something like
+
+ bcoeff[i] = acoeff[i] * (bcoeff[i] - bcoeff[i-1])
+
+where in the main routine, there is a procedure call something like the
+following:
+
+ call fit_bspline3 (coeff[COFF], coeff[off2], ...)
+
+In other words, the routines that actually do the work do not need to
+know that everything is saved in a single coeff array. This simplifies
+the code, as well as making it run faster on some machines. The technique
+has an additional advantage: by isolating the compute bound code into
+a separate (small) procedure, it becomes easy to hand optimize that procedure
+in assembler, should we wish to do so.
+
+From tody Wed Apr 20 19:48:51 1983
+Date: 20 Apr 1983 19:48-MST
+To: vesa
+Subject: first benchmarks
+Cc: tody
+
+I ran some preliminary benchmarks on the asi code, assuming no bad pixels.
+The benchmark routine is in math/interp. Results:
+
+512 by 512 image interpolation, no bad pixels, using ASIEVA:
+
+ nearest 47 (cpu seconds)
+ linear 22
+ poly3 50
+ poly5 89
+ spline3 94
+
+This is quite encouraging. I expect that these timings can be decreased by
+a factor of from 3 to 5, given a good Fortran compiler (the current UNIX
+compiler is very poor), and possibly hand optimising critical sections of
+the code in assembler.
+
+The nearest neighbor timings don't make any sense (that should be the
+fastest interpolant). Are you using sqrt, or something like that?
+The spline timings are worse than I expected, compared to poly3. May
+be due to complex offset expressions, which F77 does not optimize.
+
+From tody Fri Feb 18 14:10:36 1983
+To: vesa
+Subject: x code
+Cc: tody
+
+
+We want to make IRAF source code as readable as possible, therefore there
+is a (currently unofficial) standard for ".x" code. Your code is pretty
+close to the standard, but here are some things to consider:
+
+ (1) It is preferable to enclose large blocks of documentation in
+ .help .. .endhelp sections, rather than making each line a comment.
+ This has two advantages: (1) it is awkward to edit text set off with
+ a # on each line, and (2) the help utilities can only extract
+ source code documentation which is set in help blocks. It is not
+ necessary to use text formatter commands in help blocks, i.e.,
+ you can simply type it in as it will appear on the terminal.
+
+ In the same vein, it is better to put the discussion of the input
+ and output parameters in the help text, rather than in the
+ declarations section of the procedure. Placing each input and
+ output parameter on a single line, followed at the right by a short
+ comment, gets the job done without cluttering up the declarations
+ section. More extensive comments should be placed in the help text.
+
+
+ (2) It is mostly up to the programmer to decide where to put whitespace
+ to make the structure of a program clearest. Whitespace should
+ be inserted in a statement to make the important logical components
+ of the statement stand out.
+
+ In particular, there should be a space after every keyword, before
+ the left parenthesis. If the statement is compound, the left brace
+ should be set off from the right paren by a space. In short
+ expressions, operators should be set off by whitespace.
+
+ Adding whitespace between a function name and the left paren is
+ optional, as is whitespace between the elements of an argument list
+ (after commas).
+
+ Blank lines should be used to set off sections of code, just as
+ blank lines are used to separate paragraphs of text.
+
+ It is possible to overcomment code, making it hard to read. If
+ more than a third of the lines in a procedure are comments, the
+ code is probably overcommented. Place detailed discussion of the
+ algorithm in the help text.
+
+
+ (3) Indenting structures by full tab stops is acceptable, but 4 space
+ indents are preferred (the code rapidly runs off the right side of
+ the screen if full tab indents are used, encouraging use of too
+ short identifiers and omission of whitespace). The autoindent
+ feature of VI makes this easy (in .login file: 'set ai sw=4').
+
+
+ (4) The standard form of the if .. else construct is
+
+ if (expr) {
+ stmt
+ } else {
+ stmt
+
+ or (if "stmt" is several lines, and whitespace is desired)
+
+ if (expr) {
+ stmt
+
+ } else {
+ stmt
+
+ rather than
+
+ if (expr) {
+ stmt
+ }
+ else {
+ stmt
+
+From tody Fri Feb 18 15:21:33 1983
+Date: 18 Feb 1983 15:21-MST
+To: vesa
+Subject: spec changes
+Cc: tody
+
+
+Now that Garth, Harvey, Steve and others have had a chance to comment on the
+specs for the interpolator routines, it is time to make the final revisions
+to the specifications. Often ones perspective on a problem changes when one
+actually begins coding, and even the most carefully prepared specifications
+need to be changed. Please feel free to suggest further changes.
+
+
+Modifications
+
+ (1) Everyone wanted the interpolators to be able to generate estimated
+ values to replace indefinites (as an option).
+
+ (2) Steve wanted sinc function interpolation added to the set of
+ interpolators. I would also like to try this for undersampled
+ CCD data. A fairly high "order" (basis function size) seems
+ justified for this interpolant.
+
+ (3) A surface integration routine is desired (MSIGRL).
+
+
+SET Routines
+
+ I think we should generalize the form of the "set" routines to permit
+options such as (1), and others we may wish to add in the future (such
+as telling the interpolator not to check for indefinites in the data).
+
+Set routines are also used in the FIO, IMIO, VSIO, and GIO packages in
+the program interface. For example, in FIO, the number of buffers for a
+file could be set by a call of the form
+
+ call fset (fd, NBUFFERS, 2)
+
+The form of a set call is therefore
+
+ call ___set (object, parameter, value)
+
+i.e.,
+
+ call asiset (coeff, II_INTERPOLANT, II_DIVDIF3)
+ call asiset (coeff, II_TYBNDRY, II_NEAREST)
+ call asiset (coeff, II_REPLACE_INDEFS, YES)
+
+Note that the prefix "II_" must be added to all Image Interpolation
+defined parameters and parameter values. This is unattractive, but necessary
+to avoid redefinitions of identifiers in other packages, such as IMIO (IMIO
+has the same boundary extension options as II).
+
+
+Surface Integration
+
+ I suggest the following calling sequence for the surface integration
+routine:
+
+ integral = msigrl (x, y, npts, coeff)
+
+where the surface to be integrated is defined by the closed curve {x[i],y[i]},
+where 1 <= i <= npts, defined by the caller.
+
diff --git a/math/interp/iipol_terp.x b/math/interp/iipol_terp.x
new file mode 100644
index 00000000..030d1964
--- /dev/null
+++ b/math/interp/iipol_terp.x
@@ -0,0 +1,41 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+.help
+ Procedure iipol_terp
+
+A polynomial interpolator with x and y arrays given.
+This algorithm is based on the Newton form as described in
+de Boor's book, A Practical Guide to Splines, 1978.
+There is no error checking - this is meant to be used only by calls
+from more complete routines that take care of such things.
+
+Maximum number of terms is 6.
+.endhelp
+
+real procedure iipol_terp(x,y,n,x0)
+
+real x[ARB],y[ARB] # x and y array
+real x0 # desired x
+int n # number of points in x and y = number of
+ # terms in polynomial = order + 1
+
+int k,i
+real d[6]
+
+begin
+
+ # Fill in entries for divided difference table.
+ do i = 1,n
+ d[i] = y[i]
+
+ # Generate divided differences
+ do k = 1,n-1
+ do i = 1,n-k
+ d[i] = (d[i+1] - d[i])/(x[i+k] - x[i])
+
+ # Shift divided difference table to center on x0
+ do i = 2,n
+ d[i] = d[i] + d[i-1] * (x0 - x[i])
+
+ return(d[n])
+end
diff --git a/math/interp/interp.h b/math/interp/interp.h
new file mode 100644
index 00000000..e54fc1b5
--- /dev/null
+++ b/math/interp/interp.h
@@ -0,0 +1,19 @@
+# File of definitions for interpolator package.
+
+# Interpolator Types:
+
+define IT_NEAREST 1
+define IT_LINEAR 2
+define IT_POLY3 3
+define IT_POLY5 4
+define IT_SPLINE3 5
+define ITNIT 5 # number of types
+
+# Size of header etc. used for part of coeff dimension
+
+define SZ_ASI 20
+
+# Total number of points used in spline interpolation of of bad pixels by
+# subroutine arbpix.
+
+define SPLPTS 16
diff --git a/math/interp/interpdef.h b/math/interp/interpdef.h
new file mode 100644
index 00000000..e54fc1b5
--- /dev/null
+++ b/math/interp/interpdef.h
@@ -0,0 +1,19 @@
+# File of definitions for interpolator package.
+
+# Interpolator Types:
+
+define IT_NEAREST 1
+define IT_LINEAR 2
+define IT_POLY3 3
+define IT_POLY5 4
+define IT_SPLINE3 5
+define ITNIT 5 # number of types
+
+# Size of header etc. used for part of coeff dimension
+
+define SZ_ASI 20
+
+# Total number of points used in spline interpolation of of bad pixels by
+# subroutine arbpix.
+
+define SPLPTS 16
diff --git a/math/interp/mkpkg b/math/interp/mkpkg
new file mode 100644
index 00000000..55ab29c6
--- /dev/null
+++ b/math/interp/mkpkg
@@ -0,0 +1,21 @@
+# Old image interpolator tools library.
+
+$checkout libinterp.a lib$
+$update libinterp.a
+$checkin libinterp.a lib$
+$exit
+
+libinterp.a:
+ arbpix.x interpdef.h asidef.h
+ arider.x interpdef.h
+ arival.x interpdef.h
+ asider.x interpdef.h asidef.h
+ asieva.x interpdef.h asidef.h
+ asifit.x interpdef.h asidef.h
+ asigrl.x interpdef.h asidef.h
+ asiset.x interpdef.h asidef.h
+ asival.x interpdef.h asidef.h
+ iieval.x
+ iif_spline.x
+ iipol_terp.x
+ ;
diff --git a/math/interp/noteari b/math/interp/noteari
new file mode 100644
index 00000000..d42ed48b
--- /dev/null
+++ b/math/interp/noteari
@@ -0,0 +1,64 @@
+ Using the Random One Dimensional Interpolation Routines
+ A Quick Note for Programmers
+
+
+I. GENERAL NOTES:
+
+ 1. Defines are found in file interpdef.h. The routines
+ are in library interplib.a.
+
+ 2. All pixels are assumed to be good. Except for routine
+ arbpix.
+
+ 3. This is for uniformly spaced data -- thus for the i-th
+ data value, y[i], the corresponding x[i] = i by assumption.
+
+ 4. All x references are assumed to land in the closed interval
+ 1 <= x <= NPTS, where NPTS is the number of points in the
+ data array. If x is outside this range, the result is
+ not specified.
+
+
+II. PROCEDURES:
+
+
+ **** Subroutine to replace INDEF's with interpolated values.
+ *
+ * arbpix (datain, n, dataout, interpolator_type)
+ *
+ * real datain[ARB] # data_in array
+ * int n # number of points in data_in
+ * real dataout[ARB] # array out, may not be same as
+ * # data_in
+ * int interpolator_type
+ *
+ * The interpolator type can be set to:
+ *
+ * IT_NEAREST nearest neighbor
+ * IT_LINEAR linear interpolation
+ * IT_POLY3 interior polynomial 3rd order
+ * IT_POLY5 interior polynomial 5th order
+ **** IT_SPLINE3 cubic natural spline
+
+
+ **** Subroutine to return interpolated value
+ *
+ * real arival (x, datain, n , interpolator_type)
+ *
+ * real x
+ * real datain[ARB] # data array
+ * int n # number of points in data array
+ **** int interpolator_type # see above
+
+
+ **** Subroutine to evaluate derivatives at a point.
+ *
+ * arider (x, datain, n, derivs, nder, interpolator_type)
+ *
+ * real x
+ * real datain[ARB] # data array
+ * int n # number of points in data array
+ * real derivs[ARB] # output array containing derivatives
+ * # derivs[1] is function value
+ * int nder # input: nder - 1 derivs are evaluated
+ **** int interpolator_type # see above
diff --git a/math/interp/noteasi b/math/interp/noteasi
new file mode 100644
index 00000000..ae22df83
--- /dev/null
+++ b/math/interp/noteasi
@@ -0,0 +1,101 @@
+ Using the Sequential One Dimensional Interpolation Routines
+ A Quick Note for Programmers
+
+
+I. GENERAL NOTES:
+
+ 1. Defines are found in file interpdef.h. The routines
+ are in library interplib.a.
+
+ 2. All pixels are assumed to be good. Except for routine
+ arbpix.
+
+ 3. This is for uniformly spaced data -- thus for the i-th
+ data value, y[i], the corresponding x[i] = i by assumption.
+
+ 4. All x references are assumed to land in the closed interval
+ 1 <= x <= NPTS, where NPTS is the number of points in the
+ data array. If x is outside this range, the result is
+ not specified.
+
+ 5. A storage area and work space array must be provided.
+ It is of type real and the size is 2 * NPTS + SZ_ASI
+
+
+
+II. PROCEDURES:
+
+
+ **** Subroutine to replace INDEF's with interpolated values.
+ *
+ * arbpix (datain, n, dataout, interpolator_type)
+ *
+ * real datain[ARB] # data_in array
+ * int n # number of points in data_in
+ * real dataout[ARB] # array out, may not be same as
+ * # data_in
+ * int interpolator_type
+ *
+ * The interpolator type can be set to:
+ *
+ * IT_NEAREST nearest neighbor
+ * IT_LINEAR linear interpolation
+ * IT_POLY3 interior polynomial 3rd order
+ * IT_POLY5 interior polynomial 5th order
+ **** IT_SPLINE3 cubic natural spline
+
+
+ **** Subroutine to set interpolator type.
+ *
+ * asiset(coeff,interpolator_type)
+ *
+ * real coeff[ARB] # work + storage array, dimension
+ * # 2 * NPTS + SZ_ASI
+ **** int interpolator_type # see above
+
+
+ **** Subroutine to fit interpolator to data.
+ *
+ * asifit (datain, npts, coeff)
+ *
+ * real datain[ARB] # data array
+ * int npts # number of points in data array
+ **** real coeff[ARB] # work+storage area dim 2*npts + SZ_ASI
+
+
+ **** Subroutine to return interpolated value after fitting.
+ *
+ * real asival (x, coeff)
+ *
+ * real x
+ **** real coeff[ARB]
+
+
+ **** Subroutine to evaluate an ordered sequence of values.
+ *
+ * asieva (x, y, n, coeff)
+ *
+ * real x[ARB] # input array of x values
+ * real y[ARB] # output array of interpolated values
+ * int n # number of x values
+ **** real coeff[ARB]
+
+
+ **** Subroutine to evaluate derivatives at a point.
+ *
+ * asider (x, derivs, nder, coeff)
+ *
+ * real x
+ * real derivs[ARB] # output array containing derivatives
+ * # derivs[1] is function value
+ * int nder # input: nder - 1 derivatives are evaluated
+ **** real coeff[ARB]
+
+
+ **** Subroutine to integrate the interpolated data.
+ *
+ * real asigrl (a, b, coeff)
+ *
+ * real a # lower limit
+ * real b # upper limit
+ **** real coeff[ARB]
diff --git a/math/interp/notes3 b/math/interp/notes3
new file mode 100644
index 00000000..e7121c99
--- /dev/null
+++ b/math/interp/notes3
@@ -0,0 +1,216 @@
+ Notes on the Interpolator Package for IRAF Version 2
+
+ Some parts of the image interpolator package are available.
+This is a reminder of changes to the document TRP prepared by
+Doug Tody. Also it is a place to keep track of why things were
+done the way they were. The individual procedures (subroutines)
+will be discussed; making it easy to add, subtract and change things.
+
+**************************************************************************
+** **
+** **
+
+ GENERAL NOTES FOR 1-D PACKAGE:
+
+1. Handling of errors.
+
+ Some routines call the error routines of the IRAF package.
+ Logically it is reasonable to trap silly errors at certain points.
+ For instance if the interpolator type is set to a nonexistant type
+ an error call is generated.
+
+ To the programmer, the two most important error features are:
+
+ 1. All pixels are assumed to be good.
+
+ 2. All x references are assumed to land in the closed interval
+ 1 <= x <= NPTS.
+
+ Point 2 probably needs some explanation, because at first hand
+ it seems rather easy to test for x < 1 || x > NPTS and take
+ appropriate action. There are two objections to including this
+ test. First it is often possible to generate x values in such
+ a way that they are guaranteed to lie in the given interval.
+ Testing again within the interpolator package is a waste of
+ computer time. Second the interpolator package becomes too large
+ if code is included to handle out of bounds references and such
+ code duplicates other parts of the IRAF package that handles
+ out of bound values. The alternative is to return INDEF when
+ x is out of bounds. This is not very appealing for many
+ routine applications such as picture shifting.
+
+2. Size of "coeff" array:
+
+ coeff is a real 1-d array of size -- 2 * NPTS + SZ_ASI
+
+ where SZ_ASI is currently 30. It, like the other defines needed for
+ the interp package, is available in the file -- terpdef.h .
+
+ This coeff array serves as work area for asifit, a structure to save
+ interpolator type, flags etc., an array to save data points or b-spline
+ coefficients as needed.
+
+ The polynomial interpolators are saved as the data points and the
+interpolation is done "on the fly". Rather than compute polynomial
+coefficients before-hand, the interpolated value is calculated from
+the data values at time of request. (The actual calculation is done
+by adding and multiplying things in an order suggested by Everett's
+interpolation formula rather than the polynomial coefficient form.
+The resulting values are the same up to differences due to numerical
+roundoff. As a practical matter, all forms work except polynomials
+shifted far from the point of interest. Polynomials shifted to a
+center far away suffer from bad roundoff errors.)
+
+ The splines must be calculated at a single pass because (formally)
+they are global (i.e use all of the data points). The b-splines (b for
+basis) are just certain piecewise polynomials for solving the interpo-
+lation problem, it is convenient to calculate the coefficients of these
+b-splines and to save these in the array.
+
+3. Method of solution:
+
+**************************************************************************
+** **
+** **
+** **
+ PROCEDURES:
+
+***************************************************************************
+
+ ***** asiset(coeff,interptype) *****
+
+The interpolator type can be set to:
+
+ IT_NEAREST nearest neighbor
+ IT_LINEAR linear interpolation
+ IT_POLY3 interior polynomial 3rd order
+ IT_POLY5 interior polynomial 5th order
+ IT_SPLINE3 cubic natural spline
+
+Subroutines needed:
+
+ NONE
+
+
+
+*************************************************************************
+
+ ******* asifit (data, npts, coeff) *****
+
+ This fits the interpolator to the data. Takes care of bad points by
+replacing them with interpolated values to generate a
+uniformly spaced array. For polynomial interpolators, this array is
+sent to the evaluation routines. For the spline interpolator, the uniform
+array is fitted and the basis-spline coefficients are saved.
+
+Interior polynomial near boundary:
+ Array is extended according to choice of boundary conditions.
+Out of bounds values and values near the edge depend on choice of
+boundary conditions.
+
+Spline near boundary:
+ Natural (second derivative equals zero at edge) spline is fitted to
+data only. The resulting function is reflected, wrapped etc. to generate
+out of bounds values. Out of bounds values depend on choice of boundary
+conditions but values within the array near the edges do not.
+ For the wrap boundary condition, the one segment connecting point
+number n to point 1 is not generated by the spline fit. Instead the
+polynomial that is continuous and has a continuous first and second
+derivative n is inserted. In this one case, the first and second derivative
+are not continuous at 1.
+
+Replacing bad points:
+ The same kind of interpolator is used to replace bad points as that
+used to generate interpolated values. The boundary conditions are not
+handled in the same manner. Bad points near the edge are replaced by
+using lower order polynomial interpolators if there are not enough
+points on both sides of the bad point. Bad points that are not
+straddled by good points are assigned the value of the nearest good
+point. This is done in the temporary array before the uniformly spaced
+interpolator is applied.
+
+subroutines needed:
+
+ real iipint(x,y,nterm,x0)
+ Returns interpolated value at x0 using polynomial with
+ <nterm> terms to connect the <nterm> data pairs
+ in x,y.
+
+ cubspl(tau,c,n,ibcbeg,ibcend)
+ Unmodified cubic spline interpolator for non-uniformly
+ spaced data taken from C. de Boor's book:
+ A Practical Guide to Splines, (1978
+ Springer-Verlag).
+
+ iifits(b,d,n)
+ Fits cubic spline to uniformly spaced array of y values
+ using a basis-spline representation for
+ the spline.
+
+
+
+*****************************************************************************
+
+ ***** y = asival (x, coeff) *****
+
+ Subroutine to return interpolated value after fitting.
+
+Subroutines needed:
+
+ real iivalu (x, coeff)
+ Returns interpolated value assuming x is in array. Also
+ has no code for bad point propagation.
+
+
+
+
+***************************************************************************
+
+ ***** asieva (x, y, n, coeff) *****
+
+ Given an ordered array of x values returns interpolated values in y.
+This is needed for speed. Reduces number of subroutine calls per point,
+reduces the number of tests for out of bounds, and bad pixel
+propagation can be made more efficient.
+
+Subroutines needed:
+
+ real iivalu (x, coeff)
+
+
+
+**************************************************************************
+
+ ***** asider (x, derivs, nderiv, coeff) *****
+
+ This evaluates derivatives at point x. Returns the first
+nderiv - 1 derivatives. derivs[1] is function value, derivs[2] is
+first derivative, derivs[3] is second derivative etc.
+ There is no check that nderiv is a reasonable value. Polynomials
+have a limited number of non-zero derivatives, if more are asked for
+they come back as zero.
+
+Subroutines needed:
+
+ iivalu (x, coeff)
+
+ iiderv (x, derivs, nderiv, coeff)
+ Assumes x lands in array returns derivatives. No handling
+ of bad points.
+
+****************************************************************************
+
+ ****** integral = asigrl (a, b, coeff) *******
+
+ This integrates the array from to a to b. The boundary conditions are
+incorporated into the code so if function values can be returned from all
+points between a and b, the integral will be defined. Thus for WRAP,
+REFLECT and PROJECT boundary conditions, the distance from a to b can be
+as large as 3 times the array length if a and b are chosen appropriately.
+For these boundary conditions, attempts to extend beyond +/- one cycle
+produce INDEF.
+
+Subroutines needed:
+
+ iiigrl (a, b, coeff)
+ returns integral when a and b land in array.
diff --git a/math/interp/overview b/math/interp/overview
new file mode 100644
index 00000000..4ad813ca
--- /dev/null
+++ b/math/interp/overview
@@ -0,0 +1,43 @@
+Interpolation Package
+
+ The routines here are intended to allow programmers to interpolate
+one dimensional arrays and two dimensional
+images in the IRAF system. The routines are
+mathematical in nature and are not heavily tied into the IRAF package.
+The advantages of having locally written interpolators include the
+ability to optimize for uniformly spaced data and the possibility of
+adding features that are useful for the final application. The
+one major feature that has been implemented is the ability to change
+the kind of interpolator used at run time by carrying along a variable
+that gives the interpolator type in the higher level code.
+
+ The kinds of interpolators include:
+ 1. Nearest neighbor
+ 2. Linear
+ 3. Interior polynomial order = 3
+ 4 Interior polynomial order = 5
+ 5 Spline order = 3
+
+ The package is divided into array interpolators and image
+interpolators. Within the array interpolators, there is further
+division into sequential and random interpolators. The sequential
+interpolators are optimized for returning many values as is the
+case when an array is shifted or when an array is oversampled
+at many points in order to produce a smooth plot. The random interpolators
+allow the evaluation of a few interpolated points without the computing
+time and storage overhead required for setting up the sequential version.
+
+ The original specification called for the interpolator package
+to deal with indefinite valued pixels and references out of bounds.
+A version of the array sequential interpolators was written that handled
+both situations allowing some options to the user. The extension of
+these features to the two dimensional case becomes more dependent on
+details within IRAF and less mathematical in nature. It would also
+duplicate other code within IRAF that deals with out of bound references.
+Finally the need to test for the various situations slows down the operation.
+So all features referring to indefinite valued pixels and out of bound
+references have been removed. The user is responsible for ensuring that
+"x" values land within the array. The code does not test to see if x
+is in bounds. A routine has been added that interpolates
+an array with indefinites and returns an array with all legitimate
+real numbers.
diff --git a/math/interp/usernote b/math/interp/usernote
new file mode 100644
index 00000000..55483022
--- /dev/null
+++ b/math/interp/usernote
@@ -0,0 +1,118 @@
+ Using the Sequential One Dimensional Interpolation Routines
+ A Quick Note for Programmers
+
+
+I. GENERAL NOTES:
+
+ 1. Defines are found in file interpdef.h. The routines
+ are in library interplib.a.
+
+ 2. All pixels are assumed to be good. Except for routine
+ arbpix.
+
+ 3. This is for uniformly spaced data -- thus for the i-th
+ data value, y[i], the corresponding x[i] = i by assumption.
+
+ 4. All x references are assumed to land in the closed interval
+ 1 <= x <= NPTS, where NPTS is the number of points in the
+ data array. If x is outside this range, the result is
+ not specified.
+
+ 5. A storage area and work space array must be provided.
+ It is of type real and the size is 2 * NPTS + SZ_ASI
+
+
+
+II. PROCEDURES:
+
+
+ **** Subroutine to select the interpolator type
+ *
+ * interpolator_type = clginterp (param)
+ *
+ * char param[ARB]
+ *
+ * The parameter prompt string is sent to the CL and the
+ * routine evaluates the returned string to select one of the
+ * interpolator types given in interpdef.h. The input string
+ * may be one of the following with possible abbreviations:
+ * nearest
+ * linear
+ * 3rd order poly
+ * 5th order poly
+ **** cubic spline
+
+
+ **** Subroutine to replace INDEF's with interpolated values.
+ *
+ * arbpix (datain, n, dataout, interpolator_type)
+ *
+ * real datain[ARB] # data_in array
+ * int n # number of points in data_in
+ * real dataout[ARB] # array out, may not be same as
+ * # data_in
+ * int interpolator_type
+ *
+ * The interpolator type can be set to:
+ *
+ * IT_NEAREST nearest neighbor
+ * IT_LINEAR linear interpolation
+ * IT_POLY3 interior polynomial 3rd order
+ * IT_POLY5 interior polynomial 5th order
+ **** IT_SPLINE3 cubic natural spline
+
+
+ **** Subroutine to set interpolator type.
+ *
+ * asiset(coeff,interpolator_type)
+ *
+ * real coeff[ARB] # work + storage array, dimension
+ * # 2 * NPTS + SZ_ASI
+ **** int interpolator_type # see above
+
+
+ **** Subroutine to fit interpolator to data.
+ *
+ * asifit (datain, npts, coeff)
+ *
+ * real datain[ARB] # data array
+ * int npts # number of points in data array
+ **** real coeff[ARB] # work+storage area dim 2*npts + SZ_ASI
+
+
+ **** Subroutine to return interpolated value after fitting.
+ *
+ * real asival (x, coeff)
+ *
+ * real x
+ **** real coeff[ARB]
+
+
+ **** Subroutine to evaluate an ordered sequence of values.
+ *
+ * asieva (x, y, n, coeff)
+ *
+ * real x[ARB] # input array of x values
+ * real y[ARB] # output array of interpolated values
+ * int n # number of x values
+ **** real coeff[ARB]
+
+
+ **** Subroutine to evaluate derivatives at a point.
+ *
+ * asider (x, derivs, nder, coeff)
+ *
+ * real x
+ * real derivs[ARB] # output array containing derivatives
+ * # derivs[1] is function value
+ * int nder # input: nder - 1 derivatives are evaluated
+ **** real coeff[ARB]
+
+
+ **** Subroutine to integrate the interpolated data.
+ *
+ * real asigrl (a, b, coeff)
+ *
+ * real a # lower limit
+ * real b # upper limit
+ **** real coeff[ARB]