Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - feat: port Data.Fin.Basic #1084

Closed
wants to merge 130 commits into from
Closed
Show file tree
Hide file tree
Changes from 48 commits
Commits
Show all changes
130 commits
Select commit Hold shift + click to select a range
25e5313
raw mathport: 198161d833f2c01498c39c266b0b3dbe2c7a8c07
j-loreaux Dec 15, 2022
523fd99
Finish porting
j-loreaux Dec 15, 2022
2071cfc
dot notation fixes
j-loreaux Dec 15, 2022
b40cf05
move ad hoc file
j-loreaux Dec 16, 2022
74d2ae3
raw mathport: a59dad53320b73ef180174aae867addd707ef00e
j-loreaux Dec 16, 2022
878e0a1
port up to line 955
j-loreaux Dec 16, 2022
7034fb1
Merge branch 'master' into j-loreaux/data.fin.basic
j-loreaux Dec 16, 2022
5698622
first sorry
mcdoll Dec 17, 2022
0e36725
second sorry
mcdoll Dec 17, 2022
61cbc7e
two more sorries
mcdoll Dec 17, 2022
a402d66
two more sorries
mcdoll Dec 17, 2022
f62987a
more fixes
mcdoll Dec 17, 2022
003d1ec
fixes
mcdoll Dec 17, 2022
336cc32
fixes
mcdoll Dec 17, 2022
ad1ad8e
fixes
mcdoll Dec 17, 2022
f493f02
fixes
mcdoll Dec 17, 2022
b9f9506
search and replace
mcdoll Dec 18, 2022
59344dc
fixes
mcdoll Dec 18, 2022
7f3047c
fixes
mcdoll Dec 18, 2022
df58cc0
fixes
mcdoll Dec 19, 2022
5d5b299
fixes
mcdoll Dec 19, 2022
bb5ad3a
fixes
mcdoll Dec 19, 2022
d51936f
fixes
mcdoll Dec 19, 2022
b15e9ac
fixes
mcdoll Dec 20, 2022
efded44
fixes
mcdoll Dec 20, 2022
cdf413e
fixes
mcdoll Dec 20, 2022
a294502
fixes
mcdoll Dec 20, 2022
7666306
fixes
mcdoll Dec 20, 2022
0fb70db
Merge branch 'master' into j-loreaux/data.fin.basic
jcommelin Dec 22, 2022
09dd9f4
some fixes
jcommelin Dec 22, 2022
e594fab
small fixes
ChrisHughes24 Dec 26, 2022
d30684c
one more fix
ChrisHughes24 Dec 26, 2022
3765522
fix induction_zero
ChrisHughes24 Dec 26, 2022
347698f
fix one more
ChrisHughes24 Dec 26, 2022
fdf20ed
Merge remote-tracking branch 'origin/master' into j-loreaux/data.fin.…
ChrisHughes24 Dec 28, 2022
dfc911a
one fix
ChrisHughes24 Dec 28, 2022
b27adff
wip
Ruben-VandeVelde Dec 28, 2022
797c24f
Fix
Ruben-VandeVelde Dec 29, 2022
4534bff
Partial fixes
Ruben-VandeVelde Dec 29, 2022
4d054d0
Partial fixes
Ruben-VandeVelde Dec 29, 2022
866b3bc
Partial fixes
Ruben-VandeVelde Dec 29, 2022
8fb8b31
Partial fixes
Ruben-VandeVelde Dec 29, 2022
ae56a04
Partial fixes
Ruben-VandeVelde Dec 29, 2022
0fe6007
Add ad-hoc file to Mathlib.lean
Ruben-VandeVelde Dec 29, 2022
293596d
fix wf
gebner Jan 3, 2023
0c88a72
cleanup
gebner Jan 3, 2023
0bc36ae
even shorter
gebner Jan 3, 2023
81622f0
Tiny progress
PatrickMassot Jan 3, 2023
ac69e48
Merge remote-tracking branch 'origin/master' into j-loreaux/data.fin.…
jcommelin Jan 5, 2023
f1accc0
a couple more fixes
kbuzzard Jan 5, 2023
f65daaf
fix
jcommelin Jan 6, 2023
9f9a64d
fix
jcommelin Jan 6, 2023
e7bf071
fix a bunch of names and aligns
jcommelin Jan 6, 2023
fb063d6
fix
jcommelin Jan 6, 2023
67e5fdf
fix
jcommelin Jan 6, 2023
42c0be3
fix final error, remove meta code
jcommelin Jan 6, 2023
78c03b0
a bit of simp linting
jcommelin Jan 6, 2023
eb146f2
remove out-of-date docstring, fix a statement
jcommelin Jan 6, 2023
6505ff7
better
jcommelin Jan 6, 2023
90d0411
even better
jcommelin Jan 6, 2023
c91ee49
linting
jcommelin Jan 6, 2023
081b3e9
names
jcommelin Jan 6, 2023
1040109
more names
jcommelin Jan 6, 2023
58b5067
a few linter fixes
ChrisHughes24 Jan 6, 2023
574d41c
one more linter fix
ChrisHughes24 Jan 6, 2023
3560c39
finish fixing lint
ChrisHughes24 Jan 6, 2023
abe8423
long lines
ChrisHughes24 Jan 6, 2023
1bd9c9b
Merge branch 'master' into j-loreaux/data.fin.basic
jcommelin Jan 6, 2023
c925956
long lines
jcommelin Jan 6, 2023
151080a
use lake-manifest.json from master
jcommelin Jan 6, 2023
496f5e7
remove AdHocBasic
jcommelin Jan 6, 2023
094f08a
Merge remote-tracking branch 'origin/master' into j-loreaux/data.fin.…
jcommelin Jan 6, 2023
530fb6e
fix one error
jcommelin Jan 7, 2023
803c450
is this the right direction?
jcommelin Jan 7, 2023
2c8cdfc
not sure if this is helpful
jcommelin Jan 7, 2023
853f14d
fix macro
digama0 Jan 7, 2023
372c7c1
error free ?!?!
jcommelin Jan 7, 2023
fef9823
more part of AdHoc port of Data.Fin.Basic to Data.ByteArray
jcommelin Jan 7, 2023
5f64368
linting
jcommelin Jan 7, 2023
d2f44bb
linting
jcommelin Jan 7, 2023
5c96ab6
linting
jcommelin Jan 7, 2023
c1d065b
Add latest mathport from https://github.com/leanprover-community/math…
eric-wieser Jan 7, 2023
8e9af3f
Attach latest mathport to the history of j-loreaux/data.fin.basic
eric-wieser Jan 7, 2023
5a193c6
Merge master - Note I accepted incoming changes for Data.UInt
ChrisHughes24 Jan 12, 2023
95d74a1
start fixing
ChrisHughes24 Jan 12, 2023
d1c5eff
chore: Update Lean
ChrisHughes24 Jan 12, 2023
0b8a45c
Merge branch 'update_to_nightly-2023-01-12' into j-loreaux/data.fin.b…
ChrisHughes24 Jan 12, 2023
33418c9
update in line with mathlib3 changes
ChrisHughes24 Jan 12, 2023
ac69567
Merge remote-tracking branch 'origin/master' into j-loreaux/data.fin.…
ChrisHughes24 Jan 12, 2023
190a604
fix test
ChrisHughes24 Jan 12, 2023
7277ad0
add OfNat instance
ChrisHughes24 Jan 12, 2023
195c22c
fix UInt
ChrisHughes24 Jan 12, 2023
91098b2
update file
eric-wieser Jan 12, 2023
082187b
Merge commit '91043fd87f23f06d8f243b3038fa59019635930d' into HEAD
eric-wieser Jan 12, 2023
1cc3c13
Attach latest mathport to the history of j-loreaux/data.fin.basic
eric-wieser Jan 12, 2023
b160c97
delete #print
ChrisHughes24 Jan 12, 2023
a6d05dd
fix val_one lemmas
ChrisHughes24 Jan 12, 2023
34e3394
Delete Algebraic structure notes
ChrisHughes24 Jan 12, 2023
6d63d10
Delete duplicate OfNat
ChrisHughes24 Jan 12, 2023
591c70f
naming
rwbarton Jan 12, 2023
035d954
finish fix
ChrisHughes24 Jan 12, 2023
729c859
Merge branch 'j-loreaux/data.fin.basic' of https://github.com/leanpro…
ChrisHughes24 Jan 12, 2023
6ac44d0
Fixed comments.
qawbecrdtey Jan 12, 2023
46242de
naming
rwbarton Jan 12, 2023
d7cf0ec
revert all 'was: foo' porting notes because in all cases 'foo' works
eric-wieser Jan 12, 2023
f898b71
Cleanup some mess from the adhoc port
eric-wieser Jan 12, 2023
1165365
undo bad line wrapping
eric-wieser Jan 12, 2023
bd3025a
add missing mathlib3 forward-port
eric-wieser Jan 12, 2023
447b139
make clear that some instances are ad-hoc
eric-wieser Jan 12, 2023
04dc843
undo manual de-unicode-ification
eric-wieser Jan 12, 2023
7237d6f
revert removal of comments about dsimp lemmas
eric-wieser Jan 12, 2023
564e2bd
porting note: this didn't use to be necessary. It still isn't, but us…
eric-wieser Jan 12, 2023
f1cb0b6
restore mathlib3 proof
eric-wieser Jan 12, 2023
c4e14c2
merge syntactically equal statements
eric-wieser Jan 12, 2023
c289c2c
porting note is a lie
eric-wieser Jan 12, 2023
5c413b4
revert succ <-> +1 changes
eric-wieser Jan 12, 2023
ce0c041
restore mathlib3 proofs
eric-wieser Jan 12, 2023
cf39d33
move all the ad-hoc ring instances to the end
eric-wieser Jan 12, 2023
8377647
golf the adhoc instance using the ported lemmas
eric-wieser Jan 12, 2023
7e76bca
move another ad-hoc addition to the end
eric-wieser Jan 12, 2023
dc162d2
fix linter
eric-wieser Jan 12, 2023
aca7bc5
move ad-hoc instances to a new file
eric-wieser Jan 12, 2023
048573b
style exception
eric-wieser Jan 12, 2023
fb75b1b
typo
eric-wieser Jan 12, 2023
2a3bbb3
golf uint instances
eric-wieser Jan 12, 2023
83dfb03
revert a refactor that changes the defeq of `Smul Nat (Fin n)`
eric-wieser Jan 12, 2023
328b3cd
update the sha to match the one I compared to
eric-wieser Jan 12, 2023
02a29f7
whitespace
eric-wieser Jan 12, 2023
8603e6b
correct from_ad_hoc section
eric-wieser Jan 12, 2023
c2f59d5
add Zmod.AdHocDefs to Mathlib.lean
jcommelin Jan 12, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Mathlib.lean
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ import Mathlib.Data.Countable.Small
import Mathlib.Data.DList.Basic
import Mathlib.Data.Equiv.Functor
import Mathlib.Data.Erased
import Mathlib.Data.Fin.AdHocBasic
import Mathlib.Data.Fin.Basic
import Mathlib.Data.Fin.Fin2
import Mathlib.Data.Finite.Defs
Expand Down
334 changes: 334 additions & 0 deletions Mathlib/Data/Fin/AdHocBasic.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,334 @@
import Mathlib.Data.Nat.Basic
import Std.Data.Nat.Lemmas
import Mathlib.Algebra.Group.Defs
import Mathlib.Algebra.GroupWithZero.Defs
import Mathlib.Algebra.Ring.Basic

namespace Nat

/- Up -/

/-- A well-ordered relation for "upwards" induction on the natural numbers up to some bound `ub`. -/
def Up (ub a i : ℕ) := i < a ∧ i < ub

lemma Up.next {ub i} (h : i < ub) : Up ub (i+1) i := ⟨Nat.lt_succ_self _, h⟩

lemma Up.WF (ub) : WellFounded (Up ub) :=
Subrelation.wf (h₂ := (measure (ub - .)).wf) fun ⟨ia, iu⟩ ↦ Nat.sub_lt_sub_left iu ia

/-- A well-ordered relation for "upwards" induction on the natural numbers up to some bound `ub`. -/
def upRel (ub : ℕ) : WellFoundedRelation Nat := ⟨Up ub, Up.WF ub⟩

end Nat

instance : Subsingleton (Fin 0) where
allEq := fun.

instance : Subsingleton (Fin 1) where
allEq := fun ⟨0, _⟩ ⟨0, _⟩ ↦ rfl

/-- If you actually have an element of `Fin n`, then the `n` is always positive -/
lemma Fin.size_positive : Fin n → 0 < n
| ⟨x, h⟩ =>
match Nat.eq_or_lt_of_le (Nat.zero_le x) with
| Or.inl h_eq => h_eq ▸ h
| Or.inr h_lt => Nat.lt_trans h_lt h

lemma Fin.ext {a b : Fin n} : a.val = b.val → a = b := by
cases a; cases b; intro h; cases h; rfl

lemma Fin.ext_iff {a b : Fin n} : a = b ↔ a.val = b.val :=
⟨congrArg _, ext⟩

lemma Fin.size_positive' [Nonempty (Fin n)] : 0 < n :=
‹Nonempty (Fin n)›.elim fun i ↦ Fin.size_positive i

@[simp]
protected theorem Fin.eta (a : Fin n) (h : (a : ℕ) < n) : (⟨(a : ℕ), h⟩ : Fin n) = a := by
cases a; rfl

lemma zero_lt_of_lt {a : Nat} : ∀ {x : Nat}, x < a -> 0 < a
| 0, h => h
| x+1, h => Nat.lt_trans (Nat.zero_lt_succ x) h

lemma Fin.val_eq_of_lt {n a : Nat} (h : a < n) : (Fin.ofNat' a (zero_lt_of_lt h)).val = a := by
simp only [Fin.ofNat', Nat.mod_eq_of_lt h]

@[simp] lemma Fin.one_val : (1 : Fin (n + 2)).val = 1 := by
simp only [OfNat.ofNat, Fin.ofNat]
rw [Nat.mod_eq_of_lt]
exact Nat.succ_lt_succ (Nat.zero_lt_succ _)

lemma Fin.mod_def : ∀ (a m : Fin n),
a % m = Fin.mk ((a.val % m.val) % n) (Nat.mod_lt (a.val % m.val) (a.size_positive))
| ⟨_, _⟩, ⟨_, _⟩ => rfl

lemma Fin.add_def : ∀ (a b : Fin n),
a + b = (Fin.mk ((a.val + b.val) % n) (Nat.mod_lt _ (a.size_positive)))
| ⟨_, _⟩, ⟨_, _⟩ => rfl

lemma Fin.mul_def : ∀ (a b : Fin n),
a * b = (Fin.mk ((a.val * b.val) % n) (Nat.mod_lt _ (a.size_positive)))
| ⟨_, _⟩, ⟨_, _⟩ => rfl

lemma Fin.sub_def : ∀ (a b : Fin n),
a - b = (Fin.mk ((a + (n - b)) % n) (Nat.mod_lt _ (a.size_positive)))
| ⟨_, _⟩, ⟨_, _⟩ => rfl

theorem Fin.mod_eq_of_lt {a b : Fin n} (h : a < b) : a % b = a := by
apply Fin.eq_of_val_eq
simp only [Fin.mod_def]
rw [Nat.mod_eq_of_lt h, Nat.mod_eq_of_lt a.isLt]

/- The basic structures on `Fin` are predicated on `Fin n` being nonempty.
The Nonempty bound is there so that we can implement `Zero` in a way that satisfies
the requirements of the relevant typeclasses (for example, AddMonoid). If we were to
use `Fin n+1` for the `Zero` implementation, we would be shutting out some irreducible
definitions (notably USize.size) that are known to be inhabited, but not defined in terms
of `Nat.succ`. Since there's a blanket implementation of `∀ n, Inhabited (Fin n+1)` in
the prelude, this hopefully won't be a significant impediment. -/
section

variable {n : Nat} [Nonempty (Fin n)]

@[to_additive_fixed_numeral]
instance : OfNat (Fin n) a where
ofNat := Fin.ofNat' a Fin.size_positive'

@[simp] lemma Fin.ofNat'_zero : (Fin.ofNat' 0 h : Fin n) = 0 := rfl
@[simp] lemma Fin.ofNat'_one : (Fin.ofNat' 1 h : Fin n) = 1 := rfl

lemma Fin.ofNat'_succ : {n : Nat} → [Nonempty (Fin n)] →
(Fin.ofNat' i.succ Fin.size_positive' : Fin n) = (Fin.ofNat' i Fin.size_positive' : Fin n) + 1
| n + 2, h => ext (by simp [Fin.ofNat', Fin.add_def])
| 1, h => Subsingleton.allEq _ _
| 0, h => Subsingleton.allEq _ _

instance : AddCommSemigroup (Fin n) where
add_assoc _ _ _ := by
apply Fin.eq_of_val_eq
simp only [Fin.add_def, Nat.mod_add_mod, Nat.add_mod_mod, Nat.add_assoc]
add_comm _ _ := by
apply Fin.eq_of_val_eq
simp only [Fin.add_def, Nat.add_comm]

instance : CommSemigroup (Fin n) where
mul_assoc a b c := by
apply Fin.eq_of_val_eq
simp only [Fin.mul_def]
generalize lhs : ((a.val * b.val) % n * c.val) % n = l
generalize rhs : a.val * (b.val * c.val % n) % n = r
rw [← Nat.mod_eq_of_lt c.isLt, (Nat.mul_mod (a.val * b.val) c.val n).symm] at lhs
rw [← Nat.mod_eq_of_lt a.isLt, (Nat.mul_mod a.val (b.val * c.val) n).symm,
← Nat.mul_assoc] at rhs
rw [← lhs, ← rhs]
mul_comm (a b : Fin n) : a * b = b * a := by
apply Fin.eq_of_val_eq; simp only [Fin.mul_def, Nat.mul_comm]

@[simp] lemma Fin.zero_def : (0 : Fin n).val = (0 : Nat) :=
show (Fin.ofNat' 0 Fin.size_positive').val = (0 : Nat) by simp only [Fin.ofNat', Nat.zero_mod]

theorem Fin.mod_lt : ∀ (i : Fin n) {m : Fin n}, (0 : Fin n) < m → (i % m) < m
| ⟨a, aLt⟩, ⟨m, mLt⟩, hp => by
have zero_lt : (0 : Nat) < m := @Fin.zero_def n _ ▸ hp
have a_mod_lt : a % m < m := Nat.mod_lt _ zero_lt
simp only [Fin.mod_def, LT.lt]
rw [(Nat.mod_eq_of_lt (Nat.lt_trans a_mod_lt mLt) : a % m % n = a % m)]
exact Nat.mod_lt _ zero_lt

/- Aux lemma that makes nsmul_succ easier -/
protected lemma Fin.nsmuls_eq (x : Nat) : ∀ (a : Fin n),
((Fin.ofNat' x Fin.size_positive') * a) = Fin.ofNat' (x * a.val) Fin.size_positive'
| ⟨a, isLt⟩ => by
apply Fin.eq_of_val_eq
simp only [Fin.ofNat', Fin.mul_def]
generalize hy : x * a % n = y
rw [← Nat.mod_eq_of_lt isLt, ← Nat.mul_mod, hy]

@[simp] lemma Fin.one_def : (1 : Fin n).val = (1 % n : Nat) :=
show (Fin.ofNat' 1 Fin.size_positive').val = 1 % n by simp [Fin.ofNat']

def Fin.addOverflows? (a b : Fin n) : Bool := n <= a.val + b.val

def Fin.mulOverflows? (a b : Fin n) : Bool := n <= a.val * b.val

def Fin.subUnderflows? (a b : Fin n) : Bool := a.val < b.val

def Fin.overflowingAdd (a b : Fin n) : (Bool × Fin n) := (n <= a.val + b.val, a + b)

def Fin.overflowingMul (a b : Fin n) : (Bool × Fin n) := (n <= a.val * b.val, a * b)

def Fin.underflowingSub (a b : Fin n) : (Bool × Fin n) := (a.val < b.val, a - b)

def Fin.checkedAdd (a b : Fin n) : Option (Fin n) :=
match Fin.overflowingAdd a b with
| (true, _) => none
| (false, sum) => some (sum)

def Fin.checkedMul (a b : Fin n) : Option (Fin n) :=
match Fin.overflowingMul a b with
| (true, _) => none
| (false, prod) => some (prod)

def Fin.checkedSub (a b : Fin n) : Option (Fin n) :=
match Fin.underflowingSub a b with
| (true, _) => none
| (false, diff) => some (diff)

lemma Fin.checked_add_spec (a b : Fin n) :
(Fin.checkedAdd a b).isSome = true ↔ a.val + b.val < n := by
by_cases n <= a.val + b.val <;>
simp_all [checkedAdd, Option.isSome, overflowingAdd, decide_eq_true, decide_eq_false]

lemma Fin.checked_mul_spec (a b : Fin n) :
(Fin.checkedMul a b).isSome = true ↔ a.val * b.val < n := by
simp only [checkedMul, overflowingMul, Option.isSome]
refine Iff.intro ?mp ?mpr <;> intro h
case mp =>
by_cases hx : n <= a.val * b.val
case pos => simp only [(decide_eq_true_iff (n <= a.val * b.val)).mpr hx] at h
case neg => exact Nat.lt_of_not_le hx
case mpr => simp only [decide_eq_false (Nat.not_le_of_lt h : ¬n <= a.val * b.val)]

lemma Fin.checked_sub_spec (a b : Fin n) :
(Fin.checkedSub a b).isSome = true ↔ b.val <= a.val := by
simp only [checkedSub, underflowingSub, Option.isSome]
refine Iff.intro ?mp ?mpr <;> intro h
case mp =>
by_cases hx : a.val < b.val
case pos => simp only [(decide_eq_true_iff (a.val < b.val)).mpr hx] at h
case neg => exact Nat.le_of_not_lt hx
case mpr => simp only [decide_eq_false (Nat.not_lt_of_le h : ¬a.val < b.val)]

instance : AddCommMonoid (Fin n) where
__ := inferInstanceAs (AddCommSemigroup (Fin n))

add_zero (a : Fin n) : a + 0 = a := by
apply Fin.eq_of_val_eq
simp only [Fin.add_def, Fin.zero_def, Nat.add_zero]
exact Nat.mod_eq_of_lt a.isLt
zero_add (a : Fin n) : 0 + a = a := by
apply Fin.eq_of_val_eq
simp only [Fin.add_def, Fin.zero_def, Nat.zero_add]
exact Nat.mod_eq_of_lt a.isLt

nsmul := fun x a ↦ (Fin.ofNat' x a.size_positive) * a
nsmul_zero := fun _ ↦ by
apply Fin.eq_of_val_eq
simp [Fin.mul_def, Fin.ofNat', Fin.zero_def, Nat.zero_mul, Nat.zero_mod]
nsmul_succ := fun x a ↦ by
simp only [Fin.nsmuls_eq]
simp [Fin.ofNat', Fin.add_def]
exact congrArg (fun x ↦ x % n) (Nat.add_comm (x * a.val) (a.val) ▸ Nat.succ_mul x a.val)

instance : AddMonoidWithOne (Fin n) where
__ := inferInstanceAs (AddCommMonoid (Fin n))
natCast n := Fin.ofNat' n Fin.size_positive'
natCast_zero := rfl
natCast_succ _ := Fin.ofNat'_succ

private theorem Fin.mul_one (a : Fin n) : a * 1 = a := by
apply Fin.eq_of_val_eq
simp only [Fin.mul_def, Fin.one_def]
cases n with
| zero => exact (False.elim a.elim0)
| succ n =>
match Nat.lt_or_eq_of_le (Nat.mod_le 1 n.succ) with
| Or.inl h_lt =>
have h_eq : 1 % n.succ = 0 := Nat.eq_zero_of_le_zero (Nat.le_of_lt_succ h_lt)
have hnz : n = 0 := Nat.eq_zero_of_le_zero (Nat.le_of_succ_le_succ (Nat.le_of_mod_lt h_lt))
have haz : a.val = 0 := Nat.eq_zero_of_le_zero (Nat.le_of_succ_le_succ (hnz ▸ a.isLt))
rw [h_eq, haz]
simp only [Nat.zero_mul, Nat.zero_mod]
| Or.inr h_eq => simp only [h_eq, Nat.mul_one, Nat.mod_eq_of_lt (a.isLt)]

instance : MonoidWithZero (Fin n) where
__ := inferInstanceAs (CommSemigroup (Fin n))
mul_one := Fin.mul_one
one_mul _ := by rw [mul_comm, Fin.mul_one]
npow_zero _ := rfl
npow_succ _ _ := rfl
zero_mul x := by
apply Fin.eq_of_val_eq
simp only [Fin.mul_def, Fin.zero_def, Nat.zero_mul, Nat.zero_mod]
mul_zero x := by
apply Fin.eq_of_val_eq
simp only [Fin.mul_def, Fin.zero_def, Nat.mul_zero, Nat.zero_mod]

private theorem Fin.mul_add (a b c : Fin n) : a * (b + c) = a * b + a * c := by
apply Fin.eq_of_val_eq
simp [Fin.mul_def, Fin.add_def]
generalize lhs : a.val * ((b.val + c.val) % n) % n = l
rw [(Nat.mod_eq_of_lt a.isLt).symm, ← Nat.mul_mod] at lhs
rw [← lhs, left_distrib]

instance : CommSemiring (Fin n) where
__ := inferInstanceAs (MonoidWithZero (Fin n))
__ := inferInstanceAs (CommSemigroup (Fin n))
__ := inferInstanceAs (AddCommMonoid (Fin n))
__ := inferInstanceAs (AddMonoidWithOne (Fin n))
left_distrib := Fin.mul_add
right_distrib a b c := (by rw [mul_comm, Fin.mul_add, mul_comm c, mul_comm c])

instance : Neg (Fin n) where
neg a := ⟨(n - a) % n, Nat.mod_lt _ (lt_of_le_of_lt (Nat.zero_le _) a.isLt)⟩

lemma Fin.neg_def :
(-a : Fin n) = ⟨(n - a) % n, Nat.mod_lt _ (lt_of_le_of_lt (Nat.zero_le _) a.isLt)⟩ :=
rfl

protected def Fin.ofInt'' : Int → Fin n
| Int.ofNat a => Fin.ofNat' a Fin.size_positive'
| Int.negSucc a => -(Fin.ofNat' a.succ Fin.size_positive')

private theorem Fin.sub_eq_add_neg : ∀ (a b : Fin n), a - b = a + -b := by
simp [Fin.add_def, Fin.sub_def, Neg.neg]

private theorem Fin.add_left_neg (a : Fin n) : -a + a = 0 := by
rw [add_comm, ← Fin.sub_eq_add_neg]
apply Fin.eq_of_val_eq
simp [Fin.sub_def, (Nat.add_sub_cancel' (Nat.le_of_lt a.isLt)), Nat.mod_self]

def Fin.ofInt' : ℤ → Fin n
| (i : ℕ) => i
| (Int.negSucc i) => -↑(i + 1 : ℕ)

instance : AddGroupWithOne (Fin n) where
__ := inferInstanceAs (AddMonoidWithOne (Fin n))
sub_eq_add_neg := Fin.sub_eq_add_neg
add_left_neg := Fin.add_left_neg
intCast := Fin.ofInt'
intCast_ofNat _ := rfl
intCast_negSucc _ := rfl

instance : CommRing (Fin n) where
__ := inferInstanceAs (AddGroupWithOne (Fin n))
__ := inferInstanceAs (CommSemiring (Fin n))

lemma Fin.gt_wf : WellFounded (fun a b : Fin n ↦ b < a) :=
Subrelation.wf (fun {_ i} h ↦ ⟨h, i.2⟩) (invImage (fun i ↦ i.1) (Nat.upRel n)).wf

/-- A well-ordered relation for "upwards" induction on `Fin n`. -/
def Fin.upRel (n : ℕ) : WellFoundedRelation (Fin n) := ⟨_, gt_wf⟩

lemma Fin.le_refl (f : Fin n) : f ≤ f := Nat.le_refl _
lemma Fin.le_trans (a b c : Fin n) : a ≤ b → b ≤ c → a ≤ c := Nat.le_trans
lemma Fin.lt_iff_le_not_le (a b : Fin n) : a < b ↔ a ≤ b ∧ ¬b ≤ a := Nat.lt_iff_le_not_le
lemma Fin.le_antisymm (a b : Fin n) : a ≤ b → b ≤ a → a = b := by
intro h1 h2
apply Fin.eq_of_val_eq
exact Nat.le_antisymm h1 h2

lemma Fin.le_total (a b : Fin n) : a ≤ b ∨ b ≤ a := Nat.le_total _ _

instance : LinearOrder (Fin n) where
le_refl := Fin.le_refl
le_trans := Fin.le_trans
lt_iff_le_not_le := Fin.lt_iff_le_not_le
le_antisymm := Fin.le_antisymm
le_total := Fin.le_total
decidable_le := inferInstance
toMin := minOfLe
toMax := maxOfLe

end
Loading