Version: SMASH-3.4
interpolation.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015-2018,2020,2026
3  * SMASH Team
4  *
5  * GNU General Public License (GPLv3 or later)
6  */
7 
8 #include "smash/interpolation.h"
9 
10 #include <iostream>
11 
12 namespace smash {
13 
15  const std::vector<double>& x, const std::vector<double>& y,
16  const ExtrapolationType extrapolation_type)
17  : extrapolation_type_{extrapolation_type} {
18  switch (extrapolation_type_) {
22  break;
23  default:
24  throw std::invalid_argument(
25  "The provided extrapolation type is not supported. Valid types are "
26  "'None', 'Zero', and 'Constant'.");
27  }
28  const auto N = x.size();
29  if (y.size() != N) {
30  throw std::invalid_argument(
31  "The interpolation requires two vectors of equal length.");
32  }
33  if (N < 3) {
34  throw std::invalid_argument(
35  "Need at least 3 data points for cubic spline interpolation.");
36  }
37  const auto p = generate_sort_permutation(
38  x, [&](double const& a, double const& b) { return a < b; });
39  const std::vector<double> sorted_x = apply_permutation(x, p);
40  const std::vector<double> sorted_y = apply_permutation(y, p);
41  check_duplicates(sorted_x, "InterpolateDataSpline");
42 
43  first_x_ = sorted_x.front();
44  last_x_ = sorted_x.back();
45  first_y_ = sorted_y.front();
46  last_y_ = sorted_y.back();
47  acc_ = gsl_interp_accel_alloc();
48  spline_ = gsl_spline_alloc(gsl_interp_cspline, N);
49  gsl_spline_init(spline_, &(*sorted_x.begin()), &(*sorted_y.begin()), N);
50 }
51 
53  gsl_spline_free(spline_);
54  gsl_interp_accel_free(acc_);
55 }
56 
57 double InterpolateDataSpline::operator()(double xi) const {
58  if (xi < first_x_ || xi > last_x_) {
60  std::ostringstream error_msg{
61  "InterpolateDataSpline only accepts x values within the range of the "
62  "underlying data\nwhen an extrapolation type is not specified. ",
63  std::ios::ate};
64  error_msg << "x value " << xi << " is out of bounds.";
65  throw std::out_of_range(error_msg.str());
67  return 0.;
69  return (xi < first_x_) ? first_y_ : last_y_;
70  }
71  }
72  // cubic spline interpolation
73  return gsl_spline_eval(spline_, xi, acc_);
74 }
75 
76 } // namespace smash
double first_x_
First x value of underlying data.
gsl_spline * spline_
GSL spline.
double last_y_
Last y value of underlying data.
double operator()(double x) const
Calculate spline interpolation at x.
double first_y_
First y value of underlying data.
ExtrapolationType extrapolation_type_
Extrapolation type.
InterpolateDataSpline(const std::vector< double > &x, const std::vector< double > &y, ExtrapolationType extrapolation_type=ExtrapolationType::None)
Interpolate function f given discrete samples f(x_i) = y_i.
gsl_interp_accel * acc_
GSL iterator for interpolation lookups.
double last_x_
Last x value of underlying data.
ExtrapolationType
Allows to specify the desired extrapolation type.
@ None
No extrapolation is done.
@ Constant
Extrapolate using a constant value.
@ Zero
Extrapolate with zero.
constexpr int p
Proton.
Definition: action.h:24
std::vector< T > apply_permutation(const std::vector< T > &v, const Permutation &p)
Apply a permutation to a vector.
void check_duplicates(const std::vector< T > &x, const std::string &error_position)
Check whether two components have the same value in a sorted vector x.
Permutation generate_sort_permutation(std::vector< T > const &v, Cmp compare)
Calculate the permutations necessary for sorting a vector.