Miller-Rabin primality test (now in 64 bit!)
% Remco Bloemen % 2009-11-27, last updated 2014-03-03
In the previous post I showed an implementation of Miller-Rabin that overflowed when the number was more that 32 bits. In this post I present a way to fix this.
I could remember an instruction I used before, mulq
which does 128 bit
multiplication. It multiplies two 64 bit number and stores the least
significant 64 bits in rax
and the significant half in rdx
.
Now we still need to reduce this number modulo m. Originally I planned
to create a table of 2^n\!\!\mod m, use the bits of rdx
to add
them and then add rax % m
. But after consulting this x86-64
manual
I found out about divq
, which takes a 128 bit number stored in
rdx:rax
, a 64 bit number m and p roduces the quotient and remainder.
The whole thing can be coded as:
/// Modular multiplication
/// @param a The first factor, a < m
/// @param a The second factor, b < m
/// @param m The modulus
/// @return The reduced product, a b mod m < m
uint64
This should work fast, but I still need to look into Montgomery reduction. Perhaps I should benchmark the two.
Modular exponentiation can now be implemented using exponentiation by squaring:
/// Modular exponentiation
/// @param b The base, b < m
/// @param e The exponent
/// @param m The modulus
/// @returns The reduced power of a, a^b mod m
uint64
And the Miller-Rabin test becomes:
/// Miller-Rabin probabilistic primality testing
/// @param n The number to test for primality
/// @param k The witness for primality
/// @returns True iff when n is a k-stong pseudoprime
bool
Together with the prime sieve I created earlier a fast probablilistic prime checking procedure can be developed:
const vector<uint64> small_primes = ;
/// Miller-Rabin probabilistic primality testing
/// @param n The number to test for primality
/// @returns False when n is not a prime
bool
This algorithm correctly identifies the first ten primes less than 2^{64}. But then again, so does a single Miller-Rabin round with K= 17. Perhaps I should implement the Baillie-PSW algorithm, there are rumours that it has no false positives for 64 bits!