TheAlgorithms/C++ 1.0.0
All the algorithms implemented in C++
Loading...
Searching...
No Matches
miller_rabin.cpp
Go to the documentation of this file.
1
8#include <cassert>
9#include <iostream>
10#include <random>
11#include <vector>
12
18template <typename T>
19std::vector<T> reverse_binary(T num) {
20 std::vector<T> result;
21 T temp = num;
22 while (temp > 0) {
23 result.push_back(temp % 2);
24 temp = temp / 2;
25 }
26 return result;
27}
28
42template <typename T>
43T modular_exponentiation(T base, const std::vector<T> &rev_binary_exponent,
44 T mod) {
45 if (mod == 1)
46 return 0;
47 T b = 1;
48 if (rev_binary_exponent.size() == 0)
49 return b;
50 T A = base;
51 if (rev_binary_exponent[0] == 1)
52 b = base;
53
54 for (typename std::vector<T>::const_iterator it =
55 rev_binary_exponent.cbegin() + 1;
56 it != rev_binary_exponent.cend(); ++it) {
57 A = A * A % mod;
58 if (*it == 1)
59 b = A * b % mod;
60 }
61 return b;
62}
63
72template <typename T>
73bool miller_test(T d, T num) {
74 // random number seed
75 std::random_device rd_seed;
76 // random number generator
77 std::mt19937 gen(rd_seed());
78 // Uniformly distributed range [2, num - 2] for random numbers
79 std::uniform_int_distribution<> distribution(2, num - 2);
80 // Random number generated in the range [2, num -2].
81 T random = distribution(gen);
82 // vector for reverse binary of the power
83 std::vector<T> power = reverse_binary(d);
84 // x = random ^ d % num
85 T x = modular_exponentiation(random, power, num);
86 // miller conditions
87 if (x == 1 || x == num - 1) {
88 return true;
89 }
90
91 while (d != num - 1) {
92 x = (x * x) % num;
93 d *= 2;
94 if (x == 1) {
95 return false;
96 }
97 if (x == num - 1) {
98 return true;
99 }
100 }
101 return false;
102}
103
124template <typename T>
125bool miller_rabin_primality_test(T num, T repeats) {
126 if (num <= 4) {
127 // If num == 2 or num == 3 then prime
128 if (num == 2 || num == 3) {
129 return true;
130 } else {
131 return false;
132 }
133 }
134 // If num is even then not prime
135 if (num % 2 == 0) {
136 return false;
137 }
138 // Finding d and r in num = 2^r * d + 1
139 T d = num - 1, r = 0;
140 while (d % 2 == 0) {
141 d = d / 2;
142 r++;
143 }
144
145 for (T i = 0; i < repeats; ++i) {
146 if (!miller_test(d, num)) {
147 return false;
148 }
149 }
150 return true;
151}
152
157void tests() {
158 // First test on 2
159 assert(((void)"2 is prime but function says otherwise.\n",
160 miller_rabin_primality_test(2, 1) == true));
161 std::cout << "First test passes." << std::endl;
162 // Second test on 5
163 assert(((void)"5 should be prime but the function says otherwise.\n",
164 miller_rabin_primality_test(5, 3) == true));
165 std::cout << "Second test passes." << std::endl;
166 // Third test on 23
167 assert(((void)"23 should be prime but the function says otherwise.\n",
168 miller_rabin_primality_test(23, 3) == true));
169 std::cout << "Third test passes." << std::endl;
170 // Fourth test on 16
171 assert(((void)"16 is not a prime but the function says otherwise.\n",
172 miller_rabin_primality_test(16, 3) == false));
173 std::cout << "Fourth test passes." << std::endl;
174 // Fifth test on 27
175 assert(((void)"27 is not a prime but the function says otherwise.\n",
176 miller_rabin_primality_test(27, 3) == false));
177 std::cout << "Fifth test passes." << std::endl;
178}
179
183int main() {
184 tests();
185 return 0;
186}
std::vector< T > reverse_binary(T num)
bool miller_test(T d, T num)
void tests()
bool miller_rabin_primality_test(T num, T repeats)
T modular_exponentiation(T base, const std::vector< T > &rev_binary_exponent, T mod)
int main()
void power(int x, int n)