Module docstring
{}
{}
Ordering
inductive
/--
The result of a comparison according to a total order.
The relationship between the compared items may be:
* `Ordering.lt`: less than
* `Ordering.eq`: equal
* `Ordering.gt`: greater than
-/
inductive Ordering where
| /-- Less than. -/
lt
| /-- Equal. -/
eq
| /-- Greater than. -/
gt
deriving Inhabited, DecidableEq
instInhabitedOrdering
instance
: Inhabited✝ (@Ordering)
Inhabited, DecidableEq
instDecidableEqOrdering
instance
: DecidableEq✝ Ordering
DecidableEq
Ordering.swap
definition
: Ordering → Ordering
Ordering.then
definition
(a b : Ordering) : Ordering
/--
If `a` and `b` are `Ordering`, then `a.then b` returns `a` unless it is `.eq`, in which case it
returns `b`. Additionally, it has “short-circuiting” behavior similar to boolean `&&`: if `a` is not
`.eq` then the expression for `b` is not evaluated.
This is a useful primitive for constructing lexicographic comparator functions. The `deriving Ord`
syntax on a structure uses the `Ord` instance to compare each field in order, combining the results
equivalently to `Ordering.then`.
Use `compareLex` to lexicographically combine two comparison functions.
Examples:
```lean example
structure Person where
name : String
age : Nat
-- Sort people first by name (in ascending order), and people with the same name by age (in
-- descending order)
instance : Ord Person where
compare a b := (compare a.name b.name).then (compare b.age a.age)
```
```lean example
#eval Ord.compare (⟨"Gert", 33⟩ : Person) ⟨"Dana", 50⟩
```
```output
Ordering.gt
```
```lean example
#eval Ord.compare (⟨"Gert", 33⟩ : Person) ⟨"Gert", 50⟩
```
```output
Ordering.gt
```
```lean example
#eval Ord.compare (⟨"Gert", 33⟩ : Person) ⟨"Gert", 20⟩
```
```output
Ordering.lt
```
-/
@[macro_inline] def «then» (a b : Ordering) : Ordering :=
match a with
| .eq => b
| a => a
Ordering.isEq
definition
: Ordering → Bool
Ordering.isNe
definition
: Ordering → Bool
Ordering.isLE
definition
: Ordering → Bool
Ordering.isLT
definition
: Ordering → Bool
Ordering.isGT
definition
: Ordering → Bool
Ordering.isGE
definition
: Ordering → Bool
Ordering.isLT_lt
theorem
: lt.isLT
Ordering.isLE_lt
theorem
: lt.isLE
Ordering.isEq_lt
theorem
: lt.isEq = false
Ordering.isNe_lt
theorem
: lt.isNe = true
Ordering.isGE_lt
theorem
: lt.isGE = false
Ordering.isGT_lt
theorem
: lt.isGT = false
Ordering.isLT_eq
theorem
: eq.isLT = false
Ordering.isLE_eq
theorem
: eq.isLE
Ordering.isEq_eq
theorem
: eq.isEq
Ordering.isNe_eq
theorem
: eq.isNe = false
Ordering.isGE_eq
theorem
: eq.isGE
Ordering.isGT_eq
theorem
: eq.isGT = false
Ordering.isLT_gt
theorem
: gt.isLT = false
Ordering.isLE_gt
theorem
: gt.isLE = false
Ordering.isEq_gt
theorem
: gt.isEq = false
Ordering.isNe_gt
theorem
: gt.isNe = true
Ordering.isGE_gt
theorem
: gt.isGE
Ordering.isGT_gt
theorem
: gt.isGT
Ordering.swap_lt
theorem
: lt.swap = .gt
Ordering.swap_eq
theorem
: eq.swap = .eq
Ordering.swap_gt
theorem
: gt.swap = .lt
Ordering.isLE_eq_false
theorem
{o : Ordering} : o.isLE = false ↔ o = .gt
@[simp]
theorem isLE_eq_false {o : Ordering} : o.isLE = false ↔ o = .gt := by
cases o <;> simp
Ordering.isGE_eq_false
theorem
{o : Ordering} : o.isGE = false ↔ o = .lt
@[simp]
theorem isGE_eq_false {o : Ordering} : o.isGE = false ↔ o = .lt := by
cases o <;> simp
Ordering.swap_eq_gt
theorem
{o : Ordering} : o.swap = .gt ↔ o = .lt
@[simp]
theorem swap_eq_gt {o : Ordering} : o.swap = .gt ↔ o = .lt := by
cases o <;> simp
Ordering.swap_eq_lt
theorem
{o : Ordering} : o.swap = .lt ↔ o = .gt
@[simp]
theorem swap_eq_lt {o : Ordering} : o.swap = .lt ↔ o = .gt := by
cases o <;> simp
Ordering.swap_eq_eq
theorem
{o : Ordering} : o.swap = .eq ↔ o = .eq
@[simp]
theorem swap_eq_eq {o : Ordering} : o.swap = .eq ↔ o = .eq := by
cases o <;> simp
Ordering.isLT_swap
theorem
{o : Ordering} : o.swap.isLT = o.isGT
Ordering.isLE_swap
theorem
{o : Ordering} : o.swap.isLE = o.isGE
Ordering.isEq_swap
theorem
{o : Ordering} : o.swap.isEq = o.isEq
Ordering.isNe_swap
theorem
{o : Ordering} : o.swap.isNe = o.isNe
Ordering.isGE_swap
theorem
{o : Ordering} : o.swap.isGE = o.isLE
Ordering.isGT_swap
theorem
{o : Ordering} : o.swap.isGT = o.isLT
Ordering.isLT_iff_eq_lt
theorem
{o : Ordering} : o.isLT ↔ o = .lt
theorem isLT_iff_eq_lt {o : Ordering} : o.isLT ↔ o = .lt := by
cases o <;> simp
Ordering.isLE_iff_eq_lt_or_eq_eq
theorem
{o : Ordering} : o.isLE ↔ o = .lt ∨ o = .eq
theorem isLE_iff_eq_lt_or_eq_eq {o : Ordering} : o.isLE ↔ o = .lt ∨ o = .eq := by
cases o <;> simp
Ordering.isLE_of_eq_lt
theorem
{o : Ordering} : o = .lt → o.isLE
theorem isLE_of_eq_lt {o : Ordering} : o = .lt → o.isLE := by
rintro rfl; rfl
Ordering.isLE_of_eq_eq
theorem
{o : Ordering} : o = .eq → o.isLE
theorem isLE_of_eq_eq {o : Ordering} : o = .eq → o.isLE := by
rintro rfl; rfl
Ordering.isEq_iff_eq_eq
theorem
{o : Ordering} : o.isEq ↔ o = .eq
theorem isEq_iff_eq_eq {o : Ordering} : o.isEq ↔ o = .eq := by
cases o <;> simp
Ordering.isNe_iff_ne_eq
theorem
{o : Ordering} : o.isNe ↔ o ≠ .eq
theorem isNe_iff_ne_eq {o : Ordering} : o.isNe ↔ o ≠ .eq := by
cases o <;> simp
Ordering.isGE_iff_eq_gt_or_eq_eq
theorem
{o : Ordering} : o.isGE ↔ o = .gt ∨ o = .eq
theorem isGE_iff_eq_gt_or_eq_eq {o : Ordering} : o.isGE ↔ o = .gt ∨ o = .eq := by
cases o <;> simp
Ordering.isGE_of_eq_gt
theorem
{o : Ordering} : o = .gt → o.isGE
theorem isGE_of_eq_gt {o : Ordering} : o = .gt → o.isGE := by
rintro rfl; rfl
Ordering.isGE_of_eq_eq
theorem
{o : Ordering} : o = .eq → o.isGE
theorem isGE_of_eq_eq {o : Ordering} : o = .eq → o.isGE := by
rintro rfl; rfl
Ordering.isGT_iff_eq_gt
theorem
{o : Ordering} : o.isGT ↔ o = .gt
theorem isGT_iff_eq_gt {o : Ordering} : o.isGT ↔ o = .gt := by
cases o <;> simp
Ordering.swap_swap
theorem
{o : Ordering} : o.swap.swap = o
Ordering.swap_inj
theorem
{o₁ o₂ : Ordering} : o₁.swap = o₂.swap ↔ o₁ = o₂
@[simp] theorem swap_inj {o₁ o₂ : Ordering} : o₁.swap = o₂.swap ↔ o₁ = o₂ :=
⟨fun h => by simpa using congrArg swap h, congrArg _⟩
Ordering.swap_then
theorem
(o₁ o₂ : Ordering) : (o₁.then o₂).swap = o₁.swap.then o₂.swap
Ordering.then_eq_lt
theorem
{o₁ o₂ : Ordering} : o₁.then o₂ = lt ↔ o₁ = lt ∨ o₁ = eq ∧ o₂ = lt
theorem then_eq_lt {o₁ o₂ : Ordering} : o₁.then o₂ = lt ↔ o₁ = lt ∨ o₁ = eq ∧ o₂ = lt := by
cases o₁ <;> cases o₂ <;> decide
Ordering.then_eq_eq
theorem
{o₁ o₂ : Ordering} : o₁.then o₂ = eq ↔ o₁ = eq ∧ o₂ = eq
theorem then_eq_eq {o₁ o₂ : Ordering} : o₁.then o₂ = eq ↔ o₁ = eq ∧ o₂ = eq := by
cases o₁ <;> simp [«then»]
Ordering.then_eq_gt
theorem
{o₁ o₂ : Ordering} : o₁.then o₂ = gt ↔ o₁ = gt ∨ o₁ = eq ∧ o₂ = gt
theorem then_eq_gt {o₁ o₂ : Ordering} : o₁.then o₂ = gt ↔ o₁ = gt ∨ o₁ = eq ∧ o₂ = gt := by
cases o₁ <;> cases o₂ <;> decide
Ordering.lt_then
theorem
{o : Ordering} : lt.then o = lt
Ordering.gt_then
theorem
{o : Ordering} : gt.then o = gt
Ordering.isLE_then_iff_or
theorem
{o₁ o₂ : Ordering} : (o₁.then o₂).isLE ↔ o₁ = lt ∨ (o₁ = eq ∧ o₂.isLE)
theorem isLE_then_iff_or {o₁ o₂ : Ordering} : (o₁.then o₂).isLE ↔ o₁ = lt ∨ (o₁ = eq ∧ o₂.isLE) := by
cases o₁ <;> simp
Ordering.isLE_then_iff_and
theorem
{o₁ o₂ : Ordering} : (o₁.then o₂).isLE ↔ o₁.isLE ∧ (o₁ = lt ∨ o₂.isLE)
theorem isLE_then_iff_and {o₁ o₂ : Ordering} : (o₁.then o₂).isLE ↔ o₁.isLE ∧ (o₁ = lt ∨ o₂.isLE) := by
cases o₁ <;> simp
Ordering.isLE_left_of_isLE_then
theorem
{o₁ o₂ : Ordering} (h : (o₁.then o₂).isLE) : o₁.isLE
theorem isLE_left_of_isLE_then {o₁ o₂ : Ordering} (h : (o₁.then o₂).isLE) : o₁.isLE := by
cases o₁ <;> simp_all
Ordering.isGE_left_of_isGE_then
theorem
{o₁ o₂ : Ordering} (h : (o₁.then o₂).isGE) : o₁.isGE
theorem isGE_left_of_isGE_then {o₁ o₂ : Ordering} (h : (o₁.then o₂).isGE) : o₁.isGE := by
cases o₁ <;> simp_all
compareOfLessAndEq
definition
{α} (x y : α) [LT α] [Decidable (x < y)] [DecidableEq α] : Ordering
/--
Uses decidable less-than and equality relations to find an `Ordering`.
In particular, if `x < y` then the result is `Ordering.lt`. If `x = y` then the result is
`Ordering.eq`. Otherwise, it is `Ordering.gt`.
`compareOfLessAndBEq` uses `BEq` instead of `DecidableEq`.
-/
@[inline] def compareOfLessAndEq {α} (x y : α) [LT α] [Decidable (x < y)] [DecidableEq α] : Ordering :=
if x < y then Ordering.lt
else if x = y then Ordering.eq
else Ordering.gt
compareOfLessAndBEq
definition
{α} (x y : α) [LT α] [Decidable (x < y)] [BEq α] : Ordering
/--
Uses a decidable less-than relation and Boolean equality to find an `Ordering`.
In particular, if `x < y` then the result is `Ordering.lt`. If `x == y` then the result is
`Ordering.eq`. Otherwise, it is `Ordering.gt`.
`compareOfLessAndEq` uses `DecidableEq` instead of `BEq`.
-/
@[inline] def compareOfLessAndBEq {α} (x y : α) [LT α] [Decidable (x < y)] [BEq α] : Ordering :=
if x < y then .lt
else if x == y then .eq
else .gt
compareLex
definition
(cmp₁ cmp₂ : α → β → Ordering) (a : α) (b : β) : Ordering
/--
Compares `a` and `b` lexicographically by `cmp₁` and `cmp₂`.
`a` and `b` are first compared by `cmp₁`. If this returns `Ordering.eq`, `a` and `b` are compared
by `cmp₂` to break the tie.
To lexicographically combine two `Ordering`s, use `Ordering.then`.
-/
@[inline] def compareLex (cmp₁ cmp₂ : α → β → Ordering) (a : α) (b : β) : Ordering :=
(cmp₁ a b).then (cmp₂ a b)
compareLex_eq_eq
theorem
{α} {cmp₁ cmp₂} {a b : α} : compareLex cmp₁ cmp₂ a b = .eq ↔ cmp₁ a b = .eq ∧ cmp₂ a b = .eq
@[simp]
theorem compareLex_eq_eq {α} {cmp₁ cmp₂} {a b : α} :
compareLexcompareLex cmp₁ cmp₂ a b = .eq ↔ cmp₁ a b = .eq ∧ cmp₂ a b = .eq := by
simp [compareLex, Ordering.then_eq_eq]
compareOfLessAndEq_eq_swap_of_lt_iff_not_gt_and_ne
theorem
{α : Type u} [LT α] [DecidableLT α] [DecidableEq α] (h : ∀ x y : α, x < y ↔ ¬y < x ∧ x ≠ y) {x y : α} :
compareOfLessAndEq x y = (compareOfLessAndEq y x).swap
theorem compareOfLessAndEq_eq_swap_of_lt_iff_not_gt_and_ne {α : Type u} [LT α] [DecidableLT α] [DecidableEq α]
(h : ∀ x y : α, x < y ↔ ¬ y < x ∧ x ≠ y) {x y : α} :
compareOfLessAndEq x y = (compareOfLessAndEq y x).swap := by
simp only [compareOfLessAndEq]
split
· rename_i h'
rw [h] at h'
simp only [h'.1, h'.2.symm, reduceIte, Ordering.swap_gt]
· split
· rename_i h'
have : ¬ y < y := Not.imp (·.2 rfl) <| (h y y).mp
simp only [h', this, reduceIte, Ordering.swap_eq]
· rename_i h' h''
replace h' := (h y x).mpr ⟨h', Ne.symm h''⟩
simp only [h', Ne.symm h'', reduceIte, Ordering.swap_lt]
lt_iff_not_gt_and_ne_of_antisymm_of_total_of_not_le
theorem
{α : Type u} [LT α] [LE α] [DecidableLT α] [DecidableEq α] (antisymm : ∀ {x y : α}, x ≤ y → y ≤ x → x = y)
(total : ∀ (x y : α), x ≤ y ∨ y ≤ x) (not_le : ∀ {x y : α}, ¬x ≤ y ↔ y < x) (x y : α) : x < y ↔ ¬y < x ∧ x ≠ y
theorem lt_iff_not_gt_and_ne_of_antisymm_of_total_of_not_le
{α : Type u} [LT α] [LE α] [DecidableLT α] [DecidableEq α]
(antisymm : ∀ {x y : α}, x ≤ y → y ≤ x → x = y)
(total : ∀ (x y : α), x ≤ y ∨ y ≤ x) (not_le : ∀ {x y : α}, ¬ x ≤ y¬ x ≤ y ↔ y < x) (x y : α) :
x < y ↔ ¬ y < x ∧ x ≠ y := by
simp only [← not_le, Classical.not_not]
constructor
· intro h
have refl := by cases total y y <;> assumption
exact ⟨(total _ _).resolve_left h, fun h' => (h' ▸ h) refl⟩
· intro ⟨h₁, h₂⟩ h₃
exact h₂ (antisymm h₁ h₃)
compareOfLessAndEq_eq_swap
theorem
{α : Type u} [LT α] [LE α] [DecidableLT α] [DecidableEq α] (antisymm : ∀ {x y : α}, x ≤ y → y ≤ x → x = y)
(total : ∀ (x y : α), x ≤ y ∨ y ≤ x) (not_le : ∀ {x y : α}, ¬x ≤ y ↔ y < x) {x y : α} :
compareOfLessAndEq x y = (compareOfLessAndEq y x).swap
theorem compareOfLessAndEq_eq_swap
{α : Type u} [LT α] [LE α] [DecidableLT α] [DecidableEq α]
(antisymm : ∀ {x y : α}, x ≤ y → y ≤ x → x = y)
(total : ∀ (x y : α), x ≤ y ∨ y ≤ x) (not_le : ∀ {x y : α}, ¬ x ≤ y¬ x ≤ y ↔ y < x) {x y : α} :
compareOfLessAndEq x y = (compareOfLessAndEq y x).swap := by
apply compareOfLessAndEq_eq_swap_of_lt_iff_not_gt_and_ne
exact lt_iff_not_gt_and_ne_of_antisymm_of_total_of_not_le antisymm total not_le
compareOfLessAndEq_eq_lt
theorem
{α : Type u} [LT α] [LE α] [DecidableLT α] [DecidableEq α] {x y : α} : compareOfLessAndEq x y = .lt ↔ x < y
@[simp]
theorem compareOfLessAndEq_eq_lt
{α : Type u} [LT α] [LE α] [DecidableLT α] [DecidableEq α] {x y : α} :
compareOfLessAndEqcompareOfLessAndEq x y = .lt ↔ x < y := by
rw [compareOfLessAndEq]
repeat' split <;> simp_all
compareOfLessAndEq_eq_eq
theorem
{α : Type u} [LT α] [LE α] [DecidableLT α] [DecidableLE α] [DecidableEq α] (refl : ∀ (x : α), x ≤ x)
(not_le : ∀ {x y : α}, ¬x ≤ y ↔ y < x) {x y : α} : compareOfLessAndEq x y = .eq ↔ x = y
theorem compareOfLessAndEq_eq_eq
{α : Type u} [LT α] [LE α] [DecidableLT α] [DecidableLE α] [DecidableEq α]
(refl : ∀ (x : α), x ≤ x) (not_le : ∀ {x y : α}, ¬ x ≤ y¬ x ≤ y ↔ y < x) {x y : α} :
compareOfLessAndEqcompareOfLessAndEq x y = .eq ↔ x = y := by
rw [compareOfLessAndEq]
repeat' split <;> try (simp_all; done)
simp only [reduceCtorEq, false_iff]
rintro rfl
rename_i hlt
simp [← not_le] at hlt
exact hlt (refl x)
compareOfLessAndEq_eq_gt_of_lt_iff_not_gt_and_ne
theorem
{α : Type u} [LT α] [LE α] [DecidableLT α] [DecidableEq α] {x y : α} (h : ∀ x y : α, x < y ↔ ¬y < x ∧ x ≠ y) :
compareOfLessAndEq x y = .gt ↔ y < x
theorem compareOfLessAndEq_eq_gt_of_lt_iff_not_gt_and_ne
{α : Type u} [LT α] [LE α] [DecidableLT α] [DecidableEq α] {x y : α}
(h : ∀ x y : α, x < y ↔ ¬ y < x ∧ x ≠ y) :
compareOfLessAndEqcompareOfLessAndEq x y = .gt ↔ y < x := by
rw [compareOfLessAndEq_eq_swap_of_lt_iff_not_gt_and_ne h, Ordering.swap_eq_gt]
exact compareOfLessAndEq_eq_lt
compareOfLessAndEq_eq_gt
theorem
{α : Type u} [LT α] [LE α] [DecidableLT α] [DecidableEq α] (antisymm : ∀ {x y : α}, x ≤ y → y ≤ x → x = y)
(total : ∀ (x y : α), x ≤ y ∨ y ≤ x) (not_le : ∀ {x y : α}, ¬x ≤ y ↔ y < x) (x y : α) :
compareOfLessAndEq x y = .gt ↔ y < x
theorem compareOfLessAndEq_eq_gt
{α : Type u} [LT α] [LE α] [DecidableLT α] [DecidableEq α]
(antisymm : ∀ {x y : α}, x ≤ y → y ≤ x → x = y)
(total : ∀ (x y : α), x ≤ y ∨ y ≤ x) (not_le : ∀ {x y : α}, ¬ x ≤ y¬ x ≤ y ↔ y < x) (x y : α) :
compareOfLessAndEqcompareOfLessAndEq x y = .gt ↔ y < x := by
apply compareOfLessAndEq_eq_gt_of_lt_iff_not_gt_and_ne
exact lt_iff_not_gt_and_ne_of_antisymm_of_total_of_not_le antisymm total not_le
isLE_compareOfLessAndEq
theorem
{α : Type u} [LT α] [LE α] [DecidableLT α] [DecidableLE α] [DecidableEq α]
(antisymm : ∀ {x y : α}, x ≤ y → y ≤ x → x = y) (not_le : ∀ {x y : α}, ¬x ≤ y ↔ y < x)
(total : ∀ (x y : α), x ≤ y ∨ y ≤ x) {x y : α} : (compareOfLessAndEq x y).isLE ↔ x ≤ y
theorem isLE_compareOfLessAndEq
{α : Type u} [LT α] [LE α] [DecidableLT α] [DecidableLE α] [DecidableEq α]
(antisymm : ∀ {x y : α}, x ≤ y → y ≤ x → x = y)
(not_le : ∀ {x y : α}, ¬ x ≤ y¬ x ≤ y ↔ y < x) (total : ∀ (x y : α), x ≤ y ∨ y ≤ x) {x y : α} :
(compareOfLessAndEq x y).isLE ↔ x ≤ y := by
have refl (a : α) := by cases total a a <;> assumption
rw [Ordering.isLE_iff_eq_lt_or_eq_eq, compareOfLessAndEq_eq_lt,
compareOfLessAndEq_eq_eq refl not_le]
constructor
· rintro (h | rfl)
· rw [← not_le] at h
exact total _ _ |>.resolve_left h
· exact refl x
· intro hle
by_cases hge : x ≥ y
· exact Or.inr <| antisymm hle hge
· exact Or.inl <| not_le.mp hge
Ord
structure
(α : Type u)
/--
`Ord α` provides a computable total order on `α`, in terms of the
`compare : α → α → Ordering` function.
Typically instances will be transitive, reflexive, and antisymmetric,
but this is not enforced by the typeclass.
There is a derive handler, so appending `deriving Ord` to an inductive type or structure
will attempt to create an `Ord` instance.
-/
class Ord (α : Type u) where
/-- Compare two elements in `α` using the comparator contained in an `[Ord α]` instance. -/
compare : α → α → Ordering
compareOn
definition
[ord : Ord β] (f : α → β) (x y : α) : Ordering
/--
Compares two values by comparing the results of applying a function.
In particular, `x` is compared to `y` by comparing `f x` and `f y`.
Examples:
* `compareOn (·.length) "apple" "banana" = .lt`
* `compareOn (· % 3) 5 6 = .gt`
* `compareOn (·.foldl max 0) [1, 2, 3] [3, 2, 1] = .eq`
-/
@[inline] def compareOn [ord : Ord β] (f : α → β) (x y : α) : Ordering :=
compare (f x) (f y)
instOrdNat
instance
: Ord Nat
instance : Ord Nat where
compare x y := compareOfLessAndEq x y
instOrdInt
instance
: Ord Int
instance : Ord Int where
compare x y := compareOfLessAndEq x y
instOrdBool
instance
: Ord Bool
instOrdString
instance
: Ord String
instance : Ord String where
compare x y := compareOfLessAndEq x y
instOrdFin
instance
(n : Nat) : Ord (Fin n)
instOrdUInt8
instance
: Ord UInt8
instance : Ord UInt8 where
compare x y := compareOfLessAndEq x y
instOrdUInt16
instance
: Ord UInt16
instance : Ord UInt16 where
compare x y := compareOfLessAndEq x y
instOrdUInt32
instance
: Ord UInt32
instance : Ord UInt32 where
compare x y := compareOfLessAndEq x y
instOrdUInt64
instance
: Ord UInt64
instance : Ord UInt64 where
compare x y := compareOfLessAndEq x y
instOrdUSize
instance
: Ord USize
instance : Ord USize where
compare x y := compareOfLessAndEq x y
instOrdChar
instance
: Ord Char
instance : Ord Char where
compare x y := compareOfLessAndEq x y
instOrdInt8
instance
: Ord Int8
instance : Ord Int8 where
compare x y := compareOfLessAndEq x y
instOrdInt16
instance
: Ord Int16
instance : Ord Int16 where
compare x y := compareOfLessAndEq x y
instOrdInt32
instance
: Ord Int32
instance : Ord Int32 where
compare x y := compareOfLessAndEq x y
instOrdInt64
instance
: Ord Int64
instance : Ord Int64 where
compare x y := compareOfLessAndEq x y
instOrdISize
instance
: Ord ISize
instance : Ord ISize where
compare x y := compareOfLessAndEq x y
instOrdBitVec
instance
{n} : Ord (BitVec n)
instance {n} : Ord (BitVec n) where
compare x y := compareOfLessAndEq x y
instOrdOption
instance
[Ord α] : Ord (Option α)
instOrdOrdering
instance
: Ord Ordering
List.compareLex
definition
{α} (cmp : α → α → Ordering) : List α → List α → Ordering
List.instOrd
instance
{α} [Ord α] : Ord (List α)
List.compare_eq_compareLex
theorem
{α} [Ord α] : compare (α := List α) = List.compareLex compare
protected theorem compare_eq_compareLex {α} [Ord α] :
compare (α := List α) = List.compareLex compare := rfl
List.compareLex_cons_cons
theorem
{α} {cmp} {x y : α} {xs ys : List α} : (x :: xs).compareLex cmp (y :: ys) = (cmp x y).then (xs.compareLex cmp ys)
protected theorem compareLex_cons_cons {α} {cmp} {x y : α} {xs ys : List α} :
(x :: xs).compareLex cmp (y :: ys) = (cmp x y).then (xs.compareLex cmp ys) := by
rw [List.compareLex]
split <;> simp_all
List.compare_cons_cons
theorem
{α} [Ord α] {x y : α} {xs ys : List α} : compare (x :: xs) (y :: ys) = (compare x y).then (compare xs ys)
@[simp]
protected theorem compare_cons_cons {α} [Ord α] {x y : α} {xs ys : List α} :
compare (x :: xs) (y :: ys) = (compare x y).then (compare xs ys) :=
List.compareLex_cons_cons
List.compareLex_nil_cons
theorem
{α} {cmp} {x : α} {xs : List α} : [].compareLex cmp (x :: xs) = .lt
protected theorem compareLex_nil_cons {α} {cmp} {x : α} {xs : List α} :
[].compareLex cmp (x :: xs) = .lt :=
rfl
List.compare_nil_cons
theorem
{α} [Ord α] {x : α} {xs : List α} : compare [] (x :: xs) = .lt
List.compareLex_cons_nil
theorem
{α} {cmp} {x : α} {xs : List α} : (x :: xs).compareLex cmp [] = .gt
protected theorem compareLex_cons_nil {α} {cmp} {x : α} {xs : List α} :
(x :: xs).compareLex cmp [] = .gt :=
rfl
List.compare_cons_nil
theorem
{α} [Ord α] {x : α} {xs : List α} : compare (x :: xs) [] = .gt
List.compareLex_nil_nil
theorem
{α} {cmp} : [].compareLex (α := α) cmp [] = .eq
protected theorem compareLex_nil_nil {α} {cmp} :
[].compareLex (α := α) cmp [] = .eq :=
rfl
List.compare_nil_nil
theorem
{α} [Ord α] : compare (α := List α) [] [] = .eq
List.isLE_compareLex_nil_left
theorem
{α} {cmp} {xs : List α} : (List.compareLex (cmp := cmp) [] xs).isLE
protected theorem isLE_compareLex_nil_left {α} {cmp} {xs : List α} :
(List.compareLex (cmp := cmp) [] xs).isLE := by
cases xs <;> simp [List.compareLex_nil_nil, List.compareLex_nil_cons]
List.isLE_compare_nil_left
theorem
{α} [Ord α] {xs : List α} : (compare [] xs).isLE
protected theorem isLE_compare_nil_left {α} [Ord α] {xs : List α} :
(compare [] xs).isLE :=
List.isLE_compareLex_nil_left
List.isLE_compareLex_nil_right
theorem
{α} {cmp} {xs : List α} : (List.compareLex (cmp := cmp) xs []).isLE ↔ xs = []
protected theorem isLE_compareLex_nil_right {α} {cmp} {xs : List α} :
(List.compareLex (cmp := cmp) xs []).isLE ↔ xs = [] := by
cases xs <;> simp [List.compareLex_nil_nil, List.compareLex_cons_nil]
List.isLE_compare_nil_right
theorem
{α} [Ord α] {xs : List α} : (compare xs []).isLE ↔ xs = []
@[simp]
protected theorem isLE_compare_nil_right {α} [Ord α] {xs : List α} :
(compare xs []).isLE ↔ xs = [] :=
List.isLE_compareLex_nil_right
List.isGE_compareLex_nil_left
theorem
{α} {cmp} {xs : List α} : (List.compareLex (cmp := cmp) [] xs).isGE ↔ xs = []
protected theorem isGE_compareLex_nil_left {α} {cmp} {xs : List α} :
(List.compareLex (cmp := cmp) [] xs).isGE ↔ xs = [] := by
cases xs <;> simp [List.compareLex_nil_nil, List.compareLex_nil_cons]
List.isGE_compare_nil_left
theorem
{α} [Ord α] {xs : List α} : (compare [] xs).isGE ↔ xs = []
@[simp]
protected theorem isGE_compare_nil_left {α} [Ord α] {xs : List α} :
(compare [] xs).isGE ↔ xs = [] :=
List.isGE_compareLex_nil_left
List.isGE_compareLex_nil_right
theorem
{α} {cmp} {xs : List α} : (List.compareLex (cmp := cmp) xs []).isGE
protected theorem isGE_compareLex_nil_right {α} {cmp} {xs : List α} :
(List.compareLex (cmp := cmp) xs []).isGE := by
cases xs <;> simp [List.compareLex_nil_nil, List.compareLex_cons_nil]
List.isGE_compare_nil_right
theorem
{α} [Ord α] {xs : List α} : (compare xs []).isGE
protected theorem isGE_compare_nil_right {α} [Ord α] {xs : List α} :
(compare xs []).isGE :=
List.isGE_compareLex_nil_right
List.compareLex_nil_left_eq_eq
theorem
{α} {cmp} {xs : List α} : List.compareLex cmp [] xs = .eq ↔ xs = []
protected theorem compareLex_nil_left_eq_eq {α} {cmp} {xs : List α} :
List.compareLexList.compareLex cmp [] xs = .eq ↔ xs = [] := by
cases xs <;> simp [List.compareLex_nil_nil, List.compareLex_nil_cons]
List.compare_nil_left_eq_eq
theorem
{α} [Ord α] {xs : List α} : compare [] xs = .eq ↔ xs = []
@[simp]
protected theorem compare_nil_left_eq_eq {α} [Ord α] {xs : List α} :
comparecompare [] xs = .eq ↔ xs = [] :=
List.compareLex_nil_left_eq_eq
List.compareLex_nil_right_eq_eq
theorem
{α} {cmp} {xs : List α} : xs.compareLex cmp [] = .eq ↔ xs = []
protected theorem compareLex_nil_right_eq_eq {α} {cmp} {xs : List α} :
xs.compareLex cmp [] = .eq ↔ xs = [] := by
cases xs <;> simp [List.compareLex_nil_nil, List.compareLex_cons_nil]
List.compare_nil_right_eq_eq
theorem
{α} [Ord α] {xs : List α} : compare xs [] = .eq ↔ xs = []
@[simp]
protected theorem compare_nil_right_eq_eq {α} [Ord α] {xs : List α} :
comparecompare xs [] = .eq ↔ xs = [] :=
List.compareLex_nil_right_eq_eq
Array.compareLex
definition
{α} (cmp : α → α → Ordering) (a₁ a₂ : Array α) : Ordering
@[specialize]
protected def compareLex {α} (cmp : α → α → Ordering) (a₁ a₂ : Array α) : Ordering :=
go 0
where go i :=
if h₁ : a₁.size <= i then
if a₂.size <= i then .eq else .lt
else
if h₂ : a₂.size <= i then
.gt
else match cmp a₁[i] a₂[i] with
| .lt => .lt
| .eq => go (i + 1)
| .gt => .gt
termination_by a₁.size - i
Array.instOrd
instance
{α} [Ord α] : Ord (Array α)
Array.compare_eq_compareLex
theorem
{α} [Ord α] : compare (α := Array α) = Array.compareLex compare
protected theorem compare_eq_compareLex {α} [Ord α] :
compare (α := Array α) = Array.compareLex compare := rfl
List.compareLex_eq_compareLex_toArray
theorem
{α} {cmp} {l₁ l₂ : List α} : List.compareLex cmp l₁ l₂ = Array.compareLex cmp l₁.toArray l₂.toArray
protected theorem _root_.List.compareLex_eq_compareLex_toArray {α} {cmp} {l₁ l₂ : List α} :
List.compareLex cmp l₁ l₂ = Array.compareLex cmp l₁.toArray l₂.toArray := by
simp only [Array.compareLex]
induction l₁ generalizing l₂ with
| nil =>
cases l₂
· simp [Array.compareLex.go, List.compareLex_nil_nil]
· simp [Array.compareLex.go, List.compareLex_nil_cons]
| cons x xs ih =>
cases l₂
· simp [Array.compareLex.go, List.compareLex_cons_nil]
· rw [Array.compareLex.go, List.compareLex_cons_cons]
simp only [List.size_toArray, List.length_cons, Nat.le_zero_eq, Nat.add_one_ne_zero,
↓reduceDIte, List.getElem_toArray, List.getElem_cons_zero, Nat.zero_add]
split <;> simp_all [compareLex.go_succ]
List.compare_eq_compare_toArray
theorem
{α} [Ord α] {l₁ l₂ : List α} : compare l₁ l₂ = compare l₁.toArray l₂.toArray
protected theorem _root_.List.compare_eq_compare_toArray {α} [Ord α] {l₁ l₂ : List α} :
compare l₁ l₂ = compare l₁.toArray l₂.toArray :=
List.compareLex_eq_compareLex_toArray
Array.compareLex_eq_compareLex_toList
theorem
{α} {cmp} {a₁ a₂ : Array α} : Array.compareLex cmp a₁ a₂ = List.compareLex cmp a₁.toList a₂.toList
protected theorem compareLex_eq_compareLex_toList {α} {cmp} {a₁ a₂ : Array α} :
Array.compareLex cmp a₁ a₂ = List.compareLex cmp a₁.toList a₂.toList := by
rw [List.compareLex_eq_compareLex_toArray]
Array.compare_eq_compare_toList
theorem
{α} [Ord α] {a₁ a₂ : Array α} : compare a₁ a₂ = compare a₁.toList a₂.toList
protected theorem compare_eq_compare_toList {α} [Ord α] {a₁ a₂ : Array α} :
compare a₁ a₂ = compare a₁.toList a₂.toList :=
Array.compareLex_eq_compareLex_toList
Vector.compareLex
definition
{α n} (cmp : α → α → Ordering) (a b : Vector α n) : Ordering
protected def compareLex {α n} (cmp : α → α → Ordering) (a b : Vector α n) : Ordering :=
Array.compareLex cmp a.toArray b.toArray
Vector.instOrd
instance
{α n} [Ord α] : Ord (Vector α n)
Vector.compareLex_eq_compareLex_toArray
theorem
{α n cmp} {a b : Vector α n} : Vector.compareLex cmp a b = Array.compareLex cmp a.toArray b.toArray
protected theorem compareLex_eq_compareLex_toArray {α n cmp} {a b : Vector α n} :
Vector.compareLex cmp a b = Array.compareLex cmp a.toArray b.toArray :=
rfl
Vector.compareLex_eq_compareLex_toList
theorem
{α n cmp} {a b : Vector α n} : Vector.compareLex cmp a b = List.compareLex cmp a.toList b.toList
protected theorem compareLex_eq_compareLex_toList {α n cmp} {a b : Vector α n} :
Vector.compareLex cmp a b = List.compareLex cmp a.toList b.toList :=
Array.compareLex_eq_compareLex_toList
Vector.compare_eq_compare_toArray
theorem
{α n} [Ord α] {a b : Vector α n} : compare a b = compare a.toArray b.toArray
Vector.compare_eq_compare_toList
theorem
{α n} [Ord α] {a b : Vector α n} : compare a b = compare a.toList b.toList
protected theorem compare_eq_compare_toList {α n} [Ord α] {a b : Vector α n} :
compare a b = compare a.toList b.toList :=
Array.compare_eq_compare_toList
lexOrd
definition
[Ord α] [Ord β] : Ord (α × β)
ltOfOrd
definition
[Ord α] : LT α
/--
Constructs an `LT` instance from an `Ord` instance that asserts that the result of `compare` is
`Ordering.lt`.
-/
def ltOfOrd [Ord α] : LT α where
lt a b := compare a b = Ordering.lt
instDecidableRelLt
instance
[Ord α] : DecidableRel (@LT.lt α ltOfOrd)
instance [Ord α] : DecidableRel (@LT.lt α ltOfOrd) :=
inferInstanceAs (DecidableRel (fun a b => compare a b = Ordering.lt))
leOfOrd
definition
[Ord α] : LE α
instDecidableRelLe
instance
[Ord α] : DecidableRel (@LE.le α leOfOrd)
instance [Ord α] : DecidableRel (@LE.le α leOfOrd) :=
inferInstanceAs (DecidableRel (fun a b => (compare a b).isLE))
Ord.toBEq
definition
(ord : Ord α) : BEq α
Ord.toLT
definition
(ord : Ord α) : LT α
Ord.instDecidableRelLt
instance
[i : Ord α] : DecidableRel (@LT.lt _ (Ord.toLT i))
instance [i : Ord α] : DecidableRel (@LT.lt _ (Ord.toLT i)) :=
inferInstanceAs (DecidableRel (fun a b => compare a b = Ordering.lt))
Ord.toLE
definition
(ord : Ord α) : LE α
Ord.instDecidableRelLe
instance
[i : Ord α] : DecidableRel (@LE.le _ (Ord.toLE i))
instance [i : Ord α] : DecidableRel (@LE.le _ (Ord.toLE i)) :=
inferInstanceAs (DecidableRel (fun a b => (compare a b).isLE))
Ord.opposite
definition
(ord : Ord α) : Ord α
/--
Inverts the order of an `Ord` instance.
The result is an `Ord α` instance that returns `Ordering.lt` when `ord` would return `Ordering.gt`
and that returns `Ordering.gt` when `ord` would return `Ordering.lt`.
-/
protected def opposite (ord : Ord α) : Ord α where
compare x y := ord.compare y x
Ord.on
definition
(_ : Ord β) (f : α → β) : Ord α
/--
Constructs an `Ord` instance that compares values according to the results of `f`.
In particular, `ord.on f` compares `x` and `y` by comparing `f x` and `f y` according to `ord`.
The function `compareOn` can be used to perform this comparison without constructing an intermediate
`Ord` instance.
-/
protected def on (_ : Ord β) (f : α → β) : Ord α where
compare := compareOn f
Ord.lex
definition
(_ : Ord α) (_ : Ord β) : Ord (α × β)
Ord.lex'
definition
(ord₁ ord₂ : Ord α) : Ord α
/--
Constructs an `Ord` instance from two existing instances by combining them lexicographically.
The resulting instance compares elements first by `ord₁` and then, if this returns `Ordering.eq`, by
`ord₂`.
The function `compareLex` can be used to perform this comparison without constructing an
intermediate `Ord` instance. `Ordering.then` can be used to lexicographically combine the results of
comparisons.
-/
protected def lex' (ord₁ ord₂ : Ord α) : Ord α where
compare := compareLex ord₁.compare ord₂.compare
Ord.arrayOrd
definition
[a : Ord α] : Ord (Array α)