OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
nr_spline.c
Go to the documentation of this file.
1 /*
2 
3 This code is based on the cubic spline interpolation code presented in:
4 Numerical Recipes in C: The Art of Scientific Computing
5 by
6 William H. Press,
7 Brian P. Flannery,
8 Saul A. Teukolsky, and
9 William T. Vetterling .
10 Copyright 1988 (and 1992 for the 2nd edition)
11 
12 I am assuming zero-offset arrays instead of the unit-offset arrays
13 suggested by the authors. You may style me rebel or conformist
14 depending on your point of view.
15 
16 Norman Kuring 31-Mar-1999
17 W. Robinson, SAIC, 16 Dec 2004 added I/O descriptions
18 
19  */
20 
21 #include <stdio.h>
22 #include <stdlib.h>
23 
24 #define MALLOC(ptr,typ,num) { \
25  (ptr) = (typ *)malloc((num) * sizeof(typ)); \
26  if((ptr) == NULL){ \
27  fprintf(stderr,"-E- %s line %d: Memory allocation failure.\n", \
28  __FILE__,__LINE__); \
29  exit(EXIT_FAILURE); \
30  } \
31 }
32 
33 /* spline setus up to do the spline fit */
34 void
36  float x[], /* x, y values of points known */
37  float y[],
38  int n, /* # points in x, y */
39  float yp1, /* 1st derivative at 1, nth point, set to */
40  float ypn, /* >= 10^30 to do nat'l spline */
41  float y2[] /* output, 2nd derivative to use in splint */
42  ) {
43 
44  int i, k;
45  float p, qn, sig, un, *u;
46 
47  MALLOC(u, float, n - 1);
48 
49  if (yp1 > 0.99e30)
50  y2[0] = u[0] = 0.0;
51  else {
52  y2[0] = -0.5;
53  u[0] = (3.0 / (x[1] - x[0]))*((y[1] - y[0]) / (x[1] - x[0]) - yp1);
54  }
55  for (i = 1; i < n - 1; i++) {
56  sig = (x[i] - x[i - 1]) / (x[i + 1] - x[i - 1]);
57  p = sig * y2[i - 1] + 2.0;
58  y2[i] = (sig - 1.0) / p;
59  u[i] = (y[i + 1] - y[i]) / (x[i + 1] - x[i]) - (y[i] - y[i - 1]) / (x[i] - x[i - 1]);
60  u[i] = (6.0 * u[i] / (x[i + 1] - x[i - 1]) - sig * u[i - 1]) / p;
61  }
62  if (ypn > 0.99e30)
63  qn = un = 0.0;
64  else {
65  qn = 0.5;
66  un = (3.0 / (x[n - 1] - x[n - 2]))*(ypn - (y[n - 1] - y[n - 2]) / (x[n - 1] - x[n - 2]));
67  }
68  y2[n - 1] = (un - qn * u[n - 2]) / (qn * y2[n - 2] + 1.0);
69  for (k = n - 2; k >= 0; k--) {
70  y2[k] = y2[k] * y2[k + 1] + u[k];
71  }
72 
73  free(u);
74 }
75 
76 /* splint applys the fit for any x: low x - high x */
77 void
79  float xa[], /* known x, y as above */
80  float ya[],
81  float y2a[], /* 2nd derivative from spline */
82  int n, /* # points in x, y */
83  float x, /* x to find fit for */
84  float *y /* output - spline fit y value */
85  ) {
86 
87  int klo, khi, k;
88  float h, b, a;
89  static int pklo = 0, pkhi = 1;
90 
91  /*
92  Based on the assumption that sequential calls to this function are made
93  with closely-spaced, steadily-increasing values of x, I first try using
94  the same values of klo and khi as were used in the previous invocation.
95  If that interval is no longer correct, I do a binary search for the
96  correct interval.
97  */
98  if (xa[pklo] <= x && xa[pkhi] > x) {
99  klo = pklo;
100  khi = pkhi;
101  } else {
102  klo = 0;
103  khi = n - 1;
104  while (khi - klo > 1) {
105  k = (khi + klo) >> 1;
106  if (xa[k] > x) khi = k;
107  else klo = k;
108  }
109  }
110 
111  h = xa[khi] - xa[klo];
112  if (h == 0) {
113  fprintf(stderr, "-E- %s line %d: Bad xa input to function splint()\n",
114  __FILE__, __LINE__);
115  exit(EXIT_FAILURE);
116  }
117  a = (xa[khi] - x) / h;
118  b = (x - xa[klo]) / h;
119  *y = a * ya[klo] + b * ya[khi] +
120  ((a * a * a - a) * y2a[klo] + (b * b * b - b) * y2a[khi])*(h * h) / 6.0;
121 }
float h[MODELMAX]
Definition: atrem_corl1.h:131
void splint(float xa[], float ya[], float y2a[], int n, float x, float *y)
Definition: nr_spline.c:78
void spline(float x[], float y[], int n, float yp1, float ypn, float y2[])
Definition: nr_spline.c:35
data_t b[NROOTS+1]
Definition: decode_rs.h:77
data_t u
Definition: decode_rs.h:74
#define MALLOC(ptr, typ, num)
Definition: nr_spline.c:24
int i
Definition: decode_rs.h:71
PGE01 indicating that PGE02 PGE01 V6 for and PGE01 V2 for MOD03 were used to produce the granule By convention adopted in all MODIS Terra PGE02 code versions are The fourth digit of the PGE02 version denotes the LUT version used to produce the granule The source of the metadata environment variable ProcessingCenter was changed from a QA LUT value to the Process Configuration A sign used in error in the second order term was changed to a
Definition: HISTORY.txt:424
int k
Definition: decode_rs.h:73
float p[MODELMAX]
Definition: atrem_corl1.h:131