OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
interpol.cpp
Go to the documentation of this file.
1 /* interpol.C
2 
3  Spline interpolation routines
4  NUMERICAL RECIPES IN C: THE ART OF SCIENTIFIC COMPUTING (ISBN 0-521-43108-5)
5 
6  Project: Beam Envelope Tracker (BET)
7 
8  Revision history
9  Date Description Programmer
10  ------------ -------------------------------------------- --------------
11  09-03-06 Created Rene Bakker
12 
13  Last Revision:
14  $Id: interpol.C 29 2007-04-14 17:03:18Z l_bakker $
15 */
16 
19 
20 #include <cstdlib>
21 #include <cstddef>
22 #include <cmath>
23 #include <vector>
24 
25 using namespace std;
26 
27 
28 
29 
30 
31 /* Internal functions
32  ========================================================================= */
33 
34 // :FIXME: remove unused function
35 #if 0
36 /* vector
37  allocate an array of doubles [0..n-1] and check memory */
38 static double *vector(int n) {
39  double *b;
40 
41  b = (double *) malloc(sizeof(double) * n);
42  if(!b) {
43  //writeBetError(errModeAll,errFatal,
44  // "Insufficient memory malloc %d bytes (interpol.C)",sizeof(double)*n);
45  writeBetError("Insufficient memory (interpol.C)");
46  }
47  return b;
48 } /* vector */
49 #endif
50 
51 /* Internal functions
52  ========================================================================= */
53 
54 /* spline()
55  Given arrays x[0..n-1] and y[0..n-1] containing a tabulated function,
56  i.e., yi = f(xi), with x1 < x2 < .. . < xN, this routine returns an
57  array y2[0..n-1] that contains the second derivatives of the
58  interpolating function at the tabulated points x[i].
59  Derrivate at bounderies set to zero !
60 */
61 void spline(double x[], double y[], int n, double y2[]) {
62  int i, k;
63  double
64  p, qn, sig, un;
65 
66  std::vector<double> u(n - 1);
67  y2[0] = u[0] = 0.0;
68  // y2[0] = -0.5;
69  // u[0]=(3.0/(x[1]-x[0]))*((y[1]-y[0])/(x[1]-x[0]));
70 
71  for(i = 1; i <= n - 2; i++) {
72  sig = (x[i] - x[i-1]) / (x[i+1] - x[i-1]);
73  p = sig * y2[i-1] + 2.0;
74  y2[i] = (sig - 1.0) / p;
75  u[i] = (y[i+1] - y[i]) / (x[i+1] - x[i]) - (y[i] - y[i-1]) / (x[i] - x[i-1]);
76  u[i] = (6.0 * u[i] / (x[i+1] - x[i-1]) - sig * u[i-1]) / p;
77  }
78 
79  qn = un = 0.0;
80  // qn=0.5;
81  // un=(3.0/(x[n-1]-x[n-2]))*((y[n-1]-y[n-2])/(x[n-1]-x[n-2]));
82 
83  y2[n-1] = (un - qn * u[n-2]) / (qn * y2[n-2] + 1.0);
84  for(k = n - 2; k >= 0; k--)
85  y2[k] = y2[k] * y2[k+1] + u[k];
86 } /* spline() */
87 
88 
89 /* splint()
90  Given the arrays xa[0..n-1] and ya[0..n-1], which tabulate a function
91  (with the xa[i] in order), and given the array y2a[0..n-1], which
92  is the output from spline above, and given a value of x, this routine
93  returns a cubic-spline interpolated value y.
94 */
95 void splint(double xa[], double ya[], double y2a[], int n, double x, double *y) {
96  int klo, khi, k;
97  double xb, h, b, a;
98 
99  xb = x;
100  if(xb < xa[0]) {
101  xb = xa[0];
102  //writeBetError(errModeAll,errGeneral,"slint called with x < xMin: %lf < %lf",x,xa[0]);
103  writeBetError("slint called with x < xMin");
104  }
105  if(xb > xa[n-1]) {
106  xb = xa[n-1];
107  //writeBetError(errModeAll,errGeneral,"slint called with x > xMax: %lf > %lf",x,xa[n-1]);
108  writeBetError("slint called with x > xMax");
109  }
110 
111  klo = 0;
112  khi = n - 1;
113  while(khi - klo > 1) {
114  k = (khi + klo) >> 1;
115  if(xa[k] > xb) khi = k;
116  else klo = k;
117  }
118  h = xa[khi] - xa[klo];
119  if(h == 0.0)
120  //writeBetError(errModeAll,errFatal,
121  // "Bad xa input to routine splint: x=%lf [%lf,%lf]",
122  // x,xa[0],xa[n-1]);
123  writeBetError("Bad xa input to routine splint");
124  a = (xa[khi] - xb) / h;
125  b = (xb - xa[klo]) / h;
126  *y = a * ya[klo] + b * ya[khi] + ((a * a * a - a) * y2a[klo] + (b * b * b - b) * y2a[khi]) * (h * h) / 6.0;
127 } /* splint() */
128 
129 
130 /* splint()
131  Given the arrays xa[0..n-1] and ya[0..n-1], which tabulate a function
132  (with the xa[i] in order), and given the array y2a[0..n-1], which
133  is the output from spline above, and given a value of x, this routine
134  returns a cubic-spline interpolated value y, which is limited between
135  the y-values of the adjacent points.
136 */
137 void lsplint(double xa[], double ya[], double y2a[], int n, double x, double *y) {
138  int klo, khi, k;
139  double xb, h, b, a, yy;
140 
141  xb = x;
142  if(xb < xa[0]) {
143  xb = xa[0];
144  //writeBetError(errModeAll,errGeneral,"lsplint called with x < xMin: %lf < %lf",x,xa[0]);
145  writeBetError("lslplint x < xMin");
146  }
147  if(xb > xa[n-1]) {
148  xb = xa[n-1];
149  //writeBetError(errModeAll,errGeneral,"lsplint called with x > xMax: %lf > %lf",x,xa[n-1]);
150  writeBetError("lsplint x > xMax");
151  }
152 
153  klo = 0;
154  khi = n - 1;
155  while(khi - klo > 1) {
156  k = (khi + klo) >> 1;
157  if(xa[k] > xb) khi = k;
158  else klo = k;
159  }
160  h = xa[khi] - xa[klo];
161  if(h == 0.0)
162  //writeBetError(errModeAll,errFatal,
163  // "Bad xa input to routine lsplint: x=%lf [%lf,%lf]",
164  // x,xa[0],xa[n-1]);
165  writeBetError("Bad xa input to routine lsplint");
166  a = (xa[khi] - xb) / h;
167  b = (xb - xa[klo]) / h;
168 
169  yy = a * ya[klo] + b * ya[khi] + ((a * a * a - a) * y2a[klo] + (b * b * b - b) * y2a[khi]) * (h * h) / 6.0;
170  if(ya[khi] > ya[klo]) {
171  if(yy > ya[khi]) yy = ya[khi];
172  else if(yy < ya[klo]) yy = ya[klo];
173  } else {
174  if(yy > ya[klo]) yy = ya[klo];
175  else if(yy < ya[khi]) yy = ya[khi];
176  }
177  *y = yy;
178 } /* splint() */
179 
180 
void writeBetError(std::string err)
Definition: BetError.cpp:36
void splint(double xa[], double ya[], double y2a[], int n, double x, double *y)
Definition: interpol.cpp:95
void spline(double x[], double y[], int n, double y2[])
Definition: interpol.cpp:61
void lsplint(double xa[], double ya[], double y2a[], int n, double x, double *y)
Definition: interpol.cpp:137