]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/math/test/pchip_test.cpp
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / boost / libs / math / test / pchip_test.cpp
CommitLineData
f67539c2
TL
1/*
2 * Copyright Nick Thompson, 2020
3 * Use, modification and distribution are subject to the
4 * Boost Software License, Version 1.0. (See accompanying file
5 * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 */
7
8#include "math_unit_test.hpp"
9#include <numeric>
10#include <utility>
11#include <random>
12#include <boost/math/interpolators/pchip.hpp>
13#include <boost/circular_buffer.hpp>
14#ifdef BOOST_HAS_FLOAT128
15#include <boost/multiprecision/float128.hpp>
16using boost::multiprecision::float128;
17#endif
18
19
20using boost::math::interpolators::pchip;
21
22template<typename Real>
23void test_constant()
24{
25
26 std::vector<Real> x{0,1,2,3, 9, 22, 81};
27 std::vector<Real> y(x.size());
28 for (auto & t : y) {
29 t = 7;
30 }
31
32 auto x_copy = x;
33 auto y_copy = y;
34 auto pchip_spline = pchip(std::move(x_copy), std::move(y_copy));
35 //std::cout << "Constant value pchip spline = " << pchip_spline << "\n";
36
37 for (Real t = x[0]; t <= x.back(); t += 0.25) {
38 CHECK_ULP_CLOSE(Real(7), pchip_spline(t), 2);
39 CHECK_ULP_CLOSE(Real(0), pchip_spline.prime(t), 2);
40 }
41
42 boost::circular_buffer<Real> x_buf(x.size());
43 for (auto & t : x) {
44 x_buf.push_back(t);
45 }
46
47 boost::circular_buffer<Real> y_buf(x.size());
48 for (auto & t : y) {
49 y_buf.push_back(t);
50 }
51
52 auto circular_pchip_spline = pchip(std::move(x_buf), std::move(y_buf));
53
54 for (Real t = x[0]; t <= x.back(); t += 0.25) {
55 CHECK_ULP_CLOSE(Real(7), circular_pchip_spline(t), 2);
56 CHECK_ULP_CLOSE(Real(0), pchip_spline.prime(t), 2);
57 }
58
59 circular_pchip_spline.push_back(x.back() + 1, 7);
60 CHECK_ULP_CLOSE(Real(0), circular_pchip_spline.prime(x.back()+1), 2);
61
62}
63
64template<typename Real>
65void test_linear()
66{
67 std::vector<Real> x{0,1,2,3};
68 std::vector<Real> y{0,1,2,3};
69
70 auto x_copy = x;
71 auto y_copy = y;
72 auto pchip_spline = pchip(std::move(x_copy), std::move(y_copy));
73
74 CHECK_ULP_CLOSE(y[0], pchip_spline(x[0]), 0);
75 CHECK_ULP_CLOSE(Real(1)/Real(2), pchip_spline(Real(1)/Real(2)), 10);
76 CHECK_ULP_CLOSE(y[1], pchip_spline(x[1]), 0);
77 CHECK_ULP_CLOSE(Real(3)/Real(2), pchip_spline(Real(3)/Real(2)), 10);
78 CHECK_ULP_CLOSE(y[2], pchip_spline(x[2]), 0);
79 CHECK_ULP_CLOSE(Real(5)/Real(2), pchip_spline(Real(5)/Real(2)), 10);
80 CHECK_ULP_CLOSE(y[3], pchip_spline(x[3]), 0);
81
82 x.resize(45);
83 y.resize(45);
84 for (size_t i = 0; i < x.size(); ++i) {
85 x[i] = i;
86 y[i] = i;
87 }
88
89 x_copy = x;
90 y_copy = y;
91 pchip_spline = pchip(std::move(x_copy), std::move(y_copy));
92 for (Real t = 0; t < x.back(); t += 0.5) {
93 CHECK_ULP_CLOSE(t, pchip_spline(t), 0);
94 CHECK_ULP_CLOSE(Real(1), pchip_spline.prime(t), 0);
95 }
96
97 x_copy = x;
98 y_copy = y;
99 // Test endpoint derivatives:
100 pchip_spline = pchip(std::move(x_copy), std::move(y_copy), Real(1), Real(1));
101 for (Real t = 0; t < x.back(); t += 0.5) {
102 CHECK_ULP_CLOSE(t, pchip_spline(t), 0);
103 CHECK_ULP_CLOSE(Real(1), pchip_spline.prime(t), 0);
104 }
105
106
107 boost::circular_buffer<Real> x_buf(x.size());
108 for (auto & t : x) {
109 x_buf.push_back(t);
110 }
111
112 boost::circular_buffer<Real> y_buf(x.size());
113 for (auto & t : y) {
114 y_buf.push_back(t);
115 }
116
117 auto circular_pchip_spline = pchip(std::move(x_buf), std::move(y_buf));
118
119 for (Real t = x[0]; t <= x.back(); t += 0.25) {
120 CHECK_ULP_CLOSE(t, circular_pchip_spline(t), 2);
121 CHECK_ULP_CLOSE(Real(1), circular_pchip_spline.prime(t), 2);
122 }
123
124 circular_pchip_spline.push_back(x.back() + 1, y.back()+1);
125
126 CHECK_ULP_CLOSE(Real(y.back() + 1), circular_pchip_spline(Real(x.back()+1)), 2);
127 CHECK_ULP_CLOSE(Real(1), circular_pchip_spline.prime(Real(x.back()+1)), 2);
128
129}
130
131template<typename Real>
132void test_interpolation_condition()
133{
134 for (size_t n = 4; n < 50; ++n) {
135 std::vector<Real> x(n);
136 std::vector<Real> y(n);
137 std::default_random_engine rd;
138 std::uniform_real_distribution<Real> dis(0,1);
139 Real x0 = dis(rd);
140 x[0] = x0;
141 y[0] = dis(rd);
142 for (size_t i = 1; i < n; ++i) {
143 x[i] = x[i-1] + dis(rd);
144 y[i] = dis(rd);
145 }
146
147 auto x_copy = x;
148 auto y_copy = y;
149 auto s = pchip(std::move(x_copy), std::move(y_copy));
150 //std::cout << "s = " << s << "\n";
151 for (size_t i = 0; i < x.size(); ++i) {
152 CHECK_ULP_CLOSE(y[i], s(x[i]), 2);
153 }
154
155 x_copy = x;
156 y_copy = y;
157 // The interpolation condition is not affected by the endpoint derivatives, even though these derivatives might be super weird:
158 s = pchip(std::move(x_copy), std::move(y_copy), Real(0), Real(0));
159 //std::cout << "s = " << s << "\n";
160 for (size_t i = 0; i < x.size(); ++i) {
161 CHECK_ULP_CLOSE(y[i], s(x[i]), 2);
162 }
163
164 }
165}
166
167template<typename Real>
168void test_monotonicity()
169{
170 for (size_t n = 4; n < 50; ++n) {
171 std::vector<Real> x(n);
172 std::vector<Real> y(n);
173 std::default_random_engine rd;
174 std::uniform_real_distribution<Real> dis(0,1);
175 Real x0 = dis(rd);
176 x[0] = x0;
177 y[0] = dis(rd);
178 // Monotone increasing:
179 for (size_t i = 1; i < n; ++i) {
180 x[i] = x[i-1] + dis(rd);
181 y[i] = y[i-1] + dis(rd);
182 }
183
184 auto x_copy = x;
185 auto y_copy = y;
186 auto s = pchip(std::move(x_copy), std::move(y_copy));
187 //std::cout << "s = " << s << "\n";
188 for (size_t i = 0; i < x.size() - 1; ++i) {
189 Real tmin = x[i];
190 Real tmax = x[i+1];
191 Real val = y[i];
192 CHECK_ULP_CLOSE(y[i], s(x[i]), 2);
193 for (Real t = tmin; t < tmax; t += (tmax-tmin)/16) {
194 Real greater_val = s(t);
195 assert(val <= greater_val);
196 val = greater_val;
197 }
198 }
199
200
201 x[0] = dis(rd);
202 y[0] = dis(rd);
203 // Monotone decreasing:
204 for (size_t i = 1; i < n; ++i) {
205 x[i] = x[i-1] + dis(rd);
206 y[i] = y[i-1] - dis(rd);
207 }
208
209 x_copy = x;
210 y_copy = y;
211 s = pchip(std::move(x_copy), std::move(y_copy));
212 //std::cout << "s = " << s << "\n";
213 for (size_t i = 0; i < x.size() - 1; ++i) {
214 Real tmin = x[i];
215 Real tmax = x[i+1];
216 Real val = y[i];
217 CHECK_ULP_CLOSE(y[i], s(x[i]), 2);
218 for (Real t = tmin; t < tmax; t += (tmax-tmin)/16) {
219 Real lesser_val = s(t);
220 assert(val >= lesser_val);
221 val = lesser_val;
222 }
223 }
224
225 }
226}
227
228
229int main()
230{
231 test_constant<float>();
232 test_linear<float>();
233 test_interpolation_condition<float>();
234 test_monotonicity<float>();
235
236 test_constant<double>();
237 test_linear<double>();
238 test_interpolation_condition<double>();
239 test_monotonicity<double>();
240
241 test_constant<long double>();
242 test_linear<long double>();
243 test_interpolation_condition<long double>();
244 test_monotonicity<long double>();
245
246#ifdef BOOST_HAS_FLOAT128
247 test_constant<float128>();
248 test_linear<float128>();
249#endif
250
251 return boost::math::test::report_errors();
252}