test_move.cpp 10.0 KB

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