1-- Further divisibility laws for the natural numbers: truncated subtraction,2-- powers, cancellation of a common factor, remainders, minimum and maximum,3-- parity, the distance between naturals, and factorials4-- Part of Cumulus, the Grace17 mathematics library.5-- Copyright (c) 2026 Grant Passmore.6-- Released under the Apache License 2.0. See LICENSE in the repository root.7-- Authors: Grant Passmore89module Grace.Cumulus.NumberTheory.DivisibilityMore10import Modular11import Nat.Distance1213theorem divides.intro (a b k : Nat)14requires product : a * k = b15shows a ∣ b16proof17witness k18exact product1920theorem divides.of_eq (a b : Nat)21requires same : a = b22shows a ∣ b23proof24rw same25exact divides.reflexive at b2627theorem divides.mul_left_self (a b : Nat)28shows a ∣ a * b29proof30witness b31rfl3233theorem divides.mul_right_self (a b : Nat)34shows a ∣ b * a35proof36witness b37ring3839theorem divides.mul_self (a b : Nat)40requires hab : a ∣ b41shows a ∣ b * b42proof43exact divides.multiply_right with hab4445theorem divides.of_mul_left (a b c : Nat)46requires product : a * b ∣ c47shows a ∣ c48proof49have factor := divides.mul_left_self at a, b50exact divides.transitive at a, a * b, c with factor, product5152theorem divides.of_mul_right (a b c : Nat)53requires product : a * b ∣ c54shows b ∣ c55proof56have factor := divides.mul_right_self at b, a57exact divides.transitive at b, a * b, c with factor, product5859theorem divides.mul_mono (a b c d : Nat)60requiresleft : a ∣ b61requiresright : c ∣ d62shows a * c ∣ b * d63proof64obtain⟨k, kNat, kEquation⟩:=left65obtain⟨l, lNat, lEquation⟩:=right66witness k * l67rw [← kEquation, ← lEquation]68ring6970theorem divides.mul_cancel_left (a b c : Nat)71requires nonzero : a ≠072shows a * b ∣ a * c ↔ b ∣ c73proof74constructor75 . intro scaled76obtain⟨k, kNat, equation⟩:= scaled77have rearranged : a * (b * k) = a * c78 . rw← equation79ring80have cancelled := mul.left_cancel_positive with nonzero, rearranged81witness k82exact cancelled83 . intro plain84obtain⟨k, kNat, equation⟩:= plain85witness k86rw← equation87ring8889theorem divides.mul_cancel_right (a b c : Nat)90requires nonzero : a ≠091shows b * a ∣ c * a ↔ b ∣ c92proof93haveleft : b * a = a * b byring94haveright : c * a = a * c byring95rw [left, right]96exact divides.mul_cancel_left with nonzero9798theorem divides.zero_iff (a : Nat)99shows0 ∣ a ↔ a =0100proof101constructor102 . intro h103exact zero.divides_only_zero with h104 . intro zero105rw zero106exact divides.reflexive at0107108theorem divides.one_iff (a : Nat)109shows a ∣ 1↔ a =1110proof111constructor112 . intro h113exact divides.one_only at a with*114 . intro one115rw one116exact divides.reflexive at1117118theorem divides.antisymmetric_iff (a b : Nat)119shows a ∣ b ∧ b ∣ a ↔ a = b120proof121constructor122 . intro both123rcases both with⟨forward, backward⟩124exact divides.antisymmetric with forward, backward125 . intro same126rw same127have reflexive := divides.reflexive at b128exact⟨reflexive, reflexive⟩129130theorem divides.nonzero (a b : Nat)131requires hab : a ∣ b132requires nonzero : b ≠0133shows a ≠0134proof135intro zero136rw zero at hab137have bZero := zero.divides_only_zero with hab138exact nonzero with bZero139140theorem divides.lt_of_ne (a b : Nat)141requires hab : a ∣ b142requires nonzero : b ≠0143requires distinct : a ≠ b144shows a < b145proof146have below := divides.le at a, b with hab, nonzero147exact Less.of_LessEqual_ne with below, distinct148149theorem divides.factor_le (a b k : Nat)150requires product : a * k = b151requires nonzero : b ≠0152shows k ≤ b153proof154have factor : k ∣ b155witness a156rw← product157ring158exact divides.le at k, b with factor, nonzero159160theorem divides.sub (a b c : Nat)161requiresleft : a ∣ b162requiresright : a ∣ c163shows a ∣ b - c164proof165have total := LessEqual.total at c, b166cases total with below | above167 . havesplit:= sub.add_cancel_left at b, c with below168rw←splitatleft169exact divides.add_cancel_left at a, c, b - c withright, left170 . have zero := sub.eq_zero_of_le at b, c with above171rw zero172exact divides.zero at a173174theorem divides.of_sub (a b c : Nat)175requires below : c ≤ b176requiresright : a ∣ c177requires difference : a ∣ b - c178shows a ∣ b179proof180havesplit:= sub.add_cancel_left at b, c with below181rw←split182exact divides.add at a, c, b - c withright, difference183184theorem divides.natDist (a b c : Nat)185requiresleft : a ∣ b186requiresright : a ∣ c187shows a ∣ natDist(b, c)188proof189have first := divides.sub at a, b, c withleft, right190have second := divides.sub at a, c, b withright, left191have value := natDist.value at b, c192rw value193exact divides.add at a, b - c, c - b with first, second194195theorem divides.pow (a b n : Nat)196requires hab : a ∣ b197shows a ∣ b ^ (n +1)198proof199have expand := pow.add_one at b, n200rw expand201exact divides.multiply_right with hab202203theorem divides.self_pow (a n : Nat)204shows a ∣ a ^ (n +1)205proof206have reflexive := divides.reflexive at a207exact divides.pow with reflexive208209theorem divides.pow_of_le (a m n : Nat)210requires below : m ≤ n211shows a ^ m ∣ a ^ n212proof213obtain⟨k, kNat, split⟩:= LessEqual.exists_add with below214rwsplit215have expand := pow.add at a, k, m216rw expand217exact divides.mul_left_self at a ^ m, a ^ k218219theorem divides.pow_mono (a b n : Nat)220requires hab : a ∣ b221shows a ^ n ∣ b ^ n222proof223obtain⟨k, kNat, equation⟩:= hab224witness k ^ n225rw← equation226 symm227exact pow.mul_base at a, k, n228229theorem divides.two_iff_even (n : Nat)230shows2 ∣ n ↔ Even(n)231proof232have characterization := Even.iff_two_mul at n233constructor234 . intro h235obtain⟨k, kNat, equation⟩:= h236apply characterization.backward237refine⟨k, kNat, _⟩238 symm239exact equation240 . intro h241obtain⟨k, kNat, equation⟩:= characterization.forward with h242witness k243 symm244exact equation245246theorem divides.not_two_iff_odd (n : Nat)247shows¬(2 ∣ n) ↔ Odd(n)248proof249have even := divides.two_iff_even at n250have odd := Odd.iff_not_even at n251constructor252 . intro notDivides253apply odd.backward254intro isEven255exact notDivides with (even.backward with isEven)256 . intro isOdd257intro h258have isEven := even.forward with h259exact odd.forward with isOdd, isEven260261theorem divides.iff_mod_zero (d n : Nat)262shows d ∣ n ↔ n % d =0263proof264havesplit : d =0∨ d ≠0bytauto265casessplitwith zero | nonzero266 . rw zero267have value := mod.zero_right at n268rw value269exact divides.zero_iff at n270 . have characterization := mod.zero_iff at d, n with nonzero271constructor272 . intro h273exact characterization.backward with h274 . intro h275exact characterization.forward with h276277theorem divides.mod (d n m : Nat)278requiresleft : d ∣ n279requiresright : d ∣ m280shows d ∣ n % m281proof282havesplit : m =0∨ m ≠0bytauto283casessplitwith zero | nonzero284 . rw zero285have value := mod.zero_right at n286rw value287exactleft288 . obtain⟨q, qNat, equation⟩:= mod.equation at n, m with nonzero289have multiple := divides.multiply_right at d, m, q withright290rw equation atleft291exact divides.add_cancel_left at d, m * q, n % m with multiple, left292293theorem divides.mod_iff (d n m : Nat)294requiresright : d ∣ m295shows d ∣ n ↔ d ∣ n % m296proof297havesplit : m =0∨ m ≠0bytauto298casessplitwith zero | nonzero299 . rw zero300have value := mod.zero_right at n301rw value302tauto303 . obtain⟨q, qNat, equation⟩:= mod.equation at n, m with nonzero304exact divides.remainder_iff at d, n, m, q, n % m with equation, right305306theorem divides.add_right_iff (a b c : Nat)307requires hab : a ∣ b308shows a ∣ b + c ↔ a ∣ c309proof310constructor311 . intro sum312exact divides.add_cancel_left at a, b, c with hab, sum313 . intro hac314exact divides.add at a, b, c with hab, hac315316theorem divides.add_left_iff (a b c : Nat)317requires hac : a ∣ c318shows a ∣ b + c ↔ a ∣ b319proof320have commute : b + c = c + b byring321rw commute322exact divides.add_right_iff at a, c, b with hac323324theorem divides.add_mul_iff (a b k : Nat)325shows a ∣ b + a * k ↔ a ∣ b326proof327have multiple := divides.mul_left_self at a, k328exact divides.add_left_iff at a, b, a * k with multiple329330theorem divides.natMin (a b c : Nat)331requiresleft : a ∣ b332requiresright : a ∣ c333shows a ∣ natMin(b, c)334proof335have alternatives := natMin.cases at b, c336cases alternatives with first | second337 . rw first338exactleft339 . rw second340exactright341342theorem divides.natMax (a b c : Nat)343requiresleft : a ∣ b344requiresright : a ∣ c345shows a ∣ natMax(b, c)346proof347have alternatives := natMax.cases at b, c348cases alternatives with first | second349 . rw first350exactleft351 . rw second352exactright353354theorem divides.quotient_equation (a b : Nat)355requires nonzero : a ≠0356requires hab : a ∣ b357shows b = a * quotientNat(b, a)358proof359have equation := quotientNat.equation at a, b360have remainder := divides.iff_mod_zero at a, b361have zero := remainder.forward with hab362rw zero at equation363have shape : a * quotientNat(b, a) +0= a * quotientNat(b, a) byring364rw shape at equation365exact equation366367theorem divides.quotient (a b : Nat)368requires nonzero : a ≠0369requires hab : a ∣ b370shows quotientNat(b, a) ∣ b371proof372have equation := divides.quotient_equation with nonzero, hab373witness a374have shape : quotientNat(b, a) * a = a * quotientNat(b, a) byring375rw shape376 symm377exact equation378379theorem divides.factorial_of_le (p n : Nat)380requires positive : 0 < p381requires below : p ≤ n382shows p ∣ n!383proof384have zeroMember := membership.of_Less at0, p with*, positive385have bound : p < succ(n) byarith386have member := membership.of_Less at p, succ(n) with*, bound387exact factorial.divisible_through at p, n with*, zeroMember, member388