#pragma once #include "./numerics/interpolation1d/interpolation1d_base.h" #include "./numerics/abs.h" #include "./utils/vector.h" namespace numerics{ template struct interp_polynomial : Base_interp { using Base = Base_interp; // bring base data members into scope (or use this->xx / this->yy below) using Base::xx; using Base::yy; using Base::mm; T dy; interp_polynomial(const utils::Vector &xv, const utils::Vector &yv, uint64_t m) : Base_interp(xv, &yv[0], m), dy(T{0}){} T rawinterp(int64_t jl, T x) override{ int64_t ns=0; T y, den, dif, dift, ho, hp, w; const T *xa = &xx[jl], *ya = &yy[jl]; utils::Vector c(mm,0), d(mm,0); dif = numerics::abs(x-xa[0]); for (int64_t i = 0; i < mm; ++i){ // Here we find the index ns of the closest table entry, dift = numerics::abs(x-xa[i]); if (dift < dif){ ns = i; dif=dift; } c[i]=ya[i]; // and initialize the tableau of c’s and d’s. d[i]=ya[i]; } y = ya[ns]; // This is the initial approximation to y. ns -= 1; for (int64_t m = 1; m < mm; ++m){ // For each column of the tableau, for (int64_t i = 0; i < mm-m; ++i){ // we loop over the current c’s and d’s and update them. ho = xa[i]-x; hp = xa[i+m]-x; w = c[i+1]-d[i]; den = ho-hp; if (den == T{0.0}){ throw std::invalid_argument("interp_polynomial error"); // This error can occur only if two input xa’s are (to within roundoff identical. } den = w/den; // Here the c’s and d’s are updated. d[i] = hp*den; c[i] = ho*den; } bool take_left = 2 * (ns + 1) < (mm - m); if (take_left) { dy = c[ns + 1]; y += dy; } else { dy = d[ns]; y += dy; ns -= 1; } } return y; } }; } // namespace numerics