Purpose: Perform modular multiplication without any division, replacing % with shifts and multiplications. Typically 2-3Γ— faster than % when the modulus is fixed and you do millions of multiplications β€” the standard speedup inside NTT, Miller-Rabin and Pollard’s rho.

The Idea

Fix an odd modulus and a radix (in code, or , so division by is a free shift).

Work in the Montgomery domain: represent by .

The reduction REDC(T) computes for :

where . The numerator is divisible by by construction, so the division is exact and free. If , subtract once.

Then , so a domain multiplication is one REDC.

Code

struct Montgomery {
    uint64_t n, ninv, r2;                       // ninv = -n^{-1} mod 2^64
 
    Montgomery(uint64_t mod) : n(mod) {
        ninv = 1;
        for (int i = 0; i < 6; i++) ninv *= 2 - n * ninv;   // Newton, doubles bits
        ninv = -ninv;
        r2 = (__uint128_t(-(unsigned long long)n)) % n;      // R^2 mod n
    }
 
    uint64_t reduce(__uint128_t t) const {
        uint64_t m = (uint64_t)t * ninv;
        uint64_t res = (t + (__uint128_t)m * n) >> 64;
        return res >= n ? res - n : res;
    }
 
    uint64_t to(uint64_t a)   const { return reduce((__uint128_t)a * r2); }
    uint64_t from(uint64_t a) const { return reduce(a); }
    uint64_t mul(uint64_t a, uint64_t b) const { return reduce((__uint128_t)a * b); }
};

The Newton iteration ninv *= 2 - n * ninv doubles the number of correct bits each round, so six rounds suffice for 64 bits starting from 1 correct bit.

Complexity

  • One REDC: two 64Γ—64β†’128 multiplications plus a shift and a conditional subtract; no division
  • Conversion in and out costs one REDC each β€” only worth it if you do many operations in the domain

Why It Works

, and was chosen precisely so that . Hence is an integer congruent to . Bounding: and , so , meaning at most one conditional subtraction restores the range. ∎

Addition and subtraction are unchanged by the representation (), so only multiplication needs the reduction. Comparison and equality also work directly, since the map is a bijection.

Odd modulus only

must be odd for to exist. For even moduli, split with CRT or use Barrett reduction instead.

Variants / Use Cases

  • Barrett reduction β€” works for even moduli and needs no domain conversion; slightly slower per operation but simpler to drop in
  • NTT β€” the inner butterfly is a modmul; Montgomery is the standard optimisation
  • Miller-Rabin and Pollard’s rho on 64-bit inputs
  • RSA / ECC β€” Montgomery is why modular exponentiation is fast in every crypto library
  • Modular Arithmetic β€” the topic page