# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. include include "bspln.h" .help seval 2 "math library" .ih NAME seval -- evaluate the Dth derivative of a Kth order b-spline at X. .ih USAGE y = seval (x, deriv, bspln) .ih PARAMETERS The single precision real value returned by SEVAL is the value of the D-th derivative of the b-spline at X. INDEF is returned if X lies outside the domain of the spline. .ls x (real). Logical x-value at which the spline is to be evaluated. .le .ls deriv The derivative to be evaluated. The zeroth derivative is the function value. .le .ls bspln (real[2*n+30]). B-spline descriptor structure, generated by a previous call to SPLINE, SPLLSQ, etc. .le .ih DESCRIPTION Calculate the Dth derivative of a Kth order B-spline. Based on BVALUE, from "A Practical Guide to Splines", by C. DeBoor. The main changes incorporated in SEVAL involve the use of the BSPLN array to convey all of the information needed to describe the spline. This simplifies the calling sequences, and improves the communication between routines. SEVAL is designed to be easy to use, and reasonably efficient in the case where a N point spline is to be evaluated N times or less. If a spline is to be fitted and then evaluated many times, conversion to PP representation may be warranted to gain maximum efficiency. .ih METHOD See DeBoor, pg. 144, or the listing of BVALUE, for a detailed explanation of the mathematics involved. In short, we find the knot interval containing X, choosing the next interval to the left if X happens to fall square on a knot. The distances of X from the K-1 knots to the left and right are then calculated, and the K b-spline coefficients contributing to the interval are extracted. Calculation of divided differences follows, if a derivative is to be calculated. Finally the value of the b-spline at X is evaluated and returned. .ih BUGS The special case ND == 0 and ORDER == 4 (cubic spline) should be recognized, and specially optimized code used to evaluate the spline in that case. .ih SEE ALSO spline(2), fsplin(2), spllsq(2). .endhelp _____________________________________________________________ real procedure seval (x, deriv, bspln) real x # logical x value real bspln[ARB] # ARB = [2 * NCOEF + 30] int deriv # derivative = 0,1,2,...,k-1 int i, j, k, n, jj, ilo, kmj, km1, offset, knots, coefs real aj[KMAX], dl[KMAX], dr[KMAX], fkmj begin if (x < XMIN || x > XMAX) # x out of range? return (INDEF) k = ORDER # fetch k from bspln header if (deriv >= k) # Kth deriv K degree polyn is zero return (0.) # Find i such that X is in the interval T[i] <= X < T[i+1]. First we fetch # KINDEX from the bspln header. This is the index into the knot array from # the last call (many, if not most, calls to SEVAL are sequential in nature). # Usually, KINDEX will already be the right interval, or will be one off. If # more than one off, DeBoors INTERV is called to find the correct index via a # binary search. INTERV handles the special cases (x == XMAX). i = KINDEX # previous index for this spline n = NCOEF knots = KNOT1 if (x >= bspln[i+1]) { # go right i = i + 1 if (x >= bspln[i+1]) { call interv (bspln[knots], n, x, i, j) i = i + knots - 1 } } else if (x < bspln[i]) { # go left i = i - 1 if (x < bspln[i]) { call interv (bspln[knots], n, x, i, j) i = i + knots - 1 } } KINDEX = i km1 = k - 1 coefs = i - knots - k + COEF1 if (km1 <= 0) # if order=1 (& deriv=0), bvalue = bspln[i]. return (bspln[coefs+1]) # Store the ORDER b-spline coefficients relevant for the knot interval # (T[i],T[i+1]) in aj[1],...,aj[k] and compute dl[j] = x - t[i+k-j], # dr[j] = t[i+k-1+j] - x, j=1,...,k-1. Note that the K knots at each endpoint # all have the same T-value, hence we use the lookup table T, rather than # calculate the DL and DR from the knot spacing. offset = i + 1 do j = 1, km1 dl[j] = x - bspln[offset-j] offset = offset - 1 do j = 1, km1 dr[j] = bspln[i+j] - x do j = 1, k # fetch K coefficients aj[j] = bspln[coefs+j] # Difference the coefficients deriv times. if (deriv != 0) { # only if taking a derivative do j = 1, deriv { kmj = k - j fkmj = real (kmj) ilo = kmj do jj = 1, kmj { aj[jj] = ((aj[jj+1] - aj[jj]) / (dl[ilo] + dr[jj])) * fkmj ilo = ilo - 1 } } } # Compute value at X in (t[i],t[i+])) of deriv-th derivative, given its # relevant b-spline coeffs in aj[1],...,aj[k-deriv]. if (deriv != km1) { do j = deriv + 1, km1 { kmj = k - j ilo = kmj do jj = 1, kmj { aj[jj] = (aj[jj+1] * dl[ilo] + aj[jj] * dr[jj]) / (dl[ilo] + dr[jj]) ilo = ilo - 1 } } } return (aj[1]) end