test_miller_rabin.cpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  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. #ifdef _MSC_VER
  6. #define _SCL_SECURE_NO_WARNINGS
  7. #endif
  8. #include <boost/multiprecision/gmp.hpp>
  9. #include <boost/multiprecision/cpp_int.hpp>
  10. #include <boost/multiprecision/miller_rabin.hpp>
  11. #include <boost/math/special_functions/prime.hpp>
  12. #include <iostream>
  13. #include <iomanip>
  14. #include "test.hpp"
  15. template <class I>
  16. void test()
  17. {
  18. //
  19. // Very simple test program to verify that the GMP's Miller-Rabin
  20. // implementation and this one agree on whether some random numbers
  21. // are prime or not. Of course these are probabilistic tests so there's
  22. // no reason why they should actually agree - except the probability of
  23. // disagreement for 25 trials is almost infinitely small.
  24. //
  25. using namespace boost::random;
  26. using namespace boost::multiprecision;
  27. typedef I test_type;
  28. static const unsigned test_bits =
  29. std::numeric_limits<test_type>::digits && (std::numeric_limits<test_type>::digits <= 256)
  30. ? std::numeric_limits<test_type>::digits
  31. : 128;
  32. independent_bits_engine<mt11213b, test_bits, test_type> gen;
  33. //
  34. // We must use a different generator for the tests and number generation, otherwise
  35. // we get false positives. Further we use the same random number engine for the
  36. // Miller Rabin test as GMP uses internally:
  37. //
  38. mt19937 gen2;
  39. //
  40. // Begin by testing the primes in our table as all these should return true:
  41. //
  42. for (unsigned i = 1; i < boost::math::max_prime; ++i)
  43. {
  44. BOOST_TEST(miller_rabin_test(test_type(boost::math::prime(i)), 25, gen));
  45. BOOST_TEST(mpz_probab_prime_p(mpz_int(boost::math::prime(i)).backend().data(), 25));
  46. }
  47. //
  48. // Now test some random values and compare GMP's native routine with ours.
  49. //
  50. for (unsigned i = 0; i < 10000; ++i)
  51. {
  52. test_type n = gen();
  53. bool is_prime_boost = miller_rabin_test(n, 25, gen2);
  54. bool is_gmp_prime = mpz_probab_prime_p(mpz_int(n).backend().data(), 25) ? true : false;
  55. if (is_prime_boost && is_gmp_prime)
  56. {
  57. std::cout << "We have a prime: " << std::hex << std::showbase << n << std::endl;
  58. }
  59. if (is_prime_boost != is_gmp_prime)
  60. std::cout << std::hex << std::showbase << "n = " << n << std::endl;
  61. BOOST_CHECK_EQUAL(is_prime_boost, is_gmp_prime);
  62. }
  63. }
  64. int main()
  65. {
  66. using namespace boost::multiprecision;
  67. test<mpz_int>();
  68. test<number<gmp_int, et_off> >();
  69. test<boost::uint64_t>();
  70. test<boost::uint32_t>();
  71. test<cpp_int>();
  72. test<number<cpp_int_backend<64, 64, unsigned_magnitude, checked, void>, et_off> >();
  73. test<checked_uint128_t>();
  74. test<checked_uint1024_t>();
  75. return boost::report_errors();
  76. }