Purpose: Decide whether is prime in (or with fast multiplication), where is the number of bases tested. With a fixed set of bases it is deterministic for all 64-bit .

Algorithm

  1. Handle small cases: composite; prime; even composite.
  2. Write with odd.
  3. For each base :
    • Compute . If or , this base gives no evidence β€” continue to the next base.
    • Repeat times: . If , break out and continue to the next base.
    • If the loop finishes without ever hitting , then is composite β€” stop.
  4. If every base passes, report probably prime (certainly prime for the fixed base sets below).

Code

using u64 = unsigned long long;
using u128 = __uint128_t;
 
u64 mulmod(u64 a, u64 b, u64 m) { return (u128)a * b % m; }
 
u64 powmod(u64 a, u64 e, u64 m) {
    u64 r = 1; a %= m;
    while (e) { if (e & 1) r = mulmod(r, a, m); a = mulmod(a, a, m); e >>= 1; }
    return r;
}
 
bool witness(u64 a, u64 d, u64 n, int s) {
    u64 x = powmod(a, d, n);
    if (x == 1 || x == n - 1) return false;      // not a witness
    for (int i = 1; i < s; i++) {
        x = mulmod(x, x, n);
        if (x == n - 1) return false;
    }
    return true;                                  // a proves n composite
}
 
bool isPrime(u64 n) {
    if (n < 2) return false;
    for (u64 p : {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37})
        if (n % p == 0) return n == p;
    u64 d = n - 1; int s = 0;
    while ((d & 1) == 0) { d >>= 1; s++; }
    for (u64 a : {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37})
        if (witness(a, d, n, s)) return false;
    return true;
}

Deterministic base sets

  • : bases
  • : bases
  • all 64-bit : the first twelve primes
  • all 64-bit (fewer bases):

Paradigm

Randomized (Monte Carlo), made deterministic. Each base is an independent one-sided test: it can prove compositeness but never proves primality.

Complexity

  • Time: with schoolbook modmul; each base costs one modpow plus squarings
  • Space:

Why It Works

If is an odd prime, is a field, so has only the roots . Writing and applying Fermat’s little theorem, the sequence must end at , and the step before the first must be . If the algorithm sees a value that jumps to without passing through , it has found a non-trivial square root of 1, which is impossible modulo a prime. Hence is composite.

For composite , at least of the bases in are witnesses (Rabin), so random bases err with probability . The fixed base sets above were found by exhaustive verification against the known pseudoprime tables.

Fermat's test is not enough

The plain Fermat test is fooled by Carmichael numbers (561, 1105, 1729, …) for every coprime base. Miller-Rabin’s square-root check is exactly what fixes this.

Variants / Use Cases

  • Pollard’s Rho β€” pair with Miller-Rabin to factor 64-bit integers fast
  • Baillie-PSW β€” one Miller-Rabin base 2 test plus a Lucas test; no known counterexample
  • AKS β€” deterministic polynomial time without unproven hypotheses, but far slower in practice
  • Lucas-Lehmer β€” specialised, much faster, for Mersenne numbers
  • Generating random primes β€” test random odd candidates until one passes
  • Montgomery reduction β€” speeds up the inner modmul by 2-3Γ— when is fixed