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
6 #ifndef BOOST_MP_MR_HPP
7 #define BOOST_MP_MR_HPP
9 #include <boost/random.hpp>
10 #include <boost/multiprecision/integer.hpp>
13 namespace multiprecision {
17 bool check_small_factors(const I& n)
19 static const boost::uint32_t small_factors1[] = {
20 3u, 5u, 7u, 11u, 13u, 17u, 19u, 23u};
21 static const boost::uint32_t pp1 = 223092870u;
23 boost::uint32_t m1 = integer_modulus(n, pp1);
25 for (unsigned i = 0; i < sizeof(small_factors1) / sizeof(small_factors1[0]); ++i)
27 BOOST_ASSERT(pp1 % small_factors1[i] == 0);
28 if (m1 % small_factors1[i] == 0)
32 static const boost::uint32_t small_factors2[] = {
33 29u, 31u, 37u, 41u, 43u, 47u};
34 static const boost::uint32_t pp2 = 2756205443u;
36 m1 = integer_modulus(n, pp2);
38 for (unsigned i = 0; i < sizeof(small_factors2) / sizeof(small_factors2[0]); ++i)
40 BOOST_ASSERT(pp2 % small_factors2[i] == 0);
41 if (m1 % small_factors2[i] == 0)
45 static const boost::uint32_t small_factors3[] = {
46 53u, 59u, 61u, 67u, 71u};
47 static const boost::uint32_t pp3 = 907383479u;
49 m1 = integer_modulus(n, pp3);
51 for (unsigned i = 0; i < sizeof(small_factors3) / sizeof(small_factors3[0]); ++i)
53 BOOST_ASSERT(pp3 % small_factors3[i] == 0);
54 if (m1 % small_factors3[i] == 0)
58 static const boost::uint32_t small_factors4[] = {
59 73u, 79u, 83u, 89u, 97u};
60 static const boost::uint32_t pp4 = 4132280413u;
62 m1 = integer_modulus(n, pp4);
64 for (unsigned i = 0; i < sizeof(small_factors4) / sizeof(small_factors4[0]); ++i)
66 BOOST_ASSERT(pp4 % small_factors4[i] == 0);
67 if (m1 % small_factors4[i] == 0)
71 static const boost::uint32_t small_factors5[6][4] = {
72 {101u, 103u, 107u, 109u},
73 {113u, 127u, 131u, 137u},
74 {139u, 149u, 151u, 157u},
75 {163u, 167u, 173u, 179u},
76 {181u, 191u, 193u, 197u},
77 {199u, 211u, 223u, 227u}};
78 static const boost::uint32_t pp5[6] =
81 113u * 127u * 131u * 137u,
82 139u * 149u * 151u * 157u,
83 163u * 167u * 173u * 179u,
84 181u * 191u * 193u * 197u,
85 199u * 211u * 223u * 227u};
87 for (unsigned k = 0; k < sizeof(pp5) / sizeof(*pp5); ++k)
89 m1 = integer_modulus(n, pp5[k]);
91 for (unsigned i = 0; i < 4; ++i)
93 BOOST_ASSERT(pp5[k] % small_factors5[k][i] == 0);
94 if (m1 % small_factors5[k][i] == 0)
101 inline bool is_small_prime(unsigned n)
103 static const unsigned char p[] =
105 3u, 5u, 7u, 11u, 13u, 17u, 19u, 23u, 29u, 31u,
106 37u, 41u, 43u, 47u, 53u, 59u, 61u, 67u, 71u, 73u,
107 79u, 83u, 89u, 97u, 101u, 103u, 107u, 109u, 113u,
108 127u, 131u, 137u, 139u, 149u, 151u, 157u, 163u,
109 167u, 173u, 179u, 181u, 191u, 193u, 197u, 199u,
111 for (unsigned i = 0; i < sizeof(p) / sizeof(*p); ++i)
120 typename enable_if_c<is_convertible<I, unsigned>::value, unsigned>::type
121 cast_to_unsigned(const I& val)
123 return static_cast<unsigned>(val);
126 typename disable_if_c<is_convertible<I, unsigned>::value, unsigned>::type
127 cast_to_unsigned(const I& val)
129 return val.template convert_to<unsigned>();
132 } // namespace detail
134 template <class I, class Engine>
135 typename enable_if_c<number_category<I>::value == number_kind_integer, bool>::type
136 miller_rabin_test(const I& n, unsigned trials, Engine& gen)
139 #pragma warning(push)
140 #pragma warning(disable : 4127)
142 typedef I number_type;
145 return true; // Trivial special case.
146 if (bit_test(n, 0) == 0)
147 return false; // n is even
149 return detail::is_small_prime(detail::cast_to_unsigned(n));
151 if (!detail::check_small_factors(n))
154 number_type nm1 = n - 1;
156 // Begin with a single Fermat test - it excludes a lot of candidates:
158 number_type q(228), x, y; // We know n is greater than this, as we've excluded small factors
167 // Declare our random number generator:
168 boost::random::uniform_int_distribution<number_type> dist(2, n - 2);
170 // Execute the trials:
172 for (unsigned i = 0; i < trials; ++i)
185 return false; // test failed
188 return false; // failed
192 return true; // Yeheh! probably prime.
199 typename enable_if_c<number_category<I>::value == number_kind_integer, bool>::type
200 miller_rabin_test(const I& x, unsigned trials)
203 return miller_rabin_test(x, trials, gen);
206 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class Engine>
207 bool miller_rabin_test(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& n, unsigned trials, Engine& gen)
209 typedef typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type number_type;
210 return miller_rabin_test(number_type(n), trials, gen);
213 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
214 bool miller_rabin_test(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& n, unsigned trials)
216 typedef typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type number_type;
217 return miller_rabin_test(number_type(n), trials);
220 }} // namespace boost::multiprecision