I know the Miller–Rabin primality test is probabilistic. However I want to use it for a programming task that leaves no room for error.
Can we assume that it is corr
There are efficient deterministic variants of the MR test for 64-bit values - which do not rely on the GRH - having been exhaustively tested by exploiting GPUs and other known results.
I've listed the pertinent sections of a C program I wrote that tests the primality of any 64-bit value: (n > 1)
, using Jaeschke's and Sinclair's bases for the deterministic MR variant. It makes use of gcc and clang's __int128
extended type for exponentiation. If not available, an explicit routine is required. Maybe others will find this useful...
#include
/******************************************************************************/
static int sprp (uint64_t n, uint64_t a)
{
uint64_t m = n - 1, r, y;
unsigned int s = 1, j;
/* assert(n > 2 && (n & 0x1) != 0); */
while ((m & (UINT64_C(1) << s)) == 0) s++;
r = m >> s; /* r, s s.t. 2^s * r = n - 1, r in odd. */
if ((a %= n) == 0) /* else (0 < a < n) */
return (1);
{
unsigned __int128 u = 1, w = a;
while (r != 0)
{
if ((r & 0x1) != 0)
u = (u * w) % n; /* (mul-rdx) */
if ((r >>= 1) != 0)
w = (w * w) % n; /* (sqr-rdx) */
}
if ((y = (uint64_t) u) == 1)
return (1);
}
for (j = 1; j < s && y != m; j++)
{
unsigned __int128 u = y;
u = (u * u) % n; /* (sqr-rdx) */
if ((y = (uint64_t) u) <= 1) /* (n) is composite: */
return (0);
}
return (y == m);
}
/******************************************************************************/
static int is_prime (uint64_t n)
{
const uint32_t sprp32_base[] = /* (Jaeschke) */ {
2, 7, 61, 0};
const uint32_t sprp64_base[] = /* (Sinclair) */ {
2, 325, 9375, 28178, 450775, 9780504, 1795265022, 0};
const uint32_t *sprp_base;
/* assert(n > 1); */
if ((n & 0x1) == 0) /* even: */
return (n == 2);
sprp_base = (n <= UINT32_MAX) ? sprp32_base : sprp64_base;
for (; *sprp_base != 0; sprp_base++)
if (!sprp(n, *sprp_base)) return (0);
return (1); /* prime. */
}
/******************************************************************************/
Note that the MR (sprp) test is slightly modified to pass values on an iteration where the base is a multiple of the candidate, as mentioned in the 'remarks' section of the website
Update: while this has fewer base tests than Niklas' answer, it's important to note that the bases: {3, 5, 7, 11, 13, 17, 19, 23, 29}
provide a cheap test that allows us to eliminate candidates exceeding: 29 * 29 = 841
-
simply using the GCD.
For (n > 29 * 29)
, we can clearly eliminate any even value as prime. The product of the small primes: (3 * 5 * 7 * 11 * 13 * 17 * 19 * 23 * 29} = 3234846615
, fits nicely in a 32-bit unsigned value. A gcd(n, 3234846615)
is a lot cheaper than a MR test! If the result is not (1)
, then (n) > 841
has a small factor.
Merten's (?) theorem suggests that this simple gcd(u64, u64)
test eliminates ~ 68% of all odd candidates (as composites). If you're using M-R to search for primes (randomly or incrementally), rather than just a 'one-off' test, this is certainly worth while!