~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
cvs/emstar/libnl/nr/spline.c


  1 
  2 /*
  3  *  spline.c
  4  *
  5  *  Routines from numerical recipes for cubic spline interpolation
  6  *
  7  */
  8 
  9 #include "nr.h"
 10 
 11 /*
 12  * Given arrays x[1..n] and y[1..n] containing a tabulated function, i.e., yi = f(xi), with
 13  * x1 <x2 < :: : < xN, and given values yp1 and ypn for the first derivative of the interpolating
 14  * function at points 1 and n, respectively, this routine returns an array y2[1..n] that contains
 15  * the second derivatives of the interpolating function at the tabulated points xi. If yp1 and/or
 16  * ypn are equal to 1 x 10^30 or larger, the routine is signaled to set the corresponding boundary
 17  * condition for a natural spline, with zero second derivative on that boundary.
 18  */
 19 
 20 void spline(float x[], float y[], int n, float yp1, float ypn, float y2[]) {
 21   int i,k;
 22   float p,qn,sig,un,*u;
 23 
 24   u=vector(1,n-1);
 25   if (yp1 > 0.99e30) // The lower boundary condition is set either to be "natural
 26     y2[1]=u[1]=0.0;
 27   else {             // or else to have a specified first derivative.
 28     y2[1] = -0.5;
 29     u[1]=(3.0/(x[2]-x[1]))*((y[2]-y[1])/(x[2]-x[1])-yp1);
 30   }
 31 
 32   // This is the decomposition loop of the tridiagonal algorithm.
 33   // y2 and u are used for temporary storage of the decomposed factors.
 34   for (i=2;i<=n-1;i++) { 
 35     sig=(x[i]-x[i-1])/(x[i+1]-x[i-1]);
 36     p=sig*y2[i-1]+2.0;
 37     y2[i]=(sig-1.0)/p;
 38     u[i]=(y[i+1]-y[i])/(x[i+1]-x[i]) - (y[i]-y[i-1])/(x[i]-x[i-1]);
 39     u[i]=(6.0*u[i]/(x[i+1]-x[i-1])-sig*u[i-1])/p;
 40   }
 41   
 42   if (ypn > 0.99e30) // The upper boundary condition is set either to be "natural"
 43     qn=un=0.0; 
 44   else {             // or else to have a specied rst derivative.
 45     qn=0.5;
 46     un=(3.0/(x[n]-x[n-1]))*(ypn-(y[n]-y[n-1])/(x[n]-x[n-1]));
 47   }
 48 
 49   y2[n]=(un-qn*u[n-1])/(qn*y2[n-1]+1.0);
 50   for (k=n-1;k>=1;k--)        // This is the backsubstitution loop of the tridiagonal
 51     y2[k]=y2[k]*y2[k+1]+u[k]; // algorithm.
 52   free_vector(u,1,n-1);
 53 }
 54 
 55 
 56 /*
 57  * Given the arrays xa[1..n] and ya[1..n], which tabulate a function (with the xai's in order),
 58  * and given the array y2a[1..n], which is the output from spline above, and given a value of
 59  * x, this routine returns a cubic-spline interpolated value y.
 60  */
 61 void splint(float xa[], float ya[], float y2a[], int n, float x, float *y)
 62 {
 63   void nrerror(char error_text[]);
 64   int klo,khi,k;
 65   float h,b,a;
 66 
 67   /* 
 68    * We will find the right place in the table by means of
 69    * bisection. This is optimal if sequential calls to this
 70    * routine are at random values of x. If sequential calls
 71    * are in order, and closely spaced, one would do better
 72    * to store previous values of klo and khi and test if
 73    * they remain appropriate on the next call.
 74    */
 75 
 76   klo=1; 
 77   khi=n;
 78   while (khi-klo > 1) {
 79     k=(khi+klo) >> 1;
 80     if (xa[k] > x) khi=k;
 81     else klo=k;
 82   }                     // klo and khi now bracket the input value of x.
 83 
 84   h=xa[khi]-xa[klo];
 85   if (h == 0.0) nrerror("Bad xa input to routine splint"); //The xa's must be
 86     a=(xa[khi]-x)/h;                                       // distinct.
 87     b=(x-xa[klo])/h;    // Cubic spline polynomial is now evaluated.
 88   *y=a*ya[klo]+b*ya[khi]+((a*a*a-a)*y2a[klo]+(b*b*b-b)*y2a[khi])*(h*h)/6.0;
 89 }
 90 
 91 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.