data.nat.basicMathlib.Data.Nat.Defs

This file has been ported!

Changes since the initial port

The following section lists changes to this file in mathlib3 and mathlib4 that occured after the initial port. Most recent changes are shown first. Hovering over a commit will show all commits associated with the same mathlib3 commit.

Changes in mathlib3

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(last sync)

feat(logic/equiv/fin): div/mod as an equivalence on nat/int (#18359)

The motivation here is to be able to use this to change a sum/product/supr/infi/tsum/etc to be indexed by a product, such that every nth term can be collected into an inner / outer sum. We already have the API in most places for equivs and prods to do this, all that's missing is the equivalences in this PR.

Note that we use [ne_zero n] instead of hn : n ≠ 0 as this is required by fin.of_nat' for the coercion.

Zulip

Co-authored-by: Junyan Xu <junyanxumath@gmail.com>

Diff
@@ -543,6 +543,7 @@ by { rw mul_comm, exact mod_add_div _ _ }
 lemma div_add_mod' (m k : ℕ) : (m / k) * k + m % k = m :=
 by { rw mul_comm, exact div_add_mod _ _ }
 
+/-- See also `nat.div_mod_equiv` for a similar statement as an `equiv`. -/
 protected theorem div_mod_unique {n k m d : ℕ} (h : 0 < k) :
   n / k = d ∧ n % k = m ↔ m + k * d = n ∧ m < k :=
 ⟨λ ⟨e₁, e₂⟩, e₁ ▸ e₂ ▸ ⟨mod_add_div _ _, mod_lt _ h⟩,

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

chore(data/nat/digits): golf, use seemingly weaker assumptions (#18203)
Diff
@@ -210,18 +210,14 @@ by { rw ←not_iff_not, push_neg, exact forall_lt_succ }
 @[simp] theorem add_def {a b : ℕ} : nat.add a b = a + b := rfl
 @[simp] theorem mul_def {a b : ℕ} : nat.mul a b = a * b := rfl
 
-lemma exists_eq_add_of_le : ∀ {m n : ℕ}, m ≤ n → ∃ k : ℕ, n = m + k
-| 0 0 h := ⟨0, by simp⟩
-| 0 (n+1) h := ⟨n+1, by simp⟩
-| (m+1) (n+1) h :=
-  let ⟨k, hk⟩ := exists_eq_add_of_le (nat.le_of_succ_le_succ h) in
-  ⟨k, by simp [hk, add_comm, add_left_comm]⟩
-
-lemma exists_eq_add_of_lt : ∀ {m n : ℕ}, m < n → ∃ k : ℕ, n = m + k + 1
-| 0 0 h := false.elim $ lt_irrefl _ h
-| 0 (n+1) h := ⟨n, by simp⟩
-| (m+1) (n+1) h := let ⟨k, hk⟩ := exists_eq_add_of_le (nat.le_of_succ_le_succ h) in
-  ⟨k, by simp [hk]⟩
+lemma exists_eq_add_of_le (h : m ≤ n) : ∃ k : ℕ, n = m + k :=
+⟨n - m, (nat.add_sub_of_le h).symm⟩
+
+lemma exists_eq_add_of_le' (h : m ≤ n) : ∃ k : ℕ, n = k + m :=
+⟨n - m, (nat.sub_add_cancel h).symm⟩
+
+lemma exists_eq_add_of_lt (h : m < n) : ∃ k : ℕ, n = m + k + 1 :=
+⟨n - (m + 1), by rw [add_right_comm, nat.add_sub_of_le h]⟩
 
 /-! ### `pred` -/
 

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

refactor(algebra/group_with_zero/defs): use is_*cancel_mul_zero (#17963)
Diff
@@ -79,15 +79,10 @@ instance : semiring ℕ                     := infer_instance
 
 protected lemma nat.nsmul_eq_mul (m n : ℕ) : m • n = m * n := rfl
 
-theorem nat.eq_of_mul_eq_mul_right {n m k : ℕ} (Hm : 0 < m) (H : n * m = k * m) : n = k :=
-by rw [mul_comm n m, mul_comm k m] at H; exact nat.eq_of_mul_eq_mul_left Hm H
-
 instance nat.cancel_comm_monoid_with_zero : cancel_comm_monoid_with_zero ℕ :=
 { mul_left_cancel_of_ne_zero :=
     λ _ _ _ h1 h2, nat.eq_of_mul_eq_mul_left (nat.pos_of_ne_zero h1) h2,
-  mul_right_cancel_of_ne_zero :=
-    λ _ _ _ h1 h2, nat.eq_of_mul_eq_mul_right (nat.pos_of_ne_zero h1) h2,
-  .. (infer_instance : comm_monoid_with_zero ℕ) }
+  .. nat.comm_semiring }
 
 attribute [simp] nat.not_lt_zero nat.succ_ne_zero nat.succ_ne_self
   nat.zero_ne_one nat.one_ne_zero

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(first ported)

Changes in mathlib3port

mathlib3
mathlib3port
Diff
@@ -105,12 +105,12 @@ protected theorem Nat.nsmul_eq_mul (m n : ℕ) : m • n = m * n :=
 #align nat.nsmul_eq_mul Nat.nsmul_eq_mul
 -/
 
-#print Nat.cancelCommMonoidWithZero /-
-instance Nat.cancelCommMonoidWithZero : CancelCommMonoidWithZero ℕ :=
+#print Nat.instCancelCommMonoidWithZero /-
+instance Nat.instCancelCommMonoidWithZero : CancelCommMonoidWithZero ℕ :=
   { Nat.commSemiring with
     hMul_left_cancel_of_ne_zero := fun _ _ _ h1 h2 =>
       Nat.eq_of_mul_eq_mul_left (Nat.pos_of_ne_zero h1) h2 }
-#align nat.cancel_comm_monoid_with_zero Nat.cancelCommMonoidWithZero
+#align nat.cancel_comm_monoid_with_zero Nat.instCancelCommMonoidWithZero
 -/
 
 attribute [simp] Nat.not_lt_zero Nat.succ_ne_zero Nat.succ_ne_self Nat.zero_ne_one Nat.one_ne_zero
Diff
@@ -222,7 +222,7 @@ theorem succ_max_succ {m n : ℕ} : max (succ m) (succ n) = succ (max m n) :=
   by
   by_cases h1 : m ≤ n
   rw [max_eq_right h1, max_eq_right (succ_le_succ h1)]
-  · rw [not_le] at h1 ; have h2 := le_of_lt h1
+  · rw [not_le] at h1; have h2 := le_of_lt h1
     rw [max_eq_left h2, max_eq_left (succ_le_succ h2)]
 #align nat.max_succ_succ Nat.succ_max_succ
 -/
@@ -440,7 +440,7 @@ theorem mul_ne_mul_right {a b c : ℕ} (ha : 0 < a) : a * b ≠ a * c ↔ b ≠
 
 #print Nat.mul_right_eq_self_iff /-
 theorem mul_right_eq_self_iff {a b : ℕ} (ha : 0 < a) : a * b = a ↔ b = 1 :=
-  suffices a * b = a * 1 ↔ b = 1 by rwa [mul_one] at this 
+  suffices a * b = a * 1 ↔ b = 1 by rwa [mul_one] at this
   mul_right_inj' ha.ne'
 #align nat.mul_right_eq_self_iff Nat.mul_right_eq_self_iff
 -/
@@ -538,8 +538,8 @@ theorem leRecOn_succ_left {C : ℕ → Sort u} {n m} (h1 : n ≤ m) (h2 : n + 1
 theorem leRecOn_injective {C : ℕ → Sort u} {n m} (hnm : n ≤ m) (next : ∀ n, C n → C (n + 1))
     (Hnext : ∀ n, Function.Injective (next n)) : Function.Injective (leRecOn hnm next) :=
   by
-  induction' hnm with m hnm ih; · intro x y H; rwa [le_rec_on_self, le_rec_on_self] at H 
-  intro x y H; rw [le_rec_on_succ hnm, le_rec_on_succ hnm] at H ; exact ih (Hnext _ H)
+  induction' hnm with m hnm ih; · intro x y H; rwa [le_rec_on_self, le_rec_on_self] at H
+  intro x y H; rw [le_rec_on_succ hnm, le_rec_on_succ hnm] at H; exact ih (Hnext _ H)
 #align nat.le_rec_on_injective Nat.leRecOn_injective
 -/
 
@@ -925,7 +925,7 @@ theorem mod_mod (a n : ℕ) : a % n % n = a % n :=
 @[simp]
 theorem mod_add_mod (m n k : ℕ) : (m % n + k) % n = (m + k) % n := by
   have := (add_mul_mod_self_left (m % n + k) n (m / n)).symm <;>
-    rwa [add_right_comm, mod_add_div] at this 
+    rwa [add_right_comm, mod_add_div] at this
 #align nat.mod_add_mod Nat.mod_add_mod
 -/
 
Diff
@@ -1183,12 +1183,12 @@ instance decidableForallFin {n : ℕ} (P : Fin n → Prop) [H : DecidablePred P]
 #align nat.decidable_forall_fin Nat.decidableForallFin
 -/
 
-#print Nat.decidableBallLe /-
-instance decidableBallLe (n : ℕ) (P : ∀ k ≤ n, Prop) [H : ∀ n h, Decidable (P n h)] :
+#print Nat.decidableBallLE /-
+instance decidableBallLE (n : ℕ) (P : ∀ k ≤ n, Prop) [H : ∀ n h, Decidable (P n h)] :
     Decidable (∀ n h, P n h) :=
   decidable_of_iff (∀ (k) (h : k < succ n), P k (le_of_lt_succ h))
     ⟨fun a k h => a k (lt_succ_of_le h), fun a k h => a k _⟩
-#align nat.decidable_ball_le Nat.decidableBallLe
+#align nat.decidable_ball_le Nat.decidableBallLE
 -/
 
 #print Nat.decidableExistsLT /-
@@ -1201,11 +1201,11 @@ instance decidableExistsLT {P : ℕ → Prop} [h : DecidablePred P] :
 #align nat.decidable_exists_lt Nat.decidableExistsLT
 -/
 
-#print Nat.decidableExistsLe /-
-instance decidableExistsLe {P : ℕ → Prop} [h : DecidablePred P] :
+#print Nat.decidableExistsLE /-
+instance decidableExistsLE {P : ℕ → Prop} [h : DecidablePred P] :
     DecidablePred fun n => ∃ m : ℕ, m ≤ n ∧ P m := fun n =>
   decidable_of_iff (∃ m, m < n + 1 ∧ P m) (exists_congr fun x => and_congr_left' lt_succ_iff)
-#align nat.decidable_exists_le Nat.decidableExistsLe
+#align nat.decidable_exists_le Nat.decidableExistsLE
 -/
 
 end Nat
Diff
@@ -180,10 +180,10 @@ theorem succ_pos' {n : ℕ} : 0 < succ n :=
 #align nat.succ_pos' Nat.succ_pos'
 -/
 
-#print Nat.succ_inj' /-
-theorem succ_inj' {n m : ℕ} : succ n = succ m ↔ n = m :=
+#print Nat.succ_inj /-
+theorem succ_inj {n m : ℕ} : succ n = succ m ↔ n = m :=
   ⟨succ.inj, congr_arg _⟩
-#align nat.succ_inj' Nat.succ_inj'
+#align nat.succ_inj' Nat.succ_inj
 -/
 
 #print Nat.succ_injective /-
Diff
@@ -1013,14 +1013,14 @@ theorem lt_mul_div_succ (m : ℕ) {n : ℕ} (n0 : 0 < n) : m < n * (m / n + 1) :
 #align nat.lt_mul_div_succ Nat.lt_mul_div_succ
 -/
 
-#print Nat.mul_add_mod /-
-theorem mul_add_mod (a b c : ℕ) : (a * b + c) % b = c % b := by simp [Nat.add_mod]
-#align nat.mul_add_mod Nat.mul_add_mod
+#print Nat.mul_add_mod' /-
+theorem mul_add_mod' (a b c : ℕ) : (a * b + c) % b = c % b := by simp [Nat.add_mod]
+#align nat.mul_add_mod Nat.mul_add_mod'
 -/
 
 #print Nat.mul_add_mod_of_lt /-
 theorem mul_add_mod_of_lt {a b c : ℕ} (h : c < b) : (a * b + c) % b = c := by
-  rw [Nat.mul_add_mod, Nat.mod_eq_of_lt h]
+  rw [Nat.mul_add_mod', Nat.mod_eq_of_lt h]
 #align nat.mul_add_mod_of_lt Nat.mul_add_mod_of_lt
 -/
 
Diff
@@ -217,14 +217,14 @@ theorem succ_le_succ_iff {m n : ℕ} : succ m ≤ succ n ↔ m ≤ n :=
 #align nat.succ_le_succ_iff Nat.succ_le_succ_iff
 -/
 
-#print Nat.max_succ_succ /-
-theorem max_succ_succ {m n : ℕ} : max (succ m) (succ n) = succ (max m n) :=
+#print Nat.succ_max_succ /-
+theorem succ_max_succ {m n : ℕ} : max (succ m) (succ n) = succ (max m n) :=
   by
   by_cases h1 : m ≤ n
   rw [max_eq_right h1, max_eq_right (succ_le_succ h1)]
   · rw [not_le] at h1 ; have h2 := le_of_lt h1
     rw [max_eq_left h2, max_eq_left (succ_le_succ h2)]
-#align nat.max_succ_succ Nat.max_succ_succ
+#align nat.max_succ_succ Nat.succ_max_succ
 -/
 
 #print Nat.not_succ_lt_self /-
Diff
@@ -802,11 +802,13 @@ protected theorem mul_div_cancel_left' {a b : ℕ} (Hd : a ∣ b) : a * (b / a)
 #align nat.mul_div_cancel_left' Nat.mul_div_cancel_left'
 -/
 
+/- warning: nat.mul_div_mul_left clashes with nat.mul_div_mul -> Nat.mul_div_mul_left
+Case conversion may be inaccurate. Consider using '#align nat.mul_div_mul_left Nat.mul_div_mul_leftₓ'. -/
 #print Nat.mul_div_mul_left /-
 --TODO: Update `nat.mul_div_mul` in the core?
 /-- Alias of `nat.mul_div_mul` -/
 protected theorem mul_div_mul_left (a b : ℕ) {c : ℕ} (hc : 0 < c) : c * a / (c * b) = a / b :=
-  Nat.mul_div_mul a b hc
+  Nat.mul_div_mul_left a b hc
 #align nat.mul_div_mul_left Nat.mul_div_mul_left
 -/
 
Diff
@@ -3,9 +3,9 @@ Copyright (c) 2014 Floris van Doorn (c) 2016 Microsoft Corporation. All rights r
 Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Floris van Doorn, Leonardo de Moura, Jeremy Avigad, Mario Carneiro
 -/
-import Mathbin.Order.Basic
-import Mathbin.Algebra.GroupWithZero.Basic
-import Mathbin.Algebra.Ring.Defs
+import Order.Basic
+import Algebra.GroupWithZero.Basic
+import Algebra.Ring.Defs
 
 #align_import data.nat.basic from "leanprover-community/mathlib"@"bd835ef554f37ef9b804f0903089211f89cb370b"
 
Diff
@@ -108,7 +108,7 @@ protected theorem Nat.nsmul_eq_mul (m n : ℕ) : m • n = m * n :=
 #print Nat.cancelCommMonoidWithZero /-
 instance Nat.cancelCommMonoidWithZero : CancelCommMonoidWithZero ℕ :=
   { Nat.commSemiring with
-    mul_left_cancel_of_ne_zero := fun _ _ _ h1 h2 =>
+    hMul_left_cancel_of_ne_zero := fun _ _ _ h1 h2 =>
       Nat.eq_of_mul_eq_mul_left (Nat.pos_of_ne_zero h1) h2 }
 #align nat.cancel_comm_monoid_with_zero Nat.cancelCommMonoidWithZero
 -/
Diff
@@ -2,16 +2,13 @@
 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: Floris van Doorn, Leonardo de Moura, Jeremy Avigad, Mario Carneiro
-
-! This file was ported from Lean 3 source module data.nat.basic
-! leanprover-community/mathlib commit bd835ef554f37ef9b804f0903089211f89cb370b
-! Please do not edit these lines, except to modify the commit id
-! if you have ported upstream changes.
 -/
 import Mathbin.Order.Basic
 import Mathbin.Algebra.GroupWithZero.Basic
 import Mathbin.Algebra.Ring.Defs
 
+#align_import data.nat.basic from "leanprover-community/mathlib"@"bd835ef554f37ef9b804f0903089211f89cb370b"
+
 /-!
 # Basic operations on the natural numbers
 
Diff
@@ -220,6 +220,7 @@ theorem succ_le_succ_iff {m n : ℕ} : succ m ≤ succ n ↔ m ≤ n :=
 #align nat.succ_le_succ_iff Nat.succ_le_succ_iff
 -/
 
+#print Nat.max_succ_succ /-
 theorem max_succ_succ {m n : ℕ} : max (succ m) (succ n) = succ (max m n) :=
   by
   by_cases h1 : m ≤ n
@@ -227,6 +228,7 @@ theorem max_succ_succ {m n : ℕ} : max (succ m) (succ n) = succ (max m n) :=
   · rw [not_le] at h1 ; have h2 := le_of_lt h1
     rw [max_eq_left h2, max_eq_left (succ_le_succ h2)]
 #align nat.max_succ_succ Nat.max_succ_succ
+-/
 
 #print Nat.not_succ_lt_self /-
 theorem not_succ_lt_self {n : ℕ} : ¬succ n < n :=
@@ -313,9 +315,11 @@ theorem forall_lt_succ {P : ℕ → Prop} {n : ℕ} : (∀ m < n + 1, P m) ↔ (
 #align nat.forall_lt_succ Nat.forall_lt_succ
 -/
 
+#print Nat.exists_lt_succ /-
 theorem exists_lt_succ {P : ℕ → Prop} {n : ℕ} : (∃ m < n + 1, P m) ↔ (∃ m < n, P m) ∨ P n := by
   rw [← not_iff_not]; push_neg; exact forall_lt_succ
 #align nat.exists_lt_succ Nat.exists_lt_succ
+-/
 
 /-! ### `add` -/
 
@@ -394,9 +398,11 @@ theorem pred_sub (n m : ℕ) : pred n - m = pred (n - m) := by
 #align nat.pred_sub Nat.pred_sub
 -/
 
+#print Nat.le_pred_of_lt /-
 theorem le_pred_of_lt {n m : ℕ} (h : m < n) : m ≤ n - 1 :=
   Nat.sub_le_sub_right h 1
 #align nat.le_pred_of_lt Nat.le_pred_of_lt
+-/
 
 #print Nat.le_of_pred_lt /-
 theorem le_of_pred_lt {m n : ℕ} : pred m < n → m ≤ n :=
@@ -572,11 +578,13 @@ theorem strongRecOn'_beta {P : ℕ → Sort _} {h} {n : ℕ} :
 #align nat.strong_rec_on_beta' Nat.strongRecOn'_beta
 -/
 
+#print Nat.le_induction /-
 /-- Induction principle starting at a non-zero number. For maps to a `Sort*` see `le_rec_on`. -/
 @[elab_as_elim]
 theorem le_induction {P : Nat → Prop} {m} (h0 : P m) (h1 : ∀ n, m ≤ n → P n → P (n + 1)) :
     ∀ n, m ≤ n → P n := by apply Nat.le.ndrec h0 <;> exact h1
 #align nat.le_induction Nat.le_induction
+-/
 
 #print Nat.decreasingInduction /-
 /-- Decreasing induction: if `P (k+1)` implies `P k`, then `P n` implies `P m` for all `m ≤ n`.
@@ -797,15 +805,19 @@ protected theorem mul_div_cancel_left' {a b : ℕ} (Hd : a ∣ b) : a * (b / a)
 #align nat.mul_div_cancel_left' Nat.mul_div_cancel_left'
 -/
 
+#print Nat.mul_div_mul_left /-
 --TODO: Update `nat.mul_div_mul` in the core?
 /-- Alias of `nat.mul_div_mul` -/
 protected theorem mul_div_mul_left (a b : ℕ) {c : ℕ} (hc : 0 < c) : c * a / (c * b) = a / b :=
   Nat.mul_div_mul a b hc
 #align nat.mul_div_mul_left Nat.mul_div_mul_left
+-/
 
+#print Nat.mul_div_mul_right /-
 protected theorem mul_div_mul_right (a b : ℕ) {c : ℕ} (hc : 0 < c) : a * c / (b * c) = a / b := by
   rw [mul_comm, mul_comm b, a.mul_div_mul_left b hc]
 #align nat.mul_div_mul_right Nat.mul_div_mul_right
+-/
 
 #print Nat.lt_div_mul_add /-
 theorem lt_div_mul_add {a b : ℕ} (hb : 0 < b) : a < a / b * b + b :=
@@ -1036,16 +1048,20 @@ theorem find_eq_iff (h : ∃ n : ℕ, p n) : Nat.find h = m ↔ p m ∧ ∀ n <
 #align nat.find_eq_iff Nat.find_eq_iff
 -/
 
+#print Nat.find_lt_iff /-
 @[simp]
 theorem find_lt_iff (h : ∃ n : ℕ, p n) (n : ℕ) : Nat.find h < n ↔ ∃ m < n, p m :=
   ⟨fun h2 => ⟨Nat.find h, h2, Nat.find_spec h⟩, fun ⟨m, hmn, hm⟩ =>
     (Nat.find_min' h hm).trans_lt hmn⟩
 #align nat.find_lt_iff Nat.find_lt_iff
+-/
 
+#print Nat.find_le_iff /-
 @[simp]
 theorem find_le_iff (h : ∃ n : ℕ, p n) (n : ℕ) : Nat.find h ≤ n ↔ ∃ m ≤ n, p m := by
   simp only [exists_prop, ← lt_succ_iff, find_lt_iff]
 #align nat.find_le_iff Nat.find_le_iff
+-/
 
 #print Nat.le_find_iff /-
 @[simp]
Diff
@@ -747,8 +747,7 @@ protected theorem div_pos {a b : ℕ} (hba : b ≤ a) (hb : 0 < b) : 0 < a / b :
       (calc
         a = a % b := by simpa [h] using (mod_add_div a b).symm
         _ < b := (Nat.mod_lt a hb)
-        _ ≤ a := hba
-        )
+        _ ≤ a := hba)
 #align nat.div_pos Nat.div_pos
 -/
 
Diff
@@ -116,8 +116,9 @@ instance Nat.cancelCommMonoidWithZero : CancelCommMonoidWithZero ℕ :=
 #align nat.cancel_comm_monoid_with_zero Nat.cancelCommMonoidWithZero
 -/
 
-attribute [simp]
-  Nat.not_lt_zero Nat.succ_ne_zero Nat.succ_ne_self Nat.zero_ne_one Nat.one_ne_zero Nat.zero_ne_bit1 Nat.bit1_ne_zero Nat.bit0_ne_one Nat.one_ne_bit0 Nat.bit0_ne_bit1 Nat.bit1_ne_bit0
+attribute [simp] Nat.not_lt_zero Nat.succ_ne_zero Nat.succ_ne_self Nat.zero_ne_one Nat.one_ne_zero
+  Nat.zero_ne_bit1 Nat.bit1_ne_zero Nat.bit0_ne_one Nat.one_ne_bit0 Nat.bit0_ne_bit1
+  Nat.bit1_ne_bit0
 
 variable {m n k : ℕ}
 
@@ -139,7 +140,7 @@ theorem and_forall_succ {p : ℕ → Prop} : (p 0 ∧ ∀ n, p (n + 1)) ↔ ∀
 @[simp]
 theorem or_exists_succ {p : ℕ → Prop} : (p 0 ∨ ∃ n, p (n + 1)) ↔ ∃ n, p n :=
   ⟨fun h => h.elim (fun h0 => ⟨0, h0⟩) fun ⟨n, hn⟩ => ⟨n + 1, hn⟩, by rintro ⟨_ | n, hn⟩;
-    exacts[Or.inl hn, Or.inr ⟨n, hn⟩]⟩
+    exacts [Or.inl hn, Or.inr ⟨n, hn⟩]⟩
 #align nat.or_exists_succ Nat.or_exists_succ
 -/
 
@@ -223,7 +224,7 @@ theorem max_succ_succ {m n : ℕ} : max (succ m) (succ n) = succ (max m n) :=
   by
   by_cases h1 : m ≤ n
   rw [max_eq_right h1, max_eq_right (succ_le_succ h1)]
-  · rw [not_le] at h1; have h2 := le_of_lt h1
+  · rw [not_le] at h1 ; have h2 := le_of_lt h1
     rw [max_eq_left h2, max_eq_left (succ_le_succ h2)]
 #align nat.max_succ_succ Nat.max_succ_succ
 
@@ -436,7 +437,7 @@ theorem mul_ne_mul_right {a b c : ℕ} (ha : 0 < a) : a * b ≠ a * c ↔ b ≠
 
 #print Nat.mul_right_eq_self_iff /-
 theorem mul_right_eq_self_iff {a b : ℕ} (ha : 0 < a) : a * b = a ↔ b = 1 :=
-  suffices a * b = a * 1 ↔ b = 1 by rwa [mul_one] at this
+  suffices a * b = a * 1 ↔ b = 1 by rwa [mul_one] at this 
   mul_right_inj' ha.ne'
 #align nat.mul_right_eq_self_iff Nat.mul_right_eq_self_iff
 -/
@@ -534,8 +535,8 @@ theorem leRecOn_succ_left {C : ℕ → Sort u} {n m} (h1 : n ≤ m) (h2 : n + 1
 theorem leRecOn_injective {C : ℕ → Sort u} {n m} (hnm : n ≤ m) (next : ∀ n, C n → C (n + 1))
     (Hnext : ∀ n, Function.Injective (next n)) : Function.Injective (leRecOn hnm next) :=
   by
-  induction' hnm with m hnm ih; · intro x y H; rwa [le_rec_on_self, le_rec_on_self] at H
-  intro x y H; rw [le_rec_on_succ hnm, le_rec_on_succ hnm] at H; exact ih (Hnext _ H)
+  induction' hnm with m hnm ih; · intro x y H; rwa [le_rec_on_self, le_rec_on_self] at H 
+  intro x y H; rw [le_rec_on_succ hnm, le_rec_on_succ hnm] at H ; exact ih (Hnext _ H)
 #align nat.le_rec_on_injective Nat.leRecOn_injective
 -/
 
@@ -914,7 +915,7 @@ theorem mod_mod (a n : ℕ) : a % n % n = a % n :=
 @[simp]
 theorem mod_add_mod (m n k : ℕ) : (m % n + k) % n = (m + k) % n := by
   have := (add_mul_mod_self_left (m % n + k) n (m / n)).symm <;>
-    rwa [add_right_comm, mod_add_div] at this
+    rwa [add_right_comm, mod_add_div] at this 
 #align nat.mod_add_mod Nat.mod_add_mod
 -/
 
@@ -1086,7 +1087,7 @@ theorem find_comp_succ (h₁ : ∃ n, p n) (h₂ : ∃ n, p (n + 1)) (h0 : ¬p 0
   by
   refine' (find_eq_iff _).2 ⟨Nat.find_spec h₂, fun n hn => _⟩
   cases' n with n
-  exacts[h0, @Nat.find_min (fun n => p (n + 1)) _ h₂ _ (succ_lt_succ_iff.1 hn)]
+  exacts [h0, @Nat.find_min (fun n => p (n + 1)) _ h₂ _ (succ_lt_succ_iff.1 hn)]
 #align nat.find_comp_succ Nat.find_comp_succ
 -/
 
Diff
@@ -219,12 +219,6 @@ theorem succ_le_succ_iff {m n : ℕ} : succ m ≤ succ n ↔ m ≤ n :=
 #align nat.succ_le_succ_iff Nat.succ_le_succ_iff
 -/
 
-/- warning: nat.max_succ_succ -> Nat.max_succ_succ is a dubious translation:
-lean 3 declaration is
-  forall {m : Nat} {n : Nat}, Eq.{1} Nat (LinearOrder.max.{0} Nat Nat.linearOrder (Nat.succ m) (Nat.succ n)) (Nat.succ (LinearOrder.max.{0} Nat Nat.linearOrder m n))
-but is expected to have type
-  forall {m : Nat} {n : Nat}, Eq.{1} Nat (Max.max.{0} Nat Nat.instMaxNat (Nat.succ m) (Nat.succ n)) (Nat.succ (Max.max.{0} Nat Nat.instMaxNat m n))
-Case conversion may be inaccurate. Consider using '#align nat.max_succ_succ Nat.max_succ_succₓ'. -/
 theorem max_succ_succ {m n : ℕ} : max (succ m) (succ n) = succ (max m n) :=
   by
   by_cases h1 : m ≤ n
@@ -318,12 +312,6 @@ theorem forall_lt_succ {P : ℕ → Prop} {n : ℕ} : (∀ m < n + 1, P m) ↔ (
 #align nat.forall_lt_succ Nat.forall_lt_succ
 -/
 
-/- warning: nat.exists_lt_succ -> Nat.exists_lt_succ is a dubious translation:
-lean 3 declaration is
-  forall {P : Nat -> Prop} {n : Nat}, Iff (Exists.{1} Nat (fun (m : Nat) => Exists.{0} (LT.lt.{0} Nat Nat.hasLt m (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat Nat.hasAdd) n (OfNat.ofNat.{0} Nat 1 (OfNat.mk.{0} Nat 1 (One.one.{0} Nat Nat.hasOne))))) (fun (H : LT.lt.{0} Nat Nat.hasLt m (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat Nat.hasAdd) n (OfNat.ofNat.{0} Nat 1 (OfNat.mk.{0} Nat 1 (One.one.{0} Nat Nat.hasOne))))) => P m))) (Or (Exists.{1} Nat (fun (m : Nat) => Exists.{0} (LT.lt.{0} Nat Nat.hasLt m n) (fun (H : LT.lt.{0} Nat Nat.hasLt m n) => P m))) (P n))
-but is expected to have type
-  forall {P : Nat -> Prop} {n : Nat}, Iff (Exists.{1} Nat (fun (m : Nat) => And (LT.lt.{0} Nat instLTNat m (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat instAddNat) n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))) (P m))) (Or (Exists.{1} Nat (fun (m : Nat) => And (LT.lt.{0} Nat instLTNat m n) (P m))) (P n))
-Case conversion may be inaccurate. Consider using '#align nat.exists_lt_succ Nat.exists_lt_succₓ'. -/
 theorem exists_lt_succ {P : ℕ → Prop} {n : ℕ} : (∃ m < n + 1, P m) ↔ (∃ m < n, P m) ∨ P n := by
   rw [← not_iff_not]; push_neg; exact forall_lt_succ
 #align nat.exists_lt_succ Nat.exists_lt_succ
@@ -405,12 +393,6 @@ theorem pred_sub (n m : ℕ) : pred n - m = pred (n - m) := by
 #align nat.pred_sub Nat.pred_sub
 -/
 
-/- warning: nat.le_pred_of_lt -> Nat.le_pred_of_lt is a dubious translation:
-lean 3 declaration is
-  forall {n : Nat} {m : Nat}, (LT.lt.{0} Nat Nat.hasLt m n) -> (LE.le.{0} Nat Nat.hasLe m (HSub.hSub.{0, 0, 0} Nat Nat Nat (instHSub.{0} Nat Nat.hasSub) n (OfNat.ofNat.{0} Nat 1 (OfNat.mk.{0} Nat 1 (One.one.{0} Nat Nat.hasOne)))))
-but is expected to have type
-  forall {n : Nat} {m : Nat}, (LT.lt.{0} Nat instLTNat n m) -> (LE.le.{0} Nat instLENat n (HSub.hSub.{0, 0, 0} Nat Nat Nat (instHSub.{0} Nat instSubNat) m (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))))
-Case conversion may be inaccurate. Consider using '#align nat.le_pred_of_lt Nat.le_pred_of_ltₓ'. -/
 theorem le_pred_of_lt {n m : ℕ} (h : m < n) : m ≤ n - 1 :=
   Nat.sub_le_sub_right h 1
 #align nat.le_pred_of_lt Nat.le_pred_of_lt
@@ -589,12 +571,6 @@ theorem strongRecOn'_beta {P : ℕ → Sort _} {h} {n : ℕ} :
 #align nat.strong_rec_on_beta' Nat.strongRecOn'_beta
 -/
 
-/- warning: nat.le_induction -> Nat.le_induction is a dubious translation:
-lean 3 declaration is
-  forall {P : Nat -> Prop} {m : Nat}, (P m) -> (forall (n : Nat), (LE.le.{0} Nat Nat.hasLe m n) -> (P n) -> (P (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat Nat.hasAdd) n (OfNat.ofNat.{0} Nat 1 (OfNat.mk.{0} Nat 1 (One.one.{0} Nat Nat.hasOne)))))) -> (forall (n : Nat), (LE.le.{0} Nat Nat.hasLe m n) -> (P n))
-but is expected to have type
-  forall {P : Nat} {m : forall (n : Nat), (LE.le.{0} Nat instLENat P n) -> Prop}, (m P (le_rfl.{0} Nat (PartialOrder.toPreorder.{0} Nat (LinearOrder.toPartialOrder.{0} Nat Nat.linearOrder)) P)) -> (forall (n : Nat) (ᾰ : LE.le.{0} Nat instLENat P n), (m n ᾰ) -> (m (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat instAddNat) n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))) (LE.le.trans.{0} Nat (PartialOrder.toPreorder.{0} Nat (LinearOrder.toPartialOrder.{0} Nat Nat.linearOrder)) P n (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat instAddNat) n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))) ᾰ (Nat.le_succ n)))) -> (forall (n : Nat) (ᾰ : LE.le.{0} Nat instLENat P n), m n ᾰ)
-Case conversion may be inaccurate. Consider using '#align nat.le_induction Nat.le_inductionₓ'. -/
 /-- Induction principle starting at a non-zero number. For maps to a `Sort*` see `le_rec_on`. -/
 @[elab_as_elim]
 theorem le_induction {P : Nat → Prop} {m} (h0 : P m) (h1 : ∀ n, m ≤ n → P n → P (n + 1)) :
@@ -821,24 +797,12 @@ protected theorem mul_div_cancel_left' {a b : ℕ} (Hd : a ∣ b) : a * (b / a)
 #align nat.mul_div_cancel_left' Nat.mul_div_cancel_left'
 -/
 
-/- warning: nat.mul_div_mul_left -> Nat.mul_div_mul_left is a dubious translation:
-lean 3 declaration is
-  forall (a : Nat) (b : Nat) {c : Nat}, (LT.lt.{0} Nat Nat.hasLt (OfNat.ofNat.{0} Nat 0 (OfNat.mk.{0} Nat 0 (Zero.zero.{0} Nat Nat.hasZero))) c) -> (Eq.{1} Nat (HDiv.hDiv.{0, 0, 0} Nat Nat Nat (instHDiv.{0} Nat Nat.hasDiv) (HMul.hMul.{0, 0, 0} Nat Nat Nat (instHMul.{0} Nat Nat.hasMul) c a) (HMul.hMul.{0, 0, 0} Nat Nat Nat (instHMul.{0} Nat Nat.hasMul) c b)) (HDiv.hDiv.{0, 0, 0} Nat Nat Nat (instHDiv.{0} Nat Nat.hasDiv) a b))
-but is expected to have type
-  forall {a : Nat} (b : Nat) (c : Nat), (LT.lt.{0} Nat instLTNat (OfNat.ofNat.{0} Nat 0 (instOfNatNat 0)) a) -> (Eq.{1} Nat (HDiv.hDiv.{0, 0, 0} Nat Nat Nat (instHDiv.{0} Nat Nat.instDivNat) (HMul.hMul.{0, 0, 0} Nat Nat Nat (instHMul.{0} Nat instMulNat) a b) (HMul.hMul.{0, 0, 0} Nat Nat Nat (instHMul.{0} Nat instMulNat) a c)) (HDiv.hDiv.{0, 0, 0} Nat Nat Nat (instHDiv.{0} Nat Nat.instDivNat) b c))
-Case conversion may be inaccurate. Consider using '#align nat.mul_div_mul_left Nat.mul_div_mul_leftₓ'. -/
 --TODO: Update `nat.mul_div_mul` in the core?
 /-- Alias of `nat.mul_div_mul` -/
 protected theorem mul_div_mul_left (a b : ℕ) {c : ℕ} (hc : 0 < c) : c * a / (c * b) = a / b :=
   Nat.mul_div_mul a b hc
 #align nat.mul_div_mul_left Nat.mul_div_mul_left
 
-/- warning: nat.mul_div_mul_right -> Nat.mul_div_mul_right is a dubious translation:
-lean 3 declaration is
-  forall (a : Nat) (b : Nat) {c : Nat}, (LT.lt.{0} Nat Nat.hasLt (OfNat.ofNat.{0} Nat 0 (OfNat.mk.{0} Nat 0 (Zero.zero.{0} Nat Nat.hasZero))) c) -> (Eq.{1} Nat (HDiv.hDiv.{0, 0, 0} Nat Nat Nat (instHDiv.{0} Nat Nat.hasDiv) (HMul.hMul.{0, 0, 0} Nat Nat Nat (instHMul.{0} Nat Nat.hasMul) a c) (HMul.hMul.{0, 0, 0} Nat Nat Nat (instHMul.{0} Nat Nat.hasMul) b c)) (HDiv.hDiv.{0, 0, 0} Nat Nat Nat (instHDiv.{0} Nat Nat.hasDiv) a b))
-but is expected to have type
-  forall {a : Nat} (b : Nat) (c : Nat), (LT.lt.{0} Nat instLTNat (OfNat.ofNat.{0} Nat 0 (instOfNatNat 0)) a) -> (Eq.{1} Nat (HDiv.hDiv.{0, 0, 0} Nat Nat Nat (instHDiv.{0} Nat Nat.instDivNat) (HMul.hMul.{0, 0, 0} Nat Nat Nat (instHMul.{0} Nat instMulNat) b a) (HMul.hMul.{0, 0, 0} Nat Nat Nat (instHMul.{0} Nat instMulNat) c a)) (HDiv.hDiv.{0, 0, 0} Nat Nat Nat (instHDiv.{0} Nat Nat.instDivNat) b c))
-Case conversion may be inaccurate. Consider using '#align nat.mul_div_mul_right Nat.mul_div_mul_rightₓ'. -/
 protected theorem mul_div_mul_right (a b : ℕ) {c : ℕ} (hc : 0 < c) : a * c / (b * c) = a / b := by
   rw [mul_comm, mul_comm b, a.mul_div_mul_left b hc]
 #align nat.mul_div_mul_right Nat.mul_div_mul_right
@@ -1072,24 +1036,12 @@ theorem find_eq_iff (h : ∃ n : ℕ, p n) : Nat.find h = m ↔ p m ∧ ∀ n <
 #align nat.find_eq_iff Nat.find_eq_iff
 -/
 
-/- warning: nat.find_lt_iff -> Nat.find_lt_iff is a dubious translation:
-lean 3 declaration is
-  forall {p : Nat -> Prop} [_inst_1 : DecidablePred.{1} Nat p] (h : Exists.{1} Nat (fun (n : Nat) => p n)) (n : Nat), Iff (LT.lt.{0} Nat Nat.hasLt (Nat.find (fun (n : Nat) => p n) (fun (a : Nat) => _inst_1 a) h) n) (Exists.{1} Nat (fun (m : Nat) => Exists.{0} (LT.lt.{0} Nat Nat.hasLt m n) (fun (H : LT.lt.{0} Nat Nat.hasLt m n) => p m)))
-but is expected to have type
-  forall {p : Nat -> Prop} [_inst_1 : DecidablePred.{1} Nat p] (h : Exists.{1} Nat (fun (n : Nat) => p n)) (n : Nat), Iff (LT.lt.{0} Nat instLTNat (Nat.find (fun (n : Nat) => p n) (fun (a : Nat) => _inst_1 a) h) n) (Exists.{1} Nat (fun (m : Nat) => And (LT.lt.{0} Nat instLTNat m n) (p m)))
-Case conversion may be inaccurate. Consider using '#align nat.find_lt_iff Nat.find_lt_iffₓ'. -/
 @[simp]
 theorem find_lt_iff (h : ∃ n : ℕ, p n) (n : ℕ) : Nat.find h < n ↔ ∃ m < n, p m :=
   ⟨fun h2 => ⟨Nat.find h, h2, Nat.find_spec h⟩, fun ⟨m, hmn, hm⟩ =>
     (Nat.find_min' h hm).trans_lt hmn⟩
 #align nat.find_lt_iff Nat.find_lt_iff
 
-/- warning: nat.find_le_iff -> Nat.find_le_iff is a dubious translation:
-lean 3 declaration is
-  forall {p : Nat -> Prop} [_inst_1 : DecidablePred.{1} Nat p] (h : Exists.{1} Nat (fun (n : Nat) => p n)) (n : Nat), Iff (LE.le.{0} Nat Nat.hasLe (Nat.find (fun (n : Nat) => p n) (fun (a : Nat) => _inst_1 a) h) n) (Exists.{1} Nat (fun (m : Nat) => Exists.{0} (LE.le.{0} Nat Nat.hasLe m n) (fun (H : LE.le.{0} Nat Nat.hasLe m n) => p m)))
-but is expected to have type
-  forall {p : Nat -> Prop} [_inst_1 : DecidablePred.{1} Nat p] (h : Exists.{1} Nat (fun (n : Nat) => p n)) (n : Nat), Iff (LE.le.{0} Nat instLENat (Nat.find (fun (n : Nat) => p n) (fun (a : Nat) => _inst_1 a) h) n) (Exists.{1} Nat (fun (m : Nat) => And (LE.le.{0} Nat instLENat m n) (p m)))
-Case conversion may be inaccurate. Consider using '#align nat.find_le_iff Nat.find_le_iffₓ'. -/
 @[simp]
 theorem find_le_iff (h : ∃ n : ℕ, p n) (n : ℕ) : Nat.find h ≤ n ↔ ∃ m ≤ n, p m := by
   simp only [exists_prop, ← lt_succ_iff, find_lt_iff]
Diff
@@ -138,9 +138,7 @@ theorem and_forall_succ {p : ℕ → Prop} : (p 0 ∧ ∀ n, p (n + 1)) ↔ ∀
 #print Nat.or_exists_succ /-
 @[simp]
 theorem or_exists_succ {p : ℕ → Prop} : (p 0 ∨ ∃ n, p (n + 1)) ↔ ∃ n, p n :=
-  ⟨fun h => h.elim (fun h0 => ⟨0, h0⟩) fun ⟨n, hn⟩ => ⟨n + 1, hn⟩,
-    by
-    rintro ⟨_ | n, hn⟩
+  ⟨fun h => h.elim (fun h0 => ⟨0, h0⟩) fun ⟨n, hn⟩ => ⟨n + 1, hn⟩, by rintro ⟨_ | n, hn⟩;
     exacts[Or.inl hn, Or.inr ⟨n, hn⟩]⟩
 #align nat.or_exists_succ Nat.or_exists_succ
 -/
@@ -231,8 +229,7 @@ theorem max_succ_succ {m n : ℕ} : max (succ m) (succ n) = succ (max m n) :=
   by
   by_cases h1 : m ≤ n
   rw [max_eq_right h1, max_eq_right (succ_le_succ h1)]
-  · rw [not_le] at h1
-    have h2 := le_of_lt h1
+  · rw [not_le] at h1; have h2 := le_of_lt h1
     rw [max_eq_left h2, max_eq_left (succ_le_succ h2)]
 #align nat.max_succ_succ Nat.max_succ_succ
 
@@ -327,11 +324,8 @@ lean 3 declaration is
 but is expected to have type
   forall {P : Nat -> Prop} {n : Nat}, Iff (Exists.{1} Nat (fun (m : Nat) => And (LT.lt.{0} Nat instLTNat m (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat instAddNat) n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))) (P m))) (Or (Exists.{1} Nat (fun (m : Nat) => And (LT.lt.{0} Nat instLTNat m n) (P m))) (P n))
 Case conversion may be inaccurate. Consider using '#align nat.exists_lt_succ Nat.exists_lt_succₓ'. -/
-theorem exists_lt_succ {P : ℕ → Prop} {n : ℕ} : (∃ m < n + 1, P m) ↔ (∃ m < n, P m) ∨ P n :=
-  by
-  rw [← not_iff_not]
-  push_neg
-  exact forall_lt_succ
+theorem exists_lt_succ {P : ℕ → Prop} {n : ℕ} : (∃ m < n + 1, P m) ↔ (∃ m < n, P m) ∨ P n := by
+  rw [← not_iff_not]; push_neg; exact forall_lt_succ
 #align nat.exists_lt_succ Nat.exists_lt_succ
 
 /-! ### `add` -/
@@ -558,9 +552,7 @@ theorem leRecOn_succ_left {C : ℕ → Sort u} {n m} (h1 : n ≤ m) (h2 : n + 1
 theorem leRecOn_injective {C : ℕ → Sort u} {n m} (hnm : n ≤ m) (next : ∀ n, C n → C (n + 1))
     (Hnext : ∀ n, Function.Injective (next n)) : Function.Injective (leRecOn hnm next) :=
   by
-  induction' hnm with m hnm ih;
-  · intro x y H
-    rwa [le_rec_on_self, le_rec_on_self] at H
+  induction' hnm with m hnm ih; · intro x y H; rwa [le_rec_on_self, le_rec_on_self] at H
   intro x y H; rw [le_rec_on_succ hnm, le_rec_on_succ hnm] at H; exact ih (Hnext _ H)
 #align nat.le_rec_on_injective Nat.leRecOn_injective
 -/
@@ -569,10 +561,7 @@ theorem leRecOn_injective {C : ℕ → Sort u} {n m} (hnm : n ≤ m) (next : ∀
 theorem leRecOn_surjective {C : ℕ → Sort u} {n m} (hnm : n ≤ m) (next : ∀ n, C n → C (n + 1))
     (Hnext : ∀ n, Function.Surjective (next n)) : Function.Surjective (leRecOn hnm next) :=
   by
-  induction' hnm with m hnm ih;
-  · intro x
-    use x
-    rw [le_rec_on_self]
+  induction' hnm with m hnm ih; · intro x; use x; rw [le_rec_on_self]
   intro x; rcases Hnext _ x with ⟨w, rfl⟩; rcases ih w with ⟨x, rfl⟩; use x; rw [le_rec_on_succ]
 #align nat.le_rec_on_surjective Nat.leRecOn_surjective
 -/
@@ -595,10 +584,8 @@ def strongRecOn' {P : ℕ → Sort _} (n : ℕ) (h : ∀ n, (∀ m, m < n → P
 
 #print Nat.strongRecOn'_beta /-
 theorem strongRecOn'_beta {P : ℕ → Sort _} {h} {n : ℕ} :
-    (strongRecOn' n h : P n) = h n fun m hmn => (strongRecOn' m h : P m) :=
-  by
-  simp only [strong_rec_on']
-  rw [Nat.strongRec']
+    (strongRecOn' n h : P n) = h n fun m hmn => (strongRecOn' m h : P m) := by
+  simp only [strong_rec_on']; rw [Nat.strongRec']
 #align nat.strong_rec_on_beta' Nat.strongRecOn'_beta
 -/
 
@@ -628,9 +615,7 @@ def decreasingInduction {P : ℕ → Sort _} (h : ∀ n, P (n + 1) → P n) {m n
 #print Nat.decreasingInduction_self /-
 @[simp]
 theorem decreasingInduction_self {P : ℕ → Sort _} (h : ∀ n, P (n + 1) → P n) {n : ℕ} (nn : n ≤ n)
-    (hP : P n) : (decreasingInduction h nn hP : P n) = hP :=
-  by
-  dsimp only [decreasing_induction]
+    (hP : P n) : (decreasingInduction h nn hP : P n) = hP := by dsimp only [decreasing_induction];
   rw [le_rec_on_self]
 #align nat.decreasing_induction_self Nat.decreasingInduction_self
 -/
@@ -638,20 +623,16 @@ theorem decreasingInduction_self {P : ℕ → Sort _} (h : ∀ n, P (n + 1) →
 #print Nat.decreasingInduction_succ /-
 theorem decreasingInduction_succ {P : ℕ → Sort _} (h : ∀ n, P (n + 1) → P n) {m n : ℕ} (mn : m ≤ n)
     (msn : m ≤ n + 1) (hP : P (n + 1)) :
-    (decreasingInduction h msn hP : P m) = decreasingInduction h mn (h n hP) :=
-  by
-  dsimp only [decreasing_induction]
-  rw [le_rec_on_succ]
+    (decreasingInduction h msn hP : P m) = decreasingInduction h mn (h n hP) := by
+  dsimp only [decreasing_induction]; rw [le_rec_on_succ]
 #align nat.decreasing_induction_succ Nat.decreasingInduction_succ
 -/
 
 #print Nat.decreasingInduction_succ' /-
 @[simp]
 theorem decreasingInduction_succ' {P : ℕ → Sort _} (h : ∀ n, P (n + 1) → P n) {m : ℕ}
-    (msm : m ≤ m + 1) (hP : P (m + 1)) : (decreasingInduction h msm hP : P m) = h m hP :=
-  by
-  dsimp only [decreasing_induction]
-  rw [le_rec_on_succ']
+    (msm : m ≤ m + 1) (hP : P (m + 1)) : (decreasingInduction h msm hP : P m) = h m hP := by
+  dsimp only [decreasing_induction]; rw [le_rec_on_succ']
 #align nat.decreasing_induction_succ' Nat.decreasingInduction_succ'
 -/
 
@@ -661,8 +642,7 @@ theorem decreasingInduction_trans {P : ℕ → Sort _} (h : ∀ n, P (n + 1) →
     (decreasingInduction h (le_trans mn nk) hP : P m) =
       decreasingInduction h mn (decreasingInduction h nk hP) :=
   by
-  induction' nk with k nk ih
-  rw [decreasing_induction_self]
+  induction' nk with k nk ih; rw [decreasing_induction_self]
   rw [decreasing_induction_succ h (le_trans mn nk), ih, decreasing_induction_succ]
 #align nat.decreasing_induction_trans Nat.decreasingInduction_trans
 -/
@@ -730,8 +710,7 @@ def decreasingInduction' {P : ℕ → Sort _} {m n : ℕ} (h : ∀ k < n, m ≤
     apply ih
     · exact fun k hk => h k hk.step
     · exact h n (lt_succ_self n) mn hP
-  · intro h hP
-    exact hP
+  · intro h hP; exact hP
 #align nat.decreasing_induction' Nat.decreasingInduction'
 -/
 
@@ -906,18 +885,12 @@ theorem div_add_mod (m k : ℕ) : k * (m / k) + m % k = m :=
 -/
 
 #print Nat.mod_add_div' /-
-theorem mod_add_div' (m k : ℕ) : m % k + m / k * k = m :=
-  by
-  rw [mul_comm]
-  exact mod_add_div _ _
+theorem mod_add_div' (m k : ℕ) : m % k + m / k * k = m := by rw [mul_comm]; exact mod_add_div _ _
 #align nat.mod_add_div' Nat.mod_add_div'
 -/
 
 #print Nat.div_add_mod' /-
-theorem div_add_mod' (m k : ℕ) : m / k * k + m % k = m :=
-  by
-  rw [mul_comm]
-  exact div_add_mod _ _
+theorem div_add_mod' (m k : ℕ) : m / k * k + m % k = m := by rw [mul_comm]; exact div_add_mod _ _
 #align nat.div_add_mod' Nat.div_add_mod'
 -/
 
@@ -1052,8 +1025,7 @@ theorem lt_iff_le_pred : ∀ {m n : ℕ}, 0 < n → (m < n ↔ m ≤ n - 1)
 theorem mul_div_le (m n : ℕ) : n * (m / n) ≤ m :=
   by
   cases' Nat.eq_zero_or_pos n with n0 h
-  · rw [n0, MulZeroClass.zero_mul]
-    exact m.zero_le
+  · rw [n0, MulZeroClass.zero_mul]; exact m.zero_le
   · rw [mul_comm, ← Nat.le_div_iff_mul_le' h]
 #align nat.mul_div_le Nat.mul_div_le
 -/
@@ -1094,8 +1066,7 @@ variable {p q : ℕ → Prop} [DecidablePred p] [DecidablePred q]
 theorem find_eq_iff (h : ∃ n : ℕ, p n) : Nat.find h = m ↔ p m ∧ ∀ n < m, ¬p n :=
   by
   constructor
-  · rintro rfl
-    exact ⟨Nat.find_spec h, fun _ => Nat.find_min h⟩
+  · rintro rfl; exact ⟨Nat.find_spec h, fun _ => Nat.find_min h⟩
   · rintro ⟨hm, hlt⟩
     exact le_antisymm (Nat.find_min' h hm) (not_lt.1 <| imp_not_comm.1 (hlt _) <| Nat.find_spec h)
 #align nat.find_eq_iff Nat.find_eq_iff
@@ -1226,9 +1197,7 @@ instance decidableBallLT (n : Nat) (P : ∀ k < n, Prop) :
   induction' n with n IH <;> intro <;> skip
   · exact is_true fun n => by decide
   cases' IH fun k h => P k (lt_succ_of_lt h) with h
-  · refine' is_false (mt _ h)
-    intro hn k h
-    apply hn
+  · refine' is_false (mt _ h); intro hn k h; apply hn
   by_cases p : P n (lt_succ_self n)
   ·
     exact
Diff
@@ -1032,7 +1032,7 @@ theorem eq_of_dvd_of_div_eq_one {a b : ℕ} (w : a ∣ b) (h : b / a = 1) : a =
 
 #print Nat.eq_zero_of_dvd_of_div_eq_zero /-
 theorem eq_zero_of_dvd_of_div_eq_zero {a b : ℕ} (w : a ∣ b) (h : b / a = 0) : b = 0 := by
-  rw [← Nat.div_mul_cancel w, h, zero_mul]
+  rw [← Nat.div_mul_cancel w, h, MulZeroClass.zero_mul]
 #align nat.eq_zero_of_dvd_of_div_eq_zero Nat.eq_zero_of_dvd_of_div_eq_zero
 -/
 
@@ -1052,7 +1052,7 @@ theorem lt_iff_le_pred : ∀ {m n : ℕ}, 0 < n → (m < n ↔ m ≤ n - 1)
 theorem mul_div_le (m n : ℕ) : n * (m / n) ≤ m :=
   by
   cases' Nat.eq_zero_or_pos n with n0 h
-  · rw [n0, zero_mul]
+  · rw [n0, MulZeroClass.zero_mul]
     exact m.zero_le
   · rw [mul_comm, ← Nat.le_div_iff_mul_le' h]
 #align nat.mul_div_le Nat.mul_div_le
Diff
@@ -790,7 +790,7 @@ protected theorem div_pos {a b : ℕ} (hba : b ≤ a) (hb : 0 < b) : 0 < a / b :
     lt_irrefl a
       (calc
         a = a % b := by simpa [h] using (mod_add_div a b).symm
-        _ < b := Nat.mod_lt a hb
+        _ < b := (Nat.mod_lt a hb)
         _ ≤ a := hba
         )
 #align nat.div_pos Nat.div_pos

Changes in mathlib4

mathlib3
mathlib4
chore: adapt to multiple goal linter 1 (#12338)

A PR accompanying #12339.

Zulip discussion

Diff
@@ -1197,7 +1197,8 @@ lemma dvd_sub_mod (k : ℕ) : n ∣ k - k % n :=
 
 lemma add_mod_eq_ite :
     (m + n) % k = if k ≤ m % k + n % k then m % k + n % k - k else m % k + n % k := by
-  cases k; simp only [zero_eq, mod_zero, zero_le, ↓reduceIte, Nat.sub_zero]
+  cases k
+  · simp
   rw [Nat.add_mod]
   split_ifs with h
   · rw [Nat.mod_eq_sub_mod h, Nat.mod_eq_of_lt]
@@ -1292,9 +1293,9 @@ set_option linter.deprecated false in
 protected theorem not_two_dvd_bit1 (n : ℕ) : ¬2 ∣ bit1 n := by
   rw [bit1, Nat.dvd_add_right, Nat.dvd_one]
   -- Porting note: was `cc`
-  decide
-  rw [bit0, ← Nat.two_mul]
-  exact Nat.dvd_mul_right _ _
+  · decide
+  · rw [bit0, ← Nat.two_mul]
+    exact Nat.dvd_mul_right _ _
 #align nat.not_two_dvd_bit1 Nat.not_two_dvd_bit1
 
 /-- A natural number `m` divides the sum `m + n` if and only if `m` divides `n`.-/
feat: Axiomatise b ≠ 0 → a * b / b = a (#12424)

This lets us unify a few lemmas between GroupWithZero and EuclideanDomain and two lemmas that were previously proved separately for Nat, Int, Polynomial.

Diff
@@ -40,6 +40,9 @@ instance instCancelCommMonoidWithZero : CancelCommMonoidWithZero ℕ where
   mul_left_cancel_of_ne_zero h := Nat.eq_of_mul_eq_mul_left (Nat.pos_of_ne_zero h)
 #align nat.cancel_comm_monoid_with_zero Nat.instCancelCommMonoidWithZero
 
+instance instMulDivCancelClass : MulDivCancelClass ℕ where
+  mul_div_cancel _ _b hb := Nat.mul_div_cancel _ (Nat.pos_iff_ne_zero.2 hb)
+
 /-!
 ### Extra instances to short-circuit type class resolution
 
chore: Rename Int and Rat instances (#12235)

Fix a few names and deduplicate the AddCommGroup ℤ instance

Diff
@@ -64,7 +64,7 @@ open Function
 namespace Nat
 variable {a b c d m n k : ℕ} {p q : ℕ → Prop}
 
-instance nontrivial : Nontrivial ℕ := ⟨⟨0, 1, Nat.zero_ne_one⟩⟩
+instance instNontrivial : Nontrivial ℕ := ⟨⟨0, 1, Nat.zero_ne_one⟩⟩
 
 attribute [gcongr] Nat.succ_le_succ
 attribute [simp] Nat.not_lt_zero Nat.succ_ne_zero Nat.succ_ne_self Nat.zero_ne_one Nat.one_ne_zero
chore: Rename Int and Rat instances (#12235)

Fix a few names and deduplicate the AddCommGroup ℤ instance

Diff
@@ -22,8 +22,8 @@ namespace Nat
 
 /-! ### Instances -/
 
-instance commSemiring : CommSemiring ℕ where
-  __ := commMonoid
+instance instCommSemiring : CommSemiring ℕ where
+  __ := instCommMonoid
   left_distrib := Nat.left_distrib
   right_distrib := Nat.right_distrib
   zero_mul := Nat.zero_mul
@@ -35,10 +35,10 @@ instance commSemiring : CommSemiring ℕ where
   natCast_zero := rfl
   natCast_succ _ := rfl
 
-instance cancelCommMonoidWithZero : CancelCommMonoidWithZero ℕ where
+instance instCancelCommMonoidWithZero : CancelCommMonoidWithZero ℕ where
   __ : CommMonoidWithZero ℕ := by infer_instance
   mul_left_cancel_of_ne_zero h := Nat.eq_of_mul_eq_mul_left (Nat.pos_of_ne_zero h)
-#align nat.cancel_comm_monoid_with_zero Nat.cancelCommMonoidWithZero
+#align nat.cancel_comm_monoid_with_zero Nat.instCancelCommMonoidWithZero
 
 /-!
 ### Extra instances to short-circuit type class resolution
@@ -46,8 +46,8 @@ instance cancelCommMonoidWithZero : CancelCommMonoidWithZero ℕ where
 These also prevent non-computable instances being used to construct these instances non-computably.
 -/
 
-instance addCommMonoidWithOne : AddCommMonoidWithOne ℕ := by infer_instance
-instance distrib              : Distrib ℕ              := by infer_instance
-instance semiring             : Semiring ℕ             := by infer_instance
+instance instAddCommMonoidWithOne : AddCommMonoidWithOne ℕ := by infer_instance
+instance instDistrib              : Distrib ℕ              := by infer_instance
+instance instSemiring             : Semiring ℕ             := by infer_instance
 
 end Nat
chore: Rename Int and Rat instances (#12235)

Fix a few names and deduplicate the AddCommGroup ℤ instance

Diff
@@ -23,7 +23,7 @@ namespace Nat
 
 /-! ### Instances -/
 
-instance addCommMonoid : AddCommMonoid ℕ where
+instance instAddCommMonoid : AddCommMonoid ℕ where
   add := Nat.add
   add_assoc := Nat.add_assoc
   zero := Nat.zero
@@ -34,7 +34,7 @@ instance addCommMonoid : AddCommMonoid ℕ where
   nsmul_zero := Nat.zero_mul
   nsmul_succ := succ_mul
 
-instance commMonoid : CommMonoid ℕ where
+instance instCommMonoid : CommMonoid ℕ where
   mul := Nat.mul
   mul_assoc := Nat.mul_assoc
   one := Nat.succ Nat.zero
@@ -51,12 +51,12 @@ instance commMonoid : CommMonoid ℕ where
 These also prevent non-computable instances being used to construct these instances non-computably.
 -/
 
-instance addMonoid        : AddMonoid ℕ        := by infer_instance
-instance monoid           : Monoid ℕ           := by infer_instance
-instance commSemigroup    : CommSemigroup ℕ    := by infer_instance
-instance semigroup        : Semigroup ℕ        := by infer_instance
-instance addCommSemigroup : AddCommSemigroup ℕ := by infer_instance
-instance addSemigroup     : AddSemigroup ℕ     := by infer_instance
+instance instAddMonoid        : AddMonoid ℕ        := by infer_instance
+instance instMonoid           : Monoid ℕ           := by infer_instance
+instance instCommSemigroup    : CommSemigroup ℕ    := by infer_instance
+instance instSemigroup        : Semigroup ℕ        := by infer_instance
+instance instAddCommSemigroup : AddCommSemigroup ℕ := by infer_instance
+instance instAddSemigroup     : AddSemigroup ℕ     := by infer_instance
 
 /-! ### Miscellaneous lemmas -/
 
feat(Nat/Defs): Add div_dvd_iff_dvd_mul (#12243)
Diff
@@ -1377,6 +1377,17 @@ lemma dvd_div_of_mul_dvd (h : a * b ∣ c) : b ∣ c / a :=
   ⟨fun h => mul_dvd_of_dvd_div hbc h, fun h => dvd_div_of_mul_dvd h⟩
 #align nat.dvd_div_iff Nat.dvd_div_iff
 
+lemma dvd_mul_of_div_dvd (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] lemma div_dvd_iff_dvd_mul (h : b ∣ a) (hb : b ≠ 0) : a / b ∣ c ↔ a ∣ b * c :=
+  exists_congr <| fun d => by
+  have := Nat.dvd_trans (Nat.dvd_mul_left _ d) (Nat.mul_dvd_mul_left d h)
+  rw [eq_comm, Nat.mul_comm, ← Nat.mul_div_assoc d h,
+    Nat.div_eq_iff_eq_mul_right (Nat.pos_of_ne_zero hb) this, Nat.mul_comm, eq_comm]
+
 @[simp] lemma div_div_div_eq_div (dvd : b ∣ a) (dvd2 : a ∣ c) : c / (a / b) / b = c / a :=
   match a, b, c with
   | 0, _, _ => by simp
chore(Data/Nat/Defs): Integrate Nat.sqrt material (#11866)

Move the content of Data.Nat.ForSqrt and Data.Nat.Sqrt to Data.Nat.Defs by using Nat-specific Std lemmas rather than the mathlib general ones. This makes it ready to move to Std if wanted.

Diff
@@ -12,6 +12,7 @@ import Mathlib.Tactic.PushNeg
 import Mathlib.Util.AssertExists
 
 #align_import data.nat.basic from "leanprover-community/mathlib"@"bd835ef554f37ef9b804f0903089211f89cb370b"
+#align_import data.nat.sqrt from "leanprover-community/mathlib"@"ba2245edf0c8bb155f1569fd9b9492a9b384cde6"
 
 /-!
 # Basic operations on the natural numbers
@@ -678,6 +679,22 @@ protected lemma eq_div_of_mul_eq_left (hc : c ≠ 0) (h : a * c = b) : a = b / c
 protected lemma 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 lemma mul_le_of_le_div (k x y : ℕ) (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)]
+
+protected lemma div_mul_div_le (a b c d : ℕ) :
+    (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)]
+  transitivity ((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`
 
@@ -1419,6 +1436,235 @@ lemma div_lt_div_of_lt_of_dvd {a b d : ℕ} (hdb : d ∣ b) (h : a < b) : a / d
   exact lt_of_le_of_lt (mul_div_le a d) h
 #align nat.div_lt_div_of_lt_of_dvd Nat.div_lt_div_of_lt_of_dvd
 
+/-!
+### `sqrt`
+
+See [Wikipedia, *Methods of computing square roots*]
+(https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Binary_numeral_system_(base_2)).
+-/
+
+private lemma iter_fp_bound (n k : ℕ) :
+    let iter_next (n guess : ℕ) := (guess + n / guess) / 2;
+    sqrt.iter n k ≤ iter_next n (sqrt.iter n k) := by
+  intro iter_next
+  unfold sqrt.iter
+  if h : (k + n / k) / 2 < k then
+    simpa [if_pos h] using iter_fp_bound _ _
+  else
+    simpa [if_neg h] using Nat.le_of_not_lt h
+
+private lemma AM_GM : {a b : ℕ} → (4 * a * b ≤ (a + b) * (a + b))
+  | 0, _ => by rw [Nat.mul_zero, Nat.zero_mul]; exact zero_le _
+  | _, 0 => by rw [Nat.mul_zero]; exact zero_le _
+  | a + 1, b + 1 => by
+    simpa only [Nat.mul_add, Nat.add_mul, show (4 : ℕ) = 1 + 1 + 1 + 1 from rfl, Nat.one_mul,
+      Nat.mul_one, Nat.add_assoc, Nat.add_left_comm, Nat.add_le_add_iff_left]
+      using Nat.add_le_add_right (@AM_GM a b) 4
+
+-- These two lemmas seem like they belong to `Std.Data.Nat.Basic`.
+
+lemma sqrt.iter_sq_le (n guess : ℕ) : sqrt.iter n guess * sqrt.iter n guess ≤ n := by
+  unfold sqrt.iter
+  let next := (guess + n / guess) / 2
+  if h : next < guess then
+    simpa only [dif_pos h] using sqrt.iter_sq_le n next
+  else
+    simp only [dif_neg h]
+    apply Nat.mul_le_of_le_div
+    apply Nat.le_of_add_le_add_left (a := guess)
+    rw [← Nat.mul_two, ← le_div_iff_mul_le]
+    · exact Nat.le_of_not_lt h
+    · exact Nat.zero_lt_two
+
+lemma sqrt.lt_iter_succ_sq (n guess : ℕ) (hn : n < (guess + 1) * (guess + 1)) :
+    n < (sqrt.iter n guess + 1) * (sqrt.iter n guess + 1) := by
+  unfold sqrt.iter
+  -- m was `next`
+  let m := (guess + n / guess) / 2
+  dsimp
+  split_ifs with h
+  · suffices n < (m + 1) * (m + 1) by
+      simpa only [dif_pos h] using sqrt.lt_iter_succ_sq n m this
+    refine Nat.lt_of_mul_lt_mul_left ?_ (a := 4 * (guess * guess))
+    apply Nat.lt_of_le_of_lt AM_GM
+    rw [show (4 : ℕ) = 2 * 2 from rfl]
+    rw [Nat.mul_mul_mul_comm 2, Nat.mul_mul_mul_comm (2 * guess)]
+    refine Nat.mul_self_lt_mul_self (?_ : _ < _ * succ (_ / 2))
+    rw [← add_div_right _ (by decide), Nat.mul_comm 2, Nat.mul_assoc,
+      show guess + n / guess + 2 = (guess + n / guess + 1) + 1 from rfl]
+    have aux_lemma {a : ℕ} : a ≤ 2 * ((a + 1) / 2) := by omega
+    refine lt_of_lt_of_le ?_ (Nat.mul_le_mul_left _ aux_lemma)
+    rw [Nat.add_assoc, Nat.mul_add]
+    exact Nat.add_lt_add_left (lt_mul_div_succ _ (lt_of_le_of_lt (Nat.zero_le m) h)) _
+  · simpa only [dif_neg h] using hn
+
+#align nat.sqrt Nat.sqrt
+-- Porting note: the implementation òf `Nat.sqrt` in `Std` no longer needs `sqrt_aux`.
+#noalign nat.sqrt_aux_dec
+#noalign nat.sqrt_aux
+#noalign nat.sqrt_aux_0
+#noalign nat.sqrt_aux_1
+#noalign nat.sqrt_aux_2
+private def IsSqrt (n q : ℕ) : Prop :=
+  q * q ≤ n ∧ n < (q + 1) * (q + 1)
+-- Porting note: as the definition of square root has changed,
+-- the proof of `sqrt_isSqrt` is attempted from scratch.
+/-
+Sketch of proof:
+Up to rounding, in terms of the definition of `sqrt.iter`,
+
+* By AM-GM inequality, `next² ≥ n` giving one of the bounds.
+* When we terminated, we have `guess ≥ next` from which we deduce the other bound `n ≥ next²`.
+
+To turn this into a lean proof we need to manipulate, use properties of natural number division etc.
+-/
+private lemma sqrt_isSqrt (n : ℕ) : IsSqrt n (sqrt n) := by
+  match n with
+  | 0 => simp [IsSqrt, sqrt]
+  | 1 => simp [IsSqrt, sqrt]
+  | n + 2 =>
+    have h : ¬ (n + 2) ≤ 1 := by simp
+    simp only [IsSqrt, sqrt, h, ite_false]
+    refine ⟨sqrt.iter_sq_le _ _, sqrt.lt_iter_succ_sq _ _ ?_⟩
+    simp only [Nat.mul_add, Nat.add_mul, Nat.one_mul, Nat.mul_one, ← Nat.add_assoc]
+    rw [lt_add_one_iff, Nat.add_assoc, ← Nat.mul_two]
+    refine le_trans (Nat.le_of_eq (div_add_mod' (n + 2) 2).symm) ?_
+    rw [Nat.add_comm, Nat.add_le_add_iff_right, add_mod_right]
+    simp only [Nat.zero_lt_two, add_div_right, succ_mul_succ]
+    refine le_trans (b := 1) ?_ ?_
+    · exact (lt_succ.1 <| mod_lt n Nat.zero_lt_two)
+    · exact Nat.le_add_left _ _
+
+lemma sqrt_le (n : ℕ) : sqrt n * sqrt n ≤ n := (sqrt_isSqrt n).left
+#align nat.sqrt_le Nat.sqrt_le
+
+lemma sqrt_le' (n : ℕ) : sqrt n ^ 2 ≤ n := by simpa [Nat.pow_two] using sqrt_le n
+#align nat.sqrt_le' Nat.sqrt_le'
+
+lemma lt_succ_sqrt (n : ℕ) : n < succ (sqrt n) * succ (sqrt n) := (sqrt_isSqrt n).right
+#align nat.lt_succ_sqrt Nat.lt_succ_sqrt
+
+lemma lt_succ_sqrt' (n : ℕ) : n < succ (sqrt n) ^ 2 := by simpa [Nat.pow_two] using lt_succ_sqrt n
+#align nat.lt_succ_sqrt' Nat.lt_succ_sqrt'
+
+lemma sqrt_le_add (n : ℕ) : n ≤ sqrt n * sqrt n + sqrt n + sqrt n := by
+  rw [← succ_mul]; exact le_of_lt_succ (lt_succ_sqrt n)
+#align nat.sqrt_le_add Nat.sqrt_le_add
+
+lemma le_sqrt : m ≤ sqrt n ↔ m * m ≤ n :=
+  ⟨fun h ↦ le_trans (mul_self_le_mul_self h) (sqrt_le n),
+    fun h ↦ le_of_lt_succ <| Nat.mul_self_lt_mul_self_iff.1 <| lt_of_le_of_lt h (lt_succ_sqrt n)⟩
+#align nat.le_sqrt Nat.le_sqrt
+
+lemma le_sqrt' : m ≤ sqrt n ↔ m ^ 2 ≤ n := by simpa only [Nat.pow_two] using le_sqrt
+#align nat.le_sqrt' Nat.le_sqrt'
+
+lemma sqrt_lt : sqrt m < n ↔ m < n * n := by simp only [← not_le, le_sqrt]
+#align nat.sqrt_lt Nat.sqrt_lt
+
+lemma sqrt_lt' : sqrt m < n ↔ m < n ^ 2 := by simp only [← not_le, le_sqrt']
+#align nat.sqrt_lt' Nat.sqrt_lt'
+
+lemma sqrt_le_self (n : ℕ) : sqrt n ≤ n := le_trans (le_mul_self _) (sqrt_le n)
+#align nat.sqrt_le_self Nat.sqrt_le_self
+
+lemma sqrt_le_sqrt (h : m ≤ n) : sqrt m ≤ sqrt n := le_sqrt.2 (le_trans (sqrt_le _) h)
+#align nat.sqrt_le_sqrt Nat.sqrt_le_sqrt
+
+@[simp] lemma sqrt_zero : sqrt 0 = 0 := rfl
+#align nat.sqrt_zero Nat.sqrt_zero
+
+@[simp] lemma sqrt_one : sqrt 1 = 1 := rfl
+#align nat.sqrt_one Nat.sqrt_one
+
+lemma sqrt_eq_zero : sqrt n = 0 ↔ n = 0 :=
+  ⟨fun h ↦
+      Nat.eq_zero_of_le_zero <| le_of_lt_succ <| (@sqrt_lt n 1).1 <| by rw [h]; decide,
+    by rintro rfl; simp⟩
+#align nat.sqrt_eq_zero Nat.sqrt_eq_zero
+
+lemma eq_sqrt : a = sqrt n ↔ a * a ≤ n ∧ n < (a + 1) * (a + 1) :=
+  ⟨fun e ↦ e.symm ▸ sqrt_isSqrt n,
+   fun ⟨h₁, h₂⟩ ↦ le_antisymm (le_sqrt.2 h₁) (le_of_lt_succ <| sqrt_lt.2 h₂)⟩
+#align nat.eq_sqrt Nat.eq_sqrt
+
+lemma eq_sqrt' : a = sqrt n ↔ a ^ 2 ≤ n ∧ n < (a + 1) ^ 2 := by
+  simpa only [Nat.pow_two] using eq_sqrt
+#align nat.eq_sqrt' Nat.eq_sqrt'
+
+lemma le_three_of_sqrt_eq_one (h : sqrt n = 1) : n ≤ 3 :=
+  le_of_lt_succ <| (@sqrt_lt n 2).1 <| by rw [h]; decide
+#align nat.le_three_of_sqrt_eq_one Nat.le_three_of_sqrt_eq_one
+
+lemma sqrt_lt_self (h : 1 < n) : sqrt n < n :=
+  sqrt_lt.2 <| by have := Nat.mul_lt_mul_of_pos_left h (lt_of_succ_lt h); rwa [Nat.mul_one] at this
+#align nat.sqrt_lt_self Nat.sqrt_lt_self
+
+lemma sqrt_pos : 0 < sqrt n ↔ 0 < n :=
+  le_sqrt
+#align nat.sqrt_pos Nat.sqrt_pos
+
+lemma sqrt_add_eq (n : ℕ) (h : a ≤ n + n) : sqrt (n * n + a) = n :=
+  le_antisymm
+    (le_of_lt_succ <|
+      sqrt_lt.2 <| by
+        rw [succ_mul, mul_succ, add_succ, Nat.add_assoc];
+          exact lt_succ_of_le (Nat.add_le_add_left h _))
+    (le_sqrt.2 <| Nat.le_add_right _ _)
+#align nat.sqrt_add_eq Nat.sqrt_add_eq
+
+lemma sqrt_add_eq' (n : ℕ) (h : a ≤ n + n) : sqrt (n ^ 2 + a) = n := by
+  simpa [Nat.pow_two] using sqrt_add_eq n h
+#align nat.sqrt_add_eq' Nat.sqrt_add_eq'
+
+lemma sqrt_eq (n : ℕ) : sqrt (n * n) = n := sqrt_add_eq n (zero_le _)
+#align nat.sqrt_eq Nat.sqrt_eq
+
+lemma sqrt_eq' (n : ℕ) : sqrt (n ^ 2) = n := sqrt_add_eq' n (zero_le _)
+#align nat.sqrt_eq' Nat.sqrt_eq'
+
+lemma sqrt_succ_le_succ_sqrt (n : ℕ) : sqrt n.succ ≤ n.sqrt.succ :=
+  le_of_lt_succ <| sqrt_lt.2 <| lt_succ_of_le <|
+  succ_le_succ <| le_trans (sqrt_le_add n) <| Nat.add_le_add_right
+    (by refine' add_le_add (Nat.mul_le_mul_right _ _) _ <;> exact Nat.le_add_right _ 2) _
+#align nat.sqrt_succ_le_succ_sqrt Nat.sqrt_succ_le_succ_sqrt
+
+lemma exists_mul_self (x : ℕ) : (∃ n, n * n = x) ↔ sqrt x * sqrt x = x :=
+  ⟨fun ⟨n, hn⟩ ↦ by rw [← hn, sqrt_eq], fun h ↦ ⟨sqrt x, h⟩⟩
+#align nat.exists_mul_self Nat.exists_mul_self
+
+lemma exists_mul_self' (x : ℕ) : (∃ n, n ^ 2 = x) ↔ sqrt x ^ 2 = x := by
+  simpa only [Nat.pow_two] using exists_mul_self x
+#align nat.exists_mul_self' Nat.exists_mul_self'
+
+lemma sqrt_mul_sqrt_lt_succ (n : ℕ) : sqrt n * sqrt n < n + 1 :=
+  Nat.lt_succ_iff.mpr (sqrt_le _)
+#align nat.sqrt_mul_sqrt_lt_succ Nat.sqrt_mul_sqrt_lt_succ
+
+lemma sqrt_mul_sqrt_lt_succ' (n : ℕ) : sqrt n ^ 2 < n + 1 :=
+  Nat.lt_succ_iff.mpr (sqrt_le' _)
+#align nat.sqrt_mul_sqrt_lt_succ' Nat.sqrt_mul_sqrt_lt_succ'
+
+lemma succ_le_succ_sqrt (n : ℕ) : n + 1 ≤ (sqrt n + 1) * (sqrt n + 1) :=
+  le_of_pred_lt (lt_succ_sqrt _)
+#align nat.succ_le_succ_sqrt Nat.succ_le_succ_sqrt
+
+lemma succ_le_succ_sqrt' (n : ℕ) : n + 1 ≤ (sqrt n + 1) ^ 2 :=
+  le_of_pred_lt (lt_succ_sqrt' _)
+#align nat.succ_le_succ_sqrt' Nat.succ_le_succ_sqrt'
+
+/-- There are no perfect squares strictly between m² and (m+1)² -/
+lemma not_exists_sq (hl : m * m < n) (hr : n < (m + 1) * (m + 1)) : ¬∃ t, t * t = n := by
+  rintro ⟨t, rfl⟩
+  have h1 : m < t := Nat.mul_self_lt_mul_self_iff.1 hl
+  have h2 : t < m + 1 := Nat.mul_self_lt_mul_self_iff.1 hr
+  exact (not_lt_of_ge <| le_of_lt_succ h2) h1
+#align nat.not_exists_sq Nat.not_exists_sq
+
+lemma not_exists_sq' : m ^ 2 < n → n < (m + 1) ^ 2 → ¬∃ t, t ^ 2 = n := by
+  simpa only [Nat.pow_two] using not_exists_sq
+#align nat.not_exists_sq' Nat.not_exists_sq'
+
 /-! ### `find` -/
 
 section Find
chore: Split Data.{Nat,Int}{.Order}.Basic in group vs ring instances (#11924)

Scatter the content of Data.Nat.Basic across:

  • Data.Nat.Defs for the lemmas having no dependencies
  • Algebra.Group.Nat for the monoid instances and the few miscellaneous lemmas needing them.
  • Algebra.Ring.Nat for the semiring instance and the few miscellaneous lemmas following it.

Similarly, scatter

  • Data.Int.Basic across Data.Int.Defs, Algebra.Group.Int, Algebra.Ring.Int
  • Data.Nat.Order.Basic across Data.Nat.Defs, Algebra.Order.Group.Nat, Algebra.Order.Ring.Nat
  • Data.Int.Order.Basic across Data.Int.Defs, Algebra.Order.Group.Int, Algebra.Order.Ring.Int

Also move a few lemmas from Data.Nat.Order.Lemmas to Data.Nat.Defs.

Before pre_11924

After post_11924

Diff
@@ -25,21 +25,34 @@ This file contains:
   * `strong_rec'`: recursion based on strong inequalities
 * decidability instances on predicates about the natural numbers
 
-## Implementation note
-
-Std has a home-baked development of the algebraic and order theoretic theory of `ℕ` which, in
-particular, is not typeclass-mediated. This is useful to set up the algebra and finiteness libraries
-in mathlib (naturals show up as indices in lists, cardinality in finsets, powers in groups, ...).
-This home-baked development is pursued in this file.
-
-Less basic uses of `ℕ` should however use the typeclass-mediated development. `Data.Nat.Basic` gives
-access to the algebraic instances. `Data.Nat.Order.Basic` is the one giving access to the algebraic
-order instances.
+See note [foundational algebra order theory].
 
 ## TODO
 
-The names of this file, `Data.Nat.Basic` and `Data.Nat.Order.Basic` are archaic and don't match up
-with reality anymore. Rename them.
+Split this file into:
+* `Data.Nat.Init` (or maybe `Data.Nat.Std`?) for lemmas that could go to Std
+* `Data.Nat.Basic` for the lemmas that require mathlib definitions
+-/
+
+library_note "foundational algebra order theory"/--
+Std has a home-baked development of the algebraic and order theoretic theory of `ℕ` and `ℤ` which,
+in particular, is not typeclass-mediated. This is useful to set up the algebra and finiteness
+libraries in mathlib (naturals and integers show up as indices/offsets in lists, cardinality in
+finsets, powers in groups, ...).
+
+Less basic uses of `ℕ` and `ℤ` should however use the typeclass-mediated development.
+
+The relevant files are:
+* `Data.Nat.Defs` for the continuation of the home-baked development on `ℕ`
+* `Data.Int.Defs` for the continuation of the home-baked development on `ℤ`
+* `Algebra.Group.Nat` for the monoid instances on `ℕ`
+* `Algebra.Group.Int` for the group instance on `ℤ`
+* `Algebra.Ring.Nat` for the semiring instance on `ℕ`
+* `Algebra.Ring.Int` for the ring instance on `ℤ`
+* `Algebra.Order.Group.Nat` for the ordered monoid instance on `ℕ`
+* `Algebra.Order.Group.Int` for the ordered group instance on `ℤ`
+* `Algebra.Order.Ring.Nat` for the ordered semiring instance on `ℕ`
+* `Algebra.Order.Ring.Int` for the ordered ring instance on `ℤ`
 -/
 
 /- We don't want to import the algebraic hierarchy in this file. -/
@@ -54,6 +67,7 @@ instance nontrivial : Nontrivial ℕ := ⟨⟨0, 1, Nat.zero_ne_one⟩⟩
 
 attribute [gcongr] Nat.succ_le_succ
 attribute [simp] Nat.not_lt_zero Nat.succ_ne_zero Nat.succ_ne_self Nat.zero_ne_one Nat.one_ne_zero
+  Nat.min_eq_left Nat.min_eq_right Nat.max_eq_left Nat.max_eq_right
   -- Nat.zero_ne_bit1 Nat.bit1_ne_zero Nat.bit0_ne_one Nat.one_ne_bit0 Nat.bit0_ne_bit1
   -- Nat.bit1_ne_bit0
 
@@ -262,9 +276,14 @@ attribute [simp] le_add_left le_add_right Nat.lt_add_left_iff_pos Nat.lt_add_rig
 
 -- Sometimes a bare `Nat.add` or similar appears as a consequence of unfolding during pattern
 -- matching. These lemmas package them back up as typeclass mediated operations.
+-- TODO: This is a duplicate of `Nat.add_eq`
 @[simp] lemma add_def : Nat.add m n = m + n := rfl
 #align nat.add_def Nat.add_def
 
+-- We want to use these two lemmas earlier than the lemmas simp can prove them with
+@[simp, nolint simpNF] protected lemma add_eq_left : a + b = a ↔ b = 0 := by omega
+@[simp, nolint simpNF] protected lemma add_eq_right : a + b = b ↔ a = 0 := by omega
+
 lemma two_le_iff : ∀ n, 2 ≤ n ↔ n ≠ 0 ∧ n ≠ 1
   | 0 => by simp
   | 1 => by simp
@@ -480,6 +499,7 @@ protected lemma add_le_mul {a : ℕ} (ha : 2 ≤ a) : ∀ {b : ℕ} (_ : 2 ≤ b
 
 #align nat.pow_div Nat.pow_div
 #align nat.div_lt_of_lt_mul Nat.div_lt_of_lt_mul
+#align nat.div_eq_zero Nat.div_eq_of_lt
 
 attribute [simp] Nat.div_self
 
@@ -966,7 +986,7 @@ def pincerRecursion {P : ℕ → ℕ → Sort*} (Ha0 : ∀ m : ℕ, P m 0) (H0b
 /-- Decreasing induction: if `P (k+1)` implies `P k` for all `m ≤ k < n`, then `P n` implies `P m`.
 Also works for functions to `Sort*`. Weakens the assumptions of `decreasing_induction`. -/
 @[elab_as_elim]
-def decreasingInduction' {P : ℕ → Sort*} {m n : ℕ} (h : ∀ k < n, m ≤ k → P (k + 1) → P k)
+def decreasingInduction' {P : ℕ → Sort*} (h : ∀ k < n, m ≤ k → P (k + 1) → P k)
     (mn : m ≤ n) (hP : P n) : P m := by
   revert h hP
   refine' leRecOn' mn _ _
@@ -1021,9 +1041,45 @@ lemma set_induction {S : Set ℕ} (hb : 0 ∈ S) (h_ind : ∀ k : ℕ, k ∈ S 
 #align nat.pow_dvd_pow_iff_le_right' Nat.pow_dvd_pow_iff_le_right'
 #align nat.mod_mul_right_div_self Nat.mod_mul_right_div_self
 #align nat.mod_mul_left_div_self Nat.mod_mul_left_div_self
+#align nat.mod_div_self Nat.mod_div_self
 
 attribute [simp] Nat.dvd_zero
 
+protected lemma lt_div_iff_mul_lt (hdn : d ∣ n) (a : ℕ) : 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]
+#align nat.lt_div_iff_mul_lt Nat.lt_div_iff_mul_lt
+
+lemma mul_div_eq_iff_dvd {n d : ℕ} : 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]
+
+lemma mul_div_lt_iff_not_dvd : d * (n / d) < n ↔ ¬ d ∣ n := by
+  simp [Nat.lt_iff_le_and_ne, mul_div_eq_iff_dvd, mul_div_le]
+
+lemma 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]
+#align nat.div_eq_iff_eq_of_dvd_dvd Nat.div_eq_iff_eq_of_dvd_dvd
+
+protected lemma div_eq_zero_iff (hb : 0 < b) : a / b = 0 ↔ a < b where
+  mp h := by rw [← mod_add_div a b, h, Nat.mul_zero, Nat.add_zero]; exact mod_lt _ hb
+  mpr h := by rw [← Nat.mul_right_inj (Nat.ne_of_gt hb), ← Nat.add_left_cancel_iff, mod_add_div,
+      mod_eq_of_lt h, Nat.mul_zero, Nat.add_zero]
+#align nat.div_eq_zero_iff Nat.div_eq_zero_iff
+
+protected lemma div_ne_zero_iff (hb : b ≠ 0) : a / b ≠ 0 ↔ b ≤ a := by
+  rw [ne_eq, Nat.div_eq_zero_iff (Nat.pos_of_ne_zero hb), not_lt]
+
+protected lemma div_pos_iff (hb : b ≠ 0) : 0 < a / b ↔ b ≤ a := by
+  rw [Nat.pos_iff_ne_zero, Nat.div_ne_zero_iff hb]
+
 lemma mul_div_mul_comm_of_dvd_dvd (hba : b ∣ a) (hdc : d ∣ c) :
     a * c / (b * d) = a / b * (c / d) := by
   obtain rfl | hb := b.eq_zero_or_pos; · simp
@@ -1214,6 +1270,155 @@ lemma mul_add_mod_of_lt (h : c < b) : (a * b + c) % b = c := by
   rw [Nat.mul_add_mod', Nat.mod_eq_of_lt h]
 #align nat.mul_add_mod_of_lt Nat.mul_add_mod_of_lt
 
+set_option linter.deprecated false in
+@[simp]
+protected theorem not_two_dvd_bit1 (n : ℕ) : ¬2 ∣ bit1 n := by
+  rw [bit1, Nat.dvd_add_right, Nat.dvd_one]
+  -- Porting note: was `cc`
+  decide
+  rw [bit0, ← Nat.two_mul]
+  exact Nat.dvd_mul_right _ _
+#align nat.not_two_dvd_bit1 Nat.not_two_dvd_bit1
+
+/-- A natural number `m` divides the sum `m + n` if and only if `m` divides `n`.-/
+@[simp] protected lemma dvd_add_self_left : m ∣ m + n ↔ m ∣ n := Nat.dvd_add_right (Nat.dvd_refl m)
+#align nat.dvd_add_self_left Nat.dvd_add_self_left
+
+/-- A natural number `m` divides the sum `n + m` if and only if `m` divides `n`.-/
+@[simp] protected lemma dvd_add_self_right : m ∣ n + m ↔ m ∣ n := Nat.dvd_add_left (Nat.dvd_refl m)
+#align nat.dvd_add_self_right Nat.dvd_add_self_right
+
+-- TODO: update `Nat.dvd_sub` in core
+lemma dvd_sub' (h₁ : k ∣ m) (h₂ : k ∣ n) : k ∣ m - n := by
+  rcases le_total n m with H | H
+  · exact dvd_sub H h₁ h₂
+  · rw [Nat.sub_eq_zero_iff_le.mpr H]
+    exact Nat.dvd_zero k
+#align nat.dvd_sub' Nat.dvd_sub'
+
+lemma succ_div : ∀ a b : ℕ, (a + 1) / b = a / b + if b ∣ a + 1 then 1 else 0
+  | a, 0 => by simp
+  | 0, 1 => by simp
+  | 0, b + 2 => by
+    have hb2 : b + 2 > 1 := by simp
+    simp [ne_of_gt hb2, div_eq_of_lt hb2]
+  | a + 1, b + 1 => by
+    rw [Nat.div_eq]
+    conv_rhs => rw [Nat.div_eq]
+    by_cases hb_eq_a : b = a + 1
+    · simp [hb_eq_a, Nat.le_refl, Nat.not_succ_le_self, Nat.dvd_refl]
+    by_cases hb_le_a1 : b ≤ a + 1
+    · have hb_le_a : b ≤ a := le_of_lt_succ (lt_of_le_of_ne hb_le_a1 hb_eq_a)
+      have h₁ : 0 < b + 1 ∧ b + 1 ≤ a + 1 + 1 := ⟨succ_pos _, Nat.add_le_add_iff_right.2 hb_le_a1⟩
+      have h₂ : 0 < b + 1 ∧ b + 1 ≤ a + 1 := ⟨succ_pos _, Nat.add_le_add_iff_right.2 hb_le_a⟩
+      have dvd_iff : b + 1 ∣ a - b + 1 ↔ b + 1 ∣ a + 1 + 1 := by
+        rw [Nat.dvd_add_iff_left (Nat.dvd_refl (b + 1)), ← Nat.add_sub_add_right a 1 b,
+          Nat.add_comm (_ - _), Nat.add_assoc, Nat.sub_add_cancel (succ_le_succ hb_le_a),
+          Nat.add_comm 1]
+      have wf : a - b < a + 1 := lt_succ_of_le (Nat.sub_le _ _)
+      rw [if_pos h₁, if_pos h₂, Nat.add_sub_add_right, Nat.add_sub_add_right, Nat.add_comm a,
+        Nat.add_sub_assoc hb_le_a, Nat.add_comm 1,
+        have := wf
+        succ_div (a - b)]
+      simp [dvd_iff, succ_eq_add_one, Nat.add_comm 1, Nat.add_assoc]
+    · have hba : ¬b ≤ a := not_le_of_gt (lt_trans (lt_succ_self a) (lt_of_not_ge hb_le_a1))
+      have hb_dvd_a : ¬b + 1 ∣ a + 2 := fun h =>
+        hb_le_a1 (le_of_succ_le_succ (le_of_dvd (succ_pos _) h))
+      simp [hba, hb_le_a1, hb_dvd_a]
+#align nat.succ_div Nat.succ_div
+
+lemma succ_div_of_dvd (hba : b ∣ a + 1) : (a + 1) / b = a / b + 1 := by rw [succ_div, if_pos hba]
+#align nat.succ_div_of_dvd Nat.succ_div_of_dvd
+
+lemma succ_div_of_not_dvd (hba : ¬b ∣ a + 1) : (a + 1) / b = a / b := by
+  rw [succ_div, if_neg hba, Nat.add_zero]
+#align nat.succ_div_of_not_dvd Nat.succ_div_of_not_dvd
+
+lemma dvd_iff_div_mul_eq (n d : ℕ) : d ∣ n ↔ n / d * d = n :=
+  ⟨fun h => Nat.div_mul_cancel h, fun h => by rw [← h]; exact Nat.dvd_mul_left _ _⟩
+#align nat.dvd_iff_div_mul_eq Nat.dvd_iff_div_mul_eq
+
+lemma dvd_iff_le_div_mul (n d : ℕ) : d ∣ n ↔ n ≤ n / d * d :=
+  ((dvd_iff_div_mul_eq _ _).trans le_antisymm_iff).trans (and_iff_right (div_mul_le_self n d))
+#align nat.dvd_iff_le_div_mul Nat.dvd_iff_le_div_mul
+
+lemma dvd_iff_dvd_dvd (n d : ℕ) : d ∣ n ↔ ∀ k : ℕ, k ∣ d → k ∣ n :=
+  ⟨fun h _ hkd => Nat.dvd_trans hkd h, fun h => h _ (Nat.dvd_refl _)⟩
+#align nat.dvd_iff_dvd_dvd Nat.dvd_iff_dvd_dvd
+
+lemma dvd_div_of_mul_dvd (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⟩
+#align nat.dvd_div_of_mul_dvd Nat.dvd_div_of_mul_dvd
+
+@[simp] lemma dvd_div_iff (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⟩
+#align nat.dvd_div_iff Nat.dvd_div_iff
+
+@[simp] lemma div_div_div_eq_div (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)]
+#align nat.div_div_div_eq_div Nat.div_div_div_eq_div
+
+/-- If a small natural number is divisible by a larger natural number,
+the small number is zero. -/
+lemma eq_zero_of_dvd_of_lt (w : a ∣ b) (h : b < a) : b = 0 :=
+  Nat.eq_zero_of_dvd_of_div_eq_zero w ((Nat.div_eq_zero_iff (lt_of_le_of_lt (zero_le b) h)).mpr h)
+#align nat.eq_zero_of_dvd_of_lt Nat.eq_zero_of_dvd_of_lt
+
+lemma le_of_lt_add_of_dvd (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)
+#align nat.le_of_lt_add_of_dvd Nat.le_of_lt_add_of_dvd
+
+/-- `n` is not divisible by `a` iff it is between `a * k` and `a * (k + 1)` for some `k`. -/
+lemma not_dvd_iff_between_consec_multiples (n : ℕ) {a : ℕ} (ha : 0 < a) :
+    (∃ k : ℕ, a * k < n ∧ n < a * (k + 1)) ↔ ¬a ∣ n := by
+  refine'
+    ⟨fun ⟨k, hk1, hk2⟩ => not_dvd_of_between_consec_multiples hk1 hk2, fun han =>
+      ⟨n / a, ⟨lt_of_le_of_ne (mul_div_le n a) _, lt_mul_div_succ _ ha⟩⟩⟩
+  exact mt (⟨n / a, Eq.symm ·⟩) han
+#align nat.not_dvd_iff_between_consec_multiples Nat.not_dvd_iff_between_consec_multiples
+
+/-- Two natural numbers are equal if and only if they have the same multiples. -/
+lemma dvd_right_iff_eq : (∀ a : ℕ, m ∣ a ↔ n ∣ a) ↔ m = n :=
+  ⟨fun h => Nat.dvd_antisymm ((h _).mpr (Nat.dvd_refl _)) ((h _).mp (Nat.dvd_refl _)),
+    fun h n => by rw [h]⟩
+#align nat.dvd_right_iff_eq Nat.dvd_right_iff_eq
+
+/-- Two natural numbers are equal if and only if they have the same divisors. -/
+lemma dvd_left_iff_eq : (∀ a : ℕ, a ∣ m ↔ a ∣ n) ↔ m = n :=
+  ⟨fun h => Nat.dvd_antisymm ((h _).mp (Nat.dvd_refl _)) ((h _).mpr (Nat.dvd_refl _)),
+    fun h n => by rw [h]⟩
+#align nat.dvd_left_iff_eq Nat.dvd_left_iff_eq
+
+/-- `dvd` is injective in the left argument -/
+lemma dvd_left_injective : Function.Injective ((· ∣ ·) : ℕ → ℕ → Prop) := fun _ _ h =>
+  dvd_right_iff_eq.mp fun a => iff_of_eq (congr_fun h a)
+#align nat.dvd_left_injective Nat.dvd_left_injective
+
+lemma div_lt_div_of_lt_of_dvd {a b d : ℕ} (hdb : d ∣ b) (h : a < b) : a / d < b / d := by
+  rw [Nat.lt_div_iff_mul_lt hdb]
+  exact lt_of_le_of_lt (mul_div_le a d) h
+#align nat.div_lt_div_of_lt_of_dvd Nat.div_lt_div_of_lt_of_dvd
+
 /-! ### `find` -/
 
 section Find
chore: Split Data.{Nat,Int}{.Order}.Basic in group vs ring instances (#11924)

Scatter the content of Data.Nat.Basic across:

  • Data.Nat.Defs for the lemmas having no dependencies
  • Algebra.Group.Nat for the monoid instances and the few miscellaneous lemmas needing them.
  • Algebra.Ring.Nat for the semiring instance and the few miscellaneous lemmas following it.

Similarly, scatter

  • Data.Int.Basic across Data.Int.Defs, Algebra.Group.Int, Algebra.Ring.Int
  • Data.Nat.Order.Basic across Data.Nat.Defs, Algebra.Order.Group.Nat, Algebra.Order.Ring.Nat
  • Data.Int.Order.Basic across Data.Int.Defs, Algebra.Order.Group.Int, Algebra.Order.Ring.Int

Also move a few lemmas from Data.Nat.Order.Lemmas to Data.Nat.Defs.

Before pre_11924

After post_11924

chore: Split Data.{Nat,Int}{.Order}.Basic in group vs ring instances (#11924)

Scatter the content of Data.Nat.Basic across:

  • Data.Nat.Defs for the lemmas having no dependencies
  • Algebra.Group.Nat for the monoid instances and the few miscellaneous lemmas needing them.
  • Algebra.Ring.Nat for the semiring instance and the few miscellaneous lemmas following it.

Similarly, scatter

  • Data.Int.Basic across Data.Int.Defs, Algebra.Group.Int, Algebra.Ring.Int
  • Data.Nat.Order.Basic across Data.Nat.Defs, Algebra.Order.Group.Nat, Algebra.Order.Ring.Nat
  • Data.Int.Order.Basic across Data.Int.Defs, Algebra.Order.Group.Int, Algebra.Order.Ring.Int

Also move a few lemmas from Data.Nat.Order.Lemmas to Data.Nat.Defs.

Before pre_11924

After post_11924

chore(Data/List): Do not depend on algebra (#11845)

Remove dependencies on algebra in the Data.List folder except for:

  • Data.List.EditDistance: Actually relies on algebra. Maybe should be moved?
  • Data.List.Card: Completely unused and redundant.
  • Data.List.Cycle: Relies on Fintype, which shouldn't rely on algebra but it's hard to fix right now. Maybe should be moved?
  • Data.List.Func: Completely unused and redundant.
  • Data.List.Lex: That's order theory. Could be moved.
  • Data.List.Prime. That's algebra. Should definitely be moved.
  • Data.List.Sym: Relies on Multiset, which shouldn't rely on algebra but it's hard to fix right now. Maybe should be moved?
  • Data.List.ToFinsupp: That's algebra. Should definitely be moved.

As a consequence, move the big operators lemmas that were in there to Algebra.BigOperators.List.Basic. For the lemmas that were Nat-specific and not about auxiliary definitions, keep a version of them in the original file but stated using Nat.sum.

Before pre_11845

After post_11845

Diff
@@ -323,10 +323,16 @@ theorem le_or_le_of_add_eq_add_pred (h : a + c = b + d - 1) : b ≤ a ∨ d ≤
 
 /-! ### `sub` -/
 
+attribute [simp] Nat.sub_eq_zero_of_le Nat.sub_le_iff_le_add
+
 /-- A version of `Nat.sub_succ` in the form `_ - 1` instead of `Nat.pred _`. -/
 lemma sub_succ' (m n : ℕ) : m - n.succ = m - n - 1 := rfl
 #align nat.sub_succ' Nat.sub_succ'
 
+protected lemma sub_eq_of_eq_add' (h : a = b + c) : a - b = c := by rw [h, Nat.add_sub_cancel_left]
+protected lemma eq_sub_of_add_eq (h : c + b = a) : c = a - b := (Nat.sub_eq_of_eq_add h.symm).symm
+protected lemma eq_sub_of_add_eq' (h : b + c = a) : c = a - b := (Nat.sub_eq_of_eq_add' h.symm).symm
+
 protected lemma lt_sub_iff_add_lt : a < c - b ↔ a + b < c := ⟨add_lt_of_lt_sub, lt_sub_of_add_lt⟩
 protected lemma lt_sub_iff_add_lt' : a < c - b ↔ b + a < c := by omega
 protected lemma sub_lt_iff_lt_add (hba : b ≤ a) : a - b < c ↔ a < b + c := by omega
chore(Algebra/BigOperators/List): Use Std lemmas (#11725)
  • Make Algebra.BigOperators.List.Basic, Data.List.Chain not depend on Data.Nat.Order.Basic by using Nat-specific Std lemmas rather than general mathlib ones. I leave the Data.Nat.Basic import since Algebra.BigOperators.List.Basic is algebra territory.
  • Make Algebra.BigOperators.List.Basic not depend on Algebra.Divisibility.Basic. I'm not too sure about that one since they already are algebra. My motivation is that they involve ring-like objects while big operators are about group-like objects, but this is in some sense a second order refactor.
  • As a consequence, move the divisibility and MonoidWithZero lemmas from Algebra.BigOperators.List.Basic to Algebra.BigOperators.List.Lemmas.
  • Move the content of Algebra.BigOperators.List.Defs to Algebra.BigOperators.List.Basic since no file imported the former without the latter and their imports are becoming very close after this PR.
  • Make Data.List.Count, Data.List.Dedup, Data.List.ProdSigma, Data.List.Zip not depend on Algebra.BigOperators.List.Basic.
  • As a consequence, move the big operators lemmas that were in there to Algebra.BigOperators.List.Basic. For the lemmas that were Nat -specific, keep a version of them stated using Nat.sum.
  • To help with this, add Nat.sum_eq_listSum (l : List Nat) : Nat.sum l = l.sum.
Diff
@@ -57,6 +57,8 @@ attribute [simp] Nat.not_lt_zero Nat.succ_ne_zero Nat.succ_ne_self Nat.zero_ne_o
   -- Nat.zero_ne_bit1 Nat.bit1_ne_zero Nat.bit0_ne_one Nat.one_ne_bit0 Nat.bit0_ne_bit1
   -- Nat.bit1_ne_bit0
 
+attribute [simp] Nat.min_eq_left Nat.min_eq_right
+
 /-! ### `succ`, `pred` -/
 
 lemma succ_pos' : 0 < succ n := succ_pos n
chore: reduce mathlib dependencies in Data.Nat.Defs (#11918)

It seems that most of this file belongs in Std. This changes some proofs to avoid dependencies on mathlib, notably on the typeclass-mediated order lemmas.

Diff
@@ -9,7 +9,6 @@ import Mathlib.Logic.Nontrivial.Defs
 import Mathlib.Tactic.Cases
 import Mathlib.Tactic.GCongr.Core
 import Mathlib.Tactic.PushNeg
-import Mathlib.Tactic.Use
 import Mathlib.Util.AssertExists
 
 #align_import data.nat.basic from "leanprover-community/mathlib"@"bd835ef554f37ef9b804f0903089211f89cb370b"
@@ -88,7 +87,7 @@ lemma succ_succ_ne_one (n : ℕ) : n.succ.succ ≠ 1 := by simp
 alias _root_.LT.lt.nat_succ_le := succ_le_of_lt
 #align has_lt.lt.nat_succ_le LT.lt.nat_succ_le
 
-lemma not_succ_lt_self : ¬ succ n < n := not_lt_of_ge n.le_succ
+lemma not_succ_lt_self : ¬ succ n < n := Nat.not_lt_of_ge n.le_succ
 #align nat.not_succ_lt_self Nat.not_succ_lt_self
 
 #align nat.lt_succ_iff Nat.lt_succ_iff
@@ -97,10 +96,10 @@ lemma succ_le_iff : succ m ≤ n ↔ m < n := ⟨lt_of_succ_le, succ_le_of_lt⟩
 #align nat.succ_le_iff Nat.succ_le_iff
 
 lemma le_succ_iff : m ≤ n.succ ↔ m ≤ n ∨ m = n.succ := by
-  refine ⟨fun hmn ↦ (lt_or_eq_of_le hmn).imp_left le_of_lt_succ, ?_⟩
+  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
-  · rfl
+  · exact Nat.le_refl _
 
 alias ⟨of_le_succ, _⟩ := le_succ_iff
 #align nat.of_le_succ Nat.of_le_succ
@@ -113,7 +112,7 @@ lemma lt_iff_le_pred : ∀ {n}, 0 < n → (m < n ↔ m ≤ n - 1) | _ + 1, _ =>
 #align nat.lt_iff_le_pred Nat.lt_iff_le_pred
 
 lemma le_of_pred_lt : ∀ {m}, pred m < n → m ≤ n
-  | 0 => le_of_lt
+  | 0 => Nat.le_of_lt
   | _ + 1 => id
 #align nat.le_of_pred_lt Nat.le_of_pred_lt
 
@@ -150,7 +149,7 @@ lemma le_one_iff_eq_zero_or_eq_one : ∀ {n : ℕ}, n ≤ 1 ↔ n = 0 ∨ n = 1
 @[simp] lemma lt_one_iff : n < 1 ↔ n = 0 := Nat.lt_succ_iff.trans $ by rw [le_zero_eq]
 #align nat.lt_one_iff Nat.lt_one_iff
 
-lemma one_le_of_lt (h : a < b) : 1 ≤ b := lt_of_le_of_lt (Nat.zero_le _) h
+lemma one_le_of_lt (h : a < b) : 1 ≤ b := Nat.lt_of_le_of_lt (Nat.zero_le _) h
 #align nat.one_le_of_lt Nat.one_le_of_lt
 
 @[simp] lemma min_eq_zero_iff : min m n = 0 ↔ m = 0 ∨ n = 0 := by omega
@@ -295,11 +294,11 @@ lemma add_eq_three_iff :
 #align nat.add_eq_three_iff Nat.add_eq_three_iff
 
 lemma le_add_one_iff : m ≤ n + 1 ↔ m ≤ n ∨ m = n + 1 := by
-  rw [le_iff_lt_or_eq, lt_add_one_iff]
+  rw [Nat.le_iff_lt_or_eq, lt_add_one_iff]
 #align nat.le_add_one_iff Nat.le_add_one_iff
 
 lemma le_and_le_add_one_iff : n ≤ m ∧ m ≤ n + 1 ↔ m = n ∨ m = n + 1 := by
-  rw [le_add_one_iff, and_or_left, ← le_antisymm_iff, eq_comm, and_iff_right_of_imp]
+  rw [le_add_one_iff, and_or_left, ← Nat.le_antisymm_iff, eq_comm, and_iff_right_of_imp]
   rintro rfl
   exact n.le_succ
 #align nat.le_and_le_add_one_iff Nat.le_and_le_add_one_iff
@@ -356,7 +355,7 @@ protected lemma zero_eq_mul : 0 = m * n ↔ m = 0 ∨ n = 0 := by rw [eq_comm, N
 #align nat.zero_eq_mul Nat.zero_eq_mul
 
 lemma two_mul_ne_two_mul_add_one : 2 * n ≠ 2 * m + 1 :=
-  mt (congr_arg (· % 2))
+  mt (congrArg (· % 2))
     (by rw [Nat.add_comm, add_mul_mod_self_left, mul_mod_right, mod_eq_of_lt] <;> simp)
 #align nat.two_mul_ne_two_mul_add_one Nat.two_mul_ne_two_mul_add_one
 
@@ -368,10 +367,12 @@ protected lemma mul_left_inj (ha : a ≠ 0) : b * a = c * a ↔ b = c :=
 protected lemma 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 lemma mul_ne_mul_left (ha : a ≠ 0) : b * a ≠ c * a ↔ b ≠ c := (Nat.mul_left_inj ha).not
+protected lemma mul_ne_mul_left (ha : a ≠ 0) : b * a ≠ c * a ↔ b ≠ c :=
+  not_congr (Nat.mul_left_inj ha)
 #align nat.mul_ne_mul_left Nat.mul_ne_mul_left
 
-protected lemma mul_ne_mul_right (ha : a ≠ 0) : a * b ≠ a * c ↔ b ≠ c := (Nat.mul_right_inj ha).not
+protected lemma mul_ne_mul_right (ha : a ≠ 0) : a * b ≠ a * c ↔ b ≠ c :=
+  not_congr (Nat.mul_right_inj ha)
 #align nat.mul_ne_mul_right Nat.mul_ne_mul_right
 
 lemma mul_eq_left (ha : a ≠ 0) : a * b = a ↔ b = 1 := by simpa using Nat.mul_right_inj ha (c := 1)
@@ -418,7 +419,7 @@ lemma eq_zero_of_double_le (h : 2 * n ≤ n) : n = 0 := by omega
 #align nat.eq_zero_of_double_le Nat.eq_zero_of_double_le
 
 lemma eq_zero_of_mul_le (hb : 2 ≤ n) (h : n * m ≤ m) : m = 0 :=
-  eq_zero_of_double_le <| le_trans (Nat.mul_le_mul_right _ hb) h
+  eq_zero_of_double_le <| Nat.le_trans (Nat.mul_le_mul_right _ hb) h
 #align nat.eq_zero_of_mul_le Nat.eq_zero_of_mul_le
 
 lemma succ_mul_pos (m : ℕ) (hn : 0 < n) : 0 < succ m * n := Nat.mul_pos m.succ_pos hn
@@ -428,25 +429,27 @@ lemma mul_self_le_mul_self (h : m ≤ n) : m * m ≤ n * n := Nat.mul_le_mul h h
 #align nat.mul_self_le_mul_self Nat.mul_self_le_mul_self
 
 lemma mul_lt_mul'' (hac : a < c) (hbd : b < d) : a * b < c * d :=
-  Nat.mul_lt_mul_of_lt_of_le hac (le_of_lt hbd) $ by omega
+  Nat.mul_lt_mul_of_lt_of_le hac (Nat.le_of_lt hbd) $ by omega
 
 lemma mul_self_lt_mul_self (h : m < n) : m * m < n * n := mul_lt_mul'' h h
 #align nat.mul_self_lt_mul_self Nat.mul_self_lt_mul_self
 
 lemma mul_self_le_mul_self_iff : m * m ≤ n * n ↔ m ≤ n :=
-  ⟨le_imp_le_of_lt_imp_lt mul_self_lt_mul_self, mul_self_le_mul_self⟩
+  ⟨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⟩
 #align nat.mul_self_le_mul_self_iff Nat.mul_self_le_mul_self_iff
 
 lemma mul_self_lt_mul_self_iff : m * m < n * n ↔ m < n := by
-  simp only [← not_le, mul_self_le_mul_self_iff]
+  simp only [← Nat.not_le, mul_self_le_mul_self_iff]
 #align nat.mul_self_lt_mul_self_iff Nat.mul_self_lt_mul_self_iff
 
 lemma le_mul_self : ∀ n : ℕ, n ≤ n * n
-  | 0 => le_refl _
+  | 0 => Nat.le_refl _
   | n + 1 => by simp [Nat.mul_add]
 #align nat.le_mul_self Nat.le_mul_self
 
-lemma mul_self_inj : m * m = n * n ↔ m = n := by simp [le_antisymm_iff, mul_self_le_mul_self_iff]
+lemma mul_self_inj : m * m = n * n ↔ m = n := by
+  simp [Nat.le_antisymm_iff, mul_self_le_mul_self_iff]
 #align nat.mul_self_inj Nat.mul_self_inj
 
 @[simp] lemma lt_mul_self_iff : ∀ {n : ℕ}, n < n * n ↔ 1 < n
@@ -486,19 +489,20 @@ lemma le_div_iff_mul_le' (hb : 0 < b) : a ≤ c / b ↔ a * b ≤ c := le_div_if
 #align nat.le_div_iff_mul_le' Nat.le_div_iff_mul_le'
 
 lemma div_lt_iff_lt_mul' (hb : 0 < b) : a / b < c ↔ a < c * b := by
-  simp only [← not_le, le_div_iff_mul_le' hb]
+  simp only [← Nat.not_le, le_div_iff_mul_le' hb]
 #align nat.div_lt_iff_lt_mul' Nat.div_lt_iff_lt_mul'
 
 lemma one_le_div_iff (hb : 0 < b) : 1 ≤ a / b ↔ b ≤ a := by rw [le_div_iff_mul_le hb, Nat.one_mul]
 #align nat.one_le_div_iff Nat.one_le_div_iff
 
-lemma div_lt_one_iff (hb : 0 < b) : a / b < 1 ↔ a < b := by simp only [← not_le, one_le_div_iff hb]
+lemma div_lt_one_iff (hb : 0 < b) : a / b < 1 ↔ a < b := by
+  simp only [← Nat.not_le, one_le_div_iff hb]
 #align nat.div_lt_one_iff Nat.div_lt_one_iff
 
 @[gcongr]
 protected lemma div_le_div_right (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 <| le_trans (Nat.div_mul_le_self _ _) h
+    (le_div_iff_mul_le' hc).2 <| Nat.le_trans (Nat.div_mul_le_self _ _) h
 #align nat.div_le_div_right Nat.div_le_div_right
 
 lemma lt_of_div_lt_div (h : a / c < b / c) : a < b :=
@@ -506,7 +510,7 @@ lemma lt_of_div_lt_div (h : a / c < b / c) : a < b :=
 #align nat.lt_of_div_lt_div Nat.lt_of_div_lt_div
 
 protected lemma div_pos (hba : b ≤ a) (hb : 0 < b) : 0 < a / b :=
-  Nat.pos_of_ne_zero fun h ↦ lt_irrefl a $
+  Nat.pos_of_ne_zero fun h ↦ Nat.lt_irrefl a $
     calc
       a = a % b := by simpa [h] using (mod_add_div a b).symm
       _ < b := mod_lt a hb
@@ -514,7 +518,7 @@ protected lemma div_pos (hba : b ≤ a) (hb : 0 < b) : 0 < a / b :=
 #align nat.div_pos Nat.div_pos
 
 lemma lt_mul_of_div_lt (h : a / c < b) (hc : 0 < c) : a < b * c :=
-  lt_of_not_ge <| not_le_of_gt h ∘ (Nat.le_div_iff_mul_le hc).2
+  Nat.lt_of_not_ge <| Nat.not_le_of_gt h ∘ (Nat.le_div_iff_mul_le hc).2
 #align nat.lt_mul_of_div_lt Nat.lt_mul_of_div_lt
 
 lemma mul_div_le_mul_div_assoc (a b c : ℕ) : a * (b / c) ≤ a * b / c :=
@@ -544,7 +548,7 @@ lemma lt_div_mul_add (hb : 0 < b) : a < a / b * b + b := by
 
 @[simp]
 protected lemma div_left_inj (hda : d ∣ a) (hdb : d ∣ b) : a / d = b / d ↔ a = b := by
-  refine ⟨fun h ↦ ?_, congr_arg fun b ↦ b / d⟩
+  refine ⟨fun h ↦ ?_, congrArg fun b ↦ b / d⟩
   rw [← Nat.mul_div_cancel' hda, ← Nat.mul_div_cancel' hdb, h]
 #align nat.div_left_inj Nat.div_left_inj
 
@@ -560,27 +564,27 @@ lemma div_mul_div_comm : b ∣ a → d ∣ c → (a / b) * (c / d) = (a * c) / (
 
 lemma 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' (lt_of_lt_of_le (by decide) hn)).1 h
+    rw [Nat.mul_comm]; exact (Nat.le_div_iff_mul_le' (Nat.lt_of_lt_of_le (by decide) hn)).1 h
 #align nat.eq_zero_of_le_div Nat.eq_zero_of_le_div
 
 lemma div_mul_div_le_div (a b c : ℕ) : a / c * b / a ≤ b / c := by
-  obtain rfl | ha := eq_or_ne a 0
+  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 _ _ (Nat.pos_of_ne_zero ha)]
+          Nat.mul_div_mul_left _ _ ha]
 #align nat.div_mul_div_le_div Nat.div_mul_div_le_div
 
-lemma eq_zero_of_le_half (h : n ≤ n / 2) : n = 0 := eq_zero_of_le_div (le_refl _) h
+lemma eq_zero_of_le_half (h : n ≤ n / 2) : n = 0 := eq_zero_of_le_div (Nat.le_refl _) h
 #align nat.eq_zero_of_le_half Nat.eq_zero_of_le_half
 
 lemma le_half_of_half_lt_sub (h : a / 2 < a - b) : b ≤ a / 2 := by
   rw [Nat.le_div_iff_mul_le Nat.two_pos]
   rw [Nat.div_lt_iff_lt_mul Nat.two_pos, Nat.mul_sub_right_distrib, Nat.lt_sub_iff_add_lt,
     Nat.mul_two a] at h
-  exact le_of_lt (Nat.lt_of_add_lt_add_left h)
+  exact Nat.le_of_lt (Nat.lt_of_add_lt_add_left h)
 #align nat.le_half_of_half_lt_sub Nat.le_half_of_half_lt_sub
 
 lemma half_le_of_sub_le_half (h : a - b ≤ a / 2) : a / 2 ≤ b := by
@@ -615,7 +619,7 @@ lemma two_mul_odd_div_two (hn : n % 2 = 1) : 2 * (n / 2) = n - 1 := by
 
 @[gcongr]
 lemma div_le_div_left (hcb : c ≤ b) (hc : 0 < c) : a / b ≤ a / c :=
-  (Nat.le_div_iff_mul_le hc).2 <| le_trans (Nat.mul_le_mul_left _ hcb) (div_mul_le_self _ _)
+  (Nat.le_div_iff_mul_le hc).2 <| Nat.le_trans (Nat.mul_le_mul_left _ hcb) (div_mul_le_self _ _)
 #align nat.div_le_div_left Nat.div_le_div_left
 
 lemma div_eq_self : m / n = m ↔ m = 0 ∨ n = 1 := by
@@ -671,7 +675,7 @@ protected lemma pow_lt_pow_right (ha : 1 < a) (h : m < n) : a ^ m < a ^ n :=
   (Nat.pow_lt_pow_iff_right ha).2 h
 
 protected lemma pow_le_pow_iff_left {n : ℕ} (hn : n ≠ 0) : a ^ n ≤ b ^ n ↔ a ≤ b where
-  mp := by simpa only [← Nat.not_le, not_imp_not] using (Nat.pow_lt_pow_left · hn)
+  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 _
 #align nat.pow_le_iff_le_left Nat.pow_le_pow_iff_left
 
@@ -738,7 +742,7 @@ lemma one_lt_two_pow' (n : ℕ) : 1 < 2 ^ (n + 1) := one_lt_pow n.succ_ne_zero (
 #align nat.one_lt_two_pow' Nat.one_lt_two_pow'
 
 lemma 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 (lt_trans Nat.zero_lt_one hb)]
+  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 _)
 #align nat.mul_lt_mul_pow_succ Nat.mul_lt_mul_pow_succ
@@ -811,39 +815,45 @@ lemma leRecOn_succ' {C : ℕ → Sort*} {n} {h : n ≤ n + 1} {next : ∀ {k}, C
 #align nat.le_rec_on_succ' Nat.leRecOn_succ'
 
 lemma leRecOn_trans {C : ℕ → Sort*} {n m k} (hnm : n ≤ m) (hmk : m ≤ k) {next} (x : C n) :
-    (leRecOn (le_trans hnm hmk) (@next) x : C k) = leRecOn hmk (@next) (leRecOn hnm (@next) x) := by
-  induction' hmk with k hmk ih
-  · rw [leRecOn_self]
-  · rw [leRecOn_succ (le_trans hnm hmk), ih, leRecOn_succ]
+    (leRecOn (Nat.le_trans hnm hmk) (@next) x : C k) =
+      leRecOn hmk (@next) (leRecOn hnm (@next) x) := by
+  induction hmk with
+  | refl => rw [leRecOn_self]
+  | step hmk ih => rw [leRecOn_succ (Nat.le_trans hnm hmk), ih, leRecOn_succ]
 #align nat.le_rec_on_trans Nat.leRecOn_trans
 
 lemma leRecOn_succ_left {C : ℕ → Sort*} {n m} (h1 : n ≤ m) (h2 : n + 1 ≤ m)
     {next : ∀ {k}, C k → C (k + 1)} (x : C n) :
     (leRecOn h2 next (next x) : C m) = (leRecOn h1 next x : C m) := by
-  rw [Subsingleton.elim h1 (le_trans (le_succ n) h2), leRecOn_trans (le_succ n) h2, leRecOn_succ']
+  rw [Subsingleton.elim h1 (Nat.le_trans (le_succ n) h2), leRecOn_trans (le_succ n) h2,
+    leRecOn_succ']
 #align nat.le_rec_on_succ_left Nat.leRecOn_succ_left
 
 lemma leRecOn_injective {C : ℕ → Sort*} {n m} (hnm : n ≤ m) (next : ∀ {k}, C k → C (k + 1))
     (Hnext : ∀ n, Injective (@next n)) : Injective (@leRecOn C n m hnm next) := by
-  induction' hnm with m hnm ih
-  · intro x y H
+  induction hnm with
+  | refl =>
+    intro x y H
     rwa [leRecOn_self, leRecOn_self] at H
-  intro x y H
-  rw [leRecOn_succ hnm, leRecOn_succ hnm] at H
-  exact ih (Hnext _ H)
+  | step hnm ih =>
+    intro x y H
+    rw [leRecOn_succ hnm, leRecOn_succ hnm] at H
+    exact ih (Hnext _ H)
 #align nat.le_rec_on_injective Nat.leRecOn_injective
 
 lemma leRecOn_surjective {C : ℕ → Sort*} {n m} (hnm : n ≤ m) (next : ∀ {k}, C k → C (k + 1))
     (Hnext : ∀ n, Surjective (@next n)) : Surjective (@leRecOn C n m hnm next) := by
-  induction' hnm with m hnm ih
-  · intro x
-    use x
+  induction hnm with
+  | refl =>
+    intro x
+    refine ⟨x, ?_⟩
     rw [leRecOn_self]
-  intro x
-  obtain ⟨w, rfl⟩ := Hnext _ x
-  obtain ⟨x, rfl⟩ := ih w
-  use x
-  rw [leRecOn_succ]
+  | step hnm ih =>
+    intro x
+    obtain ⟨w, rfl⟩ := Hnext _ x
+    obtain ⟨x, rfl⟩ := ih w
+    refine ⟨x, ?_⟩
+    rw [leRecOn_succ]
 #align nat.le_rec_on_surjective Nat.leRecOn_surjective
 
 /-- Recursion principle based on `<`. -/
@@ -905,17 +915,18 @@ lemma decreasingInduction_succ' {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P
 
 lemma decreasingInduction_trans {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P n)
     (hmn : m ≤ n) (hnk : n ≤ k) (hP : P k) :
-    (decreasingInduction h (le_trans hmn hnk) hP : P m) =
+    (decreasingInduction h (Nat.le_trans hmn hnk) hP : P m) =
     decreasingInduction h hmn (decreasingInduction h hnk hP) := by
-  induction' hnk with k hnk ih
-  · rw [decreasingInduction_self]
-  · rw [decreasingInduction_succ h (le_trans hmn hnk), ih, decreasingInduction_succ]
+  induction hnk with
+  | refl => rw [decreasingInduction_self]
+  | step hnk ih =>
+      rw [decreasingInduction_succ h (Nat.le_trans hmn hnk), ih, decreasingInduction_succ]
 #align nat.decreasing_induction_trans Nat.decreasingInduction_trans
 
 lemma decreasingInduction_succ_left {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P n)
     (smn : m + 1 ≤ n) (mn : m ≤ n) (hP : P n) :
     decreasingInduction h mn hP = h m (decreasingInduction h smn hP) := by
-  rw [Subsingleton.elim mn (le_trans (le_succ m) smn), decreasingInduction_trans,
+  rw [Subsingleton.elim mn (Nat.le_trans (le_succ m) smn), decreasingInduction_trans,
     decreasingInduction_succ']
   apply Nat.le_succ
 #align nat.decreasing_induction_succ_left Nat.decreasingInduction_succ_left
@@ -975,7 +986,7 @@ theorem diag_induction (P : ℕ → ℕ → Prop) (ha : ∀ a, P (a + 1) (a + 1)
       apply diag_induction P ha hb hd (a + 1) b h
     have _ : a + (b + 1) < (a + 1) + (b + 1) := by simp
     apply diag_induction P ha hb hd a (b + 1)
-    apply lt_of_le_of_lt (Nat.le_succ _) h
+    apply Nat.lt_of_le_of_lt (Nat.le_succ _) h
   termination_by a b _c => a + b
   decreasing_by all_goals assumption
 #align nat.diag_induction Nat.diag_induction
@@ -1022,7 +1033,9 @@ lemma mul_div_mul_comm_of_dvd_dvd (hba : b ∣ a) (hdc : d ∣ c) :
   rw [mul_mod, mod_mod, ← mul_mod]
 
 lemma pow_mod (a b n : ℕ) : a ^ b % n = (a % n) ^ b % n := by
-  induction' b with b ih; rfl; simp [Nat.pow_succ, Nat.mul_mod, ih]
+  induction b with
+  | zero => rfl
+  | succ b ih => simp [Nat.pow_succ, Nat.mul_mod, ih]
 #align nat.pow_mod Nat.pow_mod
 
 lemma not_pos_pow_dvd : ∀ {a n : ℕ} (_ : 1 < a) (_ : 1 < n), ¬ a ^ n ∣ a
@@ -1039,7 +1052,7 @@ lemma not_pos_pow_dvd : ∀ {a n : ℕ} (_ : 1 < a) (_ : 1 < n), ¬ a ^ n ∣ a
 
 lemma 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 lt_of_le_of_lt (le_of_dvd (Nat.pos_iff_ne_zero.2 hb) h) (lt_pow_self ha _)
+  exact Nat.lt_of_le_of_lt (le_of_dvd (Nat.pos_iff_ne_zero.2 hb) h) (lt_pow_self ha _)
 #align nat.lt_of_pow_dvd_right Nat.lt_of_pow_dvd_right
 
 lemma div_dvd_of_dvd (h : n ∣ m) : m / n ∣ m := ⟨n, (Nat.div_mul_cancel h).symm⟩
@@ -1054,8 +1067,8 @@ protected lemma div_div_self (h : n ∣ m) (hm : m ≠ 0) : m / (m / n) = n := b
 lemma 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 lt_irrefl 0 h1
-  · exact not_lt.2 (Nat.le_mul_of_pos_right _ hk) h2
+  · exact Nat.lt_irrefl 0 h1
+  · exact Nat.not_lt.2 (Nat.le_mul_of_pos_right _ hk) h2
 #align nat.not_dvd_of_pos_of_lt Nat.not_dvd_of_pos_of_lt
 
 lemma mod_eq_iff_lt (hn : n ≠ 0) : m % n = m ↔ m < n :=
@@ -1109,7 +1122,7 @@ lemma add_mod_eq_ite :
   · rw [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 _)))
-  · exact Nat.mod_eq_of_lt (lt_of_not_ge h)
+  · exact Nat.mod_eq_of_lt (Nat.lt_of_not_ge h)
 #align nat.add_mod_eq_ite Nat.add_mod_eq_ite
 
 /-- `m` is not divisible by `n` if it is between `n * k` and `n * (k + 1)` for some `k`. -/
@@ -1396,7 +1409,7 @@ instance decidableLoHi (lo hi : ℕ) (P : ℕ → Prop) [H : DecidablePred P] :
 instance decidableLoHiLe (lo hi : ℕ) (P : ℕ → Prop) [DecidablePred P] :
     Decidable (∀ x, lo ≤ x → x ≤ hi → P x) :=
   decidable_of_iff (∀ x, lo ≤ x → x < hi + 1 → P x) <|
-    ball_congr fun _ _ => imp_congr Nat.lt_succ_iff Iff.rfl
+    forall₂_congr fun _ _ ↦ imp_congr Nat.lt_succ_iff Iff.rfl
 #align nat.decidable_lo_hi_le Nat.decidableLoHiLe
 
 end Nat
feat: add some docstrings to lemmas specialized to Nat and Int (#11694)
Diff
@@ -10,6 +10,7 @@ import Mathlib.Tactic.Cases
 import Mathlib.Tactic.GCongr.Core
 import Mathlib.Tactic.PushNeg
 import Mathlib.Tactic.Use
+import Mathlib.Util.AssertExists
 
 #align_import data.nat.basic from "leanprover-community/mathlib"@"bd835ef554f37ef9b804f0903089211f89cb370b"
 
@@ -42,6 +43,9 @@ The names of this file, `Data.Nat.Basic` and `Data.Nat.Order.Basic` are archaic
 with reality anymore. Rename them.
 -/
 
+/- We don't want to import the algebraic hierarchy in this file. -/
+assert_not_exists Monoid
+
 open Function
 
 namespace Nat
@@ -1123,10 +1127,14 @@ protected lemma dvd_add_left (h : a ∣ c) : a ∣ b + c ↔ a ∣ b := (Nat.dvd
 protected lemma dvd_add_right (h : a ∣ b) : a ∣ b + c ↔ a ∣ c := (Nat.dvd_add_iff_right h).symm
 #align nat.dvd_add_right Nat.dvd_add_right
 
+/-- special case of `mul_dvd_mul_iff_left` for `ℕ`.
+Duplicated here to keep simple imports for this file. -/
 protected lemma mul_dvd_mul_iff_left (ha : 0 < a) : a * b ∣ a * c ↔ b ∣ c :=
   exists_congr fun d ↦ by rw [Nat.mul_assoc, Nat.mul_right_inj $ ne_of_gt ha]
 #align nat.mul_dvd_mul_iff_left Nat.mul_dvd_mul_iff_left
 
+/-- special case of `mul_dvd_mul_iff_right` for `ℕ`.
+Duplicated here to keep simple imports for this file. -/
 protected lemma mul_dvd_mul_iff_right (hc : 0 < c) : a * c ∣ b * c ↔ a ∣ b :=
   exists_congr fun d ↦ by rw [Nat.mul_right_comm, Nat.mul_left_inj $ ne_of_gt hc]
 #align nat.mul_dvd_mul_iff_right Nat.mul_dvd_mul_iff_right
chore: avoid Ne.def (adaptation for nightly-2024-03-27) (#11801)
Diff
@@ -1315,7 +1315,7 @@ lemma findGreatest_eq_zero_iff : Nat.findGreatest P k = 0 ↔ ∀ ⦃n⦄, 0 < n
 #align nat.find_greatest_eq_zero_iff Nat.findGreatest_eq_zero_iff
 
 @[simp] lemma findGreatest_pos : 0 < Nat.findGreatest P k ↔ ∃ n, 0 < n ∧ n ≤ k ∧ P n := by
-  rw [Nat.pos_iff_ne_zero, Ne.def, findGreatest_eq_zero_iff]; push_neg; rfl
+  rw [Nat.pos_iff_ne_zero, Ne, findGreatest_eq_zero_iff]; push_neg; rfl
 
 lemma findGreatest_spec (hmb : m ≤ n) (hm : P m) : P (Nat.findGreatest P n) := by
   by_cases h : Nat.findGreatest P n = 0
change the order of operation in zsmulRec and nsmulRec (#11451)

We change the following field in the definition of an additive commutative monoid:

 nsmul_succ : ∀ (n : ℕ) (x : G),
-  AddMonoid.nsmul (n + 1) x = x + AddMonoid.nsmul n x
+  AddMonoid.nsmul (n + 1) x = AddMonoid.nsmul n x + x

where the latter is more natural

We adjust the definitions of ^ in monoids, groups, etc. Originally there was a warning comment about why this natural order was preferred

use x * npowRec n x and not npowRec n x * x in the definition to make sure that definitional unfolding of npowRec is blocked, to avoid deep recursion issues.

but it seems to no longer apply.

Remarks on the PR :

  • pow_succ and pow_succ' have switched their meanings.
  • Most of the time, the proofs were adjusted by priming/unpriming one lemma, or exchanging left and right; a few proofs were more complicated to adjust.
  • In particular, [Mathlib/NumberTheory/RamificationInertia.lean] used Ideal.IsPrime.mul_mem_pow which is defined in [Mathlib/RingTheory/DedekindDomain/Ideal.lean]. Changing the order of operation forced me to add the symmetric lemma Ideal.IsPrime.mem_pow_mul.
  • the docstring for Cauchy condensation test in [Mathlib/Analysis/PSeries.lean] was mathematically incorrect, I added the mention that the function is antitone.
Diff
@@ -56,13 +56,13 @@ instance commSemiring : CommSemiring ℕ where
   mul_comm := Nat.mul_comm
   natCast n := n
   natCast_zero := rfl
-  natCast_succ n := rfl
+  natCast_succ _ := rfl
   nsmul m n := m * n
   nsmul_zero := Nat.zero_mul
-  nsmul_succ _ _ := by dsimp only; rw [Nat.add_comm, Nat.right_distrib, Nat.one_mul]
+  nsmul_succ := succ_mul
   npow m n := n ^ m
   npow_zero := Nat.pow_zero
-  npow_succ _ _ := Nat.pow_succ'
+  npow_succ _ _ := rfl
 
 /-! Extra instances to short-circuit type class resolution and ensure computability -/
 
chore(Data/List): Use Std lemmas (#11711)

Make use of Nat-specific lemmas from Std rather than the general ones provided by mathlib. Also reverse the dependency between Multiset.Nodup/Multiset.dedup and Multiset.sum since only the latter needs algebra. Also rename Algebra.BigOperators.Multiset.Abs to Algebra.BigOperators.Multiset.Order and move some lemmas from Algebra.BigOperators.Multiset.Basic to it.

The ultimate goal here is to carve out Data, Algebra and Order sublibraries.

Diff
@@ -999,6 +999,8 @@ lemma set_induction {S : Set ℕ} (hb : 0 ∈ S) (h_ind : ∀ k : ℕ, k ∈ S 
 #align nat.mod_mul_right_div_self Nat.mod_mul_right_div_self
 #align nat.mod_mul_left_div_self Nat.mod_mul_left_div_self
 
+attribute [simp] Nat.dvd_zero
+
 lemma mul_div_mul_comm_of_dvd_dvd (hba : b ∣ a) (hdc : d ∣ c) :
     a * c / (b * d) = a / b * (c / d) := by
   obtain rfl | hb := b.eq_zero_or_pos; · simp
chore(Data/Nat/Factorial): Use Std lemmas (#11715)

Make use of Nat-specific lemmas from Std rather than the general ones provided by mathlib.

The ultimate goal here is to carve out Data, Algebra and Order sublibraries.

Diff
@@ -636,6 +636,12 @@ lemma div_eq_sub_mod_div : m / n = (m - m % n) / n := by
     rw [this, mul_div_right _ hn]
 #align nat.div_eq_sub_mod_div Nat.div_eq_sub_mod_div
 
+protected lemma 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 lemma 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)]
+
 /-!
 ### `pow`
 
chore(Data/Nat): Use Std lemmas (#11661)

Move basic Nat lemmas from Data.Nat.Order.Basic and Data.Nat.Pow to Data.Nat.Defs. Most proofs need adapting, but that's easily solved by replacing the general mathlib lemmas by the new Std Nat-specific lemmas and using omega.

Other changes

  • Move the last few lemmas left in Data.Nat.Pow to Algebra.GroupPower.Order
  • Move the deprecated aliases from Data.Nat.Pow to Algebra.GroupPower.Order
  • Move the bit/bit0/bit1 lemmas from Data.Nat.Order.Basic to Data.Nat.Bits
  • Fix some fallout from not importing Data.Nat.Order.Basic anymore
  • Add a few Nat-specific lemmas to help fix the fallout (look for nolint simpNF)
  • Turn Nat.mul_self_le_mul_self_iff and Nat.mul_self_lt_mul_self_iff around (they were misnamed)
  • Make more arguments to Nat.one_lt_pow implicit
Diff
@@ -25,10 +25,21 @@ This file contains:
   * `strong_rec'`: recursion based on strong inequalities
 * decidability instances on predicates about the natural numbers
 
-Many theorems that used to live in this file have been moved to `Data.Nat.Order`, so that
-this file requires fewer imports. For each section here there is a corresponding section in
-that file with additional results. It may be possible to move some of these results here,
-by tweaking their proofs.
+## Implementation note
+
+Std has a home-baked development of the algebraic and order theoretic theory of `ℕ` which, in
+particular, is not typeclass-mediated. This is useful to set up the algebra and finiteness libraries
+in mathlib (naturals show up as indices in lists, cardinality in finsets, powers in groups, ...).
+This home-baked development is pursued in this file.
+
+Less basic uses of `ℕ` should however use the typeclass-mediated development. `Data.Nat.Basic` gives
+access to the algebraic instances. `Data.Nat.Order.Basic` is the one giving access to the algebraic
+order instances.
+
+## TODO
+
+The names of this file, `Data.Nat.Basic` and `Data.Nat.Order.Basic` are archaic and don't match up
+with reality anymore. Rename them.
 -/
 
 open Function
@@ -132,9 +143,21 @@ lemma one_lt_iff_ne_zero_and_ne_one : ∀ {n : ℕ}, 1 < n ↔ n ≠ 0 ∧ n ≠
 
 lemma le_one_iff_eq_zero_or_eq_one : ∀ {n : ℕ}, n ≤ 1 ↔ n = 0 ∨ n = 1 := by simp [le_succ_iff]
 
+@[simp] lemma lt_one_iff : n < 1 ↔ n = 0 := Nat.lt_succ_iff.trans $ by rw [le_zero_eq]
+#align nat.lt_one_iff Nat.lt_one_iff
+
+lemma one_le_of_lt (h : a < b) : 1 ≤ b := lt_of_le_of_lt (Nat.zero_le _) h
+#align nat.one_le_of_lt Nat.one_le_of_lt
+
+@[simp] lemma min_eq_zero_iff : min m n = 0 ↔ m = 0 ∨ n = 0 := by omega
+@[simp] lemma max_eq_zero_iff : max m n = 0 ↔ m = 0 ∧ n = 0 := by omega
+#align nat.min_eq_zero_iff Nat.min_eq_zero_iff
+#align nat.max_eq_zero_iff Nat.max_eq_zero_iff
+
 -- Moved to Std
 #align nat.succ_eq_one_add Nat.succ_eq_one_add
 #align nat.one_add Nat.one_add
+#align nat.zero_max Nat.zero_max
 
 lemma pred_eq_sub_one (n : ℕ) : pred n = n - 1 := rfl
 #align nat.pred_eq_sub_one Nat.pred_eq_sub_one
@@ -206,24 +229,127 @@ lemma sub_one_add_self (n : ℕ) : (n - 1) + n = 2 * n - 1 := Nat.add_comm _ n 
 lemma self_add_pred (n : ℕ) : n + pred n = (2 * n).pred := self_add_sub_one n
 lemma pred_add_self (n : ℕ) : pred n + n = (2 * n).pred := sub_one_add_self n
 
+lemma pred_le_iff : pred m ≤ n ↔ m ≤ succ n :=
+  ⟨le_succ_of_pred_le, by cases m; exacts [fun _ ↦ zero_le n, le_of_succ_le_succ]⟩
+#align nat.pred_le_iff Nat.pred_le_iff
+
+lemma lt_of_lt_pred (h : m < n - 1) : m < n := by omega
+#align nat.lt_of_lt_pred Nat.lt_of_lt_pred
+
+lemma le_add_pred_of_pos (a : ℕ) (hb : b ≠ 0) : a ≤ b + (a - 1) := by omega
+#align nat.le_add_pred_of_pos Nat.le_add_pred_of_pos
+
 /-! ### `add` -/
 
+#align nat.add_pos_left Nat.add_pos_left
+#align nat.add_pos_right Nat.add_pos_right
+#align nat.exists_eq_add_of_le Nat.exists_eq_add_of_le
+#align nat.exists_eq_add_of_le' Nat.exists_eq_add_of_le'
+#align nat.exists_eq_add_of_lt Nat.exists_eq_add_of_lt
+
+attribute [simp] le_add_left le_add_right Nat.lt_add_left_iff_pos Nat.lt_add_right_iff_pos
+  Nat.add_le_add_iff_left Nat.add_le_add_iff_right Nat.add_lt_add_iff_left Nat.add_lt_add_iff_right
+  not_lt_zero
+
+-- We want to use these two lemmas earlier than the lemmas simp can prove them with
+@[simp, nolint simpNF] protected alias add_left_inj := Nat.add_right_cancel_iff
+@[simp, nolint simpNF] protected alias add_right_inj := Nat.add_left_cancel_iff
+
 -- Sometimes a bare `Nat.add` or similar appears as a consequence of unfolding during pattern
 -- matching. These lemmas package them back up as typeclass mediated operations.
 @[simp] lemma add_def : Nat.add m n = m + n := rfl
 #align nat.add_def Nat.add_def
 
-#align nat.exists_eq_add_of_le Nat.exists_eq_add_of_le
-#align nat.exists_eq_add_of_le' Nat.exists_eq_add_of_le'
-#align nat.exists_eq_add_of_lt Nat.exists_eq_add_of_lt
+lemma two_le_iff : ∀ n, 2 ≤ n ↔ n ≠ 0 ∧ n ≠ 1
+  | 0 => by simp
+  | 1 => by simp
+  | n + 2 => by simp
+#align nat.two_le_iff Nat.two_le_iff
+
+lemma add_eq_max_iff : m + n = max m n ↔ m = 0 ∨ n = 0 := by omega
+lemma add_eq_min_iff : m + n = min m n ↔ m = 0 ∧ n = 0 := by omega
+#align nat.add_eq_max_iff Nat.add_eq_max_iff
+#align nat.add_eq_min_iff Nat.add_eq_min_iff
+
+-- We want to use this lemma earlier than the lemma simp can prove it with
+@[simp, nolint simpNF] protected lemma add_eq_zero : m + n = 0 ↔ m = 0 ∧ n = 0 := by omega
+
+lemma add_pos_iff_pos_or_pos : 0 < m + n ↔ 0 < m ∨ 0 < n := by omega
+#align nat.add_pos_iff_pos_or_pos Nat.add_pos_iff_pos_or_pos
+
+lemma add_eq_one_iff : m + n = 1 ↔ m = 0 ∧ n = 1 ∨ m = 1 ∧ n = 0 := by
+  cases n <;> simp [succ_eq_add_one, ← Nat.add_assoc, succ_inj']
+#align nat.add_eq_one_iff Nat.add_eq_one_iff
+
+lemma add_eq_two_iff : m + n = 2 ↔ m = 0 ∧ n = 2 ∨ m = 1 ∧ n = 1 ∨ m = 2 ∧ n = 0 := by
+  omega
+#align nat.add_eq_two_iff Nat.add_eq_two_iff
+
+lemma 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
+#align nat.add_eq_three_iff Nat.add_eq_three_iff
+
+lemma le_add_one_iff : m ≤ n + 1 ↔ m ≤ n ∨ m = n + 1 := by
+  rw [le_iff_lt_or_eq, lt_add_one_iff]
+#align nat.le_add_one_iff Nat.le_add_one_iff
+
+lemma le_and_le_add_one_iff : n ≤ m ∧ m ≤ n + 1 ↔ m = n ∨ m = n + 1 := by
+  rw [le_add_one_iff, and_or_left, ← le_antisymm_iff, eq_comm, and_iff_right_of_imp]
+  rintro rfl
+  exact n.le_succ
+#align nat.le_and_le_add_one_iff Nat.le_and_le_add_one_iff
+
+lemma add_succ_lt_add (hab : a < b) (hcd : c < d) : a + c + 1 < b + d := by
+  rw [Nat.add_assoc]; exact Nat.add_lt_add_of_lt_of_le hab (Nat.succ_le_iff.2 hcd)
+#align nat.add_succ_lt_add Nat.add_succ_lt_add
+
+theorem le_or_le_of_add_eq_add_pred (h : a + c = b + d - 1) : b ≤ a ∨ d ≤ c := by
+  rcases le_or_lt b a with h' | h' <;> [left; right]
+  · exact h'
+  · replace h' := Nat.add_lt_add_right h' c
+    rw [h] at h'
+    rcases d.eq_zero_or_pos with hn | hn
+    · rw [hn]
+      exact zero_le c
+    rw [d.add_sub_assoc (Nat.succ_le_of_lt hn), Nat.add_lt_add_iff_left] at h'
+    exact Nat.le_of_pred_lt h'
+#align nat.le_or_le_of_add_eq_add_pred Nat.le_or_le_of_add_eq_add_pred
+
+/-! ### `sub` -/
+
+/-- A version of `Nat.sub_succ` in the form `_ - 1` instead of `Nat.pred _`. -/
+lemma sub_succ' (m n : ℕ) : m - n.succ = m - n - 1 := rfl
+#align nat.sub_succ' Nat.sub_succ'
+
+protected lemma lt_sub_iff_add_lt : a < c - b ↔ a + b < c := ⟨add_lt_of_lt_sub, lt_sub_of_add_lt⟩
+protected lemma lt_sub_iff_add_lt' : a < c - b ↔ b + a < c := by omega
+protected lemma sub_lt_iff_lt_add (hba : b ≤ a) : a - b < c ↔ a < b + c := by omega
+protected lemma sub_lt_iff_lt_add' (hba : b ≤ a) : a - b < c ↔ a < c + b := by omega
+
+protected lemma sub_sub_sub_cancel_right (h : c ≤ b) : a - c - (b - c) = a - b := by omega
+protected lemma add_sub_sub_cancel (h : c ≤ a) : a + b - (a - c) = b + c := by omega
+protected lemma sub_add_sub_cancel (hab : b ≤ a) (hcb : c ≤ b) : a - b + (b - c) = a - c := by omega
+
+lemma lt_pred_iff : a < pred b ↔ succ a < b := Nat.lt_sub_iff_add_lt (b := 1)
+#align nat.lt_pred_iff Nat.lt_pred_iff
+
+protected lemma sub_lt_sub_iff_right (h : c ≤ a) : a - c < b - c ↔ a < b := by omega
 
 /-! ### `mul` -/
 
+#align nat.mul_ne_zero Nat.mul_ne_zero
+#align nat.mul_eq_zero Nat.mul_eq_zero
+#align nat.eq_of_mul_eq_mul_right Nat.eq_of_mul_eq_mul_right
+#align nat.le_mul_of_pos_left Nat.le_mul_of_pos_left
+#align nat.le_mul_of_pos_right Nat.le_mul_of_pos_right
+
 @[simp] lemma mul_def : Nat.mul m n = m * n := rfl
 #align nat.mul_def Nat.mul_def
 
--- Moved to core
-#align nat.eq_of_mul_eq_mul_right Nat.eq_of_mul_eq_mul_right
+-- Porting note: removing `simp` attribute
+protected lemma zero_eq_mul : 0 = m * n ↔ m = 0 ∨ n = 0 := by rw [eq_comm, Nat.mul_eq_zero]
+#align nat.zero_eq_mul Nat.zero_eq_mul
 
 lemma two_mul_ne_two_mul_add_one : 2 * n ≠ 2 * m + 1 :=
   mt (congr_arg (· % 2))
@@ -254,6 +380,9 @@ lemma mul_right_eq_self_iff (ha : 0 < a) : a * b = a ↔ b = 1 := mul_eq_left $
 lemma mul_left_eq_self_iff (hb : 0 < b) : a * b = b ↔ a = 1 := mul_eq_right $ ne_of_gt hb
 #align nat.mul_left_eq_self_iff Nat.mul_left_eq_self_iff
 
+protected lemma le_of_mul_le_mul_right (h : a * c ≤ b * c) (hc : 0 < c) : a ≤ b :=
+  Nat.le_of_mul_le_mul_left (by simpa [Nat.mul_comm]) hc
+
 set_option push_neg.use_distrib true in
 /-- 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. -/
@@ -268,8 +397,75 @@ lemma one_lt_mul_iff : 1 < m * n ↔ 0 < m ∧ 0 < n ∧ (1 < m ∨ 1 < n) := by
     · 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
 
+lemma eq_one_of_mul_eq_one_right (H : m * n = 1) : m = 1 := eq_one_of_dvd_one ⟨n, H.symm⟩
+#align nat.eq_one_of_mul_eq_one_right Nat.eq_one_of_mul_eq_one_right
+
+lemma eq_one_of_mul_eq_one_left (H : m * n = 1) : n = 1 :=
+  eq_one_of_mul_eq_one_right (by rwa [Nat.mul_comm])
+#align nat.eq_one_of_mul_eq_one_left Nat.eq_one_of_mul_eq_one_left
+
+@[simp] protected lemma 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 lemma 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
+
+lemma eq_zero_of_double_le (h : 2 * n ≤ n) : n = 0 := by omega
+#align nat.eq_zero_of_double_le Nat.eq_zero_of_double_le
+
+lemma eq_zero_of_mul_le (hb : 2 ≤ n) (h : n * m ≤ m) : m = 0 :=
+  eq_zero_of_double_le <| le_trans (Nat.mul_le_mul_right _ hb) h
+#align nat.eq_zero_of_mul_le Nat.eq_zero_of_mul_le
+
+lemma succ_mul_pos (m : ℕ) (hn : 0 < n) : 0 < succ m * n := Nat.mul_pos m.succ_pos hn
+#align nat.succ_mul_pos Nat.succ_mul_pos
+
+lemma mul_self_le_mul_self (h : m ≤ n) : m * m ≤ n * n := Nat.mul_le_mul h h
+#align nat.mul_self_le_mul_self Nat.mul_self_le_mul_self
+
+lemma mul_lt_mul'' (hac : a < c) (hbd : b < d) : a * b < c * d :=
+  Nat.mul_lt_mul_of_lt_of_le hac (le_of_lt hbd) $ by omega
+
+lemma mul_self_lt_mul_self (h : m < n) : m * m < n * n := mul_lt_mul'' h h
+#align nat.mul_self_lt_mul_self Nat.mul_self_lt_mul_self
+
+lemma mul_self_le_mul_self_iff : m * m ≤ n * n ↔ m ≤ n :=
+  ⟨le_imp_le_of_lt_imp_lt mul_self_lt_mul_self, mul_self_le_mul_self⟩
+#align nat.mul_self_le_mul_self_iff Nat.mul_self_le_mul_self_iff
+
+lemma mul_self_lt_mul_self_iff : m * m < n * n ↔ m < n := by
+  simp only [← not_le, mul_self_le_mul_self_iff]
+#align nat.mul_self_lt_mul_self_iff Nat.mul_self_lt_mul_self_iff
+
+lemma le_mul_self : ∀ n : ℕ, n ≤ n * n
+  | 0 => le_refl _
+  | n + 1 => by simp [Nat.mul_add]
+#align nat.le_mul_self Nat.le_mul_self
+
+lemma mul_self_inj : m * m = n * n ↔ m = n := by simp [le_antisymm_iff, mul_self_le_mul_self_iff]
+#align nat.mul_self_inj Nat.mul_self_inj
+
+@[simp] lemma lt_mul_self_iff : ∀ {n : ℕ}, n < n * n ↔ 1 < n
+  | 0 => by simp
+  | n + 1 => Nat.lt_mul_iff_one_lt_left n.succ_pos
+#align nat.lt_mul_self_iff Nat.lt_mul_self_iff
+
+lemma 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) _
+#align nat.add_sub_one_le_mul Nat.add_sub_one_le_mul
+
+protected lemma add_le_mul {a : ℕ} (ha : 2 ≤ a) : ∀ {b : ℕ} (_ : 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` -/
 
+#align nat.pow_div Nat.pow_div
+#align nat.div_lt_of_lt_mul Nat.div_lt_of_lt_mul
+
 attribute [simp] Nat.div_self
 
 lemma div_le_iff_le_mul_add_pred (hb : 0 < b) : a / b ≤ c ↔ a ≤ b * c + (b - 1) := by
@@ -358,6 +554,192 @@ lemma div_mul_div_comm : b ∣ a → d ∣ c → (a / b) * (c / d) = (a * c) / (
     Nat.mul_left_comm x, ← Nat.mul_assoc b, Nat.mul_div_cancel_left _ (Nat.mul_pos hb hd)]
 #align nat.div_mul_div_comm Nat.div_mul_div_comm
 
+lemma 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' (lt_of_lt_of_le (by decide) hn)).1 h
+#align nat.eq_zero_of_le_div Nat.eq_zero_of_le_div
+
+lemma div_mul_div_le_div (a b c : ℕ) : a / c * b / a ≤ b / c := by
+  obtain rfl | ha := eq_or_ne a 0
+  · 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 _ _ (Nat.pos_of_ne_zero ha)]
+#align nat.div_mul_div_le_div Nat.div_mul_div_le_div
+
+lemma eq_zero_of_le_half (h : n ≤ n / 2) : n = 0 := eq_zero_of_le_div (le_refl _) h
+#align nat.eq_zero_of_le_half Nat.eq_zero_of_le_half
+
+lemma le_half_of_half_lt_sub (h : a / 2 < a - b) : b ≤ a / 2 := by
+  rw [Nat.le_div_iff_mul_le Nat.two_pos]
+  rw [Nat.div_lt_iff_lt_mul Nat.two_pos, Nat.mul_sub_right_distrib, Nat.lt_sub_iff_add_lt,
+    Nat.mul_two a] at h
+  exact le_of_lt (Nat.lt_of_add_lt_add_left h)
+#align nat.le_half_of_half_lt_sub Nat.le_half_of_half_lt_sub
+
+lemma half_le_of_sub_le_half (h : a - b ≤ a / 2) : a / 2 ≤ b := by
+  rw [Nat.le_div_iff_mul_le Nat.two_pos, Nat.mul_sub_right_distrib, Nat.sub_le_iff_le_add,
+    Nat.mul_two, Nat.add_le_add_iff_left] at h
+  rw [← Nat.mul_div_left b Nat.two_pos]
+  exact Nat.div_le_div_right h
+#align nat.half_le_of_sub_le_half Nat.half_le_of_sub_le_half
+
+protected lemma div_le_of_le_mul' (h : m ≤ k * n) : m / k ≤ n := by
+  obtain rfl | hk := k.eq_zero_or_pos
+  · simp
+  · refine Nat.le_of_mul_le_mul_left ?_ hk
+    calc
+      k * (m / k) ≤ m % k + k * (m / k) := Nat.le_add_left _ _
+      _ = m := mod_add_div _ _
+      _ ≤ k * n := h
+#align nat.div_le_of_le_mul' Nat.div_le_of_le_mul'
+
+protected lemma div_le_self' (m n : ℕ) : m / n ≤ m := by
+  obtain rfl | hn := n.eq_zero_or_pos
+  · simp
+  · refine Nat.div_le_of_le_mul' ?_
+    calc
+      m = 1 * m := by rw [Nat.one_mul]
+      _ ≤ n * m := Nat.mul_le_mul_right _ hn
+#align nat.div_le_self' Nat.div_le_self'
+
+lemma two_mul_odd_div_two (hn : n % 2 = 1) : 2 * (n / 2) = n - 1 := by
+  conv => rhs; rw [← Nat.mod_add_div n 2, hn, Nat.add_sub_cancel_left]
+#align nat.two_mul_odd_div_two Nat.two_mul_odd_div_two
+
+@[gcongr]
+lemma div_le_div_left (hcb : c ≤ b) (hc : 0 < c) : a / b ≤ a / c :=
+  (Nat.le_div_iff_mul_le hc).2 <| le_trans (Nat.mul_le_mul_left _ hcb) (div_mul_le_self _ _)
+#align nat.div_le_div_left Nat.div_le_div_left
+
+lemma div_eq_self : m / n = m ↔ m = 0 ∨ n = 1 := by
+  constructor
+  · intro
+    match n with
+    | 0 => simp_all
+    | 1 => right; rfl
+    | n+2 =>
+      left
+      have : m / (n + 2) ≤ m / 2 := div_le_div_left (by simp) (by decide)
+      refine eq_zero_of_le_half ?_
+      simp_all
+  · rintro (rfl | rfl) <;> simp
+#align nat.div_eq_self Nat.div_eq_self
+
+lemma div_eq_sub_mod_div : 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]
+#align nat.div_eq_sub_mod_div Nat.div_eq_sub_mod_div
+
+/-!
+### `pow`
+
+#### TODO
+
+* Rename `Nat.pow_le_pow_of_le_left` to `Nat.pow_le_pow_left`, protect it, remove the alias
+* Rename `Nat.pow_le_pow_of_le_right` to `Nat.pow_le_pow_right`, protect it, remove the alias
+-/
+
+#align nat.pow_le_pow_of_le_left Nat.pow_le_pow_left
+#align nat.pow_le_pow_of_le_right Nat.pow_le_pow_right
+#align nat.pow_le_iff_lt_right Nat.pow_le_pow_iff_right
+#align nat.pow_lt_iff_lt_right Nat.pow_lt_pow_iff_right
+#align nat.pow_lt_pow_succ Nat.pow_lt_pow_succ
+
+protected lemma pow_lt_pow_left (h : a < b) : ∀ {n : ℕ}, n ≠ 0 → a ^ n < b ^ n
+  | 1, _ => by simpa
+  | n + 2, _ => Nat.mul_lt_mul_of_lt_of_le (Nat.pow_lt_pow_left h n.succ_ne_zero) (Nat.le_of_lt h)
+    (zero_lt_of_lt h)
+#align nat.pow_lt_pow_of_lt_left Nat.pow_lt_pow_left
+
+protected lemma pow_lt_pow_right (ha : 1 < a) (h : m < n) : a ^ m < a ^ n :=
+  (Nat.pow_lt_pow_iff_right ha).2 h
+
+protected lemma pow_le_pow_iff_left {n : ℕ} (hn : n ≠ 0) : a ^ n ≤ b ^ n ↔ a ≤ b where
+  mp := by simpa only [← Nat.not_le, not_imp_not] using (Nat.pow_lt_pow_left · hn)
+  mpr h := Nat.pow_le_pow_left h _
+#align nat.pow_le_iff_le_left Nat.pow_le_pow_iff_left
+
+protected lemma pow_lt_pow_iff_left (hn : n ≠ 0) : a ^ n < b ^ n ↔ a < b := by
+  simp only [← Nat.not_le, Nat.pow_le_pow_iff_left hn]
+#align nat.pow_lt_iff_lt_left Nat.pow_lt_pow_iff_left
+
+lemma pow_left_injective (hn : n ≠ 0) : Injective (fun a : ℕ ↦ a ^ n) := by
+  simp [Injective, le_antisymm_iff, Nat.pow_le_pow_iff_left hn]
+#align nat.pow_left_injective Nat.pow_left_injective
+
+protected lemma pow_right_injective (ha : 2 ≤ a) : Injective (a ^ ·) :=by
+  simp [Injective, le_antisymm_iff, Nat.pow_le_pow_iff_right ha]
+#align nat.pow_right_injective Nat.pow_right_injective
+
+-- We want to use this lemma earlier than the lemma simp can prove it with
+@[simp, nolint simpNF] protected lemma pow_eq_zero {a : ℕ} : ∀ {n : ℕ}, 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
+
+lemma le_self_pow (hn : n ≠ 0) : ∀ a : ℕ, 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)
+#align nat.le_self_pow Nat.le_self_pow
+
+lemma lt_pow_self (ha : 1 < a) : ∀ n : ℕ, n < a ^ n
+  | 0 => by simp
+  | n + 1 =>
+    calc
+      n + 1 < a ^ n + 1 := Nat.add_lt_add_right (lt_pow_self ha _) _
+      _ ≤ a ^ (n + 1) := Nat.pow_lt_pow_succ ha
+#align nat.lt_pow_self Nat.lt_pow_self
+
+lemma lt_two_pow (n : ℕ) : n < 2 ^ n := lt_pow_self (by decide) n
+#align nat.lt_two_pow Nat.lt_two_pow
+
+lemma one_le_pow (n m : ℕ) (h : 0 < m) : 1 ≤ m ^ n := by simpa using Nat.pow_le_pow_of_le_left h n
+#align nat.one_le_pow Nat.one_le_pow
+
+lemma one_le_pow' (n m : ℕ) : 1 ≤ (m + 1) ^ n := one_le_pow n (m + 1) (succ_pos m)
+#align nat.one_le_pow' Nat.one_le_pow'
+
+#align nat.one_le_two_pow Nat.one_le_two_pow
+
+lemma one_lt_pow (hn : n ≠ 0) (ha : 1 < a) : 1 < a ^ n := by simpa using Nat.pow_lt_pow_left ha hn
+#align nat.one_lt_pow Nat.one_lt_pow
+
+lemma two_pow_succ (n : ℕ) : 2 ^ (n + 1) = 2 ^ n + 2 ^ n := by simp [Nat.pow_succ, Nat.mul_two]
+
+lemma one_lt_pow' (n m : ℕ) : 1 < (m + 2) ^ (n + 1) :=
+  one_lt_pow n.succ_ne_zero (Nat.lt_of_sub_eq_succ rfl)
+#align nat.one_lt_pow' Nat.one_lt_pow'
+
+@[simp] lemma one_lt_pow_iff {n : ℕ} (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]
+  -- one_lt_pow_iff_of_nonneg (zero_le _) h
+#align nat.one_lt_pow_iff Nat.one_lt_pow_iff
+
+#align nat.one_lt_two_pow Nat.one_lt_two_pow
+
+lemma one_lt_two_pow' (n : ℕ) : 1 < 2 ^ (n + 1) := one_lt_pow n.succ_ne_zero (by decide)
+#align nat.one_lt_two_pow' Nat.one_lt_two_pow'
+
+lemma 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 (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 _)
+#align nat.mul_lt_mul_pow_succ Nat.mul_lt_mul_pow_succ
+
+lemma sq_sub_sq (a b : ℕ) : a ^ 2 - b ^ 2 = (a + b) * (a - b) := by
+  simpa [Nat.pow_succ] using Nat.mul_self_sub_mul_self_eq a b
+#align nat.sq_sub_sq Nat.sq_sub_sq
+
+alias pow_two_sub_pow_two := sq_sub_sq
+#align nat.pow_two_sub_pow_two Nat.pow_two_sub_pow_two
+
 protected lemma div_pow (h : a ∣ b) : (b / a) ^ c = b ^ c / a ^ c := by
   obtain rfl | hc := c.eq_zero_or_pos
   · simp
@@ -567,8 +949,103 @@ def decreasingInduction' {P : ℕ → Sort*} {m n : ℕ} (h : ∀ k < n, m ≤ k
     exact hP
 #align nat.decreasing_induction' Nat.decreasingInduction'
 
+/-- Given a predicate on two naturals `P : ℕ → ℕ → Prop`, `P a b` is true for all `a < b` if
+`P (a + 1) (a + 1)` is true for all `a`, `P 0 (b + 1)` is true for all `b` and for all
+`a < b`, `P (a + 1) b` is true and `P a (b + 1)` is true implies `P (a + 1) (b + 1)` is true. -/
+@[elab_as_elim]
+theorem diag_induction (P : ℕ → ℕ → Prop) (ha : ∀ a, P (a + 1) (a + 1)) (hb : ∀ b, P 0 (b + 1))
+    (hd : ∀ a b, a < b → P (a + 1) b → P a (b + 1) → P (a + 1) (b + 1)) : ∀ a b, a < b → P a b
+  | 0, b + 1, _ => hb _
+  | a + 1, b + 1, h => by
+    apply hd _ _ (Nat.add_lt_add_iff_right.1 h)
+    · have this : a + 1 = b ∨ a + 1 < b := by omega
+      have wf : (a + 1) + b < (a + 1) + (b + 1) := by simp
+      rcases this with (rfl | h)
+      · exact ha _
+      apply diag_induction P ha hb hd (a + 1) b h
+    have _ : a + (b + 1) < (a + 1) + (b + 1) := by simp
+    apply diag_induction P ha hb hd a (b + 1)
+    apply lt_of_le_of_lt (Nat.le_succ _) h
+  termination_by a b _c => a + b
+  decreasing_by all_goals assumption
+#align nat.diag_induction Nat.diag_induction
+
+/-- A subset of `ℕ` containing `k : ℕ` and closed under `Nat.succ` contains every `n ≥ k`. -/
+lemma set_induction_bounded {S : Set ℕ} (hk : k ∈ S) (h_ind : ∀ k : ℕ, k ∈ S → k + 1 ∈ S)
+    (hnk : k ≤ n) : n ∈ S :=
+  @leRecOn (fun n => n ∈ S) k n hnk @h_ind hk
+#align nat.set_induction_bounded Nat.set_induction_bounded
+
+/-- A subset of `ℕ` containing zero and closed under `Nat.succ` contains all of `ℕ`. -/
+lemma set_induction {S : Set ℕ} (hb : 0 ∈ S) (h_ind : ∀ k : ℕ, k ∈ S → k + 1 ∈ S) (n : ℕ) :
+    n ∈ S :=
+  set_induction_bounded hb h_ind (zero_le n)
+#align nat.set_induction Nat.set_induction
+
 /-! ### `mod`, `dvd` -/
 
+#align nat.pow_dvd_of_le_of_pow_dvd Nat.pow_dvd_of_le_of_pow_dvd
+#align nat.dvd_of_pow_dvd Nat.dvd_of_pow_dvd
+#align nat.mod_pow_succ Nat.mod_pow_succ
+#align nat.pow_dvd_pow_iff_pow_le_pow Nat.pow_dvd_pow_iff_pow_le_pow
+#align nat.pow_dvd_pow_iff_le_right Nat.pow_dvd_pow_iff_le_right
+#align nat.pow_dvd_pow_iff_le_right' Nat.pow_dvd_pow_iff_le_right'
+#align nat.mod_mul_right_div_self Nat.mod_mul_right_div_self
+#align nat.mod_mul_left_div_self Nat.mod_mul_left_div_self
+
+lemma mul_div_mul_comm_of_dvd_dvd (hba : b ∣ a) (hdc : d ∣ c) :
+    a * c / (b * d) = a / b * (c / d) := by
+  obtain rfl | hb := b.eq_zero_or_pos; · simp
+  obtain rfl | hd := d.eq_zero_or_pos; · simp
+  obtain ⟨_, rfl⟩ := hba
+  obtain ⟨_, rfl⟩ := hdc
+  rw [Nat.mul_mul_mul_comm, Nat.mul_div_cancel_left _ hb, Nat.mul_div_cancel_left _ hd,
+    Nat.mul_div_cancel_left _ (Nat.mul_pos hb hd)]
+#align nat.mul_div_mul_comm_of_dvd_dvd Nat.mul_div_mul_comm_of_dvd_dvd
+
+@[simp] lemma mul_mod_mod (a b c : ℕ) : (a * (b % c)) % c = a * b % c := by
+  rw [mul_mod, mod_mod, ← mul_mod]
+
+@[simp] lemma mod_mul_mod (a b c : ℕ) : (a % c * b) % c = a * b % c := by
+  rw [mul_mod, mod_mod, ← mul_mod]
+
+lemma pow_mod (a b n : ℕ) : a ^ b % n = (a % n) ^ b % n := by
+  induction' b with b ih; rfl; simp [Nat.pow_succ, Nat.mul_mod, ih]
+#align nat.pow_mod Nat.pow_mod
+
+lemma not_pos_pow_dvd : ∀ {a n : ℕ} (_ : 1 < a) (_ : 1 < n), ¬ a ^ n ∣ a
+  | succ a, succ n, hp, hk, h =>
+    have : succ a * succ a ^ n ∣ succ a * 1 := by simpa [pow_succ'] using h
+    have : succ a ^ n ∣ 1 := Nat.dvd_of_mul_dvd_mul_left (succ_pos _) this
+    have he : succ a ^ n = 1 := eq_one_of_dvd_one this
+    have : n < succ a ^ n := lt_pow_self hp n
+    have : n < 1 := by rwa [he] at this
+    have : n = 0 := Nat.eq_zero_of_le_zero <| le_of_lt_succ this
+    have : 1 < 1 := by rwa [this] at hk
+    absurd this (by decide)
+#align nat.not_pos_pow_dvd Nat.not_pos_pow_dvd
+
+lemma 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 lt_of_le_of_lt (le_of_dvd (Nat.pos_iff_ne_zero.2 hb) h) (lt_pow_self ha _)
+#align nat.lt_of_pow_dvd_right Nat.lt_of_pow_dvd_right
+
+lemma div_dvd_of_dvd (h : n ∣ m) : m / n ∣ m := ⟨n, (Nat.div_mul_cancel h).symm⟩
+#align nat.div_dvd_of_dvd Nat.div_dvd_of_dvd
+
+protected lemma 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)]
+#align nat.div_div_self Nat.div_div_self
+
+lemma 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 lt_irrefl 0 h1
+  · exact not_lt.2 (Nat.le_mul_of_pos_right _ hk) h2
+#align nat.not_dvd_of_pos_of_lt Nat.not_dvd_of_pos_of_lt
+
 lemma 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⟩
 #align nat.mod_eq_iff_lt Nat.mod_eq_iff_lt
@@ -595,6 +1072,42 @@ protected lemma div_mod_unique (h : 0 < b) :
     rw [add_mul_div_left _ _ h, add_mul_mod_self_left]; simp [div_eq_of_lt, mod_eq_of_lt, h₂]⟩
 #align nat.div_mod_unique Nat.div_mod_unique
 
+/-- If `m` and `n` are equal mod `k`, `m - n` is zero mod `k`. -/
+lemma 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, ← Nat.mul_sub_left_distrib k, Nat.mul_mod_right]
+#align nat.sub_mod_eq_zero_of_mod_eq Nat.sub_mod_eq_zero_of_mod_eq
+
+@[simp] lemma one_mod (n : ℕ) : 1 % (n + 2) = 1 :=
+  Nat.mod_eq_of_lt (Nat.add_lt_add_right n.succ_pos 1)
+#align nat.one_mod Nat.one_mod
+
+lemma one_mod_of_ne_one : ∀ {n : ℕ}, n ≠ 1 → 1 % n = 1
+  | 0, _ | (n + 2), _ => by simp
+
+lemma dvd_sub_mod (k : ℕ) : n ∣ k - k % n :=
+  ⟨k / n, Nat.sub_eq_of_eq_add (Nat.div_add_mod k n).symm⟩
+#align nat.dvd_sub_mod Nat.dvd_sub_mod
+
+lemma add_mod_eq_ite :
+    (m + n) % k = if k ≤ m % k + n % k then m % k + n % k - k else m % k + n % k := by
+  cases k; simp only [zero_eq, mod_zero, zero_le, ↓reduceIte, Nat.sub_zero]
+  rw [Nat.add_mod]
+  split_ifs with h
+  · rw [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 _)))
+  · exact Nat.mod_eq_of_lt (lt_of_not_ge h)
+#align nat.add_mod_eq_ite Nat.add_mod_eq_ite
+
+/-- `m` is not divisible by `n` if it is between `n * k` and `n * (k + 1)` for some `k`. -/
+theorem not_dvd_of_between_consec_multiples (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
+#align nat.not_dvd_of_between_consec_multiples Nat.not_dvd_of_between_consec_multiples
+
 -- TODO: Replace `Nat.dvd_add_iff_left`
 protected lemma dvd_add_left (h : a ∣ c) : a ∣ b + c ↔ a ∣ b := (Nat.dvd_add_iff_left h).symm
 #align nat.dvd_add_left Nat.dvd_add_left
@@ -643,11 +1156,6 @@ lemma eq_zero_of_dvd_of_div_eq_zero (hab : a ∣ b) (h : b / a = 0) : b = 0 := b
   rw [← Nat.div_mul_cancel hab, h, Nat.zero_mul]
 #align nat.eq_zero_of_dvd_of_div_eq_zero Nat.eq_zero_of_dvd_of_div_eq_zero
 
-@[gcongr]
-lemma div_le_div_left (hcb : c ≤ b) (hc : 0 < c) : a / b ≤ a / c :=
-  (Nat.le_div_iff_mul_le hc).2 <| le_trans (Nat.mul_le_mul_left _ hcb) (div_mul_le_self _ _)
-#align nat.div_le_div_left Nat.div_le_div_left
-
 @[gcongr]
 protected theorem div_le_div {a b c d : ℕ} (h1 : a ≤ b) (h2 : d ≤ c) (h3 : d ≠ 0) : a / c ≤ b / d :=
   calc a / c ≤ b / c := Nat.div_le_div_right h1
@@ -717,6 +1225,23 @@ lemma find_comp_succ (h₁ : ∃ n, p n) (h₂ : ∃ n, p (n + 1)) (h0 : ¬ p 0)
   exacts [h0, @Nat.find_min (fun n ↦ p (n + 1)) _ h₂ _ (succ_lt_succ_iff.1 hn)]
 #align nat.find_comp_succ Nat.find_comp_succ
 
+-- Porting note (#10618): removing `simp` attribute as `simp` can prove it
+lemma find_pos (h : ∃ n : ℕ, p n) : 0 < Nat.find h ↔ ¬p 0 :=
+  Nat.pos_iff_ne_zero.trans (Nat.find_eq_zero _).not
+#align nat.find_pos Nat.find_pos
+
+lemma find_add {hₘ : ∃ m, p (m + n)} {hₙ : ∃ n, p n} (hn : n ≤ Nat.find hₙ) :
+    Nat.find hₘ + n = Nat.find hₙ := by
+  refine le_antisymm ((le_find_iff _ _).2 fun m hm hpm => Nat.not_le.2 hm ?_) ?_
+  · have hnm : n ≤ m := le_trans hn (find_le hpm)
+    refine Nat.add_le_of_le_sub hnm (find_le ?_)
+    rwa [Nat.sub_add_cancel hnm]
+  · rw [← Nat.sub_le_iff_le_add]
+    refine (le_find_iff _ _).2 fun m hm hpm => Nat.not_le.2 hm ?_
+    rw [Nat.sub_le_iff_le_add]
+    exact find_le hpm
+#align nat.find_add Nat.find_add
+
 end Find
 
 /-! ### `Nat.findGreatest` -/
@@ -749,6 +1274,90 @@ lemma findGreatest_of_not (h : ¬ P (n + 1)) : findGreatest P (n + 1) = findGrea
   simp [Nat.findGreatest, h]
 #align nat.find_greatest_of_not Nat.findGreatest_of_not
 
+lemma findGreatest_eq_iff :
+    Nat.findGreatest P k = m ↔ m ≤ k ∧ (m ≠ 0 → P m) ∧ ∀ ⦃n⦄, m < n → n ≤ k → ¬P n := by
+  induction' k with k ihk generalizing m
+  · rw [eq_comm, Iff.comm]
+    simp only [zero_eq, Nat.le_zero, ne_eq, findGreatest_zero, and_iff_left_iff_imp]
+    rintro rfl
+    exact ⟨fun h ↦ (h rfl).elim, fun n hlt heq ↦ by omega⟩
+  · by_cases hk : P (k + 1)
+    · rw [findGreatest_eq hk]
+      constructor
+      · rintro rfl
+        exact ⟨le_refl _, fun _ ↦ hk, fun n hlt hle ↦ by omega⟩
+      · rintro ⟨hle, h0, hm⟩
+        rcases Decidable.eq_or_lt_of_le hle with (rfl | hlt)
+        exacts [rfl, (hm hlt (le_refl _) hk).elim]
+    · rw [findGreatest_of_not hk, ihk]
+      constructor
+      · rintro ⟨hle, hP, hm⟩
+        refine ⟨le_trans hle k.le_succ, hP, fun n hlt hle ↦ ?_⟩
+        rcases Decidable.eq_or_lt_of_le hle with (rfl | hlt')
+        exacts [hk, hm hlt <| Nat.lt_succ_iff.1 hlt']
+      · rintro ⟨hle, hP, hm⟩
+        refine ⟨Nat.lt_succ_iff.1 (lt_of_le_of_ne hle ?_), hP,
+          fun n hlt hle ↦ hm hlt (le_trans hle k.le_succ)⟩
+        rintro rfl
+        exact hk (hP k.succ_ne_zero)
+#align nat.find_greatest_eq_iff Nat.findGreatest_eq_iff
+
+lemma findGreatest_eq_zero_iff : Nat.findGreatest P k = 0 ↔ ∀ ⦃n⦄, 0 < n → n ≤ k → ¬P n := by
+  simp [findGreatest_eq_iff]
+#align nat.find_greatest_eq_zero_iff Nat.findGreatest_eq_zero_iff
+
+@[simp] lemma findGreatest_pos : 0 < Nat.findGreatest P k ↔ ∃ n, 0 < n ∧ n ≤ k ∧ P n := by
+  rw [Nat.pos_iff_ne_zero, Ne.def, findGreatest_eq_zero_iff]; push_neg; rfl
+
+lemma findGreatest_spec (hmb : m ≤ n) (hm : P m) : P (Nat.findGreatest P n) := by
+  by_cases h : Nat.findGreatest P n = 0
+  · cases m
+    · rwa [h]
+    exact ((findGreatest_eq_zero_iff.1 h) (zero_lt_succ _) hmb hm).elim
+  · exact (findGreatest_eq_iff.1 rfl).2.1 h
+#align nat.find_greatest_spec Nat.findGreatest_spec
+
+lemma findGreatest_le (n : ℕ) : Nat.findGreatest P n ≤ n :=
+  (findGreatest_eq_iff.1 rfl).1
+#align nat.find_greatest_le Nat.findGreatest_le
+
+lemma le_findGreatest (hmb : m ≤ n) (hm : P m) : m ≤ Nat.findGreatest P n :=
+  le_of_not_lt fun hlt => (findGreatest_eq_iff.1 rfl).2.2 hlt hmb hm
+#align nat.le_find_greatest Nat.le_findGreatest
+
+lemma findGreatest_mono_right (P : ℕ → Prop) [DecidablePred P] {m n} (hmn : m ≤ n) :
+    Nat.findGreatest P m ≤ Nat.findGreatest P n := by
+  induction' hmn with k hmk ih
+  · simp
+  rw [findGreatest_succ]
+  split_ifs
+  · exact le_trans ih $ le_trans (findGreatest_le _) (le_succ _)
+  · exact ih
+#align nat.find_greatest_mono_right Nat.findGreatest_mono_right
+
+lemma findGreatest_mono_left [DecidablePred Q] (hPQ : ∀ n, P n → Q n) (n : ℕ) :
+    Nat.findGreatest P n ≤ Nat.findGreatest Q n := by
+  induction' n with n hn
+  · rfl
+  by_cases h : P (n + 1)
+  · rw [findGreatest_eq h, findGreatest_eq (hPQ _ h)]
+  · rw [findGreatest_of_not h]
+    exact le_trans hn (Nat.findGreatest_mono_right _ <| le_succ _)
+#align nat.find_greatest_mono_left Nat.findGreatest_mono_left
+
+lemma findGreatest_mono [DecidablePred Q] (hPQ : ∀ n, P n → Q n) (hmn : m ≤ n) :
+    Nat.findGreatest P m ≤ Nat.findGreatest Q n :=
+  le_trans (Nat.findGreatest_mono_right _ hmn) (findGreatest_mono_left hPQ _)
+#align nat.find_greatest_mono Nat.findGreatest_mono
+
+theorem findGreatest_is_greatest (hk : Nat.findGreatest P n < k) (hkb : k ≤ n) : ¬P k :=
+  (findGreatest_eq_iff.1 rfl).2.2 hk hkb
+#align nat.find_greatest_is_greatest Nat.findGreatest_is_greatest
+
+theorem findGreatest_of_ne_zero (h : Nat.findGreatest P n = m) (h0 : m ≠ 0) : P m :=
+  (findGreatest_eq_iff.1 h).2.1 h0
+#align nat.find_greatest_of_ne_zero Nat.findGreatest_of_ne_zero
+
 end FindGreatest
 
 /-! ### Decidability of predicates -/
@@ -759,4 +1368,19 @@ end FindGreatest
 #align nat.decidable_exists_lt Nat.decidableExistsLT
 #align nat.decidable_exists_le Nat.decidableExistsLE
 
+instance decidableLoHi (lo hi : ℕ) (P : ℕ → Prop) [H : DecidablePred P] :
+    Decidable (∀ x, lo ≤ x → x < hi → P x) :=
+  decidable_of_iff (∀ x < hi - lo, P (lo + x)) $ by
+    refine ⟨fun al x hl hh ↦ ?_,
+      fun al x h ↦ al _ (Nat.le_add_right _ _) (Nat.lt_sub_iff_add_lt'.1 h)⟩
+    have := al (x - lo) ((Nat.sub_lt_sub_iff_right hl).2 hh)
+    rwa [Nat.add_sub_cancel' hl] at this
+#align nat.decidable_lo_hi Nat.decidableLoHi
+
+instance decidableLoHiLe (lo hi : ℕ) (P : ℕ → Prop) [DecidablePred P] :
+    Decidable (∀ x, lo ≤ x → x ≤ hi → P x) :=
+  decidable_of_iff (∀ x, lo ≤ x → x < hi + 1 → P x) <|
+    ball_congr fun _ _ => imp_congr Nat.lt_succ_iff Iff.rfl
+#align nat.decidable_lo_hi_le Nat.decidableLoHiLe
+
 end Nat
chore(Data/Nat): Use Std lemmas (#11661)

Move basic Nat lemmas from Data.Nat.Order.Basic and Data.Nat.Pow to Data.Nat.Defs. Most proofs need adapting, but that's easily solved by replacing the general mathlib lemmas by the new Std Nat-specific lemmas and using omega.

Other changes

  • Move the last few lemmas left in Data.Nat.Pow to Algebra.GroupPower.Order
  • Move the deprecated aliases from Data.Nat.Pow to Algebra.GroupPower.Order
  • Move the bit/bit0/bit1 lemmas from Data.Nat.Order.Basic to Data.Nat.Bits
  • Fix some fallout from not importing Data.Nat.Order.Basic anymore
  • Add a few Nat-specific lemmas to help fix the fallout (look for nolint simpNF)
  • Turn Nat.mul_self_le_mul_self_iff and Nat.mul_self_lt_mul_self_iff around (they were misnamed)
  • Make more arguments to Nat.one_lt_pow implicit
Diff
@@ -10,12 +10,25 @@ import Mathlib.Algebra.GroupWithZero.Defs
 #align_import data.nat.basic from "leanprover-community/mathlib"@"bd835ef554f37ef9b804f0903089211f89cb370b"
 
 /-!
-# Basic instances for the natural numbers
+# Algebraic instances for the natural numbers
 
-This file contains:
-* Algebraic instances on the natural numbers
-* Basic lemmas about natural numbers that require more imports than available in
-  `Data.Nat.Defs`.
+This file contains algebraic instances on the natural numbers and a few lemmas about them.
+
+## Implementation note
+
+Std has a home-baked development of the algebraic and order theoretic theory of `ℕ` which, in
+particular, is not typeclass-mediated. This is useful to set up the algebra and finiteness libraries
+in mathlib (naturals show up as indices in lists, cardinality in finsets, powers in groups, ...).
+This home-baked development is pursued in `Data.Nat.Defs`.
+
+Less basic uses of `ℕ` should however use the typeclass-mediated development. This file is the one
+giving access to the algebraic instances. `Data.Nat.Order.Basic` is the one giving access to the
+algebraic order instances.
+
+## TODO
+
+The names of this file, `Data.Nat.Defs` and `Data.Nat.Order.Basic` are archaic and don't match up
+with reality anymore. Rename them.
 -/
 
 open Multiplicative
chore: remove unneeded decreasing_by and termination_by (#11386)

The termination checker has been getting more capable, and many of the termination_by or decreasing_by clauses in Mathlib are no longer needed.

(Note that termination_by? will show the automatically derived termination expression, so no information is being lost by removing these.)

Co-authored-by: Scott Morrison <scott.morrison@gmail.com>

Diff
@@ -550,7 +550,6 @@ def pincerRecursion {P : ℕ → ℕ → Sort*} (Ha0 : ∀ m : ℕ, P m 0) (H0b
   | m, 0 => Ha0 m
   | 0, n => H0b n
   | Nat.succ m, Nat.succ n => H _ _ (pincerRecursion Ha0 H0b H _ _) (pincerRecursion Ha0 H0b H _ _)
-termination_by n m => n + m
 #align nat.pincer_recursion Nat.pincerRecursion
 
 /-- Decreasing induction: if `P (k+1)` implies `P k` for all `m ≤ k < n`, then `P n` implies `P m`.
chore: small fixes around Nat.find/findGreatest (#10512)
Diff
@@ -703,7 +703,7 @@ lemma find_eq_iff (h : ∃ n : ℕ, p n) : Nat.find h = m ↔ p m ∧ ∀ n < m,
 @[simp] lemma find_eq_zero (h : ∃ n : ℕ, p n) : Nat.find h = 0 ↔ p 0 := by simp [find_eq_iff]
 #align nat.find_eq_zero Nat.find_eq_zero
 
-lemma find_mono (h : ∀ n, q n → p n) {hp : ∃ n, p n} {hq : ∃ n, q n} :  Nat.find hp ≤ Nat.find hq :=
+lemma find_mono (h : ∀ n, q n → p n) {hp : ∃ n, p n} {hq : ∃ n, q n} : Nat.find hp ≤ Nat.find hq :=
   Nat.find_min' _ (h _ (Nat.find_spec hq))
 #align nat.find_mono Nat.find_mono
 
@@ -714,17 +714,17 @@ lemma find_le {h : ∃ n, p n} (hn : p n) : Nat.find h ≤ n :=
 lemma find_comp_succ (h₁ : ∃ n, p n) (h₂ : ∃ n, p (n + 1)) (h0 : ¬ p 0) :
     Nat.find h₁ = Nat.find h₂ + 1 := by
   refine' (find_eq_iff _).2 ⟨Nat.find_spec h₂, fun n hn ↦ _⟩
-  cases' n with n
+  cases n
   exacts [h0, @Nat.find_min (fun n ↦ p (n + 1)) _ h₂ _ (succ_lt_succ_iff.1 hn)]
 #align nat.find_comp_succ Nat.find_comp_succ
 
 end Find
 
-/-! ### `find_greatest` -/
+/-! ### `Nat.findGreatest` -/
 
 section FindGreatest
 
-/-- `find_greatest P n` is the largest `i ≤ bound` such that `P i` holds, or `0` if no such `i`
+/-- `Nat.findGreatest P n` is the largest `i ≤ bound` such that `P i` holds, or `0` if no such `i`
 exists -/
 def findGreatest (P : ℕ → Prop) [DecidablePred P] : ℕ → ℕ
   | 0 => 0
chore: bump Std (#10514)

Co-authored-by: Scott Morrison <scott.morrison@gmail.com> Co-authored-by: Tobias Grosser <tobias@grosser.es>

Diff
@@ -323,16 +323,8 @@ lemma mul_div_le_mul_div_assoc (a b c : ℕ) : a * (b / c) ≤ a * b / c :=
       (by rw [Nat.mul_assoc]; exact Nat.mul_le_mul_left _ (Nat.div_mul_le_self _ _))
 #align nat.mul_div_le_mul_div_assoc Nat.mul_div_le_mul_div_assoc
 
-protected lemma eq_mul_of_div_eq_right (H1 : b ∣ a) (H2 : a / b = c) : a = b * c := by
-  rw [← H2, Nat.mul_div_cancel' H1]
 #align nat.eq_mul_of_div_eq_right Nat.eq_mul_of_div_eq_right
-
-protected lemma div_eq_iff_eq_mul_right (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⟩
 #align nat.div_eq_iff_eq_mul_right Nat.div_eq_iff_eq_mul_right
-
-protected lemma div_eq_iff_eq_mul_left (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'
 #align nat.div_eq_iff_eq_mul_left Nat.div_eq_iff_eq_mul_left
 
 protected lemma eq_mul_of_div_eq_left (H1 : b ∣ a) (H2 : a / b = c) : a = c * b := by
chore: bump Std (#10482)

Co-authored-by: Scott Morrison <scott.morrison@gmail.com>

Diff
@@ -91,13 +91,7 @@ alias ⟨of_le_succ, _⟩ := le_succ_iff
 #align nat.of_le_succ Nat.of_le_succ
 
 #align nat.lt_succ_iff_lt_or_eq Nat.lt_succ_iff_lt_or_eq
-
-lemma eq_of_lt_succ_of_not_lt (hmn : m < n + 1) (h : ¬ m < n) : m = n :=
-  (Nat.lt_succ_iff_lt_or_eq.1 hmn).resolve_left h
 #align nat.eq_of_lt_succ_of_not_lt Nat.eq_of_lt_succ_of_not_lt
-
-lemma eq_of_le_of_lt_succ (h₁ : n ≤ m) (h₂ : m < n + 1) : m = n :=
-  Nat.le_antisymm (le_of_succ_le_succ h₂) h₁
 #align nat.eq_of_le_of_lt_succ Nat.eq_of_le_of_lt_succ
 
 lemma lt_iff_le_pred : ∀ {n}, 0 < n → (m < n ↔ m ≤ n - 1) | _ + 1, _ => Nat.lt_succ_iff
@@ -219,14 +213,8 @@ lemma pred_add_self (n : ℕ) : pred n + n = (2 * n).pred := sub_one_add_self n
 @[simp] lemma add_def : Nat.add m n = m + n := rfl
 #align nat.add_def Nat.add_def
 
-lemma exists_eq_add_of_le (h : m ≤ n) : ∃ k : ℕ, n = m + k := ⟨n - m, (add_sub_of_le h).symm⟩
 #align nat.exists_eq_add_of_le Nat.exists_eq_add_of_le
-
-lemma exists_eq_add_of_le' (h : m ≤ n) : ∃ k : ℕ, n = k + m := ⟨n - m, (Nat.sub_add_cancel h).symm⟩
 #align nat.exists_eq_add_of_le' Nat.exists_eq_add_of_le'
-
-lemma exists_eq_add_of_lt (h : m < n) : ∃ k : ℕ, n = m + k + 1 :=
-  ⟨n - (m + 1), by rw [Nat.add_right_comm, add_sub_of_le h]⟩
 #align nat.exists_eq_add_of_lt Nat.exists_eq_add_of_lt
 
 /-! ### `mul` -/
@@ -632,11 +620,6 @@ protected lemma mul_dvd_mul_iff_right (hc : 0 < c) : a * c ∣ b * c ↔ a ∣ b
 #align nat.mul_dvd_mul_iff_right Nat.mul_dvd_mul_iff_right
 
 #align nat.dvd_one Nat.dvd_one
-
-@[simp] lemma mod_mod_of_dvd (a : ℕ) (h : c ∣ b) : a % b % c = a % c := by
-  conv_rhs => rw [← mod_add_div a b]
-  obtain ⟨x, rfl⟩ := h
-  rw [Nat.mul_assoc, add_mul_mod_self_left]
 #align nat.mod_mod_of_dvd Nat.mod_mod_of_dvd
 
 -- Moved to Std
chore(Tactic/GCongr): move @[gcongr] tags around (#9393)
  • Add import Mathlib.Tactic.GCongr.Core to Algebra/Order/Ring/Lemmas.
  • Move most @[gcongr] tags next to the lemmas.

See Zulip thread

Co-authored-by: Jeremy Tan Jie Rui <reddeloostw@gmail.com>

Diff
@@ -7,6 +7,7 @@ import Mathlib.Init.Data.Nat.Lemmas
 import Mathlib.Logic.Function.Basic
 import Mathlib.Logic.Nontrivial.Defs
 import Mathlib.Tactic.Cases
+import Mathlib.Tactic.GCongr.Core
 import Mathlib.Tactic.PushNeg
 import Mathlib.Tactic.Use
 
@@ -37,6 +38,7 @@ variable {a b c d m n k : ℕ} {p q : ℕ → Prop}
 
 instance nontrivial : Nontrivial ℕ := ⟨⟨0, 1, Nat.zero_ne_one⟩⟩
 
+attribute [gcongr] Nat.succ_le_succ
 attribute [simp] Nat.not_lt_zero Nat.succ_ne_zero Nat.succ_ne_self Nat.zero_ne_one Nat.one_ne_zero
   -- Nat.zero_ne_bit1 Nat.bit1_ne_zero Nat.bit0_ne_one Nat.one_ne_bit0 Nat.bit0_ne_bit1
   -- Nat.bit1_ne_bit0
@@ -305,6 +307,7 @@ lemma one_le_div_iff (hb : 0 < b) : 1 ≤ a / b ↔ b ≤ a := by rw [le_div_iff
 lemma div_lt_one_iff (hb : 0 < b) : a / b < 1 ↔ a < b := by simp only [← not_le, one_le_div_iff hb]
 #align nat.div_lt_one_iff Nat.div_lt_one_iff
 
+@[gcongr]
 protected lemma div_le_div_right (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 <| le_trans (Nat.div_mul_le_self _ _) h
@@ -666,10 +669,16 @@ lemma eq_zero_of_dvd_of_div_eq_zero (hab : a ∣ b) (h : b / a = 0) : b = 0 := b
   rw [← Nat.div_mul_cancel hab, h, Nat.zero_mul]
 #align nat.eq_zero_of_dvd_of_div_eq_zero Nat.eq_zero_of_dvd_of_div_eq_zero
 
+@[gcongr]
 lemma div_le_div_left (hcb : c ≤ b) (hc : 0 < c) : a / b ≤ a / c :=
   (Nat.le_div_iff_mul_le hc).2 <| le_trans (Nat.mul_le_mul_left _ hcb) (div_mul_le_self _ _)
 #align nat.div_le_div_left Nat.div_le_div_left
 
+@[gcongr]
+protected theorem div_le_div {a b c d : ℕ} (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)
+
 -- Moved to Std
 #align nat.mul_div_le Nat.mul_div_le
 
chore: bump dependencies (#10315)

Co-authored-by: Scott Morrison <scott.morrison@gmail.com>

Diff
@@ -74,7 +74,6 @@ alias _root_.LT.lt.nat_succ_le := succ_le_of_lt
 lemma not_succ_lt_self : ¬ succ n < n := not_lt_of_ge n.le_succ
 #align nat.not_succ_lt_self Nat.not_succ_lt_self
 
-lemma lt_succ_iff : m < succ n ↔ m ≤ n := ⟨le_of_lt_succ, lt_succ_of_le⟩
 #align nat.lt_succ_iff Nat.lt_succ_iff
 
 lemma succ_le_iff : succ m ≤ n ↔ m < n := ⟨lt_of_succ_le, succ_le_of_lt⟩
@@ -89,18 +88,17 @@ lemma le_succ_iff : m ≤ n.succ ↔ m ≤ n ∨ m = n.succ := by
 alias ⟨of_le_succ, _⟩ := le_succ_iff
 #align nat.of_le_succ Nat.of_le_succ
 
-lemma lt_succ_iff_lt_or_eq : m < n.succ ↔ m < n ∨ m = n := lt_succ_iff.trans Nat.le_iff_lt_or_eq
 #align nat.lt_succ_iff_lt_or_eq Nat.lt_succ_iff_lt_or_eq
 
 lemma eq_of_lt_succ_of_not_lt (hmn : m < n + 1) (h : ¬ m < n) : m = n :=
-  (lt_succ_iff_lt_or_eq.1 hmn).resolve_left h
+  (Nat.lt_succ_iff_lt_or_eq.1 hmn).resolve_left h
 #align nat.eq_of_lt_succ_of_not_lt Nat.eq_of_lt_succ_of_not_lt
 
 lemma eq_of_le_of_lt_succ (h₁ : n ≤ m) (h₂ : m < n + 1) : m = n :=
   Nat.le_antisymm (le_of_succ_le_succ h₂) h₁
 #align nat.eq_of_le_of_lt_succ Nat.eq_of_le_of_lt_succ
 
-lemma lt_iff_le_pred : ∀ {n}, 0 < n → (m < n ↔ m ≤ n - 1) | _ + 1, _ => lt_succ_iff
+lemma lt_iff_le_pred : ∀ {n}, 0 < n → (m < n ↔ m ≤ n - 1) | _ + 1, _ => Nat.lt_succ_iff
 #align nat.lt_iff_le_pred Nat.lt_iff_le_pred
 
 lemma le_of_pred_lt : ∀ {m}, pred m < n → m ≤ n
@@ -112,11 +110,11 @@ lemma lt_iff_add_one_le : m < n ↔ m + 1 ≤ n := by rw [succ_le_iff]
 #align nat.lt_iff_add_one_le Nat.lt_iff_add_one_le
 
 -- Just a restatement of `Nat.lt_succ_iff` using `+1`.
-lemma lt_add_one_iff : m < n + 1 ↔ m ≤ n := lt_succ_iff
+lemma lt_add_one_iff : m < n + 1 ↔ m ≤ n := Nat.lt_succ_iff
 #align nat.lt_add_one_iff Nat.lt_add_one_iff
 
 -- A flipped version of `lt_add_one_iff`.
-lemma lt_one_add_iff : m < 1 + n ↔ m ≤ n := by simp only [Nat.add_comm, lt_succ_iff]
+lemma lt_one_add_iff : m < 1 + n ↔ m ≤ n := by simp only [Nat.add_comm, Nat.lt_succ_iff]
 #align nat.lt_one_add_iff Nat.lt_one_add_iff
 
 -- This is true reflexively, by the definition of `≤` on ℕ,
@@ -173,7 +171,7 @@ lemma or_exists_succ : p 0 ∨ (∃ n, p (n + 1)) ↔ ∃ n, p n :=
 #align nat.or_exists_succ Nat.or_exists_succ
 
 lemma forall_lt_succ : (∀ m < n + 1, p m) ↔ (∀ m < n, p m) ∧ p n := by
-  simp only [lt_succ_iff, Nat.le_iff_lt_or_eq, or_comm, forall_eq_or_imp, and_comm]
+  simp only [Nat.lt_succ_iff, Nat.le_iff_lt_or_eq, or_comm, forall_eq_or_imp, and_comm]
 #align nat.forall_lt_succ Nat.forall_lt_succ
 
 lemma exists_lt_succ : (∃ m < n + 1, p m) ↔ (∃ m < n, p m) ∨ p n := by
@@ -285,7 +283,8 @@ lemma one_lt_mul_iff : 1 < m * n ↔ 0 < m ∧ 0 < n ∧ (1 < m ∨ 1 < n) := by
 attribute [simp] Nat.div_self
 
 lemma div_le_iff_le_mul_add_pred (hb : 0 < b) : a / b ≤ c ↔ a ≤ b * c + (b - 1) := by
-  rw [← lt_succ_iff, div_lt_iff_lt_mul hb, succ_mul, Nat.mul_comm]; cases hb <;> exact lt_succ_iff
+  rw [← Nat.lt_succ_iff, div_lt_iff_lt_mul hb, succ_mul, Nat.mul_comm]
+  cases hb <;> exact Nat.lt_succ_iff
 #align nat.div_le_iff_le_mul_add_pred Nat.div_le_iff_le_mul_add_pred
 
 /-- A version of `Nat.div_lt_self` using successors, rather than additional hypotheses. -/
@@ -706,7 +705,7 @@ lemma find_eq_iff (h : ∃ n : ℕ, p n) : Nat.find h = m ↔ p m ∧ ∀ n < m,
 #align nat.find_lt_iff Nat.find_lt_iff
 
 @[simp] lemma find_le_iff (h : ∃ n : ℕ, p n) (n : ℕ) : Nat.find h ≤ n ↔ ∃ m ≤ n, p m := by
-  simp only [exists_prop, ← lt_succ_iff, find_lt_iff]
+  simp only [exists_prop, ← Nat.lt_succ_iff, find_lt_iff]
 #align nat.find_le_iff Nat.find_le_iff
 
 @[simp] lemma le_find_iff (h : ∃ n : ℕ, p n) (n : ℕ) : n ≤ Nat.find h ↔ ∀ m < n, ¬ p m := by
@@ -771,44 +770,10 @@ end FindGreatest
 
 /-! ### Decidability of predicates -/
 
--- To work around lean4#2552, we use `match` instead of `if/casesOn` with decidable instances.
-instance decidableBallLT :
-  ∀ (n : Nat) (P : ∀ k, k < n → Prop) [∀ n h, Decidable (P n h)], Decidable (∀ n h, P n h)
-| 0, _, _ => isTrue fun _ ↦ (by cases ·)
-| n + 1, P, H =>
-  match decidableBallLT n (P · <| lt_succ_of_lt ·) with
-  | isFalse h => isFalse (h fun _ _ ↦ · _ _)
-  | isTrue h =>
-    match H n Nat.le.refl with
-    | isFalse p => isFalse (p <| · _ _)
-    | isTrue p => isTrue fun _ h' ↦ (lt_succ_iff_lt_or_eq.1 h').elim (h _) fun hn ↦ hn ▸ p
 #align nat.decidable_ball_lt Nat.decidableBallLT
-
--- To verify we don't have a regression on the speed, we put a difficult example.
--- any regression should take a huge amount of heartbeats -- we are currently at 187621.
--- For reference, the instance using `casesOn` took 44544 for 4; this one takes 1299 for 4.
-example : ∀ m, m < 25 → ∀ n, n < 25 → ∀ c, c < 25 → m ^ 2 + n ^ 2 + c ^ 2 ≠ 7 := by decide
-
-instance decidableForallFin (P : Fin n → Prop) [DecidablePred P] : Decidable (∀ i, P i) :=
-  decidable_of_iff (∀ k h, P ⟨k, h⟩) ⟨fun m ⟨k, h⟩ ↦ m k h, fun m k h ↦ m ⟨k, h⟩⟩
 #align nat.decidable_forall_fin Nat.decidableForallFin
-
-instance decidableBallLe (n : ℕ) (P : ∀ k ≤ n, Prop) [∀ n h, Decidable (P n h)] :
-    Decidable (∀ n h, P n h) :=
-  decidable_of_iff (∀ (k) (h : k < succ n), P k (le_of_lt_succ h))
-    ⟨fun m k h ↦ m k (lt_succ_of_le h), fun m k _ ↦ m k _⟩
-#align nat.decidable_ball_le Nat.decidableBallLe
-
-instance decidableExistsLT [h : DecidablePred p] : DecidablePred fun n ↦ ∃ m : ℕ, m < n ∧ p m
-  | 0 => isFalse (by simp)
-  | n + 1 =>
-    @decidable_of_decidable_of_iff _ _ (@instDecidableOr _ _ (decidableExistsLT n) (h n))
-      (by simp only [lt_succ_iff_lt_or_eq, or_and_right, exists_or, exists_eq_left])
+#align nat.decidable_ball_le Nat.decidableBallLE
 #align nat.decidable_exists_lt Nat.decidableExistsLT
-
-instance decidableExistsLe [DecidablePred p] : DecidablePred fun n ↦ ∃ m : ℕ, m ≤ n ∧ p m :=
-  fun n ↦ decidable_of_iff (∃ m, m < n + 1 ∧ p m)
-    (exists_congr fun _ ↦ and_congr_left' lt_succ_iff)
-#align nat.decidable_exists_le Nat.decidableExistsLe
+#align nat.decidable_exists_le Nat.decidableExistsLE
 
 end Nat
chore: move to v4.6.0-rc1, merging adaptations from bump/v4.6.0 (#10176)

Co-authored-by: Scott Morrison <scott.morrison@gmail.com> Co-authored-by: Eric Wieser <wieser.eric@gmail.com> Co-authored-by: Joachim Breitner <mail@joachim-breitner.de>

Diff
@@ -568,7 +568,7 @@ def pincerRecursion {P : ℕ → ℕ → Sort*} (Ha0 : ∀ m : ℕ, P m 0) (H0b
   | m, 0 => Ha0 m
   | 0, n => H0b n
   | Nat.succ m, Nat.succ n => H _ _ (pincerRecursion Ha0 H0b H _ _) (pincerRecursion Ha0 H0b H _ _)
-termination_by pincerRecursion Ha0 Hab H n m => n + m
+termination_by n m => n + m
 #align nat.pincer_recursion Nat.pincerRecursion
 
 /-- Decreasing induction: if `P (k+1)` implies `P k` for all `m ≤ k < n`, then `P n` implies `P m`.
chore: reduce imports (#9830)

This uses the improved shake script from #9772 to reduce imports across mathlib. The corresponding noshake.json file has been added to #9772.

Co-authored-by: Mario Carneiro <di.gama@gmail.com>

Diff
@@ -6,9 +6,6 @@ Authors: Floris van Doorn, Leonardo de Moura, Jeremy Avigad, Mario Carneiro
 import Mathlib.Algebra.Group.TypeTags
 import Mathlib.Algebra.Ring.Defs
 import Mathlib.Algebra.GroupWithZero.Defs
-import Mathlib.Algebra.Ring.Defs
-import Mathlib.Data.Nat.Defs
-import Mathlib.Order.Basic
 
 #align_import data.nat.basic from "leanprover-community/mathlib"@"bd835ef554f37ef9b804f0903089211f89cb370b"
 
fix: patch for std4#198 (more mul lemmas for Nat) (#6204)

Co-authored-by: Scott Morrison <scott.morrison@gmail.com>

Diff
@@ -277,8 +277,8 @@ lemma one_lt_mul_iff : 1 < m * n ↔ 0 < m ∧ 0 < n ∧ (1 < m ∨ 1 < n) := by
     · 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 hm h.2.1 Nat.zero_lt_one
-    · exact Nat.mul_lt_mul' h.1 hn h.1
+    · 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
 
 /-! ### `div` -/
 
refactor: Split off basic Nat file (#9551)

Data.Nat.Basic is currently made of two things:

  • Basic lemmas that continue the theory in Std (and could belong there, really)
  • Basic algebraic order instances

I need the first ones earlier in the algebraic order hierarchy, hence the split.

Part of #9411. Similar to #9443

refactor: Split off basic Nat file (#9551)

Data.Nat.Basic is currently made of two things:

  • Basic lemmas that continue the theory in Std (and could belong there, really)
  • Basic algebraic order instances

I need the first ones earlier in the algebraic order hierarchy, hence the split.

Part of #9411. Similar to #9443

Diff
@@ -5,43 +5,27 @@ Authors: Floris van Doorn, Leonardo de Moura, Jeremy Avigad, Mario Carneiro
 -/
 import Mathlib.Algebra.Group.TypeTags
 import Mathlib.Algebra.Ring.Defs
-import Mathlib.Init.Data.Nat.Lemmas
+import Mathlib.Algebra.GroupWithZero.Defs
+import Mathlib.Algebra.Ring.Defs
+import Mathlib.Data.Nat.Defs
 import Mathlib.Order.Basic
-import Mathlib.Tactic.PushNeg
-import Mathlib.Tactic.Use
 
 #align_import data.nat.basic from "leanprover-community/mathlib"@"bd835ef554f37ef9b804f0903089211f89cb370b"
 
 /-!
-# Basic operations on the natural numbers
+# Basic instances for the natural numbers
 
 This file contains:
-- instances on the natural numbers
-- some basic lemmas about natural numbers
-- extra recursors:
-  * `le_rec_on`, `le_induction`: recursion and induction principles starting at non-zero numbers
-  * `decreasing_induction`: recursion growing downwards
-  * `le_rec_on'`, `decreasing_induction'`: versions with slightly weaker assumptions
-  * `strong_rec'`: recursion based on strong inequalities
-- decidability instances on predicates about the natural numbers
-
-Many theorems that used to live in this file have been moved to `Data.Nat.Order`,
-so that this file requires fewer imports.
-For each section here there is a corresponding section in that file with additional results.
-It may be possible to move some of these results here, by tweaking their proofs.
-
-
+* Algebraic instances on the natural numbers
+* Basic lemmas about natural numbers that require more imports than available in
+  `Data.Nat.Defs`.
 -/
 
-
-universe u v
+open Multiplicative
 
 namespace Nat
 
-/-! ### instances -/
-
-instance nontrivial : Nontrivial ℕ :=
-  ⟨⟨0, 1, Nat.zero_ne_one⟩⟩
+/-! ### Instances -/
 
 instance commSemiring : CommSemiring ℕ where
   add := Nat.add
@@ -72,7 +56,6 @@ instance commSemiring : CommSemiring ℕ where
 
 /-! Extra instances to short-circuit type class resolution and ensure computability -/
 
-
 instance addCommMonoid : AddCommMonoid ℕ :=
   inferInstance
 
@@ -103,27 +86,18 @@ instance distrib : Distrib ℕ :=
 instance semiring : Semiring ℕ :=
   inferInstance
 
-protected theorem nsmul_eq_mul (m n : ℕ) : m • n = m * n :=
-  rfl
-#align nat.nsmul_eq_mul Nat.nsmul_eq_mul
-
--- Moved to core
-#align nat.eq_of_mul_eq_mul_right Nat.eq_of_mul_eq_mul_right
-
 instance cancelCommMonoidWithZero : CancelCommMonoidWithZero ℕ :=
   { (inferInstance : CommMonoidWithZero ℕ) with
     mul_left_cancel_of_ne_zero :=
       fun h1 h2 => Nat.eq_of_mul_eq_mul_left (Nat.pos_of_ne_zero h1) h2 }
 #align nat.cancel_comm_monoid_with_zero Nat.cancelCommMonoidWithZero
 
-attribute [simp]
-  Nat.not_lt_zero Nat.succ_ne_zero Nat.succ_ne_self Nat.zero_ne_one Nat.one_ne_zero
-  -- Nat.zero_ne_bit1 Nat.bit1_ne_zero Nat.bit0_ne_one Nat.one_ne_bit0 Nat.bit0_ne_bit1
-  -- Nat.bit1_ne_bit0
+/-! ### Extra lemmas -/
 
-section Multiplicative
+protected lemma nsmul_eq_mul (m n : ℕ) : m • n = m * n := rfl
+#align nat.nsmul_eq_mul Nat.nsmul_eq_mul
 
-open Multiplicative
+section Multiplicative
 
 lemma toAdd_pow (a : Multiplicative ℕ) (b : ℕ) : toAdd (a ^ b) = toAdd a * b := mul_comm _ _
 #align nat.to_add_pow Nat.toAdd_pow
@@ -132,871 +106,4 @@ lemma toAdd_pow (a : Multiplicative ℕ) (b : ℕ) : toAdd (a ^ b) = toAdd a * b
 #align nat.of_add_mul Nat.ofAdd_mul
 
 end Multiplicative
-
-variable {m n k : ℕ}
-
-/-!
-### Recursion and `forall`/`exists`
--/
-
--- Porting note:
--- this doesn't work as a simp lemma in Lean 4
--- @[simp]
-theorem and_forall_succ {p : ℕ → Prop} : (p 0 ∧ ∀ n, p (n + 1)) ↔ ∀ n, p n :=
-  ⟨fun h n => Nat.casesOn n h.1 h.2, fun h => ⟨h _, fun _ => h _⟩⟩
-#align nat.and_forall_succ Nat.and_forall_succ
-
--- Porting note:
--- this doesn't work as a simp lemma in Lean 4
--- @[simp]
-theorem or_exists_succ {p : ℕ → Prop} : (p 0 ∨ ∃ n, p (n + 1)) ↔ ∃ n, p n :=
-  ⟨fun h => h.elim (fun h0 => ⟨0, h0⟩) fun ⟨n, hn⟩ => ⟨n + 1, hn⟩, by
-    rintro ⟨_ | n, hn⟩
-    exacts [Or.inl hn, Or.inr ⟨n, hn⟩]⟩
-#align nat.or_exists_succ Nat.or_exists_succ
-
-/-! ### `succ` -/
-
-
-theorem _root_.LT.lt.nat_succ_le {n m : ℕ} (h : n < m) : succ n ≤ m :=
-  succ_le_of_lt h
-#align has_lt.lt.nat_succ_le LT.lt.nat_succ_le
-
--- Moved to Std
-#align nat.succ_eq_one_add Nat.succ_eq_one_add
-
-theorem eq_of_lt_succ_of_not_lt {a b : ℕ} (h1 : a < b + 1) (h2 : ¬a < b) : a = b :=
-  have h3 : a ≤ b := le_of_lt_succ h1
-  Or.elim (eq_or_lt_of_not_lt h2) (fun h => h) fun h => absurd h (not_lt_of_ge h3)
-#align nat.eq_of_lt_succ_of_not_lt Nat.eq_of_lt_succ_of_not_lt
-
-theorem eq_of_le_of_lt_succ {n m : ℕ} (h₁ : n ≤ m) (h₂ : m < n + 1) : m = n :=
-  Nat.le_antisymm (le_of_succ_le_succ h₂) h₁
-#align nat.eq_of_le_of_lt_succ Nat.eq_of_le_of_lt_succ
-
--- Moved to Std
-#align nat.one_add Nat.one_add
-
-theorem succ_pos' {n : ℕ} : 0 < succ n :=
-  succ_pos n
-#align nat.succ_pos' Nat.succ_pos'
-
--- Moved to Std
-#align nat.succ_inj' Nat.succ_inj'
-
-theorem succ_injective : Function.Injective Nat.succ := fun _ _ => succ.inj
-#align nat.succ_injective Nat.succ_injective
-
-theorem succ_ne_succ {n m : ℕ} : succ n ≠ succ m ↔ n ≠ m :=
-  succ_injective.ne_iff
-#align nat.succ_ne_succ Nat.succ_ne_succ
-
--- Porting note: no longer a simp lemma, as simp can prove this
-theorem succ_succ_ne_one (n : ℕ) : n.succ.succ ≠ 1 :=
-  succ_ne_succ.mpr n.succ_ne_zero
-#align nat.succ_succ_ne_one Nat.succ_succ_ne_one
-
-@[simp]
-theorem one_lt_succ_succ (n : ℕ) : 1 < n.succ.succ :=
-  succ_lt_succ <| succ_pos n
-#align nat.one_lt_succ_succ Nat.one_lt_succ_succ
-
--- Porting note: Nat.succ_le_succ_iff is in Std
-
-#align nat.max_succ_succ Nat.succ_max_succ
-
-theorem not_succ_lt_self {n : ℕ} : ¬succ n < n :=
-  not_lt_of_ge (Nat.le_succ _)
-#align nat.not_succ_lt_self Nat.not_succ_lt_self
-
-theorem lt_succ_iff {m n : ℕ} : m < succ n ↔ m ≤ n :=
-  ⟨le_of_lt_succ, lt_succ_of_le⟩
-#align nat.lt_succ_iff Nat.lt_succ_iff
-
-theorem succ_le_iff {m n : ℕ} : succ m ≤ n ↔ m < n :=
-  ⟨lt_of_succ_le, succ_le_of_lt⟩
-#align nat.succ_le_iff Nat.succ_le_iff
-
-theorem lt_iff_add_one_le {m n : ℕ} : m < n ↔ m + 1 ≤ n := by rw [succ_le_iff]
-#align nat.lt_iff_add_one_le Nat.lt_iff_add_one_le
-
--- Just a restatement of `Nat.lt_succ_iff` using `+1`.
-theorem lt_add_one_iff {a b : ℕ} : a < b + 1 ↔ a ≤ b :=
-  lt_succ_iff
-#align nat.lt_add_one_iff Nat.lt_add_one_iff
-
--- A flipped version of `lt_add_one_iff`.
-theorem lt_one_add_iff {a b : ℕ} : a < 1 + b ↔ a ≤ b := by simp only [add_comm, lt_succ_iff]
-#align nat.lt_one_add_iff Nat.lt_one_add_iff
-
--- This is true reflexively, by the definition of `≤` on ℕ,
--- but it's still useful to have, to convince Lean to change the syntactic type.
-theorem add_one_le_iff {a b : ℕ} : a + 1 ≤ b ↔ a < b :=
-  Iff.refl _
-#align nat.add_one_le_iff Nat.add_one_le_iff
-
-theorem one_add_le_iff {a b : ℕ} : 1 + a ≤ b ↔ a < b := by simp only [add_comm, add_one_le_iff]
-#align nat.one_add_le_iff Nat.one_add_le_iff
-
-theorem of_le_succ {n m : ℕ} (H : n ≤ m.succ) : n ≤ m ∨ n = m.succ :=
-  H.lt_or_eq_dec.imp le_of_lt_succ id
-#align nat.of_le_succ Nat.of_le_succ
-
-#align nat.succ_lt_succ_iff Nat.succ_lt_succ_iff
-
-theorem div_le_iff_le_mul_add_pred {m n k : ℕ} (n0 : 0 < n) : m / n ≤ k ↔ m ≤ n * k + (n - 1) := by
-  rw [← lt_succ_iff, div_lt_iff_lt_mul n0, succ_mul, mul_comm]
-  cases n
-  · cases n0
-
-  exact lt_succ_iff
-#align nat.div_le_iff_le_mul_add_pred Nat.div_le_iff_le_mul_add_pred
-
-theorem two_lt_of_ne : ∀ {n}, n ≠ 0 → n ≠ 1 → n ≠ 2 → 2 < n
-  | 0, h, _, _ => (h rfl).elim
-  | 1, _, h, _ => (h rfl).elim
-  | 2, _, _, h => (h rfl).elim
-  -- Porting note: was `by decide`
-  | n + 3, _, _, _ => by rw [Nat.lt_iff_add_one_le]; convert Nat.le_add_left 3 n
-#align nat.two_lt_of_ne Nat.two_lt_of_ne
-
-theorem forall_lt_succ {P : ℕ → Prop} {n : ℕ} : (∀ m < n + 1, P m) ↔ (∀ m < n, P m) ∧ P n := by
-  simp only [lt_succ_iff, Decidable.le_iff_eq_or_lt, forall_eq_or_imp, and_comm]
-#align nat.forall_lt_succ Nat.forall_lt_succ
-
-theorem exists_lt_succ {P : ℕ → Prop} {n : ℕ} : (∃ m < n + 1, P m) ↔ (∃ m < n, P m) ∨ P n := by
-  rw [← not_iff_not]
-  push_neg
-  exact forall_lt_succ
-#align nat.exists_lt_succ Nat.exists_lt_succ
-
-/-! ### `add` -/
-
--- Sometimes a bare `Nat.add` or similar appears as a consequence of unfolding
--- during pattern matching. These lemmas package them back up as typeclass
--- mediated operations.
-@[simp]
-theorem add_def {a b : ℕ} : Nat.add a b = a + b :=
-  rfl
-#align nat.add_def Nat.add_def
-
-@[simp]
-theorem mul_def {a b : ℕ} : Nat.mul a b = a * b :=
-  rfl
-#align nat.mul_def Nat.mul_def
-
-theorem exists_eq_add_of_le (h : m ≤ n) : ∃ k : ℕ, n = m + k :=
-  ⟨n - m, (add_sub_of_le h).symm⟩
-#align nat.exists_eq_add_of_le Nat.exists_eq_add_of_le
-
-theorem exists_eq_add_of_le' (h : m ≤ n) : ∃ k : ℕ, n = k + m :=
-  ⟨n - m, (Nat.sub_add_cancel h).symm⟩
-#align nat.exists_eq_add_of_le' Nat.exists_eq_add_of_le'
-
-theorem exists_eq_add_of_lt (h : m < n) : ∃ k : ℕ, n = m + k + 1 :=
-  ⟨n - (m + 1), by rw [Nat.add_right_comm, add_sub_of_le h]⟩
-#align nat.exists_eq_add_of_lt Nat.exists_eq_add_of_lt
-
-/-! ### `pred` -/
-
-@[simp]
-theorem add_succ_sub_one (n m : ℕ) : n + succ m - 1 = n + m := by rw [add_succ, Nat.add_one_sub_one]
-#align nat.add_succ_sub_one Nat.add_succ_sub_one
-
-@[simp]
-theorem succ_add_sub_one (n m : ℕ) : succ n + m - 1 = n + m := by rw [succ_add, Nat.add_one_sub_one]
-#align nat.succ_add_sub_one Nat.succ_add_sub_one
-
-theorem pred_eq_sub_one (n : ℕ) : pred n = n - 1 :=
-  rfl
-#align nat.pred_eq_sub_one Nat.pred_eq_sub_one
-
-theorem pred_eq_of_eq_succ {m n : ℕ} (H : m = n.succ) : m.pred = n := by simp [H]
-#align nat.pred_eq_of_eq_succ Nat.pred_eq_of_eq_succ
-
-@[simp]
-theorem pred_eq_succ_iff {n m : ℕ} : pred n = succ m ↔ n = m + 2 := by
-  cases n <;> constructor <;> rintro ⟨⟩ <;> rfl
-#align nat.pred_eq_succ_iff Nat.pred_eq_succ_iff
-
-theorem pred_sub (n m : ℕ) : pred n - m = pred (n - m) := by
-  rw [← Nat.sub_one, Nat.sub_sub, one_add, sub_succ]
-#align nat.pred_sub Nat.pred_sub
-
--- Moved to Std
-#align nat.le_pred_of_lt Nat.le_pred_of_lt
-
-theorem le_of_pred_lt {m n : ℕ} : pred m < n → m ≤ n :=
-  match m with
-  | 0 => le_of_lt
-  | _ + 1 => id
-#align nat.le_of_pred_lt Nat.le_of_pred_lt
-
-theorem self_add_sub_one (n : ℕ) : n + (n - 1) = 2 * n - 1 := by
-  cases n
-  · rfl
-  · rw [two_mul]
-    convert (add_succ_sub_one (Nat.succ _) _).symm
-
-theorem sub_one_add_self (n : ℕ) : (n - 1) + n = 2 * n - 1 :=
-  add_comm _ n ▸ self_add_sub_one n
-
-theorem self_add_pred (n : ℕ) : n + pred n = (2 * n).pred :=
-  self_add_sub_one n
-
-theorem pred_add_self (n : ℕ) : pred n + n = (2 * n).pred :=
-  sub_one_add_self n
-
-/-- This ensures that `simp` succeeds on `pred (n + 1) = n`. -/
-@[simp]
-theorem pred_one_add (n : ℕ) : pred (1 + n) = n := by rw [add_comm, add_one, Nat.pred_succ]
-#align nat.pred_one_add Nat.pred_one_add
-
-/-! ### `mul` -/
-
-
-theorem two_mul_ne_two_mul_add_one {n m} : 2 * n ≠ 2 * m + 1 :=
-  mt (congr_arg (· % 2))
-    (by rw [add_comm, add_mul_mod_self_left, mul_mod_right, mod_eq_of_lt] <;> simp)
-#align nat.two_mul_ne_two_mul_add_one Nat.two_mul_ne_two_mul_add_one
-
-theorem mul_ne_mul_left {a b c : ℕ} (ha : 0 < a) : b * a ≠ c * a ↔ b ≠ c :=
-  (mul_left_injective₀ ha.ne').ne_iff
-#align nat.mul_ne_mul_left Nat.mul_ne_mul_left
-
-theorem mul_ne_mul_right {a b c : ℕ} (ha : 0 < a) : a * b ≠ a * c ↔ b ≠ c :=
-  (mul_right_injective₀ ha.ne').ne_iff
-#align nat.mul_ne_mul_right Nat.mul_ne_mul_right
-
-theorem mul_right_eq_self_iff {a b : ℕ} (ha : 0 < a) : a * b = a ↔ b = 1 :=
-  suffices a * b = a * 1 ↔ b = 1 by rwa [mul_one] at this
-  mul_right_inj' ha.ne'
-#align nat.mul_right_eq_self_iff Nat.mul_right_eq_self_iff
-
-theorem mul_left_eq_self_iff {a b : ℕ} (hb : 0 < b) : a * b = b ↔ a = 1 := by
-  rw [mul_comm, Nat.mul_right_eq_self_iff hb]
-#align nat.mul_left_eq_self_iff Nat.mul_left_eq_self_iff
-
-theorem lt_succ_iff_lt_or_eq {n i : ℕ} : n < i.succ ↔ n < i ∨ n = i :=
-  lt_succ_iff.trans Decidable.le_iff_lt_or_eq
-#align nat.lt_succ_iff_lt_or_eq Nat.lt_succ_iff_lt_or_eq
-
-set_option push_neg.use_distrib true in
-/-- 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. -/
-lemma one_lt_mul_iff : 1 < m * n ↔ 0 < m ∧ 0 < n ∧ (1 < m ∨ 1 < n) := by
-  constructor <;> intro h
-  · by_contra h'; push_neg at h'; simp_rw [Nat.le_zero] at h'
-    obtain rfl | rfl | h' := h'
-    · simp at h
-    · simp at h
-    · exact (Nat.mul_le_mul h'.1 h'.2).not_lt h
-  · obtain hm | hn := h.2.2
-    · exact Nat.mul_lt_mul hm h.2.1 Nat.zero_lt_one
-    · exact Nat.mul_lt_mul' h.1 hn h.1
-
-/-!
-### Recursion and induction principles
-
-This section is here due to dependencies -- the lemmas here require some of the lemmas
-proved above, and some of the results in later sections depend on the definitions in this section.
--/
-
--- Porting note: The type ascriptions of these two theorems need to be changed,
--- as mathport wrote a lambda that wasn't there in mathlib3, that prevents `simp` applying them.
-
-@[simp]
-theorem rec_zero {C : ℕ → Sort u} (h0 : C 0) (h : ∀ n, C n → C (n + 1)) :
-    Nat.rec h0 h 0 = h0 :=
-  rfl
-#align nat.rec_zero Nat.rec_zero
-
-@[simp]
-theorem rec_add_one {C : ℕ → Sort u} (h0 : C 0) (h : ∀ n, C n → C (n + 1)) (n : ℕ) :
-    Nat.rec h0 h (n + 1) = h n (Nat.rec h0 h n) :=
-  rfl
-#align nat.rec_add_one Nat.rec_add_one
-
-/-- Recursion starting at a non-zero number: given a map `C k → C (k+1)` for each `k`,
-there is a map from `C n` to each `C m`, `n ≤ m`. For a version where the assumption is only made
-when `k ≥ n`, see `leRecOn`. -/
-@[elab_as_elim]
-def leRecOn {C : ℕ → Sort u} {n : ℕ} : ∀ {m : ℕ}, n ≤ m → (∀ {k}, C k → C (k + 1)) → C n → C m
-  | 0, H, _, x => Eq.recOn (Nat.eq_zero_of_le_zero H) x
-  | m + 1, H, next, x =>
-    Or.by_cases (of_le_succ H) (fun h : n ≤ m => next <| leRecOn h (@next) x)
-      fun h : n = m + 1 => Eq.recOn h x
-#align nat.le_rec_on Nat.leRecOn
-
-theorem leRecOn_self {C : ℕ → Sort u} {n} {h : n ≤ n} {next : ∀ {k}, C k → C (k + 1)} (x : C n) :
-    (leRecOn h next x : C n) = x := by
-  cases n <;> unfold leRecOn Eq.recOn
-  · simp
-  · unfold Or.by_cases
-    rw [dif_neg (Nat.not_succ_le_self _)]
-#align nat.le_rec_on_self Nat.leRecOn_self
-
-theorem leRecOn_succ {C : ℕ → Sort u} {n m} (h1 : n ≤ m) {h2 : n ≤ m + 1} {next} (x : C n) :
-    (leRecOn h2 (@next) x : C (m + 1)) = next (leRecOn h1 (@next) x : C m) := by
-  conv =>
-    lhs
-    rw [leRecOn, Or.by_cases, dif_pos h1]
-#align nat.le_rec_on_succ Nat.leRecOn_succ
-
-theorem leRecOn_succ' {C : ℕ → Sort u} {n} {h : n ≤ n + 1} {next : ∀ {k}, C k → C (k + 1)}
-    (x : C n) :
-    (leRecOn h next x : C (n + 1)) = next x := by rw [leRecOn_succ (le_refl n), leRecOn_self]
-#align nat.le_rec_on_succ' Nat.leRecOn_succ'
-
-theorem leRecOn_trans {C : ℕ → Sort u} {n m k} (hnm : n ≤ m) (hmk : m ≤ k) {next} (x : C n) :
-    (leRecOn (le_trans hnm hmk) (@next) x : C k) = leRecOn hmk (@next) (leRecOn hnm (@next) x) := by
-  induction' hmk with k hmk ih
-  · rw [leRecOn_self]
-
-  rw [leRecOn_succ (le_trans hnm hmk), ih, leRecOn_succ]
-#align nat.le_rec_on_trans Nat.leRecOn_trans
-
-theorem leRecOn_succ_left {C : ℕ → Sort u} {n m} (h1 : n ≤ m) (h2 : n + 1 ≤ m)
-    {next : ∀ {k}, C k → C (k + 1)} (x : C n) :
-    (leRecOn h2 next (next x) : C m) = (leRecOn h1 next x : C m) := by
-  rw [Subsingleton.elim h1 (le_trans (le_succ n) h2), leRecOn_trans (le_succ n) h2, leRecOn_succ']
-#align nat.le_rec_on_succ_left Nat.leRecOn_succ_left
-
-theorem leRecOn_injective {C : ℕ → Sort u} {n m} (hnm : n ≤ m) (next : ∀ {k}, C k → C (k + 1))
-    (Hnext : ∀ n, Function.Injective (@next n)) :
-    Function.Injective (@leRecOn C n m hnm next) := by
-  induction' hnm with m hnm ih
-  · intro x y H
-    rwa [leRecOn_self, leRecOn_self] at H
-
-  intro x y H
-  rw [leRecOn_succ hnm, leRecOn_succ hnm] at H
-  exact ih (Hnext _ H)
-#align nat.le_rec_on_injective Nat.leRecOn_injective
-
-theorem leRecOn_surjective {C : ℕ → Sort u} {n m} (hnm : n ≤ m) (next : ∀ {k}, C k → C (k + 1))
-    (Hnext : ∀ n, Function.Surjective (@next n)) :
-    Function.Surjective (@leRecOn C n m hnm next) := by
-  induction' hnm with m hnm ih
-  · intro x
-    use x
-    rw [leRecOn_self]
-
-  intro x
-  rcases Hnext _ x with ⟨w, rfl⟩
-  rcases ih w with ⟨x, rfl⟩
-  use x
-  rw [leRecOn_succ]
-#align nat.le_rec_on_surjective Nat.leRecOn_surjective
-
-/-- Recursion principle based on `<`. -/
-@[elab_as_elim]
-protected def strongRec' {p : ℕ → Sort u} (H : ∀ n, (∀ m, m < n → p m) → p n) : ∀ n : ℕ, p n
-  | n => H n fun m _ => Nat.strongRec' H m
-#align nat.strong_rec' Nat.strongRec'
-
-/-- Recursion principle based on `<` applied to some natural number. -/
-@[elab_as_elim]
-def strongRecOn' {P : ℕ → Sort*} (n : ℕ) (h : ∀ n, (∀ m, m < n → P m) → P n) : P n :=
-  Nat.strongRec' h n
-#align nat.strong_rec_on' Nat.strongRecOn'
-
-theorem strongRecOn'_beta {P : ℕ → Sort*} {h} {n : ℕ} :
-    (strongRecOn' n h : P n) = h n fun m _ => (strongRecOn' m h : P m) := by
-  simp only [strongRecOn']
-  rw [Nat.strongRec']
-#align nat.strong_rec_on_beta' Nat.strongRecOn'_beta
-
-/-- Induction principle starting at a non-zero number. For maps to a `Sort*` see `le_rec_on`.
-To use in an induction proof, the syntax is `induction n, hn using Nat.le_induction` (or the same
-for `induction'`). -/
-@[elab_as_elim]
-theorem le_induction {m} {P : ∀ (n : Nat) (_ : m ≤ n), Prop} (base : P m le_rfl)
-    (succ : ∀ (n : Nat) (hn : m ≤ n), P n hn → P (n + 1) (hn.trans <| Nat.le_succ _)) :
-    ∀ (n : Nat) (hn : m ≤ n), P n hn := by
-  apply Nat.le.rec
-  · exact base
-  · intros n hn
-    apply succ n hn
-#align nat.le_induction Nat.le_induction
-
-/-- Decreasing induction: if `P (k+1)` implies `P k`, then `P n` implies `P m` for all `m ≤ n`.
-Also works for functions to `Sort*`. For a version assuming only the assumption for `k < n`, see
-`decreasing_induction'`. -/
-@[elab_as_elim]
-def decreasingInduction {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P n) {m n : ℕ} (mn : m ≤ n)
-    (hP : P n) : P m :=
-  leRecOn mn (fun {k} ih hsk => ih <| h k hsk) (fun h => h) hP
-#align nat.decreasing_induction Nat.decreasingInduction
-
-@[simp]
-theorem decreasingInduction_self {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P n) {n : ℕ} (nn : n ≤ n)
-    (hP : P n) :
-    (decreasingInduction h nn hP : P n) = hP := by
-  dsimp only [decreasingInduction]
-  rw [leRecOn_self]
-#align nat.decreasing_induction_self Nat.decreasingInduction_self
-
-theorem decreasingInduction_succ {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P n) {m n : ℕ} (mn : m ≤ n)
-    (msn : m ≤ n + 1) (hP : P (n + 1)) :
-    (decreasingInduction h msn hP : P m) = decreasingInduction h mn (h n hP) := by
-  dsimp only [decreasingInduction]
-  rw [leRecOn_succ]
-#align nat.decreasing_induction_succ Nat.decreasingInduction_succ
-
-@[simp]
-theorem decreasingInduction_succ' {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P n) {m : ℕ}
-    (msm : m ≤ m + 1) (hP : P (m + 1)) : (decreasingInduction h msm hP : P m) = h m hP := by
-  dsimp only [decreasingInduction]
-  rw [leRecOn_succ']
-#align nat.decreasing_induction_succ' Nat.decreasingInduction_succ'
-
-theorem decreasingInduction_trans {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P n) {m n k : ℕ}
-    (mn : m ≤ n) (nk : n ≤ k) (hP : P k) :
-    (decreasingInduction h (le_trans mn nk) hP : P m) =
-    decreasingInduction h mn (decreasingInduction h nk hP) := by
-  induction' nk with k nk ih
-  · rw [decreasingInduction_self]
-  · rw [decreasingInduction_succ h (le_trans mn nk), ih, decreasingInduction_succ]
-#align nat.decreasing_induction_trans Nat.decreasingInduction_trans
-
-theorem decreasingInduction_succ_left {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P n) {m n : ℕ}
-    (smn : m + 1 ≤ n) (mn : m ≤ n) (hP : P n) :
-    (decreasingInduction h mn hP : P m) = h m (decreasingInduction h smn hP) := by
-  rw [Subsingleton.elim mn (le_trans (le_succ m) smn), decreasingInduction_trans,
-    decreasingInduction_succ']
-  apply Nat.le_succ
-#align nat.decreasing_induction_succ_left Nat.decreasingInduction_succ_left
-
-/-- Given `P : ℕ → ℕ → Sort*`, if for all `a b : ℕ` we can extend `P` from the rectangle
-strictly below `(a,b)` to `P a b`, then we have `P n m` for all `n m : ℕ`.
-Note that for non-`Prop` output it is preferable to use the equation compiler directly if possible,
-since this produces equation lemmas. -/
-@[elab_as_elim]
-def strongSubRecursion {P : ℕ → ℕ → Sort*} (H : ∀ a b, (∀ x y, x < a → y < b → P x y) → P a b) :
-    ∀ n m : ℕ, P n m
-  | n, m => H n m fun x y _ _ => strongSubRecursion H x y
-#align nat.strong_sub_recursion Nat.strongSubRecursion
-
-/-- Given `P : ℕ → ℕ → Sort*`, if we have `P i 0` and `P 0 i` for all `i : ℕ`,
-and for any `x y : ℕ` we can extend `P` from `(x,y+1)` and `(x+1,y)` to `(x+1,y+1)`
-then we have `P n m` for all `n m : ℕ`.
-Note that for non-`Prop` output it is preferable to use the equation compiler directly if possible,
-since this produces equation lemmas. -/
-@[elab_as_elim]
-def pincerRecursion {P : ℕ → ℕ → Sort*} (Ha0 : ∀ a : ℕ, P a 0) (H0b : ∀ b : ℕ, P 0 b)
-    (H : ∀ x y : ℕ, P x y.succ → P x.succ y → P x.succ y.succ) : ∀ n m : ℕ, P n m
-  | a, 0 => Ha0 a
-  | 0, b => H0b b
-  | Nat.succ a, Nat.succ b => H _ _ (pincerRecursion Ha0 H0b H _ _) (pincerRecursion Ha0 H0b H _ _)
-termination_by pincerRecursion Ha0 Hab H n m => n + m
-#align nat.pincer_recursion Nat.pincerRecursion
-
-/-- Recursion starting at a non-zero number: given a map `C k → C (k+1)` for each `k ≥ n`,
-there is a map from `C n` to each `C m`, `n ≤ m`. -/
-@[elab_as_elim]
-def leRecOn' {C : ℕ → Sort*} {n : ℕ} :
-    ∀ {m : ℕ}, n ≤ m → (∀ ⦃k⦄, n ≤ k → C k → C (k + 1)) → C n → C m
-  | 0, H, _, x => Eq.recOn (Nat.eq_zero_of_le_zero H) x
-  | m + 1, H, next, x =>
-    Or.by_cases (of_le_succ H) (fun h : n ≤ m => next h <| leRecOn' h next x)
-      fun h : n = m + 1 => Eq.recOn h x
-#align nat.le_rec_on' Nat.leRecOn'
-
-/-- Decreasing induction: if `P (k+1)` implies `P k` for all `m ≤ k < n`, then `P n` implies `P m`.
-Also works for functions to `Sort*`. Weakens the assumptions of `decreasing_induction`. -/
-@[elab_as_elim]
-def decreasingInduction' {P : ℕ → Sort*} {m n : ℕ} (h : ∀ k < n, m ≤ k → P (k + 1) → P k)
-    (mn : m ≤ n) (hP : P n) :
-    P m := by
-  revert h hP
-  refine' leRecOn' mn _ _
-  · intro n mn ih h hP
-    apply ih
-    · exact fun k hk => h k (Nat.lt.step hk)
-    · exact h n (lt_succ_self n) mn hP
-  · intro _ hP
-    exact hP
-#align nat.decreasing_induction' Nat.decreasingInduction'
-
-/-! ### `div` -/
-
-attribute [simp] Nat.div_self
-
-/-- A version of `Nat.div_lt_self` using successors, rather than additional hypotheses. -/
-theorem div_lt_self' (n b : ℕ) : (n + 1) / (b + 2) < n + 1 :=
-  Nat.div_lt_self (Nat.succ_pos n) (Nat.succ_lt_succ (Nat.succ_pos _))
-#align nat.div_lt_self' Nat.div_lt_self'
-
-theorem le_div_iff_mul_le' {x y : ℕ} {k : ℕ} (k0 : 0 < k) : x ≤ y / k ↔ x * k ≤ y :=
-  le_div_iff_mul_le k0
-#align nat.le_div_iff_mul_le' Nat.le_div_iff_mul_le'
-
-theorem div_lt_iff_lt_mul' {x y : ℕ} {k : ℕ} (k0 : 0 < k) : x / k < y ↔ x < y * k :=
-  lt_iff_lt_of_le_iff_le <| le_div_iff_mul_le' k0
-#align nat.div_lt_iff_lt_mul' Nat.div_lt_iff_lt_mul'
-
-theorem one_le_div_iff {a b : ℕ} (hb : 0 < b) : 1 ≤ a / b ↔ b ≤ a := by
-  rw [le_div_iff_mul_le hb, one_mul]
-#align nat.one_le_div_iff Nat.one_le_div_iff
-
-theorem div_lt_one_iff {a b : ℕ} (hb : 0 < b) : a / b < 1 ↔ a < b :=
-  lt_iff_lt_of_le_iff_le <| one_le_div_iff hb
-#align nat.div_lt_one_iff Nat.div_lt_one_iff
-
-protected theorem div_le_div_right {n m : ℕ} (h : n ≤ m) {k : ℕ} : n / k ≤ m / k :=
-  ((Nat.eq_zero_or_pos k).elim fun k0 => by simp [k0]) fun hk =>
-    (le_div_iff_mul_le' hk).2 <| le_trans (Nat.div_mul_le_self _ _) h
-#align nat.div_le_div_right Nat.div_le_div_right
-
-theorem lt_of_div_lt_div {m n k : ℕ} : m / k < n / k → m < n :=
-  lt_imp_lt_of_le_imp_le fun h => Nat.div_le_div_right h
-#align nat.lt_of_div_lt_div Nat.lt_of_div_lt_div
-
-protected theorem div_pos {a b : ℕ} (hba : b ≤ a) (hb : 0 < b) : 0 < a / b :=
-  Nat.pos_of_ne_zero fun h =>
-    lt_irrefl a
-      (calc
-        a = a % b := by simpa [h] using (mod_add_div a b).symm
-        _ < b := Nat.mod_lt a hb
-        _ ≤ a := hba
-        )
-#align nat.div_pos Nat.div_pos
-
-theorem lt_mul_of_div_lt {a b c : ℕ} (h : a / c < b) (w : 0 < c) : a < b * c :=
-  lt_of_not_ge <| not_le_of_gt h ∘ (Nat.le_div_iff_mul_le w).2
-#align nat.lt_mul_of_div_lt Nat.lt_mul_of_div_lt
-
-theorem mul_div_le_mul_div_assoc (a b c : ℕ) : 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 [mul_assoc]; exact Nat.mul_le_mul_left _ (Nat.div_mul_le_self _ _))
-#align nat.mul_div_le_mul_div_assoc Nat.mul_div_le_mul_div_assoc
-
-protected theorem eq_mul_of_div_eq_right {a b c : ℕ} (H1 : b ∣ a) (H2 : a / b = c) : a = b * c := by
-  rw [← H2, Nat.mul_div_cancel' H1]
-#align nat.eq_mul_of_div_eq_right Nat.eq_mul_of_div_eq_right
-
-protected theorem div_eq_iff_eq_mul_right {a b c : ℕ} (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⟩
-#align nat.div_eq_iff_eq_mul_right Nat.div_eq_iff_eq_mul_right
-
-protected theorem div_eq_iff_eq_mul_left {a b c : ℕ} (H : 0 < b) (H' : b ∣ a) :
-    a / b = c ↔ a = c * b := by
-  rw [mul_comm]
-  exact Nat.div_eq_iff_eq_mul_right H H'
-#align nat.div_eq_iff_eq_mul_left Nat.div_eq_iff_eq_mul_left
-
-protected theorem eq_mul_of_div_eq_left {a b c : ℕ} (H1 : b ∣ a) (H2 : a / b = c) : a = c * b := by
-  rw [mul_comm, Nat.eq_mul_of_div_eq_right H1 H2]
-#align nat.eq_mul_of_div_eq_left Nat.eq_mul_of_div_eq_left
-
-protected theorem mul_div_cancel_left' {a b : ℕ} (Hd : a ∣ b) : a * (b / a) = b := by
-  rw [mul_comm, Nat.div_mul_cancel Hd]
-#align nat.mul_div_cancel_left' Nat.mul_div_cancel_left'
-
-#align nat.mul_div_mul_left Nat.mul_div_mul_left
-#align nat.mul_div_mul_right Nat.mul_div_mul_right
-
-theorem lt_div_mul_add {a b : ℕ} (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 _
-#align nat.lt_div_mul_add Nat.lt_div_mul_add
-
-@[simp]
-protected theorem div_left_inj {a b d : ℕ} (hda : d ∣ a) (hdb : d ∣ b) : a / d = b / d ↔ a = b := by
-  refine ⟨fun h => ?_, congr_arg fun n => n / d⟩
-  rw [← Nat.mul_div_cancel' hda, ← Nat.mul_div_cancel' hdb, h]
-#align nat.div_left_inj Nat.div_left_inj
-
-theorem div_mul_div_comm {l : ℕ} (hmn : n ∣ m) (hkl : l ∣ k) :
-    (m / n) * (k / l) = (m * k) / (n * l) := by
-  obtain ⟨x, rfl⟩ := hmn
-  obtain ⟨y, rfl⟩ := hkl
-  rcases n.eq_zero_or_pos with rfl | hn
-  · simp
-  rcases l.eq_zero_or_pos with rfl | hl
-  · simp
-  rw [Nat.mul_div_cancel_left _ hn, Nat.mul_div_cancel_left _ hl, mul_assoc n, Nat.mul_left_comm x,
-    ← mul_assoc n, Nat.mul_div_cancel_left _ (Nat.mul_pos hn hl)]
-#align nat.div_mul_div_comm Nat.div_mul_div_comm
-
-protected theorem div_pow {a b c : ℕ} (h : a ∣ b) : (b / a) ^ c = b ^ c / a ^ c := by
-  rcases c.eq_zero_or_pos with rfl | hc
-  · simp
-  rcases a.eq_zero_or_pos with rfl | ha
-  · simp [Nat.zero_pow hc]
-  refine (Nat.div_eq_of_eq_mul_right (pos_pow_of_pos c ha) ?_).symm
-  rw [← Nat.mul_pow, Nat.mul_div_cancel_left' h]
-
-/-! ### `mod`, `dvd` -/
-
-
-theorem mod_eq_iff_lt {a b : ℕ} (h : b ≠ 0) : a % b = a ↔ a < b := by
-  cases b
-  contradiction
-  exact ⟨fun h => h.ge.trans_lt (mod_lt _ (succ_pos _)), mod_eq_of_lt⟩
-#align nat.mod_eq_iff_lt Nat.mod_eq_iff_lt
-
-@[simp]
-theorem mod_succ_eq_iff_lt {a b : ℕ} : a % b.succ = a ↔ a < b.succ :=
-  mod_eq_iff_lt (succ_ne_zero _)
-#align nat.mod_succ_eq_iff_lt Nat.mod_succ_eq_iff_lt
-
-@[simp]
-theorem mod_succ (n : ℕ) : n % n.succ = n :=
-  Nat.mod_eq_of_lt (Nat.lt_succ_self _)
-
--- Porting note `Nat.div_add_mod` is now in core.
-
-theorem mod_add_div' (m k : ℕ) : m % k + m / k * k = m := by
-  rw [mul_comm]
-  exact mod_add_div _ _
-#align nat.mod_add_div' Nat.mod_add_div'
-
-theorem div_add_mod' (m k : ℕ) : m / k * k + m % k = m := by
-  rw [mul_comm]
-  exact div_add_mod _ _
-#align nat.div_add_mod' Nat.div_add_mod'
-
-/-- See also `Nat.divModEquiv` for a similar statement as an `Equiv`. -/
-protected theorem div_mod_unique {n k m d : ℕ} (h : 0 < k) :
-    n / k = d ∧ n % k = m ↔ m + k * d = n ∧ m < k :=
-  ⟨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₂]⟩
-#align nat.div_mod_unique Nat.div_mod_unique
-
-protected theorem dvd_add_left {k m n : ℕ} (h : k ∣ n) : k ∣ m + n ↔ k ∣ m :=
-  (Nat.dvd_add_iff_left h).symm
-#align nat.dvd_add_left Nat.dvd_add_left
-
-protected theorem dvd_add_right {k m n : ℕ} (h : k ∣ m) : k ∣ m + n ↔ k ∣ n :=
-  (Nat.dvd_add_iff_right h).symm
-#align nat.dvd_add_right Nat.dvd_add_right
-
-protected theorem mul_dvd_mul_iff_left {a b c : ℕ} (ha : 0 < a) : a * b ∣ a * c ↔ b ∣ c :=
-  exists_congr fun d => by rw [mul_assoc, mul_right_inj' ha.ne']
-#align nat.mul_dvd_mul_iff_left Nat.mul_dvd_mul_iff_left
-
-protected theorem mul_dvd_mul_iff_right {a b c : ℕ} (hc : 0 < c) : a * c ∣ b * c ↔ a ∣ b :=
-  exists_congr fun d => by rw [Nat.mul_right_comm, mul_left_inj' hc.ne']
-#align nat.mul_dvd_mul_iff_right Nat.mul_dvd_mul_iff_right
-
-#align nat.dvd_one Nat.dvd_one
-
-@[simp]
-theorem mod_mod_of_dvd (n : Nat) {m k : Nat} (h : m ∣ k) : n % k % m = n % m := by
-  conv_rhs => rw [← mod_add_div n k]
-  rcases h with ⟨t, rfl⟩
-  rw [mul_assoc, add_mul_mod_self_left]
-#align nat.mod_mod_of_dvd Nat.mod_mod_of_dvd
-
--- Moved to Std
-#align nat.mod_mod Nat.mod_mod
-#align nat.mod_add_mod Nat.mod_add_mod
-#align nat.add_mod_mod Nat.add_mod_mod
-#align nat.add_mod Nat.add_mod
-
-theorem add_mod_eq_add_mod_right {m n k : ℕ} (i : ℕ) (H : m % n = k % n) :
-    (m + i) % n = (k + i) % n := by
-  rw [← mod_add_mod, ← mod_add_mod k, H]
-#align nat.add_mod_eq_add_mod_right Nat.add_mod_eq_add_mod_right
-
-theorem add_mod_eq_add_mod_left {m n k : ℕ} (i : ℕ) (H : m % n = k % n) :
-    (i + m) % n = (i + k) % n := by
-  rw [add_comm, add_mod_eq_add_mod_right _ H, add_comm]
-#align nat.add_mod_eq_add_mod_left Nat.add_mod_eq_add_mod_left
-
--- Moved to Std
-#align nat.mul_mod Nat.mul_mod
-
-theorem mul_dvd_of_dvd_div {a b c : ℕ} (hab : c ∣ b) (h : a ∣ b / c) : c * a ∣ b :=
-  have h1 : ∃ d, b / c = a * d := h
-  let ⟨d, hd⟩ := h1
-  have h3 : b = a * d * c := Nat.eq_mul_of_div_eq_left hab hd
-  -- Porting note: was `cc`
-  show ∃ d, b = c * a * d from ⟨d, by rwa [mul_comm, ← mul_assoc] at h3⟩
-#align nat.mul_dvd_of_dvd_div Nat.mul_dvd_of_dvd_div
-
-theorem eq_of_dvd_of_div_eq_one {a b : ℕ} (w : a ∣ b) (h : b / a = 1) : a = b := by
-  rw [← Nat.div_mul_cancel w, h, one_mul]
-#align nat.eq_of_dvd_of_div_eq_one Nat.eq_of_dvd_of_div_eq_one
-
-theorem eq_zero_of_dvd_of_div_eq_zero {a b : ℕ} (w : a ∣ b) (h : b / a = 0) : b = 0 := by
-  rw [← Nat.div_mul_cancel w, h, zero_mul]
-#align nat.eq_zero_of_dvd_of_div_eq_zero Nat.eq_zero_of_dvd_of_div_eq_zero
-
-theorem div_le_div_left {a b c : ℕ} (h₁ : c ≤ b) (h₂ : 0 < c) : a / b ≤ a / c :=
-  (Nat.le_div_iff_mul_le h₂).2 <| le_trans (Nat.mul_le_mul_left _ h₁) (div_mul_le_self _ _)
-#align nat.div_le_div_left Nat.div_le_div_left
-
-theorem lt_iff_le_pred : ∀ {m n : ℕ}, 0 < n → (m < n ↔ m ≤ n - 1)
-  | _, _ + 1, _ => lt_succ_iff
-#align nat.lt_iff_le_pred Nat.lt_iff_le_pred
-
--- Moved to Std
-#align nat.mul_div_le Nat.mul_div_le
-
-theorem lt_mul_div_succ (m : ℕ) {n : ℕ} (n0 : 0 < n) : m < n * (m / n + 1) := by
-  rw [mul_comm, ← Nat.div_lt_iff_lt_mul' n0]
-  exact lt_succ_self _
-#align nat.lt_mul_div_succ Nat.lt_mul_div_succ
-
--- TODO: Std4 claimed this name but flipped the order of multiplication
-theorem mul_add_mod' (a b c : ℕ) : (a * b + c) % b = c % b := by rw [mul_comm, Nat.mul_add_mod]
-#align nat.mul_add_mod Nat.mul_add_mod'
-
-theorem mul_add_mod_of_lt {a b c : ℕ} (h : c < b) : (a * b + c) % b = c := by
-  rw [Nat.mul_add_mod', Nat.mod_eq_of_lt h]
-#align nat.mul_add_mod_of_lt Nat.mul_add_mod_of_lt
-
-theorem pred_eq_self_iff {n : ℕ} : n.pred = n ↔ n = 0 := by
-  cases n <;> simp [(Nat.succ_ne_self _).symm]
-#align nat.pred_eq_self_iff Nat.pred_eq_self_iff
-
-/-! ### `find` -/
-
-
-section Find
-
-variable {p q : ℕ → Prop} [DecidablePred p] [DecidablePred q]
-
-theorem find_eq_iff (h : ∃ n : ℕ, p n) : Nat.find h = m ↔ p m ∧ ∀ n < m, ¬p n := by
-  constructor
-  · rintro rfl
-    exact ⟨Nat.find_spec h, fun _ => Nat.find_min h⟩
-  · rintro ⟨hm, hlt⟩
-    exact le_antisymm (Nat.find_min' h hm) (not_lt.1 <| imp_not_comm.1 (hlt _) <| Nat.find_spec h)
-#align nat.find_eq_iff Nat.find_eq_iff
-
-@[simp]
-theorem find_lt_iff (h : ∃ n : ℕ, p n) (n : ℕ) : Nat.find h < n ↔ ∃ m < n, p m :=
-  ⟨fun h2 => ⟨Nat.find h, h2, Nat.find_spec h⟩,
-   fun ⟨_, hmn, hm⟩ => (Nat.find_min' h hm).trans_lt hmn⟩
-#align nat.find_lt_iff Nat.find_lt_iff
-
-@[simp]
-theorem find_le_iff (h : ∃ n : ℕ, p n) (n : ℕ) : Nat.find h ≤ n ↔ ∃ m ≤ n, p m := by
-  simp only [exists_prop, ← lt_succ_iff, find_lt_iff]
-#align nat.find_le_iff Nat.find_le_iff
-
-@[simp]
-theorem le_find_iff (h : ∃ n : ℕ, p n) (n : ℕ) : n ≤ Nat.find h ↔ ∀ m < n, ¬p m := by
-  simp_rw [← not_lt, find_lt_iff, not_exists, not_and]
-#align nat.le_find_iff Nat.le_find_iff
-
-@[simp]
-theorem lt_find_iff (h : ∃ n : ℕ, p n) (n : ℕ) : n < Nat.find h ↔ ∀ m ≤ n, ¬p m := by
-  simp only [← succ_le_iff, le_find_iff, succ_le_succ_iff]
-#align nat.lt_find_iff Nat.lt_find_iff
-
-@[simp]
-theorem find_eq_zero (h : ∃ n : ℕ, p n) : Nat.find h = 0 ↔ p 0 := by simp [find_eq_iff]
-#align nat.find_eq_zero Nat.find_eq_zero
-
-theorem find_mono (h : ∀ n, q n → p n) {hp : ∃ n, p n} {hq : ∃ n, q n} :
-    Nat.find hp ≤ Nat.find hq :=
-  Nat.find_min' _ (h _ (Nat.find_spec hq))
-#align nat.find_mono Nat.find_mono
-
-theorem find_le {h : ∃ n, p n} (hn : p n) : Nat.find h ≤ n :=
-  (Nat.find_le_iff _ _).2 ⟨n, le_rfl, hn⟩
-#align nat.find_le Nat.find_le
-
-theorem find_comp_succ (h₁ : ∃ n, p n) (h₂ : ∃ n, p (n + 1)) (h0 : ¬p 0) :
-    Nat.find h₁ = Nat.find h₂ + 1 := by
-  refine' (find_eq_iff _).2 ⟨Nat.find_spec h₂, fun n hn => _⟩
-  cases' n with n
-  exacts [h0, @Nat.find_min (fun n => p (n + 1)) _ h₂ _ (succ_lt_succ_iff.1 hn)]
-#align nat.find_comp_succ Nat.find_comp_succ
-
-end Find
-
-/-! ### `find_greatest` -/
-
-
-section FindGreatest
-
-/-- `find_greatest P b` is the largest `i ≤ bound` such that `P i` holds, or `0` if no such `i`
-exists -/
-protected def findGreatest (P : ℕ → Prop) [DecidablePred P] : ℕ → ℕ
-  | 0 => 0
-  | n + 1 => if P (n + 1) then n + 1 else Nat.findGreatest P n
-#align nat.find_greatest Nat.findGreatest
-
-variable {P Q : ℕ → Prop} [DecidablePred P] {b : ℕ}
-
-@[simp]
-theorem findGreatest_zero : Nat.findGreatest P 0 = 0 :=
-  rfl
-#align nat.find_greatest_zero Nat.findGreatest_zero
-
-theorem findGreatest_succ (n : ℕ) :
-    Nat.findGreatest P (n + 1) = if P (n + 1) then n + 1 else Nat.findGreatest P n :=
-  rfl
-#align nat.find_greatest_succ Nat.findGreatest_succ
-
-@[simp]
-theorem findGreatest_eq : ∀ {b}, P b → Nat.findGreatest P b = b
-  | 0, _ => rfl
-  | n + 1, h => by simp [Nat.findGreatest, h]
-#align nat.find_greatest_eq Nat.findGreatest_eq
-
-@[simp]
-theorem findGreatest_of_not (h : ¬P (b + 1)) :
-    Nat.findGreatest P (b + 1) = Nat.findGreatest P b := by
-  simp [Nat.findGreatest, h]
-#align nat.find_greatest_of_not Nat.findGreatest_of_not
-
-end FindGreatest
-
-/-! ### decidability of predicates -/
-
--- To work around lean4#2552, we use `match` instead of `if/casesOn` with decidable instances.
-instance decidableBallLT :
-  ∀ (n : Nat) (P : ∀ k, k < n → Prop) [∀ n h, Decidable (P n h)], Decidable (∀ n h, P n h)
-| 0, _, _ => isTrue fun _ => (by cases ·)
-| (n+1), P, H =>
-  match decidableBallLT n (P · <| lt_succ_of_lt ·) with
-  | isFalse h => isFalse (h fun _ _ => · _ _)
-  | isTrue h =>
-    match H n Nat.le.refl with
-    | isFalse p => isFalse (p <| · _ _)
-    | isTrue p => isTrue fun _ h' => (Nat.le_of_lt_succ h').lt_or_eq_dec.elim (h _) (· ▸ p)
-#align nat.decidable_ball_lt Nat.decidableBallLT
-
--- To verify we don't have a regression on the speed, we put a difficult example.
--- any regression should take a huge amount of heartbeats -- we are currently at 187621.
--- For reference, the instance using `casesOn` took 44544 for 4; this one takes 1299 for 4.
-example : ∀ a, a < 25 → ∀ b, b < 25 → ∀ c, c < 25 → a ^ 2 + b ^ 2 + c ^ 2 ≠ 7 := by decide
-
-instance decidableForallFin {n : ℕ} (P : Fin n → Prop) [DecidablePred P] :
-    Decidable (∀ i, P i) :=
-  decidable_of_iff (∀ k h, P ⟨k, h⟩) ⟨fun a ⟨k, h⟩ => a k h, fun a k h => a ⟨k, h⟩⟩
-#align nat.decidable_forall_fin Nat.decidableForallFin
-
-instance decidableBallLe (n : ℕ) (P : ∀ k ≤ n, Prop) [∀ n h, Decidable (P n h)] :
-    Decidable (∀ n h, P n h) :=
-  decidable_of_iff (∀ (k) (h : k < succ n), P k (le_of_lt_succ h))
-    ⟨fun a k h => a k (lt_succ_of_le h), fun a k _ => a k _⟩
-#align nat.decidable_ball_le Nat.decidableBallLe
-
-instance decidableExistsLT {P : ℕ → Prop} [h : DecidablePred P] :
-    DecidablePred fun n => ∃ m : ℕ, m < n ∧ P m
-  | 0 => isFalse (by simp)
-  | n + 1 =>
-    @decidable_of_decidable_of_iff _ _ (@instDecidableOr _ _ (decidableExistsLT n) (h n))
-      (by simp only [lt_succ_iff_lt_or_eq, or_and_right, exists_or, exists_eq_left]; apply Iff.refl)
-#align nat.decidable_exists_lt Nat.decidableExistsLT
-
-instance decidableExistsLe {P : ℕ → Prop} [DecidablePred P] :
-    DecidablePred fun n => ∃ m : ℕ, m ≤ n ∧ P m :=
-  fun n => decidable_of_iff (∃ m, m < n + 1 ∧ P m)
-    (exists_congr fun _ => and_congr_left' lt_succ_iff)
-#align nat.decidable_exists_le Nat.decidableExistsLe
-
 end Nat
chore: Move Int and Nat cast lemmas (#9503)

Part of #9411

Diff
@@ -3,10 +3,10 @@ Copyright (c) 2014 Floris van Doorn (c) 2016 Microsoft Corporation. All rights r
 Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Floris van Doorn, Leonardo de Moura, Jeremy Avigad, Mario Carneiro
 -/
+import Mathlib.Algebra.Group.TypeTags
+import Mathlib.Algebra.Ring.Defs
 import Mathlib.Init.Data.Nat.Lemmas
 import Mathlib.Order.Basic
-import Mathlib.Algebra.GroupWithZero.Defs
-import Mathlib.Algebra.Ring.Defs
 import Mathlib.Tactic.PushNeg
 import Mathlib.Tactic.Use
 
@@ -121,6 +121,18 @@ attribute [simp]
   -- Nat.zero_ne_bit1 Nat.bit1_ne_zero Nat.bit0_ne_one Nat.one_ne_bit0 Nat.bit0_ne_bit1
   -- Nat.bit1_ne_bit0
 
+section Multiplicative
+
+open Multiplicative
+
+lemma toAdd_pow (a : Multiplicative ℕ) (b : ℕ) : toAdd (a ^ b) = toAdd a * b := mul_comm _ _
+#align nat.to_add_pow Nat.toAdd_pow
+
+@[simp] lemma ofAdd_mul (a b : ℕ) : ofAdd (a * b) = ofAdd a ^ b := (toAdd_pow _ _).symm
+#align nat.of_add_mul Nat.ofAdd_mul
+
+end Multiplicative
+
 variable {m n k : ℕ}
 
 /-!
chore: bump dependencies (#9424)

Co-authored-by: Scott Morrison <scott.morrison@gmail.com>

Diff
@@ -774,9 +774,6 @@ protected theorem mul_dvd_mul_iff_right {a b c : ℕ} (hc : 0 < c) : a * c ∣ b
   exists_congr fun d => by rw [Nat.mul_right_comm, mul_left_inj' hc.ne']
 #align nat.mul_dvd_mul_iff_right Nat.mul_dvd_mul_iff_right
 
-@[simp] -- TODO: move to Std4
-theorem dvd_one {a : ℕ} : a ∣ 1 ↔ a = 1 :=
-  ⟨eq_one_of_dvd_one, fun h ↦ h.symm ▸ Nat.dvd_refl _⟩
 #align nat.dvd_one Nat.dvd_one
 
 @[simp]
chore: use elab_as_elim directly, now that lean4#1900 is fixed (#9288)

Adds the attribute elab_as_elim directly to the declarations of strongSubRecursion and pincerRecursion, rather than in separate commands.

This change was made possible by https://github.com/leanprover/lean4/commit/8a573b5d87a42bd19307522ee747aaed44d9d71c, which fixed https://github.com/leanprover/lean4/issues/1900.

Diff
@@ -560,21 +560,18 @@ theorem decreasingInduction_succ_left {P : ℕ → Sort*} (h : ∀ n, P (n + 1)
 strictly below `(a,b)` to `P a b`, then we have `P n m` for all `n m : ℕ`.
 Note that for non-`Prop` output it is preferable to use the equation compiler directly if possible,
 since this produces equation lemmas. -/
+@[elab_as_elim]
 def strongSubRecursion {P : ℕ → ℕ → Sort*} (H : ∀ a b, (∀ x y, x < a → y < b → P x y) → P a b) :
     ∀ n m : ℕ, P n m
   | n, m => H n m fun x y _ _ => strongSubRecursion H x y
 #align nat.strong_sub_recursion Nat.strongSubRecursion
 
--- Porting note:
--- we can't put this on the definition itself because of
--- https://github.com/leanprover/lean4/issues/1900
-attribute [elab_as_elim] strongSubRecursion
-
 /-- Given `P : ℕ → ℕ → Sort*`, if we have `P i 0` and `P 0 i` for all `i : ℕ`,
 and for any `x y : ℕ` we can extend `P` from `(x,y+1)` and `(x+1,y)` to `(x+1,y+1)`
 then we have `P n m` for all `n m : ℕ`.
 Note that for non-`Prop` output it is preferable to use the equation compiler directly if possible,
 since this produces equation lemmas. -/
+@[elab_as_elim]
 def pincerRecursion {P : ℕ → ℕ → Sort*} (Ha0 : ∀ a : ℕ, P a 0) (H0b : ∀ b : ℕ, P 0 b)
     (H : ∀ x y : ℕ, P x y.succ → P x.succ y → P x.succ y.succ) : ∀ n m : ℕ, P n m
   | a, 0 => Ha0 a
@@ -583,11 +580,6 @@ def pincerRecursion {P : ℕ → ℕ → Sort*} (Ha0 : ∀ a : ℕ, P a 0) (H0b
 termination_by pincerRecursion Ha0 Hab H n m => n + m
 #align nat.pincer_recursion Nat.pincerRecursion
 
--- Porting note:
--- we can't put this on the definition itself because of
--- https://github.com/leanprover/lean4/issues/1900
-attribute [elab_as_elim] pincerRecursion
-
 /-- Recursion starting at a non-zero number: given a map `C k → C (k+1)` for each `k ≥ n`,
 there is a map from `C n` to each `C m`, `n ≤ m`. -/
 @[elab_as_elim]
feat(Data/Fin): add lemmas (#8974)
  • move Nat.dvd_one to Data.Nat.Basic; it should go to Std4;
  • rename Fin.ofNat_eq_val to Fin.ofNat''_eq_cast;
  • add @[simp] lemmas Fin.val_nat_cast, Fin.nat_cast_self, and Fin.nat_cast_eq_zero;
  • add @[simp] to Fin.cast_nat_eq_last and ZMod.val_nat_cast;
  • add binomial_apply_last, as the LHS of binomial_apply_self is no longer in simp normal form.
Diff
@@ -782,11 +782,14 @@ protected theorem mul_dvd_mul_iff_right {a b c : ℕ} (hc : 0 < c) : a * c ∣ b
   exists_congr fun d => by rw [Nat.mul_right_comm, mul_left_inj' hc.ne']
 #align nat.mul_dvd_mul_iff_right Nat.mul_dvd_mul_iff_right
 
+@[simp] -- TODO: move to Std4
+theorem dvd_one {a : ℕ} : a ∣ 1 ↔ a = 1 :=
+  ⟨eq_one_of_dvd_one, fun h ↦ h.symm ▸ Nat.dvd_refl _⟩
+#align nat.dvd_one Nat.dvd_one
+
 @[simp]
 theorem mod_mod_of_dvd (n : Nat) {m k : Nat} (h : m ∣ k) : n % k % m = n % m := by
-  conv =>
-  rhs
-  rw [← mod_add_div n k]
+  conv_rhs => rw [← mod_add_div n k]
   rcases h with ⟨t, rfl⟩
   rw [mul_assoc, add_mul_mod_self_left]
 #align nat.mod_mod_of_dvd Nat.mod_mod_of_dvd
chore: Nat.mod_succ (#9031)

A simp lemma specialized to n % n.succ

Co-authored-by: Yakov Pechersky <pechersky@users.noreply.github.com>

Diff
@@ -741,6 +741,10 @@ theorem mod_succ_eq_iff_lt {a b : ℕ} : a % b.succ = a ↔ a < b.succ :=
   mod_eq_iff_lt (succ_ne_zero _)
 #align nat.mod_succ_eq_iff_lt Nat.mod_succ_eq_iff_lt
 
+@[simp]
+theorem mod_succ (n : ℕ) : n % n.succ = n :=
+  Nat.mod_eq_of_lt (Nat.lt_succ_self _)
+
 -- Porting note `Nat.div_add_mod` is now in core.
 
 theorem mod_add_div' (m k : ℕ) : m % k + m / k * k = m := by
chore: space after (#8178)

Co-authored-by: Moritz Firsching <firsching@google.com>

Diff
@@ -716,7 +716,7 @@ theorem div_mul_div_comm {l : ℕ} (hmn : n ∣ m) (hkl : l ∣ k) :
   rcases l.eq_zero_or_pos with rfl | hl
   · simp
   rw [Nat.mul_div_cancel_left _ hn, Nat.mul_div_cancel_left _ hl, mul_assoc n, Nat.mul_left_comm x,
-    ←mul_assoc n, Nat.mul_div_cancel_left _ (Nat.mul_pos hn hl)]
+    ← mul_assoc n, Nat.mul_div_cancel_left _ (Nat.mul_pos hn hl)]
 #align nat.div_mul_div_comm Nat.div_mul_div_comm
 
 protected theorem div_pow {a b c : ℕ} (h : a ∣ b) : (b / a) ^ c = b ^ c / a ^ c := by
@@ -725,7 +725,7 @@ protected theorem div_pow {a b c : ℕ} (h : a ∣ b) : (b / a) ^ c = b ^ c / a
   rcases a.eq_zero_or_pos with rfl | ha
   · simp [Nat.zero_pow hc]
   refine (Nat.div_eq_of_eq_mul_right (pos_pow_of_pos c ha) ?_).symm
-  rw [←Nat.mul_pow, Nat.mul_div_cancel_left' h]
+  rw [← Nat.mul_pow, Nat.mul_div_cancel_left' h]
 
 /-! ### `mod`, `dvd` -/
 
@@ -811,7 +811,7 @@ theorem mul_dvd_of_dvd_div {a b c : ℕ} (hab : c ∣ b) (h : a ∣ b / c) : c *
   let ⟨d, hd⟩ := h1
   have h3 : b = a * d * c := Nat.eq_mul_of_div_eq_left hab hd
   -- Porting note: was `cc`
-  show ∃ d, b = c * a * d from ⟨d, by rwa [mul_comm, ←mul_assoc] at h3⟩
+  show ∃ d, b = c * a * d from ⟨d, by rwa [mul_comm, ← mul_assoc] at h3⟩
 #align nat.mul_dvd_of_dvd_div Nat.mul_dvd_of_dvd_div
 
 theorem eq_of_dvd_of_div_eq_one {a b : ℕ} (w : a ∣ b) (h : b / a = 1) : a = b := by
chore: bump Std, changes for leanprover/std4#366 (#8700)

Notably leanprover/std4#366 changed the definition of testBit (to something equivalent) when upstreaming it, which broke a handful of proofs.

Other conflicting changes in Std, resolved for now by priming the mathlib name:

  • Std.BitVec.adc: the type was changed from BitVec (n + 1) to Bool × BitVec w
  • Nat.mul_add_mod: the type was changed from (a * b + c) % b = c % b to (b * a + c) % b = c % b

Zulip thread

Co-authored-by: Scott Morrison <scott.morrison@gmail.com> Co-authored-by: Alex Keizer <alex@keizer.dev> Co-authored-by: Eric Wieser <wieser.eric@gmail.com>

Diff
@@ -838,11 +838,12 @@ theorem lt_mul_div_succ (m : ℕ) {n : ℕ} (n0 : 0 < n) : m < n * (m / n + 1) :
   exact lt_succ_self _
 #align nat.lt_mul_div_succ Nat.lt_mul_div_succ
 
-theorem mul_add_mod (a b c : ℕ) : (a * b + c) % b = c % b := by simp [Nat.add_mod]
-#align nat.mul_add_mod Nat.mul_add_mod
+-- TODO: Std4 claimed this name but flipped the order of multiplication
+theorem mul_add_mod' (a b c : ℕ) : (a * b + c) % b = c % b := by rw [mul_comm, Nat.mul_add_mod]
+#align nat.mul_add_mod Nat.mul_add_mod'
 
 theorem mul_add_mod_of_lt {a b c : ℕ} (h : c < b) : (a * b + c) % b = c := by
-  rw [Nat.mul_add_mod, Nat.mod_eq_of_lt h]
+  rw [Nat.mul_add_mod', Nat.mod_eq_of_lt h]
 #align nat.mul_add_mod_of_lt Nat.mul_add_mod_of_lt
 
 theorem pred_eq_self_iff {n : ℕ} : n.pred = n ↔ n = 0 := by
fix: patch for std4#203 (more sub lemmas for Nat) (#6216)
Diff
@@ -288,11 +288,11 @@ theorem exists_eq_add_of_lt (h : m < n) : ∃ k : ℕ, n = m + k + 1 :=
 /-! ### `pred` -/
 
 @[simp]
-theorem add_succ_sub_one (n m : ℕ) : n + succ m - 1 = n + m := by rw [add_succ, succ_sub_one]
+theorem add_succ_sub_one (n m : ℕ) : n + succ m - 1 = n + m := by rw [add_succ, Nat.add_one_sub_one]
 #align nat.add_succ_sub_one Nat.add_succ_sub_one
 
 @[simp]
-theorem succ_add_sub_one (n m : ℕ) : succ n + m - 1 = n + m := by rw [succ_add, succ_sub_one]
+theorem succ_add_sub_one (n m : ℕ) : succ n + m - 1 = n + m := by rw [succ_add, Nat.add_one_sub_one]
 #align nat.succ_add_sub_one Nat.succ_add_sub_one
 
 theorem pred_eq_sub_one (n : ℕ) : pred n = n - 1 :=
feat(Data/Nat): add Nat.div_pow (#8327)

Adds the missing lemma Nat.div_pow, which seemed to be missing (at least, exact?% couldn't find it with all of Mathlib imported). Also moves div_mul_div_comm higher in the hierarchy (and golf) because it doesn't need the ordered semiring instance, cf the docstring of Data/Nat/Order/Basic.

Co-authored-by: Bhavik Mehta <bm489@cam.ac.uk>

Diff
@@ -707,6 +707,26 @@ protected theorem div_left_inj {a b d : ℕ} (hda : d ∣ a) (hdb : d ∣ b) : a
   rw [← Nat.mul_div_cancel' hda, ← Nat.mul_div_cancel' hdb, h]
 #align nat.div_left_inj Nat.div_left_inj
 
+theorem div_mul_div_comm {l : ℕ} (hmn : n ∣ m) (hkl : l ∣ k) :
+    (m / n) * (k / l) = (m * k) / (n * l) := by
+  obtain ⟨x, rfl⟩ := hmn
+  obtain ⟨y, rfl⟩ := hkl
+  rcases n.eq_zero_or_pos with rfl | hn
+  · simp
+  rcases l.eq_zero_or_pos with rfl | hl
+  · simp
+  rw [Nat.mul_div_cancel_left _ hn, Nat.mul_div_cancel_left _ hl, mul_assoc n, Nat.mul_left_comm x,
+    ←mul_assoc n, Nat.mul_div_cancel_left _ (Nat.mul_pos hn hl)]
+#align nat.div_mul_div_comm Nat.div_mul_div_comm
+
+protected theorem div_pow {a b c : ℕ} (h : a ∣ b) : (b / a) ^ c = b ^ c / a ^ c := by
+  rcases c.eq_zero_or_pos with rfl | hc
+  · simp
+  rcases a.eq_zero_or_pos with rfl | ha
+  · simp [Nat.zero_pow hc]
+  refine (Nat.div_eq_of_eq_mul_right (pos_pow_of_pos c ha) ?_).symm
+  rw [←Nat.mul_pow, Nat.mul_div_cancel_left' h]
+
 /-! ### `mod`, `dvd` -/
 
 
fix: patch for std4#195 (more succ/pred lemmas for Nat) (#6203)
Diff
@@ -165,7 +165,6 @@ theorem eq_of_le_of_lt_succ {n m : ℕ} (h₁ : n ≤ m) (h₂ : m < n + 1) : m
 -- Moved to Std
 #align nat.one_add Nat.one_add
 
-@[simp]
 theorem succ_pos' {n : ℕ} : 0 < succ n :=
   succ_pos n
 #align nat.succ_pos' Nat.succ_pos'
feat: patch for std4#196 (more min/max lemmas for Nat) (#8074)

Co-authored-by: Scott Morrison <scott.morrison@gmail.com>

Diff
@@ -192,13 +192,7 @@ theorem one_lt_succ_succ (n : ℕ) : 1 < n.succ.succ :=
 
 -- Porting note: Nat.succ_le_succ_iff is in Std
 
-theorem max_succ_succ {m n : ℕ} : max (succ m) (succ n) = succ (max m n) := by
-  by_cases h1 : m ≤ n
-  rw [max_eq_right h1, max_eq_right (succ_le_succ h1)]
-  · rw [not_le] at h1
-    have h2 := le_of_lt h1
-    rw [max_eq_left h2, max_eq_left (succ_le_succ h2)]
-#align nat.max_succ_succ Nat.max_succ_succ
+#align nat.max_succ_succ Nat.succ_max_succ
 
 theorem not_succ_lt_self {n : ℕ} : ¬succ n < n :=
   not_lt_of_ge (Nat.le_succ _)
fix: use match with Decidable. (#7232)

This works around leanprover/lean4#2552 - fix found by @b-mehta. I changed the Nat instance where the issue was found, and some List instances in hope it fixes mysterious slowdowns with Finset decidability. Any more instances changed would probably be good.

Diff
@@ -934,23 +934,24 @@ end FindGreatest
 
 /-! ### decidability of predicates -/
 
+-- To work around lean4#2552, we use `match` instead of `if/casesOn` with decidable instances.
 instance decidableBallLT :
-    ∀ (n : Nat) (P : ∀ k < n, Prop) [∀ n h, Decidable (P n h)], Decidable (∀ n h, P n h)
-| 0, P, _ => isTrue fun n h => by cases h
-| (n+1), P, H => by
-  cases' decidableBallLT n fun k h => P k (lt_succ_of_lt h) with h h
-  · refine' isFalse (mt _ h)
-    intro hn k h
-    apply hn
-  by_cases p : P n (lt_succ_self n)
-  · exact
-      isTrue fun k h' =>
-        (le_of_lt_succ h').lt_or_eq_dec.elim (h _) fun e =>
-          match k, e, h' with
-          | _, rfl, _ => p
-  · exact isFalse (mt (fun hn => hn _ _) p)
+  ∀ (n : Nat) (P : ∀ k, k < n → Prop) [∀ n h, Decidable (P n h)], Decidable (∀ n h, P n h)
+| 0, _, _ => isTrue fun _ => (by cases ·)
+| (n+1), P, H =>
+  match decidableBallLT n (P · <| lt_succ_of_lt ·) with
+  | isFalse h => isFalse (h fun _ _ => · _ _)
+  | isTrue h =>
+    match H n Nat.le.refl with
+    | isFalse p => isFalse (p <| · _ _)
+    | isTrue p => isTrue fun _ h' => (Nat.le_of_lt_succ h').lt_or_eq_dec.elim (h _) (· ▸ p)
 #align nat.decidable_ball_lt Nat.decidableBallLT
 
+-- To verify we don't have a regression on the speed, we put a difficult example.
+-- any regression should take a huge amount of heartbeats -- we are currently at 187621.
+-- For reference, the instance using `casesOn` took 44544 for 4; this one takes 1299 for 4.
+example : ∀ a, a < 25 → ∀ b, b < 25 → ∀ c, c < 25 → a ^ 2 + b ^ 2 + c ^ 2 ≠ 7 := by decide
+
 instance decidableForallFin {n : ℕ} (P : Fin n → Prop) [DecidablePred P] :
     Decidable (∀ i, P i) :=
   decidable_of_iff (∀ k h, P ⟨k, h⟩) ⟨fun a ⟨k, h⟩ => a k h, fun a k h => a ⟨k, h⟩⟩
feat: Finsets of cardinality > 1 in Pi types (#6818)

Add an equivalent condition for 1 < m * n in Nat, and two lemmas about Finsets of cardinality > 1.

Co-authored-by: Junyan Xu <junyanxu.math@gmail.com>

Diff
@@ -376,6 +376,20 @@ theorem lt_succ_iff_lt_or_eq {n i : ℕ} : n < i.succ ↔ n < i ∨ n = i :=
   lt_succ_iff.trans Decidable.le_iff_lt_or_eq
 #align nat.lt_succ_iff_lt_or_eq Nat.lt_succ_iff_lt_or_eq
 
+set_option push_neg.use_distrib true in
+/-- 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. -/
+lemma one_lt_mul_iff : 1 < m * n ↔ 0 < m ∧ 0 < n ∧ (1 < m ∨ 1 < n) := by
+  constructor <;> intro h
+  · by_contra h'; push_neg at h'; simp_rw [Nat.le_zero] at h'
+    obtain rfl | rfl | h' := h'
+    · simp at h
+    · simp at h
+    · exact (Nat.mul_le_mul h'.1 h'.2).not_lt h
+  · obtain hm | hn := h.2.2
+    · exact Nat.mul_lt_mul hm h.2.1 Nat.zero_lt_one
+    · exact Nat.mul_lt_mul' h.1 hn h.1
+
 /-!
 ### Recursion and induction principles
 
feat(Data/Nat/Basic): self_add_sub_one and friends (#7123)

Co-authored-by: Moritz Firsching <firsching@google.com>

Diff
@@ -327,6 +327,21 @@ theorem le_of_pred_lt {m n : ℕ} : pred m < n → m ≤ n :=
   | _ + 1 => id
 #align nat.le_of_pred_lt Nat.le_of_pred_lt
 
+theorem self_add_sub_one (n : ℕ) : n + (n - 1) = 2 * n - 1 := by
+  cases n
+  · rfl
+  · rw [two_mul]
+    convert (add_succ_sub_one (Nat.succ _) _).symm
+
+theorem sub_one_add_self (n : ℕ) : (n - 1) + n = 2 * n - 1 :=
+  add_comm _ n ▸ self_add_sub_one n
+
+theorem self_add_pred (n : ℕ) : n + pred n = (2 * n).pred :=
+  self_add_sub_one n
+
+theorem pred_add_self (n : ℕ) : pred n + n = (2 * n).pred :=
+  sub_one_add_self n
+
 /-- This ensures that `simp` succeeds on `pred (n + 1) = n`. -/
 @[simp]
 theorem pred_one_add (n : ℕ) : pred (1 + n) = n := by rw [add_comm, add_one, Nat.pred_succ]
chore: delay import of Tactic.Common (#7000)

I know that this is contrary to what we've done previously, but:

  • I'm trying to upstream a great many tactics from Mathlib to Std (essentially, everything that non-mathematicians want too).
  • This makes it much easier for me to see what is going on, and understand the import requirements (particularly for the "big" tactics norm_num / ring / linarith)
  • It's actually not as bad as it looks here, because as these tactics move up to Std they will start disappearing again from explicit imports, but Mathlib can happily import all of Std.

(Oh

Co-authored-by: Scott Morrison <scott.morrison@gmail.com>

Diff
@@ -7,6 +7,8 @@ import Mathlib.Init.Data.Nat.Lemmas
 import Mathlib.Order.Basic
 import Mathlib.Algebra.GroupWithZero.Defs
 import Mathlib.Algebra.Ring.Defs
+import Mathlib.Tactic.PushNeg
+import Mathlib.Tactic.Use
 
 #align_import data.nat.basic from "leanprover-community/mathlib"@"bd835ef554f37ef9b804f0903089211f89cb370b"
 
chore: cleanup in Mathlib.Init (#6977)

Co-authored-by: Scott Morrison <scott.morrison@gmail.com>

Diff
@@ -3,6 +3,7 @@ Copyright (c) 2014 Floris van Doorn (c) 2016 Microsoft Corporation. All rights r
 Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Floris van Doorn, Leonardo de Moura, Jeremy Avigad, Mario Carneiro
 -/
+import Mathlib.Init.Data.Nat.Lemmas
 import Mathlib.Order.Basic
 import Mathlib.Algebra.GroupWithZero.Defs
 import Mathlib.Algebra.Ring.Defs
chore: reduce imports of Data.Nat.Basic (#6974)

Slightly delay the import of Mathlib.Algebra.Group.Basic, to reduce imports for tactics.

Co-authored-by: Scott Morrison <scott.morrison@gmail.com>

Diff
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Floris van Doorn, Leonardo de Moura, Jeremy Avigad, Mario Carneiro
 -/
 import Mathlib.Order.Basic
-import Mathlib.Algebra.GroupWithZero.Basic
+import Mathlib.Algebra.GroupWithZero.Defs
 import Mathlib.Algebra.Ring.Defs
 
 #align_import data.nat.basic from "leanprover-community/mathlib"@"bd835ef554f37ef9b804f0903089211f89cb370b"
@@ -286,7 +286,7 @@ theorem exists_eq_add_of_le' (h : m ≤ n) : ∃ k : ℕ, n = k + m :=
 #align nat.exists_eq_add_of_le' Nat.exists_eq_add_of_le'
 
 theorem exists_eq_add_of_lt (h : m < n) : ∃ k : ℕ, n = m + k + 1 :=
-  ⟨n - (m + 1), by rw [add_right_comm, add_sub_of_le h]⟩
+  ⟨n - (m + 1), by rw [Nat.add_right_comm, add_sub_of_le h]⟩
 #align nat.exists_eq_add_of_lt Nat.exists_eq_add_of_lt
 
 /-! ### `pred` -/
@@ -730,7 +730,7 @@ protected theorem mul_dvd_mul_iff_left {a b c : ℕ} (ha : 0 < a) : a * b ∣ a
 #align nat.mul_dvd_mul_iff_left Nat.mul_dvd_mul_iff_left
 
 protected theorem mul_dvd_mul_iff_right {a b c : ℕ} (hc : 0 < c) : a * c ∣ b * c ↔ a ∣ b :=
-  exists_congr fun d => by rw [mul_right_comm, mul_left_inj' hc.ne']
+  exists_congr fun d => by rw [Nat.mul_right_comm, mul_left_inj' hc.ne']
 #align nat.mul_dvd_mul_iff_right Nat.mul_dvd_mul_iff_right
 
 @[simp]
chore: banish Type _ and Sort _ (#6499)

We remove all possible occurences of Type _ and Sort _ in favor of Type* and Sort*.

This has nice performance benefits.

Diff
@@ -460,11 +460,11 @@ protected def strongRec' {p : ℕ → Sort u} (H : ∀ n, (∀ m, m < n → p m)
 
 /-- Recursion principle based on `<` applied to some natural number. -/
 @[elab_as_elim]
-def strongRecOn' {P : ℕ → Sort _} (n : ℕ) (h : ∀ n, (∀ m, m < n → P m) → P n) : P n :=
+def strongRecOn' {P : ℕ → Sort*} (n : ℕ) (h : ∀ n, (∀ m, m < n → P m) → P n) : P n :=
   Nat.strongRec' h n
 #align nat.strong_rec_on' Nat.strongRecOn'
 
-theorem strongRecOn'_beta {P : ℕ → Sort _} {h} {n : ℕ} :
+theorem strongRecOn'_beta {P : ℕ → Sort*} {h} {n : ℕ} :
     (strongRecOn' n h : P n) = h n fun m _ => (strongRecOn' m h : P m) := by
   simp only [strongRecOn']
   rw [Nat.strongRec']
@@ -487,20 +487,20 @@ theorem le_induction {m} {P : ∀ (n : Nat) (_ : m ≤ n), Prop} (base : P m le_
 Also works for functions to `Sort*`. For a version assuming only the assumption for `k < n`, see
 `decreasing_induction'`. -/
 @[elab_as_elim]
-def decreasingInduction {P : ℕ → Sort _} (h : ∀ n, P (n + 1) → P n) {m n : ℕ} (mn : m ≤ n)
+def decreasingInduction {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P n) {m n : ℕ} (mn : m ≤ n)
     (hP : P n) : P m :=
   leRecOn mn (fun {k} ih hsk => ih <| h k hsk) (fun h => h) hP
 #align nat.decreasing_induction Nat.decreasingInduction
 
 @[simp]
-theorem decreasingInduction_self {P : ℕ → Sort _} (h : ∀ n, P (n + 1) → P n) {n : ℕ} (nn : n ≤ n)
+theorem decreasingInduction_self {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P n) {n : ℕ} (nn : n ≤ n)
     (hP : P n) :
     (decreasingInduction h nn hP : P n) = hP := by
   dsimp only [decreasingInduction]
   rw [leRecOn_self]
 #align nat.decreasing_induction_self Nat.decreasingInduction_self
 
-theorem decreasingInduction_succ {P : ℕ → Sort _} (h : ∀ n, P (n + 1) → P n) {m n : ℕ} (mn : m ≤ n)
+theorem decreasingInduction_succ {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P n) {m n : ℕ} (mn : m ≤ n)
     (msn : m ≤ n + 1) (hP : P (n + 1)) :
     (decreasingInduction h msn hP : P m) = decreasingInduction h mn (h n hP) := by
   dsimp only [decreasingInduction]
@@ -508,13 +508,13 @@ theorem decreasingInduction_succ {P : ℕ → Sort _} (h : ∀ n, P (n + 1) →
 #align nat.decreasing_induction_succ Nat.decreasingInduction_succ
 
 @[simp]
-theorem decreasingInduction_succ' {P : ℕ → Sort _} (h : ∀ n, P (n + 1) → P n) {m : ℕ}
+theorem decreasingInduction_succ' {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P n) {m : ℕ}
     (msm : m ≤ m + 1) (hP : P (m + 1)) : (decreasingInduction h msm hP : P m) = h m hP := by
   dsimp only [decreasingInduction]
   rw [leRecOn_succ']
 #align nat.decreasing_induction_succ' Nat.decreasingInduction_succ'
 
-theorem decreasingInduction_trans {P : ℕ → Sort _} (h : ∀ n, P (n + 1) → P n) {m n k : ℕ}
+theorem decreasingInduction_trans {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P n) {m n k : ℕ}
     (mn : m ≤ n) (nk : n ≤ k) (hP : P k) :
     (decreasingInduction h (le_trans mn nk) hP : P m) =
     decreasingInduction h mn (decreasingInduction h nk hP) := by
@@ -523,7 +523,7 @@ theorem decreasingInduction_trans {P : ℕ → Sort _} (h : ∀ n, P (n + 1) →
   · rw [decreasingInduction_succ h (le_trans mn nk), ih, decreasingInduction_succ]
 #align nat.decreasing_induction_trans Nat.decreasingInduction_trans
 
-theorem decreasingInduction_succ_left {P : ℕ → Sort _} (h : ∀ n, P (n + 1) → P n) {m n : ℕ}
+theorem decreasingInduction_succ_left {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P n) {m n : ℕ}
     (smn : m + 1 ≤ n) (mn : m ≤ n) (hP : P n) :
     (decreasingInduction h mn hP : P m) = h m (decreasingInduction h smn hP) := by
   rw [Subsingleton.elim mn (le_trans (le_succ m) smn), decreasingInduction_trans,
@@ -535,7 +535,7 @@ theorem decreasingInduction_succ_left {P : ℕ → Sort _} (h : ∀ n, P (n + 1)
 strictly below `(a,b)` to `P a b`, then we have `P n m` for all `n m : ℕ`.
 Note that for non-`Prop` output it is preferable to use the equation compiler directly if possible,
 since this produces equation lemmas. -/
-def strongSubRecursion {P : ℕ → ℕ → Sort _} (H : ∀ a b, (∀ x y, x < a → y < b → P x y) → P a b) :
+def strongSubRecursion {P : ℕ → ℕ → Sort*} (H : ∀ a b, (∀ x y, x < a → y < b → P x y) → P a b) :
     ∀ n m : ℕ, P n m
   | n, m => H n m fun x y _ _ => strongSubRecursion H x y
 #align nat.strong_sub_recursion Nat.strongSubRecursion
@@ -550,7 +550,7 @@ and for any `x y : ℕ` we can extend `P` from `(x,y+1)` and `(x+1,y)` to `(x+1,
 then we have `P n m` for all `n m : ℕ`.
 Note that for non-`Prop` output it is preferable to use the equation compiler directly if possible,
 since this produces equation lemmas. -/
-def pincerRecursion {P : ℕ → ℕ → Sort _} (Ha0 : ∀ a : ℕ, P a 0) (H0b : ∀ b : ℕ, P 0 b)
+def pincerRecursion {P : ℕ → ℕ → Sort*} (Ha0 : ∀ a : ℕ, P a 0) (H0b : ∀ b : ℕ, P 0 b)
     (H : ∀ x y : ℕ, P x y.succ → P x.succ y → P x.succ y.succ) : ∀ n m : ℕ, P n m
   | a, 0 => Ha0 a
   | 0, b => H0b b
@@ -566,7 +566,7 @@ attribute [elab_as_elim] pincerRecursion
 /-- Recursion starting at a non-zero number: given a map `C k → C (k+1)` for each `k ≥ n`,
 there is a map from `C n` to each `C m`, `n ≤ m`. -/
 @[elab_as_elim]
-def leRecOn' {C : ℕ → Sort _} {n : ℕ} :
+def leRecOn' {C : ℕ → Sort*} {n : ℕ} :
     ∀ {m : ℕ}, n ≤ m → (∀ ⦃k⦄, n ≤ k → C k → C (k + 1)) → C n → C m
   | 0, H, _, x => Eq.recOn (Nat.eq_zero_of_le_zero H) x
   | m + 1, H, next, x =>
@@ -577,7 +577,7 @@ def leRecOn' {C : ℕ → Sort _} {n : ℕ} :
 /-- Decreasing induction: if `P (k+1)` implies `P k` for all `m ≤ k < n`, then `P n` implies `P m`.
 Also works for functions to `Sort*`. Weakens the assumptions of `decreasing_induction`. -/
 @[elab_as_elim]
-def decreasingInduction' {P : ℕ → Sort _} {m n : ℕ} (h : ∀ k < n, m ≤ k → P (k + 1) → P k)
+def decreasingInduction' {P : ℕ → Sort*} {m n : ℕ} (h : ∀ k < n, m ≤ k → P (k + 1) → P k)
     (mn : m ≤ n) (hP : P n) :
     P m := by
   revert h hP
chore: bump to nightly-2023-07-15 (#5992)

Various adaptations to changes when Fin API was moved to Std. One notable change is that many lemmas are now stated in terms of i ≠ 0 (for i : Fin n) rather then i.1 ≠ 0, and as a consequence many Fin.vne_of_ne applications have been added or removed, mostly removed.

Co-authored-by: Scott Morrison <scott.morrison@gmail.com> Co-authored-by: Wojciech Nawrocki <wjnawrocki@protonmail.com> Co-authored-by: Eric Wieser <wieser.eric@gmail.com>

Diff
@@ -234,8 +234,6 @@ theorem of_le_succ {n m : ℕ} (H : n ≤ m.succ) : n ≤ m ∨ n = m.succ :=
   H.lt_or_eq_dec.imp le_of_lt_succ id
 #align nat.of_le_succ Nat.of_le_succ
 
-theorem succ_lt_succ_iff {m n : ℕ} : succ m < succ n ↔ m < n :=
-  ⟨lt_of_succ_lt_succ, succ_lt_succ⟩
 #align nat.succ_lt_succ_iff Nat.succ_lt_succ_iff
 
 theorem div_le_iff_le_mul_add_pred {m n k : ℕ} (n0 : 0 < n) : m / n ≤ k ↔ m ≤ n * k + (n - 1) := by
chore: script to replace headers with #align_import statements (#5979)

Open in Gitpod

Co-authored-by: Eric Wieser <wieser.eric@gmail.com> Co-authored-by: Scott Morrison <scott.morrison@gmail.com>

Diff
@@ -2,16 +2,13 @@
 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: Floris van Doorn, Leonardo de Moura, Jeremy Avigad, Mario Carneiro
-
-! This file was ported from Lean 3 source module data.nat.basic
-! leanprover-community/mathlib commit bd835ef554f37ef9b804f0903089211f89cb370b
-! Please do not edit these lines, except to modify the commit id
-! if you have ported upstream changes.
 -/
 import Mathlib.Order.Basic
 import Mathlib.Algebra.GroupWithZero.Basic
 import Mathlib.Algebra.Ring.Defs
 
+#align_import data.nat.basic from "leanprover-community/mathlib"@"bd835ef554f37ef9b804f0903089211f89cb370b"
+
 /-!
 # Basic operations on the natural numbers
 
chore: add space after exacts (#4945)

Too often tempted to change these during other PRs, so doing a mass edit here.

Co-authored-by: Scott Morrison <scott.morrison@anu.edu.au>

Diff
@@ -140,7 +140,7 @@ theorem and_forall_succ {p : ℕ → Prop} : (p 0 ∧ ∀ n, p (n + 1)) ↔ ∀
 theorem or_exists_succ {p : ℕ → Prop} : (p 0 ∨ ∃ n, p (n + 1)) ↔ ∃ n, p n :=
   ⟨fun h => h.elim (fun h0 => ⟨0, h0⟩) fun ⟨n, hn⟩ => ⟨n + 1, hn⟩, by
     rintro ⟨_ | n, hn⟩
-    exacts[Or.inl hn, Or.inr ⟨n, hn⟩]⟩
+    exacts [Or.inl hn, Or.inr ⟨n, hn⟩]⟩
 #align nat.or_exists_succ Nat.or_exists_succ
 
 /-! ### `succ` -/
@@ -862,7 +862,7 @@ theorem find_comp_succ (h₁ : ∃ n, p n) (h₂ : ∃ n, p (n + 1)) (h0 : ¬p 0
     Nat.find h₁ = Nat.find h₂ + 1 := by
   refine' (find_eq_iff _).2 ⟨Nat.find_spec h₂, fun n hn => _⟩
   cases' n with n
-  exacts[h0, @Nat.find_min (fun n => p (n + 1)) _ h₂ _ (succ_lt_succ_iff.1 hn)]
+  exacts [h0, @Nat.find_min (fun n => p (n + 1)) _ h₂ _ (succ_lt_succ_iff.1 hn)]
 #align nat.find_comp_succ Nat.find_comp_succ
 
 end Find
feat: add Mathlib.Tactic.Common, and import (#4056)

This makes a mathlib4 version of mathlib3's tactic.basic, now called Mathlib.Tactic.Common, which imports all tactics which do not have significant theory requirements, and then is imported all across the base of the hierarchy.

This ensures that all common tactics are available nearly everywhere in the library, rather than having to be imported one-by-one as you need them.

Co-authored-by: Scott Morrison <scott.morrison@gmail.com>

Diff
@@ -11,9 +11,6 @@ Authors: Floris van Doorn, Leonardo de Moura, Jeremy Avigad, Mario Carneiro
 import Mathlib.Order.Basic
 import Mathlib.Algebra.GroupWithZero.Basic
 import Mathlib.Algebra.Ring.Defs
-import Mathlib.Tactic.Convert
-import Mathlib.Tactic.PushNeg
-import Mathlib.Tactic.Use
 
 /-!
 # Basic operations on the natural numbers
fix: remove lambda abstraction of Nat.rec_zero and Nat.rec_add_one (#3839)
theorem rec_zero {C : ℕ → Sort u} (h0 : C 0) (h : ∀ n, C n → C (n + 1)) :
    (Nat.rec h0 h : ∀ n, C n) 0 = h0 :=
  rfl

The above theorem is elaborated as follow:

theorem rec_zero {C : ℕ → Sort u} (h0 : C 0) (h : ∀ n, C n → C (n + 1)) :
    (fun n => Nat.rec h0 h n) 0 = h0 :=
  rfl

This form of the theorem isn't generic. This PR fixes this problem.

Co-authored-by: Pol_tta <52843868+Komyyy@users.noreply.github.com>

Diff
@@ -373,16 +373,18 @@ This section is here due to dependencies -- the lemmas here require some of the
 proved above, and some of the results in later sections depend on the definitions in this section.
 -/
 
+-- Porting note: The type ascriptions of these two theorems need to be changed,
+-- as mathport wrote a lambda that wasn't there in mathlib3, that prevents `simp` applying them.
 
 @[simp]
 theorem rec_zero {C : ℕ → Sort u} (h0 : C 0) (h : ∀ n, C n → C (n + 1)) :
-    (Nat.rec h0 h : ∀ n, C n) 0 = h0 :=
+    Nat.rec h0 h 0 = h0 :=
   rfl
 #align nat.rec_zero Nat.rec_zero
 
 @[simp]
 theorem rec_add_one {C : ℕ → Sort u} (h0 : C 0) (h : ∀ n, C n → C (n + 1)) (n : ℕ) :
-    (Nat.rec h0 h : ∀ n, C n) (n + 1) = h n ((Nat.rec h0 h : ∀ n, C n) n) :=
+    Nat.rec h0 h (n + 1) = h n (Nat.rec h0 h n) :=
   rfl
 #align nat.rec_add_one Nat.rec_add_one
 
chore: fix #align lines (#3640)

This PR fixes two things:

  • Most align statements for definitions and theorems and instances that are separated by two newlines from the relevant declaration (s/\n\n#align/\n#align). This is often seen in the mathport output after ending calc blocks.
  • All remaining more-than-one-line #align statements. (This was needed for a script I wrote for #3630.)
Diff
@@ -201,7 +201,6 @@ theorem max_succ_succ {m n : ℕ} : max (succ m) (succ n) = succ (max m n) := by
   · rw [not_le] at h1
     have h2 := le_of_lt h1
     rw [max_eq_left h2, max_eq_left (succ_le_succ h2)]
-
 #align nat.max_succ_succ Nat.max_succ_succ
 
 theorem not_succ_lt_self {n : ℕ} : ¬succ n < n :=
@@ -595,7 +594,6 @@ def decreasingInduction' {P : ℕ → Sort _} {m n : ℕ} (h : ∀ k < n, m ≤
     · exact h n (lt_succ_self n) mn hP
   · intro _ hP
     exact hP
-
 #align nat.decreasing_induction' Nat.decreasingInduction'
 
 /-! ### `div` -/
@@ -823,10 +821,8 @@ theorem find_eq_iff (h : ∃ n : ℕ, p n) : Nat.find h = m ↔ p m ∧ ∀ n <
   constructor
   · rintro rfl
     exact ⟨Nat.find_spec h, fun _ => Nat.find_min h⟩
-
   · rintro ⟨hm, hlt⟩
     exact le_antisymm (Nat.find_min' h hm) (not_lt.1 <| imp_not_comm.1 (hlt _) <| Nat.find_spec h)
-
 #align nat.find_eq_iff Nat.find_eq_iff
 
 @[simp]
@@ -927,7 +923,6 @@ instance decidableBallLT :
           match k, e, h' with
           | _, rfl, _ => p
   · exact isFalse (mt (fun hn => hn _ _) p)
-
 #align nat.decidable_ball_lt Nat.decidableBallLT
 
 instance decidableForallFin {n : ℕ} (P : Fin n → Prop) [DecidablePred P] :
feat: forward-port leanprover-community/mathlib#18359 (#2106)

Also fixes a lemma statement to use % notation like it did in Lean3

Co-authored-by: Jon Eugster <eugster.jon@gmail.com>

Diff
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Floris van Doorn, Leonardo de Moura, Jeremy Avigad, Mario Carneiro
 
 ! This file was ported from Lean 3 source module data.nat.basic
-! leanprover-community/mathlib commit 2609ad04e2b77aceb2200e273daf11cc65856fda
+! leanprover-community/mathlib commit bd835ef554f37ef9b804f0903089211f89cb370b
 ! Please do not edit these lines, except to modify the commit id
 ! if you have ported upstream changes.
 -/
@@ -716,6 +716,7 @@ theorem div_add_mod' (m k : ℕ) : m / k * k + m % k = m := by
   exact div_add_mod _ _
 #align nat.div_add_mod' Nat.div_add_mod'
 
+/-- See also `Nat.divModEquiv` for a similar statement as an `Equiv`. -/
 protected theorem div_mod_unique {n k m d : ℕ} (h : 0 < k) :
     n / k = d ∧ n % k = m ↔ m + k * d = n ∧ m < k :=
   ⟨fun ⟨e₁, e₂⟩ => e₁ ▸ e₂ ▸ ⟨mod_add_div _ _, mod_lt _ h⟩, fun ⟨h₁, h₂⟩ =>
chore: update SHA for #1662 (#2542)

#1662 forward-ported the changes to this file, but forgot to update the SHA.

Diff
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Floris van Doorn, Leonardo de Moura, Jeremy Avigad, Mario Carneiro
 
 ! This file was ported from Lean 3 source module data.nat.basic
-! leanprover-community/mathlib commit 2f3994e1b117b1e1da49bcfb67334f33460c3ce4
+! leanprover-community/mathlib commit 2609ad04e2b77aceb2200e273daf11cc65856fda
 ! Please do not edit these lines, except to modify the commit id
 ! if you have ported upstream changes.
 -/
Feat: add Nat.exists_eq_add_of_le' (#1662)

Also golf 2 proofs. This is a forward-port of leanprover-community/mathlib#18203.

Diff
@@ -273,7 +273,6 @@ theorem exists_lt_succ {P : ℕ → Prop} {n : ℕ} : (∃ m < n + 1, P m) ↔ (
 
 /-! ### `add` -/
 
-
 -- Sometimes a bare `Nat.add` or similar appears as a consequence of unfolding
 -- during pattern matching. These lemmas package them back up as typeclass
 -- mediated operations.
@@ -287,25 +286,20 @@ theorem mul_def {a b : ℕ} : Nat.mul a b = a * b :=
   rfl
 #align nat.mul_def Nat.mul_def
 
-theorem exists_eq_add_of_le : ∀ {m n : ℕ}, m ≤ n → ∃ k : ℕ, n = m + k
-  | 0, 0, _ => ⟨0, by simp⟩
-  | 0, n + 1, h => ⟨n + 1, by simp⟩
-  | m + 1, n + 1, h =>
-    let ⟨k, hk⟩ := exists_eq_add_of_le (Nat.le_of_succ_le_succ h)
-    ⟨k, by simp [hk, add_comm, add_left_comm]; rfl⟩
+theorem exists_eq_add_of_le (h : m ≤ n) : ∃ k : ℕ, n = m + k :=
+  ⟨n - m, (add_sub_of_le h).symm⟩
 #align nat.exists_eq_add_of_le Nat.exists_eq_add_of_le
 
-theorem exists_eq_add_of_lt : ∀ {m n : ℕ}, m < n → ∃ k : ℕ, n = m + k + 1
-  | 0, 0, h => False.elim <| lt_irrefl _ h
-  | 0, n + 1, _ => ⟨n, by simp⟩
-  | m + 1, n + 1, h =>
-    let ⟨k, hk⟩ := exists_eq_add_of_le (Nat.le_of_succ_le_succ h)
-    ⟨k, by simp [hk]⟩
+theorem exists_eq_add_of_le' (h : m ≤ n) : ∃ k : ℕ, n = k + m :=
+  ⟨n - m, (Nat.sub_add_cancel h).symm⟩
+#align nat.exists_eq_add_of_le' Nat.exists_eq_add_of_le'
+
+theorem exists_eq_add_of_lt (h : m < n) : ∃ k : ℕ, n = m + k + 1 :=
+  ⟨n - (m + 1), by rw [add_right_comm, add_sub_of_le h]⟩
 #align nat.exists_eq_add_of_lt Nat.exists_eq_add_of_lt
 
 /-! ### `pred` -/
 
-
 @[simp]
 theorem add_succ_sub_one (n m : ℕ) : n + succ m - 1 = n + m := by rw [add_succ, succ_sub_one]
 #align nat.add_succ_sub_one Nat.add_succ_sub_one
chore: fix most phantom #aligns (#1794)
Diff
@@ -151,7 +151,7 @@ theorem or_exists_succ {p : ℕ → Prop} : (p 0 ∨ ∃ n, p (n + 1)) ↔ ∃ n
 
 theorem _root_.LT.lt.nat_succ_le {n m : ℕ} (h : n < m) : succ n ≤ m :=
   succ_le_of_lt h
-#align nat._root_.has_lt.lt.nat_succ_le LT.lt.nat_succ_le
+#align has_lt.lt.nat_succ_le LT.lt.nat_succ_le
 
 -- Moved to Std
 #align nat.succ_eq_one_add Nat.succ_eq_one_add
chore: typo in Data.Nat.Basic (#1781)

The line (line 559) attribute [elab_as_elim] strongSubRecursion has been copy-pasted a couple of line below (line 577) but someone forgot to change the name of the result.

Diff
@@ -574,7 +574,7 @@ termination_by pincerRecursion Ha0 Hab H n m => n + m
 -- Porting note:
 -- we can't put this on the definition itself because of
 -- https://github.com/leanprover/lean4/issues/1900
-attribute [elab_as_elim] strongSubRecursion
+attribute [elab_as_elim] pincerRecursion
 
 /-- Recursion starting at a non-zero number: given a map `C k → C (k+1)` for each `k ≥ n`,
 there is a map from `C n` to each `C m`, `n ≤ m`. -/
chore: adjust Nat.le_induction for compatibility with induction tactic (#1611)

See Zulip.

Diff
@@ -483,14 +483,17 @@ theorem strongRecOn'_beta {P : ℕ → Sort _} {h} {n : ℕ} :
   rw [Nat.strongRec']
 #align nat.strong_rec_on_beta' Nat.strongRecOn'_beta
 
-/-- Induction principle starting at a non-zero number. For maps to a `Sort*` see `le_rec_on`. -/
+/-- Induction principle starting at a non-zero number. For maps to a `Sort*` see `le_rec_on`.
+To use in an induction proof, the syntax is `induction n, hn using Nat.le_induction` (or the same
+for `induction'`). -/
 @[elab_as_elim]
-theorem le_induction {P : Nat → Prop} {m} (h0 : P m) (h1 : ∀ n, m ≤ n → P n → P (n + 1)) :
-    ∀ n, m ≤ n → P n := by
+theorem le_induction {m} {P : ∀ (n : Nat) (_ : m ≤ n), Prop} (base : P m le_rfl)
+    (succ : ∀ (n : Nat) (hn : m ≤ n), P n hn → P (n + 1) (hn.trans <| Nat.le_succ _)) :
+    ∀ (n : Nat) (hn : m ≤ n), P n hn := by
   apply Nat.le.rec
-  · exact h0
+  · exact base
   · intros n hn
-    apply h1 n hn
+    apply succ n hn
 #align nat.le_induction Nat.le_induction
 
 /-- Decreasing induction: if `P (k+1)` implies `P k`, then `P n` implies `P m` for all `m ≤ n`.
chore: fix more casing errors per naming scheme (#1232)

I've avoided anything under Tactic or test.

In correcting the names, I found Option.isNone_iff_eq_none duplicated between Std and Mathlib, so the Mathlib one has been removed.

Co-authored-by: Reid Barton <rwbarton@gmail.com>

Diff
@@ -28,7 +28,7 @@ This file contains:
   * `strong_rec'`: recursion based on strong inequalities
 - decidability instances on predicates about the natural numbers
 
-Many theorems that used to live in this file have been moved to `data.nat.order`,
+Many theorems that used to live in this file have been moved to `Data.Nat.Order`,
 so that this file requires fewer imports.
 For each section here there is a corresponding section in that file with additional results.
 It may be possible to move some of these results here, by tweaking their proofs.
@@ -219,7 +219,7 @@ theorem succ_le_iff {m n : ℕ} : succ m ≤ n ↔ m < n :=
 theorem lt_iff_add_one_le {m n : ℕ} : m < n ↔ m + 1 ≤ n := by rw [succ_le_iff]
 #align nat.lt_iff_add_one_le Nat.lt_iff_add_one_le
 
--- Just a restatement of `nat.lt_succ_iff` using `+1`.
+-- Just a restatement of `Nat.lt_succ_iff` using `+1`.
 theorem lt_add_one_iff {a b : ℕ} : a < b + 1 ↔ a ≤ b :=
   lt_succ_iff
 #align nat.lt_add_one_iff Nat.lt_add_one_iff
@@ -274,7 +274,7 @@ theorem exists_lt_succ {P : ℕ → Prop} {n : ℕ} : (∃ m < n + 1, P m) ↔ (
 /-! ### `add` -/
 
 
--- Sometimes a bare `nat.add` or similar appears as a consequence of unfolding
+-- Sometimes a bare `Nat.add` or similar appears as a consequence of unfolding
 -- during pattern matching. These lemmas package them back up as typeclass
 -- mediated operations.
 @[simp]
@@ -605,7 +605,7 @@ def decreasingInduction' {P : ℕ → Sort _} {m n : ℕ} (h : ∀ k < n, m ≤
 
 attribute [simp] Nat.div_self
 
-/-- A version of `nat.div_lt_self` using successors, rather than additional hypotheses. -/
+/-- A version of `Nat.div_lt_self` using successors, rather than additional hypotheses. -/
 theorem div_lt_self' (n b : ℕ) : (n + 1) / (b + 2) < n + 1 :=
   Nat.div_lt_self (Nat.succ_pos n) (Nat.succ_lt_succ (Nat.succ_pos _))
 #align nat.div_lt_self' Nat.div_lt_self'
@@ -914,11 +914,11 @@ end FindGreatest
 
 /-! ### decidability of predicates -/
 
-instance decidableBallLt :
+instance decidableBallLT :
     ∀ (n : Nat) (P : ∀ k < n, Prop) [∀ n h, Decidable (P n h)], Decidable (∀ n h, P n h)
 | 0, P, _ => isTrue fun n h => by cases h
 | (n+1), P, H => by
-  cases' decidableBallLt n fun k h => P k (lt_succ_of_lt h) with h h
+  cases' decidableBallLT n fun k h => P k (lt_succ_of_lt h) with h h
   · refine' isFalse (mt _ h)
     intro hn k h
     apply hn
@@ -930,7 +930,7 @@ instance decidableBallLt :
           | _, rfl, _ => p
   · exact isFalse (mt (fun hn => hn _ _) p)
 
-#align nat.decidable_ball_lt Nat.decidableBallLt
+#align nat.decidable_ball_lt Nat.decidableBallLT
 
 instance decidableForallFin {n : ℕ} (P : Fin n → Prop) [DecidablePred P] :
     Decidable (∀ i, P i) :=
@@ -943,13 +943,13 @@ instance decidableBallLe (n : ℕ) (P : ∀ k ≤ n, Prop) [∀ n h, Decidable (
     ⟨fun a k h => a k (lt_succ_of_le h), fun a k _ => a k _⟩
 #align nat.decidable_ball_le Nat.decidableBallLe
 
-instance decidableExistsLt {P : ℕ → Prop} [h : DecidablePred P] :
+instance decidableExistsLT {P : ℕ → Prop} [h : DecidablePred P] :
     DecidablePred fun n => ∃ m : ℕ, m < n ∧ P m
   | 0 => isFalse (by simp)
   | n + 1 =>
-    @decidable_of_decidable_of_iff _ _ (@instDecidableOr _ _ (decidableExistsLt n) (h n))
+    @decidable_of_decidable_of_iff _ _ (@instDecidableOr _ _ (decidableExistsLT n) (h n))
       (by simp only [lt_succ_iff_lt_or_eq, or_and_right, exists_or, exists_eq_left]; apply Iff.refl)
-#align nat.decidable_exists_lt Nat.decidableExistsLt
+#align nat.decidable_exists_lt Nat.decidableExistsLT
 
 instance decidableExistsLe {P : ℕ → Prop} [DecidablePred P] :
     DecidablePred fun n => ∃ m : ℕ, m ≤ n ∧ P m :=
refactor: use Is*CancelMulZero (#1137)

This is a Lean 4 version of leanprover-community/mathlib#17963

Diff
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Floris van Doorn, Leonardo de Moura, Jeremy Avigad, Mario Carneiro
 
 ! This file was ported from Lean 3 source module data.nat.basic
-! leanprover-community/mathlib commit 70d50ecfd4900dd6d328da39ab7ebd516abe4025
+! leanprover-community/mathlib commit 2f3994e1b117b1e1da49bcfb67334f33460c3ce4
 ! Please do not edit these lines, except to modify the commit id
 ! if you have ported upstream changes.
 -/
@@ -116,9 +116,7 @@ protected theorem nsmul_eq_mul (m n : ℕ) : m • n = m * n :=
 instance cancelCommMonoidWithZero : CancelCommMonoidWithZero ℕ :=
   { (inferInstance : CommMonoidWithZero ℕ) with
     mul_left_cancel_of_ne_zero :=
-      fun {_ _ _} h1 h2 => Nat.eq_of_mul_eq_mul_left (Nat.pos_of_ne_zero h1) h2,
-    mul_right_cancel_of_ne_zero :=
-      fun {_ _ _} h1 h2 => Nat.eq_of_mul_eq_mul_right (Nat.pos_of_ne_zero h1) h2 }
+      fun h1 h2 => Nat.eq_of_mul_eq_mul_left (Nat.pos_of_ne_zero h1) h2 }
 #align nat.cancel_comm_monoid_with_zero Nat.cancelCommMonoidWithZero
 
 attribute [simp]
chore: update lean4/std4 (#1096)
Diff
@@ -227,7 +227,7 @@ theorem lt_add_one_iff {a b : ℕ} : a < b + 1 ↔ a ≤ b :=
 #align nat.lt_add_one_iff Nat.lt_add_one_iff
 
 -- A flipped version of `lt_add_one_iff`.
-theorem lt_one_add_iff {a b : ℕ} : a < 1 + b ↔ a ≤ b := by simp only [add_comm, lt_succ_iff]; rfl
+theorem lt_one_add_iff {a b : ℕ} : a < 1 + b ↔ a ≤ b := by simp only [add_comm, lt_succ_iff]
 #align nat.lt_one_add_iff Nat.lt_one_add_iff
 
 -- This is true reflexively, by the definition of `≤` on ℕ,
@@ -236,7 +236,7 @@ theorem add_one_le_iff {a b : ℕ} : a + 1 ≤ b ↔ a < b :=
   Iff.refl _
 #align nat.add_one_le_iff Nat.add_one_le_iff
 
-theorem one_add_le_iff {a b : ℕ} : 1 + a ≤ b ↔ a < b := by simp only [add_comm, add_one_le_iff]; rfl
+theorem one_add_le_iff {a b : ℕ} : 1 + a ≤ b ↔ a < b := by simp only [add_comm, add_one_le_iff]
 #align nat.one_add_le_iff Nat.one_add_le_iff
 
 theorem of_le_succ {n m : ℕ} (H : n ≤ m.succ) : n ≤ m ∨ n = m.succ :=
@@ -264,7 +264,7 @@ theorem two_lt_of_ne : ∀ {n}, n ≠ 0 → n ≠ 1 → n ≠ 2 → 2 < n
 #align nat.two_lt_of_ne Nat.two_lt_of_ne
 
 theorem forall_lt_succ {P : ℕ → Prop} {n : ℕ} : (∀ m < n + 1, P m) ↔ (∀ m < n, P m) ∧ P n := by
-  simp only [lt_succ_iff, Decidable.le_iff_eq_or_lt, forall_eq_or_imp, and_comm]; rfl
+  simp only [lt_succ_iff, Decidable.le_iff_eq_or_lt, forall_eq_or_imp, and_comm]
 #align nat.forall_lt_succ Nat.forall_lt_succ
 
 theorem exists_lt_succ {P : ℕ → Prop} {n : ℕ} : (∃ m < n + 1, P m) ↔ (∃ m < n, P m) ∨ P n := by
@@ -681,14 +681,7 @@ protected theorem mul_div_cancel_left' {a b : ℕ} (Hd : a ∣ b) : a * (b / a)
   rw [mul_comm, Nat.div_mul_cancel Hd]
 #align nat.mul_div_cancel_left' Nat.mul_div_cancel_left'
 
---TODO: Update `nat.mul_div_mul` in the core?
-/-- Alias of `nat.mul_div_mul` -/
-protected theorem mul_div_mul_left (a b : ℕ) {c : ℕ} (hc : 0 < c) : c * a / (c * b) = a / b :=
-  Nat.mul_div_mul a b hc
 #align nat.mul_div_mul_left Nat.mul_div_mul_left
-
-protected theorem mul_div_mul_right (a b : ℕ) {c : ℕ} (hc : 0 < c) : a * c / (b * c) = a / b := by
-  rw [mul_comm, mul_comm b, a.mul_div_mul_left b hc]
 #align nat.mul_div_mul_right Nat.mul_div_mul_right
 
 theorem lt_div_mul_add {a b : ℕ} (hb : 0 < b) : a < a / b * b + b := by
@@ -848,17 +841,17 @@ theorem find_lt_iff (h : ∃ n : ℕ, p n) (n : ℕ) : Nat.find h < n ↔ ∃ m
 
 @[simp]
 theorem find_le_iff (h : ∃ n : ℕ, p n) (n : ℕ) : Nat.find h ≤ n ↔ ∃ m ≤ n, p m := by
-  simp only [exists_prop, ← lt_succ_iff, find_lt_iff]; rfl
+  simp only [exists_prop, ← lt_succ_iff, find_lt_iff]
 #align nat.find_le_iff Nat.find_le_iff
 
 @[simp]
 theorem le_find_iff (h : ∃ n : ℕ, p n) (n : ℕ) : n ≤ Nat.find h ↔ ∀ m < n, ¬p m := by
-  simp_rw [← not_lt, find_lt_iff, not_exists, not_and]; rfl
+  simp_rw [← not_lt, find_lt_iff, not_exists, not_and]
 #align nat.le_find_iff Nat.le_find_iff
 
 @[simp]
 theorem lt_find_iff (h : ∃ n : ℕ, p n) (n : ℕ) : n < Nat.find h ↔ ∀ m ≤ n, ¬p m := by
-  simp only [← succ_le_iff, le_find_iff, succ_le_succ_iff]; rfl
+  simp only [← succ_le_iff, le_find_iff, succ_le_succ_iff]
 #align nat.lt_find_iff Nat.lt_find_iff
 
 @[simp]
chore: add source headers to ported theory files (#1094)

The script used to do this is included. The yaml file was obtained from https://raw.githubusercontent.com/wiki/leanprover-community/mathlib/mathlib4-port-status.md

Diff
@@ -2,6 +2,11 @@
 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: Floris van Doorn, Leonardo de Moura, Jeremy Avigad, Mario Carneiro
+
+! This file was ported from Lean 3 source module data.nat.basic
+! leanprover-community/mathlib commit 70d50ecfd4900dd6d328da39ab7ebd516abe4025
+! Please do not edit these lines, except to modify the commit id
+! if you have ported upstream changes.
 -/
 import Mathlib.Order.Basic
 import Mathlib.Algebra.GroupWithZero.Basic

Dependencies 24

25 files ported (100.0%)
10260 lines ported (100.0%)

All dependencies are ported!