1 #ifndef PSPM_CUBIC_SPLINE_H_ 2 #define PSPM_CUBIC_SPLINE_H_ 35 inline void thomas_solve(
double* a,
double* b,
double* c,
double* d,
int n) {
40 for (
int i = 1; i < n; i++) {
41 c[i] /= b[i] - a[i]*c[i-1];
42 d[i] = (d[i] - a[i]*d[i-1]) / (b[i] - a[i]*c[i-1]);
45 d[n] = (d[n] - a[n]*d[n-1]) / (b[n] - a[n]*c[n-1]);
47 for (
int i = n; i-- > 0;) {
65 int it, first=0, last=arrlen;
70 it = first; step=count/2;
90 int it, first=0, last=arrlen;
95 it = first; step=count/2;
138 template <
typename Container>
140 assert(x.size() == y.size());
141 m_x.assign(x.begin(), x.end());
142 m_y.assign(y.begin(), y.end());
150 for(
int i=0; i<npoints-1; i++) {
151 assert(m_x[i]<m_x[i+1]);
154 if( splineType ==
CUBIC) {
157 else if (splineType ==
LINEAR) {
160 else if (splineType == CONSTRAINED_CUBIC){
169 for(
int i=0; i<n-1; i++) {
172 m_c[i]=(m_y[i+1]-m_y[i])/(m_x[i+1]-m_x[i]);
174 m_a[n-1] = m_b[n-1] = 0.0;
184 std::vector <Float> l(n,0), m(n,0), u(n,0);
185 std::vector<double> rhs(n);
186 for(
int i=1; i<n-1; i++) {
187 l[i] =1.0/3.0*(m_x[i]-m_x[i-1]);
188 m[i] =2.0/3.0*(m_x[i+1]-m_x[i-1]);
189 u[i] =1.0/3.0*(m_x[i+1]-m_x[i]);
190 rhs[i]=(m_y[i+1]-m_y[i])/(m_x[i+1]-m_x[i]) - (m_y[i]-m_y[i-1])/(m_x[i]-m_x[i-1]);
205 for(
int i=0; i<n-1; i++) {
206 m_a[i]=1.0/3.0*(m_b[i+1]-m_b[i])/(m_x[i+1]-m_x[i]);
207 m_c[i]=(m_y[i+1]-m_y[i])/(m_x[i+1]-m_x[i])
208 - 1.0/3.0*(2.0*m_b[i]+m_b[i+1])*(m_x[i+1]-m_x[i]);
212 double h=m_x[n-1]-m_x[n-2];
215 m_c[n-1]=3.0*m_a[n-2]*h*h+2.0*m_b[n-2]*h+m_c[n-2];
222 std::vector <double> m(n);
223 for (
int i=1; i<n-1; ++i){
224 double fplus = (m_y[i+1]-m_y[i])/(m_x[i+1]-m_x[i]);
225 double fminus = (m_y[i]-m_y[i-1])/(m_x[i]-m_x[i-1]);
226 if (fplus*fminus < 0) m[i] = 0;
227 else m[i] = 2/(1/fplus + 1/fminus);
231 m[0] = 3*(m_y[1]-m_y[0])/(m_x[1]-m_x[0])/2 - m[1]/2;
232 m[n-1] = 3*(m_y[n-1]-m_y[n-2])/(m_x[n-1]-m_x[n-2])/2 - m[n-2]/2;
234 for (
int i=0; i<n-1; ++i){
236 double hi = m_x[i+1]-m_x[i];
237 m_b[i] = ( 3*(m_y[i+1]-m_y[i] - m[i]*hi) - hi*(m[i+1]-m[i]))/hi/hi;
238 m_a[i] = (-2*(m_y[i+1]-m_y[i] - m[i]*hi) + hi*(m[i+1]-m[i]))/hi/hi/hi;
245 template <
typename Container>
253 if (extrapolate ==
ZERO)
return 0;
254 else if (extrapolate ==
CONSTANT)
return m_y[0];
255 else return ((m_b[0])*h + m_c[0])*h + m_y[0];
262 if (extrapolate ==
ZERO)
return 0;
263 else if (extrapolate ==
CONSTANT)
return m_y[n-1];
264 else return ((m_b[n-1])*h + m_c[n-1])*h + m_y[n-1];
279 int idx=std::max(it-1,0);
290 return ((m_a[idx]*h + m_b[idx])*h + m_c[idx])*h + m_y[idx];
294 std::cout <<
"Spline: \n";
296 std::cout << std::right << std::setw(10) << std::setfill(
' ') << m_x[i] <<
" " 297 << std::right << std::setw(10) << std::setfill(
' ') << m_y[i] <<
" " 298 << std::right << std::setw(10) << std::setfill(
' ') << m_a[i] <<
" " 299 << std::right << std::setw(10) << std::setfill(
' ') << m_b[i] <<
" " 300 << std::right << std::setw(10) << std::setfill(
' ') << m_c[i] <<
" " 303 std:: cout << std::endl;
328 inline BandMatrix(std::vector<Float> _lower, std::vector<Float> _diag, std::vector<Float> _upper){
336 for (
int i=0; i<N; ++i){
337 for (
int z=0; z<i-1;++z) std::cout << 0 <<
"\t";
338 if (i > 0) std::cout << lower[i] <<
"\t";
339 std::cout << diag[i] <<
"\t";
340 if (i < N-1) std::cout << upper[i] <<
"\t";
341 for (
int z=i+2; z<N; ++z) std::cout << 0 <<
"\t";
346 inline void solve(std::vector<Float>&y){
347 thomas_solve(lower.data(), diag.data(), upper.data(), y.data(), N);
void solve_coeffs_linear()
Float extrapolate_right(double x) const
Float eval(Float x, int idx) const
Float extrapolate_left(double x) const
void solve_coeffs_constrained_cubic()
int my_lower_bound(const T &val, const T *arr, const int arrlen)
void set_points(const Container &x, const Container &y)
void solve_coeffs_cubic()
std::vector< Float > upper
BandMatrix(std::vector< Float > _lower, std::vector< Float > _diag, std::vector< Float > _upper)
Float eval(Float x) const
void thomas_solve(double *a, double *b, double *c, double *d, int n)
void solve(std::vector< Float > &y)
int my_upper_bound(const T &val, T *arr, int arrlen)
std::vector< Float > lower
std::vector< Float > diag
void constructAndReset(const Container &x, const Container &y)