source: trunk/src/CubicSplineInterpolator1D.cpp @ 2730

Last change on this file since 2730 was 2730, checked in by Takeshi Nakazato, 11 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.