multiprecision/test/test_miller_rabin.cpp

90 lines
2.9 KiB
C++

///////////////////////////////////////////////////////////////
// Copyright 2012 John Maddock. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
#ifdef _MSC_VER
#define _SCL_SECURE_NO_WARNINGS
#endif
#include <boost/multiprecision/gmp.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/multiprecision/miller_rabin.hpp>
#include <boost/math/special_functions/prime.hpp>
#include <boost/random.hpp>
#include <random>
#include <iostream>
#include <iomanip>
#include "test.hpp"
template <class I>
void test()
{
//
// Very simple test program to verify that the GMP's Miller-Rabin
// implementation and this one agree on whether some random numbers
// are prime or not. Of course these are probabilistic tests so there's
// no reason why they should actually agree - except the probability of
// disagreement for 25 trials is almost infinitely small.
//
using namespace boost::random;
using namespace boost::multiprecision;
typedef I test_type;
static const unsigned test_bits =
std::numeric_limits<test_type>::digits && (std::numeric_limits<test_type>::digits <= 256)
? std::numeric_limits<test_type>::digits
: 128;
independent_bits_engine<mt11213b, test_bits, test_type> gen;
//
// We must use a different generator for the tests and number generation, otherwise
// we get false positives. Further we use the same random number engine for the
// Miller Rabin test as GMP uses internally:
//
mt19937 gen2;
//
// Begin by testing the primes in our table as all these should return true:
//
for (unsigned i = 1; i < boost::math::max_prime; ++i)
{
BOOST_TEST(miller_rabin_test(test_type(boost::math::prime(i)), 25, gen));
BOOST_TEST(mpz_probab_prime_p(mpz_int(boost::math::prime(i)).backend().data(), 25));
}
//
// Now test some random values and compare GMP's native routine with ours.
//
for (unsigned i = 0; i < 10000; ++i)
{
test_type n = gen();
bool is_prime_boost = miller_rabin_test(n, 25, gen2);
bool is_gmp_prime = mpz_probab_prime_p(mpz_int(n).backend().data(), 25) ? true : false;
if (is_prime_boost && is_gmp_prime)
{
std::cout << "We have a prime: " << std::hex << std::showbase << n << std::endl;
}
if (is_prime_boost != is_gmp_prime)
std::cout << std::hex << std::showbase << "n = " << n << std::endl;
BOOST_CHECK_EQUAL(is_prime_boost, is_gmp_prime);
}
}
int main()
{
using namespace boost::multiprecision;
test<mpz_int>();
test<number<gmp_int, et_off> >();
test<std::uint64_t>();
test<std::uint32_t>();
test<cpp_int>();
test<number<cpp_int_backend<64, 64, unsigned_magnitude, checked, void>, et_off> >();
test<checked_uint128_t>();
test<checked_uint1024_t>();
return boost::report_errors();
}