source: trunk/src/CubicSplineInterpolator1D.tcc@ 2744

Last change on this file since 2744 was 2736, checked in by Takeshi Nakazato, 12 years ago

New Development: No

JIRA Issue: Yes CAS-4770

Ready for Test: Yes

Interface Changes: Yes/No

What Interface Changed: Please list interface changes

Test Programs: List test programs

Put in Release Notes: Yes/No

Module(s): Module Names change impacts.

Description: Describe your changes here...

Bug fix on reusable_ attribute.


File size: 3.1 KB
RevLine 
[2733]1//
2// C++ Implementation: CubicSplineInterpolator1D
3//
4// Description:
5//
6//
7// Author: Takeshi Nakazato <takeshi.nakazato@nao.ac.jp>, (C) 2012
8//
9// Copyright: See COPYING file that comes with this distribution
10//
11//
12#include <assert.h>
13
14#include <iostream>
15using namespace std;
16
17#include "CubicSplineInterpolator1D.h"
18
19namespace asap {
20
21template <class T, class U>
22CubicSplineInterpolator1D<T, U>::CubicSplineInterpolator1D()
23 : Interpolator1D<T, U>(),
24 y2_(0),
25 ny2_(0),
26 reusable_(false)
27{}
28
29template <class T, class U>
30CubicSplineInterpolator1D<T, U>::~CubicSplineInterpolator1D()
31{
32 if (y2_)
33 delete[] y2_;
34}
35
36template <class T, class U>
37void CubicSplineInterpolator1D<T, U>::setData(T *x, U *y, unsigned int n)
38{
39 Interpolator1D<T, U>::setData(x, y, n);
40 reusable_ = false;
41}
42
43template <class T, class U>
[2736]44void CubicSplineInterpolator1D<T, U>::setX(T *x, unsigned int n)
45{
46 Interpolator1D<T, U>::setX(x, n);
47 reusable_ = false;
48}
49
50template <class T, class U>
[2733]51void CubicSplineInterpolator1D<T, U>::setY(U *y, unsigned int n)
52{
53 Interpolator1D<T, U>::setY(y, n);
54 reusable_ = false;
55}
56
57template <class T, class U>
58U CubicSplineInterpolator1D<T, U>::interpolate(T x)
59{
60 assert(this->isready());
61 if (this->n_ == 1)
62 return this->y_[0];
63
64 unsigned int i = this->locator_->locate(x);
65
66 // do not perform extrapolation
67 if (i == 0) {
68 return this->y_[i];
69 }
70 else if (i == this->n_) {
71 return this->y_[i-1];
72 }
73
74 // determine second derivative of each point
75 if (!reusable_) {
76 evaly2();
77 reusable_ = true;
78 }
79
80 // cubic spline interpolation
81 float y = dospline(x, i);
82 return y;
83}
84
85template <class T, class U>
86void CubicSplineInterpolator1D<T, U>::evaly2()
87{
88 if (this->n_ > ny2_) {
89 if (y2_)
90 delete[] y2_;
91 y2_ = new U[this->n_];
92 ny2_ = this->n_;
93 }
94
95 U *u = new U[ny2_-1];
96
97 // Natural cubic spline.
98 y2_[0] = 0.0;
99 y2_[ny2_-1] = 0.0;
100 u[0] = 0.0;
101
102 // Solve tridiagonal system.
[2736]103 // Here, tridiagonal matrix is decomposed to upper triangular
104 // matrix. u stores upper triangular components while y2_ stores
105 // right-hand side vector. The diagonal elements are normalized
106 // to 1.
[2733]107 T a1 = this->x_[1] - this->x_[0];
108 T a2, bi;
109 for (unsigned int i = 1; i < ny2_ - 1; i++) {
110 a2 = this->x_[i+1] - this->x_[i];
111 bi = 1.0 / (this->x_[i+1] - this->x_[i-1]);
112 y2_[i] = 3.0 * bi * ((this->y_[i+1] - this->y_[i]) / a2
113 - (this->y_[i] - this->y_[i-1]) / a1
114 - y2_[i-1] * 0.5 * a1);
115 a1 = 1.0 / (1.0 - u[i-1] * 0.5 * a1 * bi);
116 y2_[i] *= a1;
117 u[i] = 0.5 * a2 * bi * a1;
118 a1 = a2;
119 }
120
121 // Then, solve the system by backsubstitution and store solution
122 // vector to y2_.
123 for (int k = ny2_ - 2; k >= 0; k--)
124 y2_[k] -= u[k] * y2_[k+1];
125
126 delete[] u;
127}
128
129template <class T, class U>
130U CubicSplineInterpolator1D<T, U>::dospline(T x, unsigned int i)
131{
132 unsigned int j = i - 1;
133 T h = this->x_[i] - this->x_[j];
134 T a = (this->x_[i] - x) / h;
135 T b = (x - this->x_[j]) / h;
136 U y = a * this->y_[j] + b * this->y_[i] +
137 ((a * a * a - a) * y2_[j] + (b * b * b - b) * y2_[i]) * (h * h) / 6.0;
138 return y;
139}
140
141}
Note: See TracBrowser for help on using the repository browser.