source: trunk/src/CubicSplineInterpolator1D.cpp@ 2732

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

New Development: No

JIRA Issue: Yes CAS-4770

Ready for Test: Yes

Interface Changes: 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...

Rewrite implementations for locator and interpolator.
Documentation (doxygen format) is added to header files.


File size: 2.5 KB
Line 
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
21CubicSplineInterpolator1D::CubicSplineInterpolator1D()
22 : Interpolator1D(),
23 y2_(0),
24 ny2_(0),
25 reusable_(false)
26{}
27
28CubicSplineInterpolator1D::~CubicSplineInterpolator1D()
29{
30 if (y2_)
31 delete[] y2_;
32}
33
34void CubicSplineInterpolator1D::setData(double *x, float *y, unsigned int n)
35{
36 Interpolator1D::setData(x, y, n);
37 reusable_ = false;
38}
39
40void CubicSplineInterpolator1D::setY(float *y, unsigned int n)
41{
42 Interpolator1D::setY(y, n);
43 reusable_ = false;
44}
45
46float CubicSplineInterpolator1D::interpolate(double x)
47{
48 assert(isready());
49 if (n_ == 1)
50 return y_[0];
51
52 unsigned int i = locator_->locate(x);
53
54 // do not perform extrapolation
55 if (i == 0) {
56 return y_[i];
57 }
58 else if (i == n_) {
59 return y_[i-1];
60 }
61
62 // determine second derivative of each point
63 if (!reusable_) {
64 evaly2();
65 reusable_ = true;
66 }
67
68 // cubic spline interpolation
69 float y = dospline(x, i);
70 return y;
71}
72
73void CubicSplineInterpolator1D::evaly2()
74{
75 if (n_ > ny2_) {
76 if (y2_)
77 delete[] y2_;
78 y2_ = new float[n_];
79 ny2_ = n_;
80 }
81
82 float *u = new float[ny2_-1];
83
84 // Natural cubic spline.
85 y2_[0] = 0.0;
86 y2_[ny2_-1] = 0.0;
87 u[0] = 0.0;
88
89 // Solve tridiagonal system.
90 // Here, tridiagonal matrix is decomposed to triangular matrix
91 // u stores upper triangular components while y2_ stores
92 // right-hand side vector.
93 double a1 = x_[1] - x_[0];
94 double a2, bi;
95 for (unsigned int i = 1; i < ny2_ - 1; i++) {
96 a2 = x_[i+1] - x_[i];
97 bi = 1.0 / (x_[i+1] - x_[i-1]);
98 y2_[i] = 3.0 * bi * ((y_[i+1] - y_[i]) / a2 - (y_[i] - y_[i-1]) / a1
99 - y2_[i-1] * 0.5 * a1);
100 a1 = 1.0 / (1.0 - u[i-1] * 0.5 * a1 * bi);
101 y2_[i] *= a1;
102 u[i] = 0.5 * a2 * bi * a1;
103 a1 = a2;
104 }
105
106 // Then, solve the system by backsubstitution and store solution
107 // vector to y2_.
108 for (int k = ny2_ - 2; k >= 0; k--)
109 y2_[k] -= u[k] * y2_[k+1];
110
111 delete[] u;
112}
113
114float CubicSplineInterpolator1D::dospline(double x, unsigned int i)
115{
116 unsigned int j = i - 1;
117 double h = x_[i] - x_[j];
118 double a = (x_[i] - x) / h;
119 double b = (x - x_[j]) / h;
120 float y = a * y_[j] + b * y_[i] +
121 ((a * a * a - a) * y2_[j] + (b * b * b - b) * y2_[i]) * (h * h) / 6.0;
122 return y;
123}
124
125}
Note: See TracBrowser for help on using the repository browser.