Algorithms_in_C++  1.0.0
Set of algorithms implemented in C++.
miller_rabin.cpp File Reference
#include <cassert>
#include <iostream>
#include <random>
#include <vector>
Include dependency graph for miller_rabin.cpp:

Functions

template<typename T >
std::vector< T > reverse_binary (T num)
 
template<typename T >
modular_exponentiation (T base, const std::vector< T > &rev_binary_exponent, T mod)
 
template<typename T >
bool miller_test (T d, T num)
 
template<typename T >
bool miller_rabin_primality_test (T num, T repeats)
 
void tests ()
 
int main ()
 

Detailed Description

Copyright 2020

Author
tjgurwara99

A basic implementation of Miller-Rabin primality test.

Function Documentation

◆ main()

int main ( )

Main function

180  {
181  tests();
182  return 0;
183 }
Here is the call graph for this function:

◆ miller_rabin_primality_test()

template<typename T >
bool miller_rabin_primality_test ( num,
repeats 
)

Function that test (probabilistically) whether a given number is a prime based on the Miller-Rabin Primality Test.

Parameters
numnumber to be tested for primality.
repeatsnumber of repetitions for the test to increase probability of correct result.
Returns
'false' if num is composite
'true' if num is (probably) prime

\detail First we check whether the num input is less than 4, if so we can determine whether this is a prime or composite by checking for 2 and 3. Next we check whether this num is odd (as all primes greater than 2 are odd). Next we write our num in the following format \(num = 2^r \cdot d + 1\). After finding r and d for our input num, we use for loop repeat number of times inside which we check the miller conditions using the function miller_test. If miller_test returns false then the number is composite After the loop finishes completely without issuing a false return call, we can conclude that this number is probably prime.

122  {
123  if (num <= 4) {
124  // If num == 2 or num == 3 then prime
125  if (num == 2 || num == 3) {
126  return true;
127  } else {
128  return false;
129  }
130  }
131  // If num is even then not prime
132  if (num % 2 == 0) {
133  return false;
134  }
135  // Finding d and r in num = 2^r * d + 1
136  T d = num - 1, r = 0;
137  while (d % 2 == 0) {
138  d = d / 2;
139  r++;
140  }
141 
142  for (T i = 0; i < repeats; ++i) {
143  if (!miller_test(d, num)) {
144  return false;
145  }
146  }
147  return true;
148 }
Here is the call graph for this function:

◆ miller_test()

template<typename T >
bool miller_test ( d,
num 
)

Function for testing the conditions that are satisfied when a number is prime.

Parameters
dnumber such that \(d \cdot 2^r = n - 1\) where \(n = num\) parameter and \(r \geq 1\)
numnumber being tested for primality.
Returns
'false' if n is composite
'true' if n is (probably) prime.
71  {
72  // random number seed
73  std::random_device rd_seed;
74  // random number generator
75  std::mt19937 gen(rd_seed());
76  // Uniformly distributed range [2, num - 2] for random numbers
77  std::uniform_int_distribution<> distribution(2, num - 2);
78  // Random number generated in the range [2, num -2].
79  T random = distribution(gen);
80  // vector for reverse binary of the power
82  // x = random ^ d % num
83  T x = modular_exponentiation(random, power, num);
84  // miller conditions
85  if (x == 1 || x == num - 1) {
86  return true;
87  }
88 
89  while (d != num - 1) {
90  x = (x * x) % num;
91  d *= 2;
92  if (x == 1) {
93  return false;
94  }
95  if (x == num - 1) {
96  return true;
97  }
98  }
99  return false;
100 }
Here is the call graph for this function:

◆ modular_exponentiation()

template<typename T >
T modular_exponentiation ( base,
const std::vector< T > &  rev_binary_exponent,
mod 
)

Function for modular exponentiation. This function is an efficient modular exponentiation function. It can be used with any big integer library such as Boost multiprecision to give result any modular exponentiation problem relatively quickly.

Parameters
basenumber being raised to a power as integer
rev_binary_exponentreverse binary of the power the base is being raised to
modmodulo
Returns
r the modular exponentiation of \(a^{n} \equiv r \mod{m}\) where \(n\) is the base 10 representation of rev_binary_exponent and \(m = mod \) parameter.
43  {
44  if (mod == 1)
45  return 0;
46  T b = 1;
47  if (rev_binary_exponent.size() == 0)
48  return b;
49  T A = base;
50  if (rev_binary_exponent[0] == 1)
51  b = base;
52 
53  for (typename std::vector<T>::const_iterator it =
54  rev_binary_exponent.cbegin() + 1;
55  it != rev_binary_exponent.cend(); ++it) {
56  A = A * A % mod;
57  if (*it == 1)
58  b = A * b % mod;
59  }
60  return b;
61 }

◆ reverse_binary()

template<typename T >
std::vector<T> reverse_binary ( num)

Function to give a binary representation of a number in reverse order

Parameters
numinteger number that we want to convert
Returns
result vector of the number input in reverse binary
18  {
19  std::vector<T> result;
20  T temp = num;
21  while (temp > 0) {
22  result.push_back(temp % 2);
23  temp = temp / 2;
24  }
25  return result;
26 }
Here is the call graph for this function:

◆ tests()

void tests ( )

Functions for testing the miller_rabin_primality_test() function with some assert statements.

154  {
155  // First test on 2
156  assert(((void)"2 is prime but function says otherwise.\n",
157  miller_rabin_primality_test(2, 1) == true));
158  std::cout << "First test passes." << std::endl;
159  // Second test on 5
160  assert(((void)"5 should be prime but the function says otherwise.\n",
161  miller_rabin_primality_test(5, 3) == true));
162  std::cout << "Second test passes." << std::endl;
163  // Third test on 23
164  assert(((void)"23 should be prime but the function says otherwise.\n",
165  miller_rabin_primality_test(23, 3) == true));
166  std::cout << "Third test passes." << std::endl;
167  // Fourth test on 16
168  assert(((void)"16 is not a prime but the function says otherwise.\n",
169  miller_rabin_primality_test(16, 3) == false));
170  std::cout << "Fourth test passes." << std::endl;
171  // Fifth test on 27
172  assert(((void)"27 is not a prime but the function says otherwise.\n",
173  miller_rabin_primality_test(27, 3) == false));
174  std::cout << "Fifth test passes." << std::endl;
175 }
Here is the call graph for this function:
std::uniform_int_distribution
miller_rabin_primality_test
bool miller_rabin_primality_test(T num, T repeats)
Definition: miller_rabin.cpp:122
std::vector
STL class.
std::vector::size
T size(T... args)
reverse_binary
std::vector< T > reverse_binary(T num)
Definition: miller_rabin.cpp:18
power
void power(int x, int n)
Definition: power_for_huge_numbers.cpp:56
std::mt19937
std::vector::push_back
T push_back(T... args)
std::random_device
std::cout
modular_exponentiation
T modular_exponentiation(T base, const std::vector< T > &rev_binary_exponent, T mod)
Definition: miller_rabin.cpp:42
miller_test
bool miller_test(T d, T num)
Definition: miller_rabin.cpp:71
std::endl
T endl(T... args)
std::vector::cbegin
T cbegin(T... args)
std::vector::cend
T cend(T... args)
tests
void tests()
Definition: miller_rabin.cpp:154