291194828 5/28/2016 The Lagrange Polynomial (Press Chapter 3) If we know a function at N distinct data points and if we require that the polynomial approximation pn(x) be equal to f(x) at all N points. The N constants in the expansion pN 1 ( x) i N 1 cx i 0 i i (0.1) are uniquely determined by the N equations c0 c1 x1 c2 x12 c3 x13 cN 1 x1N 1 f1 c0 c1 x2 c2 x22 c3 x23 cN 1 x2N 1 f 2 c0 c1 x3 c2 x32 c3 x33 cN 1 x3N 1 f 3 c0 c1 x4 c2 x42 c3 x43 cN 1 x4N 1 f 4 (0.2) 1/3 N N k 1 k 1 pn ( x) f k Lk x f xk Lk x (0.4) Note L x pn ( x) N (0.5) f xk k x x k 1 This depends on x only through the Lk(x) terms. At x = xk, the L’s are equal to zero except for the one multiplying fk which is equal to 1. Thus pn(x) goes through all of the data points and is explicitly of order N-1. Equation (0.4) is the solution to the problem leading to (0.2). Note that (0.4) does not explicitly give us the coefficients c0 through cN-1. This is a drawback. The coding for (0.5) and higher derivatives along with a practical example is in ..\wsteve\FDERS\The Lagrange Polynomial.htm ... c0 c1 xN c2 xN2 c3 xN3 cN 1 xNN 1 f N This implies that there is one and only one polynomial of degree N-1 which passes through the N data points, we can write the Lagrange polynomial which accomplishes this almost by inspection. The Lagrange polynomials are defined with respect to x and the data abscissa xk and xj as jN Lk x j 1 j k x x x x j j k 1, Coding the Lagrange Polynomial A quotation from our text “It is not terribly wrong to implement the Lagrange formula straightforwardly, but it is not terribly right either”1 gives fair warning that a few extra computer steps are involved in coding the above in directly and that many people will say that it lacks elegance. It is very easy and also easy to debug. In fortran for/lagrange.for -- for\LAGRANGE.ZIP , N (0.3) k One term is always left out of the product that covers N values in which x always appears once. Thus it is easy to see that Lk is a polynomial of degree N-1 and that sums of the Lk values times constants will also be of degree N-1. The value of Lk(xmk) where xmk is any of the data points other than the k’th one will have a x x zero in the numerator for the j=m term m m so xm xk NL = C*** C*** C*** that Lk(xmk)=0. The value of Lk(xm=k) is quite different. Each term in the product is of the form x j xm 1 and by construction the dangerous x j xk term with xj=xk has been left out so that Lk(xm=k)=1. Thus the polynomial desired is FUNCTION POLYL(NL,NDAT,X,XDAT,FDAT) IMPLICIT REAL*8 (A-H,O-Z) DIMENSION XDAT(*),FDAT(*) DIMENSION ALAG(24) IF(NL.GT.24)THEN PRINT*,' FROM POLYL ALAG DIMENSION EXCEEDED ',NL NL=24 READ(*,*)ITEST ENDIF CALL LOCATE(X,XDAT,NDAT,JB) JB is such that XP(JB)<X<XP(JB+1) MOVE BACK (NL-2)/2 IF POSSIBLE MOVE BACK TO LEAVE NL+JB=NDAT JB=MIN(JB,NDAT-NL) JB=MAX(0,JB-1-(NL-2)/2) CALL UELAG(NL,JB,X,ALAG,XDAT) POLYL=0 DO I=1,NL POLYL=POLYL+ALAG(I)*FDAT(I+JB) ENDDO RETURN END SUBROUTINE UELAG(NL,JB,X,ALAG,XDAT) IMPLICIT REAL*8 (A-H,O-Z) DIMENSION ALAG(NL),XDAT(*) DO M=1,NL 1 Numerical Recipes in C, W.H. Press, S.A. Teukolsky, W.T. Vetterling, B.P. Flannery, Cambridge, New York 1992 p. 108 291194828 5/28/2016 ALAG(M)=1.D0 DO J=1,NL IF(J.NE.M)THEN FACT=(X-XDAT(J+JB))/(XDAT(M+JB)XDAT(J+JB)) ALAG(M)=ALAG(M)*FACT ENDIF ENDDO ENDDO RETURN END cpp\CTLAG.ZIP 02/07/2005 16:20 CTLAG.WPJ 02/08/2005 05:08 TLAG.C double laglo(double x) {static int nc=0, ndat; static double xp[137],dp[137]; FILE *fp; if(nc == 0) {nc=1; fp = fopen("loren.out","r"); if(fp == NULL) {printf(" cannot open file loren.out \n"); return 0.0;} ndat=0; redbeg: if(fscanf(fp, "%lg %lg", &xp[ndat],&dp[ndat])!= EOF) {/*printf("The line read was: %lg %g\n", xp[ndat],dp[ndat]);*/ ndat = ndat+1; if(ndat <= 137) goto redbeg; else {printf(" from laglo ndat > 137, enter to continue "); scanf(" \n");}} fclose(fp); ndat=ndat-1;} return bpolyl(4,ndat,x,xp,dp);} void main(void) {double xi[502],fi[502],err[502]; int np=500,ndo=2,i,ibli,itest; /* double x,test; double x=1.99,test; */ FILE *fp; /* test=laglo(x); printf(" x, TEST =%lg %lg \n",x,test); return; */ fp=fopen("blic.out","w"); if(fp ==NULL){printf(" cannot open bli.out file\n"); scanf(" %d ",&itest); return;} printf(" enter the beginning and ending x values \n"); scanf(" %lg %lg",&xi[0],&xi[1]); printf(" xi[0] %lg xi[1] %lg \n",xi[0],xi[1]); /* for(i=0;i<=np;i++) {x=-4+i*(xi[1]-xi[0])/np; test=laglo(x); fprintf(fp,"%14.6lg %14.6lg\n",x,test);} */ 2/3 ibli=bli(xi,fi,err,np,ndo,laglo); /* printf(" after bli xi[0] = %lg \n",xi[0]); */ for(i=0;i<=ibli;i++)fprintf(fp,"%14.6lg %14.6lg\n",xi[i],fi[i]); fclose(fp); return;} 02/08/2005 05:08 BLI.C tbli.c in cpp\cbli.zip 04/19/2003 20:13 LOCATE.C 02/08/2005 05:00 LAGRANGE.C #include <stdio.h> int locate(double x,double r[],int n); void uelag(int nl,int jb,double x,double alag[],double xdat[]) {int m,j; double fact; for (m = 0; m < nl; ++m) {alag[m] = 1.; for (j = 0; j < nl; ++j) {if (j != m) {fact = (x - xdat[j+jb]) / (xdat[m+jb] - xdat[j+jb]); /* printf(" from uelag fact = %lg \n",fact); */ alag[m] = alag[m] * fact;}}} return;} double bpolyl(int nl,int ndat,double x,double xdat[],double fdat[]) {int i,jb; double ret_val; double alag[24]; if(nl > 24) {printf(" from polyl alag dimension exceeded nl = %d \n",nl); nl = 24; scanf(" \n");} jb = locate(x,xdat,ndat); if(jb > ndat - nl)jb = ndat - nl; jb=jb-(nl-2)/2; if(jb < -1 ) jb = -1; uelag(nl,jb,x,alag,xdat); ret_val = 0.; for (i = 0; i < nl; ++i) {ret_val += alag[i] * fdat[i+jb];} return ret_val;} 01/31/2005 15:12 LOREN.OUT 02/07/2005 16:20 CTLAG.TGT 291194828 5/28/2016 The one change from defaults is to switch from full debugging information to line number information. #include <stdio.h> #include <math.h> These are needed for all files in Watcom, not for most other compilers. double bpolyl(int nl,int ndat,double x,double xdat[],double fdat[]); int bli(double xi[],double fi[],double err[],int np, int ndo, double (*fext)(double)); /* #include "d:\cpp\bli.c" see tbli.c in cpp\cbli.zip #include "d:\cpp\lagrange.c" #include "d:\cpp\locate.c" */ These are commented out here, they are needed for other compilers. Derivatives See ..\Derivatives\Lagrange.docx Code that gives interpolated value and its derivative is in uelagwd.zip. 3/3