JEMRIS 2.9.2
open-source MRI simulations
Loading...
Searching...
No Matches
spline.h
1#ifndef SPLINE_H
2#define SPLINE_H 1
3/* spline.c
4 Cubic interpolating spline. */
5
6/************************************************/
7/* */
8/* CMATH. Copyright (c) 1989 Design Software */
9/* */
10/************************************************/
11
12/*-----------------------------------------------------------------*/
13template <class T>
14inline T linspace(T *Array, double d1, double d2, int n){
15 int i,j;
16 double Increment;
17
18 j = 0;
19 Increment = (d2-d1)/((double)(n-1));
20
21 for (i = 0; i < n-1; i++){
22 Array[i] = d1+ j*Increment;
23 j++;
24 }
25 Array[n-1] = d2;
26
27 return 0.0;
28}
29
30inline int spline (int n, int end1, int end2,
31 double slope1, double slope2,
32 double x[], double y[],
33 double b[], double c[], double d[],
34 int *iflag)
35
36
37/* Purpose ...
38 -------
39 Evaluate the coefficients b[i], c[i], d[i], i = 0, 1, .. n-1 for
40 a cubic interpolating spline
41
42 S(xx) = Y[i] + b[i] * w + c[i] * w**2 + d[i] * w**3
43 where w = xx - x[i]
44 and x[i] <= xx <= x[i+1]
45
46 The n supplied data points are x[i], y[i], i = 0 ... n-1.
47
48 Input :
49 -------
50 n : The number of data points or knots (n >= 2)
51 end1,
52 end2 : = 1 to specify the slopes at the end points
53 = 0 to obtain the default conditions
54 slope1,
55 slope2 : the slopes at the end points x[0] and x[n-1]
56 respectively
57 x[] : the abscissas of the knots in strictly
58 increasing order
59 y[] : the ordinates of the knots
60
61 Output :
62 --------
63 b, c, d : arrays of spline coefficients as defined above
64 (See note 2 for a definition.)
65 iflag : status flag
66 = 0 normal return
67 = 1 less than two data points; cannot interpolate
68 = 2 x[] are not in ascending order
69
70 This C code written by ... Peter & Nigel,
71 ---------------------- Design Software,
72 42 Gubberley St,
73 Kenmore, 4069,
74 Australia.
75
76 Version ... 1.1, 30 September 1987
77 ------- 2.0, 6 April 1989 (start with zero subscript)
78 remove ndim from parameter list
79 2.1, 28 April 1989 (check on x[])
80 2.2, 10 Oct 1989 change number order of matrix
81
82 Notes ...
83 -----
84 (1) The accompanying function seval() may be used to evaluate the
85 spline while deriv will provide the first derivative.
86 (2) Using p to denote differentiation
87 y[i] = S(X[i])
88 b[i] = Sp(X[i])
89 c[i] = Spp(X[i])/2
90 d[i] = Sppp(X[i])/6 ( Derivative from the right )
91 (3) Since the zero elements of the arrays ARE NOW used here,
92 all arrays to be passed from the main program should be
93 dimensioned at least [n]. These routines will use elements
94 [0 .. n-1].
95 (4) Adapted from the text
96 Forsythe, G.E., Malcolm, M.A. and Moler, C.B. (1977)
97 "Computer Methods for Mathematical Computations"
98 Prentice Hall
99 (5) Note that although there are only n-1 polynomial segments,
100 n elements are requird in b, c, d. The elements b[n-1],
101 c[n-1] and d[n-1] are set to continue the last segment
102 past x[n-1].
103 */
104
105/*----------------------------------------------------------------*/
106
107{ /* begin procedure spline() */
108
109 int nm1, ib, i;
110 double t;
111
112 nm1 = n - 1;
113 *iflag = 0;
114
115 if (n < 2) {
116 /* no possible interpolation */
117 *iflag = 1;
118 return 0;
119 }
120
121 for (i = 1; i < n; ++i) {
122 if (x[i] <= x[i-1]) {
123 *iflag = 2;
124 return 0;
125 }
126 }
127
128 if (n >= 3) {
129 /* ---- At least quadratic ---- */
130
131 /* ---- Set up the symmetric tri-diagonal system
132 b = diagonal
133 d = offdiagonal
134 c = right-hand-side */
135 d[0] = x[1] - x[0];
136 c[1] = (y[1] - y[0]) / d[0];
137 for (i = 1; i < nm1; ++i) {
138 d[i] = x[i+1] - x[i];
139 b[i] = 2.0 * (d[i-1] + d[i]);
140 c[i+1] = (y[i+1] - y[i]) / d[i];
141 c[i] = c[i+1] - c[i];
142 }
143
144 /* ---- Default End conditions
145 Third derivatives at x[0] and x[n-1] obtained
146 from divided differences */
147 b[0] = -d[0];
148 b[nm1] = -d[n-2];
149 c[0] = 0.0;
150 c[nm1] = 0.0;
151 if (n != 3) {
152 c[0] = c[2] / (x[3] - x[1]) - c[1] / (x[2] - x[0]);
153 c[nm1] = c[n-2] / (x[nm1] - x[n-3]) - c[n-3] / (x[n-2] - x[n-4]);
154 c[0] = c[0] * d[0] * d[0] / (x[3] - x[0]);
155 c[nm1] = -c[nm1] * d[n-2] * d[n-2] / (x[nm1] - x[n-4]);
156 }
157
158 /* Alternative end conditions -- known slopes */
159 if (end1 == 1) {
160 b[0] = 2.0 * (x[1] - x[0]);
161 c[0] = (y[1] - y[0]) / (x[1] - x[0]) - slope1;
162 }
163 if (end2 == 1) {
164 b[nm1] = 2.0 * (x[nm1] - x[n-2]);
165 c[nm1] = slope2 - (y[nm1] - y[n-2]) / (x[nm1] - x[n-2]);
166 }
167
168 /* Forward elimination */
169 for (i = 1; i < n; ++i) {
170 t = d[i-1] / b[i-1];
171 b[i] = b[i] - t * d[i-1];
172 c[i] = c[i] - t * c[i-1];
173 }
174
175 /* Back substitution */
176 c[nm1] = c[nm1] / b[nm1];
177 for (ib = 0; ib < nm1; ++ib) {
178 i = n - ib - 2;
179 c[i] = (c[i] - d[i] * c[i+1]) / b[i];
180 }
181
182 /* c[i] is now the sigma[i] of the text */
183
184 /* Compute the polynomial coefficients */
185 b[nm1] = (y[nm1] - y[n-2]) / d[n-2] + d[n-2] * (c[n-2] + 2.0 * c[nm1]);
186 for (i = 0; i < nm1; ++i) {
187 b[i] = (y[i+1] - y[i]) / d[i] - d[i] * (c[i+1] + 2.0 * c[i]);
188 d[i] = (c[i+1] - c[i]) / d[i];
189 c[i] = 3.0 * c[i];
190 }
191 c[nm1] = 3.0 * c[nm1];
192 d[nm1] = d[n-2];
193
194 } else { /* if n >= 3 */
195 /* linear segment only */
196 b[0] = (y[1] - y[0]) / (x[1] - x[0]);
197 c[0] = 0.0;
198 d[0] = 0.0;
199 b[1] = b[0];
200 c[1] = 0.0;
201 d[1] = 0.0;
202 }
203
204 return 0;
205} /* end of spline() */
206/*-------------------------------------------------------------------*/
207
208
209inline double seval (int n, double u,
210 double x[], double y[],
211 double b[], double c[], double d[],
212 int *last)
213
214/*Purpose ...
215 -------
216 Evaluate the cubic spline function
217
218 S(xx) = y[i] + b[i] * w + c[i] * w**2 + d[i] * w**3
219 where w = u - x[i]
220 and x[i] <= u <= x[i+1]
221 Note that Horner's rule is used.
222 If u < x[0] then i = 0 is used.
223 If u > x[n-1] then i = n-1 is used.
224
225 Input :
226 -------
227 n : The number of data points or knots (n >= 2)
228 u : the abscissa at which the spline is to be evaluated
229 Last : the segment that was last used to evaluate U
230 x[] : the abscissas of the knots in strictly increasing order
231 y[] : the ordinates of the knots
232 b, c, d : arrays of spline coefficients computed by spline().
233
234 Output :
235 --------
236 seval : the value of the spline function at u
237 Last : the segment in which u lies
238
239 Notes ...
240 -----
241 (1) If u is not in the same interval as the previous call then a
242 binary search is performed to determine the proper interval.
243
244 */
245/*-------------------------------------------------------------------*/
246
247{ /* begin function seval() */
248
249 int i, j, k;
250 double w;
251
252 i = *last;
253 if (i >= n-1)
254 i = 0;
255 else if (i < 0)
256 i = 0;
257
258 if ((x[i] > u) || (x[i+1] < u)) {
259 /* ---- perform a binary search ---- */
260 i = 0;
261 j = n;
262 do {
263 k = (i + j) / 2; /* split the domain to search */
264 if (u < x[k]) /* move the upper bound */
265 j = k;
266 else /* move the lower bound */
267 i = k;
268 } while (j > i+1); /* there are no more segments to search */
269 }
270 *last = i;
271
272 /* ---- Evaluate the spline ---- */
273 w = u - x[i];
274 w = y[i] + w * (b[i] + w * (c[i] + w * d[i]));
275 return (w);
276}
277/*-------------------------------------------------------------------*/
278
279
280inline double deriv (int n, double u,
281 double x[],
282 double b[], double c[], double d[],
283 int *last)
284
285/* Purpose ...
286 -------
287 Evaluate the derivative of the cubic spline function
288
289 S(x) = B[i] + 2.0 * C[i] * w + 3.0 * D[i] * w**2
290 where w = u - X[i]
291 and X[i] <= u <= X[i+1]
292 Note that Horner's rule is used.
293 If U < X[0] then i = 0 is used.
294 If U > X[n-1] then i = n-1 is used.
295
296 Input :
297 -------
298 n : The number of data points or knots (n >= 2)
299 u : the abscissa at which the derivative is to be evaluated
300 last : the segment that was last used
301 x : the abscissas of the knots in strictly increasing order
302 b, c, d : arrays of spline coefficients computed by spline()
303
304 Output :
305 --------
306 deriv : the value of the derivative of the spline
307 function at u
308 last : the segment in which u lies
309
310 Notes ...
311 -----
312 (1) If u is not in the same interval as the previous call then a
313 binary search is performed to determine the proper interval.
314
315 */
316/*-------------------------------------------------------------------*/
317
318{ /* begin function deriv() */
319
320 int i, j, k;
321 double w;
322
323 i = *last;
324 if (i >= n-1)
325 i = 0;
326 else if (i < 0)
327 i = 0;
328
329 if ((x[i] > u) || (x[i+1] < u)) {
330 /* ---- perform a binary search ---- */
331 i = 0;
332 j = n;
333 do {
334 k = (i + j) / 2; /* split the domain to search */
335 if (u < x[k]) /* move the upper bound */
336 j = k;
337 else /* move the lower bound */
338 i = k;
339 } while (j > i+1); /* there are no more segments to search */
340 }
341 *last = i;
342
343 /* ---- Evaluate the derivative ---- */
344 w = u - x[i];
345 w = b[i] + w * (2.0 * c[i] + w * 3.0 * d[i]);
346 return (w);
347
348} /* end of deriv() */
349
350/*-------------------------------------------------------------------*/
351
352
353inline double sinteg (int n, double u,
354 double x[], double y[],
355 double b[], double c[], double d[],
356 int *last)
357
358/*Purpose ...
359 -------
360 Integrate the cubic spline function
361
362 S(xx) = y[i] + b[i] * w + c[i] * w**2 + d[i] * w**3
363 where w = u - x[i]
364 and x[i] <= u <= x[i+1]
365
366 The integral is zero at u = x[0].
367
368 If u < x[0] then i = 0 segment is extrapolated.
369 If u > x[n-1] then i = n-1 segment is extrapolated.
370
371 Input :
372 -------
373 n : The number of data points or knots (n >= 2)
374 u : the abscissa at which the spline is to be evaluated
375 Last : the segment that was last used to evaluate U
376 x[] : the abscissas of the knots in strictly increasing order
377 y[] : the ordinates of the knots
378 b, c, d : arrays of spline coefficients computed by spline().
379
380 Output :
381 --------
382 sinteg : the value of the spline function at u
383 Last : the segment in which u lies
384
385 Notes ...
386 -----
387 (1) If u is not in the same interval as the previous call then a
388 binary search is performed to determine the proper interval.
389
390 */
391/*-------------------------------------------------------------------*/
392
393{ /* begin function sinteg() */
394
395 int i, j, k;
396 double sum, dx;
397
398 i = *last;
399 if (i >= n-1)
400 i = 0;
401 else if (i < 0)
402 i = 0;
403
404 if ((x[i] > u) || (x[i+1] < u)) {
405 /* ---- perform a binary search ---- */
406 i = 0;
407 j = n;
408 do {
409 k = (i + j) / 2; /* split the domain to search */
410 if (u < x[k]) /* move the upper bound */
411 j = k;
412 else /* move the lower bound */
413 i = k;
414 } while (j > i+1); /* there are no more segments to search */
415 }
416 *last = i;
417
418 sum = 0.0;
419 /* ---- Evaluate the integral for segments x < u ---- */
420 for (j = 0; j < i; ++j) {
421 dx = x[j+1] - x[j];
422 sum += dx *
423 (y[j] + dx *
424 (0.5 * b[j] + dx *
425 (c[j] / 3.0 + dx * 0.25 * d[j])));
426 }
427
428 /* ---- Evaluate the integral fot this segment ---- */
429 dx = u - x[i];
430 sum += dx *
431 (y[i] + dx *
432 (0.5 * b[i] + dx *
433 (c[i] / 3.0 + dx * 0.25 * d[i])));
434
435 return (sum);
436}
437/*-------------------------------------------------------------------*/
438
439
440inline double deriv2 (int n, double u,
441 double x[],
442 double b[], double c[], double d[],
443 int *last)
444
445
446/* Purpose ...
447 -------
448 Evaluate the 2nd derivative of the cubic spline function
449
450 S(x) = 2.0 * C[i]+ 6.0 * D[i] * w
451 where w = u - X[i]
452 and X[i] <= u <= X[i+1]
453 Note that Horner's rule is used.
454 If U < X[0] then i = 0 is used.
455 If U > X[n-1] then i = n-1 is used.
456
457 Input :
458 -------
459 n : The number of data points or knots (n >= 2)
460 u : the abscissa at which the derivative is to be evaluated
461 last : the segment that was last used
462 x : the abscissas of the knots in strictly increasing order
463 b, c, d : arrays of spline coefficients computed by spline()
464
465 Output :
466 --------
467 deriv : the value of the derivative of the spline
468 function at u
469 last : the segment in which u lies
470
471 Notes ...
472 -----
473 (1) If u is not in the same interval as the previous call then a
474 binary search is performed to determine the proper interval.
475
476 */
477/*-------------------------------------------------------------------*/
478
479{ /* begin function deriv2() */
480 //avoid compiler warning:
481 (void) b;
482
483 int i, j, k;
484 double w;
485
486 i = *last;
487 if (i >= n-1)
488 i = 0;
489 else if (i < 0)
490 i = 0;
491
492 if ((x[i] > u) || (x[i+1] < u)) {
493 /* ---- perform a binary search ---- */
494 i = 0;
495 j = n;
496 do {
497 k = (i + j) / 2; /* split the domain to search */
498 if (u < x[k]) /* move the upper bound */
499 j = k;
500 else /* move the lower bound */
501 i = k;
502 } while (j > i+1); /* there are no more segments to search */
503 }
504 *last = i;
505
506 /* ---- Evaluate the derivative ---- */
507 w = u - x[i];
508 w = 2.0 * c[i] + w * 6.0 * d[i];
509 return (w);
510
511} /* end of deriv2() */
512
513/*-------------------------------------------------------------------*/
514
515#endif

-- last change 03.01.2025 | Tony Stoecker | Imprint | Data Protection --