1-- Parity of products, powers, and remainders modulo two2-- 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.ParityLemmas8import Parity9import PowLemmas10import Division1112theorem Even.two_mul (k : Nat)13shows Even(2* k)14proof15have doubled := mul.two_left at k16rw doubled17exact Even.double with*1819theorem Even.mul_two (k : Nat)20shows Even(k *2)21proof22have swap := mul.commutative at2, k with*23rw swap24exact Even.two_mul with*2526theorem Even.iff_two_mul (n : Nat)27shows Even(n) ↔∃ k, Nat(k) ∧ n =2* k28proof29constructor30 . intro even31obtain⟨k, kMember, equation⟩:= even32have kNat := nat.omega.backward with kMember33witness k34rw equation35ring36 . intro shape37obtain⟨k, kNat, equation⟩:= shape38rw equation39exact Even.two_mul with*4041theorem Odd.iff_two_mul_add_one (n : Nat)42shows Odd(n) ↔∃ k, Nat(k) ∧ n =2* k +143proof44constructor45 . intro odd46obtain⟨k, kMember, equation⟩:= odd47have kNat := nat.omega.backward with kMember48witness k49rw equation50ring51 . intro shape52obtain⟨k, kNat, equation⟩:= shape53have doubled := mul.two_left at k54have step : 2* k +1= succ(k + k) byring55rw [equation, step]56exact Odd.double_successor with*5758theorem Odd.one59shows Odd(1)60proof61have doubled := Odd.double_successor at062 simpa [add] using doubled6364theorem Even.not_one65shows¬Even(1)66proof67have one := Odd.one68exact Odd.not_even with one6970theorem Odd.add_one_iff (n : Nat)71shows Odd(n +1) ↔ Even(n)72proof73have shape := add.right_one at n74rw shape75exact Odd.succ_iff with*7677theorem Odd.positive (n : Nat)78requires odd : Odd(n)79shows0 < n80proof81obtain⟨k, kMember, equation⟩:= odd82have kNat := nat.omega.backward with kMember83rw equation84have step : succ(k + k) = k + k +1byring85rw step86linarith8788theorem Even.mul_left (a b : Nat)89requires even : Even(a)90shows Even(a * b)91proof92obtain⟨k, kNat, equation⟩:= Even.iff_two_mul.forward with even93apply Even.iff_two_mul.backward94witness k * b95rw equation96ring9798theorem Even.mul_right (a b : Nat)99requires even : Even(b)100shows Even(a * b)101proof102have swap := mul.commutative at b, a with*103rw swap104exact Even.mul_left with even105106theorem Odd.mul (a b : Nat)107requires first : Odd(a)108requires second : Odd(b)109shows Odd(a * b)110proof111obtain⟨k, kNat, aShape⟩:= Odd.iff_two_mul_add_one.forward with first112obtain⟨m, mNat, bShape⟩:= Odd.iff_two_mul_add_one.forward with second113apply Odd.iff_two_mul_add_one.backward114witness2* k * m + k + m115rw [aShape, bShape]116ring117118theorem Even.of_mul (a b : Nat)119requires even : Even(a * b)120shows Even(a) ∨ Even(b)121proof122have aSplit := parity.exhaustive at a123cases aSplit with aEven | aOdd124 . left125exact aEven126 . have bSplit := parity.exhaustive at b127cases bSplit with bEven | bOdd128 . right129exact bEven130 . have odd := Odd.mul with aOdd, bOdd131exfalso132exact Odd.not_even with odd, even133134theorem Odd.of_mul (a b : Nat)135requires odd : Odd(a * b)136shows Odd(a) ∧ Odd(b)137proof138have aSplit := parity.exhaustive at a139have bSplit := parity.exhaustive at b140constructor141 . cases aSplit with aEven | aOdd142 . have even := Even.mul_left at a, b with aEven143exfalso144exact Even.not_odd with even, odd145 . exact aOdd146 . cases bSplit with bEven | bOdd147 . have even := Even.mul_right at a, b with bEven148exfalso149exact Even.not_odd with even, odd150 . exact bOdd151152theorem Even.mul_self_iff (n : Nat)153shows Even(n * n) ↔ Even(n)154proof155constructor156 . intro even157havesplit:= Even.of_mul with even158casessplitwith first | second159 . exact first160 . exact second161 . intro even162exact Even.mul_left with even163164theorem Odd.mul_self_iff (n : Nat)165shows Odd(n * n) ↔ Odd(n)166proof167constructor168 . intro odd169have both := Odd.of_mul with odd170exact both.left171 . intro odd172exact Odd.mul with odd, odd173174theorem Even.pow (a n : Nat)175requires even : Even(a)176shows Even(a ^ (n +1))177proof178have powNat := pow.closed at a, n179rw pow.add_one180exact Even.mul_left with even181182theorem Odd.pow (a n : Nat)183requires odd : Odd(a)184shows Odd(a ^ n)185proof186induction n187| zero =>188rw pow.zero189exact Odd.one190| succ(k) using ih =>191have powNat := pow.closed at a, k192rw pow.succ193exact Odd.mul with odd, ih194195theorem Even.of_pow (a n : Nat)196requires even : Even(a ^ n)197shows Even(a)198proof199havesplit:= parity.exhaustive at a200casessplitwith aEven | aOdd201 . exact aEven202 . have odd := Odd.pow at a, n with aOdd203exfalso204exact Odd.not_even with odd, even205206theorem Even.of_add_even (a b : Nat)207requires sum : Even(a + b)208requires even : Even(a)209shows Even(b)210proof211havesplit:= parity.exhaustive at b212casessplitwith bEven | bOdd213 . exact bEven214 . have odd := Odd.even_add at a, b with even, bOdd215exfalso216exact Odd.not_even with odd, sum217218theorem Odd.of_add_even_odd (a b : Nat)219requires sum : Even(a + b)220requires odd : Odd(a)221shows Odd(b)222proof223havesplit:= parity.exhaustive at b224casessplitwith bEven | bOdd225 . have sumOdd := Odd.add_even at a, b with odd, bEven226exfalso227exact Odd.not_even with sumOdd, sum228 . exact bOdd229230theorem Odd.of_add_odd_even (a b : Nat)231requires sum : Odd(a + b)232requires even : Even(a)233shows Odd(b)234proof235havesplit:= parity.exhaustive at b236casessplitwith bEven | bOdd237 . have sumEven := Even.add at a, b with even, bEven238exfalso239exact Even.not_odd with sumEven, sum240 . exact bOdd241242theorem Even.of_add_odd_odd (a b : Nat)243requires sum : Odd(a + b)244requires odd : Odd(a)245shows Even(b)246proof247havesplit:= parity.exhaustive at b248casessplitwith bEven | bOdd249 . exact bEven250 . have sumEven := Odd.add_odd at a, b with odd, bOdd251exfalso252exact Even.not_odd with sumEven, sum253254theorem Even.add_iff (a b : Nat)255shows Even(a + b) ↔ (Even(a) ↔ Even(b))256proof257have aSplit := parity.exhaustive at a258constructor259 . intro sum260constructor261 . intro aEven262exact Even.of_add_even with sum, aEven263 . intro bEven264have swap := add.commutative at b, a with*265rw swap at sum266exact Even.of_add_even at b, a with sum, bEven267 . intro same268cases aSplit with aEven | aOdd269 . have bEven := same.forward with aEven270exact Even.add with aEven, bEven271 . have bOdd : Odd(b)272havesplit:= parity.exhaustive at b273casessplitwith bEven | odd274 . have aEven := same.backward with bEven275exfalso276exact Odd.not_even with aOdd, aEven277 . exact odd278exact Odd.add_odd with aOdd, bOdd279280theorem Even.mod_two (n : Nat)281shows Even(n) ↔ n %2=0282proof283have two : 2≠0284intro zero285have impossible : 0 < 2bylinarith286rw zero at impossible287exact Less.irreflexive with impossible288have division := mod.division at2, n with two289rcases division with⟨equation, bound⟩290obtain⟨q, qNat, shape⟩:= equation291have modNat := mod.natural at2, n292have remainder : n %2=0∨ n %2=1293have small : n %2≤1bylinarith294havesplit:= LessEqual.cases with small295casessplitwith strict | one296 . left297have zero : n %2≤0bylinarith298exact LessEqual.eq_zero with zero299 . right300exact one301constructor302 . intro even303cases remainder with zero | one304 . exact zero305 . rw one at shape306have odd : Odd(n)307apply Odd.iff_two_mul_add_one.backward308witness q309exact shape310exfalso311exact Odd.not_even with odd, even312 . intro zero313rw zero at shape314apply Even.iff_two_mul.backward315witness q316have unit := add.right_unit at2* q317rw unit at shape318exact shape319320theorem Odd.mod_two (n : Nat)321shows Odd(n) ↔ n %2=1322proof323have two : 2≠0324intro zero325have impossible : 0 < 2bylinarith326rw zero at impossible327exact Less.irreflexive with impossible328have modNat := mod.natural at2, n329have bound := mod.less at n, 2with two330constructor331 . intro odd332have notEven := Odd.not_even with odd333have nonzero : n %2≠0334intro zero335have even := Even.mod_two.backward with zero336exact notEven with even337have positive := Less.positive_of_ne_zero with nonzero338have upper : n %2≤1bylinarith339have lower : 1≤ n %2bylinarith340exact LessEqual.antisymmetric with upper, lower341 . intro one342havesplit:= parity.exhaustive at n343casessplitwith even | odd344 . have zero := Even.mod_two.forward with even345rw zero at one346have impossible : 0 < 1bylinarith347rw← one at impossible348exfalso349exact Less.irreflexive with impossible350 . exact odd351