• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1[/
2Copyright (c) 2020 Nick Thompson
3Use, modification and distribution are subject to the
4Boost Software License, Version 1.0. (See accompanying file
5LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6]
7
8[section:pchip PCHIP interpolation]
9
10[heading Synopsis]
11
12    #include <boost/math/interpolators/pchip.hpp>
13
14    namespace boost::math::interpolators {
15
16    template <class RandomAccessContainer>
17    class pchip
18    {
19    public:
20
21        using Real = RandomAccessContainer::value_type;
22
23        pchip(RandomAccessContainer&& abscissas, RandomAccessContainer&& ordinates,
24              Real left_endpoint_derivative = std::numeric_limits<Real>::quiet_NaN(),
25              Real right_endpoint_derivative = std::numeric_limits<Real>::quiet_NaN());
26
27        Real operator()(Real x) const;
28
29        Real prime(Real x) const;
30
31        void push_back(Real x, Real y);
32
33        friend std::ostream& operator<<(std::ostream & os, const pchip & m);
34    };
35
36    } // namespaces
37
38
39[heading PCHIP Interpolation]
40
41The PCHIP interpolant takes non-equispaced data and interpolates between them via cubic Hermite polynomials whose slopes are chosen so that the resulting interpolant is monotonic; see [@https://doi.org/10.1137/0717021 Fritsch and Carlson] for details.
42The interpolant is /C/[super 1] and evaluation has [bigo](log(/N/)) complexity.
43An example usage is as follows:
44
45    std::vector<double> x{1, 5, 9 , 12};
46    std::vector<double> y{8,17, 4, -3};
47    using boost::math::interpolators::pchip;
48    auto spline = pchip(std::move(x), std::move(y));
49    // evaluate at a point:
50    double z = spline(3.4);
51    // evaluate derivative at a point:
52    double zprime = spline.prime(3.4);
53
54Periodically, it is helpful to see what data the interpolator has, and the slopes it has chosen.
55This can be achieved via
56
57    std::cout << spline << "\n";
58
59Note that the interpolator is pimpl'd, so that copying the class is cheap, and hence it can be shared between threads.
60(The call operator and `.prime()` are threadsafe; `push_back` is not.)
61
62This interpolant can be updated in constant time.
63Hence we can use `boost::circular_buffer` to do real-time interpolation:
64
65    #include <boost/circular_buffer.hpp>
66    ...
67    boost::circular_buffer<double> initial_x{1,2,3,4};
68    boost::circular_buffer<double> initial_y{4,5,6,7};
69    auto circular_pchip = pchip(std::move(initial_x), std::move(initial_y));
70    // interpolate via call operation:
71    double y = circular_pchip(3.5);
72    // add new data:
73    circular_pchip.push_back(5, 8);
74    // interpolate at 4.5:
75    y = circular_pchip(4.5);
76
77
78
79[$../graphs/pchip.svg]
80
81
82[heading Complexity and Performance]
83
84This interpolator chooses the slopes and forwards data to the cubic Hermite interpolator, so the performance is stated in the documentation for `cubic_hermite.hpp`.
85
86
87[endsect]
88[/section:pchip]
89