summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/math/test/makima_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/math/test/makima_test.cpp')
-rw-r--r--src/boost/libs/math/test/makima_test.cpp186
1 files changed, 186 insertions, 0 deletions
diff --git a/src/boost/libs/math/test/makima_test.cpp b/src/boost/libs/math/test/makima_test.cpp
new file mode 100644
index 000000000..07d2a7185
--- /dev/null
+++ b/src/boost/libs/math/test/makima_test.cpp
@@ -0,0 +1,186 @@
+/*
+ * Copyright Nick Thompson, 2020
+ * 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)
+ */
+
+#include "math_unit_test.hpp"
+#include <numeric>
+#include <utility>
+#include <random>
+#include <boost/math/interpolators/makima.hpp>
+#include <boost/circular_buffer.hpp>
+#ifdef BOOST_HAS_FLOAT128
+#include <boost/multiprecision/float128.hpp>
+using boost::multiprecision::float128;
+#endif
+
+
+using boost::math::interpolators::makima;
+
+template<typename Real>
+void test_constant()
+{
+
+ std::vector<Real> x{0,1,2,3, 9, 22, 81};
+ std::vector<Real> y(x.size());
+ for (auto & t : y) {
+ t = 7;
+ }
+
+ auto x_copy = x;
+ auto y_copy = y;
+ auto akima = makima(std::move(x_copy), std::move(y_copy));
+
+ for (Real t = x[0]; t <= x.back(); t += 0.25) {
+ CHECK_ULP_CLOSE(Real(7), akima(t), 2);
+ CHECK_ULP_CLOSE(Real(0), akima.prime(t), 2);
+ }
+
+ boost::circular_buffer<Real> x_buf(x.size());
+ for (auto & t : x) {
+ x_buf.push_back(t);
+ }
+
+ boost::circular_buffer<Real> y_buf(x.size());
+ for (auto & t : y) {
+ y_buf.push_back(t);
+ }
+
+ auto circular_akima = makima(std::move(x_buf), std::move(y_buf));
+
+ for (Real t = x[0]; t <= x.back(); t += 0.25) {
+ CHECK_ULP_CLOSE(Real(7), circular_akima(t), 2);
+ CHECK_ULP_CLOSE(Real(0), akima.prime(t), 2);
+ }
+
+ circular_akima.push_back(x.back() + 1, 7);
+ CHECK_ULP_CLOSE(Real(0), circular_akima.prime(x.back()+1), 2);
+
+}
+
+template<typename Real>
+void test_linear()
+{
+ std::vector<Real> x{0,1,2,3};
+ std::vector<Real> y{0,1,2,3};
+
+ auto x_copy = x;
+ auto y_copy = y;
+ auto akima = makima(std::move(x_copy), std::move(y_copy));
+
+ CHECK_ULP_CLOSE(y[0], akima(x[0]), 0);
+ CHECK_ULP_CLOSE(Real(1)/Real(2), akima(Real(1)/Real(2)), 10);
+ CHECK_ULP_CLOSE(y[1], akima(x[1]), 0);
+ CHECK_ULP_CLOSE(Real(3)/Real(2), akima(Real(3)/Real(2)), 10);
+ CHECK_ULP_CLOSE(y[2], akima(x[2]), 0);
+ CHECK_ULP_CLOSE(Real(5)/Real(2), akima(Real(5)/Real(2)), 10);
+ CHECK_ULP_CLOSE(y[3], akima(x[3]), 0);
+
+ x.resize(45);
+ y.resize(45);
+ for (size_t i = 0; i < x.size(); ++i) {
+ x[i] = i;
+ y[i] = i;
+ }
+
+ x_copy = x;
+ y_copy = y;
+ akima = makima(std::move(x_copy), std::move(y_copy));
+ for (Real t = 0; t < x.back(); t += 0.5) {
+ CHECK_ULP_CLOSE(t, akima(t), 0);
+ CHECK_ULP_CLOSE(Real(1), akima.prime(t), 0);
+ }
+
+ x_copy = x;
+ y_copy = y;
+ // Test endpoint derivatives:
+ akima = makima(std::move(x_copy), std::move(y_copy), Real(1), Real(1));
+ for (Real t = 0; t < x.back(); t += 0.5) {
+ CHECK_ULP_CLOSE(t, akima(t), 0);
+ CHECK_ULP_CLOSE(Real(1), akima.prime(t), 0);
+ }
+
+
+ boost::circular_buffer<Real> x_buf(x.size());
+ for (auto & t : x) {
+ x_buf.push_back(t);
+ }
+
+ boost::circular_buffer<Real> y_buf(x.size());
+ for (auto & t : y) {
+ y_buf.push_back(t);
+ }
+
+ auto circular_akima = makima(std::move(x_buf), std::move(y_buf));
+
+ for (Real t = x[0]; t <= x.back(); t += 0.25) {
+ CHECK_ULP_CLOSE(t, circular_akima(t), 2);
+ CHECK_ULP_CLOSE(Real(1), circular_akima.prime(t), 2);
+ }
+
+ circular_akima.push_back(x.back() + 1, y.back()+1);
+
+ CHECK_ULP_CLOSE(Real(y.back() + 1), circular_akima(Real(x.back()+1)), 2);
+ CHECK_ULP_CLOSE(Real(1), circular_akima.prime(Real(x.back()+1)), 2);
+
+}
+
+template<typename Real>
+void test_interpolation_condition()
+{
+ for (size_t n = 4; n < 50; ++n) {
+ std::vector<Real> x(n);
+ std::vector<Real> y(n);
+ std::default_random_engine rd;
+ std::uniform_real_distribution<Real> dis(0,1);
+ Real x0 = dis(rd);
+ x[0] = x0;
+ y[0] = dis(rd);
+ for (size_t i = 1; i < n; ++i) {
+ x[i] = x[i-1] + dis(rd);
+ y[i] = dis(rd);
+ }
+
+ auto x_copy = x;
+ auto y_copy = y;
+ auto s = makima(std::move(x_copy), std::move(y_copy));
+ //std::cout << "s = " << s << "\n";
+ for (size_t i = 0; i < x.size(); ++i) {
+ CHECK_ULP_CLOSE(y[i], s(x[i]), 2);
+ }
+
+ x_copy = x;
+ y_copy = y;
+ // The interpolation condition is not affected by the endpoint derivatives, even though these derivatives might be super weird:
+ s = makima(std::move(x_copy), std::move(y_copy), Real(0), Real(0));
+ //std::cout << "s = " << s << "\n";
+ for (size_t i = 0; i < x.size(); ++i) {
+ CHECK_ULP_CLOSE(y[i], s(x[i]), 2);
+ }
+
+ }
+}
+
+int main()
+{
+ test_constant<float>();
+ test_linear<float>();
+ test_interpolation_condition<float>();
+
+ test_constant<double>();
+ test_linear<double>();
+ test_interpolation_condition<double>();
+
+ test_constant<long double>();
+ test_linear<long double>();
+ test_interpolation_condition<long double>();
+
+#ifdef BOOST_HAS_FLOAT128
+ test_constant<float128>();
+ test_linear<float128>();
+#endif
+
+ return boost::math::test::report_errors();
+}