powMod: binary modular exponentiation for kernel-decide modular arithmetic #
ZModDecide decides a ground ZMod m ring identity by a bounded integer-residue
computation, reducing % m after every operation. Its pow node computes base ^ n
in full before the final % m, so a huge exponent — a Legendre-symbol exponent
(p - 1) / 2 ≈ 2 ^ 380 at BLS12-381 size — builds an astronomically large
intermediate and stalls the kernel.
This module supplies the missing piece: a square-and-multiply modular exponentiation
powMod b e m that reduces % m after every squaring and multiply, so no intermediate
exceeds m ^ 2. The recursion is structural on a fuel argument, and the fuel is only a
termination certificate — the e = 0 guard halts the loop after ⌈log₂ e⌉ steps — so
the Lean kernel reduces a fully applied powMod in a logarithmic number of steps and
decide stays on the GMP Nat fast path.
On top of it sit two number-theoretic deciders whose exponents were previously out of reach: a modular inverse via Fermat's little theorem, and a quadratic-residue test via Euler's criterion.
Main results #
powMod/powModGo— square-and-multiply modular exponentiation and its fuelled worker.powMod_cast— the correctness lemma:(powMod b e m : ZMod m) = (b : ZMod m) ^ e.powMod_lt— the output is a residue,powMod b e m < mfor1 < m.invMod/invMod_cast— modular inverse for a prime modulus,a ^ (p - 2) % p, correct as(a : ZMod p)⁻¹.isSquare_of_powMod/not_isSquare_of_powMod— the Euler-criterion quadratic-residue decider:IsSquare (a : ZMod p)reduces to a kerneldecideonpowMod a.val (p / 2) p = 1.
Binary modular exponentiation #
Square-and-multiply worker for modular exponentiation. fuel bounds the number of
squarings; base is the running square b ^ (2 ^ k), e the remaining exponent bits,
and acc the accumulated product, all kept reduced % m. The e = 0 guard halts the
loop, so the actual recursion depth is the bit length of the initial exponent.
Equations
- One or more equations did not get rendered due to their size.
- Transfer.ZModPowMod.powModGo m 0 x✝² x✝¹ x✝ = x✝
Instances For
b ^ e mod m by square-and-multiply, reducing % m after every operation. Fuel e
is a termination certificate (e < 2 ^ e); the e = 0 guard in powModGo stops the
loop after ⌈log₂ e⌉ steps, so a fully applied powMod reduces in the kernel in a
logarithmic number of GMP Nat operations.
Equations
- Transfer.ZModPowMod.powMod b e m = Transfer.ZModPowMod.powModGo m e (b % m) e (1 % m)
Instances For
Modular inverse via Fermat's little theorem #
Modular inverse of a modulo a prime p, computed as a ^ (p - 2) mod p.
Equations
- Transfer.ZModPowMod.invMod a p = Transfer.ZModPowMod.powMod a (p - 2) p
Instances For
Quadratic residues via Euler's criterion #
Euler-criterion quadratic-residue witness. For a concrete nonzero a : ZMod p
with p prime, a kernel decide on powMod a.val (p / 2) p = 1 proves IsSquare a.