123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393 |
- // Copyright John Maddock 2012.
- // Use, modification and distribution are subject to the
- // Boost Software License, Version 1.0.
- // (See accompanying file LICENSE_1_0.txt
- // or copy at http://www.boost.org/LICENSE_1_0.txt)
- #ifdef _MSC_VER
- #define _SCL_SECURE_NO_WARNINGS
- #endif
- #include <boost/config.hpp>
- #include <vector>
- #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- #if !defined(TEST_GMP) && !defined(TEST_MPFR) && !defined(TEST_TOMMATH) && !defined(TEST_CPP_INT) && !defined(TEST_MPC)
- #define TEST_GMP
- #define TEST_MPFR
- #define TEST_TOMMATH
- #define TEST_CPP_INT
- #define TEST_MPC
- #ifdef _MSC_VER
- #pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!")
- #endif
- #ifdef __GNUC__
- #pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!"
- #endif
- #endif
- #if defined(TEST_GMP)
- #include <boost/multiprecision/gmp.hpp>
- #endif
- #if defined(TEST_MPFR)
- #include <boost/multiprecision/mpfr.hpp>
- #endif
- #ifdef TEST_TOMMATH
- #include <boost/multiprecision/tommath.hpp>
- #endif
- #ifdef TEST_CPP_INT
- #include <boost/multiprecision/cpp_int.hpp>
- #endif
- #ifdef TEST_MPC
- #include <boost/multiprecision/mpc.hpp>
- #endif
- #include "test.hpp"
- unsigned allocation_count = 0;
- void* (*alloc_func_ptr)(size_t);
- void* (*realloc_func_ptr)(void*, size_t, size_t);
- void (*free_func_ptr)(void*, size_t);
- void* alloc_func(size_t n)
- {
- ++allocation_count;
- return (*alloc_func_ptr)(n);
- }
- void free_func(void* p, size_t n)
- {
- (*free_func_ptr)(p, n);
- }
- void* realloc_func(void* p, size_t old, size_t n)
- {
- ++allocation_count;
- return (*realloc_func_ptr)(p, old, n);
- }
- template <class T>
- void do_something(const T&)
- {
- }
- template <class T>
- void test_std_lib()
- {
- std::vector<T> v;
- for (unsigned i = 0; i < 100; ++i)
- v.insert(v.begin(), i);
- T a(2), b(3);
- std::swap(a, b);
- BOOST_TEST(a == 3);
- BOOST_TEST(b == 2);
- }
- template <class T, class A>
- void test_move_and_assign(T x, A val)
- {
- // move away from x, then assign val to x.
- T z(x);
- T y(std::move(x));
- x.assign(val);
- BOOST_CHECK_EQUAL(x, T(val));
- BOOST_CHECK_EQUAL(z, y);
- }
- template <class T>
- void test_move_and_assign()
- {
- T x(23);
- test_move_and_assign(x, static_cast<short>(2));
- test_move_and_assign(x, static_cast<int>(2));
- test_move_and_assign(x, static_cast<long>(2));
- test_move_and_assign(x, static_cast<long long>(2));
- test_move_and_assign(x, static_cast<unsigned short>(2));
- test_move_and_assign(x, static_cast<unsigned int>(2));
- test_move_and_assign(x, static_cast<unsigned long>(2));
- test_move_and_assign(x, static_cast<unsigned long long>(2));
- test_move_and_assign(x, static_cast<float>(2));
- test_move_and_assign(x, static_cast<double>(2));
- test_move_and_assign(x, static_cast<long double>(2));
- test_move_and_assign(x, x);
- test_move_and_assign(x, "23");
- }
- int main()
- {
- #if defined(TEST_MPFR) || defined(TEST_GMP)
- #if defined(MPFR_VERSION) && (MPFR_VERSION_MAJOR > 3)
- mpfr_mp_memory_cleanup();
- #endif
- mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr);
- mp_set_memory_functions(&alloc_func, &realloc_func, &free_func);
- #endif
- using namespace boost::multiprecision;
- #ifdef TEST_MPFR
- {
- test_std_lib<mpfr_float_50>();
- mpfr_float_50 a = 2;
- if (allocation_count)
- {
- //
- // We can only conduct meaningful tests if we're actually using our custom allocators,
- // there are some situations where mpfr-4.x doesn't call them even though we've
- // done everything requested to make them work....
- //
- allocation_count = 0;
- mpfr_float_50 b = std::move(a);
- BOOST_TEST(allocation_count == 0);
- //
- // Move assign - we rely on knowledge of the internals to make this test work!!
- //
- mpfr_float_50 c(3);
- do_something(b);
- do_something(c);
- const void* p = b.backend().data()[0]._mpfr_d;
- BOOST_TEST(c.backend().data()[0]._mpfr_d != p);
- c = std::move(b);
- BOOST_TEST(c.backend().data()[0]._mpfr_d == p);
- BOOST_TEST(b.backend().data()[0]._mpfr_d != p);
- //
- // Again with variable precision, this we can test more easily:
- //
- mpfr_float d, e;
- d.precision(100);
- e.precision(1000);
- d = 2;
- e = 3;
- allocation_count = 0;
- BOOST_TEST(d == 2);
- d = std::move(e);
- BOOST_TEST(allocation_count == 0);
- BOOST_TEST(d == 3);
- e = 2;
- BOOST_TEST(e == 2);
- d = std::move(e);
- e = d;
- BOOST_TEST(e == d);
- test_move_and_assign<mpfr_float>();
- test_move_and_assign<mpfr_float_50>();
- }
- }
- #endif
- #ifdef TEST_MPC
- {
- test_std_lib<mpc_complex_50>();
- mpc_complex_50 a = 2;
- if (allocation_count)
- {
- //
- // We can only conduct meaningful tests if we're actually using our custom allocators,
- // there are some situations where mpfr-4.x doesn't call them even though we've
- // done everything requested to make them work....
- //
- allocation_count = 0;
- mpc_complex_50 b = std::move(a);
- BOOST_TEST(allocation_count == 0);
- //
- // Move assign - we rely on knowledge of the internals to make this test work!!
- //
- mpc_complex_50 c(3);
- do_something(b);
- do_something(c);
- //
- // Again with variable precision, this we can test more easily:
- //
- mpc_complex d, e;
- d.precision(100);
- e.precision(1000);
- d = 2;
- e = 3;
- allocation_count = 0;
- BOOST_TEST(d == 2);
- d = std::move(e);
- BOOST_TEST(allocation_count == 0);
- BOOST_TEST(d == 3);
- e = 2;
- BOOST_TEST(e == 2);
- d = std::move(e);
- e = d;
- BOOST_TEST(e == d);
- test_move_and_assign<mpc_complex>();
- test_move_and_assign<mpc_complex_50>();
- }
- }
- #endif
- #ifdef TEST_GMP
- {
- test_std_lib<mpf_float_50>();
- mpf_float_50 a = 2;
- BOOST_TEST(allocation_count); // sanity check that we are tracking allocations
- allocation_count = 0;
- mpf_float_50 b = std::move(a);
- BOOST_TEST(allocation_count == 0);
- //
- // Move assign: this requires knowledge of the internals to test!!
- //
- mpf_float_50 c(3);
- do_something(b);
- do_something(c);
- const void* p = b.backend().data()[0]._mp_d;
- BOOST_TEST(c.backend().data()[0]._mp_d != p);
- c = std::move(b);
- BOOST_TEST(c.backend().data()[0]._mp_d == p);
- BOOST_TEST(b.backend().data()[0]._mp_d != p);
- //
- // Again with variable precision, this we can test more easily:
- //
- mpf_float d, e;
- d.precision(100);
- e.precision(1000);
- d = 2;
- e = 3;
- allocation_count = 0;
- BOOST_TEST(d == 2);
- d = std::move(e);
- BOOST_TEST(allocation_count == 0);
- BOOST_TEST(d == 3);
- e = 2;
- BOOST_TEST(e == 2);
- d = std::move(e);
- e = d;
- BOOST_TEST(e == d);
- test_move_and_assign<mpf_float>();
- test_move_and_assign<mpf_float_50>();
- }
- {
- test_std_lib<mpz_int>();
- mpz_int a = 2;
- BOOST_TEST(allocation_count); // sanity check that we are tracking allocations
- allocation_count = 0;
- mpz_int b = std::move(a);
- BOOST_TEST(allocation_count == 0);
- //
- // Move assign:
- //
- mpz_int d, e;
- d = 2;
- d <<= 1000;
- e = 3;
- allocation_count = 0;
- e = std::move(d);
- BOOST_TEST(allocation_count == 0);
- e = 2;
- BOOST_TEST(e == 2);
- d = std::move(e);
- e = d;
- BOOST_TEST(e == d);
- test_move_and_assign<mpz_int>();
- }
- {
- test_std_lib<mpq_rational>();
- mpq_rational a = 2;
- BOOST_TEST(allocation_count); // sanity check that we are tracking allocations
- allocation_count = 0;
- mpq_rational b = std::move(a);
- BOOST_TEST(allocation_count == 0);
- //
- // Move assign:
- //
- mpq_rational d, e;
- d = mpz_int(2) << 1000;
- e = 3;
- allocation_count = 0;
- e = std::move(d);
- BOOST_TEST(allocation_count == 0);
- d = 2;
- BOOST_TEST(d == 2);
- d = std::move(e);
- e = d;
- BOOST_TEST(e == d);
- test_move_and_assign<mpq_rational>();
- }
- #endif
- #ifdef TEST_TOMMATH
- {
- test_std_lib<tom_int>();
- tom_int a = 2;
- void const* p = a.backend().data().dp;
- tom_int b = std::move(a);
- BOOST_TEST(b.backend().data().dp == p);
- // We can't test this, as it will assert inside data():
- //BOOST_TEST(a.backend().data().dp == 0);
- //
- // Move assign:
- //
- tom_int d, e;
- d = 2;
- d <<= 1000;
- e = 3;
- p = d.backend().data().dp;
- BOOST_TEST(p != e.backend().data().dp);
- e = std::move(d);
- BOOST_TEST(e.backend().data().dp == p);
- d = 2;
- BOOST_TEST(d == 2);
- d = std::move(e);
- e = d;
- BOOST_TEST(e == d);
- test_move_and_assign<tom_int>();
- }
- #endif
- #ifdef TEST_CPP_INT
- {
- test_std_lib<cpp_int>();
- cpp_int a = 2;
- a <<= 1000; // Force dynamic allocation.
- void const* p = a.backend().limbs();
- cpp_int b = std::move(a);
- BOOST_TEST(b.backend().limbs() == p);
- //
- // Move assign:
- //
- cpp_int d, e;
- d = 2;
- d <<= 1000;
- e = 3;
- e <<= 1000;
- p = d.backend().limbs();
- BOOST_TEST(p != e.backend().limbs());
- e = std::move(d);
- BOOST_TEST(e.backend().limbs() == p);
- d = 2;
- BOOST_TEST(d == 2);
- d = std::move(e);
- e = d;
- BOOST_TEST(e == d);
- test_move_and_assign<cpp_int>();
- test_move_and_assign<int512_t>();
- }
- #endif
- return boost::report_errors();
- }
- #else
- //
- // No rvalue refs, nothing to test:
- //
- int main()
- {
- return 0;
- }
- #endif
|