Mathematical Algorithms/Modular Exponentiation & Primality

Lesson 10.21,534 words

Modular Exponentiation & Primality

Computing anmodma^n \bmod m naively costs nn multiplications; repeated squaring does it in O(logn)O(\log n) by reading the bits of the exponent. We use this routine to state Fermat's little theorem (and the modular inverse it gives), then to test primality — trial division, the probabilistic Fermat and Miller–Rabin tests, and the deterministic witness set that settles primality for every 64-bit number.

╌╌╌╌

The previous lesson built the arithmetic of : addition, multiplication, and the modular inverse via the extended Euclidean algorithm. One operation it left on the table is exponentiation: given , , and a modulus , compute . The obvious loop multiplies into an accumulator times, which is , hopelessly slow when is a 1024-bit number, as it routinely is in cryptography. This lesson's first result is that we can do it in multiplications. That single trick, repeated squaring, is the engine behind primality testing, the modular inverse, and the public-key primitives that secure the internet.

Binary exponentiation: repeated squaring

The idea is to read in binary. Write with . Then

The numbers are just the repeated squares of : each one is the square of the previous, since . So we sweep the bits of from least to most significant, keeping a running square , and whenever the current bit is we multiply that square into the result.

Square at each step; multiply the running square into the accumulator where the bit of is

Each square is one multiplication and there are of them; each bit costs at most one more multiplication into the accumulator. So the total is at most multiplications, which is .1 Reducing modulo after every multiplication keeps every intermediate value below .

Algorithm:ModPow(a,n,m)\textsc{ModPow}(a, n, m) — iterative bit-scan, returns anmodma^n \bmod m
  1. 1
    result1result \gets 1
  2. 2
    aamodma \gets a \bmod m
  3. 3
    while n>0n > 0 do
  4. 4
    if nmod2=1n \bmod 2 = 1 then
    low bit set
  5. 5
    result(resulta)modmresult \gets (result \cdot a) \bmod m
  6. 6
    a(aa)modma \gets (a \cdot a) \bmod m
    square for next bit
  7. 7
    nn/2n \gets \lfloor n / 2 \rfloor
  8. 8
    return resultresult

Running this on makes the bit-scan concrete: the running square is across the bits of , and the accumulator picks up a factor at each set bit, finishing at .

traced — bits of drive square-and-multiply

The same computation has a clean recursive shape, splitting the exponent in half:

Algorithm:ModPow-Rec(a,n,m)\textsc{ModPow-Rec}(a, n, m) — recursive halving
  1. 1
    if n=0n = 0 then return 11
  2. 2
    hModPow-Rec(a,n/2,m)h \gets \textsc{ModPow-Rec}(a, \lfloor n/2 \rfloor, m)
  3. 3
    h(hh)modmh \gets (h \cdot h) \bmod m
  4. 4
    if nmod2=1n \bmod 2 = 1 then
  5. 5
    h(ha)modmh \gets (h \cdot a) \bmod m
  6. 6
    return hh

The recursion descends by halving the exponent and rebuilds the answer on the way back up: each return squares the child's value, and an odd exponent multiplies one extra copy of . For the four downward halvings unwind into four squarings, three of them carrying the extra from an odd level.

Recursive halving for — each level squares, odd exponents multiply one extra

The doubling structure is not special to integers. Replace multiply with matrix multiply and the identity gives the -th Fibonacci number in matrix multiplications by the very same repeated-squaring loop.

Fermat's little theorem

Repeated squaring lets us compute large powers; number theory tells us what those powers are modulo a prime.

A corollary recovers the modular inverse from the previous lesson without the extended Euclidean algorithm: multiplying by gives

a single call. This only works for a prime modulus, but that is exactly the common case in competitive programming, where arithmetic is done modulo a fixed prime such as .2 For a general modulus, Euler's theorem generalizes Fermat: if then , where is Euler's totient, giving .

Primality testing

How do we decide whether a number is prime? Three approaches, in increasing power.

Trial division —

If has a nontrivial factor it has one no larger than (factors come in pairs , and the smaller is ). So testing every candidate divisor up to settles the question.

Algorithm:IsPrime-Trial(n)\textsc{IsPrime-Trial}(n)O(n)O(\sqrt n) deterministic test
  1. 1
    if n<2n < 2 then return false
  2. 2
    d2d \gets 2
  3. 3
    while ddnd \cdot d \le n do
  4. 4
    if nmodd=0n \bmod d = 0 then return false
  5. 5
    dd+1d \gets d + 1
  6. 6
    return true

This is perfectly adequate for one moderate number (say ), and is the right tool when a problem hands you a single value. It is hopeless for a 200-digit cryptographic number, where is astronomically large.

The Fermat test — probabilistic

Fermat's little theorem runs in reverse as a compositeness detector. If is prime, then for every coprime to . So if we find a single witness with , then is certainly composite, and one call refutes primality. If instead , then is only probably prime; repeat with several random to raise confidence.

The fatal caveat is the Carmichael numbers, composites such as for which holds for every coprime to . No choice of coprime witness ever exposes them, so the Fermat test silently declares them prime. There are infinitely many. We need a test that looks deeper.

Watching the full square-root chain for shows exactly what the Fermat test misses. With witness and , the chain ends at — so Fermat, which sees only that last entry, is fooled — yet it reaches from , a value that is neither nor . A prime can never square a non- residue to , so that one extra observation convicts as composite.

The Carmichael number passes Fermat () but fails Miller–Rabin: the chain hits from , a nontrivial square root of .

Miller–Rabin

Miller–Rabin strengthens the Fermat test by exploiting a second fact about primes: in , the only square roots of are . Write the even number as

For a witness , consider the chain obtained by computing and then squaring it times:

If is prime, this chain must end at (Fermat), and the first time it reaches it must arrive from , because has no square root other than . So a prime forces one of two patterns: either , or some for . If neither holds, we have found a -step value that is a nontrivial square root of (it squares to but is not ), which a prime can never have, so is a witness that is composite.3

A nontrivial square root of in the chain betrays a composite
Algorithm:Miller-Rabin(n,a)\textsc{Miller-Rabin}(n, a) — true if aa fails to witness compositeness
  1. 1
    write n1=2sdn - 1 = 2^{s} d with dd odd
  2. 2
    xModPow(a,d,n)x \gets \textsc{ModPow}(a, d, n)
  3. 3
    if x=1x = 1 or x=n1x = n - 1 then return true
    probably prime
  4. 4
    repeat s1s - 1 times
  5. 5
    x(xx)modnx \gets (x \cdot x) \bmod n
  6. 6
    if x=n1x = n - 1 then return true
    hit 1-1
  7. 7
    return false
    nontrivial 1\sqrt 1 ⇒ composite

With random witnesses, each composite is exposed by at least three quarters of the possible , so independent rounds leave a false-:qprime probability below , and crucially, Carmichael numbers are not immune, because the square-root test sees structure the Fermat test cannot. Better still, the test can be made deterministic for bounded inputs: there is a fixed small set of bases that never errs below a threshold. Testing against the first twelve primes is a proven-correct deterministic primality test for all , covering every 64-bit (indeed every 80-bit) integer with a dozen calls.4

Miller–Rabin decides whether is prime but never produces a factor. Factoring a large composite is a separate, much harder problem; Pollard's rho finds a nontrivial factor in expected time using a cycle-detection trick on , and is the standard tool for splitting numbers too big for trial division. (The next lesson handles factoring small numbers wholesale with a sieve.)

Why this matters: cryptography

These two ingredients, fast modular exponentiation and fast primality testing, are the beating heart of public-key cryptography. RSA picks two large random primes (found by Miller–Rabin), and both encryption and decryption are a single modular exponentiation . Diffie–Hellman key exchange computes the same way. In every case the security rests on a power being easy to compute but its inverse (factoring , or the discrete logarithm) being infeasible, and is what makes the easy direction .

Takeaways

  • Binary exponentiation computes in multiplications by repeated squaring, reading the bits of and multiplying in each square whose bit is ; reduce mod every step, and guard against overflow with 128-bit or arithmetic. The same doubling gives Fibonacci via matrix powers.
  • Fermat's little theorem () gives the modular inverse for a prime modulus; Euler's theorem generalizes it to for any coprime .
  • Trial division tests divisors up to in time, deterministic, fine for one moderate number.
  • The Fermat test detects composites probabilistically but is fooled by Carmichael numbers for every coprime witness.
  • Miller–Rabin writes and watches the square-root chain collapse to , catching the nontrivial square roots that betray a composite; it is probabilistic with random witnesses and deterministic below with the first twelve primes as bases.
  • Modular exponentiation and primality testing power RSA and Diffie–Hellman; Pollard's rho handles factoring of large numbers when a factor is actually needed.

Footnotes

  1. CLRS, Ch. 31 — Number-Theoretic Algorithms (§31.6): modular exponentiation by repeated squaring in multiplications, reducing mod at each step.
  2. Skiena, § — Number Theory: Fermat's little theorem and modular inverse via for a prime modulus.
  3. CLRS, Ch. 31 — Number-Theoretic Algorithms (§31.8): the Miller–Rabin witness test built on nontrivial square roots of , with error below over rounds.
  4. Skiena, § — Number Theory: deterministic Miller–Rabin with a fixed small base set, and Pollard's rho for factoring.
Practice

╌╌ END ╌╌