aboutsummaryrefslogtreecommitdiff
path: root/math/interp/asider.x
blob: 2c9a281954aa42248049c34ac221e232f33c8780 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
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