1-- Coprime cancellation and modular inverses from Bézout2-- Part of Cumulus, the Grace17 mathematics library.3-- Copyright (c) 2026 Grant Passmore.4-- Released under the Apache License 2.0. See LICENSE in the repository root.5-- Authors: Grant Passmore67module Grace.Cumulus.NumberTheory.Coprime8import IntegerGCD910predicate IntegerCoprime (a b : Integer) := integerGCD(a, b) =111predicate IntegerCongruent (m a b : Integer) := IntegerDivides(m, a - b)1213theorem IntegerDivides.linear_combination (d a b u v : Integer)14requiresleft : IntegerDivides(d, a)15requiresright : IntegerDivides(d, b)16shows IntegerDivides(d, u * a + v * b)17proof18obtain⟨p, pInteger, leftEquation⟩:=left19obtain⟨q, qInteger, rightEquation⟩:=right20witness u * p + v * q21rw [← leftEquation, ← rightEquation]22ring2324theorem IntegerCoprime.symmetric (a b : Integer)25requires coprime : IntegerCoprime(a, b)26shows IntegerCoprime(b, a)27proof28unfold IntegerCoprime29rw integerGCD.commutative30exact coprime3132theorem IntegerCoprime.bezout (a b : Integer)33requires coprime : IntegerCoprime(a, b)34shows∃ u, Integer(u) ∧∃ v, Integer(v) ∧ u * a + v * b = integerOne35proof36have identity := integerGCD.bezout at a, b with*37unfold IntegerCoprime at coprime38 simpa [coprime, integerOne] using identity3940-- Euclid's coprime cancellation lemma, with an explicit quotient witness.41theorem IntegerCoprime.cancel (a b c : Integer)42requires coprime : IntegerCoprime(a, b)43requires divides : IntegerDivides(a, b * c)44shows IntegerDivides(a, c)45proof46obtain⟨u, uInteger, v, vInteger, identity⟩:= IntegerCoprime.bezout at a, b with*47obtain⟨q, qInteger, equation⟩:= divides48have scaled : (u * a + v * b) * c = c49 . rw identity50ring51witness u * c + v * q52linear_combination scaled + v * equation5354theorem IntegerCongruent.reflexive (m a : Integer)55shows IntegerCongruent(m, a, a)56proof57witness integerZero58ring5960theorem IntegerCongruent.symmetric (m a b : Integer)61requires congruent : IntegerCongruent(m, a, b)62shows IntegerCongruent(m, b, a)63proof64obtain⟨q, qInteger, equation⟩:= congruent65witness -q66linear_combination -equation6768theorem IntegerCongruent.transitive (m a b c : Integer)69requires first : IntegerCongruent(m, a, b)70requires second : IntegerCongruent(m, b, c)71shows IntegerCongruent(m, a, c)72proof73obtain⟨p, pInteger, left⟩:= first74obtain⟨q, qInteger, right⟩:= second75witness p + q76linear_combinationleft+right7778-- Every integer coprime to the modulus has a multiplicative inverse modulo it.79theorem IntegerCoprime.modular_inverse (a m : Integer)80requires coprime : IntegerCoprime(a, m)81shows∃ u, Integer(u) ∧ IntegerCongruent(m, a * u, integerOne)82proof83obtain⟨u, uInteger, v, vInteger, identity⟩:= IntegerCoprime.bezout at a, m with*84witness u85witness -v86linear_combination -identity8788theorem IntegerCoprime.of_bezout (a b u v : Integer)89requires identity : u * a + v * b = integerOne90shows IntegerCoprime(a, b)91proof92haveleft:= integerGCD.divides_left at a, b with*93haveright:= integerGCD.divides_right at a, b with*94have divides := IntegerDivides.linear_combination at integerOfNat(integerGCD(a, b)), a, b, u, v with*95rw identity at divides96have magnitude := IntegerDivides.natural_left.forward at integerGCD(a, b), integerOne with*97simp [integerOne, integerNatAbs.ofNat] at magnitude98unfold IntegerCoprime99exact divides.one_only with*100101theorem IntegerCoprime.of_modular_inverse (a m u : Integer)102requires inverse : IntegerCongruent(m, a * u, integerOne)103shows IntegerCoprime(a, m)104proof105obtain⟨q, qInteger, equation⟩:= inverse106apply IntegerCoprime.of_bezout at a, m, u, -q with*{4}107linear_combination -equation108109theorem IntegerCoprime.modular_inverse_iff (a m : Integer)110shows IntegerCoprime(a, m) ↔∃ u, Integer(u) ∧ IntegerCongruent(m, a * u, integerOne)111proof112constructor113 . intro coprime114exact IntegerCoprime.modular_inverse with*115 . intro exists116obtain⟨u, uInteger, inverse⟩:= exists117exact IntegerCoprime.of_modular_inverse with*118119theorem IntegerCongruent.add (m a b c d : Integer)120requires first : IntegerCongruent(m, a, b)121requires second : IntegerCongruent(m, c, d)122shows IntegerCongruent(m, a + c, b + d)123proof124obtain⟨p, pInteger, left⟩:= first125obtain⟨q, qInteger, right⟩:= second126witness p + q127linear_combinationleft+right128129theorem IntegerCongruent.mul (m a b c d : Integer)130requires first : IntegerCongruent(m, a, b)131requires second : IntegerCongruent(m, c, d)132shows IntegerCongruent(m, a * c, b * d)133proof134obtain⟨p, pInteger, left⟩:= first135obtain⟨q, qInteger, right⟩:= second136witness p * c + b * q137linear_combination c *left+ b *right138139theorem IntegerCongruent.cancel_coprime (m a b c : Integer)140requires coprime : IntegerCoprime(m, a)141requires congruent : IntegerCongruent(m, a * b, a * c)142shows IntegerCongruent(m, b, c)143proof144unfold IntegerCongruent at congruent145have distribution : a * b - a * c = a * (b - c)146 . ring147rw distribution at congruent148unfold IntegerCongruent149exact IntegerCoprime.cancel with*150151theorem IntegerCongruent.inverse_unique (m a u v : Integer)152requires first : IntegerCongruent(m, a * u, integerOne)153requires second : IntegerCongruent(m, a * v, integerOne)154shows IntegerCongruent(m, u, v)155proof156have coprime := IntegerCoprime.of_modular_inverse at a, m, u with*157have symmetric := IntegerCoprime.symmetric with*158have reverse := IntegerCongruent.symmetric at m, a * v, integerOne with*159have same := IntegerCongruent.transitive at m, a * u, integerOne, a * v with*160exact IntegerCongruent.cancel_coprime with*161162-- Ground natural arithmetic can certify a congruence of embedded integers.163theorem IntegerCongruent.of_natural_difference (m a b q : Nat)164requires equation : a = b + m * q165shows IntegerCongruent(integerOfNat(m), integerOfNat(a), integerOfNat(b))166proof167witness integerOfNat(q)168simp [integerOfNat.add, integerOfNat.mul]169ring170