[/ Copyright (c) 2020 Nick Thompson Use, modification and distribution are subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ] [section:makima Modified Akima interpolation] [heading Synopsis] #include namespace boost::math::interpolators { template class makima { public: using Real = RandomAccessContainer::value_type; makima(RandomAccessContainer&& abscissas, RandomAccessContainer&& ordinates, Real left_endpoint_derivative = std::numeric_limits::quiet_NaN(), Real right_endpoint_derivative = std::numeric_limits::quiet_NaN()); Real operator()(Real x) const; Real prime(Real x) const; void push_back(Real x, Real y); friend std::ostream& operator<<(std::ostream & os, const makima & m); }; } // namespaces [heading Modified Akima Interpolation] The modified Akima interpolant takes non-equispaced data and interpolates between them via cubic Hermite polynomials whose slopes are chosen by a modification of a geometric construction proposed by [@https://doi.org/10.1145/321607.321609 Akima]. The modification is given by [@https://blogs.mathworks.com/cleve/2019/04/29/makima-piecewise-cubic-interpolation/ Cosmin Ionita] and agrees with Matlab's version. The interpolant is /C/[super 1] and evaluation has [bigo](log(/N/)) complexity. This is faster than barycentric rational interpolation, but also less smooth. An example usage is as follows: std::vector x{1, 5, 9 , 12}; std::vector y{8,17, 4, -3}; using boost::math::interpolators::makima; auto spline = makima(std::move(x), std::move(y)); // evaluate at a point: double z = spline(3.4); // evaluate derivative at a point: double zprime = spline.prime(3.4); Periodically, it is helpful to see what data the interpolator has, and the slopes it has chosen. This can be achieved via std::cout << spline << "\n"; Note that the interpolator is pimpl'd, so that copying the class is cheap, and hence it can be shared between threads. (The call operator and `.prime()` are threadsafe.) One unique aspect of this interpolator is that it can be updated in constant time. Hence we can use `boost::circular_buffer` to do real-time interpolation: #include ... boost::circular_buffer initial_x{1,2,3,4}; boost::circular_buffer initial_y{4,5,6,7}; auto circular_akima = makima(std::move(initial_x), std::move(initial_y)); // interpolate via call operation: double y = circular_akima(3.5); // add new data: circular_akima.push_back(5, 8); // interpolat at 4.5: y = circular_akima(4.5); [$../graphs/makima_vs_cubic_b.svg] The modified Akima spline compared to the cubic /B/-spline. The modified Akima spline oscillates less than the cubic spline, but has less smoothness and is not exact on quadratic polynomials. [heading Complexity and Performance] The complexity and performance is identical to that of the cubic Hermite interpolator, since this object simply constructs derivatives and forwards the data to `cubic_hermite.hpp`. [endsect] [/section:makima]