chore: upstream Nat material from mathlib (#7971)

This PR upstreams much of the material from `Mathlib/Data/Nat/Init.lean`
and `Mathlib/Data/Nat/Basic.lean`.
This commit is contained in:
Markus Himmel 2025-04-16 08:55:32 +02:00 committed by GitHub
parent 020b8834c3
commit 5a34ffb9b0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
36 changed files with 855 additions and 118 deletions

View file

@ -59,7 +59,7 @@ theorem exists_or_eq_self_of_eraseP (p) (xs : Array α) :
@[simp] theorem size_eraseP_of_mem {xs : Array α} (al : a ∈ xs) (pa : p a) :
(xs.eraseP p).size = xs.size - 1 := by
let ⟨_, ys, zs, _, _, e₁, e₂⟩ := exists_of_eraseP al pa
rw [e₂]; simp [size_append, e₁]; omega
rw [e₂]; simp [size_append, e₁]
theorem size_eraseP {xs : Array α} : (xs.eraseP p).size = if xs.any p then xs.size - 1 else xs.size := by
split <;> rename_i h

View file

@ -3035,7 +3035,7 @@ theorem foldrM_start_stop {m} [Monad m] {xs : Array α} {f : α → β → m β}
simp
| succ i ih =>
unfold foldrM.fold
simp only [beq_iff_eq, Nat.add_right_eq_self, Nat.add_one_ne_zero, ↓reduceIte, Nat.add_eq,
simp only [beq_iff_eq, Nat.add_eq_left, Nat.add_one_ne_zero, ↓reduceIte, Nat.add_eq,
getElem_extract]
congr
funext b

View file

@ -1456,7 +1456,6 @@ theorem udiv_intMin_of_msb_false {x : BitVec w} (h : x.msb = false) :
have wpos : 0 < w := by omega
have := Nat.two_pow_pos (w-1)
simp [toNat_eq, wpos]
rw [Nat.div_eq_zero_iff_lt (by omega)]
exact toNat_lt_of_msb_false h
theorem sdiv_intMin {x : BitVec w} :

View file

@ -2032,7 +2032,6 @@ theorem toInt_ushiftRight_of_lt {x : BitVec w} {n : Nat} (hn : 0 < n) :
have : 2^w ≤ 2^n := Nat.pow_le_pow_of_le (by decide) (by omega)
omega
simp [this] at h
omega
/--
Unsigned shift right by at least one bit makes the interpretations of the bitvector as an `Int` or `Nat` agree,
@ -4914,7 +4913,6 @@ theorem intMin_eq_zero_iff {w : Nat} : intMin w = 0#w ↔ w = 0 := by
· constructor
· have := Nat.two_pow_pos (w - 1)
simp [toNat_eq, show 0 < w by omega]
omega
· simp [h]
/--

View file

@ -156,7 +156,7 @@ theorem add_mul_ediv_right (a b : Int) {c : Int} (H : c ≠ 0) : (a + b * c) / c
show ediv (↑(n * succ k) + -((m : Int) + 1)) (succ k) = n + -(↑(m / succ k) + 1 : Int)
rw [H h, H ((Nat.le_div_iff_mul_le k.succ_pos).2 h)]
apply congrArg negSucc
rw [Nat.mul_comm, Nat.sub_mul_div]; rwa [Nat.mul_comm]
rw [Nat.mul_comm, Nat.sub_mul_div_of_le]; rwa [Nat.mul_comm]
theorem add_mul_ediv_left (a : Int) {b : Int}
(c : Int) (H : b ≠ 0) : (a + b * c) / b = a / b + c :=

View file

@ -481,7 +481,7 @@ theorem ediv_eq_neg_one_of_neg_of_le {a b : Int} (H1 : a < 0) (H2 : -a ≤ b) :
| negSucc a', ofNat (b' + 1), H1, H2 =>
rw [Int.div_def, ediv, Int.negSucc_eq, Int.neg_inj]
norm_cast
rw [Nat.add_left_eq_self, Nat.div_eq_zero_iff_lt (by omega)]
rw [Nat.add_eq_right, Nat.div_eq_zero_iff_lt (by omega)]
simp [Int.negSucc_eq] at H2
omega
@ -491,7 +491,7 @@ theorem ediv_eq_one_of_neg_of_le {a b : Int} (H1 : a < 0) (H2 : b ≤ a) : a / b
| negSucc a', negSucc b', H1, H2 =>
rw [Int.div_def, ediv, ofNat_eq_coe]
norm_cast
rw [Nat.succ_eq_add_one, Nat.add_left_eq_self, Nat.div_eq_zero_iff_lt (by omega)]
rw [Nat.succ_eq_add_one, Nat.add_eq_right, Nat.div_eq_zero_iff_lt (by omega)]
simp [Int.negSucc_eq] at H2
omega

View file

@ -88,7 +88,7 @@ theorem exists_or_eq_self_of_eraseP (p) (l : List α) :
@[simp] theorem length_eraseP_of_mem (al : a ∈ l) (pa : p a) :
length (l.eraseP p) = length l - 1 := by
let ⟨_, l₁, l₂, _, _, e₁, e₂⟩ := exists_of_eraseP al pa
rw [e₂]; simp [length_append, e₁]; rfl
rw [e₂]; simp [length_append, e₁]
theorem length_eraseP {l : List α} : (l.eraseP p).length = if l.any p then l.length - 1 else l.length := by
split <;> rename_i h
@ -542,7 +542,7 @@ theorem eraseIdx_eq_take_drop_succ :
match l, i with
| [], _
| a::l, 0
| a::l, i + 1 => simp [Nat.succ_inj']
| a::l, i + 1 => simp [Nat.succ_inj]
@[deprecated eraseIdx_eq_nil_iff (since := "2025-01-30")]
abbrev eraseIdx_eq_nil := @eraseIdx_eq_nil_iff
@ -551,7 +551,7 @@ theorem eraseIdx_ne_nil_iff {l : List α} {i : Nat} : eraseIdx l i ≠ [] ↔ 2
match l with
| []
| [a]
| a::b::l => simp [Nat.succ_inj']
| a::b::l => simp [Nat.succ_inj]
@[deprecated eraseIdx_ne_nil_iff (since := "2025-01-30")]
abbrev eraseIdx_ne_nil := @eraseIdx_ne_nil_iff

View file

@ -792,7 +792,7 @@ theorem of_findIdx?_eq_some {xs : List α} {p : α → Bool} (w : xs.findIdx? p
| nil => simp_all
| cons x xs ih =>
simp_all only [findIdx?_cons, Nat.zero_add]
split at w <;> cases i <;> simp_all [succ_inj']
split at w <;> cases i <;> simp_all [succ_inj]
@[deprecated of_findIdx?_eq_some (since := "2025-02-02")]
abbrev findIdx?_of_eq_some := @of_findIdx?_eq_some

View file

@ -701,7 +701,7 @@ theorem set_comm (a b : α) : ∀ {i j : Nat} {l : List α}, i ≠ j →
| _+1, 0, _ :: _, _ => by simp [set]
| 0, _+1, _ :: _, _ => by simp [set]
| _+1, _+1, _ :: t, h =>
congrArg _ <| set_comm a b fun h' => h <| Nat.succ_inj'.mpr h'
congrArg _ <| set_comm a b fun h' => h <| Nat.succ_inj.mpr h'
@[simp]
theorem set_set (a : α) {b : α} : ∀ {l : List α} {i : Nat}, (l.set i a).set i b = l.set i b

View file

@ -118,7 +118,7 @@ theorem mem_eraseIdx_iff_getElem {x : α} :
| a::l, 0 => by simp [mem_iff_getElem, Nat.succ_lt_succ_iff]
| a::l, k+1 => by
rw [← Nat.or_exists_add_one]
simp [mem_eraseIdx_iff_getElem, @eq_comm _ a, succ_inj', Nat.succ_lt_succ_iff]
simp [mem_eraseIdx_iff_getElem, @eq_comm _ a, succ_inj, Nat.succ_lt_succ_iff]
theorem mem_eraseIdx_iff_getElem? {x : α} {l} {k} : x ∈ eraseIdx l k ↔ ∃ i ≠ k, l[i]? = some x := by
simp only [mem_eraseIdx_iff_getElem, getElem_eq_iff, exists_and_left]

View file

@ -40,7 +40,6 @@ theorem getLast?_range' {n : Nat} : (range' s n).getLast? = if n = 0 then none e
simp [h]
· rw [if_neg h]
simp
omega
@[simp] theorem getLast_range' {n : Nat} (h) : (range' s n).getLast h = s + n - 1 := by
cases n with
@ -358,7 +357,7 @@ theorem zipIdx_singleton {x : α} {k : Nat} : zipIdx [x] k = [(x, k)] :=
@[simp] theorem getLast?_zipIdx {l : List α} {k : Nat} :
(zipIdx l k).getLast? = l.getLast?.map fun a => (a, k + l.length - 1) := by
simp [getLast?_eq_getElem?]
cases l <;> simp; omega
cases l <;> simp
theorem mk_add_mem_zipIdx_iff_getElem? {k i : Nat} {x : α} {l : List α} :
(x, k + i) ∈ zipIdx l k ↔ l[i]? = some x := by
@ -497,7 +496,7 @@ theorem head?_enumFrom (n : Nat) (l : List α) :
theorem getLast?_enumFrom (n : Nat) (l : List α) :
(enumFrom n l).getLast? = l.getLast?.map fun a => (n + l.length - 1, a) := by
simp [getLast?_eq_getElem?]
cases l <;> simp; omega
cases l <;> simp
@[deprecated mk_add_mem_zipIdx_iff_getElem? (since := "2025-01-21")]
theorem mk_add_mem_enumFrom_iff_getElem? {n i : Nat} {x : α} {l : List α} :

View file

@ -532,7 +532,7 @@ theorem dropWhile_eq_drop_findIdx_not {xs : List α} {p : α → Bool} :
| zero => simp
| succ n =>
suffices 1 < m → m - (m - (n + 1) % m) + min (m - (n + 1) % m) m = m by
simpa [rotateRight]
simp [rotateRight]
intro h
have : (n + 1) % m < m := Nat.mod_lt _ (by omega)
rw [Nat.min_eq_left (by omega)]

View file

@ -407,7 +407,7 @@ theorem perm_iff_count {l₁ l₂ : List α} : l₁ ~ l₂ ↔ ∀ a, count a l
refine ((IH fun b => ?_).cons a).trans (perm_cons_erase this).symm
specialize H b
rw [(perm_cons_erase this).count_eq] at H
by_cases h : b = a <;> simpa [h, count_cons, Nat.succ_inj'] using H
by_cases h : b = a <;> simpa [h, count_cons, Nat.succ_inj] using H
theorem isPerm_iff : ∀ {l₁ l₂ : List α}, l₁.isPerm l₂ ↔ l₁ ~ l₂
| [], [] => by simp [isPerm, isEmpty]

View file

@ -69,7 +69,7 @@ theorem mem_range' : ∀ {n}, m ∈ range' s n step ↔ ∃ i < n, m = s + step
| 0 => by simp [range', Nat.not_lt_zero]
| n + 1 => by
have h (i) : i ≤ n ↔ i = 0 ∃ j, i = succ j ∧ j < n := by
cases i <;> simp [Nat.succ_le, Nat.succ_inj']
cases i <;> simp [Nat.succ_le, Nat.succ_inj]
simp [range', mem_range', Nat.lt_succ, h]; simp only [← exists_and_right, and_assoc]
rw [exists_comm]; simp [Nat.mul_succ, Nat.add_assoc, Nat.add_comm]

View file

@ -220,7 +220,7 @@ theorem zipWith_eq_append_iff {f : α → β → γ} {l₁ : List α} {l₂ : Li
· simp_all
· obtain (⟨rfl, rfl⟩ | ⟨_, rfl, rfl⟩) := h₃
· simp_all
· simp_all [zipWith_append, Nat.succ_inj']
· simp_all [zipWith_append, Nat.succ_inj]
/-- See also `List.zipWith_replicate` in `Init.Data.List.TakeDrop` for a generalization with different lengths. -/
@[simp] theorem zipWith_replicate' {a : α} {b : β} {n : Nat} :

View file

@ -546,6 +546,10 @@ protected theorem le_of_add_le_add_right {a b c : Nat} : a + b ≤ c + b → a
/-! ### le/lt -/
attribute [simp] not_lt_zero
example : (default : Nat) = 0 := rfl
protected theorem lt_asymm {a b : Nat} (h : a < b) : ¬ b < a := Nat.not_lt.2 (Nat.le_of_lt h)
/-- Alias for `Nat.lt_asymm`. -/
protected abbrev not_lt_of_gt := @Nat.lt_asymm
@ -618,7 +622,7 @@ protected theorem eq_zero_of_not_pos (h : ¬0 < n) : n = 0 :=
attribute [simp] zero_lt_succ
theorem succ_ne_self (n) : succ n ≠ n := Nat.ne_of_gt (lt_succ_self n)
@[simp] theorem succ_ne_self (n) : succ n ≠ n := Nat.ne_of_gt (lt_succ_self n)
theorem add_one_ne_self (n) : n + 1 ≠ n := Nat.ne_of_gt (lt_succ_self n)
@ -641,13 +645,20 @@ theorem eq_zero_or_eq_succ_pred : ∀ n, n = 0 n = succ (pred n)
| 0 => .inl rfl
| _+1 => .inr rfl
theorem succ_inj' : succ a = succ b ↔ a = b := (Nat.succ.injEq a b).to_iff
theorem succ_inj : succ a = succ b ↔ a = b := (Nat.succ.injEq a b).to_iff
@[deprecated succ_inj (since := "2025-04-14")]
theorem succ_inj' : succ a = succ b ↔ a = b := succ_inj
theorem succ_le_succ_iff : succ a ≤ succ b ↔ a ≤ b := ⟨le_of_succ_le_succ, succ_le_succ⟩
theorem succ_lt_succ_iff : succ a < succ b ↔ a < b := ⟨lt_of_succ_lt_succ, succ_lt_succ⟩
theorem add_one_inj : a + 1 = b + 1 ↔ a = b := succ_inj'
theorem succ_ne_succ_iff : succ a ≠ succ b ↔ a ≠ b := by simp [Nat.succ.injEq]
theorem succ_succ_ne_one (a : Nat) : succ (succ a) ≠ 1 := nofun
theorem add_one_inj : a + 1 = b + 1 ↔ a = b := succ_inj
theorem ne_add_one (n : Nat) : n ≠ n + 1 := fun h => by cases h
@ -657,6 +668,10 @@ theorem add_one_le_add_one_iff : a + 1 ≤ b + 1 ↔ a ≤ b := succ_le_succ_iff
theorem add_one_lt_add_one_iff : a + 1 < b + 1 ↔ a < b := succ_lt_succ_iff
theorem add_one_ne_add_one_iff : a + 1 ≠ b + 1 ↔ a ≠ b := succ_ne_succ_iff
theorem add_one_add_one_ne_one : a + 1 + 1 ≠ 1 := nofun
theorem pred_inj : ∀ {a b}, 0 < a → 0 < b → pred a = pred b → a = b
| _+1, _+1, _, _ => congrArg _
@ -714,16 +729,18 @@ theorem exists_eq_add_one_of_ne_zero : ∀ {n}, n ≠ 0 → Exists fun k => n =
theorem ctor_eq_zero : Nat.zero = 0 :=
rfl
protected theorem one_ne_zero : 1 ≠ (0 : Nat) :=
@[simp] protected theorem one_ne_zero : 1 ≠ (0 : Nat) :=
fun h => Nat.noConfusion h
protected theorem zero_ne_one : 0 ≠ (1 : Nat) :=
@[simp] protected theorem zero_ne_one : 0 ≠ (1 : Nat) :=
fun h => Nat.noConfusion h
theorem succ_ne_zero (n : Nat) : succ n ≠ 0 := by simp
@[simp] theorem succ_ne_zero (n : Nat) : succ n ≠ 0 := by simp
instance instNeZeroSucc {n : Nat} : NeZero (n + 1) := ⟨succ_ne_zero n⟩
@[simp] theorem default_eq_zero : default = 0 := rfl
/-! # mul + order -/
theorem mul_le_mul_left {n m : Nat} (k : Nat) (h : n ≤ m) : k * n ≤ k * m :=
@ -1003,7 +1020,7 @@ protected theorem add_sub_add_left (k n m : Nat) : (k + n) - (k + m) = n - m :=
suffices n + m - (0 + m) = n by rw [Nat.zero_add] at this; assumption
by rw [Nat.add_sub_add_right, Nat.sub_zero]
protected theorem add_sub_cancel_left (n m : Nat) : n + m - n = m :=
@[simp] protected theorem add_sub_cancel_left (n m : Nat) : n + m - n = m :=
show n + m - (n + 0) = m from
by rw [Nat.add_sub_add_left, Nat.sub_zero]
@ -1054,7 +1071,7 @@ protected theorem sub_self_add (n m : Nat) : n - (n + m) = 0 := by
show (n + 0) - (n + m) = 0
rw [Nat.add_sub_add_left, Nat.zero_sub]
protected theorem sub_eq_zero_of_le {n m : Nat} (h : n ≤ m) : n - m = 0 := by
@[simp] protected theorem sub_eq_zero_of_le {n m : Nat} (h : n ≤ m) : n - m = 0 := by
match le.dest h with
| ⟨k, hk⟩ => rw [← hk, Nat.sub_self_add]

View file

@ -473,7 +473,8 @@ Nat.le_antisymm
(le_of_lt_succ ((Nat.div_lt_iff_lt_mul npos).2 hi))
((Nat.le_div_iff_mul_le npos).2 lo)
theorem sub_mul_div (x n p : Nat) (h₁ : n*p ≤ x) : (x - n*p) / n = x / n - p := by
/-- See also `sub_mul_div` for a strictly more general version. -/
theorem sub_mul_div_of_le (x n p : Nat) (h₁ : n*p ≤ x) : (x - n*p) / n = x / n - p := by
match eq_zero_or_pos n with
| .inl h₀ => rw [h₀, Nat.div_zero, Nat.div_zero, Nat.zero_sub]
| .inr h₀ => induction p with
@ -551,7 +552,7 @@ protected theorem div_le_of_le_mul {m n : Nat} : ∀ {k}, m ≤ k * n → m / k
@[simp] theorem mul_div_left (m : Nat) {n : Nat} (H : 0 < n) : m * n / n = m := by
rw [Nat.mul_comm, mul_div_right _ H]
protected theorem div_self (H : 0 < n) : n / n = 1 := by
@[simp] protected theorem div_self (H : 0 < n) : n / n = 1 := by
let t := add_div_right 0 H
rwa [Nat.zero_add, Nat.zero_div] at t

View file

@ -84,6 +84,10 @@ theorem div_le_div_left (hcb : c ≤ b) (hc : 0 < c) : a / b ≤ a / c :=
(Nat.le_div_iff_mul_le hc).2 <|
Nat.le_trans (Nat.mul_le_mul_left _ hcb) (Nat.div_mul_le_self a b)
protected theorem div_le_div {a b c d : Nat} (h1 : a ≤ b) (h2 : d ≤ c) (h3 : d ≠ 0) : a / c ≤ b / d :=
calc a / c ≤ b / c := Nat.div_le_div_right h1
_ ≤ b / d := Nat.div_le_div_left h2 (Nat.pos_of_ne_zero h3)
theorem div_add_le_right {z : Nat} (h : 0 < z) (x y : Nat) :
x / (y + z) ≤ x / z :=
div_le_div_left (Nat.le_add_left z y) h
@ -104,7 +108,7 @@ theorem succ_div_of_dvd {a b : Nat} (h : b a + 1) :
Nat.add_right_cancel_iff] at h
subst h
rw [Nat.add_sub_cancel, ← Nat.add_one_mul, mul_div_right _ (zero_lt_succ _), Nat.add_comm,
Nat.add_mul_div_left _ _ (zero_lt_succ _), Nat.self_eq_add_left, div_eq_of_lt le.refl]
Nat.add_mul_div_left _ _ (zero_lt_succ _), Nat.right_eq_add, div_eq_of_lt le.refl]
· simp only [Nat.not_le] at h'
replace h' : a + 1 < b + 1 := Nat.add_lt_add_right h' 1
rw [Nat.mod_eq_of_lt h'] at h

View file

@ -1,21 +1,22 @@
/-
Copyright (c) 2016 Microsoft Corporation. All rights reserved.
Copyright (c) 2014 Floris van Doorn (c) 2016 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura, Jeremy Avigad, Mario Carneiro
Authors: Leonardo de Moura, Jeremy Avigad, Mario Carneiro, Floris van Doorn
-/
prelude
import Init.Data.Nat.MinMax
import Init.Data.Nat.Log2
import Init.Data.Nat.Power2
import Init.Data.Nat.Mod
import Init.Omega
/-! # Basic lemmas about natural numbers
/-! # Basic theorems about natural numbers
The primary purpose of the lemmas in this file is to assist with reasoning
The primary purpose of the theorems in this file is to assist with reasoning
about sizes of objects, array indices and such.
This file was upstreamed from Std,
and later these lemmas should be organised into other files more systematically.
The content of this file was upstreamed from Batteries and mathlib,
and later these theorems should be organised into other files more systematically.
-/
namespace Nat
@ -100,13 +101,94 @@ theorem exists_lt_succ_left {p : Nat → Prop} :
(∃ m, m < n + 1 ∧ p m) ↔ p 0 (∃ m, m < n ∧ p (m + 1)) := by
simpa using exists_lt_succ_left' (p := fun m _ => p m)
/-! ## succ/pred -/
protected theorem sub_one (n) : n - 1 = pred n := rfl
theorem one_add (n) : 1 + n = succ n := Nat.add_comm ..
theorem succ_ne_succ : succ m ≠ succ n ↔ m ≠ n :=
⟨mt (congrArg Nat.succ ·), mt succ.inj⟩
theorem one_lt_succ_succ (n : Nat) : 1 < n.succ.succ := succ_lt_succ <| succ_pos _
theorem not_succ_lt_self : ¬ succ n < n := Nat.not_lt_of_ge n.le_succ
theorem succ_le_iff : succ m ≤ n ↔ m < n := ⟨lt_of_succ_le, succ_le_of_lt⟩
theorem le_succ_iff {m n : Nat} : m ≤ n.succ ↔ m ≤ n m = n.succ := by
refine ⟨fun hmn ↦ (Nat.lt_or_eq_of_le hmn).imp_left le_of_lt_succ, ?_⟩
rintro (hmn | rfl)
· exact le_succ_of_le hmn
· exact Nat.le_refl _
theorem lt_iff_le_pred : ∀ {n}, 0 < n → (m < n ↔ m ≤ n - 1) | _ + 1, _ => Nat.lt_succ_iff
-- TODO: state LHS using `- 1` instead?
theorem le_of_pred_lt : ∀ {m}, pred m < n → m ≤ n
| 0 => Nat.le_of_lt
| _ + 1 => id
theorem lt_iff_add_one_le : m < n ↔ m + 1 ≤ n := by rw [succ_le_iff]
theorem lt_one_add_iff : m < 1 + n ↔ m ≤ n := by simp only [Nat.add_comm, Nat.lt_succ_iff]
theorem one_add_le_iff : 1 + m ≤ n ↔ m < n := by simp only [Nat.add_comm, add_one_le_iff]
theorem one_le_iff_ne_zero : 1 ≤ n ↔ n ≠ 0 := Nat.pos_iff_ne_zero
theorem one_lt_iff_ne_zero_and_ne_one : ∀ {n : Nat}, 1 < n ↔ n ≠ 0 ∧ n ≠ 1
| 0 => by decide
| 1 => by decide
| n + 2 => by omega
theorem le_one_iff_eq_zero_or_eq_one : ∀ {n : Nat}, n ≤ 1 ↔ n = 0 n = 1 := by simp [le_succ_iff]
theorem one_le_of_lt (h : a < b) : 1 ≤ b := Nat.lt_of_le_of_lt (Nat.zero_le _) h
theorem pred_one_add (n : Nat) : pred (1 + n) = n := by rw [Nat.add_comm, add_one, Nat.pred_succ]
theorem pred_eq_self_iff : n.pred = n ↔ n = 0 := by cases n <;> simp [(Nat.succ_ne_self _).symm]
theorem pred_eq_of_eq_succ {m n : Nat} (H : m = n.succ) : m.pred = n := by simp [H]
@[simp] theorem pred_eq_succ_iff : n - 1 = m + 1 ↔ n = m + 2 := by
cases n <;> constructor <;> rintro ⟨⟩ <;> rfl
@[simp] theorem add_succ_sub_one (m n : Nat) : m + succ n - 1 = m + n := rfl
@[simp]
theorem succ_add_sub_one (n m : Nat) : succ m + n - 1 = m + n := by rw [succ_add, Nat.add_one_sub_one]
theorem pred_sub (n m : Nat) : pred n - m = pred (n - m) := by
rw [← Nat.sub_one, Nat.sub_sub, one_add, sub_succ]
theorem self_add_sub_one : ∀ n, n + (n - 1) = 2 * n - 1
| 0 => rfl
| n + 1 => by rw [Nat.two_mul]; exact (add_succ_sub_one (Nat.succ _) _).symm
theorem sub_one_add_self (n : Nat) : (n - 1) + n = 2 * n - 1 := Nat.add_comm _ n ▸ self_add_sub_one n
theorem self_add_pred (n : Nat) : n + pred n = (2 * n).pred := self_add_sub_one n
theorem pred_add_self (n : Nat) : pred n + n = (2 * n).pred := sub_one_add_self n
theorem pred_le_iff : pred m ≤ n ↔ m ≤ succ n :=
⟨le_succ_of_pred_le, by
cases m
· exact fun _ ↦ zero_le n
· exact le_of_succ_le_succ⟩
theorem lt_of_lt_pred (h : m < n - 1) : m < n := by omega
theorem le_add_pred_of_pos (a : Nat) (hb : b ≠ 0) : a ≤ b + (a - 1) := by omega
theorem lt_pred_iff : a < pred b ↔ succ a < b := by simp; omega
/-! ## add -/
protected theorem add_add_add_comm (a b c d : Nat) : (a + b) + (c + d) = (a + c) + (b + d) := by
rw [Nat.add_assoc, Nat.add_assoc, Nat.add_left_comm b]
theorem one_add (n) : 1 + n = succ n := Nat.add_comm ..
theorem succ_eq_one_add (n) : succ n = 1 + n := (one_add _).symm
theorem succ_add_eq_add_succ (a b) : succ a + b = a + succ b := Nat.succ_add ..
@ -114,19 +196,31 @@ theorem succ_add_eq_add_succ (a b) : succ a + b = a + succ b := Nat.succ_add ..
protected theorem eq_zero_of_add_eq_zero_right (h : n + m = 0) : n = 0 :=
(Nat.eq_zero_of_add_eq_zero h).1
@[simp] protected theorem add_eq_zero_iff : n + m = 0 ↔ n = 0 ∧ m = 0 :=
protected theorem add_eq_zero_iff : n + m = 0 ↔ n = 0 ∧ m = 0 :=
⟨Nat.eq_zero_of_add_eq_zero, fun ⟨h₁, h₂⟩ => h₂.symm ▸ h₁⟩
@[simp] protected theorem add_left_cancel_iff {n : Nat} : n + m = n + k ↔ m = k :=
@[simp high] protected theorem add_left_cancel_iff {n : Nat} : n + m = n + k ↔ m = k :=
⟨Nat.add_left_cancel, fun | rfl => rfl⟩
@[simp] protected theorem add_right_cancel_iff {n : Nat} : m + n = k + n ↔ m = k :=
@[simp high] protected theorem add_right_cancel_iff {n : Nat} : m + n = k + n ↔ m = k :=
⟨Nat.add_right_cancel, fun | rfl => rfl⟩
@[simp] protected theorem add_left_eq_self {a b : Nat} : a + b = b ↔ a = 0 := by omega
@[simp] protected theorem add_right_eq_self {a b : Nat} : a + b = a ↔ b = 0 := by omega
@[simp] protected theorem self_eq_add_right {a b : Nat} : a = a + b ↔ b = 0 := by omega
@[simp] protected theorem self_eq_add_left {a b : Nat} : a = b + a ↔ b = 0 := by omega
protected theorem add_left_inj {n : Nat} : m + n = k + n ↔ m = k := Nat.add_right_cancel_iff
protected theorem add_right_inj {n : Nat} : n + m = n + k ↔ m = k := Nat.add_left_cancel_iff
@[simp high] protected theorem add_eq_left {a b : Nat} : a + b = a ↔ b = 0 := by omega
@[simp high] protected theorem add_eq_right {a b : Nat} : a + b = b ↔ a = 0 := by omega
@[simp high] protected theorem left_eq_add {a b : Nat} : a = a + b ↔ b = 0 := by omega
@[simp high] protected theorem right_eq_add {a b : Nat} : b = a + b ↔ a = 0 := by omega
@[deprecated Nat.add_eq_right (since := "2025-04-15")]
protected theorem add_left_eq_self {a b : Nat} : a + b = b ↔ a = 0 := Nat.add_eq_right
@[deprecated Nat.add_eq_left (since := "2025-04-15")]
protected theorem add_right_eq_self {a b : Nat} : a + b = a ↔ b = 0 := Nat.add_eq_left
@[deprecated Nat.left_eq_add (since := "2025-04-15")]
protected theorem self_eq_add_right {a b : Nat} : a = a + b ↔ b = 0 := Nat.left_eq_add
@[deprecated Nat.right_eq_add (since := "2025-04-15")]
protected theorem self_eq_add_left {a b : Nat} : a = b + a ↔ b = 0 := Nat.right_eq_add
protected theorem lt_of_add_lt_add_right : ∀ {n : Nat}, k + n < m + n → k < m
| 0, h => h
@ -173,9 +267,28 @@ protected theorem add_self_ne_one : ∀ n, n + n ≠ 1
theorem le_iff_lt_add_one : x ≤ y ↔ x < y + 1 := by
omega
/-! ## sub -/
@[simp high] protected theorem add_eq_zero : m + n = 0 ↔ m = 0 ∧ n = 0 := by omega
protected theorem sub_one (n) : n - 1 = pred n := rfl
theorem add_pos_iff_pos_or_pos : 0 < m + n ↔ 0 < m 0 < n := by omega
theorem add_eq_one_iff : m + n = 1 ↔ m = 0 ∧ n = 1 m = 1 ∧ n = 0 := by omega
theorem add_eq_two_iff : m + n = 2 ↔ m = 0 ∧ n = 2 m = 1 ∧ n = 1 m = 2 ∧ n = 0 := by
omega
theorem add_eq_three_iff :
m + n = 3 ↔ m = 0 ∧ n = 3 m = 1 ∧ n = 2 m = 2 ∧ n = 1 m = 3 ∧ n = 0 := by
omega
theorem le_add_one_iff : m ≤ n + 1 ↔ m ≤ n m = n + 1 := by omega
theorem le_and_le_add_one_iff : n ≤ m ∧ m ≤ n + 1 ↔ m = n m = n + 1 := by omega
theorem add_succ_lt_add (hab : a < b) (hcd : c < d) : a + c + 1 < b + d := by omega
theorem le_or_le_of_add_eq_add_pred (h : a + c = b + d - 1) : b ≤ a d ≤ c := by omega
/-! ## sub -/
protected theorem one_sub : ∀ n, 1 - n = if n = 0 then 1 else 0
| 0 => rfl
@ -213,7 +326,7 @@ protected theorem sub_eq_zero_iff_le : n - m = 0 ↔ n ≤ m :=
protected theorem sub_pos_iff_lt : 0 < n - m ↔ m < n :=
⟨Nat.lt_of_sub_pos, Nat.sub_pos_of_lt⟩
protected theorem sub_le_iff_le_add {a b c : Nat} : a - b ≤ c ↔ a ≤ c + b :=
@[simp] protected theorem sub_le_iff_le_add {a b c : Nat} : a - b ≤ c ↔ a ≤ c + b :=
⟨Nat.le_add_of_sub_le, sub_le_of_le_add⟩
protected theorem sub_le_iff_le_add' {a b c : Nat} : a - b ≤ c ↔ a ≤ b + c := by
@ -274,6 +387,25 @@ protected theorem exists_eq_add_of_le' (h : m ≤ n) : ∃ k : Nat, n = k + m :=
protected theorem exists_eq_add_of_lt (h : m < n) : ∃ k : Nat, n = m + k + 1 :=
⟨n - (m + 1), by rw [Nat.add_right_comm, add_sub_of_le h]⟩
/-- A version of `Nat.sub_succ` in the form `_ - 1` instead of `Nat.pred _`. -/
theorem sub_succ' (m n : Nat) : m - n.succ = m - n - 1 := rfl
protected theorem sub_eq_of_eq_add' {a b c : Nat} (h : a = b + c) : a - b = c := by omega
protected theorem eq_sub_of_add_eq {a b c : Nat} (h : c + b = a) : c = a - b := by omega
protected theorem eq_sub_of_add_eq' {a b c : Nat} (h : b + c = a) : c = a - b := by omega
protected theorem lt_sub_iff_add_lt {a b c : Nat} : a < c - b ↔ a + b < c := ⟨add_lt_of_lt_sub, lt_sub_of_add_lt⟩
protected theorem lt_sub_iff_add_lt' {a b c : Nat} : a < c - b ↔ b + a < c := by omega
protected theorem sub_lt_iff_lt_add {a b c : Nat} (hba : b ≤ a) : a - b < c ↔ a < c + b := by omega
protected theorem sub_lt_iff_lt_add' {a b c : Nat} (hba : b ≤ a) : a - b < c ↔ a < b + c := by omega
-- TODO: variants
protected theorem sub_sub_sub_cancel_right {a b c : Nat} (h : c ≤ b) : a - c - (b - c) = a - b := by omega
protected theorem add_sub_sub_cancel {a b c : Nat} (h : c ≤ a) : a + b - (a - c) = b + c := by omega
protected theorem sub_add_sub_cancel {a b c : Nat} (hab : b ≤ a) (hcb : c ≤ b) : a - b + (b - c) = a - c := by omega
protected theorem sub_lt_sub_iff_right {a b c : Nat} (h : c ≤ a) : a - c < b - c ↔ a < b := by omega
/-! ### min/max -/
theorem succ_min_succ (x y) : min (succ x) (succ y) = succ (min x y) := by
@ -417,6 +549,24 @@ protected theorem sub_min_sub_left (a b c : Nat) : min (a - b) (a - c) = a - max
protected theorem sub_max_sub_left (a b c : Nat) : max (a - b) (a - c) = a - min b c := by
omega
protected theorem min_left_comm (a b c : Nat) : min a (min b c) = min b (min a c) := by
rw [← Nat.min_assoc, ← Nat.min_assoc, b.min_comm]
protected theorem max_left_comm (a b c : Nat) : max a (max b c) = max b (max a c) := by
rw [← Nat.max_assoc, ← Nat.max_assoc, b.max_comm]
protected theorem min_right_comm (a b c : Nat) : min (min a b) c = min (min a c) b := by
rw [Nat.min_assoc, Nat.min_assoc, b.min_comm]
protected theorem max_right_comm (a b c : Nat) : max (max a b) c = max (max a c) b := by
rw [Nat.max_assoc, Nat.max_assoc, b.max_comm]
@[simp] theorem min_eq_zero_iff : min m n = 0 ↔ m = 0 n = 0 := by omega
@[simp] theorem max_eq_zero_iff : max m n = 0 ↔ m = 0 ∧ n = 0 := by omega
theorem add_eq_max_iff : m + n = max m n ↔ m = 0 n = 0 := by omega
theorem add_eq_min_iff : m + n = min m n ↔ m = 0 ∧ n = 0 := by omega
/-! ### mul -/
protected theorem mul_right_comm (n m k : Nat) : n * m * k = n * k * m := by
@ -538,6 +688,101 @@ protected theorem mul_dvd_mul_iff_left {a b c : Nat} (h : 0 < a) : a * b a *
protected theorem mul_dvd_mul_iff_right {a b c : Nat} (h : 0 < c) : a * c b * c ↔ a b := by
rw [Nat.mul_comm _ c, Nat.mul_comm _ c, Nat.mul_dvd_mul_iff_left h]
protected theorem zero_eq_mul : 0 = m * n ↔ m = 0 n = 0 := by rw [eq_comm, Nat.mul_eq_zero]
-- TODO: Replace `Nat.mul_right_cancel_iff` with `Nat.mul_left_inj`
protected theorem mul_left_inj (ha : a ≠ 0) : b * a = c * a ↔ b = c :=
Nat.mul_right_cancel_iff (Nat.pos_iff_ne_zero.2 ha)
-- TODO: Replace `Nat.mul_left_cancel_iff` with `Nat.mul_right_inj`
protected theorem mul_right_inj (ha : a ≠ 0) : a * b = a * c ↔ b = c :=
Nat.mul_left_cancel_iff (Nat.pos_iff_ne_zero.2 ha)
protected theorem mul_ne_mul_left (ha : a ≠ 0) : b * a ≠ c * a ↔ b ≠ c :=
not_congr (Nat.mul_left_inj ha)
protected theorem mul_ne_mul_right (ha : a ≠ 0) : a * b ≠ a * c ↔ b ≠ c :=
not_congr (Nat.mul_right_inj ha)
theorem mul_eq_left (ha : a ≠ 0) : a * b = a ↔ b = 1 := by simpa using Nat.mul_right_inj ha (c := 1)
theorem mul_eq_right (hb : b ≠ 0) : a * b = b ↔ a = 1 := by simpa using Nat.mul_left_inj hb (c := 1)
/-- The product of two natural numbers is greater than 1 if and only if
at least one of them is greater than 1 and both are positive. -/
theorem one_lt_mul_iff : 1 < m * n ↔ 0 < m ∧ 0 < n ∧ (1 < m 1 < n) := by
constructor <;> intro h
· refine Decidable.by_contra (fun h' => ?_)
simp only [Nat.le_zero, Decidable.not_and_iff_not_or_not, not_or, Nat.not_lt] at h'
obtain rfl | rfl | h' := h'
· simp at h
· simp at h
· exact Nat.not_lt_of_le (Nat.mul_le_mul h'.1 h'.2) h
· obtain hm | hn := h.2.2
· exact Nat.mul_lt_mul_of_lt_of_le' hm h.2.1 Nat.zero_lt_one
· exact Nat.mul_lt_mul_of_le_of_lt h.1 hn h.1
theorem eq_one_of_mul_eq_one_right (H : m * n = 1) : m = 1 := eq_one_of_dvd_one ⟨n, H.symm⟩
theorem eq_one_of_mul_eq_one_left (H : m * n = 1) : n = 1 :=
eq_one_of_mul_eq_one_right (n := m) (by rwa [Nat.mul_comm])
@[simp] protected theorem lt_mul_iff_one_lt_left (hb : 0 < b) : b < a * b ↔ 1 < a := by
simpa using Nat.mul_lt_mul_right (b := 1) hb
@[simp] protected theorem lt_mul_iff_one_lt_right (ha : 0 < a) : a < a * b ↔ 1 < b := by
simpa using Nat.mul_lt_mul_left (b := 1) ha
theorem eq_zero_of_two_mul_le (h : 2 * n ≤ n) : n = 0 := by omega
theorem eq_zero_of_mul_le (hb : 2 ≤ n) (h : n * m ≤ m) : m = 0 :=
eq_zero_of_two_mul_le <| Nat.le_trans (Nat.mul_le_mul_right _ hb) h
theorem succ_mul_pos (m : Nat) (hn : 0 < n) : 0 < succ m * n := Nat.mul_pos m.succ_pos hn
theorem mul_self_le_mul_self {m n : Nat} (h : m ≤ n) : m * m ≤ n * n := Nat.mul_le_mul h h
-- This name is consistent with mathlib's top level definitions for groups with zero, where there
-- are `mul_lt_mul`, `mul_lt_mul'` and `mul_lt_mul''`, all with different sets of hypotheses.
theorem mul_lt_mul'' {a b c d : Nat} (hac : a < c) (hbd : b < d) : a * b < c * d :=
Nat.mul_lt_mul_of_lt_of_le hac (Nat.le_of_lt hbd) <| by omega
protected theorem lt_iff_lt_of_mul_eq_mul (ha : a ≠ 0) (hbd : a = b * d) (hce : a = c * e) :
c < b ↔ d < e where
mp hcb := Nat.lt_of_not_le fun hed ↦ Nat.not_lt_of_le (Nat.le_of_eq <| hbd.symm.trans hce) <|
Nat.mul_lt_mul_of_lt_of_le hcb hed <| by simp [hbd, Nat.mul_eq_zero] at ha; omega
mpr hde := Nat.lt_of_not_le fun hbc ↦ Nat.not_lt_of_le (Nat.le_of_eq <| hce.symm.trans hbd) <|
Nat.mul_lt_mul_of_le_of_lt hbc hde <| by simp [hce, Nat.mul_eq_zero] at ha; omega
theorem mul_self_lt_mul_self {m n : Nat} (h : m < n) : m * m < n * n := mul_lt_mul'' h h
theorem mul_self_le_mul_self_iff {m n : Nat} : m * m ≤ n * n ↔ m ≤ n :=
⟨fun h => Nat.le_of_not_lt fun h' => Nat.not_le_of_gt (mul_self_lt_mul_self h') h,
mul_self_le_mul_self⟩
theorem mul_self_lt_mul_self_iff {m n : Nat} : m * m < n * n ↔ m < n := by
simp only [← Nat.not_le, mul_self_le_mul_self_iff]
theorem le_mul_self : ∀ n : Nat, n ≤ n * n
| 0 => Nat.le_refl _
| n + 1 => by simp [Nat.mul_add]
theorem mul_self_inj {m n : Nat} : m * m = n * n ↔ m = n := by
simp [Nat.le_antisymm_iff, mul_self_le_mul_self_iff]
@[simp] theorem lt_mul_self_iff : ∀ {n : Nat}, n < n * n ↔ 1 < n
| 0 => by simp
| n + 1 => Nat.lt_mul_iff_one_lt_left n.succ_pos
theorem add_sub_one_le_mul (ha : a ≠ 0) (hb : b ≠ 0) : a + b - 1 ≤ a * b := by
cases a
· cases ha rfl
· rw [succ_add, Nat.add_one_sub_one, succ_mul]
exact Nat.add_le_add_right (Nat.le_mul_of_pos_right _ <| Nat.pos_iff_ne_zero.2 hb) _
protected theorem add_le_mul {a : Nat} (ha : 2 ≤ a) : ∀ {b : Nat} (_ : 2 ≤ b), a + b ≤ a * b
| 2, _ => by omega
| b + 3, _ => by have := Nat.add_le_mul ha (Nat.le_add_left _ b); rw [mul_succ]; omega
/-! ### div/mod -/
theorem mod_two_eq_zero_or_one (n : Nat) : n % 2 = 0 n % 2 = 1 :=
@ -629,6 +874,203 @@ theorem div_eq_self {m n : Nat} : m / n = m ↔ m = 0 n = 1 := by
· exact hn
· exact False.elim (absurd h (Nat.ne_of_lt (Nat.div_lt_self hm hn)))
@[simp] protected theorem div_eq_zero_iff : a / b = 0 ↔ b = 0 a < b where
mp h := by
rw [← mod_add_div a b, h, Nat.mul_zero, Nat.add_zero, Decidable.or_iff_not_imp_left]
exact mod_lt _ ∘ Nat.pos_iff_ne_zero.2
mpr := by
obtain rfl | hb := Decidable.em (b = 0)
· simp
simp only [hb, false_or]
rw [← Nat.mul_right_inj hb, ← Nat.add_left_cancel_iff, mod_add_div]
simp +contextual [mod_eq_of_lt]
protected theorem div_ne_zero_iff : a / b ≠ 0 ↔ b ≠ 0 ∧ b ≤ a := by simp
@[simp] protected theorem div_pos_iff : 0 < a / b ↔ 0 < b ∧ b ≤ a := by
simp [Nat.pos_iff_ne_zero]
theorem lt_mul_of_div_lt (h : a / c < b) (hc : 0 < c) : a < b * c :=
Nat.lt_of_not_ge <| Nat.not_le_of_gt h ∘ (Nat.le_div_iff_mul_le hc).2
theorem mul_div_le_mul_div_assoc (a b c : Nat) : a * (b / c) ≤ a * b / c :=
if hc0 : c = 0 then by simp [hc0] else
(Nat.le_div_iff_mul_le (Nat.pos_of_ne_zero hc0)).2
(by rw [Nat.mul_assoc]; exact Nat.mul_le_mul_left _ (Nat.div_mul_le_self _ _))
protected theorem eq_mul_of_div_eq_right {a b c : Nat} (H1 : b a) (H2 : a / b = c) :
a = b * c := by
rw [← H2, Nat.mul_div_cancel' H1]
protected theorem eq_mul_of_div_eq_left {a b c : Nat} (H1 : b a) (H2 : a / b = c) : a = c * b := by
rw [Nat.mul_comm, Nat.eq_mul_of_div_eq_right H1 H2]
protected theorem mul_div_cancel_left' {a b : Nat} (Hd : a b) : a * (b / a) = b := by
rw [Nat.mul_comm, Nat.div_mul_cancel Hd]
theorem lt_div_mul_add {a b : Nat} (hb : 0 < b) : a < a / b * b + b := by
rw [← Nat.succ_mul, ← Nat.div_lt_iff_lt_mul hb]; exact Nat.lt_succ_self _
@[simp]
protected theorem div_left_inj {a b d : Nat} (hda : d a) (hdb : d b) :
a / d = b / d ↔ a = b := by
refine ⟨fun h ↦ ?_, congrArg fun b ↦ b / d⟩
rw [← Nat.mul_div_cancel' hda, ← Nat.mul_div_cancel' hdb, h]
theorem div_le_iff_le_mul_add_pred (hb : 0 < b) : a / b ≤ c ↔ a ≤ b * c + (b - 1) := by
rw [← Nat.lt_succ_iff, div_lt_iff_lt_mul hb, succ_mul, Nat.mul_comm]
cases hb <;> exact Nat.lt_succ_iff
theorem one_le_div_iff {a b : Nat} (hb : 0 < b) : 1 ≤ a / b ↔ b ≤ a := by
rw [le_div_iff_mul_le hb, Nat.one_mul]
theorem div_lt_one_iff (hb : 0 < b) : a / b < 1 ↔ a < b := by
simp only [← Nat.not_le, one_le_div_iff hb]
protected theorem div_le_div_right {a b c : Nat} (h : a ≤ b) : a / c ≤ b / c :=
(c.eq_zero_or_pos.elim fun hc ↦ by simp [hc]) fun hc ↦
(le_div_iff_mul_le hc).2 <| Nat.le_trans (Nat.div_mul_le_self _ _) h
theorem lt_of_div_lt_div {a b c : Nat} (h : a / c < b / c) : a < b :=
Nat.lt_of_not_le fun hab ↦ Nat.not_le_of_lt h <| Nat.div_le_div_right hab
theorem sub_mul_div (a b c : Nat) : (a - b * c) / b = a / b - c := by
obtain h | h := Nat.le_total (b * c) a
· rw [Nat.sub_mul_div_of_le _ _ _ h]
· rw [Nat.sub_eq_zero_of_le h, Nat.zero_div]
by_cases hn : b = 0
· simp only [hn, Nat.div_zero, zero_le, Nat.sub_eq_zero_of_le]
· have h2 : a / b ≤ (b * c) / b := Nat.div_le_div_right h
rw [Nat.mul_div_cancel_left _ (zero_lt_of_ne_zero hn)] at h2
rw [Nat.sub_eq_zero_of_le h2]
theorem mul_sub_div_of_dvd {b c : Nat} (hc : c ≠ 0) (hcb : c b) (a : Nat) : (c * a - b) / c = a - b / c := by
obtain ⟨_, hx⟩ := hcb
simp only [hx, ← Nat.mul_sub_left_distrib, Nat.mul_div_right, zero_lt_of_ne_zero hc]
theorem mul_add_mul_div_of_dvd (hb : b ≠ 0) (hd : d ≠ 0) (hba : b a) (hdc : d c) :
(a * d + b * c) / (b * d) = a / b + c / d := by
obtain ⟨n, hn⟩ := hba
obtain ⟨_, hm⟩ := hdc
rw [hn, hm, Nat.mul_assoc b n d, Nat.mul_comm n d, ← Nat.mul_assoc, ← Nat.mul_assoc,
← Nat.mul_add,
Nat.mul_div_right _ (zero_lt_of_ne_zero hb),
Nat.mul_div_right _ (zero_lt_of_ne_zero hd),
Nat.mul_div_right _ (zero_lt_of_ne_zero <| Nat.mul_ne_zero hb hd)]
theorem mul_sub_mul_div_of_dvd (hb : b ≠ 0) (hd : d ≠ 0) (hba : b a) (hdc : d c) :
(a * d - b * c) / (b * d) = a / b - c / d := by
obtain ⟨n, hn⟩ := hba
obtain ⟨m, hm⟩ := hdc
rw [hn, hm]
rw [Nat.mul_assoc,Nat.mul_comm n d, ← Nat.mul_assoc,← Nat.mul_assoc, ← Nat.mul_sub_left_distrib,
Nat.mul_div_right _ (zero_lt_of_ne_zero hb), Nat.mul_div_right _ (zero_lt_of_ne_zero hd),
Nat.mul_div_right _ (zero_lt_of_ne_zero <| Nat.mul_ne_zero hb hd)]
protected theorem div_mul_right_comm {a b : Nat} (hba : b a) (c : Nat) : a / b * c = a * c / b := by
rw [Nat.mul_comm, ← Nat.mul_div_assoc _ hba, Nat.mul_comm]
protected theorem mul_div_right_comm {a b : Nat} (hba : b a) (c : Nat) : a * c / b = a / b * c :=
(Nat.div_mul_right_comm hba _).symm
protected theorem div_eq_iff_eq_mul_right {a b c : Nat} (H : 0 < b) (H' : b a) :
a / b = c ↔ a = b * c :=
⟨Nat.eq_mul_of_div_eq_right H', Nat.div_eq_of_eq_mul_right H⟩
protected theorem div_eq_iff_eq_mul_left {a b c : Nat} (H : 0 < b) (H' : b a) :
a / b = c ↔ a = c * b := by
rw [Nat.mul_comm]; exact Nat.div_eq_iff_eq_mul_right H H'
theorem eq_div_iff_mul_eq_left (hc : c ≠ 0) (hcb : c b) : a = b / c ↔ b = a * c := by
rw [eq_comm, Nat.div_eq_iff_eq_mul_left (zero_lt_of_ne_zero hc) hcb]
theorem div_mul_div_comm {a b c d : Nat} : b a → d c → (a / b) * (c / d) = (a * c) / (b * d) := by
rintro ⟨x, rfl⟩ ⟨y, rfl⟩
obtain rfl | hb := b.eq_zero_or_pos
· simp
obtain rfl | hd := d.eq_zero_or_pos
· simp
rw [Nat.mul_div_cancel_left _ hb, Nat.mul_div_cancel_left _ hd, Nat.mul_assoc b,
Nat.mul_left_comm x, ← Nat.mul_assoc b, Nat.mul_div_cancel_left _ (Nat.mul_pos hb hd)]
protected theorem mul_div_mul_comm {a b c d : Nat} (hba : b a) (hdc : d c) : a * c / (b * d) = a / b * (c / d) :=
(div_mul_div_comm hba hdc).symm
theorem eq_zero_of_le_div (hn : 2 ≤ n) (h : m ≤ m / n) : m = 0 :=
eq_zero_of_mul_le hn <| by
rw [Nat.mul_comm]; exact (Nat.le_div_iff_mul_le (Nat.lt_of_lt_of_le (by decide) hn)).1 h
theorem div_mul_div_le_div (a b c : Nat) : a / c * b / a ≤ b / c := by
obtain rfl | ha := Nat.eq_zero_or_pos a
· simp
· calc
a / c * b / a ≤ b * a / c / a :=
Nat.div_le_div_right (by rw [Nat.mul_comm]; exact mul_div_le_mul_div_assoc _ _ _)
_ = b / c := by rw [Nat.div_div_eq_div_mul, Nat.mul_comm b, Nat.mul_comm c,
Nat.mul_div_mul_left _ _ ha]
theorem eq_zero_of_le_div_two (h : n ≤ n / 2) : n = 0 := eq_zero_of_le_div (Nat.le_refl _) h
theorem le_div_two_of_div_two_lt_sub (h : a / 2 < a - b) : b ≤ a / 2 := by
omega
theorem div_two_le_of_sub_le_div_two (h : a - b ≤ a / 2) : a / 2 ≤ b := by
omega
protected theorem div_le_div_of_mul_le_mul (hd : d ≠ 0) (hdc : d c) (h : a * d ≤ c * b) :
a / b ≤ c / d :=
Nat.div_le_of_le_mul <| by
rwa [← Nat.mul_div_assoc _ hdc, Nat.le_div_iff_mul_le (Nat.pos_iff_ne_zero.2 hd), b.mul_comm]
theorem div_eq_sub_mod_div {m n : Nat} : m / n = (m - m % n) / n := by
obtain rfl | hn := n.eq_zero_or_pos
· rw [Nat.div_zero, Nat.div_zero]
· have : m - m % n = n * (m / n) := by
rw [Nat.sub_eq_iff_eq_add (Nat.mod_le _ _), Nat.add_comm, mod_add_div]
rw [this, mul_div_right _ hn]
protected theorem eq_div_of_mul_eq_left (hc : c ≠ 0) (h : a * c = b) : a = b / c := by
rw [← h, Nat.mul_div_cancel _ (Nat.pos_iff_ne_zero.2 hc)]
protected theorem eq_div_of_mul_eq_right (hc : c ≠ 0) (h : c * a = b) : a = b / c := by
rw [← h, Nat.mul_div_cancel_left _ (Nat.pos_iff_ne_zero.2 hc)]
protected theorem mul_le_of_le_div (k x y : Nat) (h : x ≤ y / k) : x * k ≤ y := by
if hk : k = 0 then
rw [hk, Nat.mul_zero]; exact zero_le _
else
rwa [← le_div_iff_mul_le (Nat.pos_iff_ne_zero.2 hk)]
theorem div_le_iff_le_mul_of_dvd (hb : b ≠ 0) (hba : b a) : a / b ≤ c ↔ a ≤ c * b := by
obtain ⟨_, hx⟩ := hba
simp only [hx]
rw [Nat.mul_div_right _ (zero_lt_of_ne_zero hb), Nat.mul_comm]
exact ⟨mul_le_mul_right b, fun h ↦ Nat.le_of_mul_le_mul_right h (zero_lt_of_ne_zero hb)⟩
protected theorem div_lt_div_right (ha : a ≠ 0) : a b → a c → (b / a < c / a ↔ b < c) := by
rintro ⟨d, rfl⟩ ⟨e, rfl⟩; simp [Nat.mul_div_cancel, Nat.pos_iff_ne_zero.2 ha]
protected theorem div_lt_div_left (ha : a ≠ 0) (hba : b a) (hca : c a) :
a / b < a / c ↔ c < b := by
obtain ⟨d, hd⟩ := hba
obtain ⟨e, he⟩ := hca
rw [Nat.div_eq_of_eq_mul_right _ hd, Nat.div_eq_of_eq_mul_right _ he,
Nat.lt_iff_lt_of_mul_eq_mul ha hd he] <;>
rw [Nat.pos_iff_ne_zero] <;> rintro rfl <;> simp at * <;> contradiction
theorem lt_div_iff_mul_lt_of_dvd (hc : c ≠ 0) (hcb : c b) : a < b / c ↔ a * c < b := by
simp [← Nat.div_lt_div_right _ _ hcb, hc, Nat.pos_iff_ne_zero, Nat.dvd_mul_left]
protected theorem div_mul_div_le (a b c d : Nat) :
(a / b) * (c / d) ≤ (a * c) / (b * d) := by
if hb : b = 0 then simp [hb] else
if hd : d = 0 then simp [hd] else
have hbd : b * d ≠ 0 := Nat.mul_ne_zero hb hd
rw [le_div_iff_mul_le (Nat.pos_of_ne_zero hbd)]
refine Nat.le_trans (m := ((a / b) * b) * ((c / d) * d)) ?_ ?_
· apply Nat.le_of_eq; simp only [Nat.mul_assoc, Nat.mul_left_comm]
· apply Nat.mul_le_mul <;> apply div_mul_le_self
/-! ### pow -/
theorem pow_succ' {m n : Nat} : m ^ n.succ = m * m ^ n := by
@ -802,6 +1244,74 @@ theorem le_pow {a b : Nat} (h : 0 < b) : a ≤ a ^ b := by
rw [(show b = b - 1 + 1 by omega), Nat.pow_succ]
exact Nat.le_mul_of_pos_left _ (Nat.pow_pos ha)
protected theorem pow_lt_pow_right (ha : 1 < a) (h : m < n) : a ^ m < a ^ n :=
(Nat.pow_lt_pow_iff_right ha).2 h
protected theorem pow_le_pow_iff_left {a b n : Nat} (hn : n ≠ 0) : a ^ n ≤ b ^ n ↔ a ≤ b where
mp := by simpa only [← Nat.not_le, Decidable.not_imp_not] using (Nat.pow_lt_pow_left · hn)
mpr h := Nat.pow_le_pow_left h _
protected theorem pow_lt_pow_iff_left {a b n : Nat} (hn : n ≠ 0) : a ^ n < b ^ n ↔ a < b := by
simp only [← Nat.not_le, Nat.pow_le_pow_iff_left hn]
@[simp high] protected theorem pow_eq_zero {a : Nat} : ∀ {n : Nat}, a ^ n = 0 ↔ a = 0 ∧ n ≠ 0
| 0 => by simp
| n + 1 => by rw [Nat.pow_succ, mul_eq_zero, Nat.pow_eq_zero]; omega
theorem le_self_pow (hn : n ≠ 0) : ∀ a : Nat, a ≤ a ^ n
| 0 => zero_le _
| a + 1 => by simpa using Nat.pow_le_pow_right a.succ_pos (Nat.one_le_iff_ne_zero.2 hn)
theorem one_le_pow (n m : Nat) (h : 0 < m) : 1 ≤ m ^ n := by simpa using Nat.pow_le_pow_left h n
theorem one_lt_pow (hn : n ≠ 0) (ha : 1 < a) : 1 < a ^ n := by simpa using Nat.pow_lt_pow_left ha hn
theorem two_pow_succ (n : Nat) : 2 ^ (n + 1) = 2 ^ n + 2 ^ n := by simp [Nat.pow_succ, Nat.mul_two]
theorem one_lt_pow' (n m : Nat) : 1 < (m + 2) ^ (n + 1) :=
one_lt_pow n.succ_ne_zero (Nat.lt_of_sub_eq_succ rfl)
@[simp] theorem one_lt_pow_iff {n : Nat} (hn : n ≠ 0) : ∀ {a}, 1 < a ^ n ↔ 1 < a
| 0 => by simp [Nat.zero_pow (Nat.pos_of_ne_zero hn)]
| 1 => by simp
| a + 2 => by simp [one_lt_pow hn]
theorem one_lt_two_pow' (n : Nat) : 1 < 2 ^ (n + 1) := one_lt_pow n.succ_ne_zero (by decide)
theorem mul_lt_mul_pow_succ (ha : 0 < a) (hb : 1 < b) : n * b < a * b ^ (n + 1) := by
rw [Nat.pow_succ, ← Nat.mul_assoc, Nat.mul_lt_mul_right (Nat.lt_trans Nat.zero_lt_one hb)]
exact Nat.lt_of_le_of_lt (Nat.le_mul_of_pos_left _ ha)
((Nat.mul_lt_mul_left ha).2 <| Nat.lt_pow_self hb)
theorem pow_two_sub_pow_two (a b : Nat) : a ^ 2 - b ^ 2 = (a + b) * (a - b) := by
simpa [Nat.pow_succ] using Nat.mul_self_sub_mul_self_eq a b
protected theorem pow_pos_iff : 0 < a ^ n ↔ 0 < a n = 0 := by
simp [Nat.pos_iff_ne_zero, Decidable.imp_iff_not_or]
theorem pow_self_pos : 0 < n ^ n := by simp [Nat.pow_pos_iff, n.eq_zero_or_pos.symm]
theorem pow_self_mul_pow_self_le : m ^ m * n ^ n ≤ (m + n) ^ (m + n) := by
rw [Nat.pow_add]
exact Nat.mul_le_mul (Nat.pow_le_pow_left (le_add_right ..) _)
(Nat.pow_le_pow_left (le_add_left ..) _)
protected theorem pow_right_inj (ha : 1 < a) : a ^ m = a ^ n ↔ m = n := by
simp [Nat.le_antisymm_iff, Nat.pow_le_pow_iff_right ha]
@[simp] protected theorem pow_eq_one : a ^ n = 1 ↔ a = 1 n = 0 := by
obtain rfl | hn := Decidable.em (n = 0)
· simp
· simpa [hn] using Nat.pow_left_inj hn (b := 1)
/-- For `a > 1`, `a ^ b = a` iff `b = 1`. -/
theorem pow_eq_self_iff {a b : Nat} (ha : 1 < a) : a ^ b = a ↔ b = 1 := by
rw [← Nat.pow_right_inj (m := b) ha, Nat.pow_one]
@[simp] protected theorem pow_le_one_iff (hn : n ≠ 0) : a ^ n ≤ 1 ↔ a ≤ 1 := by
rw [← Nat.not_lt, one_lt_pow_iff hn, Nat.not_lt]
/-! ### log2 -/
@[simp]
@ -835,19 +1345,7 @@ theorem lt_log2_self : n < 2 ^ (n.log2 + 1) :=
| 0 => by simp
| n+1 => (log2_lt n.succ_ne_zero).1 (Nat.le_refl _)
/-! ### dvd -/
protected theorem eq_mul_of_div_eq_right {a b c : Nat} (H1 : b a) (H2 : a / b = c) :
a = b * c := by
rw [← H2, Nat.mul_div_cancel' H1]
protected theorem div_eq_iff_eq_mul_right {a b c : Nat} (H : 0 < b) (H' : b a) :
a / b = c ↔ a = b * c :=
⟨Nat.eq_mul_of_div_eq_right H', Nat.div_eq_of_eq_mul_right H⟩
protected theorem div_eq_iff_eq_mul_left {a b c : Nat} (H : 0 < b) (H' : b a) :
a / b = c ↔ a = c * b := by
rw [Nat.mul_comm]; exact Nat.div_eq_iff_eq_mul_right H H'
/-! ### mod, dvd -/
theorem pow_dvd_pow_iff_pow_le_pow {k l : Nat} :
∀ {x : Nat}, 0 < x → (x ^ k x ^ l ↔ x ^ k ≤ x ^ l)
@ -903,48 +1401,151 @@ protected theorem div_pow {a b c : Nat} (h : a b) : (b / a) ^ c = b ^ c / a
rw [Nat.pow_succ (b / a), Nat.pow_succ a, Nat.mul_comm _ a, Nat.mul_assoc, ← Nat.mul_assoc _ a,
Nat.div_mul_cancel h, Nat.mul_comm b, ← Nat.mul_assoc, ← ih, Nat.pow_succ]
/-! ### shiftLeft and shiftRight -/
@[simp] theorem mod_two_not_eq_one : ¬n % 2 = 1 ↔ n % 2 = 0 := by
cases mod_two_eq_zero_or_one n <;> simp [*]
@[simp] theorem shiftLeft_zero : n <<< 0 = n := rfl
@[simp] theorem mod_two_not_eq_zero : ¬n % 2 = 0 ↔ n % 2 = 1 := by
cases mod_two_eq_zero_or_one n <;> simp [*]
/-- Shiftleft on successor with multiple moved inside. -/
theorem shiftLeft_succ_inside (m n : Nat) : m <<< (n+1) = (2*m) <<< n := rfl
theorem mod_two_ne_one : n % 2 ≠ 1 ↔ n % 2 = 0 := mod_two_not_eq_one
theorem mod_two_ne_zero : n % 2 ≠ 0 ↔ n % 2 = 1 := mod_two_not_eq_zero
/-- Shiftleft on successor with multiple moved to outside. -/
theorem shiftLeft_succ : ∀(m n), m <<< (n + 1) = 2 * (m <<< n)
| _, 0 => rfl
| _, k + 1 => by
rw [shiftLeft_succ_inside _ (k+1)]
rw [shiftLeft_succ _ k, shiftLeft_succ_inside]
/-- Variant of `Nat.lt_div_iff_mul_lt` that assumes `d n`. -/
protected theorem lt_div_iff_mul_lt' (hdn : d n) (a : Nat) : a < n / d ↔ d * a < n := by
obtain rfl | hd := d.eq_zero_or_pos
· simp [Nat.zero_dvd.1 hdn]
· rw [← Nat.mul_lt_mul_left hd, ← Nat.eq_mul_of_div_eq_right hdn rfl]
/-- Shiftright on successor with division moved inside. -/
theorem shiftRight_succ_inside : ∀m n, m >>> (n+1) = (m/2) >>> n
| _, 0 => rfl
| _, k + 1 => by
rw [shiftRight_succ _ (k+1)]
rw [shiftRight_succ_inside _ k, shiftRight_succ]
theorem mul_div_eq_iff_dvd {n d : Nat} : d * (n / d) = n ↔ d n :=
calc
d * (n / d) = n ↔ d * (n / d) = d * (n / d) + (n % d) := by rw [div_add_mod]
_ ↔ d n := by rw [eq_comm, Nat.add_eq_left, dvd_iff_mod_eq_zero]
@[simp] theorem zero_shiftLeft : ∀ n, 0 <<< n = 0
| 0 => by simp [shiftLeft]
| n + 1 => by simp [shiftLeft, zero_shiftLeft n, shiftLeft_succ]
theorem mul_div_lt_iff_not_dvd {n d : Nat} : d * (n / d) < n ↔ ¬ d n := by
simp [Nat.lt_iff_le_and_ne, mul_div_eq_iff_dvd, mul_div_le]
@[simp] theorem zero_shiftRight : ∀ n, 0 >>> n = 0
| 0 => by simp [shiftRight]
| n + 1 => by simp [shiftRight, zero_shiftRight n, shiftRight_succ]
theorem div_eq_iff_eq_of_dvd_dvd (hn : n ≠ 0) (ha : a n) (hb : b n) : n / a = n / b ↔ a = b := by
constructor <;> intro h
· rw [← Nat.mul_right_inj hn]
apply Nat.eq_mul_of_div_eq_left (Nat.dvd_trans hb (Nat.dvd_mul_right _ _))
rw [eq_comm, Nat.mul_comm, Nat.mul_div_assoc _ hb]
exact Nat.eq_mul_of_div_eq_right ha h
· rw [h]
theorem shiftLeft_add (m n : Nat) : ∀ k, m <<< (n + k) = (m <<< n) <<< k
| 0 => rfl
| k + 1 => by simp [← Nat.add_assoc, shiftLeft_add _ _ k, shiftLeft_succ]
theorem le_iff_ne_zero_of_dvd (ha : a ≠ 0) (hab : a b) : a ≤ b ↔ b ≠ 0 where
mp := by rw [← Nat.pos_iff_ne_zero] at ha ⊢; exact Nat.lt_of_lt_of_le ha
mpr hb := Nat.le_of_dvd (Nat.pos_iff_ne_zero.2 hb) hab
@[simp] theorem shiftLeft_shiftRight (x n : Nat) : x <<< n >>> n = x := by
rw [Nat.shiftLeft_eq, Nat.shiftRight_eq_div_pow, Nat.mul_div_cancel _ (Nat.two_pow_pos _)]
theorem div_ne_zero_iff_of_dvd (hba : b a) : a / b ≠ 0 ↔ a ≠ 0 ∧ b ≠ 0 := by
obtain rfl | hb := Decidable.em (b = 0) <;>
simp [Nat.div_ne_zero_iff, Nat.le_iff_ne_zero_of_dvd, *]
theorem pow_mod (a b n : Nat) : a ^ b % n = (a % n) ^ b % n := by
induction b with
| zero => rfl
| succ b ih => simp [Nat.pow_succ, Nat.mul_mod, ih]
theorem lt_of_pow_dvd_right (hb : b ≠ 0) (ha : 2 ≤ a) (h : a ^ n b) : n < b := by
rw [← Nat.pow_lt_pow_iff_right (succ_le_iff.1 ha)]
exact Nat.lt_of_le_of_lt (le_of_dvd (Nat.pos_iff_ne_zero.2 hb) h) (Nat.lt_pow_self ha)
theorem div_dvd_of_dvd {n m : Nat} (h : n m) : m / n m := ⟨n, (Nat.div_mul_cancel h).symm⟩
protected theorem div_div_self (h : n m) (hm : m ≠ 0) : m / (m / n) = n := by
rcases h with ⟨_, rfl⟩
rw [Nat.mul_ne_zero_iff] at hm
rw [mul_div_right _ (Nat.pos_of_ne_zero hm.1), mul_div_left _ (Nat.pos_of_ne_zero hm.2)]
theorem not_dvd_of_pos_of_lt (h1 : 0 < n) (h2 : n < m) : ¬m n := by
rintro ⟨k, rfl⟩
rcases Nat.eq_zero_or_pos k with (rfl | hk)
· exact Nat.lt_irrefl 0 h1
· exact Nat.not_lt.2 (Nat.le_mul_of_pos_right _ hk) h2
theorem eq_of_dvd_of_lt_two_mul (ha : a ≠ 0) (hdvd : b a) (hlt : a < 2 * b) : a = b := by
obtain ⟨_ | _ | c, rfl⟩ := hdvd
· simp at ha
· exact Nat.mul_one _
· rw [Nat.mul_comm] at hlt
cases Nat.not_le_of_lt hlt (Nat.mul_le_mul_right _ (by omega))
theorem mod_eq_iff_lt (hn : n ≠ 0) : m % n = m ↔ m < n :=
⟨fun h ↦ by rw [← h]; exact mod_lt _ <| Nat.pos_iff_ne_zero.2 hn, mod_eq_of_lt⟩
@[simp]
theorem mod_succ_eq_iff_lt {m n : Nat} : m % n.succ = m ↔ m < n.succ :=
mod_eq_iff_lt (succ_ne_zero _)
@[simp] theorem mod_succ (n : Nat) : n % n.succ = n := mod_eq_of_lt n.lt_succ_self
theorem mod_add_div' (a b : Nat) : a % b + a / b * b = a := by rw [Nat.mul_comm]; exact mod_add_div _ _
theorem div_add_mod' (a b : Nat) : a / b * b + a % b = a := by rw [Nat.mul_comm]; exact div_add_mod _ _
/-- See also `Nat.divModEquiv` for a similar statement as an `Equiv`. -/
protected theorem div_mod_unique (h : 0 < b) :
a / b = d ∧ a % b = c ↔ c + b * d = a ∧ c < b :=
⟨fun ⟨e₁, e₂⟩ ↦ e₁ ▸ e₂ ▸ ⟨mod_add_div _ _, mod_lt _ h⟩, fun ⟨h₁, h₂⟩ ↦ h₁ ▸ by
rw [add_mul_div_left _ _ h, add_mul_mod_self_left]; simp [div_eq_of_lt, mod_eq_of_lt, h₂]⟩
/-- If `m` and `n` are equal mod `k`, `m - n` is zero mod `k`. -/
theorem sub_mod_eq_zero_of_mod_eq (h : m % k = n % k) : (m - n) % k = 0 := by
rw [← Nat.mod_add_div m k, ← Nat.mod_add_div n k, ← h, ← Nat.sub_sub,
Nat.add_sub_cancel_left, ← k.mul_sub, Nat.mul_mod_right]
@[simp] theorem one_mod (n : Nat) : 1 % (n + 2) = 1 :=
Nat.mod_eq_of_lt (Nat.add_lt_add_right n.succ_pos 1)
theorem one_mod_eq_one : ∀ {n : Nat}, 1 % n = 1 ↔ n ≠ 1
| 0 | 1 | n + 2 => by simp; try omega
theorem dvd_sub_mod (k : Nat) : n k - k % n :=
⟨k / n, Nat.sub_eq_of_eq_add (Nat.div_add_mod k n).symm⟩
theorem add_mod_eq_ite {m n : Nat} :
(m + n) % k = if k ≤ m % k + n % k then m % k + n % k - k else m % k + n % k := by
cases k with
| zero => simp
| succ k =>
rw [Nat.add_mod]
by_cases h : k + 1 ≤ m % (k + 1) + n % (k + 1)
· rw [if_pos h, Nat.mod_eq_sub_mod h, Nat.mod_eq_of_lt]
exact (Nat.sub_lt_iff_lt_add h).mpr (Nat.add_lt_add (m.mod_lt (zero_lt_succ _))
(n.mod_lt (zero_lt_succ _)))
· rw [if_neg h]
exact Nat.mod_eq_of_lt (Nat.lt_of_not_ge h)
-- TODO: Replace `Nat.dvd_add_iff_left`
protected theorem dvd_add_left {a b c : Nat} (h : a c) : a b + c ↔ a b := (Nat.dvd_add_iff_left h).symm
protected theorem dvd_add_right {a b c : Nat} (h : a b) : a b + c ↔ a c := (Nat.dvd_add_iff_right h).symm
theorem add_mod_eq_add_mod_right (c : Nat) (H : a % d = b % d) : (a + c) % d = (b + c) % d := by
rw [← mod_add_mod, ← mod_add_mod b, H]
theorem add_mod_eq_add_mod_left (c : Nat) (H : a % d = b % d) : (c + a) % d = (c + b) % d := by
rw [Nat.add_comm, add_mod_eq_add_mod_right _ H, Nat.add_comm]
theorem mul_dvd_of_dvd_div {a b c : Nat} (hcb : c b) (h : a b / c) : c * a b :=
have ⟨d, hd⟩ := h
⟨d, by simpa [Nat.mul_comm, Nat.mul_left_comm] using Nat.eq_mul_of_div_eq_left hcb hd⟩
theorem eq_of_dvd_of_div_eq_one (hab : a b) (h : b / a = 1) : a = b := by
rw [← Nat.div_mul_cancel hab, h, Nat.one_mul]
theorem eq_zero_of_dvd_of_div_eq_zero (hab : a b) (h : b / a = 0) : b = 0 := by
rw [← Nat.div_mul_cancel hab, h, Nat.zero_mul]
theorem lt_mul_div_succ (a : Nat) (hb : 0 < b) : a < b * (a / b + 1) := by
rw [Nat.mul_comm, ← Nat.div_lt_iff_lt_mul hb]
exact lt_succ_self _
theorem mul_add_div {m : Nat} (m_pos : m > 0) (x y : Nat) : (m * x + y) / m = x + y / m := by
match x with
| 0 => simp
| x + 1 =>
rw [Nat.mul_succ, Nat.add_assoc _ m, mul_add_div m_pos x (m+y), div_eq]
simp +arith [m_pos]; rw [Nat.add_comm, Nat.add_sub_cancel]
simp +arith [m_pos]
theorem mul_add_mod (m x y : Nat) : (m * x + y) % m = y % m := by
match x with
@ -952,6 +1553,13 @@ theorem mul_add_mod (m x y : Nat) : (m * x + y) % m = y % m := by
| x + 1 =>
simp [Nat.mul_succ, Nat.add_assoc _ m, mul_add_mod _ x]
-- TODO: make naming and statements consistent across all variations of `mod`, `gcd` etc. across
-- `Nat` and `Int`.
theorem mul_add_mod' (a b c : Nat) : (a * b + c) % b = c % b := by rw [Nat.mul_comm, Nat.mul_add_mod]
theorem mul_add_mod_of_lt {a b c : Nat} (h : c < b) : (a * b + c) % b = c := by
rw [Nat.mul_add_mod', Nat.mod_eq_of_lt h]
@[simp] theorem mod_div_self (m n : Nat) : m % n / n = 0 := by
cases n
· exact (m % 0).div_zero
@ -1009,6 +1617,113 @@ theorem succ_mod_succ_eq_zero_iff {a b : Nat} :
subst h
simp [Nat.add_mul]
theorem dvd_iff_div_mul_eq (n d : Nat) : d n ↔ n / d * d = n :=
⟨fun h => Nat.div_mul_cancel h, fun h => by rw [← h]; exact Nat.dvd_mul_left _ _⟩
theorem dvd_iff_le_div_mul (n d : Nat) : d n ↔ n ≤ n / d * d :=
((dvd_iff_div_mul_eq _ _).trans Nat.le_antisymm_iff).trans (and_iff_right (div_mul_le_self n d))
theorem dvd_iff_dvd_dvd (n d : Nat) : d n ↔ ∀ k : Nat, k d → k n :=
⟨fun h _ hkd => Nat.dvd_trans hkd h, fun h => h _ (Nat.dvd_refl _)⟩
theorem dvd_div_of_mul_dvd {a b c : Nat} (h : a * b c) : b c / a :=
if ha : a = 0 then by simp [ha]
else
have ha : 0 < a := Nat.pos_of_ne_zero ha
have h1 : ∃ d, c = a * b * d := h
let ⟨d, hd⟩ := h1
have h2 : c / a = b * d := Nat.div_eq_of_eq_mul_right ha (by simpa [Nat.mul_assoc] using hd)
show ∃ d, c / a = b * d from ⟨d, h2⟩
@[simp] theorem dvd_div_iff_mul_dvd {a b c : Nat} (hbc : c b) : a b / c ↔ c * a b :=
⟨fun h => mul_dvd_of_dvd_div hbc h, fun h => dvd_div_of_mul_dvd h⟩
theorem dvd_mul_of_div_dvd {a b c : Nat} (h : b a) (hdiv : a / b c) : a b * c := by
obtain ⟨e, rfl⟩ := hdiv
rw [← Nat.mul_assoc, Nat.mul_comm _ (a / b), Nat.div_mul_cancel h]
exact Nat.dvd_mul_right a e
@[simp] theorem div_div_div_eq_div {a b c : Nat} (dvd : b a) (dvd2 : a c) : c / (a / b) / b = c / a :=
match a, b, c with
| 0, _, _ => by simp
| a + 1, 0, _ => by simp at dvd
| a + 1, c + 1, _ => by
have a_split : a + 1 ≠ 0 := succ_ne_zero a
have c_split : c + 1 ≠ 0 := succ_ne_zero c
rcases dvd2 with ⟨k, rfl⟩
rcases dvd with ⟨k2, pr⟩
have k2_nonzero : k2 ≠ 0 := fun k2_zero => by simp [k2_zero] at pr
rw [Nat.mul_div_cancel_left k (Nat.pos_of_ne_zero a_split), pr,
Nat.mul_div_cancel_left k2 (Nat.pos_of_ne_zero c_split), Nat.mul_comm ((c + 1) * k2) k, ←
Nat.mul_assoc k (c + 1) k2, Nat.mul_div_cancel _ (Nat.pos_of_ne_zero k2_nonzero),
Nat.mul_div_cancel _ (Nat.pos_of_ne_zero c_split)]
/-- If a small natural number is divisible by a larger natural number,
the small number is zero. -/
theorem eq_zero_of_dvd_of_lt (w : a b) (h : b < a) : b = 0 :=
Nat.eq_zero_of_dvd_of_div_eq_zero w (by simp [h])
theorem le_of_lt_add_of_dvd {a b : Nat} (h : a < b + n) : n a → n b → a ≤ b := by
rintro ⟨a, rfl⟩ ⟨b, rfl⟩
rw [← mul_succ] at h
exact Nat.mul_le_mul_left _ (Nat.lt_succ_iff.1 <| Nat.lt_of_mul_lt_mul_left h)
/-- `m` is not divisible by `n` if it is between `n * k` and `n * (k + 1)` for some `k`. -/
theorem not_dvd_of_lt_of_lt_mul_succ (h1 : n * k < m) (h2 : m < n * (k + 1)) : ¬n m := by
rintro ⟨d, rfl⟩
have := Nat.lt_of_mul_lt_mul_left h1
have := Nat.lt_of_mul_lt_mul_left h2
omega
/-- `n` is not divisible by `a` iff it is between `a * k` and `a * (k + 1)` for some `k`. -/
theorem not_dvd_iff_lt_mul_succ (n : Nat) {a : Nat} (ha : 0 < a) :
¬a n ↔ (∃ k : Nat, a * k < n ∧ n < a * (k + 1)) := by
refine Iff.symm
⟨fun ⟨k, hk1, hk2⟩ => not_dvd_of_lt_of_lt_mul_succ hk1 hk2, fun han =>
⟨n / a, ⟨Nat.lt_of_le_of_ne (mul_div_le n a) ?_, lt_mul_div_succ _ ha⟩⟩⟩
exact mt (⟨n / a, Eq.symm ·⟩) han
theorem div_lt_div_of_lt_of_dvd {a b d : Nat} (hdb : d b) (h : a < b) : a / d < b / d := by
rw [Nat.lt_div_iff_mul_lt' hdb]
exact Nat.lt_of_le_of_lt (mul_div_le a d) h
/-! ### shiftLeft and shiftRight -/
@[simp] theorem shiftLeft_zero : n <<< 0 = n := rfl
/-- Shiftleft on successor with multiple moved inside. -/
theorem shiftLeft_succ_inside (m n : Nat) : m <<< (n+1) = (2*m) <<< n := rfl
/-- Shiftleft on successor with multiple moved to outside. -/
theorem shiftLeft_succ : ∀(m n), m <<< (n + 1) = 2 * (m <<< n)
| _, 0 => rfl
| _, k + 1 => by
rw [shiftLeft_succ_inside _ (k+1)]
rw [shiftLeft_succ _ k, shiftLeft_succ_inside]
/-- Shiftright on successor with division moved inside. -/
theorem shiftRight_succ_inside : ∀m n, m >>> (n+1) = (m/2) >>> n
| _, 0 => rfl
| _, k + 1 => by
rw [shiftRight_succ _ (k+1)]
rw [shiftRight_succ_inside _ k, shiftRight_succ]
@[simp] theorem zero_shiftLeft : ∀ n, 0 <<< n = 0
| 0 => by simp [shiftLeft]
| n + 1 => by simp [shiftLeft, zero_shiftLeft n, shiftLeft_succ]
@[simp] theorem zero_shiftRight : ∀ n, 0 >>> n = 0
| 0 => by simp [shiftRight]
| n + 1 => by simp [shiftRight, zero_shiftRight n, shiftRight_succ]
theorem shiftLeft_add (m n : Nat) : ∀ k, m <<< (n + k) = (m <<< n) <<< k
| 0 => rfl
| k + 1 => by simp [← Nat.add_assoc, shiftLeft_add _ _ k, shiftLeft_succ]
@[simp] theorem shiftLeft_shiftRight (x n : Nat) : x <<< n >>> n = x := by
rw [Nat.shiftLeft_eq, Nat.shiftRight_eq_div_pow, Nat.mul_div_cancel _ (Nat.two_pow_pos _)]
/-! ### Decidability of predicates -/
instance decidableBallLT :

View file

@ -52,8 +52,8 @@ protected theorem min_le_right (a b : Nat) : min a b ≤ b := by
protected theorem min_le_left (a b : Nat) : min a b ≤ a :=
Nat.min_comm .. ▸ Nat.min_le_right ..
protected theorem min_eq_left {a b : Nat} (h : a ≤ b) : min a b = a := if_pos h
protected theorem min_eq_right {a b : Nat} (h : b ≤ a) : min a b = b :=
@[simp] protected theorem min_eq_left {a b : Nat} (h : a ≤ b) : min a b = a := if_pos h
@[simp] protected theorem min_eq_right {a b : Nat} (h : b ≤ a) : min a b = b :=
Nat.min_comm .. ▸ Nat.min_eq_left h
protected theorem le_min_of_le_of_le {a b c : Nat} : a ≤ b → a ≤ c → a ≤ min b c := by
@ -111,9 +111,9 @@ protected theorem le_max_left (a b : Nat) : a ≤ max a b := by
protected theorem le_max_right (a b : Nat) : b ≤ max a b :=
Nat.max_comm .. ▸ Nat.le_max_left ..
protected theorem max_eq_right {a b : Nat} (h : a ≤ b) : max a b = b := if_pos h
@[simp] protected theorem max_eq_right {a b : Nat} (h : a ≤ b) : max a b = b := if_pos h
protected theorem max_eq_left {a b : Nat} (h : b ≤ a) : max a b = a :=
@[simp] protected theorem max_eq_left {a b : Nat} (h : b ≤ a) : max a b = a :=
Nat.max_comm .. ▸ Nat.max_eq_right h
protected theorem max_le_of_le_of_le {a b c : Nat} : a ≤ c → b ≤ c → max a b ≤ c := by

View file

@ -1666,7 +1666,7 @@ theorem USize.toUInt32_eq (a b : USize) : a.toUInt32 = b.toUInt32 ↔ a % 429496
simp [← UInt32.toNat_inj, ← USize.toNat_inj, USize.toNat_ofNat]
have := Nat.mod_eq_of_lt a.toNat_lt_two_pow_numBits
have := Nat.mod_eq_of_lt b.toNat_lt_two_pow_numBits
cases System.Platform.numBits_eq <;> simp_all
cases System.Platform.numBits_eq <;> simp_all [Nat.mod_eq_of_lt]
theorem UInt8.toUInt16_eq_mod_256_iff (a : UInt8) (b : UInt16) : a.toUInt16 = b % 256 ↔ a = b.toUInt8 := by
simp [← UInt8.toNat_inj, ← UInt16.toNat_inj]
@ -1689,7 +1689,7 @@ theorem UInt32.toUInt64_eq_mod_4294967296_iff (a : UInt32) (b : UInt64) : a.toUI
theorem UInt32.toUSize_eq_mod_4294967296_iff (a : UInt32) (b : USize) : a.toUSize = b % 4294967296 ↔ a = b.toUInt32 := by
simp [← UInt32.toNat_inj, ← USize.toNat_inj, USize.toNat_ofNat]
have := Nat.mod_eq_of_lt b.toNat_lt_two_pow_numBits
cases System.Platform.numBits_eq <;> simp_all
cases System.Platform.numBits_eq <;> simp_all [Nat.mod_eq_of_lt]
theorem USize.toUInt64_eq_mod_usizeSize_iff (a : USize) (b : UInt64) : a.toUInt64 = b % UInt64.ofNat USize.size ↔ a = b.toUSize := by
simp [← USize.toNat_inj, ← UInt64.toNat_inj, USize.size_eq_two_pow]

View file

@ -1717,12 +1717,12 @@ theorem append_eq_append_iff {ws : Vector α n} {xs : Vector α m} {ys : Vector
constructor
· rintro (⟨as, rfl, rfl⟩ | ⟨cs, rfl, rfl⟩)
· rw [dif_pos (by simp)]
exact ⟨as.toVector.cast (by simp; omega), by simp⟩
exact ⟨as.toVector.cast (by simp), by simp⟩
· split <;> rename_i h
· have hc : cs.size = 0 := by simp at h; omega
simp at hc
exact ⟨#v[].cast (by simp; omega), by simp_all⟩
· exact ⟨cs.toVector.cast (by simp; omega), by simp⟩
exact ⟨#v[].cast (by simp), by simp_all⟩
· exact ⟨cs.toVector.cast (by simp), by simp⟩
· split <;> rename_i h
· rintro ⟨as, hc, rfl⟩
left

View file

@ -101,9 +101,8 @@ theorem range'_eq_append_iff : range' s (n + m) = xs ++ ys ↔ xs = range' s n
simp_all
subst w
simp_all
omega
· rintro ⟨h₁, h₂⟩
exact ⟨n, by omega, by simp_all; omega
exact ⟨n, by omega, by simp_all⟩
@[simp] theorem find?_range'_eq_some {s n : Nat} {i : Nat} {p : Nat → Bool} :
(range' s n).find? p = some i ↔ p i ∧ i ∈ range' s n ∧ ∀ j, s ≤ j → j < i → !p j := by

View file

@ -54,7 +54,7 @@ theorem RArray.size_ofFn {n : Nat} (f : Fin n → α) (h : 0 < n) :
where
go lb ub h1 h2 : (ofFn.go f lb ub h1 h2).size = ub - lb := by
induction lb, ub, h1, h2 using RArray.ofFn.go.induct (n := n)
case case1 => simp [ofFn.go, size]; omega
case case1 => simp [ofFn.go, size]
case case2 ih1 ih2 hiu => rw [ofFn.go]; simp +zetaDelta [size, *]; omega
section Meta

View file

@ -78,7 +78,7 @@ private theorem invert_eq_testBit (f : Fanin) : f.invert = f.val.testBit 0 := by
@[simp]
theorem invert_flip (f : Fanin) : (f.flip v).invert = f.invert ^^ v := by
cases v <;> simp [flip, invert_eq_testBit]
cases v <;> simp [flip, invert_eq_testBit, -Nat.mod_two_not_eq_one]
end Fanin

View file

@ -6,7 +6,7 @@ def f : Nat → Nat := fun x => x - x
example (n : Nat) : False := by
let g := f n
have : g + n = n := by
fail_if_success simp (config := { zeta := false }) [Nat.zero_add, -Nat.add_left_eq_self] -- Should not succeed
fail_if_success simp (config := { zeta := false }) [Nat.zero_add, -Nat.add_eq_right] -- Should not succeed
simp [g]
sorry

View file

@ -1,4 +1,4 @@
attribute [-simp] Nat.self_eq_add_right -- This was later added to the simp set and interfere with the test.
attribute [-simp] Nat.left_eq_add -- This was later added to the simp set and interfere with the test.
def foo : Nat := 0
def bar : Nat := 0

View file

@ -1,3 +1,5 @@
attribute [-simp] Nat.default_eq_zero -- undo changes to simp set after this test was written
#check_simp #[1,2,3,4,5][2] ~> 3
#check_simp #[1,2,3,4,5][2]? ~> some 3
#check_simp #[1,2,3,4,5][7]? ~> none

View file

@ -26,7 +26,7 @@ example (x : Nat) : 1 + 1 + f x = x + 2 := by
info: Try these:
• rfl
• simp
• simp only [Nat.succ_eq_add_one]
• simp only [Nat.succ_eq_add_one, Nat.add_left_cancel_iff]
• grind
• grind only
-/
@ -38,7 +38,7 @@ example (x : Nat) : x + 1 = Nat.succ x := by
info: Try these:
• · intros; rfl
• · intros; simp
• · intros; simp only [Nat.succ_eq_add_one]
• · intros; simp only [Nat.succ_eq_add_one, Nat.add_left_cancel_iff]
• · intros; grind
• · intros; grind only
-/

View file

@ -3,7 +3,7 @@ def f (x : Nat) := x + 1
theorem f_eq (x : Nat) : f (x + 1) = x + 2 := rfl
theorem ex1 : f (f (x + 1)) = x + 3 := by
simp -implicitDefEqProofs [f_eq]
simp -implicitDefEqProofs only [f_eq]
/--
info: theorem ex1 : ∀ {x : Nat}, f (f (x + 1)) = x + 3 :=
@ -15,7 +15,7 @@ fun {x} =>
#print ex1
theorem ex2 : f (f (x + 1)) = x + 3 := by
simp +implicitDefEqProofs [f_eq]
simp +implicitDefEqProofs only [f_eq]
/--
info: theorem ex2 : ∀ {x : Nat}, f (f (x + 1)) = x + 3 :=

View file

@ -1,4 +1,4 @@
attribute [-simp] Nat.add_left_eq_self -- This was later added to the simp set and interfere with the test.
attribute [-simp] Nat.add_eq_right -- This was later added to the simp set and interfere with the test.
example (a : Nat) : let n := 0; n + a = a := by
intro n

View file

@ -49,7 +49,7 @@ theorem ex8 (y x : Nat) : y = 0 → x + y = 0 → x = 0 := by
simp (config := { contextual := true })
theorem ex9 (y x : Nat) : y = 0 → x + y = 0 → x = 0 := by
fail_if_success simp [-Nat.add_eq_zero_iff]
fail_if_success simp [-Nat.add_eq_zero]
intro h₁ h₂
simp [h₁] at h₂
simp [h₂]

View file

@ -20,7 +20,7 @@ h₂ : g x < 5
-/
#guard_msgs in
theorem ex3 (x y : Nat) (h₁ : f x x = g x) (h₂ : f x x < 5) : f x x + f x x = 0 := by
simp [*, -Nat.add_eq_zero_iff] at *
simp [*, -Nat.add_eq_zero] at *
trace_state
have aux₁ : f x x = g x := h₁
have aux₂ : g x < 5 := h₂

View file

@ -1,6 +1,9 @@
set_option tactic.simp.trace true
set_option trace.Meta.Tactic.simp.rewrite true
-- These lemmas were subsequently added to the simp set and confuse the test.
attribute [-simp] Nat.add_left_cancel_iff Nat.add_right_cancel_iff Nat.sub_eq_zero_of_le Nat.add_eq_left Nat.add_eq_right
def f (x : α) := x
example (a : α) (b : List α) : f (a::b = []) = False :=
@ -84,8 +87,6 @@ example : x - 1 + 1 = x := by simp (discharger := sorry) [Nat.sub_add_cancel]
-- The following examples test simplification at hypotheses.
section
-- These lemmas were subsequently added to the simp set and confuse the test.
attribute [-simp] Nat.add_left_eq_self Nat.add_right_eq_self
-- Two simp lemmas applied to one hypothesis.
example (h' : bla x = x) : x + x = x := by

View file

@ -96,7 +96,7 @@ Try this: simp (discharger := sorry) only [Nat.sub_add_cancel]
==>
x
[Meta.Tactic.simp.rewrite] eq_self:1000: x = x ==> True
simp_trace.lean:83:0-83:7: warning: declaration uses 'sorry'
simp_trace.lean:86:0-86:7: warning: declaration uses 'sorry'
Try this: simp only [bla, h] at *
[Meta.Tactic.simp.rewrite] unfold bla, bla x ==> match h x with
| Sum.inl (y, z) => y + z
@ -108,7 +108,7 @@ Try this: simp only [bla, h] at h'
| Sum.inr val => 0
[Meta.Tactic.simp.rewrite] unfold h, h x ==> Sum.inl (x, x)
Try this: simp only [bla, h, List.length_append] at *
simp_trace.lean:102:101-103:40: error: unsolved goals
simp_trace.lean:103:101-104:40: error: unsolved goals
x y : Nat
α : Type
xs ys : List α
@ -121,7 +121,7 @@ h₂ : xs.length + ys.length = y
[Meta.Tactic.simp.rewrite] unfold h, h x ==> Sum.inl (x, x)
[Meta.Tactic.simp.rewrite] List.length_append:1000: (xs ++ ys).length ==> xs.length + ys.length
Try this: simp only [bla, h, List.length_append] at *
simp_trace.lean:106:101-107:53: error: unsolved goals
simp_trace.lean:107:101-108:53: error: unsolved goals
x y : Nat
α : Type
xs ys : List α

View file

@ -1,6 +1,8 @@
import Lean
import UserAttr.BlaAttr
attribute [-simp] Nat.add_left_cancel_iff Nat.add_right_cancel_iff
@[bla] def f (x : Nat) := x + 2
@[bla] def g (x : Nat) := x + 1