Module docstring
{"# Equivalences for Fin n
","### Miscellaneous
This is currently not very sorted. PRs welcome! "}
{"# Equivalences for Fin n
","### Miscellaneous
This is currently not very sorted. PRs welcome! "}
Fin.preimage_apply_01_prod
theorem
{α : Fin 2 → Type u} (s : Set (α 0)) (t : Set (α 1)) :
(fun f : ∀ i, α i => (f 0, f 1)) ⁻¹' s ×ˢ t = Set.pi Set.univ (Fin.cons s <| Fin.cons t finZeroElim)
theorem Fin.preimage_apply_01_prod {α : Fin 2 → Type u} (s : Set (α 0)) (t : Set (α 1)) :
(fun f : ∀ i, α i => (f 0, f 1)) ⁻¹' s ×ˢ t =
Set.pi Set.univ (Fin.cons s <| Fin.cons t finZeroElim) := by
ext f
simp [Fin.forall_fin_two]
Fin.preimage_apply_01_prod'
theorem
{α : Type u} (s t : Set α) : (fun f : Fin 2 → α => (f 0, f 1)) ⁻¹' s ×ˢ t = Set.pi Set.univ ![s, t]
theorem Fin.preimage_apply_01_prod' {α : Type u} (s t : Set α) :
(fun f : Fin 2 → α => (f 0, f 1)) ⁻¹' s ×ˢ t = Set.pi Set.univ ![s, t] :=
@Fin.preimage_apply_01_prod (fun _ => α) s t
prodEquivPiFinTwo
definition
(α β : Type u) : α × β ≃ ∀ i : Fin 2, ![α, β] i
/-- A product space `α × β` is equivalent to the space `Π i : Fin 2, γ i`, where
`γ = Fin.cons α (Fin.cons β finZeroElim)`. See also `piFinTwoEquiv` and
`finTwoArrowEquiv`. -/
@[simps! -fullyApplied]
def prodEquivPiFinTwo (α β : Type u) : α × βα × β ≃ ∀ i : Fin 2, ![α, β] i :=
(piFinTwoEquiv (Fin.cons α (Fin.cons β finZeroElim))).symm
finTwoArrowEquiv
definition
(α : Type*) : (Fin 2 → α) ≃ α × α
/-- The space of functions `Fin 2 → α` is equivalent to `α × α`. See also `piFinTwoEquiv` and
`prodEquivPiFinTwo`. -/
@[simps -fullyApplied]
def finTwoArrowEquiv (α : Type*) : (Fin 2 → α) ≃ α × α :=
{ piFinTwoEquiv fun _ => α with invFun := fun x => ![x.1, x.2] }
finSuccEquiv'
definition
(i : Fin (n + 1)) : Fin (n + 1) ≃ Option (Fin n)
/-- An equivalence that removes `i` and maps it to `none`.
This is a version of `Fin.predAbove` that produces `Option (Fin n)` instead of
mapping both `i.castSucc` and `i.succ` to `i`. -/
def finSuccEquiv' (i : Fin (n + 1)) : FinFin (n + 1) ≃ Option (Fin n) where
toFun := i.insertNth none some
invFun x := x.casesOn' i (Fin.succAbove i)
left_inv x := Fin.succAboveCases i (by simp) (fun j => by simp) x
right_inv x := by cases x <;> dsimp <;> simp
finSuccEquiv'_at
theorem
(i : Fin (n + 1)) : (finSuccEquiv' i) i = none
@[simp]
theorem finSuccEquiv'_at (i : Fin (n + 1)) : (finSuccEquiv' i) i = none := by
simp [finSuccEquiv']
finSuccEquiv'_succAbove
theorem
(i : Fin (n + 1)) (j : Fin n) : finSuccEquiv' i (i.succAbove j) = some j
@[simp]
theorem finSuccEquiv'_succAbove (i : Fin (n + 1)) (j : Fin n) :
finSuccEquiv' i (i.succAbove j) = some j :=
@Fin.insertNth_apply_succAbove n (fun _ => Option (Fin n)) i _ _ _
finSuccEquiv'_below
theorem
{i : Fin (n + 1)} {m : Fin n} (h : Fin.castSucc m < i) : (finSuccEquiv' i) (Fin.castSucc m) = m
theorem finSuccEquiv'_below {i : Fin (n + 1)} {m : Fin n} (h : Fin.castSucc m < i) :
(finSuccEquiv' i) (Fin.castSucc m) = m := by
rw [← Fin.succAbove_of_castSucc_lt _ _ h, finSuccEquiv'_succAbove]
finSuccEquiv'_above
theorem
{i : Fin (n + 1)} {m : Fin n} (h : i ≤ Fin.castSucc m) : (finSuccEquiv' i) m.succ = some m
theorem finSuccEquiv'_above {i : Fin (n + 1)} {m : Fin n} (h : i ≤ Fin.castSucc m) :
(finSuccEquiv' i) m.succ = some m := by
rw [← Fin.succAbove_of_le_castSucc _ _ h, finSuccEquiv'_succAbove]
finSuccEquiv'_symm_none
theorem
(i : Fin (n + 1)) : (finSuccEquiv' i).symm none = i
@[simp]
theorem finSuccEquiv'_symm_none (i : Fin (n + 1)) : (finSuccEquiv' i).symm none = i :=
rfl
finSuccEquiv'_symm_some
theorem
(i : Fin (n + 1)) (j : Fin n) : (finSuccEquiv' i).symm (some j) = i.succAbove j
@[simp]
theorem finSuccEquiv'_symm_some (i : Fin (n + 1)) (j : Fin n) :
(finSuccEquiv' i).symm (some j) = i.succAbove j :=
rfl
finSuccEquiv'_eq_some
theorem
{i j : Fin (n + 1)} {k : Fin n} : finSuccEquiv' i j = k ↔ j = i.succAbove k
@[simp]
theorem finSuccEquiv'_eq_some {i j : Fin (n + 1)} {k : Fin n} :
finSuccEquiv'finSuccEquiv' i j = k ↔ j = i.succAbove k :=
(finSuccEquiv' i).apply_eq_iff_eq_symm_apply
finSuccEquiv'_eq_none
theorem
{i j : Fin (n + 1)} : finSuccEquiv' i j = none ↔ i = j
@[simp]
theorem finSuccEquiv'_eq_none {i j : Fin (n + 1)} : finSuccEquiv'finSuccEquiv' i j = none ↔ i = j :=
(finSuccEquiv' i).apply_eq_iff_eq_symm_apply.trans eq_comm
finSuccEquiv'_symm_some_below
theorem
{i : Fin (n + 1)} {m : Fin n} (h : Fin.castSucc m < i) : (finSuccEquiv' i).symm (some m) = Fin.castSucc m
theorem finSuccEquiv'_symm_some_below {i : Fin (n + 1)} {m : Fin n} (h : Fin.castSucc m < i) :
(finSuccEquiv' i).symm (some m) = Fin.castSucc m :=
Fin.succAbove_of_castSucc_lt i m h
finSuccEquiv'_symm_some_above
theorem
{i : Fin (n + 1)} {m : Fin n} (h : i ≤ Fin.castSucc m) : (finSuccEquiv' i).symm (some m) = m.succ
theorem finSuccEquiv'_symm_some_above {i : Fin (n + 1)} {m : Fin n} (h : i ≤ Fin.castSucc m) :
(finSuccEquiv' i).symm (some m) = m.succ :=
Fin.succAbove_of_le_castSucc i m h
finSuccEquiv'_symm_coe_below
theorem
{i : Fin (n + 1)} {m : Fin n} (h : Fin.castSucc m < i) : (finSuccEquiv' i).symm m = Fin.castSucc m
theorem finSuccEquiv'_symm_coe_below {i : Fin (n + 1)} {m : Fin n} (h : Fin.castSucc m < i) :
(finSuccEquiv' i).symm m = Fin.castSucc m :=
finSuccEquiv'_symm_some_below h
finSuccEquiv'_symm_coe_above
theorem
{i : Fin (n + 1)} {m : Fin n} (h : i ≤ Fin.castSucc m) : (finSuccEquiv' i).symm m = m.succ
theorem finSuccEquiv'_symm_coe_above {i : Fin (n + 1)} {m : Fin n} (h : i ≤ Fin.castSucc m) :
(finSuccEquiv' i).symm m = m.succ :=
finSuccEquiv'_symm_some_above h
finSuccEquiv
definition
(n : ℕ) : Fin (n + 1) ≃ Option (Fin n)
/-- Equivalence between `Fin (n + 1)` and `Option (Fin n)`.
This is a version of `Fin.pred` that produces `Option (Fin n)` instead of
requiring a proof that the input is not `0`. -/
def finSuccEquiv (n : ℕ) : FinFin (n + 1) ≃ Option (Fin n) :=
finSuccEquiv' 0
finSuccEquiv_zero
theorem
: (finSuccEquiv n) 0 = none
@[simp]
theorem finSuccEquiv_zero : (finSuccEquiv n) 0 = none :=
rfl
finSuccEquiv_succ
theorem
(m : Fin n) : (finSuccEquiv n) m.succ = some m
@[simp]
theorem finSuccEquiv_succ (m : Fin n) : (finSuccEquiv n) m.succ = some m :=
finSuccEquiv'_above (Fin.zero_le _)
finSuccEquiv_symm_none
theorem
: (finSuccEquiv n).symm none = 0
@[simp]
theorem finSuccEquiv_symm_none : (finSuccEquiv n).symm none = 0 :=
finSuccEquiv'_symm_none _
finSuccEquiv_symm_some
theorem
(m : Fin n) : (finSuccEquiv n).symm (some m) = m.succ
@[simp]
theorem finSuccEquiv_symm_some (m : Fin n) : (finSuccEquiv n).symm (some m) = m.succ :=
congr_fun Fin.succAbove_zero m
finSuccEquiv_eq_some
theorem
{i : Fin (n + 1)} {j : Fin n} : finSuccEquiv n i = j ↔ i = j.succ
@[simp]
theorem finSuccEquiv_eq_some {i : Fin (n + 1)} {j : Fin n} :
finSuccEquivfinSuccEquiv n i = j ↔ i = j.succ :=
(finSuccEquiv n).apply_eq_iff_eq_symm_apply
finSuccEquiv_eq_none
theorem
{i : Fin (n + 1)} : finSuccEquiv n i = none ↔ i = 0
@[simp]
theorem finSuccEquiv_eq_none {i : Fin (n + 1)} : finSuccEquivfinSuccEquiv n i = none ↔ i = 0 :=
(finSuccEquiv n).apply_eq_iff_eq_symm_apply
finSuccEquiv'_zero
theorem
: finSuccEquiv' (0 : Fin (n + 1)) = finSuccEquiv n
/-- The equiv version of `Fin.predAbove_zero`. -/
theorem finSuccEquiv'_zero : finSuccEquiv' (0 : Fin (n + 1)) = finSuccEquiv n :=
rfl
finSuccEquiv'_last_apply_castSucc
theorem
(i : Fin n) : finSuccEquiv' (Fin.last n) (Fin.castSucc i) = i
theorem finSuccEquiv'_last_apply_castSucc (i : Fin n) :
finSuccEquiv' (Fin.last n) (Fin.castSucc i) = i := by
rw [← Fin.succAbove_last, finSuccEquiv'_succAbove]
finSuccEquiv'_last_apply
theorem
{i : Fin (n + 1)} (h : i ≠ Fin.last n) : finSuccEquiv' (Fin.last n) i = Fin.castLT i (Fin.val_lt_last h)
theorem finSuccEquiv'_last_apply {i : Fin (n + 1)} (h : i ≠ Fin.last n) :
finSuccEquiv' (Fin.last n) i = Fin.castLT i (Fin.val_lt_last h) := by
rcases Fin.exists_castSucc_eq.2 h with ⟨i, rfl⟩
rw [finSuccEquiv'_last_apply_castSucc]
rfl
finSuccEquiv'_ne_last_apply
theorem
{i j : Fin (n + 1)} (hi : i ≠ Fin.last n) (hj : j ≠ i) :
finSuccEquiv' i j = (i.castLT (Fin.val_lt_last hi)).predAbove j
theorem finSuccEquiv'_ne_last_apply {i j : Fin (n + 1)} (hi : i ≠ Fin.last n) (hj : j ≠ i) :
finSuccEquiv' i j = (i.castLT (Fin.val_lt_last hi)).predAbove j := by
rcases Fin.exists_succAbove_eq hj with ⟨j, rfl⟩
rcases Fin.exists_castSucc_eq.2 hi with ⟨i, rfl⟩
simp
finSuccAboveEquiv
definition
(p : Fin (n + 1)) : Fin n ≃ { x : Fin (n + 1) // x ≠ p }
/-- `Fin.succAbove` as an order isomorphism between `Fin n` and `{x : Fin (n + 1) // x ≠ p}`. -/
def finSuccAboveEquiv (p : Fin (n + 1)) : FinFin n ≃ { x : Fin (n + 1) // x ≠ p } :=
.optionSubtype p ⟨(finSuccEquiv' p).symm, rfl⟩
finSuccAboveEquiv_apply
theorem
(p : Fin (n + 1)) (i : Fin n) : finSuccAboveEquiv p i = ⟨p.succAbove i, p.succAbove_ne i⟩
theorem finSuccAboveEquiv_apply (p : Fin (n + 1)) (i : Fin n) :
finSuccAboveEquiv p i = ⟨p.succAbove i, p.succAbove_ne i⟩ :=
rfl
finSuccAboveEquiv_symm_apply_last
theorem
(x : { x : Fin (n + 1) // x ≠ Fin.last n }) :
(finSuccAboveEquiv (Fin.last n)).symm x = Fin.castLT x.1 (Fin.val_lt_last x.2)
theorem finSuccAboveEquiv_symm_apply_last (x : { x : Fin (n + 1) // x ≠ Fin.last n }) :
(finSuccAboveEquiv (Fin.last n)).symm x = Fin.castLT x.1 (Fin.val_lt_last x.2) := by
rw [← Option.some_inj]
simp [finSuccAboveEquiv]
finSuccAboveEquiv_symm_apply_ne_last
theorem
{p : Fin (n + 1)} (h : p ≠ Fin.last n) (x : { x : Fin (n + 1) // x ≠ p }) :
(finSuccAboveEquiv p).symm x = (p.castLT (Fin.val_lt_last h)).predAbove x
theorem finSuccAboveEquiv_symm_apply_ne_last {p : Fin (n + 1)} (h : p ≠ Fin.last n)
(x : { x : Fin (n + 1) // x ≠ p }) :
(finSuccAboveEquiv p).symm x = (p.castLT (Fin.val_lt_last h)).predAbove x := by
rw [← Option.some_inj]
simpa [finSuccAboveEquiv] using finSuccEquiv'_ne_last_apply h x.property
finSuccEquivLast
definition
: Fin (n + 1) ≃ Option (Fin n)
/-- `Equiv` between `Fin (n + 1)` and `Option (Fin n)` sending `Fin.last n` to `none` -/
def finSuccEquivLast : FinFin (n + 1) ≃ Option (Fin n) :=
finSuccEquiv' (Fin.last n)
finSuccEquivLast_castSucc
theorem
(i : Fin n) : finSuccEquivLast (Fin.castSucc i) = some i
@[simp]
theorem finSuccEquivLast_castSucc (i : Fin n) : finSuccEquivLast (Fin.castSucc i) = some i :=
finSuccEquiv'_below i.2
finSuccEquivLast_last
theorem
: finSuccEquivLast (Fin.last n) = none
@[simp]
theorem finSuccEquivLast_last : finSuccEquivLast (Fin.last n) = none := by
simp [finSuccEquivLast]
finSuccEquivLast_symm_some
theorem
(i : Fin n) : finSuccEquivLast.symm (some i) = Fin.castSucc i
@[simp]
theorem finSuccEquivLast_symm_some (i : Fin n) :
finSuccEquivLast.symm (some i) = Fin.castSucc i :=
finSuccEquiv'_symm_some_below i.2
finSuccEquivLast_symm_none
theorem
: finSuccEquivLast.symm none = Fin.last n
@[simp] theorem finSuccEquivLast_symm_none : finSuccEquivLast.symm none = Fin.last n :=
finSuccEquiv'_symm_none _
Equiv.embeddingFinSucc
definition
(n : ℕ) (ι : Type*) : (Fin (n + 1) ↪ ι) ≃ (Σ (e : Fin n ↪ ι), { i // i ∉ Set.range e })
/-- An embedding `e : Fin (n+1) ↪ ι` corresponds to an embedding `f : Fin n ↪ ι` (corresponding
the last `n` coordinates of `e`) together with a value not taken by `f` (corresponding to `e 0`). -/
def Equiv.embeddingFinSucc (n : ℕ) (ι : Type*) :
(Fin (n+1) ↪ ι) ≃ (Σ (e : Fin n ↪ ι), {i // i ∉ Set.range e}) :=
((finSuccEquiv n).embeddingCongr (Equiv.refl ι)).trans
(Function.Embedding.optionEmbeddingEquiv (Fin n) ι)
Equiv.embeddingFinSucc_fst
theorem
{n : ℕ} {ι : Type*} (e : Fin (n + 1) ↪ ι) : ((Equiv.embeddingFinSucc n ι e).1 : Fin n → ι) = e ∘ Fin.succ
@[simp] lemma Equiv.embeddingFinSucc_fst {n : ℕ} {ι : Type*} (e : FinFin (n+1) ↪ ι) :
((Equiv.embeddingFinSucc n ι e).1 : Fin n → ι) = e ∘ Fin.succ := rfl
Equiv.embeddingFinSucc_snd
theorem
{n : ℕ} {ι : Type*} (e : Fin (n + 1) ↪ ι) : ((Equiv.embeddingFinSucc n ι e).2 : ι) = e 0
@[simp] lemma Equiv.embeddingFinSucc_snd {n : ℕ} {ι : Type*} (e : FinFin (n+1) ↪ ι) :
((Equiv.embeddingFinSucc n ι e).2 : ι) = e 0 := rfl
Equiv.coe_embeddingFinSucc_symm
theorem
{n : ℕ} {ι : Type*} (f : Σ (e : Fin n ↪ ι), { i // i ∉ Set.range e }) :
((Equiv.embeddingFinSucc n ι).symm f : Fin (n + 1) → ι) = Fin.cons f.2.1 f.1
@[simp] lemma Equiv.coe_embeddingFinSucc_symm {n : ℕ} {ι : Type*}
(f : Σ (e : Fin n ↪ ι), {i // i ∉ Set.range e}) :
((Equiv.embeddingFinSucc n ι).symm f : Fin (n + 1) → ι) = Fin.cons f.2.1 f.1 := by
ext i
exact Fin.cases rfl (fun j ↦ rfl) i
finSumFinEquiv
definition
: Fin m ⊕ Fin n ≃ Fin (m + n)
/-- Equivalence between `Fin m ⊕ Fin n` and `Fin (m + n)` -/
def finSumFinEquiv : FinFin m ⊕ Fin nFin m ⊕ Fin n ≃ Fin (m + n) where
toFun := Sum.elim (Fin.castAdd n) (Fin.natAdd m)
invFun i := @Fin.addCases m n (fun _ => FinFin m ⊕ Fin n) Sum.inl Sum.inr i
left_inv x := by rcases x with y | y <;> dsimp <;> simp
right_inv x := by refine Fin.addCases (fun i => ?_) (fun i => ?_) x <;> simp
finSumFinEquiv_apply_left
theorem
(i : Fin m) : (finSumFinEquiv (Sum.inl i) : Fin (m + n)) = Fin.castAdd n i
@[simp]
theorem finSumFinEquiv_apply_left (i : Fin m) :
(finSumFinEquiv (Sum.inl i) : Fin (m + n)) = Fin.castAdd n i :=
rfl
finSumFinEquiv_apply_right
theorem
(i : Fin n) : (finSumFinEquiv (Sum.inr i) : Fin (m + n)) = Fin.natAdd m i
@[simp]
theorem finSumFinEquiv_apply_right (i : Fin n) :
(finSumFinEquiv (Sum.inr i) : Fin (m + n)) = Fin.natAdd m i :=
rfl
finSumFinEquiv_symm_apply_castAdd
theorem
(x : Fin m) : finSumFinEquiv.symm (Fin.castAdd n x) = Sum.inl x
@[simp]
theorem finSumFinEquiv_symm_apply_castAdd (x : Fin m) :
finSumFinEquiv.symm (Fin.castAdd n x) = Sum.inl x :=
finSumFinEquiv.symm_apply_apply (Sum.inl x)
finSumFinEquiv_symm_apply_natAdd
theorem
(x : Fin n) : finSumFinEquiv.symm (Fin.natAdd m x) = Sum.inr x
@[simp]
theorem finSumFinEquiv_symm_apply_natAdd (x : Fin n) :
finSumFinEquiv.symm (Fin.natAdd m x) = Sum.inr x :=
finSumFinEquiv.symm_apply_apply (Sum.inr x)
finSumFinEquiv_symm_last
theorem
: finSumFinEquiv.symm (Fin.last n) = Sum.inr 0
@[simp]
theorem finSumFinEquiv_symm_last : finSumFinEquiv.symm (Fin.last n) = Sum.inr 0 :=
finSumFinEquiv_symm_apply_natAdd 0
finAddFlip
definition
: Fin (m + n) ≃ Fin (n + m)
/-- The equivalence between `Fin (m + n)` and `Fin (n + m)` which rotates by `n`. -/
def finAddFlip : FinFin (m + n) ≃ Fin (n + m) :=
(finSumFinEquiv.symm.trans (Equiv.sumComm _ _)).trans finSumFinEquiv
finAddFlip_apply_castAdd
theorem
(k : Fin m) (n : ℕ) : finAddFlip (Fin.castAdd n k) = Fin.natAdd n k
@[simp]
theorem finAddFlip_apply_castAdd (k : Fin m) (n : ℕ) :
finAddFlip (Fin.castAdd n k) = Fin.natAdd n k := by simp [finAddFlip]
finAddFlip_apply_natAdd
theorem
(k : Fin n) (m : ℕ) : finAddFlip (Fin.natAdd m k) = Fin.castAdd m k
@[simp]
theorem finAddFlip_apply_natAdd (k : Fin n) (m : ℕ) :
finAddFlip (Fin.natAdd m k) = Fin.castAdd m k := by simp [finAddFlip]
finAddFlip_apply_mk_right
theorem
{k : ℕ} (h₁ : m ≤ k) (h₂ : k < m + n) : finAddFlip (⟨k, h₂⟩ : Fin (m + n)) = ⟨k - m, by omega⟩
@[simp]
theorem finAddFlip_apply_mk_right {k : ℕ} (h₁ : m ≤ k) (h₂ : k < m + n) :
finAddFlip (⟨k, h₂⟩ : Fin (m + n)) = ⟨k - m, by omega⟩ := by
convert @finAddFlip_apply_natAdd n ⟨k - m, by omega⟩ m
simp [Nat.add_sub_cancel' h₁]
finProdFinEquiv
definition
: Fin m × Fin n ≃ Fin (m * n)
/-- Equivalence between `Fin m × Fin n` and `Fin (m * n)` -/
@[simps]
def finProdFinEquiv : FinFin m × Fin nFin m × Fin n ≃ Fin (m * n) where
toFun x :=
⟨x.2 + n * x.1,
calc
x.2.1 + n * x.1.1 + 1 = x.1.1 * n + x.2.1 + 1 := by ac_rfl
_ ≤ x.1.1 * n + n := Nat.add_le_add_left x.2.2 _
_ = (x.1.1 + 1) * n := Eq.symm <| Nat.succ_mul _ _
_ ≤ m * n := Nat.mul_le_mul_right _ x.1.2
⟩
invFun x := (x.divNat, x.modNat)
left_inv := fun ⟨x, y⟩ =>
have H : 0 < n := Nat.pos_of_ne_zero fun H => Nat.not_lt_zero y.1 <| H ▸ y.2
Prod.ext
(Fin.eq_of_val_eq <|
calc
(y.1 + n * x.1) / n = y.1 / n + x.1 := Nat.add_mul_div_left _ _ H
_ = 0 + x.1 := by rw [Nat.div_eq_of_lt y.2]
_ = x.1 := Nat.zero_add x.1
)
(Fin.eq_of_val_eq <|
calc
(y.1 + n * x.1) % n = y.1 % n := Nat.add_mul_mod_self_left _ _ _
_ = y.1 := Nat.mod_eq_of_lt y.2
)
right_inv _ := Fin.eq_of_val_eq <| Nat.mod_add_div _ _
Nat.divModEquiv
definition
(n : ℕ) [NeZero n] : ℕ ≃ ℕ × Fin n
/-- The equivalence induced by `a ↦ (a / n, a % n)` for nonzero `n`.
This is like `finProdFinEquiv.symm` but with `m` infinite.
See `Nat.div_mod_unique` for a similar propositional statement. -/
@[simps]
def Nat.divModEquiv (n : ℕ) [NeZero n] : ℕℕ ≃ ℕ × Fin n where
toFun a := (a / n, ↑a)
invFun p := p.1 * n + ↑p.2
-- TODO: is there a canonical order of `*` and `+` here?
left_inv _ := Nat.div_add_mod' _ _
right_inv p := by
refine Prod.ext ?_ (Fin.ext <| Nat.mul_add_mod_of_lt p.2.is_lt)
dsimp only
rw [Nat.add_comm, Nat.add_mul_div_right _ _ n.pos_of_neZero, Nat.div_eq_of_lt p.2.is_lt,
Nat.zero_add]
Int.divModEquiv
definition
(n : ℕ) [NeZero n] : ℤ ≃ ℤ × Fin n
/-- The equivalence induced by `a ↦ (a / n, a % n)` for nonzero `n`.
See `Int.ediv_emod_unique` for a similar propositional statement. -/
@[simps]
def Int.divModEquiv (n : ℕ) [NeZero n] : ℤℤ ≃ ℤ × Fin n where
-- TODO: could cast from int directly if we import `Data.ZMod.Defs`, though there are few lemmas
-- about that coercion.
toFun a := (a / n, ↑(a.natMod n))
invFun p := p.1 * n + ↑p.2
left_inv a := by
simp_rw [Fin.coe_natCast_eq_mod, natCast_mod, natMod,
toNat_of_nonneg (emod_nonneg _ <| natCast_eq_zero.not.2 (NeZero.ne n)), emod_emod,
ediv_add_emod']
right_inv := fun ⟨q, r, hrn⟩ => by
simp only [Fin.val_mk, Prod.mk_inj, Fin.ext_iff]
obtain ⟨h1, h2⟩ := Int.natCast_nonneg r, Int.ofNat_lt.2 hrn
rw [Int.add_comm, add_mul_ediv_right _ _ (natCast_eq_zero.not.2 (NeZero.ne n)),
ediv_eq_zero_of_lt h1 h2, natMod, add_mul_emod_self_right, emod_eq_of_lt h1 h2, toNat_natCast]
exact ⟨q.zero_add, Fin.val_cast_of_lt hrn⟩
Fin.castLEquiv
definition
{n m : ℕ} (h : n ≤ m) : Fin n ≃ { i : Fin m // (i : ℕ) < n }
/-- Promote a `Fin n` into a larger `Fin m`, as a subtype where the underlying
values are retained.
This is the `Equiv` version of `Fin.castLE`. -/
@[simps apply symm_apply]
def Fin.castLEquiv {n m : ℕ} (h : n ≤ m) : FinFin n ≃ { i : Fin m // (i : ℕ) < n } where
toFun i := ⟨Fin.castLE h i, by simp⟩
invFun i := ⟨i, i.prop⟩
left_inv _ := by simp
right_inv _ := by simp
subsingleton_fin_zero
instance
: Subsingleton (Fin 0)
/-- `Fin 0` is a subsingleton. -/
instance subsingleton_fin_zero : Subsingleton (Fin 0) :=
finZeroEquiv.subsingleton
subsingleton_fin_one
instance
: Subsingleton (Fin 1)
/-- `Fin 1` is a subsingleton. -/
instance subsingleton_fin_one : Subsingleton (Fin 1) :=
finOneEquiv.subsingleton
Fin.appendEquiv
definition
{α : Type*} (m n : ℕ) : (Fin m → α) × (Fin n → α) ≃ (Fin (m + n) → α)
/-- The natural `Equiv` between `(Fin m → α) × (Fin n → α)` and `Fin (m + n) → α` -/
@[simps]
def Fin.appendEquiv {α : Type*} (m n : ℕ) :
(Fin m → α) × (Fin n → α)(Fin m → α) × (Fin n → α) ≃ (Fin (m + n) → α) where
toFun fg := Fin.append fg.1 fg.2
invFun f := ⟨fun i ↦ f (Fin.castAdd n i), fun i ↦ f (Fin.natAdd m i)⟩
left_inv fg := by simp
right_inv f := by simp [Fin.append_castAdd_natAdd]