]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Copyright John Maddock 2012. |
2 | ||
3 | // Use, modification and distribution are subject to the | |
4 | // Boost Software License, Version 1.0. | |
5 | // (See accompanying file LICENSE_1_0.txt | |
6 | // or copy at http://www.boost.org/LICENSE_1_0.txt) | |
7 | ||
8 | #ifdef _MSC_VER | |
92f5a8d4 | 9 | #define _SCL_SECURE_NO_WARNINGS |
7c673cae FG |
10 | #endif |
11 | ||
12 | #include <boost/config.hpp> | |
13 | #include <vector> | |
14 | ||
92f5a8d4 TL |
15 | #if !defined(TEST_GMP) && !defined(TEST_MPFR) && !defined(TEST_TOMMATH) && !defined(TEST_CPP_INT) && !defined(TEST_MPC) |
16 | #define TEST_GMP | |
17 | #define TEST_MPFR | |
18 | #define TEST_TOMMATH | |
19 | #define TEST_CPP_INT | |
20 | #define TEST_MPC | |
7c673cae FG |
21 | |
22 | #ifdef _MSC_VER | |
23 | #pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") | |
24 | #endif | |
25 | #ifdef __GNUC__ | |
26 | #pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" | |
27 | #endif | |
28 | ||
29 | #endif | |
30 | ||
31 | #if defined(TEST_GMP) | |
32 | #include <boost/multiprecision/gmp.hpp> | |
33 | #endif | |
34 | #if defined(TEST_MPFR) | |
35 | #include <boost/multiprecision/mpfr.hpp> | |
36 | #endif | |
37 | #ifdef TEST_TOMMATH | |
38 | #include <boost/multiprecision/tommath.hpp> | |
39 | #endif | |
40 | #ifdef TEST_CPP_INT | |
41 | #include <boost/multiprecision/cpp_int.hpp> | |
42 | #endif | |
92f5a8d4 TL |
43 | #ifdef TEST_MPC |
44 | #include <boost/multiprecision/mpc.hpp> | |
45 | #endif | |
7c673cae FG |
46 | |
47 | #include "test.hpp" | |
48 | ||
49 | unsigned allocation_count = 0; | |
50 | ||
92f5a8d4 TL |
51 | void* (*alloc_func_ptr)(size_t); |
52 | void* (*realloc_func_ptr)(void*, size_t, size_t); | |
53 | void (*free_func_ptr)(void*, size_t); | |
7c673cae | 54 | |
92f5a8d4 | 55 | void* alloc_func(size_t n) |
7c673cae FG |
56 | { |
57 | ++allocation_count; | |
58 | return (*alloc_func_ptr)(n); | |
59 | } | |
60 | ||
92f5a8d4 | 61 | void free_func(void* p, size_t n) |
7c673cae FG |
62 | { |
63 | (*free_func_ptr)(p, n); | |
64 | } | |
65 | ||
92f5a8d4 | 66 | void* realloc_func(void* p, size_t old, size_t n) |
7c673cae FG |
67 | { |
68 | ++allocation_count; | |
69 | return (*realloc_func_ptr)(p, old, n); | |
70 | } | |
71 | ||
72 | template <class T> | |
73 | void do_something(const T&) | |
74 | { | |
75 | } | |
76 | ||
77 | template <class T> | |
78 | void test_std_lib() | |
79 | { | |
80 | std::vector<T> v; | |
92f5a8d4 | 81 | for (unsigned i = 0; i < 100; ++i) |
7c673cae FG |
82 | v.insert(v.begin(), i); |
83 | ||
84 | T a(2), b(3); | |
85 | std::swap(a, b); | |
86 | BOOST_TEST(a == 3); | |
87 | BOOST_TEST(b == 2); | |
88 | } | |
89 | ||
90 | template <class T, class A> | |
91 | void test_move_and_assign(T x, A val) | |
92 | { | |
93 | // move away from x, then assign val to x. | |
94 | T z(x); | |
95 | T y(std::move(x)); | |
96 | x.assign(val); | |
97 | BOOST_CHECK_EQUAL(x, T(val)); | |
98 | BOOST_CHECK_EQUAL(z, y); | |
99 | } | |
100 | ||
101 | template <class T> | |
102 | void test_move_and_assign() | |
103 | { | |
104 | T x(23); | |
105 | test_move_and_assign(x, static_cast<short>(2)); | |
106 | test_move_and_assign(x, static_cast<int>(2)); | |
107 | test_move_and_assign(x, static_cast<long>(2)); | |
108 | test_move_and_assign(x, static_cast<long long>(2)); | |
109 | test_move_and_assign(x, static_cast<unsigned short>(2)); | |
110 | test_move_and_assign(x, static_cast<unsigned int>(2)); | |
111 | test_move_and_assign(x, static_cast<unsigned long>(2)); | |
112 | test_move_and_assign(x, static_cast<unsigned long long>(2)); | |
113 | test_move_and_assign(x, static_cast<float>(2)); | |
114 | test_move_and_assign(x, static_cast<double>(2)); | |
115 | test_move_and_assign(x, static_cast<long double>(2)); | |
116 | test_move_and_assign(x, x); | |
117 | test_move_and_assign(x, "23"); | |
118 | } | |
119 | ||
7c673cae FG |
120 | int main() |
121 | { | |
122 | #if defined(TEST_MPFR) || defined(TEST_GMP) | |
92f5a8d4 TL |
123 | #if defined(MPFR_VERSION) && (MPFR_VERSION_MAJOR > 3) |
124 | mpfr_mp_memory_cleanup(); | |
125 | #endif | |
7c673cae FG |
126 | mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr); |
127 | mp_set_memory_functions(&alloc_func, &realloc_func, &free_func); | |
128 | #endif | |
129 | ||
130 | using namespace boost::multiprecision; | |
131 | ||
132 | #ifdef TEST_MPFR | |
133 | { | |
134 | test_std_lib<mpfr_float_50>(); | |
135 | mpfr_float_50 a = 2; | |
92f5a8d4 TL |
136 | if (allocation_count) |
137 | { | |
138 | // | |
139 | // We can only conduct meaningful tests if we're actually using our custom allocators, | |
140 | // there are some situations where mpfr-4.x doesn't call them even though we've | |
141 | // done everything requested to make them work.... | |
142 | // | |
143 | allocation_count = 0; | |
144 | mpfr_float_50 b = std::move(a); | |
145 | BOOST_TEST(allocation_count == 0); | |
146 | // | |
147 | // Move assign - we rely on knowledge of the internals to make this test work!! | |
148 | // | |
149 | mpfr_float_50 c(3); | |
150 | do_something(b); | |
151 | do_something(c); | |
152 | const void* p = b.backend().data()[0]._mpfr_d; | |
153 | BOOST_TEST(c.backend().data()[0]._mpfr_d != p); | |
154 | c = std::move(b); | |
155 | BOOST_TEST(c.backend().data()[0]._mpfr_d == p); | |
156 | BOOST_TEST(b.backend().data()[0]._mpfr_d != p); | |
157 | // | |
158 | // Again with variable precision, this we can test more easily: | |
159 | // | |
160 | mpfr_float d, e; | |
161 | d.precision(100); | |
162 | e.precision(1000); | |
163 | d = 2; | |
164 | e = 3; | |
165 | allocation_count = 0; | |
166 | BOOST_TEST(d == 2); | |
167 | d = std::move(e); | |
168 | BOOST_TEST(allocation_count == 0); | |
169 | BOOST_TEST(d == 3); | |
170 | e = 2; | |
171 | BOOST_TEST(e == 2); | |
172 | d = std::move(e); | |
173 | e = d; | |
174 | BOOST_TEST(e == d); | |
175 | ||
176 | test_move_and_assign<mpfr_float>(); | |
177 | test_move_and_assign<mpfr_float_50>(); | |
178 | } | |
179 | } | |
180 | #endif | |
181 | #ifdef TEST_MPC | |
182 | { | |
183 | test_std_lib<mpc_complex_50>(); | |
184 | mpc_complex_50 a = 2; | |
185 | if (allocation_count) | |
186 | { | |
187 | // | |
188 | // We can only conduct meaningful tests if we're actually using our custom allocators, | |
189 | // there are some situations where mpfr-4.x doesn't call them even though we've | |
190 | // done everything requested to make them work.... | |
191 | // | |
192 | allocation_count = 0; | |
193 | mpc_complex_50 b = std::move(a); | |
194 | BOOST_TEST(allocation_count == 0); | |
195 | // | |
196 | // Move assign - we rely on knowledge of the internals to make this test work!! | |
197 | // | |
198 | mpc_complex_50 c(3); | |
199 | do_something(b); | |
200 | do_something(c); | |
201 | // | |
202 | // Again with variable precision, this we can test more easily: | |
203 | // | |
204 | mpc_complex d, e; | |
205 | d.precision(100); | |
206 | e.precision(1000); | |
207 | d = 2; | |
208 | e = 3; | |
209 | allocation_count = 0; | |
210 | BOOST_TEST(d == 2); | |
211 | d = std::move(e); | |
212 | BOOST_TEST(allocation_count == 0); | |
213 | BOOST_TEST(d == 3); | |
214 | e = 2; | |
215 | BOOST_TEST(e == 2); | |
216 | d = std::move(e); | |
217 | e = d; | |
218 | BOOST_TEST(e == d); | |
219 | ||
220 | test_move_and_assign<mpc_complex>(); | |
221 | test_move_and_assign<mpc_complex_50>(); | |
222 | } | |
7c673cae FG |
223 | } |
224 | #endif | |
225 | #ifdef TEST_GMP | |
226 | { | |
227 | test_std_lib<mpf_float_50>(); | |
228 | mpf_float_50 a = 2; | |
229 | BOOST_TEST(allocation_count); // sanity check that we are tracking allocations | |
230 | allocation_count = 0; | |
92f5a8d4 | 231 | mpf_float_50 b = std::move(a); |
7c673cae FG |
232 | BOOST_TEST(allocation_count == 0); |
233 | // | |
234 | // Move assign: this requires knowledge of the internals to test!! | |
235 | // | |
236 | mpf_float_50 c(3); | |
237 | do_something(b); | |
238 | do_something(c); | |
239 | const void* p = b.backend().data()[0]._mp_d; | |
240 | BOOST_TEST(c.backend().data()[0]._mp_d != p); | |
241 | c = std::move(b); | |
242 | BOOST_TEST(c.backend().data()[0]._mp_d == p); | |
243 | BOOST_TEST(b.backend().data()[0]._mp_d != p); | |
244 | // | |
245 | // Again with variable precision, this we can test more easily: | |
246 | // | |
247 | mpf_float d, e; | |
248 | d.precision(100); | |
249 | e.precision(1000); | |
92f5a8d4 TL |
250 | d = 2; |
251 | e = 3; | |
7c673cae FG |
252 | allocation_count = 0; |
253 | BOOST_TEST(d == 2); | |
254 | d = std::move(e); | |
255 | BOOST_TEST(allocation_count == 0); | |
256 | BOOST_TEST(d == 3); | |
257 | e = 2; | |
258 | BOOST_TEST(e == 2); | |
259 | d = std::move(e); | |
260 | e = d; | |
261 | BOOST_TEST(e == d); | |
262 | ||
263 | test_move_and_assign<mpf_float>(); | |
264 | test_move_and_assign<mpf_float_50>(); | |
265 | } | |
266 | { | |
267 | test_std_lib<mpz_int>(); | |
268 | mpz_int a = 2; | |
269 | BOOST_TEST(allocation_count); // sanity check that we are tracking allocations | |
270 | allocation_count = 0; | |
92f5a8d4 | 271 | mpz_int b = std::move(a); |
7c673cae FG |
272 | BOOST_TEST(allocation_count == 0); |
273 | ||
274 | // | |
275 | // Move assign: | |
276 | // | |
277 | mpz_int d, e; | |
278 | d = 2; | |
279 | d <<= 1000; | |
92f5a8d4 | 280 | e = 3; |
7c673cae | 281 | allocation_count = 0; |
92f5a8d4 | 282 | e = std::move(d); |
7c673cae FG |
283 | BOOST_TEST(allocation_count == 0); |
284 | e = 2; | |
285 | BOOST_TEST(e == 2); | |
286 | d = std::move(e); | |
287 | e = d; | |
288 | BOOST_TEST(e == d); | |
289 | ||
290 | test_move_and_assign<mpz_int>(); | |
291 | } | |
292 | { | |
293 | test_std_lib<mpq_rational>(); | |
294 | mpq_rational a = 2; | |
295 | BOOST_TEST(allocation_count); // sanity check that we are tracking allocations | |
296 | allocation_count = 0; | |
92f5a8d4 | 297 | mpq_rational b = std::move(a); |
7c673cae FG |
298 | BOOST_TEST(allocation_count == 0); |
299 | ||
300 | // | |
301 | // Move assign: | |
302 | // | |
303 | mpq_rational d, e; | |
92f5a8d4 TL |
304 | d = mpz_int(2) << 1000; |
305 | e = 3; | |
7c673cae | 306 | allocation_count = 0; |
92f5a8d4 | 307 | e = std::move(d); |
7c673cae FG |
308 | BOOST_TEST(allocation_count == 0); |
309 | d = 2; | |
310 | BOOST_TEST(d == 2); | |
311 | d = std::move(e); | |
312 | e = d; | |
313 | BOOST_TEST(e == d); | |
314 | ||
315 | test_move_and_assign<mpq_rational>(); | |
316 | } | |
317 | #endif | |
318 | #ifdef TEST_TOMMATH | |
319 | { | |
320 | test_std_lib<tom_int>(); | |
92f5a8d4 | 321 | tom_int a = 2; |
7c673cae | 322 | void const* p = a.backend().data().dp; |
92f5a8d4 | 323 | tom_int b = std::move(a); |
7c673cae FG |
324 | BOOST_TEST(b.backend().data().dp == p); |
325 | // We can't test this, as it will assert inside data(): | |
326 | //BOOST_TEST(a.backend().data().dp == 0); | |
327 | ||
328 | // | |
329 | // Move assign: | |
330 | // | |
331 | tom_int d, e; | |
332 | d = 2; | |
333 | d <<= 1000; | |
334 | e = 3; | |
335 | p = d.backend().data().dp; | |
336 | BOOST_TEST(p != e.backend().data().dp); | |
337 | e = std::move(d); | |
338 | BOOST_TEST(e.backend().data().dp == p); | |
339 | d = 2; | |
340 | BOOST_TEST(d == 2); | |
341 | d = std::move(e); | |
342 | e = d; | |
343 | BOOST_TEST(e == d); | |
344 | ||
345 | test_move_and_assign<tom_int>(); | |
346 | } | |
347 | #endif | |
348 | #ifdef TEST_CPP_INT | |
349 | { | |
350 | test_std_lib<cpp_int>(); | |
351 | cpp_int a = 2; | |
92f5a8d4 | 352 | a <<= 1000; // Force dynamic allocation. |
7c673cae | 353 | void const* p = a.backend().limbs(); |
92f5a8d4 | 354 | cpp_int b = std::move(a); |
7c673cae FG |
355 | BOOST_TEST(b.backend().limbs() == p); |
356 | ||
357 | // | |
358 | // Move assign: | |
359 | // | |
360 | cpp_int d, e; | |
361 | d = 2; | |
362 | d <<= 1000; | |
363 | e = 3; | |
364 | e <<= 1000; | |
365 | p = d.backend().limbs(); | |
366 | BOOST_TEST(p != e.backend().limbs()); | |
367 | e = std::move(d); | |
368 | BOOST_TEST(e.backend().limbs() == p); | |
369 | d = 2; | |
370 | BOOST_TEST(d == 2); | |
371 | d = std::move(e); | |
372 | e = d; | |
373 | BOOST_TEST(e == d); | |
374 | ||
375 | test_move_and_assign<cpp_int>(); | |
376 | test_move_and_assign<int512_t>(); | |
377 | } | |
378 | #endif | |
379 | return boost::report_errors(); | |
380 | } | |
381 |