mathlib documentation

data.fin.basic

The finite type with n elements #

fin n is the type whose elements are natural numbers smaller than n. This file expands on the development in the core library.

Main definitions #

Induction principles #

Order embeddings and an order isomorphism #

Other casts #

Misc definitions #

def fin_zero_elim {α : fin 0 → Sort u} (x : fin 0) :
α x

Elimination principle for the empty set fin 0, dependent version.

Equations
@[instance]
theorem fact.succ.pos {n : ℕ} :
fact (0 < n.succ)
@[instance]
theorem fact.bit0.pos {n : ℕ} [h : fact (0 < n)] :
fact (0 < bit0 n)
@[instance]
theorem fact.bit1.pos {n : ℕ} :
fact (0 < bit1 n)
@[instance]
theorem fact.pow.pos {p n : ℕ} [h : fact (0 < p)] :
fact (0 < p ^ n)
@[protected, instance]
def fin.fin_to_nat (n : ℕ) :
Equations
theorem fin.pos_iff_nonempty {n : ℕ} :
0 < n ↔ nonempty (fin n)

coercions and constructions #

@[protected, simp]
theorem fin.eta {n : ℕ} (a : fin n) (h : ↑a < n) :
⟨↑a, h⟩ = a
@[ext]
theorem fin.ext {n : ℕ} {a b : fin n} (h : ↑a = ↑b) :
a = b
theorem fin.ext_iff {n : ℕ} (a b : fin n) :
a = b ↔ ↑a = ↑b
theorem fin.eq_iff_veq {n : ℕ} (a b : fin n) :
a = b ↔ a.val = b.val
theorem fin.ne_iff_vne {n : ℕ} (a b : fin n) :
a ≠ b ↔ a.val ≠ b.val
@[simp]
theorem fin.mk_eq_subtype_mk {n : ℕ} (a : ℕ) (h : a < n) :
fin.mk a h = ⟨a, h⟩
@[protected]
theorem fin.mk.inj_iff {n a b : ℕ} {ha : a < n} {hb : b < n} :
⟨a, ha⟩ = ⟨b, hb⟩ ↔ a = b
theorem fin.mk_val {m n : ℕ} (h : m < n) :
⟨m, h⟩.val = m
theorem fin.eq_mk_iff_coe_eq {n : ℕ} {a : fin n} {k : ℕ} {hk : k < n} :
a = ⟨k, hk⟩ ↔ ↑a = k
@[simp, norm_cast]
theorem fin.coe_mk {m n : ℕ} (h : m < n) :
↑⟨m, h⟩ = m
theorem fin.mk_coe {n : ℕ} (i : fin n) :
⟨↑i, _⟩ = i
theorem fin.coe_eq_val {n : ℕ} (a : fin n) :
↑a = a.val
@[simp]
theorem fin.val_eq_coe {n : ℕ} (a : fin n) :
a.val = ↑a
@[protected]
theorem fin.heq_fun_iff {α : Sort u_1} {k l : ℕ} (h : k = l) {f : fin k → α} {g : fin l → α} :
f == g ↔ ∀ (i : fin k), f i = g ⟨↑i, _⟩

Assume k = l. If two functions defined on fin k and fin l are equal on each element, then they coincide (in the heq sense).

@[protected]
theorem fin.heq_ext_iff {k l : ℕ} (h : k = l) {i : fin k} {j : fin l} :
i == j ↔ ↑i = ↑j
theorem fin.exists_iff {n : ℕ} {p : fin n → Prop} :
(∃ (i : fin n), p i) ↔ ∃ (i : ℕ) (h : i < n), p ⟨i, h⟩
theorem fin.forall_iff {n : ℕ} {p : fin n → Prop} :
(∀ (i : fin n), p i) ↔ ∀ (i : ℕ) (h : i < n), p ⟨i, h⟩

order #

theorem fin.is_lt {n : ℕ} (i : fin n) :
↑i < n
theorem fin.is_le {n : ℕ} (i : fin (n + 1)) :
↑i ≤ n
theorem fin.lt_iff_coe_lt_coe {n : ℕ} {a b : fin n} :
a < b ↔ ↑a < ↑b
theorem fin.le_iff_coe_le_coe {n : ℕ} {a b : fin n} :
a ≤ b ↔ ↑a ≤ ↑b
theorem fin.mk_lt_of_lt_coe {n : ℕ} {b : fin n} {a : ℕ} (h : a < ↑b) :
⟨a, _⟩ < b
theorem fin.mk_le_of_le_coe {n : ℕ} {b : fin n} {a : ℕ} (h : a ≤ ↑b) :
⟨a, _⟩ ≤ b
@[simp, norm_cast]
theorem fin.coe_fin_lt {n : ℕ} {a b : fin n} :
↑a < ↑b ↔ a < b

a < b as natural numbers if and only if a < b in fin n.

@[simp, norm_cast]
theorem fin.coe_fin_le {n : ℕ} {a b : fin n} :
↑a ≤ ↑b ↔ a ≤ b

a ≤ b as natural numbers if and only if a ≤ b in fin n.

def fin.coe_embedding (n : ℕ) :

The inclusion map fin n → ℕ is a relation embedding.

Equations
@[protected, instance]

The ordering on fin n is a well order.

@[protected, instance]

Use the ordering on fin n for checking recursive definitions.

For example, the following definition is not accepted by the termination checker, unless we declare the has_well_founded instance:

def factorial {n : ℕ} : fin n → ℕ
| ⟨0, _⟩ := 1
| ⟨i + 1, hi⟩ := (i + 1) * factorial ⟨i, i.lt_succ_self.trans hi⟩
Equations
@[simp]
theorem fin.coe_zero {n : ℕ} :
↑0 = 0
@[simp]
theorem fin.val_zero' (n : ℕ) :
0.val = 0
@[simp]
theorem fin.mk_zero {n : ℕ} :
⟨0, _⟩ = 0
theorem fin.zero_le {n : ℕ} (a : fin (n + 1)) :
0 ≤ a
theorem fin.zero_lt_one {n : ℕ} :
0 < 1
theorem fin.pos_iff_ne_zero {n : ℕ} (a : fin (n + 1)) :
0 < a ↔ a ≠ 0
theorem fin.eq_zero_or_eq_succ {n : ℕ} (i : fin (n + 1)) :
i = 0 ∨ ∃ (j : fin n), i = j.succ
def fin.last (n : ℕ) :
fin (n + 1)

The greatest value of fin (n+1)

Equations
@[simp, norm_cast]
theorem fin.coe_last (n : ℕ) :
theorem fin.last_val (n : ℕ) :
(fin.last n).val = n
theorem fin.le_last {n : ℕ} (i : fin (n + 1)) :
@[protected, instance]
def fin.bounded_order {n : ℕ} :
Equations
@[protected, instance]
def fin.lattice {n : ℕ} :
lattice (fin (n + 1))
Equations
theorem fin.last_pos {n : ℕ} :
0 < fin.last (n + 1)
theorem fin.eq_last_of_not_lt {n : ℕ} {i : fin (n + 1)} (h : ¬↑i < n) :
@[simp]
theorem fin.coe_order_iso_apply {n m : ℕ} (e : fin n ≃o fin m) (i : fin n) :
↑(⇑e i) = ↑i

If e is an order_iso between fin n and fin m, then n = m and e is the identity map. In this lemma we state that for each i : fin n we have (e i : ℕ) = (i : ℕ).

@[protected, instance]
def fin.order_iso_subsingleton {n : ℕ} {α : Type u_1} [preorder α] :
@[protected, instance]
def fin.order_iso_subsingleton' {n : ℕ} {α : Type u_1} [preorder α] :
@[protected, instance]
def fin.order_iso_unique {n : ℕ} :
Equations
theorem fin.strict_mono_unique {n : ℕ} {α : Type u_1} [preorder α] {f g : fin n → α} (hf : strict_mono f) (hg : strict_mono g) (h : set.range f = set.range g) :
f = g

Two strictly monotone functions from fin n are equal provided that their ranges are equal.

theorem fin.order_embedding_eq {n : ℕ} {α : Type u_1} [preorder α] {f g : fin n ↪o α} (h : set.range ⇑f = set.range ⇑g) :
f = g

Two order embeddings of fin n are equal provided that their ranges are equal.

theorem fin.strict_mono_iff_lt_succ {n : ℕ} {α : Type u_1} [preorder α] {f : fin n → α} :
strict_mono f ↔ ∀ (i : ℕ) (h : i + 1 < n), f ⟨i, _⟩ < f ⟨i + 1, h⟩

A function f on fin n is strictly monotone if and only if f i < f (i+1) for all i.

addition, numerals, and coercion from nat #

def fin.of_nat' {n : ℕ} [h : fact (0 < n)] (i : ℕ) :
fin n

Given a positive n, fin.of_nat' i is i % n as an element of fin n.

Equations
theorem fin.one_val {n : ℕ} :
1.val = 1 % (n + 1)
theorem fin.coe_one' {n : ℕ} :
↑1 = 1 % (n + 1)
@[simp]
theorem fin.val_one {n : ℕ} :
1.val = 1
@[simp]
theorem fin.coe_one {n : ℕ} :
↑1 = 1
@[simp]
theorem fin.mk_one {n : ℕ} :
⟨1, _⟩ = 1
@[protected, instance]
def fin.nontrivial {n : ℕ} :
nontrivial (fin (n + 2))
@[protected, simp]
theorem fin.add_zero {n : ℕ} (k : fin (n + 1)) :
k + 0 = k
@[protected, simp]
theorem fin.zero_add {n : ℕ} (k : fin (n + 1)) :
0 + k = k
@[protected, instance]
Equations
theorem fin.val_add {n : ℕ} (a b : fin n) :
(a + b).val = (a.val + b.val) % n
theorem fin.coe_add {n : ℕ} (a b : fin n) :
↑(a + b) = (↑a + ↑b) % n
theorem fin.coe_add_eq_ite {n : ℕ} (a b : fin n) :
↑(a + b) = ite (n ≤ ↑a + ↑b) (↑a + ↑b - n) (↑a + ↑b)
theorem fin.coe_bit0 {n : ℕ} (k : fin n) :
↑(bit0 k) = bit0 ↑k % n
theorem fin.coe_bit1 {n : ℕ} (k : fin (n + 1)) :
↑(bit1 k) = bit1 ↑k % (n + 1)
theorem fin.coe_add_one_of_lt {n : ℕ} {i : fin n.succ} (h : i < fin.last n) :
↑(i + 1) = ↑i + 1
@[simp]
theorem fin.last_add_one (n : ℕ) :
fin.last n + 1 = 0
theorem fin.coe_add_one {n : ℕ} (i : fin (n + 1)) :
↑(i + 1) = ite (i = fin.last n) 0 (↑i + 1)
@[simp]
theorem fin.mk_bit0 {m n : ℕ} (h : bit0 m < n) :
⟨bit0 m, h⟩ = bit0 ⟨m, _⟩
@[simp]
theorem fin.mk_bit1 {m n : ℕ} (h : bit1 m < n + 1) :
⟨bit1 m, h⟩ = bit1 ⟨m, _⟩
@[simp]
theorem fin.val_two {n : ℕ} :
2.val = 2
@[simp]
theorem fin.coe_two {n : ℕ} :
↑2 = 2
@[simp]
theorem fin.of_nat_eq_coe (n a : ℕ) :
theorem fin.coe_val_of_lt {n a : ℕ} (h : a < n + 1) :
↑a.val = a

Converting an in-range number to fin (n + 1) produces a result whose value is the original number.

theorem fin.coe_val_eq_self {n : ℕ} (a : fin (n + 1)) :
↑(a.val) = a

Converting the value of a fin (n + 1) to fin (n + 1) results in the same value.

theorem fin.coe_coe_of_lt {n a : ℕ} (h : a < n + 1) :

Coercing an in-range number to fin (n + 1), and converting back to ℕ, results in that number.

@[simp]
theorem fin.coe_coe_eq_self {n : ℕ} (a : fin (n + 1)) :

Converting a fin (n + 1) to ℕ and back results in the same value.

theorem fin.coe_nat_eq_last (n : ℕ) :
theorem fin.le_coe_last {n : ℕ} (i : fin (n + 1)) :
i ≤ ↑n
theorem fin.add_one_pos {n : ℕ} (i : fin (n + 1)) (h : i < fin.last n) :
0 < i + 1
theorem fin.one_pos {n : ℕ} :
0 < 1
theorem fin.zero_ne_one {n : ℕ} :
0 ≠ 1
@[simp]
theorem fin.zero_eq_one_iff {n : ℕ} :
0 = 1 ↔ n = 0
@[simp]
theorem fin.one_eq_zero_iff {n : ℕ} :
1 = 0 ↔ n = 0

succ and casts into larger fin types #

@[simp]
theorem fin.coe_succ {n : ℕ} (j : fin n) :
↑(j.succ) = ↑j + 1
theorem fin.succ_pos {n : ℕ} (a : fin n) :
0 < a.succ
@[simp]
theorem fin.succ_le_succ_iff {n : ℕ} {a b : fin n} :
a.succ ≤ b.succ ↔ a ≤ b
@[simp]
theorem fin.succ_lt_succ_iff {n : ℕ} {a b : fin n} :
a.succ < b.succ ↔ a < b
@[simp]
theorem fin.succ_inj {n : ℕ} {a b : fin n} :
a.succ = b.succ ↔ a = b
theorem fin.succ_ne_zero {n : ℕ} (k : fin n) :
k.succ ≠ 0
@[simp]
theorem fin.succ_zero_eq_one {n : ℕ} :
0.succ = 1
@[simp]
theorem fin.succ_one_eq_two {n : ℕ} :
1.succ = 2
@[simp]
theorem fin.succ_mk (n i : ℕ) (h : i < n) :
fin.succ ⟨i, h⟩ = ⟨i + 1, _⟩
theorem fin.mk_succ_pos {n : ℕ} (i : ℕ) (h : i < n) :
0 < ⟨i.succ, _⟩
theorem fin.one_lt_succ_succ {n : ℕ} (a : fin n) :
1 < a.succ.succ
theorem fin.succ_succ_ne_one {n : ℕ} (a : fin n) :
def fin.cast_lt {n m : ℕ} (i : fin m) (h : i.val < n) :
fin n

cast_lt i h embeds i into a fin where h proves it belongs into.

Equations
@[simp]
theorem fin.coe_cast_lt {n m : ℕ} (i : fin m) (h : i.val < n) :
@[simp]
theorem fin.cast_lt_mk (i n m : ℕ) (hn : i < n) (hm : i < m) :
fin.cast_lt ⟨i, hn⟩ hm = ⟨i, hm⟩
def fin.cast_le {n m : ℕ} (h : n ≤ m) :

cast_le h i embeds i into a larger fin type.

Equations
@[simp]
theorem fin.coe_cast_le {n m : ℕ} (h : n ≤ m) (i : fin n) :
@[simp]
theorem fin.cast_le_mk (i n m : ℕ) (hn : i < n) (h : n ≤ m) :
⇑(fin.cast_le h) ⟨i, hn⟩ = ⟨i, _⟩
@[simp]
theorem fin.cast_le_zero {n m : ℕ} (h : n.succ ≤ m.succ) :
@[simp]
theorem fin.range_cast_le {n k : ℕ} (h : n ≤ k) :
set.range ⇑(fin.cast_le h) = {i : fin k | ↑i < n}
@[simp]
theorem fin.coe_of_injective_cast_le_symm {n k : ℕ} (h : n ≤ k) (i : fin k) (hi : i ∈ set.range ⇑(fin.cast_le h)) :
@[simp]
theorem fin.cast_le_succ {m n : ℕ} (h : m + 1 ≤ n + 1) (i : fin m) :
def fin.cast {n m : ℕ} (eq : n = m) :

cast eq i embeds i into a equal fin type, see also equiv.fin_congr.

Equations
@[simp]
theorem fin.symm_cast {n m : ℕ} (h : n = m) :
@[simp]
theorem fin.coe_cast {n m : ℕ} (h : n = m) (i : fin n) :

While fin.coe_order_iso_apply is a more general case of this, we mark this simp anyway as it is eligible for dsimp.

@[simp]
theorem fin.cast_mk {n m : ℕ} (h : n = m) (i : ℕ) (hn : i < n) :
⇑(fin.cast h) ⟨i, hn⟩ = ⟨i, _⟩
@[simp]
theorem fin.cast_trans {n m k : ℕ} (h : n = m) (h' : m = k) {i : fin n} :
@[simp]
theorem fin.cast_refl {n : ℕ} (h : n = n := rfl) :
theorem fin.cast_to_equiv {n m : ℕ} (h : n = m) :

While in many cases fin.cast is better than equiv.cast/cast, sometimes we want to apply a generic theorem about cast.

theorem fin.cast_eq_cast {n m : ℕ} (h : n = m) :

While in many cases fin.cast is better than equiv.cast/cast, sometimes we want to apply a generic theorem about cast.

def fin.cast_add {n : ℕ} (m : ℕ) :
fin n ↪o fin (n + m)

cast_add m i embeds i : fin n in fin (n+m). See also fin.nat_add and fin.add_nat.

Equations
@[simp]
theorem fin.coe_cast_add {n : ℕ} (m : ℕ) (i : fin n) :
theorem fin.cast_add_lt {m : ℕ} (n : ℕ) (i : fin m) :
@[simp]
theorem fin.cast_add_mk {n : ℕ} (m i : ℕ) (h : i < n) :
⇑(fin.cast_add m) ⟨i, h⟩ = ⟨i, _⟩
@[simp]
theorem fin.cast_add_cast_lt {n : ℕ} (m : ℕ) (i : fin (n + m)) (hi : i.val < n) :
@[simp]
theorem fin.cast_lt_cast_add {n : ℕ} (m : ℕ) (i : fin n) :
theorem fin.cast_add_cast {n n' : ℕ} (m : ℕ) (i : fin n') (h : n' = n) :

For rewriting in the reverse direction, see fin.cast_cast_add_left.

theorem fin.cast_cast_add_left {n n' m : ℕ} (i : fin n') (h : n' + m = n + m) :
@[simp]
theorem fin.cast_cast_add_right {n m m' : ℕ} (i : fin n) (h : n + m' = n + m) :
@[simp]
theorem fin.cast_succ_eq {n n' : ℕ} (i : fin n) (h : n.succ = n'.succ) :

The cast of the successor is the succesor of the cast. See fin.succ_cast_eq for rewriting in the reverse direction.

theorem fin.succ_cast_eq {n n' : ℕ} (i : fin n) (h : n = n') :
def fin.cast_succ {n : ℕ} :
fin n ↪o fin (n + 1)

cast_succ i embeds i : fin n in fin (n+1).

Equations
@[simp]
theorem fin.coe_cast_succ {n : ℕ} (i : fin n) :
@[simp]
theorem fin.cast_succ_mk (n i : ℕ) (h : i < n) :
⇑fin.cast_succ ⟨i, h⟩ = ⟨i, _⟩
theorem fin.cast_succ_lt_succ {n : ℕ} (i : fin n) :
theorem fin.le_cast_succ_iff {n : ℕ} {i : fin (n + 1)} {j : fin n} :
@[simp]
theorem fin.succ_last (n : ℕ) :
@[simp]
theorem fin.succ_eq_last_succ {n : ℕ} (i : fin n.succ) :
i.succ = fin.last (n + 1) ↔ i = fin.last n
@[simp]
theorem fin.cast_succ_cast_lt {n : ℕ} (i : fin (n + 1)) (h : ↑i < n) :
@[simp]
theorem fin.cast_lt_cast_succ {n : ℕ} (a : fin n) (h : ↑a < n) :
@[simp]
theorem fin.cast_succ_inj {n : ℕ} {a b : fin n} :
@[simp]
theorem fin.cast_succ_zero {n : ℕ} :
@[simp]
theorem fin.cast_succ_one {n : ℕ} :
theorem fin.cast_succ_pos {n : ℕ} {i : fin (n + 1)} (h : 0 < i) :

cast_succ i is positive when i is positive

@[simp]
theorem fin.cast_succ_eq_zero_iff {n : ℕ} (a : fin (n + 1)) :
theorem fin.cast_succ_ne_zero_iff {n : ℕ} (a : fin (n + 1)) :
@[simp, norm_cast]
theorem fin.coe_eq_cast_succ {n : ℕ} {a : fin n} :
@[simp]
theorem fin.coe_succ_eq_succ {n : ℕ} {a : fin n} :
theorem fin.lt_succ {n : ℕ} {a : fin n} :
@[simp]
theorem fin.range_cast_succ {n : ℕ} :
set.range ⇑fin.cast_succ = {i : fin (n + 1) | ↑i < n}
def fin.add_nat {n : ℕ} (m : ℕ) :
fin n ↪o fin (n + m)

add_nat m i adds m to i, generalizes fin.succ.

Equations
@[simp]
theorem fin.coe_add_nat {n : ℕ} (m : ℕ) (i : fin n) :
theorem fin.le_coe_add_nat {n : ℕ} (m : ℕ) (i : fin n) :
@[simp]
theorem fin.add_nat_mk {m : ℕ} (n i : ℕ) (hi : i < m) :
⇑(fin.add_nat n) ⟨i, hi⟩ = ⟨i + n, _⟩
@[simp]
theorem fin.cast_add_nat_zero {n n' : ℕ} (i : fin n) (h : n + 0 = n') :
theorem fin.add_nat_cast {n n' m : ℕ} (i : fin n') (h : n' = n) :

For rewriting in the reverse direction, see fin.cast_add_nat_left.

theorem fin.cast_add_nat_left {n n' m : ℕ} (i : fin n') (h : n' + m = n + m) :
@[simp]
theorem fin.cast_add_nat_right {n m m' : ℕ} (i : fin n) (h : n + m' = n + m) :
def fin.nat_add (n : ℕ) {m : ℕ} :
fin m ↪o fin (n + m)

nat_add n i adds n to i "on the left".

Equations
@[simp]
theorem fin.coe_nat_add (n : ℕ) {m : ℕ} (i : fin m) :
@[simp]
theorem fin.nat_add_mk {m : ℕ} (n i : ℕ) (hi : i < m) :
⇑(fin.nat_add n) ⟨i, hi⟩ = ⟨n + i, _⟩
theorem fin.le_coe_nat_add {n : ℕ} (m : ℕ) (i : fin n) :
theorem fin.nat_add_cast {n n' : ℕ} (m : ℕ) (i : fin n') (h : n' = n) :

For rewriting in the reverse direction, see fin.cast_nat_add_right.

theorem fin.cast_nat_add_right {n n' m : ℕ} (i : fin n') (h : m + n' = m + n) :
@[simp]
theorem fin.cast_nat_add_left {n m m' : ℕ} (i : fin n) (h : m' + n = m + n) :
@[simp]
theorem fin.cast_nat_add_zero {n n' : ℕ} (i : fin n) (h : 0 + n = n') :
@[simp]
theorem fin.cast_nat_add (n : ℕ) {m : ℕ} (i : fin m) :
@[simp]
theorem fin.cast_add_nat {n : ℕ} (m : ℕ) (i : fin n) :

pred #

@[simp]
theorem fin.coe_pred {n : ℕ} (j : fin (n + 1)) (h : j ≠ 0) :
↑(j.pred h) = ↑j - 1
@[simp]
theorem fin.succ_pred {n : ℕ} (i : fin (n + 1)) (h : i ≠ 0) :
(i.pred h).succ = i
@[simp]
theorem fin.pred_succ {n : ℕ} (i : fin n) {h : i.succ ≠ 0} :
i.succ.pred h = i
@[simp]
theorem fin.pred_mk_succ {n : ℕ} (i : ℕ) (h : i < n + 1) :
fin.pred ⟨i + 1, _⟩ _ = ⟨i, h⟩
theorem fin.pred_mk {n : ℕ} (i : ℕ) (h : i < n + 1) (w : ⟨i, h⟩ ≠ 0) :
fin.pred ⟨i, h⟩ w = ⟨i - 1, _⟩
@[simp]
theorem fin.pred_le_pred_iff {n : ℕ} {a b : fin n.succ} {ha : a ≠ 0} {hb : b ≠ 0} :
a.pred ha ≤ b.pred hb ↔ a ≤ b
@[simp]
theorem fin.pred_lt_pred_iff {n : ℕ} {a b : fin n.succ} {ha : a ≠ 0} {hb : b ≠ 0} :
a.pred ha < b.pred hb ↔ a < b
@[simp]
theorem fin.pred_inj {n : ℕ} {a b : fin (n + 1)} {ha : a ≠ 0} {hb : b ≠ 0} :
a.pred ha = b.pred hb ↔ a = b
@[simp]
theorem fin.pred_one {n : ℕ} :
1.pred _ = 0
theorem fin.pred_add_one {n : ℕ} (i : fin (n + 2)) (h : ↑i < n + 1) :
(i + 1).pred _ = i.cast_lt h
def fin.sub_nat {n : ℕ} (m : ℕ) (i : fin (n + m)) (h : m ≤ ↑i) :
fin n

sub_nat i h subtracts m from i, generalizes fin.pred.

Equations
@[simp]
theorem fin.coe_sub_nat {n m : ℕ} (i : fin (n + m)) (h : m ≤ ↑i) :
↑(fin.sub_nat m i h) = ↑i - m
@[simp]
theorem fin.sub_nat_mk {n m i : ℕ} (h₁ : i < n + m) (h₂ : m ≤ i) :
fin.sub_nat m ⟨i, h₁⟩ h₂ = ⟨i - m, _⟩
@[simp]
@[simp]
theorem fin.add_nat_sub_nat {n m : ℕ} {i : fin (n + m)} (h : m ≤ ↑i) :
@[simp]
theorem fin.sub_nat_add_nat {n : ℕ} (i : fin n) (m : ℕ) (h : m ≤ ↑(⇑(fin.add_nat m) i) := _) :
@[simp]
theorem fin.nat_add_sub_nat_cast {n m : ℕ} {i : fin (n + m)} (h : n ≤ ↑i) :
def fin.div_nat {n m : ℕ} (i : fin (m * n)) :
fin m

Compute i / n, where n is a nat and inferred the type of i.

Equations
@[simp]
theorem fin.coe_div_nat {n m : ℕ} (i : fin (m * n)) :
↑(i.div_nat) = ↑i / n
def fin.mod_nat {n m : ℕ} (i : fin (m * n)) :
fin n

Compute i % n, where n is a nat and inferred the type of i.

Equations
@[simp]
theorem fin.coe_mod_nat {n m : ℕ} (i : fin (m * n)) :
↑(i.mod_nat) = ↑i % n

recursion and induction principles #

def fin.succ_rec {C : Π (n : ℕ), fin n → Sort u_1} (H0 : Π (n : ℕ), C n.succ 0) (Hs : Π (n : ℕ) (i : fin n), C n i → C n.succ i.succ) {n : ℕ} (i : fin n) :
C n i

Define C n i by induction on i : fin n interpreted as (0 : fin (n - i)).succ.succ…. This function has two arguments: H0 n defines 0-th element C (n+1) 0 of an (n+1)-tuple, and Hs n i defines (i+1)-st element of (n+1)-tuple based on n, i, and i-th element of n-tuple.

Equations
def fin.succ_rec_on {n : ℕ} (i : fin n) {C : Π (n : ℕ), fin n → Sort u_1} (H0 : Π (n : ℕ), C n.succ 0) (Hs : Π (n : ℕ) (i : fin n), C n i → C n.succ i.succ) :
C n i

Define C n i by induction on i : fin n interpreted as (0 : fin (n - i)).succ.succ…. This function has two arguments: H0 n defines 0-th element C (n+1) 0 of an (n+1)-tuple, and Hs n i defines (i+1)-st element of (n+1)-tuple based on n, i, and i-th element of n-tuple.

A version of fin.succ_rec taking i : fin n as the first argument.

Equations
@[simp]
theorem fin.succ_rec_on_zero {C : Π (n : ℕ), fin n → Sort u_1} {H0 : Π (n : ℕ), C n.succ 0} {Hs : Π (n : ℕ) (i : fin n), C n i → C n.succ i.succ} (n : ℕ) :
0.succ_rec_on H0 Hs = H0 n
@[simp]
theorem fin.succ_rec_on_succ {C : Π (n : ℕ), fin n → Sort u_1} {H0 : Π (n : ℕ), C n.succ 0} {Hs : Π (n : ℕ) (i : fin n), C n i → C n.succ i.succ} {n : ℕ} (i : fin n) :
i.succ.succ_rec_on H0 Hs = Hs n i (i.succ_rec_on H0 Hs)
def fin.induction {n : ℕ} {C : fin (n + 1) → Sort u_1} (h0 : C 0) (hs : Π (i : fin n), C (⇑fin.cast_succ i) → C i.succ) (i : fin (n + 1)) :
C i

Define C i by induction on i : fin (n + 1) via induction on the underlying nat value. This function has two arguments: h0 handles the base case on C 0, and hs defines the inductive step using C i.cast_succ.

Equations
  • fin.induction h0 hs = λ (i : fin (n + 1)), subtype.cases_on i (λ (i : ℕ) (hi : i < n + 1), nat.rec (λ (hi : 0 < n + 1), _.mpr h0) (λ (i : ℕ) (IH : Π (hi : i < n + 1), C ⟨i, hi⟩) (hi : i.succ < n + 1), hs ⟨i, _⟩ (IH _)) i hi)
def fin.induction_on {n : ℕ} (i : fin (n + 1)) {C : fin (n + 1) → Sort u_1} (h0 : C 0) (hs : Π (i : fin n), C (⇑fin.cast_succ i) → C i.succ) :
C i

Define C i by induction on i : fin (n + 1) via induction on the underlying nat value. This function has two arguments: h0 handles the base case on C 0, and hs defines the inductive step using C i.cast_succ.

A version of fin.induction taking i : fin (n + 1) as the first argument.

Equations
def fin.cases {n : ℕ} {C : fin n.succ → Sort u_1} (H0 : C 0) (Hs : Π (i : fin n), C i.succ) (i : fin n.succ) :
C i

Define f : Π i : fin n.succ, C i by separately handling the cases i = 0 and i = j.succ, j : fin n.

Equations
@[simp]
theorem fin.cases_zero {n : ℕ} {C : fin n.succ → Sort u_1} {H0 : C 0} {Hs : Π (i : fin n), C i.succ} :
fin.cases H0 Hs 0 = H0
@[simp]
theorem fin.cases_succ {n : ℕ} {C : fin n.succ → Sort u_1} {H0 : C 0} {Hs : Π (i : fin n), C i.succ} (i : fin n) :
fin.cases H0 Hs i.succ = Hs i
@[simp]
theorem fin.cases_succ' {n : ℕ} {C : fin n.succ → Sort u_1} {H0 : C 0} {Hs : Π (i : fin n), C i.succ} {i : ℕ} (h : i + 1 < n + 1) :
fin.cases H0 Hs ⟨i.succ, h⟩ = Hs ⟨i, _⟩
theorem fin.forall_fin_succ {n : ℕ} {P : fin (n + 1) → Prop} :
(∀ (i : fin (n + 1)), P i) ↔ P 0 ∧ ∀ (i : fin n), P i.succ
theorem fin.exists_fin_succ {n : ℕ} {P : fin (n + 1) → Prop} :
(∃ (i : fin (n + 1)), P i) ↔ P 0 ∨ ∃ (i : fin n), P i.succ
theorem fin.forall_fin_one {p : fin 1 → Prop} :
(∀ (i : fin 1), p i) ↔ p 0
theorem fin.exists_fin_one {p : fin 1 → Prop} :
(∃ (i : fin 1), p i) ↔ p 0
theorem fin.forall_fin_two {p : fin 2 → Prop} :
(∀ (i : fin 2), p i) ↔ p 0 ∧ p 1
theorem fin.exists_fin_two {p : fin 2 → Prop} :
(∃ (i : fin 2), p i) ↔ p 0 ∨ p 1
def fin.reverse_induction {n : ℕ} {C : fin (n + 1) → Sort u_1} (hlast : C (fin.last n)) (hs : Π (i : fin n), C i.succ → C (⇑fin.cast_succ i)) (i : fin (n + 1)) :
C i

Define C i by reverse induction on i : fin (n + 1) via induction on the underlying nat value. This function has two arguments: hlast handles the base case on C (fin.last n), and hs defines the inductive step using C i.succ, inducting downwards.

Equations
@[simp]
theorem fin.reverse_induction_last {n : ℕ} {C : fin (n + 1) → Sort u_1} (h0 : C (fin.last n)) (hs : Π (i : fin n), C i.succ → C (⇑fin.cast_succ i)) :
@[simp]
theorem fin.reverse_induction_cast_succ {n : ℕ} {C : fin (n + 1) → Sort u_1} (h0 : C (fin.last n)) (hs : Π (i : fin n), C i.succ → C (⇑fin.cast_succ i)) (i : fin n) :
def fin.last_cases {n : ℕ} {C : fin (n + 1) → Sort u_1} (hlast : C (fin.last n)) (hcast : Π (i : fin n), C (⇑fin.cast_succ i)) (i : fin (n + 1)) :
C i

Define f : Π i : fin n.succ, C i by separately handling the cases i = fin.last n and i = j.cast_succ, j : fin n.

Equations
@[simp]
theorem fin.last_cases_last {n : ℕ} {C : fin (n + 1) → Sort u_1} (hlast : C (fin.last n)) (hcast : Π (i : fin n), C (⇑fin.cast_succ i)) :
fin.last_cases hlast hcast (fin.last n) = hlast
@[simp]
theorem fin.last_cases_cast_succ {n : ℕ} {C : fin (n + 1) → Sort u_1} (hlast : C (fin.last n)) (hcast : Π (i : fin n), C (⇑fin.cast_succ i)) (i : fin n) :
fin.last_cases hlast hcast (⇑fin.cast_succ i) = hcast i
def fin.add_cases {m n : ℕ} {C : fin (m + n) → Sort u} (hleft : Π (i : fin m), C (⇑(fin.cast_add n) i)) (hright : Π (i : fin n), C (⇑(fin.nat_add m) i)) (i : fin (m + n)) :
C i

Define f : Π i : fin (m + n), C i by separately handling the cases i = cast_add n i, j : fin m and i = nat_add m j, j : fin n.

Equations
@[simp]
theorem fin.add_cases_left {m n : ℕ} {C : fin (m + n) → Sort u_1} (hleft : Π (i : fin m), C (⇑(fin.cast_add n) i)) (hright : Π (i : fin n), C (⇑(fin.nat_add m) i)) (i : fin m) :
fin.add_cases hleft hright (⇑(fin.cast_add n) i) = hleft i
@[simp]
theorem fin.add_cases_right {m n : ℕ} {C : fin (m + n) → Sort u_1} (hleft : Π (i : fin m), C (⇑(fin.cast_add n) i)) (hright : Π (i : fin n), C (⇑(fin.nat_add m) i)) (i : fin n) :
fin.add_cases hleft hright (⇑(fin.nat_add m) i) = hright i
@[protected, instance]
def fin.has_neg (n : ℕ) :

Negation on fin n

Equations
@[protected]
theorem fin.coe_neg {n : ℕ} (a : fin n) :
↑-a = (n - ↑a) % n
@[protected]
theorem fin.coe_sub {n : ℕ} (a b : fin n) :
↑(a - b) = (↑a + (n - ↑b)) % n
theorem fin.succ_above_aux {n : ℕ} (p : fin (n + 1)) :
def fin.succ_above {n : ℕ} (p : fin (n + 1)) :
fin n ↪o fin (n + 1)

succ_above p i embeds fin n into fin (n + 1) with a hole around p.

Equations
theorem fin.succ_above_below {n : ℕ} (p : fin (n + 1)) (i : fin n) (h : ⇑fin.cast_succ i < p) :

Embedding i : fin n into fin (n + 1) with a hole around p : fin (n + 1) embeds i by cast_succ when the resulting i.cast_succ < p.

@[simp]
theorem fin.succ_above_ne_zero_zero {n : ℕ} {a : fin (n + 2)} (ha : a ≠ 0) :
theorem fin.succ_above_eq_zero_iff {n : ℕ} {a : fin (n + 2)} {b : fin (n + 1)} (ha : a ≠ 0) :
⇑(a.succ_above) b = 0 ↔ b = 0
theorem fin.succ_above_ne_zero {n : ℕ} {a : fin (n + 2)} {b : fin (n + 1)} (ha : a ≠ 0) (hb : b ≠ 0) :
@[simp]

Embedding fin n into fin (n + 1) with a hole around zero embeds by succ.

@[simp]

Embedding fin n into fin (n + 1) with a hole around last n embeds by cast_succ.

theorem fin.succ_above_above {n : ℕ} (p : fin (n + 1)) (i : fin n) (h : p ≤ ⇑fin.cast_succ i) :

Embedding i : fin n into fin (n + 1) with a hole around p : fin (n + 1) embeds i by succ when the resulting p < i.succ.

theorem fin.succ_above_lt_ge {n : ℕ} (p : fin (n + 1)) (i : fin n) :

Embedding i : fin n into fin (n + 1) is always about some hole p.

theorem fin.succ_above_lt_gt {n : ℕ} (p : fin (n + 1)) (i : fin n) :

Embedding i : fin n into fin (n + 1) is always about some hole p.

@[simp]
theorem fin.succ_above_lt_iff {n : ℕ} (p : fin (n + 1)) (i : fin n) :

Embedding i : fin n into fin (n + 1) using a pivot p that is greater results in a value that is less than p.

theorem fin.lt_succ_above_iff {n : ℕ} (p : fin (n + 1)) (i : fin n) :

Embedding i : fin n into fin (n + 1) using a pivot p that is lesser results in a value that is greater than p.

theorem fin.succ_above_ne {n : ℕ} (p : fin (n + 1)) (i : fin n) :

Embedding i : fin n into fin (n + 1) with a hole around p : fin (n + 1) never results in p itself

theorem fin.succ_above_pos {n : ℕ} (p : fin (n + 2)) (i : fin (n + 1)) (h : 0 < i) :

Embedding a positive fin n results in a positive fin (n + 1)`

@[simp]
theorem fin.succ_above_cast_lt {n : ℕ} {x y : fin (n + 1)} (h : x < y) (hx : x.val < n := _) :
⇑(y.succ_above) (x.cast_lt hx) = x
@[simp]
theorem fin.succ_above_pred {n : ℕ} {x y : fin (n + 1)} (h : x < y) (hy : y ≠ 0 := _) :
⇑(x.succ_above) (y.pred hy) = y
theorem fin.cast_lt_succ_above {n : ℕ} {x : fin n} {y : fin (n + 1)} (h : ⇑fin.cast_succ x < y) (h' : (⇑(y.succ_above) x).val < n := _) :
(⇑(y.succ_above) x).cast_lt h' = x
theorem fin.pred_succ_above {n : ℕ} {x : fin n} {y : fin (n + 1)} (h : y ≤ ⇑fin.cast_succ x) (h' : ⇑(y.succ_above) x ≠ 0 := _) :
(⇑(y.succ_above) x).pred h' = x
theorem fin.exists_succ_above_eq {n : ℕ} {x y : fin (n + 1)} (h : x ≠ y) :
∃ (z : fin n), ⇑(y.succ_above) z = x
@[simp]
theorem fin.exists_succ_above_eq_iff {n : ℕ} {x y : fin (n + 1)} :
(∃ (z : fin n), ⇑(x.succ_above) z = y) ↔ y ≠ x
@[simp]
theorem fin.range_succ_above {n : ℕ} (p : fin (n + 1)) :

The range of p.succ_above is everything except p.

Given a fixed pivot x : fin (n + 1), x.succ_above is injective

theorem fin.succ_above_right_inj {n : ℕ} {a b : fin n} {x : fin (n + 1)} :

Given a fixed pivot x : fin (n + 1), x.succ_above is injective

succ_above is injective at the pivot

@[simp]
theorem fin.succ_above_left_inj {n : ℕ} {x y : fin (n + 1)} :

succ_above is injective at the pivot

@[simp]
theorem fin.zero_succ_above {n : ℕ} (i : fin n) :
@[simp]
theorem fin.succ_succ_above_zero {n : ℕ} (i : fin (n + 1)) :
@[simp]
theorem fin.succ_succ_above_succ {n : ℕ} (i : fin (n + 1)) (j : fin n) :
@[simp]
theorem fin.one_succ_above_zero {n : ℕ} :
@[simp]
theorem fin.succ_succ_above_one {n : ℕ} (i : fin (n + 2)) :

By moving succ to the outside of this expression, we create opportunities for further simplification using succ_above_zero or succ_succ_above_zero.

@[simp]
theorem fin.one_succ_above_succ {n : ℕ} (j : fin n) :
@[simp]
theorem fin.one_succ_above_one {n : ℕ} :
def fin.pred_above {n : ℕ} (p : fin n) (i : fin (n + 1)) :
fin n

pred_above p i embeds i : fin (n+1) into fin n by subtracting one if p < i.

Equations
theorem fin.pred_above_left_monotone {n : ℕ} (i : fin (n + 1)) :
monotone (λ (p : fin n), p.pred_above i)
def fin.cast_pred {n : ℕ} (i : fin (n + 2)) :
fin (n + 1)

cast_pred embeds i : fin (n + 2) into fin (n + 1) by lowering just last (n + 1) to last n.

Equations
@[simp]
theorem fin.cast_pred_zero {n : ℕ} :
@[simp]
theorem fin.cast_pred_one {n : ℕ} :
@[simp]
theorem fin.pred_above_zero {n : ℕ} {i : fin (n + 2)} (hi : i ≠ 0) :
0.pred_above i = i.pred hi
@[simp]
theorem fin.cast_pred_last {n : ℕ} :
@[simp]
theorem fin.cast_pred_mk (n i : ℕ) (h : i < n + 1) :
fin.cast_pred ⟨i, _⟩ = ⟨i, h⟩
theorem fin.pred_above_below {n : ℕ} (p : fin (n + 1)) (i : fin (n + 2)) (h : i ≤ ⇑fin.cast_succ p) :
theorem fin.pred_above_above {n : ℕ} (p : fin n) (i : fin (n + 1)) (h : ⇑fin.cast_succ p < i) :
p.pred_above i = i.pred _
@[simp]
theorem fin.succ_above_pred_above {n : ℕ} {p : fin n} {i : fin (n + 1)} (h : i ≠ ⇑fin.cast_succ p) :

Sending fin (n+1) to fin n by subtracting one from anything above p then back to fin (n+1) with a gap around p is the identity away from p.

@[simp]
theorem fin.pred_above_succ_above {n : ℕ} (p i : fin n) :

Sending fin n into fin (n + 1) with a gap at p then back to fin n by subtracting one from anything above p is the identity.

theorem fin.cast_succ_pred_eq_pred_cast_succ {n : ℕ} {a : fin (n + 1)} (ha : a ≠ 0) (ha' : ⇑fin.cast_succ a ≠ 0 := _) :
theorem fin.pred_succ_above_pred {n : ℕ} {a : fin (n + 2)} {b : fin (n + 1)} (ha : a ≠ 0) (hb : b ≠ 0) (hk : ⇑(a.succ_above) b ≠ 0 := _) :
⇑((a.pred ha).succ_above) (b.pred hb) = (⇑(a.succ_above) b).pred hk

pred commutes with succ_above.

@[simp]
theorem fin.cast_pred_cast_succ {n : ℕ} (i : fin (n + 1)) :
theorem fin.cast_succ_cast_pred {n : ℕ} {i : fin (n + 2)} (h : i < fin.last (n + 1)) :
theorem fin.coe_cast_pred_le_self {n : ℕ} (i : fin (n + 2)) :
theorem fin.coe_cast_pred_lt_iff {n : ℕ} {i : fin (n + 2)} :
theorem fin.lt_last_iff_coe_cast_pred {n : ℕ} {i : fin (n + 2)} :
def fin.clamp (n m : ℕ) :
fin (m + 1)

min n m as an element of fin (m + 1)

Equations
@[simp]
theorem fin.coe_clamp (n m : ℕ) :
↑(fin.clamp n m) = min n m
@[simp]
theorem fin.coe_of_nat_eq_mod (m n : ℕ) :
↑↑n = n % m.succ
@[simp]
theorem fin.coe_of_nat_eq_mod' (m n : ℕ) [I : fact (0 < m)] :

mul #

theorem fin.val_mul {n : ℕ} (a b : fin n) :
(a * b).val = (a.val) * b.val % n
theorem fin.coe_mul {n : ℕ} (a b : fin n) :
↑a * b = (↑a) * ↑b % n
@[protected, simp]
theorem fin.mul_one {n : ℕ} (k : fin (n + 1)) :
k * 1 = k
@[protected, simp]
theorem fin.one_mul {n : ℕ} (k : fin (n + 1)) :
1 * k = k
@[protected, simp]
theorem fin.mul_zero {n : ℕ} (k : fin (n + 1)) :
k * 0 = 0
@[protected, simp]
theorem fin.zero_mul {n : ℕ} (k : fin (n + 1)) :
0 * k = 0