]>
Commit | Line | Data |
---|---|---|
1e59de90 TL |
1 | /////////////////////////////////////////////////////////////// |
2 | // Copyright 2021 John Maddock. Distributed under the Boost | |
3 | // Software License, Version 1.0. (See accompanying file | |
4 | // LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt | |
5 | // | |
6 | ||
7 | #ifdef _MSC_VER | |
8 | #define _SCL_SECURE_NO_WARNINGS | |
9 | #endif | |
10 | ||
11 | #include <thread> | |
12 | #include <boost/detail/lightweight_test.hpp> | |
13 | #include <boost/array.hpp> | |
14 | #include <boost/math/special_functions/relative_difference.hpp> | |
15 | #include <boost/math/special_functions/gamma.hpp> | |
16 | #include <boost/math/quadrature/tanh_sinh.hpp> | |
17 | #include "test.hpp" | |
18 | ||
19 | #if !defined(TEST_MPF) && !defined(TEST_MPFR) && !defined(TEST_MPFI) && !defined(TEST_MPC) | |
20 | #define TEST_MPF | |
21 | #define TEST_MPFR | |
22 | #define TEST_MPFI | |
23 | #define TEST_MPC | |
24 | ||
25 | #ifdef _MSC_VER | |
26 | #pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") | |
27 | #endif | |
28 | #ifdef __GNUC__ | |
29 | #pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" | |
30 | #endif | |
31 | ||
32 | #endif | |
33 | ||
34 | #include <boost/multiprecision/gmp.hpp> | |
35 | #include <boost/multiprecision/cpp_int.hpp> | |
36 | #include <boost/multiprecision/cpp_bin_float.hpp> | |
37 | #include <boost/multiprecision/cpp_dec_float.hpp> | |
38 | ||
39 | #if defined(TEST_MPFR) | |
40 | #include <boost/multiprecision/mpfr.hpp> | |
41 | #endif | |
42 | #if defined(TEST_MPFI) | |
43 | #include <boost/multiprecision/mpfi.hpp> | |
44 | #endif | |
45 | #if defined(TEST_MPC) | |
46 | #include <boost/multiprecision/mpc.hpp> | |
47 | #endif | |
48 | ||
49 | template <class T> | |
50 | T new_value() | |
51 | { | |
52 | return T("0.1"); | |
53 | } | |
54 | ||
55 | template <class Other> | |
56 | Other make_other_big_value() | |
57 | { | |
58 | if constexpr (std::numeric_limits<Other>::is_integer && !std::numeric_limits<Other>::is_bounded) | |
59 | return (Other(1) << 1000) + 1; | |
60 | else if constexpr (!std::numeric_limits<Other>::is_integer && std::numeric_limits<Other>::is_exact && (std::numeric_limits<Other>::max_exponent == std::numeric_limits<Other>::min_exponent)) | |
61 | { | |
62 | using value_type = typename Other::value_type; | |
63 | return Other(1) / ((value_type(1) << 1000) + 1); | |
64 | } | |
65 | else | |
66 | return (std::numeric_limits<Other>::max)(); | |
67 | } | |
68 | ||
69 | template <class T, class Other> | |
70 | void test_mixed() | |
71 | { | |
72 | T::thread_default_precision(10); | |
73 | T::thread_default_variable_precision_options(boost::multiprecision::variable_precision_options::preserve_target_precision); | |
74 | Other big_a(make_other_big_value<Other>()), big_b(make_other_big_value<Other>()), big_c(make_other_big_value<Other>()), big_d(make_other_big_value<Other>()); | |
75 | ||
76 | T a(big_a); | |
77 | BOOST_CHECK_EQUAL(a.precision(), 10); | |
78 | T b(std::move(big_d)); | |
79 | BOOST_CHECK_EQUAL(a.precision(), 10); | |
80 | if constexpr (std::is_assignable_v<T, Other>) | |
81 | { | |
82 | a = big_b; | |
83 | BOOST_CHECK_EQUAL(a.precision(), 10); | |
84 | b = std::move(big_c); | |
85 | BOOST_CHECK_EQUAL(a.precision(), 10); | |
86 | ||
87 | if constexpr (!std::is_assignable_v<Other, T>) | |
88 | { | |
89 | a = b + big_a; | |
90 | BOOST_CHECK_EQUAL(a.precision(), 10); | |
91 | a = b * big_a; | |
92 | BOOST_CHECK_EQUAL(a.precision(), 10); | |
93 | a = b - big_a; | |
94 | BOOST_CHECK_EQUAL(a.precision(), 10); | |
95 | a = b / big_a; | |
96 | BOOST_CHECK_EQUAL(a.precision(), 10); | |
97 | a += big_a; | |
98 | BOOST_CHECK_EQUAL(a.precision(), 10); | |
99 | a -= big_a; | |
100 | BOOST_CHECK_EQUAL(a.precision(), 10); | |
101 | a *= big_a; | |
102 | BOOST_CHECK_EQUAL(a.precision(), 10); | |
103 | a /= big_a; | |
104 | BOOST_CHECK_EQUAL(a.precision(), 10); | |
105 | } | |
106 | } | |
107 | if constexpr (!std::is_same_v<T, typename T::value_type>) | |
108 | { | |
109 | T cc(big_a, big_b); | |
110 | BOOST_CHECK_EQUAL(cc.precision(), 10); | |
111 | T dd(big_a, big_b, 55); | |
112 | BOOST_CHECK_EQUAL(dd.precision(), 55); | |
113 | T aa = new_value<T>(); | |
114 | BOOST_CHECK_EQUAL(aa.precision(), 10); | |
115 | aa.assign(big_a); | |
116 | BOOST_CHECK_EQUAL(aa.precision(), 10); | |
117 | aa.assign(big_a, big_b); | |
118 | BOOST_CHECK_EQUAL(aa.precision(), 10); | |
119 | if constexpr (0 && std::is_constructible_v<T, Other, Other, int>) | |
120 | { | |
121 | aa.assign(big_a, big_b, 55); | |
122 | BOOST_CHECK_EQUAL(aa.precision(), 55); | |
123 | } | |
124 | } | |
125 | else | |
126 | { | |
127 | if constexpr (std::is_constructible_v<T, Other, int>) | |
128 | { | |
129 | T aa(big_a, 55); | |
130 | BOOST_CHECK_EQUAL(aa.precision(), 55); | |
131 | aa.precision(10); | |
132 | BOOST_CHECK_EQUAL(aa.precision(), 10); | |
133 | aa.assign(big_a); | |
134 | BOOST_CHECK_EQUAL(aa.precision(), 10); | |
135 | aa.assign(big_a, 55); | |
136 | BOOST_CHECK_EQUAL(aa.precision(), 55); | |
137 | } | |
138 | else | |
139 | { | |
140 | T aa; | |
141 | BOOST_CHECK_EQUAL(aa.precision(), 10); | |
142 | aa.assign(big_a); | |
143 | BOOST_CHECK_EQUAL(aa.precision(), 10); | |
144 | } | |
145 | } | |
146 | } | |
147 | ||
148 | template <class T> | |
149 | void test() | |
150 | { | |
151 | T::thread_default_precision(100); | |
152 | T::thread_default_variable_precision_options(boost::multiprecision::variable_precision_options::preserve_target_precision); | |
153 | ||
154 | T hp1("0.1"), hp2("0.3"), hp3("0.11"), hp4("0.1231"); | |
155 | ||
156 | BOOST_CHECK_EQUAL(hp1.precision(), 100); | |
157 | BOOST_CHECK_EQUAL(hp2.precision(), 100); | |
158 | ||
159 | T::thread_default_precision(35); | |
160 | ||
161 | T a(hp1); | |
162 | BOOST_CHECK_EQUAL(a.precision(), 35); | |
163 | a = hp1; | |
164 | BOOST_CHECK_EQUAL(a.precision(), 35); | |
165 | a = std::move(hp1); | |
166 | BOOST_CHECK_EQUAL(a.precision(), 35); | |
167 | T b(std::move(hp2)); | |
168 | BOOST_CHECK_EQUAL(b.precision(), 35); | |
169 | ||
170 | a = b + hp3; | |
171 | BOOST_CHECK_EQUAL(a.precision(), 35); | |
172 | a = hp3 * b; | |
173 | BOOST_CHECK_EQUAL(a.precision(), 35); | |
174 | a += hp3; | |
175 | BOOST_CHECK_EQUAL(a.precision(), 35); | |
176 | a *= hp4; | |
177 | BOOST_CHECK_EQUAL(a.precision(), 35); | |
178 | a -= b * hp3; | |
179 | BOOST_CHECK_EQUAL(a.precision(), 35); | |
180 | ||
181 | if constexpr (!std::is_same_v<T, typename T::value_type>) | |
182 | { | |
183 | // | |
184 | // If we have a component type: ie we are an interval or a complex number, then | |
185 | // operations involving the component type should match those of T: | |
186 | // | |
187 | using component_t = typename T::value_type; | |
188 | component_t::thread_default_precision(100); | |
189 | component_t::thread_default_variable_precision_options(boost::multiprecision::variable_precision_options::preserve_source_precision); | |
190 | ||
191 | component_t cp1("0.1"), cp2("0.3"), cp3("0.11"), cp4("0.1231"); | |
192 | ||
193 | BOOST_CHECK_EQUAL(cp1.precision(), 100); | |
194 | BOOST_CHECK_EQUAL(cp2.precision(), 100); | |
195 | ||
196 | T::thread_default_precision(35); | |
197 | ||
198 | T aa(cp1); | |
199 | BOOST_CHECK_EQUAL(aa.precision(), 35); | |
200 | T cc(cp1, cp2); | |
201 | BOOST_CHECK_EQUAL(cc.precision(), 35); | |
202 | T dd(cp1, cp2, 20); | |
203 | BOOST_CHECK_EQUAL(dd.precision(), 20); | |
204 | aa = cp1; | |
205 | BOOST_CHECK_EQUAL(aa.precision(), 35); | |
206 | aa = std::move(cp1); | |
207 | BOOST_CHECK_EQUAL(aa.precision(), 35); | |
208 | T bb(std::move(cp2)); | |
209 | BOOST_CHECK_EQUAL(bb.precision(), 35); | |
210 | ||
211 | aa = bb + cp3; | |
212 | BOOST_CHECK_EQUAL(aa.precision(), 35); | |
213 | aa = cp3 * bb; | |
214 | BOOST_CHECK_EQUAL(aa.precision(), 35); | |
215 | aa += cp3; | |
216 | BOOST_CHECK_EQUAL(aa.precision(), 35); | |
217 | aa -= cp3; | |
218 | BOOST_CHECK_EQUAL(aa.precision(), 35); | |
219 | aa *= cp4; | |
220 | BOOST_CHECK_EQUAL(aa.precision(), 35); | |
221 | aa /= cp4; | |
222 | BOOST_CHECK_EQUAL(aa.precision(), 35); | |
223 | aa -= bb * cp3; | |
224 | BOOST_CHECK_EQUAL(aa.precision(), 35); | |
225 | ||
226 | aa.assign(cp1); | |
227 | BOOST_CHECK_EQUAL(aa.precision(), 35); | |
228 | aa.assign(cp1, cp2); | |
229 | BOOST_CHECK_EQUAL(aa.precision(), 35); | |
230 | aa.assign(cp1, cp2, 20); | |
231 | BOOST_CHECK_EQUAL(aa.precision(), 20); | |
232 | } | |
233 | else | |
234 | { | |
235 | T aa(hp4, 20); | |
236 | BOOST_CHECK_EQUAL(aa.precision(), 20); | |
237 | aa.precision(35); | |
238 | aa.assign(hp4); | |
239 | BOOST_CHECK_EQUAL(aa.precision(), 35); | |
240 | aa.assign(hp4, 20); | |
241 | BOOST_CHECK_EQUAL(aa.precision(), 20); | |
242 | } | |
243 | ||
244 | test_mixed<T, char>(); | |
245 | test_mixed<T, unsigned char>(); | |
246 | test_mixed<T, signed char>(); | |
247 | test_mixed<T, short>(); | |
248 | test_mixed<T, unsigned short>(); | |
249 | test_mixed<T, int>(); | |
250 | test_mixed<T, unsigned int>(); | |
251 | test_mixed<T, long>(); | |
252 | test_mixed<T, unsigned long>(); | |
253 | test_mixed<T, long long>(); | |
254 | test_mixed<T, unsigned long long>(); | |
255 | test_mixed<T, float>(); | |
256 | test_mixed<T, double>(); | |
257 | test_mixed<T, long double>(); | |
258 | // | |
259 | // Test with other compatible multiprecision types: | |
260 | // | |
261 | test_mixed<T, boost::multiprecision::mpz_int>(); | |
262 | test_mixed<T, boost::multiprecision::cpp_int>(); | |
263 | test_mixed<T, boost::multiprecision::mpq_rational>(); | |
264 | test_mixed<T, boost::multiprecision::cpp_rational>(); | |
265 | test_mixed<T, boost::multiprecision::cpp_bin_float_100>(); | |
266 | test_mixed<T, boost::multiprecision::cpp_dec_float_100>(); | |
267 | test_mixed<T, boost::multiprecision::mpf_float_100>(); | |
268 | #if defined(TEST_MPFR) || defined(TEST_MPC) || defined(TEST_MPFI) | |
269 | test_mixed<T, boost::multiprecision::mpfr_float_100>(); | |
270 | #endif | |
271 | } | |
272 | ||
273 | int main() | |
274 | { | |
275 | #ifdef TEST_MPF | |
276 | test<boost::multiprecision::mpf_float>(); | |
277 | test<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off>>(); | |
278 | #endif | |
279 | #ifdef TEST_MPFR | |
280 | test<boost::multiprecision::mpfr_float>(); | |
281 | test<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, boost::multiprecision::et_off> >(); | |
282 | #endif | |
283 | #ifdef TEST_MPFI | |
284 | test<boost::multiprecision::mpfi_float>(); | |
285 | test<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, boost::multiprecision::et_off> >(); | |
286 | #endif | |
287 | #ifdef TEST_MPC | |
288 | test<boost::multiprecision::mpc_complex>(); | |
289 | test<boost::multiprecision::number<boost::multiprecision::mpc_complex_backend<0>, boost::multiprecision::et_off> >(); | |
290 | #endif | |
291 | return boost::report_errors(); | |
292 | } |