Add two reduced residues using wrapped machine-word addition plus one
correction step when p < 2^64.
8.4. Principal operations
The ring operations add, subtract, negate, and multiply residues,
re-reducing each result so the output is again a standard
representative. The standard Add, Sub, Neg, and Mul instances on
Hex.ZMod64 dispatch to these, so a + b, a - b, -a, and
a * b work directly, and a Lean.Grind.CommRing instance lets the
grind tactic reason about them.
Subtract two residues by adding the modular complement of the second and
reducing mod p.
The additive inverse represented by the complementary residue mod p.
Multiply two reduced residues and reduce the product mod p.
The trusted runtime contract is the lean_hex_zmod64_mul extern, whose C body
must agree with this pure Lean fallback.
Exponentiation uses repeated squaring, and inversion runs the
extended-GCD helper from HexArith. For an element coprime to the
modulus the result is the modular inverse.
Raise a residue to a natural power using exponentiation by squaring.
The accumulator form keeps the executable path close to the intended downstream runtime usage while preserving a simple semantic contract.
Compute a modular inverse candidate via the integer extended-GCD helper from
hex-arith.
When a is coprime to p, this is the canonical inverse mod p; otherwise it
still exposes the executable Bezout-derived residue needed by later algebraic
layers.
8.4.1. Worked example: ring arithmetic
The block below works in ZMod64 7. After supplying the Bounds 7
instance it builds two residues and runs the ring operations on them.
open Hex Hex.ZMod64
namespace HexModArithChapterRing
instance : Bounds 7 := ⟨⊢ 0 < 7 All goals completed! 🐙, ⊢ 7 ≤ UInt64.word All goals completed! 🐙⟩
-- a = 3 and b = 5 as residues mod 7.
def a : ZMod64 7 := ofNat 7 3
def b : ZMod64 7 := ofNat 7 5
-- Literals reduce: 10 ≡ 3 (mod 7).
#guard a.toNat = 3
#guard (10 : ZMod64 7).toNat = 3
-- 3 + 5 = 8 ≡ 1.
#guard (a + b).toNat = 1
-- 3 - 5 ≡ -2 ≡ 5.
#guard (a - b).toNat = 5
-- 3 · 5 = 15 ≡ 1.
#guard (a * b).toNat = 1
-- 3^5 = 243 ≡ 5.
#guard (a ^ 5).toNat = 5
-- 3⁻¹ ≡ 5, since 3 · 5 ≡ 1.
#guard (inv a).toNat = 5
#guard (inv a * a).toNat = 1
end HexModArithChapterRing