]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/math/test/simple_continued_fraction_test.cpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / libs / math / test / simple_continued_fraction_test.cpp
CommitLineData
20effc67
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 <boost/math/tools/simple_continued_fraction.hpp>
10#include <boost/math/constants/constants.hpp>
1e59de90 11#include <boost/core/demangle.hpp>
20effc67
TL
12#ifdef BOOST_HAS_FLOAT128
13#include <boost/multiprecision/float128.hpp>
14using boost::multiprecision::float128;
15#endif
16#include <boost/multiprecision/cpp_bin_float.hpp>
17
18using boost::math::tools::simple_continued_fraction;
19using boost::multiprecision::cpp_bin_float_100;
20using boost::math::constants::pi;
21
22template<class Real>
23void test_integral()
24{
25 for (int64_t i = -20; i < 20; ++i) {
26 Real ii = i;
27 auto cfrac = simple_continued_fraction<Real>(ii);
28 auto const & a = cfrac.partial_denominators();
29 CHECK_EQUAL(size_t(1), a.size());
30 CHECK_EQUAL(i, a.front());
31 }
32}
33
34template<class Real>
35void test_halves()
36{
37 for (int64_t i = -20; i < 20; ++i) {
38 Real x = i + Real(1)/Real(2);
39 auto cfrac = simple_continued_fraction<Real>(x);
40 auto const & a = cfrac.partial_denominators();
41 CHECK_EQUAL(size_t(2), a.size());
42 CHECK_EQUAL(i, a.front());
43 CHECK_EQUAL(int64_t(2), a.back());
44 }
45
46 // We'll also test quarters; why not?
47 for (int64_t i = -20; i < 20; ++i) {
48 Real x = i + Real(1)/Real(4);
49 auto cfrac = simple_continued_fraction<Real>(x);
50 auto const & a = cfrac.partial_denominators();
51 CHECK_EQUAL(size_t(2), a.size());
52 CHECK_EQUAL(i, a.front());
53 CHECK_EQUAL(int64_t(4), a.back());
54 }
55
56 for (int64_t i = -20; i < 20; ++i) {
57 Real x = i + Real(1)/Real(8);
58 auto cfrac = simple_continued_fraction<Real>(x);
59 auto const & a = cfrac.partial_denominators();
60 CHECK_EQUAL(size_t(2), a.size());
61 CHECK_EQUAL(i, a.front());
62 CHECK_EQUAL(int64_t(8), a.back());
63 }
64
65 for (int64_t i = -20; i < 20; ++i) {
66 Real x = i + Real(3)/Real(4);
67 auto cfrac = simple_continued_fraction<Real>(x);
68 auto const & a = cfrac.partial_denominators();
69 CHECK_EQUAL(size_t(3), a.size());
70 CHECK_EQUAL(i, a.front());
71 CHECK_EQUAL(int64_t(1), a[1]);
72 CHECK_EQUAL(int64_t(3), a.back());
73 }
74
75 for (int64_t i = -20; i < 20; ++i) {
76 Real x = i + Real(7)/Real(8);
77 auto cfrac = simple_continued_fraction<Real>(x);
78 auto const & a = cfrac.partial_denominators();
79 CHECK_EQUAL(size_t(3), a.size());
80 CHECK_EQUAL(i, a.front());
81 CHECK_EQUAL(int64_t(1), a[1]);
82 CHECK_EQUAL(int64_t(7), a.back());
83 }
84}
85
86template<typename Real>
87void test_simple()
88{
89 std::cout << "Testing rational numbers on type " << boost::core::demangle(typeid(Real).name()) << "\n";
90 {
91 Real x = Real(649)/200;
92 // ContinuedFraction[649/200] = [3; 4, 12, 4]
93 auto cfrac = simple_continued_fraction(x);
94 auto const & a = cfrac.partial_denominators();
95 CHECK_EQUAL(size_t(4), a.size());
96 CHECK_EQUAL(int64_t(3), a[0]);
97 CHECK_EQUAL(int64_t(4), a[1]);
98 CHECK_EQUAL(int64_t(12), a[2]);
99 CHECK_EQUAL(int64_t(4), a[3]);
100 }
101
102 {
103 Real x = Real(415)/Real(93);
104 // [4; 2, 6, 7]:
105 auto cfrac = simple_continued_fraction(x);
106 auto const & a = cfrac.partial_denominators();
107 CHECK_EQUAL(size_t(4), a.size());
108 CHECK_EQUAL(int64_t(4), a[0]);
109 CHECK_EQUAL(int64_t(2), a[1]);
110 CHECK_EQUAL(int64_t(6), a[2]);
111 CHECK_EQUAL(int64_t(7), a[3]);
112 }
113
114}
115
116template<typename Real>
117void test_khinchin()
118{
119 // These are simply sanity checks; the convergence is too slow otherwise:
120 auto cfrac = simple_continued_fraction(pi<Real>());
121 auto K0 = cfrac.khinchin_geometric_mean();
122 CHECK_MOLLIFIED_CLOSE(Real(2.6854520010), K0, 0.1);
123 auto Km1 = cfrac.khinchin_harmonic_mean();
124 CHECK_MOLLIFIED_CLOSE(Real(1.74540566240), Km1, 0.1);
125
126 using std::sqrt;
127 auto rt_cfrac = simple_continued_fraction(sqrt(static_cast<Real>(2)));
128 K0 = rt_cfrac.khinchin_geometric_mean();
129 CHECK_ULP_CLOSE(Real(2), K0, 10);
130 Km1 = rt_cfrac.khinchin_harmonic_mean();
131 CHECK_ULP_CLOSE(Real(2), Km1, 10);
132}
133
134
135int main()
136{
137 test_integral<float>();
138 test_integral<double>();
139 test_integral<long double>();
140 test_integral<cpp_bin_float_100>();
141
142 test_halves<float>();
143 test_halves<double>();
144 test_halves<long double>();
145 test_halves<cpp_bin_float_100>();
146
147 test_simple<float>();
148 test_simple<double>();
149 test_simple<long double>();
150 test_simple<cpp_bin_float_100>();
151
152 test_khinchin<cpp_bin_float_100>();
153
154 #ifdef BOOST_HAS_FLOAT128
155 test_integral<float128>();
156 test_halves<float128>();
157 test_simple<float128>();
158 test_khinchin<float128>();
159 #endif
160 return boost::math::test::report_errors();
161}