Introduction The group of points shown to the left becomes a function through the process of interpolation. In general the region in which the interpolating function is most valid is that between points 12 and 13. The fact that the polynomial goes through points 12 and 13 give rise to the hope that it is reasonably accurate between them. The fact that it also goes through points 11 and 14 implies that the first derivatives should be accurate at each side of the (12,13) region. The set of points will in general be spaced such that there are more points in the regions where the function is rapidly changing. Practical Handbook of Mathematical Functions, M. Abramowitz and I. Stegun, editors Dover (1965) Contains tables of mathematical data and short code examples for approximating functions. Generally gives good pade approximates and a complete table of the Tchebyshev coefficients. Also contains tables of function values. Figure 1 Top of page from Abramawitz and Stegun Figure 2 Bottom of the same page Linear interpolation on j0(x) in this table has an error of 4 x 10-4. Interpolation with 6 Lagrange polynomials, gives the full table accuracy. Linear interpolation A linear polynomial that goes through the beginning and ending points of the data is x xJ f xJ 1 f xJ (1) xJ 1 xJ Note that the first derivative in the region is approximately given by 1 x xJ 1 f ' J f xJ 1 f xJ (2) 2 xJ 1 xJ This makes P x f xJ x xJ 1 P x f xJ x xJ f ' J (3) 2 This is mostly of value as a convenient way to remember equation (1) Locate Fortran #Tlocate in C Thus the interpolation problem begins with finding the J of equation (1).This starts the test routine for locate. The best way to find what a routine does is to test it. Test program for locate Tlocate.for IMPLICIT REAL*8 (A-H,O-Z) PARAMETER (MVALS=129) This is the f77 way to have variable dimensions. Only MVALS needs to be changed. DIMENSION XI(MVALS),FI(MVALS) OPEN(1,FILE='LOREN.OUT') N=1 5 READ(1,*,ERR=10,END=10)XI(N),FI(N) N=N+1 IF(N.GT.MVALS)THEN PRINT*,' N => MVALS IN READ LOOP ' READ(*,*)ITEST GOTO 10 ENDIF GOTO 5 10 N=N-1 15 PRINT*,' ENTER A VALUE FOR X ' READ(*,*)X CALL LOCATE(X,XI,N,J) IF(J.EQ.0)THEN PRINT*,' X IS LESS THAN ',XI(1) ELSEIF(J.EQ.N)THEN PRINT*,' x IS GREATER THAN last point ',XI(N) ELSE PRINT*,' J= ',J PRINT*,XI(J),X,XI(J+1) ENDIF GOTO 15 END C$INCLUDE LOCATE The Fortran locate routine begins The routine TLOCATE.ZIP (Tlocate.for, LOCATE.FOR, loren.out) searches an ordered vector to find the largest member less than the argument x. The following is “essentially” that given in Press (Fortran 1986) p 90. The method is the old 20 questions game. Is the result larger than x(j) halving the size of j each time. 2 N values are search with N such questions. SUBROUTINE LOCATE(X,R,NMAX,J) C RETURNS A VALUE J SUCH THAT R(J)<=X<=R(J+1) IMPLICIT REAL*8 (A-H,O-Z) DIMENSION R(*) JL=0 JU=NMAX+1 10 IF(JU- JL.LE.1)GOTO 20 JM=(JU+JL)/2 IF(X.GT.R(JM))THEN JL=JM ELSE JU=JM ENDIF GOTO 10 20 J=JL RETURN END run *WRN* ST-09 line 27, this statement will never be executed due to the preceding branch ENTER A VALUE FOR X 37 J= 72 31.746000000000000 37.000000000000000 39.682500000000000 ENTER A VALUE FOR X 25 J= 71 23.809500000000000 25.000000000000000 31.746000000000000 ENTER A VALUE FOR X .05 J= 63 2.842170000000000D-014 0.050000000000000 1.984130000000000 ENTER A VALUE FOR X -2000 X IS LESS THAN 1000.000000000000000 ENTER A VALUE FOR X +1000 J= 127 968.254000000000000 1000.000000000000000 1000.000000000000000 ENTER A VALUE FOR X s *ERR* IO-08 bad character in input field TraceBack: Executing in MAIN PROGRAM, statement 16 in file tlocate.for <hold> Enter a character such as ‘s’ to end. This ending is not elegant, but is simple. One last comment, in the ide, the c$include makes the locate code appear both as a part of tlocate and separately, but we want them both so that we can edit from the ide and so that … I always change the c$ to a c#. for\TLOCATE.ZIP. Tlocate in C The C code to do this same thing follows. It is more elegant than the Fortran (and somewhat related to Press C 1992 p 117) The tlocate source in C TLOCATE.C #include <stdio.h> #include <io.h> #define MAX 129 /* equivalent to a parameter statement */ #include "locate.c" /* the guilty line */ void main(void) { double x,xi[MAX],fi[MAX]; int n,i; FILE *fp; fp = fopen("loren.out","r"); if(fp == NULL){printf(" cannot open file loren.out \n"); return;} n=1; redbeg: if(fscanf(fp, "%lg %lg", &xi[n],&fi[n])!= EOF) {printf("The line read was: %lg %g\n", xi[n],fi[n]); n = n+1; goto redbeg;} fclose(fp); if(n > MAX ) {printf(" from tlocate or read n > MAX, enter to continue "); scanf(" \n");} n=n-1; while (x != -10000) {printf("enter a value for x or -10000 to quit \n"); /* a more contrived ending than the s above */ scanf("%lf",&x); i=locate(x,xi,n); if(i >= 0 && i != n-1) {printf(" i = %d \n",i); printf(" %f %f %f \n",xi[i],x,xi[i+1]);} else if (i == -1 )printf(" %f %f \n",x,xi[i+1]); else if (i == n-1 )printf(" %f %f \n",xi[i],x); } return; } The locate source in C cpp\TLOCATE.ZIP (cpp\tlocate.wpj cpp\TLOCATE.C cpp\LOCATE.C) int locate(double x,double r[],int n) { int jl = -1; int ju = n; int jm; while (ju-jl>1) {jm=(ju+jl) >> 1; if(x > r[jm])jl=jm; else ju=jm; } return jl;} Note that locate is a function rather than a subroutine and that the division by 2 is simply a right shift.