]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/math/test/septic_hermite_test.cpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / libs / math / test / septic_hermite_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 <array>
12#include <boost/random/uniform_real.hpp>
13#include <boost/random/mersenne_twister.hpp>
14#include <boost/math/interpolators/septic_hermite.hpp>
15#include <boost/math/special_functions/next.hpp>
16#ifdef BOOST_HAS_FLOAT128
17#include <boost/multiprecision/float128.hpp>
18using boost::multiprecision::float128;
19#endif
20
21
22using boost::math::interpolators::septic_hermite;
23using boost::math::interpolators::cardinal_septic_hermite;
24using boost::math::interpolators::cardinal_septic_hermite_aos;
25
26template<typename Real>
27void test_constant()
28{
29
30 std::vector<Real> x{0,1,2,3, 9, 22, 81};
31 std::vector<Real> y(x.size());
32 std::vector<Real> dydx(x.size(), 0);
33 std::vector<Real> d2ydx2(x.size(), 0);
34 std::vector<Real> d3ydx3(x.size(), 0);
35 for (auto & t : y)
36 {
37 t = 7;
38 }
39
40 auto sh = septic_hermite(std::move(x), std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3));
41
42 for (Real t = 0; t <= 81; t += 0.25)
43 {
44 CHECK_ULP_CLOSE(Real(7), sh(t), 24);
45 CHECK_ULP_CLOSE(Real(0), sh.prime(t), 24);
46 }
47
48 Real x0 = 0;
49 Real dx = 1;
50 y.resize(128, 7);
51 dydx.resize(128, 0);
52 d2ydx2.resize(128, 0);
53 d3ydx3.resize(128, 0);
54 auto csh = cardinal_septic_hermite(std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3), x0, dx);
55 for (Real t = x0; t <= 127; t += 0.25)
56 {
57 CHECK_ULP_CLOSE(Real(7), csh(t), 24);
58 CHECK_ULP_CLOSE(Real(0), csh.prime(t), 24);
59 CHECK_ULP_CLOSE(Real(0), csh.double_prime(t), 24);
60 }
61
62 std::vector<std::array<Real, 4>> data(128);
63 for (size_t i = 0; i < data.size(); ++i)
64 {
65 data[i][0] = 7;
66 data[i][1] = 0;
67 data[i][2] = 0;
68 data[i][3] = 0;
69 }
70 auto csh_aos = cardinal_septic_hermite_aos(std::move(data), x0, dx);
71 for (Real t = x0; t <= 127; t += 0.25)
72 {
73 CHECK_ULP_CLOSE(Real(7), csh_aos(t), 24);
74 CHECK_ULP_CLOSE(Real(0), csh_aos.prime(t), 24);
75 CHECK_ULP_CLOSE(Real(0), csh_aos.double_prime(t), 24);
76 }
77
78 // Now check the boundaries:
79 auto [tlo, thi] = csh.domain();
80 int samples = 5000;
81 int i = 0;
82 while (i++ < samples)
83 {
84 CHECK_ULP_CLOSE(Real(7), csh(tlo), 2);
85 CHECK_ULP_CLOSE(Real(7), csh(thi), 2);
86 CHECK_ULP_CLOSE(Real(7), csh_aos(tlo), 2);
87 CHECK_ULP_CLOSE(Real(7), csh_aos(thi), 2);
88 CHECK_ULP_CLOSE(Real(0), csh.prime(tlo), 2);
89 CHECK_ULP_CLOSE(Real(0), csh.prime(thi), 2);
90 CHECK_ULP_CLOSE(Real(0), csh_aos.prime(tlo), 2);
91 CHECK_ULP_CLOSE(Real(0), csh_aos.prime(thi), 2);
92 CHECK_ULP_CLOSE(Real(0), csh.double_prime(tlo), 2);
93 CHECK_ULP_CLOSE(Real(0), csh.double_prime(thi), 2);
94 CHECK_ULP_CLOSE(Real(0), csh_aos.double_prime(tlo), 2);
95 CHECK_ULP_CLOSE(Real(0), csh_aos.double_prime(thi), 2);
96
1e59de90 97 tlo = boost::math::nextafter(tlo, (std::numeric_limits<Real>::max)());
f67539c2
TL
98 thi = boost::math::nextafter(thi, std::numeric_limits<Real>::lowest());
99 }
100
101}
102
103
104template<typename Real>
105void test_linear()
106{
107 std::vector<Real> x{0,1,2,3,4,5,6,7,8,9};
108 std::vector<Real> y = x;
109 std::vector<Real> dydx(x.size(), 1);
110 std::vector<Real> d2ydx2(x.size(), 0);
111 std::vector<Real> d3ydx3(x.size(), 0);
112
113 auto sh = septic_hermite(std::move(x), std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3));
114
115 for (Real t = 0; t <= 9; t += 0.25)
116 {
117 CHECK_ULP_CLOSE(Real(t), sh(t), 2);
118 CHECK_ULP_CLOSE(Real(1), sh.prime(t), 2);
119 }
120
121 boost::random::mt19937 rng;
122 boost::random::uniform_real_distribution<Real> dis(0.5,1);
123 x.resize(512);
124 x[0] = dis(rng);
125 Real xmin = x[0];
126 for (size_t i = 1; i < x.size(); ++i)
127 {
128 x[i] = x[i-1] + dis(rng);
129 }
130 Real xmax = x.back();
131
132 y = x;
133 dydx.resize(x.size(), 1);
134 d2ydx2.resize(x.size(), 0);
135 d3ydx3.resize(x.size(), 0);
136
137 sh = septic_hermite(std::move(x), std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3));
138
139 for (Real t = xmin; t <= xmax; t += 0.125)
140 {
141 CHECK_ULP_CLOSE(t, sh(t), 25);
142 CHECK_ULP_CLOSE(Real(1), sh.prime(t), 850);
143 }
144
145 Real x0 = 0;
146 Real dx = 1;
147 y.resize(10);
148 dydx.resize(10, 1);
149 d2ydx2.resize(10, 0);
150 d3ydx3.resize(10, 0);
151 for (size_t i = 0; i < y.size(); ++i)
152 {
153 y[i] = i;
154 }
155 auto csh = cardinal_septic_hermite(std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3), x0, dx);
156 for (Real t = 0; t <= 9; t += 0.125)
157 {
158 CHECK_ULP_CLOSE(t, csh(t), 15);
159 CHECK_ULP_CLOSE(Real(1), csh.prime(t), 15);
160 CHECK_ULP_CLOSE(Real(0), csh.double_prime(t), 15);
161 }
162
163 std::vector<std::array<Real, 4>> data(10);
164 for (size_t i = 0; i < data.size(); ++i)
165 {
166 data[i][0] = i;
167 data[i][1] = 1;
168 data[i][2] = 0;
169 data[i][3] = 0;
170 }
171 auto csh_aos = cardinal_septic_hermite_aos(std::move(data), x0, dx);
172 for (Real t = 0; t <= 9; t += 0.125)
173 {
174 CHECK_ULP_CLOSE(t, csh_aos(t), 15);
175 CHECK_ULP_CLOSE(Real(1), csh_aos.prime(t), 15);
176 CHECK_ULP_CLOSE(Real(0), csh_aos.double_prime(t), 15);
177 }
178
179 // Now check the boundaries:
180 auto [tlo, thi] = csh.domain();
181 int samples = 5000;
182 int i = 0;
183 while (i++ < samples)
184 {
185 CHECK_ULP_CLOSE(Real(tlo), csh(tlo), 2);
186 CHECK_ULP_CLOSE(Real(thi), csh(thi), 8);
187 CHECK_ULP_CLOSE(Real(tlo), csh_aos(tlo), 2);
188 CHECK_ULP_CLOSE(Real(thi), csh_aos(thi), 8);
189 CHECK_ULP_CLOSE(Real(1), csh.prime(tlo), 2);
190 CHECK_ULP_CLOSE(Real(1), csh.prime(thi), 700);
191 CHECK_ULP_CLOSE(Real(1), csh_aos.prime(tlo), 2);
192 CHECK_ULP_CLOSE(Real(1), csh_aos.prime(thi), 700);
193 CHECK_MOLLIFIED_CLOSE(Real(0), csh.double_prime(tlo), std::numeric_limits<Real>::epsilon());
194 CHECK_MOLLIFIED_CLOSE(Real(0), csh.double_prime(thi), 1200*std::numeric_limits<Real>::epsilon());
195 CHECK_MOLLIFIED_CLOSE(Real(0), csh_aos.double_prime(tlo), std::numeric_limits<Real>::epsilon());
196 CHECK_MOLLIFIED_CLOSE(Real(0), csh_aos.double_prime(thi), 1200*std::numeric_limits<Real>::epsilon());
197
1e59de90 198 tlo = boost::math::nextafter(tlo, (std::numeric_limits<Real>::max)());
f67539c2
TL
199 thi = boost::math::nextafter(thi, std::numeric_limits<Real>::lowest());
200 }
201
202}
203
204template<typename Real>
205void test_quadratic()
206{
207 std::vector<Real> x{0,1,2,3,4,5,6,7,8,9};
208 std::vector<Real> y(x.size());
209 for (size_t i = 0; i < y.size(); ++i)
210 {
211 y[i] = x[i]*x[i]/2;
212 }
213
214 std::vector<Real> dydx(x.size());
215 for (size_t i = 0; i < y.size(); ++i)
216 {
217 dydx[i] = x[i];
218 }
219
220 std::vector<Real> d2ydx2(x.size(), 1);
221 std::vector<Real> d3ydx3(x.size(), 0);
222
223 auto sh = septic_hermite(std::move(x), std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3));
224
225 for (Real t = 0; t <= 9; t += 0.0078125)
226 {
227 CHECK_ULP_CLOSE(t*t/2, sh(t), 100);
228 CHECK_ULP_CLOSE(t, sh.prime(t), 32);
229 }
230
231 boost::random::mt19937 rng;
232 boost::random::uniform_real_distribution<Real> dis(0.5,1);
233 x.resize(8);
234 x[0] = dis(rng);
235 Real xmin = x[0];
236 for (size_t i = 1; i < x.size(); ++i)
237 {
238 x[i] = x[i-1] + dis(rng);
239 }
240 Real xmax = x.back();
241
242 y.resize(x.size());
243 for (size_t i = 0; i < y.size(); ++i)
244 {
245 y[i] = x[i]*x[i]/2;
246 }
247
248 dydx.resize(x.size());
249 for (size_t i = 0; i < y.size(); ++i)
250 {
251 dydx[i] = x[i];
252 }
253
254 d2ydx2.resize(x.size(), 1);
255 d3ydx3.resize(x.size(), 0);
256
257 sh = septic_hermite(std::move(x), std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3));
258
259 for (Real t = xmin; t <= xmax; t += 0.125)
260 {
261 CHECK_ULP_CLOSE(t*t/2, sh(t), 50);
262 CHECK_ULP_CLOSE(t, sh.prime(t), 300);
263 }
264
265 y.resize(10);
266 for (size_t i = 0; i < y.size(); ++i)
267 {
268 y[i] = i*i/Real(2);
269 }
270
271 dydx.resize(y.size());
272 for (size_t i = 0; i < y.size(); ++i)
273 {
274 dydx[i] = i;
275 }
276
277 d2ydx2.resize(y.size(), 1);
278 d3ydx3.resize(y.size(), 0);
279
280 Real x0 = 0;
281 Real dx = 1;
282 auto csh = cardinal_septic_hermite(std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3), x0, dx);
283 for (Real t = x0; t <= 9; t += 0.125)
284 {
285 CHECK_ULP_CLOSE(t*t/2, csh(t), 24);
286 CHECK_ULP_CLOSE(t, csh.prime(t), 24);
287 CHECK_ULP_CLOSE(Real(1), csh.double_prime(t), 24);
288 }
289
290 std::vector<std::array<Real, 4>> data(10);
291 for (size_t i = 0; i < data.size(); ++i)
292 {
293 data[i][0] = i*i/Real(2);
294 data[i][1] = i;
295 data[i][2] = 1;
296 data[i][3] = 0;
297 }
298 auto csh_aos = cardinal_septic_hermite_aos(std::move(data), x0, dx);
299 for (Real t = x0; t <= 9; t += 0.125)
300 {
301 CHECK_ULP_CLOSE(t*t/2, csh_aos(t), 24);
302 CHECK_ULP_CLOSE(t, csh_aos.prime(t), 24);
303 CHECK_ULP_CLOSE(Real(1), csh_aos.double_prime(t), 24);
304 }
305}
306
307
308
309template<typename Real>
310void test_cubic()
311{
312
313 std::vector<Real> x{0,1,2,3,4,5,6,7};
314 Real xmax = x.back();
315 std::vector<Real> y(x.size());
316 for (size_t i = 0; i < y.size(); ++i)
317 {
318 y[i] = x[i]*x[i]*x[i];
319 }
320
321 std::vector<Real> dydx(x.size());
322 for (size_t i = 0; i < y.size(); ++i)
323 {
324 dydx[i] = 3*x[i]*x[i];
325 }
326
327 std::vector<Real> d2ydx2(x.size());
328 for (size_t i = 0; i < y.size(); ++i)
329 {
330 d2ydx2[i] = 6*x[i];
331 }
332 std::vector<Real> d3ydx3(x.size(), 6);
333
334 auto sh = septic_hermite(std::move(x), std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3));
335
336 for (Real t = 0; t <= xmax; t += 0.0078125)
337 {
338 CHECK_ULP_CLOSE(t*t*t, sh(t), 151);
339 CHECK_ULP_CLOSE(3*t*t, sh.prime(t), 151);
340 }
341
342 Real x0 = 0;
343 Real dx = 1;
344 y.resize(8);
345 dydx.resize(8);
346 d2ydx2.resize(8);
347 d3ydx3.resize(8,6);
348 for (size_t i = 0; i < y.size(); ++i)
349 {
350 y[i] = i*i*i;
351 dydx[i] = 3*i*i;
352 d2ydx2[i] = 6*i;
353 }
354
355 auto csh = cardinal_septic_hermite(std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3), x0, dx);
356
357 for (Real t = 0; t <= xmax; t += 0.0078125)
358 {
359 CHECK_ULP_CLOSE(t*t*t, csh(t), 151);
360 CHECK_ULP_CLOSE(3*t*t, csh.prime(t), 151);
361 CHECK_ULP_CLOSE(6*t, csh.double_prime(t), 151);
362 }
363
364 std::vector<std::array<Real, 4>> data(8);
365 for (size_t i = 0; i < data.size(); ++i) {
366 data[i][0] = i*i*i;
367 data[i][1] = 3*i*i;
368 data[i][2] = 6*i;
369 data[i][3] = 6;
370 }
371
372 auto csh_aos = cardinal_septic_hermite_aos(std::move(data), x0, dx);
373
374 for (Real t = 0; t <= xmax; t += 0.0078125)
375 {
376 CHECK_ULP_CLOSE(t*t*t, csh_aos(t), 151);
377 CHECK_ULP_CLOSE(3*t*t, csh_aos.prime(t), 151);
378 CHECK_ULP_CLOSE(6*t, csh_aos.double_prime(t), 151);
379 }
380}
381
382template<typename Real>
383void test_quartic()
384{
385
386 std::vector<Real> x{0,1,2,3,4,5,6,7,8,9};
387 Real xmax = x.back();
388 std::vector<Real> y(x.size());
389 for (size_t i = 0; i < y.size(); ++i)
390 {
391 y[i] = x[i]*x[i]*x[i]*x[i];
392 }
393
394 std::vector<Real> dydx(x.size());
395 for (size_t i = 0; i < y.size(); ++i)
396 {
397 dydx[i] = 4*x[i]*x[i]*x[i];
398 }
399
400 std::vector<Real> d2ydx2(x.size());
401 for (size_t i = 0; i < y.size(); ++i)
402 {
403 d2ydx2[i] = 12*x[i]*x[i];
404 }
405
406 std::vector<Real> d3ydx3(x.size());
407 for (size_t i = 0; i < y.size(); ++i)
408 {
409 d3ydx3[i] = 24*x[i];
410 }
411
412 auto sh = septic_hermite(std::move(x), std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3));
413
414 for (Real t = 1; t <= xmax; t += 0.0078125) {
415 CHECK_ULP_CLOSE(t*t*t*t, sh(t), 117);
416 CHECK_ULP_CLOSE(4*t*t*t, sh.prime(t), 117);
417 }
418
419 y.resize(10);
420 dydx.resize(10);
421 d2ydx2.resize(10);
422 d3ydx3.resize(10);
423 for (size_t i = 0; i < y.size(); ++i)
424 {
425 y[i] = i*i*i*i;
426 dydx[i] = 4*i*i*i;
427 d2ydx2[i] = 12*i*i;
428 d3ydx3[i] = 24*i;
429 }
430
431 auto csh = cardinal_septic_hermite(std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3), Real(0), Real(1));
432
433 for (Real t = 1; t <= xmax; t += 0.0078125)
434 {
435 CHECK_ULP_CLOSE(t*t*t*t, csh(t), 117);
436 CHECK_ULP_CLOSE(4*t*t*t, csh.prime(t), 117);
437 CHECK_ULP_CLOSE(12*t*t, csh.double_prime(t), 117);
438 }
439
440 std::vector<std::array<Real, 4>> data(10);
441 for (size_t i = 0; i < data.size(); ++i)
442 {
443 data[i][0] = i*i*i*i;
444 data[i][1] = 4*i*i*i;
445 data[i][2] = 12*i*i;
446 data[i][3] = 24*i;
447 }
448
449 auto csh_aos = cardinal_septic_hermite_aos(std::move(data), Real(0), Real(1));
450 for (Real t = 1; t <= xmax; t += 0.0078125)
451 {
452 CHECK_ULP_CLOSE(t*t*t*t, csh_aos(t), 117);
453 CHECK_ULP_CLOSE(4*t*t*t, csh_aos.prime(t), 117);
454 CHECK_ULP_CLOSE(12*t*t, csh_aos.double_prime(t), 117);
455 }
456}
457
458
459template<typename Real>
460void test_interpolation_condition()
461{
462 for (size_t n = 4; n < 50; ++n) {
463 std::vector<Real> x(n);
464 std::vector<Real> y(n);
465 std::vector<Real> dydx(n);
466 std::vector<Real> d2ydx2(n);
467 std::vector<Real> d3ydx3(n);
468 boost::random::mt19937 rd;
469 boost::random::uniform_real_distribution<Real> dis(0,1);
470 Real x0 = dis(rd);
471 x[0] = x0;
472 y[0] = dis(rd);
473 for (size_t i = 1; i < n; ++i) {
474 x[i] = x[i-1] + dis(rd);
475 y[i] = dis(rd);
476 dydx[i] = dis(rd);
477 d2ydx2[i] = dis(rd);
478 d3ydx3[i] = dis(rd);
479 }
480
481 auto x_copy = x;
482 auto y_copy = y;
483 auto dydx_copy = dydx;
484 auto d2ydx2_copy = d2ydx2;
485 auto d3ydx3_copy = d3ydx3;
486 auto s = septic_hermite(std::move(x_copy), std::move(y_copy), std::move(dydx_copy), std::move(d2ydx2_copy), std::move(d3ydx3_copy));
487
488 for (size_t i = 0; i < x.size(); ++i)
489 {
490 CHECK_ULP_CLOSE(y[i], s(x[i]), 2);
491 CHECK_ULP_CLOSE(dydx[i], s.prime(x[i]), 2);
492 }
493 }
494}
495
496
497int main()
498{
499 test_constant<float>();
500 test_linear<float>();
501 test_quadratic<float>();
502 test_cubic<float>();
503 test_quartic<float>();
504 test_interpolation_condition<float>();
505
506 test_constant<double>();
507 test_linear<double>();
508 test_quadratic<double>();
509 test_cubic<double>();
510 test_quartic<double>();
511 test_interpolation_condition<double>();
512
513 test_constant<long double>();
514 test_linear<long double>();
515 test_quadratic<long double>();
516 test_cubic<long double>();
517 test_quartic<long double>();
518 test_interpolation_condition<long double>();
519
520#ifdef BOOST_HAS_FLOAT128
521 test_constant<float128>();
522 test_linear<float128>();
523 test_quadratic<float128>();
524 test_cubic<float128>();
525 test_quartic<float128>();
526 test_interpolation_condition<float128>();
527#endif
528
529 return boost::math::test::report_errors();
530}