test_unchecked_cpp_int.cpp 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. ///////////////////////////////////////////////////////////////
  2. // Copyright 2017 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. // Check results of truncated overflow.
  7. //
  8. #ifdef _MSC_VER
  9. #define _SCL_SECURE_NO_WARNINGS
  10. #endif
  11. #include <boost/multiprecision/cpp_int.hpp>
  12. #include "test.hpp"
  13. #include <boost/random/mersenne_twister.hpp>
  14. #include <boost/random/uniform_int.hpp>
  15. template <class T>
  16. T generate_random(unsigned bits_wanted)
  17. {
  18. static boost::random::mt19937 gen;
  19. typedef boost::random::mt19937::result_type random_type;
  20. T max_val;
  21. unsigned digits;
  22. if (std::numeric_limits<T>::is_bounded && (bits_wanted == (unsigned)std::numeric_limits<T>::digits))
  23. {
  24. max_val = (std::numeric_limits<T>::max)();
  25. digits = std::numeric_limits<T>::digits;
  26. }
  27. else
  28. {
  29. max_val = T(1) << bits_wanted;
  30. digits = bits_wanted;
  31. }
  32. unsigned bits_per_r_val = std::numeric_limits<random_type>::digits - 1;
  33. while ((random_type(1) << bits_per_r_val) > (gen.max)())
  34. --bits_per_r_val;
  35. unsigned terms_needed = digits / bits_per_r_val + 1;
  36. T val = 0;
  37. for (unsigned i = 0; i < terms_needed; ++i)
  38. {
  39. val *= (gen.max)();
  40. val += gen();
  41. }
  42. val %= max_val;
  43. return val;
  44. }
  45. template <class Number>
  46. void test()
  47. {
  48. using namespace boost::multiprecision;
  49. typedef Number test_type;
  50. for (unsigned i = 30; i < std::numeric_limits<test_type>::digits; ++i)
  51. {
  52. for (unsigned j = std::numeric_limits<test_type>::digits - i - 1; j < std::numeric_limits<test_type>::digits; ++j)
  53. {
  54. for (unsigned k = 0; k < 10; ++k)
  55. {
  56. test_type a = static_cast<test_type>(generate_random<cpp_int>(i));
  57. test_type b = static_cast<test_type>(generate_random<cpp_int>(j));
  58. test_type c = static_cast<test_type>(cpp_int(a) * cpp_int(b));
  59. test_type d = a * b;
  60. BOOST_CHECK_EQUAL(c, d);
  61. if ((k == 0) && (j == 0))
  62. {
  63. for (unsigned s = 1; s < std::numeric_limits<test_type>::digits; ++s)
  64. BOOST_CHECK_EQUAL(a << s, test_type(cpp_int(a) << s));
  65. }
  66. }
  67. }
  68. }
  69. }
  70. int main()
  71. {
  72. using namespace boost::multiprecision;
  73. test<int512_t>();
  74. test<uint512_t>();
  75. //
  76. // We also need to test type with "odd" bit counts in order to ensure full code coverage:
  77. //
  78. test<number<cpp_int_backend<528, 528, signed_magnitude, unchecked, void> > >();
  79. test<number<cpp_int_backend<528, 528, unsigned_magnitude, unchecked, void> > >();
  80. test<number<cpp_int_backend<48, 48, signed_magnitude, unchecked, void> > >();
  81. test<number<cpp_int_backend<48, 48, unsigned_magnitude, unchecked, void> > >();
  82. return boost::report_errors();
  83. }