test_cpp_int_left_shift.cpp 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. ///////////////////////////////////////////////////////////////
  2. // Copyright 2012 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. // Compare results of truncated left shift to gmp, see:
  7. // https://svn.boost.org/trac/boost/ticket/12790
  8. //
  9. #ifdef _MSC_VER
  10. #define _SCL_SECURE_NO_WARNINGS
  11. #endif
  12. #include <boost/multiprecision/gmp.hpp>
  13. #include <boost/multiprecision/cpp_int.hpp>
  14. #include <boost/random/mersenne_twister.hpp>
  15. #include <boost/random/uniform_int.hpp>
  16. #include <boost/timer.hpp>
  17. #include "test.hpp"
  18. #if !defined(TEST1) && !defined(TEST2) && !defined(TEST3)
  19. #define TEST1
  20. #define TEST2
  21. #define TEST3
  22. #endif
  23. template <class T>
  24. T generate_random(unsigned bits_wanted)
  25. {
  26. static boost::random::mt19937 gen;
  27. typedef boost::random::mt19937::result_type random_type;
  28. T max_val;
  29. unsigned digits;
  30. if (std::numeric_limits<T>::is_bounded && (bits_wanted == (unsigned)std::numeric_limits<T>::digits))
  31. {
  32. max_val = (std::numeric_limits<T>::max)();
  33. digits = std::numeric_limits<T>::digits;
  34. }
  35. else
  36. {
  37. max_val = T(1) << bits_wanted;
  38. digits = bits_wanted;
  39. }
  40. unsigned bits_per_r_val = std::numeric_limits<random_type>::digits - 1;
  41. while ((random_type(1) << bits_per_r_val) > (gen.max)())
  42. --bits_per_r_val;
  43. unsigned terms_needed = digits / bits_per_r_val + 1;
  44. T val = 0;
  45. for (unsigned i = 0; i < terms_needed; ++i)
  46. {
  47. val *= (gen.max)();
  48. val += gen();
  49. }
  50. val %= max_val;
  51. return val;
  52. }
  53. template <class T>
  54. void test_value(const T& val)
  55. {
  56. boost::multiprecision::mpz_int z(val.str()), mask(1);
  57. mask <<= std::numeric_limits<T>::digits;
  58. --mask;
  59. for (unsigned i = 0; i <= std::numeric_limits<T>::digits + 2; ++i)
  60. {
  61. BOOST_CHECK_EQUAL((val << i).str(), boost::multiprecision::mpz_int(((z << i) & mask)).str());
  62. }
  63. }
  64. void test(const boost::mpl::int_<200>&) {}
  65. template <int N>
  66. void test(boost::mpl::int_<N> const&)
  67. {
  68. test(boost::mpl::int_<N + 4>());
  69. typedef boost::multiprecision::number<boost::multiprecision::cpp_int_backend<N, N, boost::multiprecision::unsigned_magnitude>, boost::multiprecision::et_off> mp_type;
  70. std::cout << "Running tests for precision: " << N << std::endl;
  71. mp_type mp(-1);
  72. test_value(mp);
  73. for (unsigned i = 0; i < 1000; ++i)
  74. test_value(generate_random<mp_type>(std::numeric_limits<mp_type>::digits));
  75. }
  76. int main()
  77. {
  78. test(boost::mpl::int_<24>());
  79. return boost::report_errors();
  80. }