1-- Division with remainder for natural numbers2-- 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.Nat.Division8import Mod9import Order1011theorem mod.division (d n : Nat)12requires nonzero : d ≠013shows (∃ q, Nat(q) ∧ n = d * q + n % d) ∧ n % d < d14proof15induction n16| zero =>17have remainder := mod.zero_left at d with*18rw remainder19constructor20 . witness021ring22 . have positive := Less.add_positive at0, d with*23 simpa [add] using positive24| succ(k) using ih =>25rcases ih with⟨division, bound⟩26obtain⟨q, qNat, equation⟩:= division27havesplit : succ(k % d) = d ∨ succ(k % d) ≠ d28 . tauto29casessplitwith wraps | advances30 . have condition := equalNat.true_iff.backward at succ(k % d), d with*31have remainder : succ(k) % d =032 . simp [mod, nextRemainder, equalNat.reflexive, condition, chooseNat]33rw remainder34have increment := add.succ_right at k % d, d * q with*35rw← equation at increment36 symm at increment37constructor38 . witness succ(q)39rw remainder40rw wraps at increment41have product : d * succ(q) +0= d * q + d42 . ring43 rwa product44 . have positive := Less.add_positive at0, d with*45 simpa [add] using positive46 . have condition := equalNat.false_iff.backward at succ(k % d), d with*47have remainder : succ(k) % d = succ(k % d)48 . simp [mod, nextRemainder, equalNat.reflexive, condition, chooseNat]49rw remainder50have increment := add.succ_right at k % d, d * q with*51rw← equation at increment52 symm at increment53constructor54 . witness q55rw remainder56exact increment57have comparison := Less.trichotomy at succ(k % d), d with*58rcases comparison with less | equal | greater59 . exact less60 . exfalso61exact advances with equal62 . arith6364theorem mod.less (n d : Nat)65requires nonzero : d ≠066shows n % d < d67proof68have division := mod.division at d, n with*69tauto7071theorem mod.equation (n d : Nat)72requires nonzero : d ≠073shows∃ q, Nat(q) ∧ n = d * q + n % d74proof75have division := mod.division at d, n with*76tauto7778-- Count exactly the same wraps as mod. Division by zero returns zero.79def quotientNat (n d : Nat) →Nat80| zero, d => zero81| succ(n), d => chooseNat(equalNat(succ(n % d), d), succ(quotientNat(n, d)), quotientNat(n, d))8283theorem quotientNat.natural (d n : Nat)84showsNat(quotientNat(n, d))85proof86induction n87| zero =>88simp [quotientNat]89typecheck90| succ(k) using ih =>91have boolean := equalNat.boolean at succ(k % d), d with*92have natural := chooseNat.natural at equalNat(succ(k % d), d), succ(quotientNat(k, d)), quotientNat(k, d) with*93 simpa [quotientNat] using natural9495theorem quotientNat.equation (d n : Nat)96shows n = d * quotientNat(n, d) + n % d97proof98induction n99| zero =>simp [quotientNat, mod, mul.right_zero, add]100| succ(k) using ih =>101havesplit : succ(k % d) = d ∨ succ(k % d) ≠ d102 . tauto103casessplitwith wraps | advances104 . have condition := equalNat.true_iff.backward at succ(k % d), d with*105have remainder : succ(k) % d =0106 . simp [mod, nextRemainder, condition, equalNat.reflexive, chooseNat]107have quotient : quotientNat(succ(k), d) = succ(quotientNat(k, d))108 . simp [quotientNat, condition, equalNat.reflexive, chooseNat]109have increment := add.succ_right at k % d, d * quotientNat(k, d) with*110rw← ih at increment111 symm at increment112rw [quotient, remainder]113rw wraps at increment114have product : d * succ(quotientNat(k, d)) +0= d * quotientNat(k, d) + d115 . ring116 rwa product117 . have condition := equalNat.false_iff.backward at succ(k % d), d with*118have remainder : succ(k) % d = succ(k % d)119 . simp [mod, nextRemainder, condition, equalNat.reflexive, chooseNat]120have quotient : quotientNat(succ(k), d) = quotientNat(k, d)121 . simp [quotientNat, condition, equalNat.reflexive, chooseNat]122have increment := add.succ_right at k % d, d * quotientNat(k, d) with*123rw← ih at increment124 symm at increment125rw quotient126 rwa remainder127128theorem quotientNat.zero_right (n : Nat)129shows quotientNat(n, 0) =0130proof131induction n132| zero =>simp [quotientNat]133| succ(k) using ih =>134have nonzero : succ(k %0) ≠0135 . intro equal136have distinct := Naturals.disjoint.zero.succ at k %0137 symm at equal138exact distinct with equal139have condition := equalNat.false_iff.backward at succ(k %0), 0with*140simp [quotientNat, condition, equalNat.reflexive, chooseNat]141142theorem quotientNat.division (n d : Nat)143requires nonzero : d ≠0144showsNat(quotientNat(n, d)) ∧ n = d * quotientNat(n, d) + n % d ∧ n % d < d145proof146simp [quotientNat.natural, quotientNat.equation, mod.less]147148-- Dividing a bound through by a positive coefficient: these two tightenings149-- keep linear arithmetic over the naturals exact when every coefficient of150-- an atom shares a factor. The coefficient is written succ(k) so that it is151-- visibly nonzero.152theorem LessEqual.quotient_floor (a b k d : Nat)153requires bound : succ(k) * a ≤ succ(k) * b + d154shows a ≤ b + quotientNat(d, succ(k))155proof156have nonzero : succ(k) ≠0157intro zero158have disjoint := Naturals.disjoint.zero.succ at k159apply disjoint160 symm at zero161exact zero162obtain⟨qNat, equation, remainder⟩:= quotientNat.division at d, succ(k) with nonzero163by_contra refuted164have strict := Less.of_not_LessEqual with refuted165have scaled := LessEqual.mul_left at succ(b + quotientNat(d, succ(k))), a, succ(k) with strict166have expand : succ(k) * succ(b + quotientNat(d, succ(k))) = succ(k) * b + succ(k) * quotientNat(d, succ(k)) + succ(k)167ring168rw expand at scaled169rw equation at bound170have cycle : succ(k) * a < succ(k) * a byarith171exact Less.irreflexive with*, cycle172173theorem LessEqual.quotient_ceiling (a b k e : Nat)174requires bound : succ(k) * a + (e +1) ≤ succ(k) * b175shows a + (quotientNat(e, succ(k)) +1) ≤ b176proof177have nonzero : succ(k) ≠0178intro zero179have disjoint := Naturals.disjoint.zero.succ at k180apply disjoint181 symm at zero182exact zero183obtain⟨qNat, equation, remainder⟩:= quotientNat.division at e, succ(k) with nonzero184by_contra refuted185have strict := Less.of_not_LessEqual with refuted186have scaled := LessEqual.mul_left at succ(b), a + (quotientNat(e, succ(k)) +1), succ(k) with strict187haveleft : succ(k) * succ(b) = succ(k) * b + succ(k) byring188haveright : succ(k) * (a + (quotientNat(e, succ(k)) +1)) = succ(k) * a + succ(k) * quotientNat(e, succ(k)) + succ(k)189ring190rw [left, right] at scaled191rw equation at bound192have cycle : succ(k) * b < succ(k) * b byarith193exact Less.irreflexive with*, cycle194