lean4-htt/src/Init/Data/Int/DivMod/Lemmas.lean
Kim Morrison 8d9d23b5bb
feat: (approximate) inverses of dyadic rationals (#10194)
This PR adds the inverse of a dyadic rational, at a given precision, and
characterising lemmas. Also cleans up various parts of the `Int.DivMod`
and `Rat` APIs, and proves some characterising lemmas about
`Rat.toDyadic`.

---------

Co-authored-by: Rob23oba <152706811+Rob23oba@users.noreply.github.com>
2025-09-02 03:43:53 +00:00

3082 lines
124 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/-
Copyright (c) 2016 Jeremy Avigad. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Jeremy Avigad, Mario Carneiro, Kim Morrison, Markus Himmel
-/
module
prelude
public import Init.Data.Int.DivMod.Bootstrap
public import Init.Data.Nat.Lemmas
public import Init.Data.Nat.Div.Lemmas
public import Init.Data.Int.Order
public import Init.Data.Int.Lemmas
public import Init.Data.Nat.Dvd
public import Init.RCases
public section
/-!
# Further lemmas about integer division, now that `omega` is available.
-/
open Nat (succ)
namespace Int
@[simp high] theorem natCast_eq_zero {n : Nat} : (n : Int) = 0 ↔ n = 0 := by omega
instance {n : Nat} [NeZero n] : NeZero (n : Int) := ⟨mt Int.natCast_eq_zero.mp (NeZero.ne _)⟩
instance {n : Nat} [NeZero n] : NeZero (no_index (OfNat.ofNat n) : Int) :=
⟨mt Int.natCast_eq_zero.mp (NeZero.ne _)⟩
protected theorem exists_add_of_le {a b : Int} (h : a ≤ b) : ∃ (c : Nat), b = a + c :=
⟨(b - a).toNat, by omega⟩
theorem toNat_emod {x y : Int} (hx : 0 ≤ x) (hy : 0 ≤ y) :
(x % y).toNat = x.toNat % y.toNat :=
match x, y, eq_ofNat_of_zero_le hx, eq_ofNat_of_zero_le hy with
| _, _, ⟨_, rfl⟩, ⟨_, rfl⟩ => rfl
/-! ### dvd -/
theorem dvd_antisymm {a b : Int} (H1 : 0 ≤ a) (H2 : 0 ≤ b) : a b → b a → a = b := by
rw [← natAbs_of_nonneg H1, ← natAbs_of_nonneg H2]
rw [ofNat_dvd, ofNat_dvd, ofNat_inj]
apply Nat.dvd_antisymm
protected theorem dvd_add : ∀ {a b c : Int}, a b → a c → a b + c
| _, _, _, ⟨d, rfl⟩, ⟨e, rfl⟩ => ⟨d + e, by rw [Int.mul_add]⟩
protected theorem dvd_sub : ∀ {a b c : Int}, a b → a c → a b - c
| _, _, _, ⟨d, rfl⟩, ⟨e, rfl⟩ => ⟨d - e, by rw [Int.mul_sub]⟩
protected theorem dvd_add_left {a b c : Int} (H : a c) : a b + c ↔ a b :=
⟨fun h => by have := Int.dvd_sub h H; rwa [Int.add_sub_cancel] at this, (Int.dvd_add · H)⟩
protected theorem dvd_add_right {a b c : Int} (H : a b) : a b + c ↔ a c := by
rw [Int.add_comm, Int.dvd_add_left H]
@[simp] protected theorem dvd_add_mul_self {a b c : Int} : a b + c * a ↔ a b := by
rw [Int.dvd_add_left (Int.dvd_mul_left c a)]
@[simp] protected theorem dvd_add_self_mul {a b c : Int} : a b + a * c ↔ a b := by
rw [Int.mul_comm, Int.dvd_add_mul_self]
@[simp] protected theorem dvd_mul_self_add {a b c : Int} : a b * a + c ↔ a c := by
rw [Int.add_comm, Int.dvd_add_mul_self]
@[simp] protected theorem dvd_self_mul_add {a b c : Int} : a a * b + c ↔ a c := by
rw [Int.mul_comm, Int.dvd_mul_self_add]
protected theorem dvd_iff_dvd_of_dvd_sub {a b c : Int} (H : a b - c) : a b ↔ a c :=
⟨fun h => Int.sub_sub_self b c ▸ Int.dvd_sub h H,
fun h => Int.sub_add_cancel b c ▸ Int.dvd_add H h⟩
protected theorem dvd_iff_dvd_of_dvd_add {a b c : Int} (H : a b + c) : a b ↔ a c := by
rw [← Int.sub_neg] at H; rw [Int.dvd_iff_dvd_of_dvd_sub H, Int.dvd_neg]
theorem le_of_dvd {a b : Int} (bpos : 0 < b) (H : a b) : a ≤ b :=
match a, b, eq_succ_of_zero_lt bpos, H with
| ofNat _, _, ⟨n, rfl⟩, H => ofNat_le.2 <| Nat.le_of_dvd n.succ_pos <| ofNat_dvd.1 H
| -[_+1], _, ⟨_, rfl⟩, _ => Int.le_trans (Int.le_of_lt <| negSucc_lt_zero _) (ofNat_zero_le _)
theorem natAbs_dvd {a b : Int} : (a.natAbs : Int) b ↔ a b :=
match natAbs_eq a with
| .inl e => by rw [← e]
| .inr e => by rw [← Int.neg_dvd, ← e]
theorem dvd_natAbs {a b : Int} : a b.natAbs ↔ a b :=
match natAbs_eq b with
| .inl e => by rw [← e]
| .inr e => by rw [← Int.dvd_neg, ← e]
theorem natAbs_dvd_self {a : Int} : (a.natAbs : Int) a := by
rw [Int.natAbs_dvd]
exact Int.dvd_refl a
theorem dvd_natAbs_self {a : Int} : a (a.natAbs : Int) := by
rw [Int.dvd_natAbs]
exact Int.dvd_refl a
theorem natAbs_eq_of_dvd_dvd (hmn : m n) (hnm : n m) : natAbs m = natAbs n :=
Nat.dvd_antisymm (natAbs_dvd_natAbs.2 hmn) (natAbs_dvd_natAbs.2 hnm)
theorem ofNat_dvd_right {n : Nat} {z : Int} : z (↑n : Int) ↔ z.natAbs n := by
rw [← natAbs_dvd_natAbs, natAbs_natCast]
@[simp] theorem negSucc_dvd {a : Nat} {b : Int} : -[a+1] b ↔ ((a + 1 : Nat) : Int) b := by
rw [← natAbs_dvd]
norm_cast
@[simp] theorem dvd_negSucc {a : Int} {b : Nat} : a -[b+1] ↔ a ((b + 1 : Nat) : Int) := by
rw [← dvd_natAbs]
norm_cast
theorem eq_one_of_dvd_one {a : Int} (H : 0 ≤ a) (H' : a 1) : a = 1 :=
match a, eq_ofNat_of_zero_le H, H' with
| _, ⟨_, rfl⟩, H' => congrArg ofNat <| Nat.eq_one_of_dvd_one <| ofNat_dvd.1 H'
theorem eq_one_of_mul_eq_one_right {a b : Int} (H : 0 ≤ a) (H' : a * b = 1) : a = 1 :=
eq_one_of_dvd_one H ⟨b, H'.symm⟩
theorem eq_one_of_mul_eq_one_left {a b : Int} (H : 0 ≤ b) (H' : a * b = 1) : b = 1 :=
eq_one_of_mul_eq_one_right (b := a) H <| by rw [Int.mul_comm, H']
instance decidableDvd : DecidableRel (α := Int) (· ·) := fun _ _ =>
decidable_of_decidable_of_iff (dvd_iff_emod_eq_zero ..).symm
protected theorem mul_dvd_mul_iff_left {a b c : Int} (h : a ≠ 0) : (a * b) (a * c) ↔ b c :=
⟨by rintro ⟨d, h'⟩; exact ⟨d, by rw [Int.mul_assoc] at h'; exact (mul_eq_mul_left_iff h).mp h'⟩,
by rintro ⟨d, rfl⟩; exact ⟨d, by simp [Int.mul_assoc]⟩⟩
protected theorem mul_dvd_mul_iff_right {a b c : Int} (h : a ≠ 0) : (b * a) (c * a) ↔ b c := by
rw [Int.mul_comm b a, Int.mul_comm c a]
exact Int.mul_dvd_mul_iff_left h
protected theorem mul_dvd_mul {a b c d : Int} : a b → c d → a * c b * d := by
simpa [← Int.natAbs_dvd_natAbs, natAbs_mul] using Nat.mul_dvd_mul
protected theorem mul_dvd_mul_left (a : Int) (h : b c) : a * b a * c :=
Int.mul_dvd_mul a.dvd_refl h
protected theorem mul_dvd_mul_right (a : Int) (h : b c) : b * a c * a :=
Int.mul_dvd_mul h a.dvd_refl
theorem dvd_of_mul_dvd_mul_left {a m n : Int} (ha : a ≠ 0) (h : a * m a * n) : m n := by
obtain ⟨b, hb⟩ := h
rw [Int.mul_assoc, Int.mul_eq_mul_left_iff ha] at hb
exact ⟨_, hb⟩
theorem dvd_of_mul_dvd_mul_right {a m n : Int} (ha : a ≠ 0) (h : m * a n * a) : m n :=
dvd_of_mul_dvd_mul_left ha (by simpa [Int.mul_comm] using h)
@[norm_cast] theorem natCast_dvd_natCast {m n : Nat} : (↑m : Int) ↑n ↔ m n where
mp := by
rintro ⟨a, h⟩
obtain rfl | hm := m.eq_zero_or_pos
· simpa using h
have ha : 0 ≤ a := Int.not_lt.1 fun ha ↦ by
simpa [← h, Int.not_lt.2 (Int.natCast_nonneg _)]
using Int.mul_neg_of_pos_of_neg (natCast_pos.2 hm) ha
match a, ha with
| (a : Nat), _ =>
norm_cast at h
exact ⟨a, h⟩
mpr := by rintro ⟨a, rfl⟩; simp [Int.dvd_mul_right]
/-! ### *div zero -/
@[simp] protected theorem zero_tdiv : ∀ b : Int, tdiv 0 b = 0
| ofNat _ => show ofNat _ = _ by simp
| -[_+1] => show -ofNat _ = _ by simp
@[simp] protected theorem tdiv_zero : ∀ a : Int, tdiv a 0 = 0
| ofNat _ => show ofNat _ = _ by simp
| -[_+1] => by simp [tdiv]
@[simp] theorem zero_fdiv (b : Int) : fdiv 0 b = 0 := by cases b <;> rfl
@[simp] protected theorem fdiv_zero : ∀ a : Int, fdiv a 0 = 0
| 0 => rfl
| succ _ => by simp [fdiv]
| -[_+1] => rfl
/-! ### preliminaries for div equivalences -/
theorem negSucc_emod_ofNat_succ_eq_zero_iff {a b : Nat} :
-[a+1] % (b + 1 : Int) = 0 ↔ (a + 1) % (b + 1) = 0 := by
rw [← Int.natCast_one, ← Int.natCast_add]
change Int.emod _ _ = 0 ↔ _
rw [emod, natAbs_natCast]
simp only [Nat.succ_eq_add_one, subNat_eq_zero_iff, Nat.add_right_cancel_iff]
rw [eq_comm]
apply Nat.succ_mod_succ_eq_zero_iff.symm
theorem negSucc_emod_negSucc_eq_zero_iff {a b : Nat} :
-[a+1] % -[b+1] = 0 ↔ (a + 1) % (b + 1) = 0 := by
change Int.emod _ _ = 0 ↔ _
rw [emod, natAbs_negSucc]
simp only [Nat.succ_eq_add_one, subNat_eq_zero_iff, Nat.add_right_cancel_iff]
rw [eq_comm]
apply Nat.succ_mod_succ_eq_zero_iff.symm
/-! ### div equivalences -/
theorem tdiv_eq_ediv_of_nonneg : ∀ {a b : Int}, 0 ≤ a → a.tdiv b = a / b
| 0, _, _
| _, 0, _ => by simp
| succ _, succ _, _ => rfl
| succ _, -[_+1], _ => rfl
@[simp] theorem natCast_tdiv_eq_ediv {a : Nat} {b : Int} : (a : Int).tdiv b = a / b :=
tdiv_eq_ediv_of_nonneg (by simp)
theorem tdiv_eq_ediv {a b : Int} :
a.tdiv b = a / b + if 0 ≤ a b a then 0 else sign b := by
simp only [dvd_iff_emod_eq_zero]
match a, b with
| ofNat a, ofNat b => simp [tdiv_eq_ediv_of_nonneg]
| ofNat a, -[b+1] => simp [tdiv_eq_ediv_of_nonneg]
| -[a+1], 0 => simp
| -[a+1], ofNat (succ b) =>
simp only [tdiv, Nat.succ_eq_add_one, ofNat_eq_coe, Int.natCast_add, cast_ofNat_Int,
negSucc_not_nonneg, sign_of_add_one]
simp only [negSucc_emod_ofNat_succ_eq_zero_iff]
norm_cast
simp only [Nat.succ_eq_add_one, false_or]
split <;> rename_i h
· rw [Int.add_zero, neg_ofNat_eq_negSucc_iff]
exact Nat.succ_div_of_mod_eq_zero h
· rw [neg_ofNat_eq_negSucc_add_one_iff]
exact Nat.succ_div_of_mod_ne_zero h
| -[a+1], -[b+1] =>
simp only [tdiv, ofNat_eq_coe, negSucc_not_nonneg, false_or, sign_negSucc]
norm_cast
simp only [negSucc_ediv_negSucc]
rw [Int.natCast_add, Int.natCast_one]
simp only [negSucc_emod_negSucc_eq_zero_iff]
split <;> rename_i h
· norm_cast
exact Nat.succ_div_of_mod_eq_zero h
· rw [Int.add_neg_eq_sub, Int.add_sub_cancel]
norm_cast
exact Nat.succ_div_of_mod_ne_zero h
theorem ediv_eq_tdiv {a b : Int} :
a / b = a.tdiv b - if 0 ≤ a b a then 0 else sign b := by
simp [tdiv_eq_ediv]
theorem divExact_eq_tdiv {a b : Int} (h : b a) : a.divExact b h = a.tdiv b := by
simp [ediv_eq_tdiv, h]
theorem fdiv_eq_ediv_of_nonneg : ∀ (a : Int) {b : Int}, 0 ≤ b → fdiv a b = a / b
| 0, _, _ | -[_+1], 0, _ => by simp
| succ _, ofNat _, _ | -[_+1], succ _, _ => rfl
theorem fdiv_eq_ediv {a b : Int} :
a.fdiv b = a / b - if 0 ≤ b b a then 0 else 1 := by
match a, b with
| ofNat a, ofNat b => simp [fdiv_eq_ediv_of_nonneg]
| -[a+1], ofNat b => simp [fdiv_eq_ediv_of_nonneg]
| 0, -[b+1] => simp
| ofNat (a + 1), -[b+1] =>
simp only [fdiv, ofNat_ediv_negSucc, negSucc_not_nonneg, negSucc_dvd, false_or]
simp only [ofNat_eq_coe, ofNat_dvd]
norm_cast
rw [Nat.succ_div, negSucc_eq]
split <;> rename_i h
· simp
· simp [Int.neg_add]
norm_cast
| -[a+1], -[b+1] =>
simp only [fdiv, ofNat_eq_coe, negSucc_ediv_negSucc, negSucc_not_nonneg, dvd_negSucc, negSucc_dvd,
false_or]
norm_cast
rw [Int.natCast_add, Int.natCast_one, Nat.succ_div]
split <;> simp
theorem ediv_eq_fdiv {a b : Int} :
a / b = a.fdiv b + if 0 ≤ b b a then 0 else 1 := by
simp [fdiv_eq_ediv]
theorem divExact_eq_fdiv {a b : Int} (h : b a) : a.divExact b h = a.fdiv b := by
simp [ediv_eq_fdiv, h]
theorem fdiv_eq_tdiv_of_nonneg {a b : Int} (Ha : 0 ≤ a) (Hb : 0 ≤ b) : fdiv a b = tdiv a b :=
tdiv_eq_ediv_of_nonneg Ha ▸ fdiv_eq_ediv_of_nonneg _ Hb
theorem fdiv_eq_tdiv {a b : Int} :
a.fdiv b = a.tdiv b -
if b a then 0
else
if 0 ≤ a then
if 0 ≤ b then 0
else 1
else
if 0 ≤ b then b.sign
else 1 + b.sign := by
rw [fdiv_eq_ediv, tdiv_eq_ediv]
by_cases h : b a <;> simp [h] <;> omega
theorem tdiv_eq_fdiv {a b : Int} :
a.tdiv b = a.fdiv b +
if b a then 0
else
if 0 ≤ a then
if 0 ≤ b then 0
else 1
else
if 0 ≤ b then b.sign
else 1 + b.sign := by
rw [fdiv_eq_tdiv]
omega
theorem tdiv_eq_ediv_of_dvd {a b : Int} (h : b a) : a.tdiv b = a / b := by
simp [tdiv_eq_ediv, h]
theorem fdiv_eq_ediv_of_dvd {a b : Int} (h : b a) : a.fdiv b = a / b := by
simp [fdiv_eq_ediv, h]
/-! ### mod zero -/
@[simp] theorem zero_tmod (b : Int) : tmod 0 b = 0 := by cases b <;> simp [tmod]
@[simp] theorem tmod_zero : ∀ a : Int, tmod a 0 = a
| ofNat _ => congrArg ofNat <| Nat.mod_zero _
| -[_+1] => congrArg (fun n => -ofNat n) <| Nat.mod_zero _
@[simp] theorem zero_fmod (b : Int) : fmod 0 b = 0 := by cases b <;> rfl
@[simp] theorem fmod_zero : ∀ a : Int, fmod a 0 = a
| 0 => rfl
| succ _ => congrArg ofNat <| Nat.mod_zero _
| -[_+1] => congrArg negSucc <| Nat.mod_zero _
/-! ### mod definitions -/
theorem tmod_add_mul_tdiv : ∀ a b : Int, tmod a b + b * (a.tdiv b) = a
| ofNat _, ofNat _ => congrArg ofNat (Nat.mod_add_div ..)
| ofNat m, -[n+1] => by
change (m % succ n + -↑(succ n) * -↑(m / succ n) : Int) = m
rw [Int.neg_mul_neg]; exact congrArg ofNat (Nat.mod_add_div ..)
| -[m+1], 0 => by
change -(↑((succ m) % 0) : Int) + 0 * -↑(succ m / 0) = -↑(succ m)
rw [Nat.mod_zero, Int.zero_mul, Int.add_zero]
| -[m+1], ofNat n => by
change -(↑((succ m) % n) : Int) + ↑n * -↑(succ m / n) = -↑(succ m)
rw [Int.mul_neg, ← Int.neg_add]
exact congrArg (-ofNat ·) (Nat.mod_add_div ..)
| -[m+1], -[n+1] => by
change -(↑(succ m % succ n) : Int) + -↑(succ n) * ↑(succ m / succ n) = -↑(succ m)
rw [Int.neg_mul, ← Int.neg_add]
exact congrArg (-ofNat ·) (Nat.mod_add_div ..)
@[deprecated tmod_add_mul_tdiv (since := "2025-09-01")]
def tmod_add_tdiv := @tmod_add_mul_tdiv
theorem mul_tdiv_add_tmod (a b : Int) : b * a.tdiv b + tmod a b = a := by
rw [Int.add_comm]; apply tmod_add_mul_tdiv ..
@[deprecated mul_tdiv_add_tmod (since := "2025-09-01")]
def tdiv_add_tmod := @mul_tdiv_add_tmod
theorem tmod_add_tdiv_mul (m k : Int) : tmod m k + m.tdiv k * k = m := by
rw [Int.mul_comm]; apply tmod_add_mul_tdiv
@[deprecated tmod_add_tdiv_mul (since := "2025-09-01")]
def tmod_add_tdiv' := @tmod_add_mul_tdiv
theorem tdiv_mul_add_tmod (m k : Int) : m.tdiv k * k + tmod m k = m := by
rw [Int.mul_comm]; apply mul_tdiv_add_tmod
@[deprecated tdiv_mul_add_tmod (since := "2025-09-01")]
def tdiv_add_tmod' := @tdiv_mul_add_tmod
theorem tmod_def (a b : Int) : tmod a b = a - b * a.tdiv b := by
rw [← Int.add_sub_cancel (tmod a b), tmod_add_mul_tdiv]
theorem mul_tdiv_self (a b : Int) : b * (a.tdiv b) = a - a.tmod b := by
rw [tmod_def, Int.sub_sub_self]
theorem tdiv_mul_self (a b : Int) : a.tdiv b * b = a - a.tmod b := by
rw [Int.mul_comm, tmod_def, Int.sub_sub_self]
theorem fmod_add_mul_fdiv : ∀ a b : Int, a.fmod b + b * a.fdiv b = a
| 0, ofNat _ | 0, -[_+1] => congrArg ofNat <| by simp
| succ _, ofNat _ => congrArg ofNat <| Nat.mod_add_div ..
| succ m, -[n+1] => by
change subNatNat (m % succ n) n + (↑(succ n * (m / succ n)) + n + 1) = (m + 1)
rw [Int.add_comm _ n, ← Int.add_assoc, ← Int.add_assoc,
Int.subNatNat_eq_coe, Int.sub_add_cancel]
exact congrArg (ofNat · + 1) <| Nat.mod_add_div ..
| -[_+1], 0 => by rw [fmod_zero]; rfl
| -[m+1], succ n => by
change subNatNat .. - (↑(succ n * (m / succ n)) + ↑(succ n)) = -↑(succ m)
rw [Int.subNatNat_eq_coe, ← Int.sub_sub, ← Int.neg_sub, Int.sub_sub, Int.sub_sub_self]
exact congrArg (-ofNat ·) <| Nat.succ_add .. ▸ Nat.mod_add_div .. ▸ rfl
| -[m+1], -[n+1] => by
change -(↑(succ m % succ n) : Int) + -↑(succ n * (succ m / succ n)) = -↑(succ m)
rw [← Int.neg_add]; exact congrArg (-ofNat ·) <| Nat.mod_add_div ..
@[deprecated fmod_add_mul_fdiv (since := "2025-09-01")]
def fmod_add_fdiv := @fmod_add_mul_fdiv
theorem fmod_add_fdiv_mul (a b : Int) : a.fmod b + (a.fdiv b) * b = a := by
rw [Int.mul_comm]; exact fmod_add_mul_fdiv ..
@[deprecated fmod_add_fdiv_mul (since := "2025-09-01")]
def fmod_add_fdiv' := @fmod_add_fdiv_mul
theorem mul_fdiv_add_fmod (a b : Int) : b * a.fdiv b + a.fmod b = a := by
rw [Int.add_comm]; exact fmod_add_mul_fdiv ..
@[deprecated mul_fdiv_add_fmod (since := "2025-09-01")]
def fdiv_add_fmod := @mul_fdiv_add_fmod
theorem fdiv_mul_add_fmod (a b : Int) : (a.fdiv b) * b + a.fmod b = a := by
rw [Int.mul_comm]; exact mul_fdiv_add_fmod ..
@[deprecated mul_fdiv_add_fmod (since := "2025-09-01")]
def fdiv_add_fmod' := @mul_fdiv_add_fmod
theorem fmod_def (a b : Int) : a.fmod b = a - b * a.fdiv b := by
rw [← Int.add_sub_cancel (a.fmod b), fmod_add_mul_fdiv]
theorem mul_fdiv_self (a b : Int) : b * (a.fdiv b) = a - a.fmod b := by
rw [fmod_def, Int.sub_sub_self]
theorem fdiv_mul_self (a b : Int) : a.fdiv b * b = a - a.fmod b := by
rw [Int.mul_comm, fmod_def, Int.sub_sub_self]
/-! ### mod equivalences -/
theorem fmod_eq_emod_of_nonneg (a : Int) {b : Int} (hb : 0 ≤ b) : fmod a b = a % b := by
simp [fmod_def, emod_def, fdiv_eq_ediv_of_nonneg _ hb]
theorem fmod_eq_emod {a b : Int} :
fmod a b = a % b + if 0 ≤ b b a then 0 else b := by
simp [fmod_def, emod_def, fdiv_eq_ediv]
split <;> simp [Int.mul_sub]
omega
theorem emod_eq_fmod {a b : Int} :
a % b = fmod a b - if 0 ≤ b b a then 0 else b := by
simp [fmod_eq_emod]
theorem tmod_eq_emod_of_nonneg {a b : Int} (ha : 0 ≤ a) : tmod a b = a % b := by
simp [emod_def, tmod_def, tdiv_eq_ediv_of_nonneg ha]
theorem tmod_eq_emod {a b : Int} :
tmod a b = a % b - if 0 ≤ a b a then 0 else b.natAbs := by
rw [tmod_def, tdiv_eq_ediv]
simp only [dvd_iff_emod_eq_zero]
split
· simp [emod_def]
· rw [Int.mul_add, ← Int.sub_sub, emod_def]
simp
theorem emod_eq_tmod {a b : Int} :
a % b = tmod a b + if 0 ≤ a b a then 0 else b.natAbs := by
simp [tmod_eq_emod]
theorem fmod_eq_tmod_of_nonneg {a b : Int} (ha : 0 ≤ a) (hb : 0 ≤ b) : fmod a b = tmod a b :=
tmod_eq_emod_of_nonneg ha ▸ fmod_eq_emod_of_nonneg _ hb
theorem fmod_eq_tmod {a b : Int} :
fmod a b = tmod a b +
if b a then 0
else
if 0 ≤ a then
if 0 ≤ b then 0
else b
else
if 0 ≤ b then b.natAbs
else 2 * b.toNat := by
simp [fmod_eq_emod, tmod_eq_emod]
by_cases h : b a <;> simp [h]
split <;> split <;> omega
theorem tmod_eq_fmod {a b : Int} :
tmod a b = fmod a b -
if b a then 0
else
if 0 ≤ a then
if 0 ≤ b then 0
else b
else
if 0 ≤ b then b.natAbs
else 2 * b.toNat := by
simp [fmod_eq_tmod]
/-! ### `/` ediv -/
theorem mul_add_ediv_right (a c : Int) {b : Int} (H : b ≠ 0) : (a * b + c) / b = a + c / b := by
rw [Int.add_comm, add_mul_ediv_right _ _ H, Int.add_comm]
theorem mul_add_ediv_left (b : Int) {a : Int}
(c : Int) (H : a ≠ 0) : (a * b + c) / a = b + c / a := by
rw [Int.add_comm, add_mul_ediv_left _ _ H, Int.add_comm]
theorem sub_mul_ediv_right (a b : Int) {c : Int} (H : c ≠ 0) : (a - b * c) / c = a / c - b := by
rw [Int.sub_eq_add_neg, ← Int.neg_mul, add_mul_ediv_right _ _ H, Int.sub_eq_add_neg]
theorem sub_mul_ediv_left (a : Int) {b : Int}
(c : Int) (H : b ≠ 0) : (a - b * c) / b = a / b - c := by
rw [Int.sub_eq_add_neg, ← Int.mul_neg, add_mul_ediv_left _ _ H, Int.sub_eq_add_neg]
theorem mul_sub_ediv_right (a c : Int) {b : Int} (H : b ≠ 0) : (a * b - c) / b = a + -c / b := by
rw [Int.sub_eq_add_neg, Int.add_comm, add_mul_ediv_right _ _ H, Int.add_comm]
theorem mul_sub_ediv_left (b : Int) {a : Int}
(c : Int) (H : a ≠ 0) : (a * b - c) / a = b + -c / a := by
rw [Int.sub_eq_add_neg, Int.add_comm, add_mul_ediv_left _ _ H, Int.add_comm]
theorem ediv_neg_of_neg_of_pos {a b : Int} (Ha : a < 0) (Hb : 0 < b) : a / b < 0 :=
match a, b, eq_negSucc_of_lt_zero Ha, eq_succ_of_zero_lt Hb with
| _, _, ⟨_, rfl⟩, ⟨_, rfl⟩ => negSucc_lt_zero _
@[deprecated ediv_neg_of_neg_of_pos (since := "2025-03-04")]
abbrev ediv_neg' := @ediv_neg_of_neg_of_pos
theorem negSucc_ediv (m : Nat) {b : Int} (H : 0 < b) : -[m+1] / b = -(ediv m b + 1) :=
match b, eq_succ_of_zero_lt H with
| _, ⟨_, rfl⟩ => rfl
theorem ediv_nonneg {a b : Int} (Ha : 0 ≤ a) (Hb : 0 ≤ b) : 0 ≤ a / b :=
match a, b, eq_ofNat_of_zero_le Ha, eq_ofNat_of_zero_le Hb with
| _, _, ⟨_, rfl⟩, ⟨_, rfl⟩ => ofNat_zero_le _
theorem ediv_nonneg_of_nonpos_of_nonpos {a b : Int} (Ha : a ≤ 0) (Hb : b ≤ 0) : 0 ≤ a / b := by
match a, b with
| ofNat a, b =>
match Int.le_antisymm Ha (ofNat_zero_le a) with
| h1 =>
rw [h1, zero_ediv]
exact Int.le_refl 0
| a, ofNat b =>
match Int.le_antisymm Hb (ofNat_zero_le b) with
| h1 =>
rw [h1, Int.ediv_zero]
exact Int.le_refl 0
| negSucc a, negSucc b =>
rw [Int.div_def, ediv]
exact le_add_one (ediv_nonneg (ofNat_zero_le a) (Int.le_trans (ofNat_zero_le b) (le.intro 1 rfl)))
theorem ediv_pos_of_neg_of_neg {a b : Int} (ha : a < 0) (hb : b < 0) : 0 < a / b := by
rw [Int.div_def]
match a, b, ha, hb with
| .negSucc a, .negSucc b, _, _ => apply ofNat_succ_pos
theorem ediv_nonpos_of_nonneg_of_nonpos {a b : Int} (Ha : 0 ≤ a) (Hb : b ≤ 0) : a / b ≤ 0 :=
Int.nonpos_of_neg_nonneg <| Int.ediv_neg .. ▸ Int.ediv_nonneg Ha (Int.neg_nonneg_of_nonpos Hb)
@[deprecated ediv_nonpos_of_nonneg_of_nonpos (since := "2025-03-04")]
abbrev ediv_nonpos := @ediv_nonpos_of_nonneg_of_nonpos
theorem ediv_eq_zero_of_lt {a b : Int} (H1 : 0 ≤ a) (H2 : a < b) : a / b = 0 :=
match a, b, eq_ofNat_of_zero_le H1, eq_succ_of_zero_lt (Int.lt_of_le_of_lt H1 H2) with
| _, _, ⟨_, rfl⟩, ⟨_, rfl⟩ => congrArg Nat.cast <| Nat.div_eq_of_lt <| ofNat_lt.1 H2
theorem ediv_eq_neg_one_of_neg_of_le {a b : Int} (H1 : a < 0) (H2 : -a ≤ b) : a / b = -1 := by
match a, b, H1, H2 with
| negSucc a', ofNat (b' + 1), H1, H2 =>
rw [Int.div_def, ediv, Int.negSucc_eq, Int.neg_inj]
norm_cast
rw [Nat.add_eq_right, Nat.div_eq_zero_iff_lt (by omega)]
simp [Int.negSucc_eq] at H2
omega
theorem ediv_eq_one_of_neg_of_le {a b : Int} (H1 : a < 0) (H2 : b ≤ a) : a / b = 1 := by
match a, b, H1, H2 with
| negSucc a', ofNat n', H1, H2 => simp [Int.negSucc_eq] at H2; omega
| negSucc a', negSucc b', H1, H2 =>
rw [Int.div_def, ediv, ofNat_eq_coe]
norm_cast
rw [Nat.succ_eq_add_one, Nat.add_eq_right, Nat.div_eq_zero_iff_lt (by omega)]
simp [Int.negSucc_eq] at H2
omega
theorem one_ediv (b : Int) : 1 / b = if b.natAbs = 1 then b else 0 := by
induction b using wlog_sign
case inv => simp; split <;> simp
case w b =>
match b with
| 0 => simp
| 1 => simp
| b + 2 =>
apply ediv_eq_zero_of_lt (by decide) (by omega)
theorem neg_one_ediv (b : Int) : -1 / b = -b.sign :=
match b with
| ofNat 0 => by simp
| ofNat (b + 1) =>
ediv_eq_neg_one_of_neg_of_le (by decide) (by simp [ofNat_eq_coe]; omega)
| negSucc b =>
ediv_eq_one_of_neg_of_le (by decide) (by omega)
@[simp] theorem mul_ediv_mul_of_pos {a : Int}
(b c : Int) (H : 0 < a) : (a * b) / (a * c) = b / c :=
suffices ∀ (m k : Nat) (b : Int), (m.succ * b) / (m.succ * k) = b / k from
match a, eq_succ_of_zero_lt H, c, Int.eq_nat_or_neg c with
| _, ⟨m, rfl⟩, _, ⟨k, .inl rfl⟩ => this _ ..
| _, ⟨m, rfl⟩, _, ⟨k, .inr rfl⟩ => by
rw [Int.mul_neg, Int.ediv_neg, Int.ediv_neg]; apply congrArg Neg.neg; apply this
fun m k b =>
match b, k with
| ofNat _, _ => congrArg ofNat (Nat.mul_div_mul_left _ _ m.succ_pos)
| -[n+1], 0 => by
rw [Int.ofNat_zero, Int.mul_zero, Int.ediv_zero, Int.ediv_zero]
| -[n+1], succ k => congrArg negSucc <|
show (m.succ * n + m) / (m.succ * k.succ) = n / k.succ by
apply Nat.div_eq_of_lt_le
· refine Nat.le_trans ?_ (Nat.le_add_right _ _)
rw [← Nat.mul_div_mul_left _ _ m.succ_pos]
apply Nat.div_mul_le_self
· change m.succ * n.succ ≤ _
rw [Nat.mul_left_comm]
apply Nat.mul_le_mul_left
apply (Nat.div_lt_iff_lt_mul k.succ_pos).1
apply Nat.lt_succ_self
@[simp] theorem mul_ediv_mul_of_pos_left
(a : Int) {b : Int} (c : Int) (H : 0 < b) : (a * b) / (c * b) = a / c := by
rw [Int.mul_comm, Int.mul_comm c, mul_ediv_mul_of_pos _ _ H]
protected theorem ediv_eq_of_eq_mul_right {a b c : Int}
(H1 : b ≠ 0) (H2 : a = b * c) : a / b = c := by rw [H2, Int.mul_ediv_cancel_left _ H1]
protected theorem eq_ediv_of_mul_eq_right {a b c : Int}
(H1 : a ≠ 0) (H2 : a * b = c) : b = c / a :=
(Int.ediv_eq_of_eq_mul_right H1 H2.symm).symm
protected theorem ediv_eq_of_eq_mul_left {a b c : Int}
(H1 : b ≠ 0) (H2 : a = c * b) : a / b = c :=
Int.ediv_eq_of_eq_mul_right H1 (by rw [Int.mul_comm, H2])
protected theorem eq_ediv_of_mul_eq_left {a b c : Int}
(H1 : b ≠ 0) (H2 : a * b = c) : a = c / b :=
(Int.ediv_eq_of_eq_mul_left H1 H2.symm).symm
@[simp] protected theorem ediv_self {a : Int} (H : a ≠ 0) : a / a = 1 := by
have := Int.mul_ediv_cancel 1 H; rwa [Int.one_mul] at this
@[simp] protected theorem neg_ediv_self (a : Int) (h : a ≠ 0) : (-a) / a = -1 := by
rw [neg_ediv_of_dvd (Int.dvd_refl a), Int.ediv_self h]
theorem sign_ediv (a b : Int) : sign (a / b) = if 0 ≤ a ∧ a < b.natAbs then 0 else sign a * sign b := by
induction b using wlog_sign
case inv => simp; split <;> simp [Int.mul_neg]
case w b =>
match b with
| 0 => simp
| b + 1 =>
have : ((b + 1 : Nat) : Int).natAbs = b + 1 := by omega
rw [this]
match a with
| 0 => simp
| (a + 1 : Nat) =>
norm_cast
simp only [Nat.le_add_left, Nat.add_lt_add_iff_right, true_and, Int.natCast_add,
cast_ofNat_Int, sign_of_add_one, Int.mul_one]
split
· rw [Nat.div_eq_of_lt (by omega)]
simp
· have := Nat.div_pos (a := a + 1) (b := b + 1) (by omega) (by omega)
rw [sign_eq_one_of_pos (mod_cast this)]
| negSucc a =>
norm_cast
/-! ### emod -/
theorem mod_def' (m n : Int) : m % n = emod m n := rfl
theorem negSucc_emod (m : Nat) {b : Int} (bpos : 0 < b) : -[m+1] % b = b - 1 - m % b := by
rw [Int.sub_sub, Int.add_comm]
match b, eq_succ_of_zero_lt bpos with
| _, ⟨n, rfl⟩ => rfl
theorem emod_negSucc (m : Nat) (n : Int) :
(Int.negSucc m) % n = Int.subNatNat (Int.natAbs n) (Nat.succ (m % Int.natAbs n)) := rfl
theorem ofNat_mod_ofNat (m n : Nat) : (m % n : Int) = ↑(m % n) := rfl
@[simp] theorem add_neg_mul_emod_self_right (a b c : Int) : (a + -(b * c)) % c = a % c := by
rw [Int.neg_mul_eq_neg_mul, add_mul_emod_self_right]
@[deprecated add_neg_mul_emod_self_right (since := "2025-04-11")]
theorem add_neg_mul_emod_self {a b c : Int} : (a + -(b * c)) % c = a % c :=
add_neg_mul_emod_self_right ..
@[simp] theorem add_neg_mul_emod_self_left (a b c : Int) : (a + -(b * c)) % b = a % b := by
rw [Int.neg_mul_eq_mul_neg, add_mul_emod_self_left]
@[simp] theorem add_emod_right (a b : Int) : (a + b) % b = a % b := by
have := add_mul_emod_self_left a b 1; rwa [Int.mul_one] at this
@[deprecated add_emod_right (since := "2025-04-11")]
theorem add_emod_self {a b : Int} : (a + b) % b = a % b := add_emod_right ..
@[simp] theorem add_emod_left (a b : Int) : (a + b) % a = b % a := by
rw [Int.add_comm, add_emod_right]
@[deprecated add_emod_left (since := "2025-04-11")]
theorem add_emod_self_left {a b : Int} : (a + b) % a = b % a := add_emod_left ..
@[simp] theorem sub_mul_emod_self_right (a b c : Int) : (a - b * c) % c = a % c := by
simp [Int.sub_eq_add_neg]
@[simp] theorem sub_mul_emod_self_left (a b c : Int) : (a - b * c) % b = a % b := by
simp [Int.sub_eq_add_neg]
@[simp] theorem mul_sub_emod_self_right (a b c : Int) : (a * b - c) % b = -c % b := by
simp [Int.sub_eq_add_neg]
@[simp] theorem mul_sub_emod_self_left (a b c : Int) : (a * b - c) % a = -c % a := by
simp [Int.sub_eq_add_neg]
@[simp] theorem sub_emod_right (a b : Int) : (a - b) % b = a % b := by
rw (occs := [1]) [← Int.mul_one b, sub_mul_emod_self_left]
@[simp] theorem sub_emod_left (a b : Int) : (a - b) % a = -b % a := by
simp [Int.sub_eq_add_neg]
theorem neg_emod_eq_sub_emod {a b : Int} : -a % b = (b - a) % b := by
rw [← add_emod_left, Int.sub_eq_add_neg]
theorem emod_eq_add_self_emod {a b : Int} : a % b = (a + b) % b :=
(Int.add_emod_right ..).symm
@[simp] theorem emod_neg (a b : Int) : a % -b = a % b := by
rw [emod_def, emod_def, Int.ediv_neg, Int.neg_mul_neg]
@[simp] theorem neg_emod_self (a : Int) : -a % a = 0 := by
rw [neg_emod_eq_sub_emod, Int.sub_self, zero_emod]
@[simp] theorem emod_sub_emod (m n k : Int) : (m % n - k) % n = (m - k) % n :=
Int.emod_add_emod m n (-k)
@[simp] theorem sub_emod_emod (m n k : Int) : (m - n % k) % k = (m - n) % k := by
apply (emod_add_cancel_right (n % k)).mp
rw [Int.sub_add_cancel, Int.add_emod_emod, Int.sub_add_cancel]
theorem emod_eq_of_lt {a b : Int} (H1 : 0 ≤ a) (H2 : a < b) : a % b = a :=
have b0 := Int.le_trans H1 (Int.le_of_lt H2)
match a, b, eq_ofNat_of_zero_le H1, eq_ofNat_of_zero_le b0 with
| _, _, ⟨_, rfl⟩, ⟨_, rfl⟩ => congrArg ofNat <| Nat.mod_eq_of_lt (Int.ofNat_lt.1 H2)
theorem emod_lt_of_neg (a : Int) {b : Int} (h : b < 0) : a % b < -b := by
match b, h with
| .negSucc b', h =>
simp only [negSucc_eq, emod_neg]
apply emod_lt_of_pos
omega
theorem emod_lt (a : Int) {b : Int} (h : b ≠ 0) : a % b < b.natAbs :=
match b, h with
| (b : Nat), h => emod_lt_of_pos a (by omega)
| negSucc b, h => emod_lt_of_neg a (by omega)
@[simp] theorem emod_self_add_one {x : Int} (h : 0 ≤ x) : x % (x + 1) = x :=
emod_eq_of_lt h (Int.lt_succ x)
theorem sign_emod (a : Int) {b} (h : b ≠ 0) : sign (a % b) = if b a then 0 else 1 := by
split <;> rename_i w
· simp [emod_eq_zero_of_dvd, w]
· obtain rfl | w := emod_pos_of_not_dvd w
· simp at h
· simp [sign_eq_one_of_pos w]
theorem one_emod {b : Int} : 1 % b = if b.natAbs = 1 then 0 else 1 := by
rw [emod_def, one_ediv]
split <;> rename_i h
· obtain rfl | rfl := natAbs_eq_iff.mp h <;> simp
· simp
@[simp] theorem neg_emod_two (i : Int) : -i % 2 = i % 2 := by omega
/-! ### properties of `/` and `%` -/
theorem mul_ediv_cancel_of_dvd {a b : Int} (H : b a) : b * (a / b) = a :=
mul_ediv_cancel_of_emod_eq_zero (emod_eq_zero_of_dvd H)
theorem ediv_mul_cancel_of_dvd {a b : Int} (H : b a) : a / b * b = a :=
ediv_mul_cancel_of_emod_eq_zero (emod_eq_zero_of_dvd H)
theorem emod_two_eq (x : Int) : x % 2 = 0 x % 2 = 1 := by omega
theorem add_emod_eq_add_emod_left {m n k : Int} (i : Int)
(H : m % n = k % n) : (i + m) % n = (i + k) % n := by
rw [Int.add_comm, add_emod_eq_add_emod_right _ H, Int.add_comm]
theorem emod_add_cancel_left {m n k i : Int} : (i + m) % n = (i + k) % n ↔ m % n = k % n := by
rw [Int.add_comm, Int.add_comm i, emod_add_cancel_right]
theorem emod_sub_cancel_right {m n k : Int} (i) : (m - i) % n = (k - i) % n ↔ m % n = k % n :=
emod_add_cancel_right _
theorem emod_eq_emod_iff_emod_sub_eq_zero {m n k : Int} : m % n = k % n ↔ (m - k) % n = 0 :=
(emod_sub_cancel_right k).symm.trans <| by simp [Int.sub_self]
theorem emod_sub_cancel_left {m n k : Int} (i) : (i - m) % n = (i - k) % n ↔ m % n = k % n := by
simp only [emod_eq_emod_iff_emod_sub_eq_zero, ← dvd_iff_emod_eq_zero,
(by omega : i - m - (i - k) = -(m - k)), Int.dvd_neg]
protected theorem ediv_emod_unique {a b r q : Int} (h : 0 < b) :
a / b = q ∧ a % b = r ↔ r + b * q = a ∧ 0 ≤ r ∧ r < b := by
constructor
· intro ⟨rfl, rfl⟩
exact ⟨emod_add_mul_ediv a b, emod_nonneg _ (Int.ne_of_gt h), emod_lt_of_pos _ h⟩
· intro ⟨rfl, hz, hb⟩
constructor
· rw [Int.add_mul_ediv_left r q (Int.ne_of_gt h), ediv_eq_zero_of_lt hz hb]
simp [Int.zero_add]
· rw [add_mul_emod_self_left, emod_eq_of_lt hz hb]
protected theorem ediv_emod_unique' {a b r q : Int} (h : b < 0) :
a / b = q ∧ a % b = r ↔ r + b * q = a ∧ 0 ≤ r ∧ r < -b := by
have := Int.ediv_emod_unique (a := a) (b := -b) (r := r) (q := -q) (by omega)
simpa [Int.neg_inj, Int.neg_mul, Int.mul_neg]
@[simp] theorem mul_emod_mul_of_pos
{a : Int} (b c : Int) (H : 0 < a) : (a * b) % (a * c) = a * (b % c) := by
rw [emod_def, emod_def, mul_ediv_mul_of_pos _ _ H, Int.mul_sub, Int.mul_assoc]
theorem lt_ediv_add_one_mul_self (a : Int) {b : Int} (H : 0 < b) : a < (a / b + 1) * b := by
rw [Int.add_mul, Int.one_mul, Int.mul_comm]
exact Int.lt_add_of_sub_left_lt <| Int.emod_def .. ▸ emod_lt_of_pos _ H
theorem neg_ediv {a b : Int} : (-a) / b = -(a / b) - if b a then 0 else b.sign := by
if hb : b = 0 then
simp [hb]
else
conv => lhs; rw [← mul_ediv_add_emod a b]
rw [Int.neg_add, ← Int.mul_neg, mul_add_ediv_left _ _ hb, Int.add_comm]
split <;> rename_i h
· rw [emod_eq_zero_of_dvd h]
simp
· if hb : 0 < b then
rw [Int.sign_eq_one_of_pos hb, ediv_eq_neg_one_of_neg_of_le]
· omega
· have : 0 < a % b := (emod_pos_of_not_dvd h).resolve_left (by omega)
omega
· have := emod_lt_of_pos a hb
omega
else
replace hb : b < 0 := by omega
rw [Int.sign_eq_neg_one_of_neg hb, Int.ediv_eq_one_of_neg_of_le]
· omega
· have : 0 < a % b := (emod_pos_of_not_dvd h).resolve_left (by omega)
omega
· have := emod_lt_of_neg a hb
omega
theorem tdiv_cases (n m : Int) : n.tdiv m =
if 0 ≤ n then
if 0 ≤ m then n / m else -(n / (-m))
else
if 0 ≤ m then -((-n) / m) else (-n) / (-m) := by
split <;> rename_i hn
· split <;> rename_i hm
· rw [Int.tdiv_eq_ediv_of_nonneg hn]
· rw [Int.tdiv_eq_ediv_of_nonneg hn]
simp
· split <;> rename_i hm
· rw [Int.tdiv_eq_ediv, Int.neg_ediv]
simp [hn, Int.neg_sub, Int.add_comm]
· rw [Int.tdiv_eq_ediv, Int.neg_ediv, Int.ediv_neg]
simp [hn, Int.sub_eq_add_neg, apply_ite Neg.neg]
theorem neg_emod {a b : Int} : (-a) % b = if b a then 0 else b.natAbs - (a % b) := by
rw [emod_def, emod_def, neg_ediv, Int.mul_sub, Int.mul_neg]
split <;> rename_i h
· simp [mul_ediv_cancel_of_dvd h]
· simp
omega
theorem natAbs_ediv (a : Int) (b : Int) : natAbs (a / b) = natAbs a / natAbs b + if 0 ≤ a b = 0 b a then 0 else 1 := by
by_cases hb : b = 0 <;> try (simp_all; done)
simp only [hb, false_or]
induction b using wlog_sign
case neg.inv => simp
case neg.w b =>
match a with
| 0 => simp
| (a + 1 : Nat) => norm_cast
| negSucc a =>
simp only [negSucc_eq]
norm_cast
rw [neg_ediv]
norm_cast
rw [natAbs_neg, natAbs_natCast]
have : ¬ 0 ≤ -((a + 1 : Nat) : Int) := by omega
simp only [this]
have : ↑b -((a + 1 : Nat) : Int) ↔ b a + 1 := by simp; norm_cast
simp only [this, false_or]
split <;> rename_i h
· simp [-natCast_ediv]
· rw [Nat.succ_div, if_neg h, sign_eq_one_of_pos (by omega), Int.sub_eq_add_neg, ← Int.neg_add, natAbs_neg]
norm_cast
theorem natAbs_ediv_of_nonneg {a b : Int} (ha : 0 ≤ a) : (a / b).natAbs = a.natAbs / b.natAbs := by
rw [natAbs_ediv, if_pos (Or.inl ha), Nat.add_zero]
theorem natAbs_ediv_of_dvd {a b : Int} (hab : b a) : (a / b).natAbs = a.natAbs / b.natAbs := by
rw [natAbs_ediv, if_pos (Or.inr (Or.inr hab)), Nat.add_zero]
theorem natAbs_emod_of_nonneg {a : Int} (h : 0 ≤ a) (b : Int) :
natAbs (a % b) = natAbs a % natAbs b := by
match a, b, h with
| (a : Nat), (b : Nat), _ => norm_cast
| (a : Nat), negSucc b, _ => simp [negSucc_eq]; norm_cast
theorem natAbs_emod (a : Int) {b : Int} (hb : b ≠ 0):
natAbs (a % b) = if 0 ≤ a b a then natAbs a % natAbs b else natAbs b - natAbs a % natAbs b := by
match a with
| (a : Nat) => simp [natAbs_emod_of_nonneg]
| negSucc a =>
simp
split <;> rename_i h
· simp [negSucc_eq]
rw [emod_eq_zero_of_dvd, Nat.mod_eq_zero_of_dvd, natAbs_zero]
· exact ofNat_dvd_right.mp h
· exact dvd_natAbs.mp h
simp [negSucc_eq]
simp [neg_emod]
rw [if_neg h]
norm_cast
have := natAbs_emod_of_nonneg (a := a + 1) (by omega) b
norm_cast at this
rw [natAbs_sub_of_nonneg_of_le, this]
omega
· exact emod_nonneg _ hb
· have := emod_lt (a + 1 : Nat) hb
omega
theorem natAbs_ediv_le_natAbs (a b : Int) : natAbs (a / b) ≤ natAbs a :=
match b, Int.eq_nat_or_neg b with
| _, ⟨n, .inl rfl⟩ => aux _ _
| _, ⟨n, .inr rfl⟩ => by rw [Int.ediv_neg, natAbs_neg]; apply aux
where
aux : ∀ (a : Int) (n : Nat), natAbs (a / n) ≤ natAbs a
| ofNat _, _ => Nat.div_le_self ..
| -[_+1], 0 => Nat.zero_le _
| -[_+1], succ _ => Nat.succ_le_succ (Nat.div_le_self _ _)
@[deprecated natAbs_ediv_le_natAbs (since := "2025-03-05")]
abbrev natAbs_div_le_natAbs := natAbs_ediv_le_natAbs
theorem ediv_le_self {a : Int} (b : Int) (Ha : 0 ≤ a) : a / b ≤ a := by
have := Int.le_trans le_natAbs (ofNat_le.2 <| natAbs_ediv_le_natAbs a b)
rwa [natAbs_of_nonneg Ha] at this
theorem dvd_emod_sub_self {x m : Int} : m x % m - x :=
dvd_of_emod_eq_zero (by simp)
theorem dvd_self_sub_emod {x m : Int} : m x - x % m :=
dvd_of_emod_eq_zero (by simp)
theorem emod_eq_iff {a b c : Int} (hb : b ≠ 0) : a % b = c ↔ 0 ≤ c ∧ c < b.natAbs ∧ b c - a := by
refine ⟨?_, ?_⟩
· rintro rfl
exact ⟨emod_nonneg a hb, emod_lt a hb, dvd_emod_sub_self⟩
· rintro ⟨h₁, h₂, h₃⟩
rw [← Int.sub_eq_zero]
have := dvd_emod_sub_self (x := a) (m := b)
have hdvd := Int.dvd_sub this h₃
rw [(by omega : a % b - a - (c - a) = a % b - c)] at hdvd
apply eq_zero_of_dvd_of_natAbs_lt_natAbs hdvd
have := emod_nonneg a hb
have := emod_lt a hb
omega
@[simp] theorem neg_mul_emod_left (a b : Int) : -(a * b) % b = 0 := by
rw [← dvd_iff_emod_eq_zero, Int.dvd_neg]
exact Int.dvd_mul_left a b
@[simp] theorem neg_mul_emod_right (a b : Int) : -(a * b) % a = 0 := by
rw [← dvd_iff_emod_eq_zero, Int.dvd_neg]
exact Int.dvd_mul_right a b
@[deprecated mul_ediv_cancel (since := "2025-03-05")]
theorem neg_mul_ediv_cancel (a b : Int) (h : b ≠ 0) : -(a * b) / b = -a := by
rw [neg_ediv_of_dvd (Int.dvd_mul_left a b), mul_ediv_cancel _ h]
@[deprecated mul_ediv_cancel (since := "2025-03-05")]
theorem neg_mul_ediv_cancel_left (a b : Int) (h : a ≠ 0) : -(a * b) / a = -b := by
rw [neg_ediv_of_dvd (Int.dvd_mul_right a b), mul_ediv_cancel_left _ h]
@[simp] theorem ediv_one : ∀ a : Int, a / 1 = a
| (_:Nat) => congrArg Nat.cast (Nat.div_one _)
| -[_+1] => congrArg negSucc (Nat.div_one _)
@[simp] theorem emod_one (a : Int) : a % 1 = 0 := by
simp [emod_def, Int.one_mul, Int.sub_self]
theorem ediv_minus_one (a : Int) : a / (-1) = -a := by
simp
theorem emod_minus_one (a : Int) : a % (-1) = 0 := by
simp
@[deprecated sub_emod_right (since := "2025-04-11")]
theorem emod_sub_cancel (x y : Int) : (x - y) % y = x % y :=
sub_emod_right ..
@[simp] theorem add_neg_emod_self (a b : Int) : (a + -b) % b = a % b := by
rw [Int.add_neg_eq_sub, sub_emod_right]
@[simp] theorem neg_add_emod_self (a b : Int) : (-a + b) % a = b % a := by
rw [Int.add_comm, add_neg_emod_self]
/-- If `a % b = c` then `b` divides `a - c`. -/
theorem dvd_self_sub_of_emod_eq {a b : Int} : {c : Int} → a % b = c → b a - c
| _, rfl => dvd_self_sub_emod
@[deprecated dvd_self_sub_of_emod_eq (since := "2025-04-12")]
theorem dvd_sub_of_emod_eq {a b : Int} : {c : Int} → a % b = c → b a - c :=
dvd_self_sub_of_emod_eq
theorem dvd_sub_self_of_emod_eq {a b : Int} : {c : Int} → a % b = c → b c - a
| _, rfl => dvd_emod_sub_self
protected theorem eq_mul_of_ediv_eq_right {a b c : Int}
(H1 : b a) (H2 : a / b = c) : a = b * c := by rw [← H2, Int.mul_ediv_cancel' H1]
protected theorem ediv_eq_iff_eq_mul_right {a b c : Int}
(H : b ≠ 0) (H' : b a) : a / b = c ↔ a = b * c :=
⟨Int.eq_mul_of_ediv_eq_right H', Int.ediv_eq_of_eq_mul_right H⟩
protected theorem ediv_eq_iff_eq_mul_left {a b c : Int}
(H : b ≠ 0) (H' : b a) : a / b = c ↔ a = c * b := by
rw [Int.mul_comm]; exact Int.ediv_eq_iff_eq_mul_right H H'
protected theorem eq_mul_of_ediv_eq_left {a b c : Int}
(H1 : b a) (H2 : a / b = c) : a = c * b := by
rw [Int.mul_comm, Int.eq_mul_of_ediv_eq_right H1 H2]
protected theorem eq_zero_of_ediv_eq_zero {d n : Int} (h : d n) (H : n / d = 0) : n = 0 := by
rw [← Int.mul_ediv_cancel' h, H, Int.mul_zero]
theorem sub_ediv_of_dvd_sub {a b c : Int}
(hcab : c a - b) : (a - b) / c = a / c - b / c := by
rw [← Int.add_sub_cancel ((a - b) / c), ← Int.add_ediv_of_dvd_left hcab, Int.sub_add_cancel]
@[simp] protected theorem ediv_left_inj {a b d : Int}
(hda : d a) (hdb : d b) : a / d = b / d ↔ a = b := by
refine ⟨fun h => ?_, congrArg (ediv · d)⟩
rw [← Int.mul_ediv_cancel' hda, ← Int.mul_ediv_cancel' hdb, h]
theorem ediv_sign : ∀ a b, a / sign b = a * sign b
| _, succ _ => by simp [sign, Int.mul_one]
| _, 0 => by simp [sign, Int.mul_zero]
| _, -[_+1] => by simp [sign, Int.mul_neg, Int.mul_one]
protected theorem sign_eq_ediv_natAbs (a : Int) : sign a = a / (natAbs a) :=
if az : a = 0 then by simp [az] else
(Int.ediv_eq_of_eq_mul_left (ofNat_ne_zero.2 <| natAbs_ne_zero.2 az)
(sign_mul_natAbs _).symm).symm
theorem dvd_mul_of_ediv_dvd {a b c : Int} (h : b a) (hdiv : a / b c) : a b * c := by
obtain ⟨e, rfl⟩ := hdiv
rw [← Int.mul_assoc, Int.mul_comm _ (a / b), Int.ediv_mul_cancel h]
exact Int.dvd_mul_right a e
@[simp] theorem ediv_dvd_iff_dvd_mul {a b c : Int} (h : b a) (hb : b ≠ 0) : a / b c ↔ a b * c :=
exists_congr <| fun d ↦ by
have := Int.dvd_trans (Int.dvd_mul_left _ _) (Int.mul_dvd_mul_left d h)
rw [eq_comm, Int.mul_comm, ← Int.mul_ediv_assoc d h, Int.ediv_eq_iff_eq_mul_right hb this,
Int.mul_comm, eq_comm]
theorem mul_dvd_of_dvd_ediv {a b c : Int} (hcb : c b) (h : a b / c) : c * a b :=
have ⟨d, hd⟩ := h
⟨d, by simpa [Int.mul_comm, Int.mul_left_comm] using Int.eq_mul_of_ediv_eq_left hcb hd⟩
theorem dvd_ediv_of_mul_dvd {a b c : Int} (h : a * b c) : b c / a := by
obtain rfl | ha := Decidable.em (a = 0)
· simp
· obtain ⟨d, rfl⟩ := h
simp [Int.mul_assoc, ha]
@[simp] theorem dvd_ediv_iff_mul_dvd {a b c : Int} (hbc : c b) : a b / c ↔ c * a b :=
⟨mul_dvd_of_dvd_ediv hbc, dvd_ediv_of_mul_dvd⟩
theorem ediv_dvd_ediv : ∀ {a b c : Int}, a b → b c → b / a c / a
| a, _, _, ⟨b, rfl⟩, ⟨c, rfl⟩ =>
if az : a = 0 then by simp [az]
else by
rw [Int.mul_ediv_cancel_left _ az, Int.mul_assoc, Int.mul_ediv_cancel_left _ az]
apply Int.dvd_mul_right
theorem ediv_dvd_of_dvd {m n : Int} (hmn : m n) : n / m n := by
obtain rfl | hm := Decidable.em (m = 0)
· simpa using hmn
· obtain ⟨a, ha⟩ := hmn
simp [ha, Int.mul_ediv_cancel_left _ hm, Int.dvd_mul_left]
theorem emod_natAbs_of_nonneg {x : Int} (h : 0 ≤ x) {n : Nat} :
x.natAbs % n = (x % n).toNat := by
match x, h with
| (x : Nat), _ => rw [Int.natAbs_natCast, Int.ofNat_mod_ofNat, Int.toNat_natCast]
theorem emod_natAbs_of_neg {x : Int} (h : x < 0) {n : Nat} (w : n ≠ 0) :
x.natAbs % n = if (n : Int) x then 0 else n - (x % n).toNat := by
match x, h with
| -(x + 1 : Nat), _ =>
rw [Int.natAbs_neg]
rw [Int.natAbs_cast]
rw [Int.neg_emod]
simp only [Int.dvd_neg]
simp only [Int.natCast_dvd_natCast]
split <;> rename_i h
· rw [Nat.mod_eq_zero_of_dvd h]
· rw [← Int.natCast_emod]
simp only [Int.natAbs_natCast]
have : (x + 1) % n < n := Nat.mod_lt (x + 1) (by omega)
omega
/-! ### `/` and ordering -/
protected theorem ediv_mul_le (a : Int) {b : Int} (H : b ≠ 0) : a / b * b ≤ a :=
Int.le_of_sub_nonneg <| by rw [Int.mul_comm, ← emod_def]; apply emod_nonneg _ H
protected theorem lt_ediv_mul (a : Int) {b : Int} (H : 0 < b) : a - b < a / b * b := by
rw [ediv_mul_self, Int.sub_lt_sub_left_iff]
exact emod_lt_of_pos a H
theorem le_of_mul_le_mul_left {a b c : Int} (w : a * b ≤ a * c) (h : 0 < a) : b ≤ c := by
have w := Int.sub_nonneg_of_le w
rw [← Int.mul_sub] at w
have w := Int.ediv_nonneg w (Int.le_of_lt h)
rw [Int.mul_ediv_cancel_left _ (Int.ne_of_gt h)] at w
exact Int.le_of_sub_nonneg w
theorem le_of_mul_le_mul_right {a b c : Int} (w : b * a ≤ c * a) (h : 0 < a) : b ≤ c := by
rw [Int.mul_comm b, Int.mul_comm c] at w
exact le_of_mul_le_mul_left w h
protected theorem mul_le_mul_iff_of_pos_right {a b c : Int} (ha : 0 < a) : b * a ≤ c * a ↔ b ≤ c :=
⟨(le_of_mul_le_mul_right · ha), (Int.mul_le_mul_of_nonneg_right · (Int.le_of_lt ha))⟩
protected theorem mul_nonneg_iff_of_pos_right {a b : Int} (hb : 0 < b) : 0 ≤ a * b ↔ 0 ≤ a := by
simpa using (Int.mul_le_mul_iff_of_pos_right hb : 0 * b ≤ a * b ↔ 0 ≤ a)
protected theorem ediv_le_of_le_mul {a b c : Int} (H : 0 < c) (H' : a ≤ b * c) : a / c ≤ b :=
le_of_mul_le_mul_right (Int.le_trans (Int.ediv_mul_le _ (Int.ne_of_gt H)) H') H
protected theorem ediv_nonpos_of_nonpos_of_neg {n s : Int} (h : n ≤ 0) (h2 : 0 < s) : n / s ≤ 0 :=
Int.ediv_le_of_le_mul h2 (by simp [h])
protected theorem mul_lt_of_lt_ediv {a b c : Int} (H : 0 < c) (H3 : a < b / c) : a * c < b :=
Int.lt_of_not_ge <| mt (Int.ediv_le_of_le_mul H) (Int.not_le_of_gt H3)
protected theorem mul_le_of_le_ediv {a b c : Int} (H1 : 0 < c) (H2 : a ≤ b / c) : a * c ≤ b :=
Int.le_trans (Int.mul_le_mul_of_nonneg_right H2 (Int.le_of_lt H1))
(Int.ediv_mul_le _ (Int.ne_of_gt H1))
protected theorem ediv_lt_of_lt_mul {a b c : Int} (H : 0 < c) (H' : a < b * c) : a / c < b :=
Int.lt_of_not_ge <| mt (Int.mul_le_of_le_ediv H) (Int.not_le_of_gt H')
theorem lt_of_mul_lt_mul_left {a b c : Int} (w : a * b < a * c) (h : 0 ≤ a) : b < c := by
rcases Int.lt_trichotomy b c with lt | rfl | gt
· exact lt
· exact False.elim (Int.lt_irrefl _ w)
· rcases Int.lt_trichotomy a 0 with a_lt | rfl | a_gt
· exact False.elim (Int.lt_irrefl _ (Int.lt_of_lt_of_le a_lt h))
· exact False.elim (Int.lt_irrefl b (by simp at w))
· have := le_of_mul_le_mul_left (Int.le_of_lt w) a_gt
exact False.elim (Int.lt_irrefl _ (Int.lt_of_lt_of_le gt this))
theorem lt_of_mul_lt_mul_right {a b c : Int} (w : b * a < c * a) (h : 0 ≤ a) : b < c := by
rw [Int.mul_comm b, Int.mul_comm c] at w
exact lt_of_mul_lt_mul_left w h
protected theorem le_ediv_of_mul_le {a b c : Int} (H1 : 0 < c) (H2 : a * c ≤ b) : a ≤ b / c :=
le_of_lt_add_one <|
lt_of_mul_lt_mul_right (Int.lt_of_le_of_lt H2 (lt_ediv_add_one_mul_self _ H1)) (Int.le_of_lt H1)
protected theorem le_ediv_iff_mul_le {a b c : Int} (H : 0 < c) : a ≤ b / c ↔ a * c ≤ b :=
⟨Int.mul_le_of_le_ediv H, Int.le_ediv_of_mul_le H⟩
protected theorem lt_mul_of_ediv_lt {a b c : Int} (H1 : 0 < c) (H2 : a / c < b) : a < b * c :=
Int.lt_of_not_ge <| mt (Int.le_ediv_of_mul_le H1) (Int.not_le_of_gt H2)
protected theorem ediv_lt_iff_lt_mul {a b c : Int} (H : 0 < c) : a / c < b ↔ a < b * c :=
⟨Int.lt_mul_of_ediv_lt H, Int.ediv_lt_of_lt_mul H⟩
theorem ediv_le_iff_le_mul {k x y : Int} (h : 0 < k) : x / k ≤ y ↔ x < y * k + k := by
rw [Int.le_iff_lt_add_one, Int.ediv_lt_iff_lt_mul h, Int.add_mul]
omega
protected theorem le_mul_of_ediv_le {a b c : Int} (H1 : 0 ≤ b) (H2 : b a) (H3 : a / b ≤ c) :
a ≤ c * b := by
rw [← Int.ediv_mul_cancel H2]; exact Int.mul_le_mul_of_nonneg_right H3 H1
protected theorem lt_ediv_of_mul_lt {a b c : Int} (H1 : 0 ≤ b) (H2 : b c) (H3 : a * b < c) :
a < c / b :=
Int.lt_of_not_ge <| mt (Int.le_mul_of_ediv_le H1 H2) (Int.not_le_of_gt H3)
protected theorem lt_ediv_iff_mul_lt {a b : Int} {c : Int} (H : 0 < c) (H' : c b) :
a < b / c ↔ a * c < b :=
⟨Int.mul_lt_of_lt_ediv H, Int.lt_ediv_of_mul_lt (Int.le_of_lt H) H'⟩
theorem ediv_pos_of_pos_of_dvd {a b : Int} (H1 : 0 < a) (H2 : 0 ≤ b) (H3 : b a) : 0 < a / b :=
Int.lt_ediv_of_mul_lt H2 H3 (by rwa [Int.zero_mul])
theorem ediv_eq_ediv_of_mul_eq_mul {a b c d : Int}
(H2 : d c) (H3 : b ≠ 0) (H4 : d ≠ 0) (H5 : a * d = b * c) : a / b = c / d :=
Int.ediv_eq_of_eq_mul_right H3 <| by
rw [← Int.mul_ediv_assoc _ H2]; exact (Int.ediv_eq_of_eq_mul_left H4 H5.symm).symm
theorem ediv_eq_iff_of_pos {k x y : Int} (h : 0 < k) : x / k = y ↔ y * k ≤ x ∧ x < y * k + k := by
rw [Int.eq_iff_le_and_ge, and_comm, Int.le_ediv_iff_mul_le h, Int.ediv_le_iff_le_mul h]
theorem add_ediv_of_pos {a b c : Int} (h : 0 < c) :
(a + b) / c = a / c + b / c + if c ≤ a % c + b % c then 1 else 0 := by
have h' : c ≠ 0 := by omega
conv => lhs; rw [← Int.mul_ediv_add_emod a c]
rw [Int.add_assoc, Int.mul_add_ediv_left _ _ h']
conv => lhs; rw [← Int.mul_ediv_add_emod b c]
rw [Int.add_comm (a % c), Int.add_assoc, Int.mul_add_ediv_left _ _ h',
← Int.add_assoc, Int.add_comm (b % c)]
congr
rw [Int.ediv_eq_iff_of_pos h]
have := emod_lt_of_pos a h
have := emod_lt_of_pos b h
constructor
· have := emod_nonneg a h'
have := emod_nonneg b h'
split <;> · simp; omega
· split <;> · simp; omega
theorem add_ediv {a b c : Int} (h : c ≠ 0) :
(a + b) / c = a / c + b / c + if c.natAbs ≤ a % c + b % c then c.sign else 0 := by
induction c using wlog_sign
case inv => simp; omega
rename_i c
norm_cast at h
have : 0 < (c : Int) := by omega
simp [sign_natCast_of_ne_zero h, add_ediv_of_pos this]
protected theorem ediv_le_ediv {a b c : Int} (H : 0 < c) (H' : a ≤ b) : a / c ≤ b / c :=
Int.le_ediv_of_mul_le H (Int.le_trans (Int.ediv_mul_le _ (Int.ne_of_gt H)) H')
/-- If `n > 0` then `m` is not divisible by `n` iff it is between `n * k` and `n * (k + 1)`
for some `k`. -/
theorem not_dvd_iff_lt_mul_succ (m : Int) (hn : 0 < n) :
¬n m ↔ (∃ k, n * k < m ∧ m < n * (k + 1)) := by
refine ⟨fun h ↦ ?_, ?_⟩
· rw [dvd_iff_emod_eq_zero, ← Ne] at h
rw [← emod_add_mul_ediv m n]
refine ⟨m / n, Int.lt_add_of_pos_left _ ?_, ?_⟩
· have := emod_nonneg m (Int.ne_of_gt hn)
omega
· rw [Int.add_comm _ (1 : Int), Int.mul_add, Int.mul_one]
exact Int.add_lt_add_right (emod_lt_of_pos _ hn) _
· rintro ⟨k, h1k, h2k⟩ ⟨l, rfl⟩
replace h1k := lt_of_mul_lt_mul_left h1k (by omega)
replace h2k := lt_of_mul_lt_mul_left h2k (by omega)
rw [Int.lt_add_one_iff, ← Int.not_lt] at h2k
exact h2k h1k
private theorem ediv_ediv_of_pos {x y z : Int} (hy : 0 < y) (hz : 0 < z) :
x / y / z = x / (y * z) := by
rw [eq_comm, Int.ediv_eq_iff_of_pos (Int.mul_pos hy hz)]
constructor
· rw [Int.mul_comm y, ← Int.mul_assoc]
exact Int.le_trans
(Int.mul_le_mul_of_nonneg_right (Int.ediv_mul_le _ (Int.ne_of_gt hz)) (Int.le_of_lt hy))
(Int.ediv_mul_le x (Int.ne_of_gt hy))
· rw [Int.mul_comm y, ← Int.mul_assoc, ← Int.add_mul, Int.mul_comm _ z]
exact Int.lt_mul_of_ediv_lt hy (Int.lt_mul_ediv_self_add hz)
theorem ediv_ediv {x y z : Int} (hy : 0 ≤ y) : x / y / z = x / (y * z) := by
rcases y with (_ | a) | a
· simp
· rcases z with (_ | b) | b
· simp
· simp [ediv_ediv_of_pos]
· simp [Int.negSucc_eq, Int.mul_neg, ediv_ediv_of_pos]
· simp at hy
/-! ### tdiv -/
-- `tdiv` analogues of `ediv` lemmas from `Bootstrap.lean`
@[simp] protected theorem tdiv_neg : ∀ a b : Int, a.tdiv (-b) = -(a.tdiv b)
| ofNat m, 0 => show ofNat (m / 0) = -↑(m / 0) by rw [Nat.div_zero]; rfl
| ofNat _, -[_+1] | -[_+1], succ _ => (Int.neg_neg _).symm
| ofNat _, succ _ | -[_+1], 0 => by simp [Int.tdiv, Int.neg_zero, ← Int.negSucc_eq]
| -[_+1], -[_+1] => by simp only [tdiv, neg_negSucc]
/-!
There are no lemmas
* `add_mul_tdiv_right : c ≠ 0 → (a + b * c).tdiv c = a.tdiv c + b`
* `add_mul_tdiv_left : b ≠ 0 → (a + b * c).tdiv b = a.tdiv b + c`
* (similarly `mul_add_tdiv_right`, `mul_add_tdiv_left`)
* `add_tdiv_of_dvd_right : c b → (a + b).tdiv c = a.tdiv c + b.tdiv c`
* `add_tdiv_of_dvd_left : c a → (a + b).tdiv c = a.tdiv c + b.tdiv c`
because these statements are all incorrect, and require awkward conditional off-by-one corrections.
-/
@[simp] theorem mul_tdiv_cancel (a : Int) {b : Int} (H : b ≠ 0) : (a * b).tdiv b = a := by
rw [tdiv_eq_ediv_of_dvd (Int.dvd_mul_left a b), mul_ediv_cancel _ H]
@[simp] theorem mul_tdiv_cancel_left (b : Int) (H : a ≠ 0) : (a * b).tdiv a = b :=
Int.mul_comm .. ▸ Int.mul_tdiv_cancel _ H
-- `tdiv` analogues of `ediv` lemmas given above
-- There are no lemmas `tdiv_nonneg_iff_of_pos`, `tdiv_neg_of_neg_of_pos`, or `negSucc_tdiv`
-- corresponding to `ediv_nonneg_iff_of_pos`, `ediv_neg_of_neg_of_pos`, or `negSucc_ediv` as they require awkward corrections.
protected theorem tdiv_nonneg {a b : Int} (Ha : 0 ≤ a) (Hb : 0 ≤ b) : 0 ≤ a.tdiv b :=
match a, b, eq_ofNat_of_zero_le Ha, eq_ofNat_of_zero_le Hb with
| _, _, ⟨_, rfl⟩, ⟨_, rfl⟩ => ofNat_zero_le _
theorem tdiv_nonneg_of_nonpos_of_nonpos {a b : Int} (Ha : a ≤ 0) (Hb : b ≤ 0) : 0 ≤ a.tdiv b := by
rw [tdiv_eq_ediv]
split <;> rename_i h
· simpa using ediv_nonneg_of_nonpos_of_nonpos Ha Hb
· simp at h
by_cases h' : b = 0
· subst h'
simp
· replace h' : b < 0 := by omega
rw [sign_eq_neg_one_of_neg h']
have : 0 < a / b := by
by_cases h'' : a = 0
· subst h''
simp at h
· replace h'' : a < 0 := by omega
exact ediv_pos_of_neg_of_neg h'' h'
omega
protected theorem tdiv_nonpos_of_nonneg_of_nonpos {a b : Int} (Ha : 0 ≤ a) (Hb : b ≤ 0) : a.tdiv b ≤ 0 :=
Int.nonpos_of_neg_nonneg <| Int.tdiv_neg .. ▸ Int.tdiv_nonneg Ha (Int.neg_nonneg_of_nonpos Hb)
@[deprecated Int.tdiv_nonpos_of_nonneg_of_nonpos (since := "2025-03-04")]
abbrev tdiv_nonpos := @Int.tdiv_nonpos_of_nonneg_of_nonpos
theorem tdiv_eq_zero_of_lt {a b : Int} (H1 : 0 ≤ a) (H2 : a < b) : a.tdiv b = 0 :=
match a, b, eq_ofNat_of_zero_le H1, eq_succ_of_zero_lt (Int.lt_of_le_of_lt H1 H2) with
| _, _, ⟨_, rfl⟩, ⟨_, rfl⟩ => congrArg Nat.cast <| Nat.div_eq_of_lt <| ofNat_lt.1 H2
@[simp] theorem mul_tdiv_mul_of_pos {a : Int}
(b c : Int) (H : 0 < a) : (a * b).tdiv (a * c) = b.tdiv c := by
rw [tdiv_eq_ediv, mul_ediv_mul_of_pos _ _ H, tdiv_eq_ediv]
simp only [sign_mul]
by_cases h : 0 ≤ b
· rw [if_pos, if_pos (.inl h)]
left
exact Int.mul_nonneg (Int.le_of_lt H) h
· have H' : a ≠ 0 := by omega
simp only [Int.mul_dvd_mul_iff_left H']
by_cases h' : c b
· simp [h']
· rw [if_neg, if_neg]
· simp [sign_eq_one_of_pos H]
· simp [h']; omega
· simp_all only [Int.not_le, ne_eq, or_false]
exact Int.mul_neg_of_pos_of_neg H h
@[simp] theorem mul_tdiv_mul_of_pos_left
(a : Int) {b : Int} (c : Int) (H : 0 < b) : (a * b).tdiv (c * b) = a.tdiv c := by
rw [Int.mul_comm, Int.mul_comm c, mul_tdiv_mul_of_pos _ _ H]
protected theorem tdiv_eq_of_eq_mul_right {a b c : Int}
(H1 : b ≠ 0) (H2 : a = b * c) : a.tdiv b = c := by rw [H2, Int.mul_tdiv_cancel_left _ H1]
protected theorem eq_tdiv_of_mul_eq_right {a b c : Int}
(H1 : a ≠ 0) (H2 : a * b = c) : b = c.tdiv a :=
(Int.tdiv_eq_of_eq_mul_right H1 H2.symm).symm
protected theorem tdiv_eq_of_eq_mul_left {a b c : Int}
(H1 : b ≠ 0) (H2 : a = c * b) : a.tdiv b = c :=
Int.tdiv_eq_of_eq_mul_right H1 (by rw [Int.mul_comm, H2])
protected theorem eq_tdiv_of_mul_eq_left {a b c : Int}
(H1 : b ≠ 0) (H2 : a * b = c) : a = c.tdiv b :=
(Int.tdiv_eq_of_eq_mul_left H1 H2.symm).symm
@[simp] protected theorem tdiv_self {a : Int} (H : a ≠ 0) : a.tdiv a = 1 := by
have := Int.mul_tdiv_cancel 1 H; rwa [Int.one_mul] at this
@[simp] protected theorem neg_tdiv : ∀ a b : Int, (-a).tdiv b = -(a.tdiv b)
| 0, n => by simp [Int.neg_zero]
| succ _, (n:Nat) => by simp [tdiv, ← Int.negSucc_eq]
| -[_+1], 0 | -[_+1], -[_+1] => by
simp only [tdiv, neg_negSucc, Int.neg_neg]
| succ _, -[_+1] | -[_+1], succ _ => (Int.neg_neg _).symm
protected theorem neg_tdiv_neg (a b : Int) : (-a).tdiv (-b) = a.tdiv b := by
simp [Int.tdiv_neg, Int.neg_tdiv, Int.neg_neg]
theorem sign_tdiv (a b : Int) : sign (a.tdiv b) = if natAbs a < natAbs b then 0 else sign a * sign b := by
induction b using wlog_sign
case inv => simp; split <;> simp [Int.mul_neg]
case w b =>
induction a using wlog_sign
case inv => simp; split <;> simp [Int.neg_mul]
case w a =>
rw [tdiv_eq_ediv_of_nonneg (by simp), sign_ediv]
simp
@[simp] theorem natAbs_tdiv (a b : Int) : natAbs (a.tdiv b) = (natAbs a).div (natAbs b) :=
match a, b, Int.eq_nat_or_neg a, Int.eq_nat_or_neg b with
| _, _, ⟨_, .inl rfl⟩, ⟨_, .inl rfl⟩ => rfl
| _, _, ⟨_, .inl rfl⟩, ⟨_, .inr rfl⟩ => by rw [Int.tdiv_neg, natAbs_neg, natAbs_neg]; rfl
| _, _, ⟨_, .inr rfl⟩, ⟨_, .inl rfl⟩ => by rw [Int.neg_tdiv, natAbs_neg, natAbs_neg]; rfl
| _, _, ⟨_, .inr rfl⟩, ⟨_, .inr rfl⟩ => by rw [Int.neg_tdiv_neg, natAbs_neg, natAbs_neg]; rfl
/-! ### tmod -/
-- `tmod` analogues of `emod` lemmas from `Bootstrap.lean`
theorem ofNat_tmod (m n : Nat) : (↑(m % n) : Int) = tmod m n := rfl
theorem tmod_nonneg : ∀ {a : Int} (b : Int), 0 ≤ a → 0 ≤ tmod a b
| ofNat _, -[_+1], _ | ofNat _, ofNat _, _ => natCast_nonneg _
@[simp] theorem tmod_neg (a b : Int) : tmod a (-b) = tmod a b := by
rw [tmod_def, tmod_def, Int.tdiv_neg, Int.neg_mul_neg]
@[simp] theorem neg_tmod (a b : Int) : tmod (-a) b = -tmod a b := by
rw [tmod_def, Int.neg_tdiv, Int.mul_neg, tmod_def]
omega
theorem tmod_lt_of_pos (a : Int) {b : Int} (H : 0 < b) : tmod a b < b :=
match a, b, eq_succ_of_zero_lt H with
| ofNat _, _, ⟨n, rfl⟩ => ofNat_lt.2 <| Nat.mod_lt _ n.succ_pos
| -[_+1], _, ⟨n, rfl⟩ => Int.lt_of_le_of_lt
(Int.neg_nonpos_of_nonneg <| natCast_nonneg _) (natCast_pos.2 n.succ_pos)
theorem lt_tmod_of_pos (a : Int) {b : Int} (H : 0 < b) : -b < tmod a b :=
match a, b, eq_succ_of_zero_lt H with
| ofNat _, _, ⟨n, rfl⟩ => by rw [ofNat_eq_coe, ← Int.natCast_succ, ← ofNat_tmod]; omega
| -[a+1], _, ⟨n, rfl⟩ => by
rw [negSucc_eq, neg_tmod, ← Int.natCast_add_one, ← Int.natCast_add_one, ← ofNat_tmod]
have : (a + 1) % (n + 1) < n + 1 := Nat.mod_lt _ (Nat.zero_lt_succ n)
omega
-- The following statements for `tmod` are false:
-- `add_mul_tmod_self_right {a b c : Int} : (a + b * c).tmod c = a.tmod c`
-- `add_mul_tmod_self_left (a b c : Int) : (a + b * c).tmod b = a.tmod b`
-- `tmod_add_tmod (m n k : Int) : (m.tmod n + k).tmod n = (m + k).tmod n`
-- `add_tmod_tmod (m n k : Int) : (m + n.tmod k).tmod k = (m + n).tmod k`
-- `add_tmod (a b n : Int) : (a + b).tmod n = (a.tmod n + b.tmod n).tmod n`
-- `add_tmod_eq_add_tmod_right {m n k : Int} (i : Int) : (m.tmod n = k.tmod n) → (m + i).tmod n = (k + i).tmod n`
-- `tmod_add_cancel_right {m n k : Int} (i) : (m + i).tmod n = (k + i).tmod n ↔ m.tmod n = k.tmod n`
-- `sub_tmod (a b n : Int) : (a - b).tmod n = (a.tmod n - b.tmod n).tmod n`
@[simp] theorem mul_tmod_left (a b : Int) : (a * b).tmod b = 0 :=
if h : b = 0 then by simp [h, Int.mul_zero] else by
rw [Int.tmod_def, Int.mul_tdiv_cancel _ h, Int.mul_comm, Int.sub_self]
@[simp] theorem mul_tmod_right (a b : Int) : (a * b).tmod a = 0 := by
rw [Int.mul_comm, mul_tmod_left]
theorem mul_tmod (a b n : Int) : (a * b).tmod n = (a.tmod n * b.tmod n).tmod n := by
induction a using wlog_sign
case inv => simp [Int.neg_mul]
induction b using wlog_sign
case inv => simp [Int.mul_neg]
induction n using wlog_sign
case inv => simp
simp only [← Int.natCast_mul, ← ofNat_tmod]
rw [Nat.mul_mod]
@[simp] theorem tmod_self {a : Int} : a.tmod a = 0 := by
have := mul_tmod_left 1 a; rwa [Int.one_mul] at this
@[simp] theorem tmod_tmod_of_dvd (n : Int) {m k : Int}
(h : m k) : (n.tmod k).tmod m = n.tmod m := by
induction n using wlog_sign
case inv => simp
induction k using wlog_sign
case inv => simp [Int.dvd_neg]
induction m using wlog_sign
case inv => simp
simp only [← ofNat_tmod]
norm_cast at h
rw [Nat.mod_mod_of_dvd _ h]
theorem tmod_tmod (a b : Int) : (a.tmod b).tmod b = a.tmod b := by simp
theorem tmod_eq_zero_of_dvd : ∀ {a b : Int}, a b → tmod b a = 0
| _, _, ⟨_, rfl⟩ => mul_tmod_right ..
-- `tmod` analogues of `emod` lemmas from above
theorem tmod_eq_of_lt {a b : Int} (H1 : 0 ≤ a) (H2 : a < b) : tmod a b = a := by
rw [tmod_eq_emod_of_nonneg H1, emod_eq_of_lt H1 H2]
theorem sign_tmod (a b : Int) : sign (tmod a b) = if b a then 0 else sign a := by
if hb : b = 0 then
subst hb
split <;> simp_all
else
induction a using wlog_sign
case inv a => split <;> simp_all
rename_i a
match a with
| 0 => simp
| (a + 1) =>
simp
split
· simp [tmod_eq_zero_of_dvd, *]
· norm_cast
rw [tmod_eq_emod_of_nonneg (by omega)]
rw [sign_emod _ hb]
simp_all
@[simp] theorem natAbs_tmod (a b : Int) : natAbs (tmod a b) = natAbs a % natAbs b := by
induction a using wlog_sign
case inv => simp
induction b using wlog_sign
case inv => simp
norm_cast
/-! properties of `tdiv` and `tmod` -/
-- Analogues of statements about `ediv` and `emod` from `Bootstrap.lean`
theorem mul_tdiv_cancel_of_tmod_eq_zero {a b : Int} (H : a.tmod b = 0) : b * (a.tdiv b) = a := by
have := tmod_add_mul_tdiv a b; rwa [H, Int.zero_add] at this
theorem tdiv_mul_cancel_of_tmod_eq_zero {a b : Int} (H : a.tmod b = 0) : a.tdiv b * b = a := by
rw [Int.mul_comm, mul_tdiv_cancel_of_tmod_eq_zero H]
theorem dvd_of_tmod_eq_zero {a b : Int} (H : tmod b a = 0) : a b :=
⟨b.tdiv a, (mul_tdiv_cancel_of_tmod_eq_zero H).symm⟩
theorem dvd_iff_tmod_eq_zero {a b : Int} : a b ↔ tmod b a = 0 :=
⟨tmod_eq_zero_of_dvd, dvd_of_tmod_eq_zero⟩
protected theorem tdiv_mul_cancel {a b : Int} (H : b a) : a.tdiv b * b = a :=
tdiv_mul_cancel_of_tmod_eq_zero (tmod_eq_zero_of_dvd H)
protected theorem mul_tdiv_cancel' {a b : Int} (H : a b) : a * b.tdiv a = b := by
rw [Int.mul_comm, Int.tdiv_mul_cancel H]
theorem neg_tmod_self (a : Int) : (-a).tmod a = 0 := by
simp
theorem lt_tdiv_add_one_mul_self (a : Int) {b : Int} (H : 0 < b) : a < (a.tdiv b + 1) * b := by
rw [Int.add_mul, Int.one_mul, Int.mul_comm]
exact Int.lt_add_of_sub_left_lt <| Int.tmod_def .. ▸ tmod_lt_of_pos _ H
protected theorem mul_tdiv_assoc (a : Int) : ∀ {b c : Int}, c b → (a * b).tdiv c = a * (b.tdiv c)
| _, c, ⟨d, rfl⟩ =>
if cz : c = 0 then by simp [cz, Int.mul_zero] else by
rw [Int.mul_left_comm, Int.mul_tdiv_cancel_left _ cz, Int.mul_tdiv_cancel_left _ cz]
protected theorem mul_tdiv_assoc' (b : Int) {a c : Int} (h : c a) :
(a * b).tdiv c = a.tdiv c * b := by
rw [Int.mul_comm, Int.mul_tdiv_assoc _ h, Int.mul_comm]
theorem neg_tdiv_of_dvd : ∀ {a b : Int}, b a → (-a).tdiv b = -(a.tdiv b)
| _, b, ⟨c, rfl⟩ => by
by_cases bz : b = 0
· simp [bz]
· rw [Int.neg_mul_eq_mul_neg, Int.mul_tdiv_cancel_left _ bz, Int.mul_tdiv_cancel_left _ bz]
-- `sub_tdiv_of_dvd (a : Int) {b c : Int} (hcb : c b) : (a - b).tdiv c = a.tdiv c - b.tdiv c` is false in general
theorem tdiv_dvd_tdiv : ∀ {a b c : Int}, a b → b c → b.tdiv a c.tdiv a
| a, _, _, ⟨b, rfl⟩, ⟨c, rfl⟩ => by
by_cases az : a = 0
· simp [az]
· rw [Int.mul_tdiv_cancel_left _ az, Int.mul_assoc, Int.mul_tdiv_cancel_left _ az]
apply Int.dvd_mul_right
-- Analogues of statements about `emod` and `ediv` from above.
theorem mul_tdiv_cancel_of_dvd {a b : Int} (H : b a) : b * (a.tdiv b) = a :=
mul_tdiv_cancel_of_tmod_eq_zero (tmod_eq_zero_of_dvd H)
theorem tdiv_mul_cancel_of_dvd {a b : Int} (H : b a) : a.tdiv b * b = a :=
tdiv_mul_cancel_of_tmod_eq_zero (tmod_eq_zero_of_dvd H)
theorem tmod_two_eq (x : Int) : x.tmod 2 = -1 x.tmod 2 = 0 x.tmod 2 = 1 := by
have h₁ : -2 < x.tmod 2 := Int.lt_tmod_of_pos x (by decide)
have h₂ : x.tmod 2 < 2 := Int.tmod_lt_of_pos x (by decide)
match x.tmod 2, h₁, h₂ with
| -1, _, _ => simp
| 0, _, _ => simp
| 1, _, _ => simp
-- The following statements about `tmod` are false:
-- `add_tmod_eq_add_tmod_left {m n k : Int} (i : Int) (H : m.tmod n = k.tmod n) : (i + m).tmod n = (i + k).tmod n`
-- `tmod_add_cancel_left {m n k i : Int} : (i + m).tmod n = (i + k).tmod n ↔ m.tmod n = k.tmod n`
-- `tmod_sub_cancel_right {m n k : Int} (i) : (m - i).tmod n = (k - i).tmod n ↔ m.tmod n = k.tmod n`
-- `tmod_eq_tmod_iff_tmod_sub_eq_zero {m n k : Int} : m.tmod n = k.tmod n ↔ (m - k).tmod n = 0`
protected theorem tdiv_tmod_unique {a b r q : Int} (ha : 0 ≤ a) (hb : b ≠ 0) :
a.tdiv b = q ∧ a.tmod b = r ↔ r + b * q = a ∧ 0 ≤ r ∧ r < natAbs b := by
rw [tdiv_eq_ediv_of_nonneg ha, tmod_eq_emod_of_nonneg ha]
by_cases hb' : 0 < b
· rw [Int.ediv_emod_unique hb']
omega
· replace hb' : 0 < -b := by omega
have := Int.ediv_emod_unique (a := a) (q := -q) (r := r) hb'
simp at this
simp [this, Int.neg_mul, Int.mul_neg]
omega
protected theorem tdiv_tmod_unique' {a b r q : Int} (ha : a ≤ 0) (hb : b ≠ 0) :
a.tdiv b = q ∧ a.tmod b = r ↔ r + b * q = a ∧ -natAbs b < r ∧ r ≤ 0 := by
have := Int.tdiv_tmod_unique (a := -a) (q := -q) (r := -r) (by omega) hb
simp at this
simp [this, Int.mul_neg]
omega
@[simp] theorem mul_tmod_mul_of_pos
{a : Int} (b c : Int) (H : 0 < a) : (a * b).tmod (a * c) = a * (b.tmod c) := by
rw [tmod_def, tmod_def, mul_tdiv_mul_of_pos _ _ H, Int.mul_sub, Int.mul_assoc]
theorem natAbs_tdiv_le_natAbs (a b : Int) : natAbs (a.tdiv b) ≤ natAbs a := by
induction a using wlog_sign
case inv => simp
induction b using wlog_sign
case inv => simp
simpa using Nat.div_le_self _ _
theorem tdiv_le_self {a : Int} (b : Int) (Ha : 0 ≤ a) : a.tdiv b ≤ a := by
have := Int.le_trans le_natAbs (ofNat_le.2 <| natAbs_tdiv_le_natAbs a b)
rwa [natAbs_of_nonneg Ha] at this
theorem dvd_tmod_sub_self {x m : Int} : m x.tmod m - x := by
rw [tmod_eq_emod]
have := dvd_emod_sub_self (x := x) (m := m)
split
· simpa
· rw [Int.sub_sub, Int.add_comm, ← Int.sub_sub]
exact Int.dvd_sub this dvd_natAbs_self
theorem dvd_self_sub_tmod {x m : Int} : m x - x.tmod m :=
Int.dvd_neg.1 (by simpa only [Int.neg_sub] using dvd_tmod_sub_self)
theorem neg_mul_tmod_right (a b : Int) : (-(a * b)).tmod a = 0 := by
simp
theorem neg_mul_tmod_left (a b : Int) : (-(a * b)).tmod b = 0 := by
simp
@[simp] protected theorem tdiv_one : ∀ a : Int, a.tdiv 1 = a
| (n:Nat) => congrArg ofNat (Nat.div_one _)
| -[n+1] => by simp [Int.tdiv]; rfl
@[simp] theorem tmod_one (a : Int) : tmod a 1 = 0 := by
simp [tmod_def, Int.tdiv_one, Int.one_mul, Int.sub_self]
-- The following statements about `tmod` are false:
-- `tmod_sub_cancel (x y : Int) : (x - y).tmod y = x.tmod y`
-- `add_neg_tmod_self (a b : Int) : (a + -b).tmod b = a.tmod b`
-- `neg_add_tmod_self (a b : Int) : (-a + b).tmod a = b.tmod a`
theorem dvd_self_sub_of_tmod_eq {a b c : Int} (h : a.tmod b = c) : b a - c :=
h ▸ dvd_self_sub_tmod
theorem dvd_sub_self_of_tmod_eq {a b c : Int} (h : a.tmod b = c) : b c - a :=
h ▸ dvd_tmod_sub_self
protected theorem eq_mul_of_tdiv_eq_right {a b c : Int}
(H1 : b a) (H2 : a.tdiv b = c) : a = b * c := by rw [← H2, Int.mul_tdiv_cancel' H1]
protected theorem tdiv_eq_iff_eq_mul_right {a b c : Int}
(H : b ≠ 0) (H' : b a) : a.tdiv b = c ↔ a = b * c :=
⟨Int.eq_mul_of_tdiv_eq_right H', Int.tdiv_eq_of_eq_mul_right H⟩
protected theorem tdiv_eq_iff_eq_mul_left {a b c : Int}
(H : b ≠ 0) (H' : b a) : a.tdiv b = c ↔ a = c * b := by
rw [Int.mul_comm]; exact Int.tdiv_eq_iff_eq_mul_right H H'
protected theorem eq_mul_of_tdiv_eq_left {a b c : Int}
(H1 : b a) (H2 : a.tdiv b = c) : a = c * b := by
rw [Int.mul_comm, Int.eq_mul_of_tdiv_eq_right H1 H2]
protected theorem eq_zero_of_tdiv_eq_zero {d n : Int} (h : d n) (H : n.tdiv d = 0) : n = 0 := by
rw [← Int.mul_tdiv_cancel' h, H, Int.mul_zero]
-- `sub_tdiv_of_dvd_sub {a b c : Int} (hcab : c a - b) : (a - b).tdiv c = a.tdiv c - b.tdiv c` is false in general
@[simp] protected theorem tdiv_left_inj {a b d : Int}
(hda : d a) (hdb : d b) : a.tdiv d = b.tdiv d ↔ a = b := by
refine ⟨fun h => ?_, congrArg (tdiv · d)⟩
rw [← Int.mul_tdiv_cancel' hda, ← Int.mul_tdiv_cancel' hdb, h]
theorem tdiv_sign : ∀ a b, a.tdiv (sign b) = a * sign b
| _, succ _ => by simp [sign, Int.mul_one]
| _, 0 => by simp [sign, Int.mul_zero]
| _, -[_+1] => by simp [sign, Int.mul_neg, Int.mul_one]
protected theorem sign_eq_tdiv_abs (a : Int) : sign a = a.tdiv (natAbs a) :=
if az : a = 0 then by simp [az] else
(Int.tdiv_eq_of_eq_mul_left (ofNat_ne_zero.2 <| natAbs_ne_zero.2 az)
(sign_mul_natAbs _).symm).symm
@[simp high] protected theorem mul_le_mul_left {a b c : Int} (ha : 0 < a) : a * b ≤ a * c ↔ b ≤ c where
mp hbc := Int.le_of_mul_le_mul_left hbc ha
mpr hbc := Int.mul_le_mul_of_nonneg_left hbc <| Int.le_of_lt ha
@[simp high] protected theorem mul_le_mul_right {a b c : Int} (ha : 0 < a) : b * a ≤ c * a ↔ b ≤ c where
mp hbc := Int.le_of_mul_le_mul_right hbc ha
mpr hbc := Int.mul_le_mul_of_nonneg_right hbc <| Int.le_of_lt ha
@[simp high] protected theorem mul_lt_mul_left {a b c : Int} (ha : 0 < a) : a * b < a * c ↔ b < c where
mp hbc := Int.lt_of_mul_lt_mul_left hbc <| Int.le_of_lt ha
mpr hbc := Int.mul_lt_mul_of_pos_left hbc ha
@[simp high] protected theorem mul_lt_mul_right {a b c : Int} (ha : 0 < a) : b * a < c * a ↔ b < c where
mp hbc := Int.lt_of_mul_lt_mul_right hbc <| Int.le_of_lt ha
mpr hbc := Int.mul_lt_mul_of_pos_right hbc ha
@[simp high] protected theorem mul_le_mul_left_of_neg {a b c : Int} (ha : a < 0) :
a * b ≤ a * c ↔ c ≤ b := by
rw [← Int.neg_le_neg_iff, Int.neg_mul_eq_neg_mul, Int.neg_mul_eq_neg_mul,
Int.mul_le_mul_left <| Int.neg_pos.2 ha]
@[simp high] protected theorem mul_le_mul_right_of_neg {a b c : Int} (ha : a < 0) :
b * a ≤ c * a ↔ c ≤ b := by
rw [← Int.neg_le_neg_iff, Int.neg_mul_eq_mul_neg, Int.neg_mul_eq_mul_neg,
Int.mul_le_mul_right <| Int.neg_pos.2 ha]
@[simp high] protected theorem mul_lt_mul_left_of_neg {a b c : Int} (ha : a < 0) :
a * b < a * c ↔ c < b := by
rw [← Int.neg_lt_neg_iff, Int.neg_mul_eq_neg_mul, Int.neg_mul_eq_neg_mul,
Int.mul_lt_mul_left <| Int.neg_pos.2 ha]
@[simp high] protected theorem mul_lt_mul_right_of_neg {a b c : Int} (ha : a < 0) :
b * a < c * a ↔ c < b := by
rw [← Int.neg_lt_neg_iff, Int.neg_mul_eq_mul_neg, Int.neg_mul_eq_mul_neg,
Int.mul_lt_mul_right <| Int.neg_pos.2 ha]
theorem ediv_le_iff_of_dvd_of_pos {a b c : Int} (hb : 0 < b) (hba : b a) :
a / b ≤ c ↔ a ≤ b * c := by
obtain ⟨x, rfl⟩ := hba; simp [*, Int.ne_of_gt]
theorem ediv_le_iff_of_dvd_of_neg {a b c : Int} (hb : b < 0) (hba : b a) :
a / b ≤ c ↔ b * c ≤ a := by
obtain ⟨x, rfl⟩ := hba; simp [*, Int.ne_of_lt]
theorem ediv_lt_iff_of_dvd_of_pos {a b c : Int} (hb : 0 < b) (hba : b a) :
a / b < c ↔ a < b * c := by
obtain ⟨x, rfl⟩ := hba; simp [*, Int.ne_of_gt]
theorem ediv_lt_iff_of_dvd_of_neg {a b c : Int} (hb : b < 0) (hba : b a) :
a / b < c ↔ b * c < a := by
obtain ⟨x, rfl⟩ := hba; simp [*, Int.ne_of_lt]
theorem le_ediv_iff_of_dvd_of_pos {a b c : Int} (hc : 0 < c) (hcb : c b) :
a ≤ b / c ↔ c * a ≤ b := by
obtain ⟨x, rfl⟩ := hcb; simp [*, Int.ne_of_gt]
theorem le_ediv_iff_of_dvd_of_neg {a b c : Int} (hc : c < 0) (hcb : c b) :
a ≤ b / c ↔ b ≤ c * a := by
obtain ⟨x, rfl⟩ := hcb; simp [*, Int.ne_of_lt]
theorem lt_ediv_iff_of_dvd_of_pos {a b c : Int} (hc : 0 < c) (hcb : c b) :
a < b / c ↔ c * a < b := by
obtain ⟨x, rfl⟩ := hcb; simp [*, Int.ne_of_gt]
theorem lt_ediv_iff_of_dvd_of_neg {a b c : Int} (hc : c < 0) (hcb : c b) :
a < b / c ↔ b < c * a := by
obtain ⟨x, rfl⟩ := hcb; simp [*, Int.ne_of_lt]
theorem ediv_le_ediv_iff_of_dvd_of_pos_of_pos {a b c d : Int} (hb : 0 < b) (hd : 0 < d)
(hba : b a) (hdc : d c) : a / b ≤ c / d ↔ d * a ≤ c * b := by
obtain ⟨⟨x, rfl⟩, y, rfl⟩ := hba, hdc
simp [*, Int.ne_of_gt, d.mul_assoc, b.mul_comm]
theorem ediv_le_ediv_iff_of_dvd_of_pos_of_neg {a b c d : Int} (hb : 0 < b) (hd : d < 0)
(hba : b a) (hdc : d c) : a / b ≤ c / d ↔ c * b ≤ d * a := by
obtain ⟨⟨x, rfl⟩, y, rfl⟩ := hba, hdc
simp [*, Int.ne_of_lt, Int.ne_of_gt, d.mul_assoc, b.mul_comm]
theorem ediv_le_ediv_iff_of_dvd_of_neg_of_pos {a b c d : Int} (hb : b < 0) (hd : 0 < d)
(hba : b a) (hdc : d c) : a / b ≤ c / d ↔ c * b ≤ d * a := by
obtain ⟨⟨x, rfl⟩, y, rfl⟩ := hba, hdc
simp [*, Int.ne_of_lt, Int.ne_of_gt, d.mul_assoc, b.mul_comm]
theorem ediv_le_ediv_iff_of_dvd_of_neg_of_neg {a b c d : Int} (hb : b < 0) (hd : d < 0)
(hba : b a) (hdc : d c) : a / b ≤ c / d ↔ d * a ≤ c * b := by
obtain ⟨⟨x, rfl⟩, y, rfl⟩ := hba, hdc
simp [*, Int.ne_of_lt, d.mul_assoc, b.mul_comm]
theorem ediv_lt_ediv_iff_of_dvd_of_pos {a b c d : Int} (hb : 0 < b) (hd : 0 < d) (hba : b a)
(hdc : d c) : a / b < c / d ↔ d * a < c * b := by
obtain ⟨⟨x, rfl⟩, y, rfl⟩ := hba, hdc
simp [*, Int.ne_of_gt, d.mul_assoc, b.mul_comm]
theorem ediv_lt_ediv_iff_of_dvd_of_pos_of_neg {a b c d : Int} (hb : 0 < b) (hd : d < 0)
(hba : b a) (hdc : d c) : a / b < c / d ↔ c * b < d * a := by
obtain ⟨⟨x, rfl⟩, y, rfl⟩ := hba, hdc
simp [*, Int.ne_of_lt, Int.ne_of_gt, d.mul_assoc, b.mul_comm]
theorem ediv_lt_ediv_iff_of_dvd_of_neg_of_pos {a b c d : Int} (hb : b < 0) (hd : 0 < d)
(hba : b a) (hdc : d c) : a / b < c / d ↔ c * b < d * a := by
obtain ⟨⟨x, rfl⟩, y, rfl⟩ := hba, hdc
simp [*, Int.ne_of_lt, Int.ne_of_gt, d.mul_assoc, b.mul_comm]
theorem ediv_lt_ediv_iff_of_dvd_of_neg_of_neg {a b c d : Int} (hb : b < 0) (hd : d < 0)
(hba : b a) (hdc : d c) : a / b < c / d ↔ d * a < c * b := by
obtain ⟨⟨x, rfl⟩, y, rfl⟩ := hba, hdc
simp [*, Int.ne_of_lt, d.mul_assoc, b.mul_comm]
/-! ### `tdiv` and ordering -/
-- Theorems about `tdiv` and ordering, whose `ediv` analogues are in `Bootstrap.lean`.
theorem mul_tdiv_self_le {x k : Int} (h : 0 ≤ x) : k * (x.tdiv k) ≤ x := by
by_cases w : k = 0
· simp [w, h]
· rw [tdiv_eq_ediv_of_nonneg h]
apply mul_ediv_self_le w
theorem lt_mul_tdiv_self_add {x k : Int} (h : 0 < k) : x < k * (x.tdiv k) + k := by
rw [tdiv_eq_ediv, sign_eq_one_of_pos h]
have := lt_mul_ediv_self_add (x := x) h
split <;> simp [Int.mul_add] <;> omega
-- Theorems about `tdiv` and ordering, whose `ediv` analogues proved above.
protected theorem tdiv_mul_le (a : Int) {b : Int} (hb : b ≠ 0) : a.tdiv b * b ≤ a + if 0 ≤ a then 0 else (b.natAbs - 1) :=
Int.le_of_sub_nonneg <| by
rw [Int.mul_comm, Int.add_comm, Int.add_sub_assoc, ← tmod_def]
split
· simp_all [tmod_nonneg]
· match b, hb with
| .ofNat (b + 1), _ =>
have := lt_tmod_of_pos a (natCast_pos.2 (b.succ_pos))
simp_all
omega
| .negSucc b, _ =>
simp only [negSucc_eq, natAbs_neg, tmod_neg]
have := lt_tmod_of_pos (b := b + 1) a (by omega)
omega
protected theorem tdiv_le_of_le_mul {a b c : Int} (Hc : 0 < c) (H' : a ≤ b * c) : a.tdiv c ≤ b + if 0 ≤ a then 0 else 1 :=
le_of_mul_le_mul_right (Int.le_trans (Int.tdiv_mul_le _ (by omega))
(by
split
· simpa using H'
· simp [Int.add_mul]
omega)) Hc
-- We don't provide `tdiv` analogues of the lemmas
-- `mul_lt_of_lt_ediv`
-- `mul_le_of_le_ediv`
-- `ediv_lt_of_lt_mul`
-- `le_ediv_iff_mul_le`
-- `ediv_lt_iff_lt_mul`
-- `lt_ediv_iff_mul_lt`
-- as they would require quite awkward statements.
protected theorem le_tdiv_of_mul_le {a b c : Int} (H1 : 0 < c) (H2 : a * c ≤ b) : a ≤ b.tdiv c :=
le_of_lt_add_one <|
lt_of_mul_lt_mul_right (Int.lt_of_le_of_lt H2 (lt_tdiv_add_one_mul_self _ H1)) (Int.le_of_lt H1)
protected theorem lt_mul_of_tdiv_lt {a b c : Int} (H1 : 0 < c) (H2 : a.tdiv c < b) : a < b * c :=
Int.lt_of_not_ge <| mt (Int.le_tdiv_of_mul_le H1) (Int.not_le_of_gt H2)
protected theorem le_mul_of_tdiv_le {a b c : Int} (H1 : 0 ≤ b) (H2 : b a) (H3 : a.tdiv b ≤ c) :
a ≤ c * b := by
rw [← Int.tdiv_mul_cancel H2]; exact Int.mul_le_mul_of_nonneg_right H3 H1
protected theorem lt_tdiv_of_mul_lt {a b c : Int} (H1 : 0 ≤ b) (H2 : b c) (H3 : a * b < c) :
a < c.tdiv b :=
Int.lt_of_not_ge <| mt (Int.le_mul_of_tdiv_le H1 H2) (Int.not_le_of_gt H3)
theorem tdiv_pos_of_pos_of_dvd {a b : Int} (H1 : 0 < a) (H2 : 0 ≤ b) (H3 : b a) : 0 < a.tdiv b :=
Int.lt_tdiv_of_mul_lt H2 H3 (by rwa [Int.zero_mul])
theorem tdiv_eq_tdiv_of_mul_eq_mul {a b c d : Int}
(H2 : d c) (H3 : b ≠ 0) (H4 : d ≠ 0) (H5 : a * d = b * c) : a.tdiv b = c.tdiv d :=
Int.tdiv_eq_of_eq_mul_right H3 <| by
rw [← Int.mul_tdiv_assoc _ H2]; exact (Int.tdiv_eq_of_eq_mul_left H4 H5.symm).symm
theorem le_emod_self_add_one_iff {a b : Int} (h : 0 < b) : b ≤ a % b + 1 ↔ b a + 1 := by
match b, h with
| .ofNat 1, h => simp
| .ofNat (b + 2), h =>
simp only [ofNat_eq_coe, Int.natCast_add, cast_ofNat_Int] at *
constructor
· rw [dvd_iff_emod_eq_zero]
intro w
have := emod_lt_of_pos a h
have : a % (b + 2) = b + 1 := by omega
rw [add_emod, this, one_emod, if_neg (by omega)]
have : (b + 1 + 1 : Int) = b + 2 := by omega
rw [this, emod_self]
· rintro ⟨d, w⟩
replace w : a = (b + 2 : Int) * d - 1 := by omega
subst w
rw [emod_def, mul_sub_ediv_left _ _ (by omega), neg_one_ediv,
sign_eq_one_of_pos (by omega), Int.mul_add]
omega
@[deprecated le_emod_self_add_one_iff (since := "2025-04-12")]
theorem le_mod_self_add_one_iff {a b : Int} (h : 0 < b) : b ≤ a % b + 1 ↔ b a + 1 :=
le_emod_self_add_one_iff h
theorem add_one_tdiv_of_pos {a b : Int} (h : 0 < b) :
(a + 1).tdiv b = a.tdiv b + if (0 < a + 1 ∧ b a + 1) (a < 0 ∧ b a) then 1 else 0 := by
match b, h with
| .ofNat 1, h => simp; omega
| .ofNat (b + 2), h =>
simp only [ofNat_eq_coe]
rw [tdiv_eq_ediv, add_ediv (by omega), tdiv_eq_ediv]
simp only [Int.natCast_add, cast_ofNat_Int]
have : 1 / (b + 2 : Int) = 0 := by rw [one_ediv]; omega
rw [this]
have one_mod : 1 % (b + 2 : Int) = 1 := emod_eq_of_lt (by omega) (by omega)
rw [one_mod]
have : ↑(b + 2 : Int).natAbs = (b + 2 : Int) := by omega
rw [this]
have : (b + 2 : Int).sign = 1 := sign_eq_one_of_pos (by omega)
rw [this]
have : (b + 2) ≤ a % (b + 2 : Int) + 1 ↔ (b + 2 : Int) a + 1 := le_emod_self_add_one_iff (by omega)
simp only [this]
simp only [Int.add_zero]
split <;> rename_i h
· simp only [h, or_true, ↓reduceIte, and_true]
omega
· simp only [h, or_false, and_false]
by_cases h₂ : 0 ≤ a
· simp only [Int.add_zero, h₂, true_or, ↓reduceIte, false_or]
have : 0 ≤ a + 1 := by omega
have : 0 < a + 1 := by omega
have : ¬ a < 0 := by omega
simp [*]
· simp only [Int.add_zero, h₂, false_or]
split
· have : a = -1 := by omega
simp_all
· have : a < 0 := by omega
simp only [true_and, this]
split <;> simp
theorem add_one_tdiv {a b : Int} :
(a + 1).tdiv b = a.tdiv b + if (0 < a + 1 ∧ b a + 1) (a < 0 ∧ b a) then b.sign else 0 := by
if hb : b = 0 then
simp [hb]
else
induction b using wlog_sign
case inv => simp; omega
rename_i c
norm_cast at hb
have : 0 < (c : Int) := by omega
simp [sign_natCast_of_ne_zero hb, add_one_tdiv_of_pos this]
-- One could prove a general `add_tdiv` theorem giving `(a + b).tdiv c = a.tdiv c + b.tdiv c + ...`
-- but the error term would be very complicated.
protected theorem tdiv_le_tdiv {a b c : Int} (H : 0 < c) (H' : a ≤ b) : a.tdiv c ≤ b.tdiv c := by
obtain ⟨d, rfl⟩ := Int.exists_add_of_le H'
clear H'
induction d with
| zero => simp
| succ d ih =>
simp only [Int.natCast_add, cast_ofNat_Int, ← Int.add_assoc]
rw [add_one_tdiv_of_pos (by omega)]
omega
/-! ### fdiv -/
theorem add_mul_fdiv_right (a b : Int) {c : Int} (H : c ≠ 0) : (a + b * c).fdiv c = a.fdiv c + b := by
rw [fdiv_eq_ediv, add_mul_ediv_right _ _ H, fdiv_eq_ediv]
simp only [Int.dvd_add_left (Int.dvd_mul_left _ _)]
split <;> omega
theorem add_mul_fdiv_left (a : Int) {b : Int}
(c : Int) (H : b ≠ 0) : (a + b * c).fdiv b = a.fdiv b + c := by
rw [Int.mul_comm, Int.add_mul_fdiv_right _ _ H]
theorem mul_add_fdiv_right (a c : Int) {b : Int} (H : b ≠ 0) : (a * b + c).fdiv b = c.fdiv b + a := by
rw [Int.add_comm, add_mul_fdiv_right _ _ H]
theorem mul_add_fdiv_left (b : Int) {a : Int}
(c : Int) (H : a ≠ 0) : (a * b + c).fdiv a = c.fdiv a + b := by
rw [Int.add_comm, add_mul_fdiv_left _ _ H]
theorem sub_mul_fdiv_right (a b : Int) {c : Int} (H : c ≠ 0) : (a - b * c).fdiv c = a.fdiv c - b := by
rw [Int.sub_eq_add_neg, ← Int.neg_mul, add_mul_fdiv_right _ _ H, Int.sub_eq_add_neg]
theorem sub_mul_fdiv_left (a : Int) {b : Int}
(c : Int) (H : b ≠ 0) : (a - b * c).fdiv b = a.fdiv b - c := by
rw [Int.sub_eq_add_neg, ← Int.mul_neg, add_mul_fdiv_left _ _ H, Int.sub_eq_add_neg]
theorem mul_sub_fdiv_right (a c : Int) {b : Int} (H : b ≠ 0) : (a * b - c).fdiv b = a + (-c).fdiv b := by
rw [Int.sub_eq_add_neg, Int.add_comm, add_mul_fdiv_right _ _ H, Int.add_comm]
theorem mul_sub_fdiv_left (b : Int) {a : Int}
(c : Int) (H : a ≠ 0) : (a * b - c).fdiv a = b + (-c).fdiv a := by
rw [Int.sub_eq_add_neg, Int.add_comm, add_mul_fdiv_left _ _ H, Int.add_comm]
@[simp] theorem mul_fdiv_cancel (a : Int) {b : Int} (H : b ≠ 0) : fdiv (a * b) b = a :=
if b0 : 0 ≤ b then by
rw [fdiv_eq_ediv_of_nonneg _ b0, mul_ediv_cancel _ H]
else
match a, b, Int.not_le.1 b0 with
| 0, _, _ => by simp [Int.zero_mul]
| succ a, -[b+1], _ => congrArg ofNat <| Nat.mul_div_cancel (succ a) b.succ_pos
| -[a+1], -[b+1], _ => congrArg negSucc <| Nat.div_eq_of_lt_le
(Nat.le_of_lt_succ <| Nat.mul_lt_mul_of_pos_right a.lt_succ_self b.succ_pos)
(Nat.lt_succ_self _)
@[simp] theorem mul_fdiv_cancel_left (b : Int) (H : a ≠ 0) : fdiv (a * b) a = b :=
Int.mul_comm .. ▸ Int.mul_fdiv_cancel _ H
theorem add_fdiv_of_dvd_right {a b c : Int} (H : c b) : (a + b).fdiv c = a.fdiv c + b.fdiv c := by
by_cases h : c = 0
· simp [h]
· obtain ⟨d, rfl⟩ := H
rw [add_mul_fdiv_left _ _ h]
simp [h]
theorem add_fdiv_of_dvd_left {a b c : Int} (H : c a) : (a + b).fdiv c = a.fdiv c + b.fdiv c := by
rw [Int.add_comm, Int.add_fdiv_of_dvd_right H, Int.add_comm]
theorem fdiv_nonneg {a b : Int} (Ha : 0 ≤ a) (Hb : 0 ≤ b) : 0 ≤ a.fdiv b :=
match a, b, eq_ofNat_of_zero_le Ha, eq_ofNat_of_zero_le Hb with
| _, _, ⟨_, rfl⟩, ⟨_, rfl⟩ => ofNat_fdiv .. ▸ ofNat_zero_le _
theorem fdiv_nonneg_of_nonpos_of_nonpos {a b : Int} (Ha : a ≤ 0) (Hb : b ≤ 0) : 0 ≤ a.fdiv b := by
rw [fdiv_eq_ediv]
by_cases ha : a = 0
· simp [ha]
· by_cases hb : b = 0
· simp [hb]
· have : 0 < a / b := ediv_pos_of_neg_of_neg (by omega) (by omega)
split <;> omega
theorem fdiv_nonpos_of_nonneg_of_nonpos : ∀ {a b : Int}, 0 ≤ a → b ≤ 0 → a.fdiv b ≤ 0
| 0, 0, _, _ | 0, -[_+1], _, _ | succ _, 0, _, _ | succ _, -[_+1], _, _ => by
simp [fdiv, negSucc_le_zero]
@[deprecated fdiv_nonpos_of_nonneg_of_nonpos (since := "2025-03-04")]
abbrev fdiv_nonpos := @fdiv_nonpos_of_nonneg_of_nonpos
theorem fdiv_neg_of_neg_of_pos : ∀ {a b : Int}, a < 0 → 0 < b → a.fdiv b < 0
| -[_+1], succ _, _, _ => negSucc_lt_zero _
theorem fdiv_eq_zero_of_lt {a b : Int} (H1 : 0 ≤ a) (H2 : a < b) : a.fdiv b = 0 := by
rw [fdiv_eq_ediv, if_pos, Int.sub_zero]
· apply ediv_eq_zero_of_lt (by omega) (by omega)
· left; omega
@[simp] theorem mul_fdiv_mul_of_pos {a : Int}
(b c : Int) (H : 0 < a) : (a * b).fdiv (a * c) = b.fdiv c := by
rw [fdiv_eq_ediv, mul_ediv_mul_of_pos _ _ H, fdiv_eq_ediv]
congr 2
simp [Int.mul_dvd_mul_iff_left (Int.ne_of_gt H)]
constructor
· rintro (h | h)
· exact .inl (Int.nonneg_of_mul_nonneg_right h H)
· exact .inr h
· rintro (h | h)
· exact .inl (Int.mul_nonneg (by omega) h)
· exact .inr h
@[simp] theorem mul_fdiv_mul_of_pos_left
(a : Int) {b : Int} (c : Int) (H : 0 < b) : (a * b).fdiv (c * b) = a.fdiv c := by
rw [Int.mul_comm a b, Int.mul_comm c b, Int.mul_fdiv_mul_of_pos _ _ H]
@[simp] theorem fdiv_one : ∀ a : Int, a.fdiv 1 = a
| 0 => rfl
| succ _ => congrArg Nat.cast (Nat.div_one _)
| -[_+1] => congrArg negSucc (Nat.div_one _)
protected theorem fdiv_eq_of_eq_mul_right {a b c : Int}
(H1 : b ≠ 0) (H2 : a = b * c) : a.fdiv b = c := by rw [H2, Int.mul_fdiv_cancel_left _ H1]
protected theorem eq_fdiv_of_mul_eq_right {a b c : Int}
(H1 : a ≠ 0) (H2 : a * b = c) : b = c.tdiv a :=
(Int.tdiv_eq_of_eq_mul_right H1 H2.symm).symm
protected theorem fdiv_eq_of_eq_mul_left {a b c : Int}
(H1 : b ≠ 0) (H2 : a = c * b) : a.fdiv b = c :=
Int.fdiv_eq_of_eq_mul_right H1 (by rw [Int.mul_comm, H2])
protected theorem eq_fdiv_of_mul_eq_left {a b c : Int}
(H1 : b ≠ 0) (H2 : a * b = c) : a = c.fdiv b :=
(Int.fdiv_eq_of_eq_mul_left H1 H2.symm).symm
@[simp] protected theorem fdiv_self {a : Int} (H : a ≠ 0) : a.fdiv a = 1 := by
have := Int.mul_fdiv_cancel 1 H; rwa [Int.one_mul] at this
theorem neg_fdiv {a b : Int} : (-a).fdiv b = -(a.fdiv b) - if b = 0 b a then 0 else 1 := by
rw [fdiv_eq_ediv, fdiv_eq_ediv, neg_ediv]
simp
by_cases h : b a
· simp [h]
· simp [h]
by_cases h' : 0 ≤ b
· by_cases h'' : b = 0
· simp [h'']
· simp only [h', ↓reduceIte, Int.sub_zero, h'']
replace h' : 0 < b := by omega
rw [sign_eq_one_of_pos (by omega)]
· simp only [h', ↓reduceIte]
rw [sign_eq_neg_one_of_neg (by omega), if_neg (by omega)]
omega
@[simp] protected theorem neg_fdiv_neg (a b : Int) : (-a).fdiv (-b) = a.fdiv b := by
match a, b with
| 0, 0 => rfl
| 0, ofNat b => simp
| 0, -[b+1] => simp
| ofNat (a + 1), 0 => simp
| ofNat (a + 1), ofNat (b + 1) =>
unfold fdiv
simp only [ofNat_eq_coe, Int.natCast_add, cast_ofNat_Int, Nat.succ_eq_add_one]
rw [← negSucc_eq, ← negSucc_eq]
| ofNat (a + 1), -[b+1] =>
unfold fdiv
simp only [ofNat_eq_coe, Int.natCast_add, cast_ofNat_Int, Nat.succ_eq_add_one]
rw [← negSucc_eq, neg_negSucc]
| -[a+1], 0 => simp
| -[a+1], ofNat (b + 1) =>
unfold fdiv
simp only [ofNat_eq_coe, Int.natCast_add, cast_ofNat_Int, Nat.succ_eq_add_one]
rw [neg_negSucc, ← negSucc_eq]
| -[a+1], -[b+1] =>
unfold fdiv
simp only [ofNat_eq_coe, natCast_ediv, Nat.succ_eq_add_one, Int.natCast_add, cast_ofNat_Int]
rw [neg_negSucc, neg_negSucc]
simp
theorem fdiv_neg {a b : Int} (h : b ≠ 0) : a.fdiv (-b) = if b a then -(a.fdiv b) else -(a.fdiv b) - 1 := by
rw [← Int.neg_fdiv_neg, Int.neg_neg, neg_fdiv]
simp only [h, false_or]
split <;> omega
/-!
One could prove the following, but as the statements are quite awkward, so far it doesn't seem worthwhile.
```
theorem natAbs_fdiv {a b : Int} (h : b ≠ 0) :
natAbs (a.fdiv b) = a.natAbs / b.natAbs + if a.sign = b.sign b a then 0 else 1 := ...
theorem sign_fdiv (a b : Int) :
sign (a.fdiv b) = if a.sign = b.sign ∧ natAbs a < natAbs b then 0 else sign a * sign b := ...
```
-/
/-! ### fmod -/
-- `fmod` analogues of `emod` lemmas from `Bootstrap.lean`
theorem ofNat_fmod (m n : Nat) : ↑(m % n) = fmod m n := by
cases m <;> simp [fmod, Nat.succ_eq_add_one]
theorem fmod_nonneg {a b : Int} (ha : 0 ≤ a) (hb : 0 ≤ b) : 0 ≤ a.fmod b :=
fmod_eq_tmod_of_nonneg ha hb ▸ tmod_nonneg _ ha
theorem fmod_nonneg_of_pos (a : Int) {b : Int} (hb : 0 < b) : 0 ≤ a.fmod b :=
fmod_eq_emod_of_nonneg _ (Int.le_of_lt hb) ▸ emod_nonneg _ (Int.ne_of_lt hb).symm
@[deprecated fmod_nonneg_of_pos (since := "2025-03-04")]
abbrev fmod_nonneg' := @fmod_nonneg_of_pos
theorem fmod_lt_of_pos (a : Int) {b : Int} (H : 0 < b) : a.fmod b < b :=
fmod_eq_emod_of_nonneg _ (Int.le_of_lt H) ▸ emod_lt_of_pos a H
-- There is no `fmod_neg : ∀ {a b : Int}, a.fmod (-b) = -a.fmod b` as this is false.
@[simp] theorem add_mul_fmod_self_right (a b c : Int) : (a + b * c).fmod c = a.fmod c := by
rw [fmod_eq_emod, add_mul_emod_self_right, fmod_eq_emod]
simp
@[deprecated add_mul_fmod_self_right (since := "2025-04-11")]
theorem add_mul_fmod_self {a b c : Int} : (a + b * c).fmod c = a.fmod c :=
add_mul_fmod_self_right ..
@[simp] theorem add_mul_fmod_self_left (a b c : Int) : (a + b * c).fmod b = a.fmod b := by
rw [Int.mul_comm, Int.add_mul_fmod_self_right]
@[simp] theorem mul_add_fmod_self_right (a b c : Int) : (a * b + c).fmod b = c.fmod b := by
rw [Int.add_comm, add_mul_fmod_self_right]
@[simp] theorem mul_add_fmod_self_left (a b c : Int) : (a * b + c).fmod a = c.fmod a := by
rw [Int.add_comm, add_mul_fmod_self_left]
@[simp] theorem add_neg_mul_fmod_self_right (a b c : Int) : (a + -(b * c)).fmod c = a.fmod c := by
rw [Int.neg_mul_eq_neg_mul, add_mul_fmod_self_right]
@[simp] theorem add_neg_mul_fmod_self_left (a b c : Int) : (a + -(b * c)).fmod b = a.fmod b := by
rw [Int.neg_mul_eq_mul_neg, add_mul_fmod_self_left]
@[simp] theorem add_fmod_right (a b : Int) : (a + b).fmod b = a.fmod b := by
have := add_mul_fmod_self_left a b 1; rwa [Int.mul_one] at this
@[simp] theorem add_fmod_left (a b : Int) : (a + b).fmod a = b.fmod a := by
rw [Int.add_comm, add_fmod_right]
@[simp] theorem sub_mul_fmod_self_right (a b c : Int) : (a - b * c).fmod c = a.fmod c := by
simp [Int.sub_eq_add_neg]
@[simp] theorem sub_mul_fmod_self_left (a b c : Int) : (a - b * c).fmod b = a.fmod b := by
simp [Int.sub_eq_add_neg]
@[simp] theorem mul_sub_fmod_self_right (a b c : Int) : (a * b - c).fmod b = (-c).fmod b := by
simp [Int.sub_eq_add_neg]
@[simp] theorem mul_sub_fmod_self_left (a b c : Int) : (a * b - c).fmod a = (-c).fmod a := by
simp [Int.sub_eq_add_neg]
@[simp] theorem sub_fmod_right (a b : Int) : (a - b).fmod b = a.fmod b := by
have := sub_mul_fmod_self_left a b 1; rwa [Int.mul_one] at this
@[simp] theorem sub_fmod_left (a b : Int) : (a - b).fmod a = (-b).fmod a := by
simp [Int.sub_eq_add_neg]
@[simp] theorem fmod_add_fmod (m n k : Int) : (m.fmod n + k).fmod n = (m + k).fmod n := by
by_cases h : n = 0
· simp [h]
rw [fmod_def, fmod_def]
conv => rhs; rw [fmod_def]
have : m - n * m.fdiv n + k = m + k + n * (- m.fdiv n) := by simp [Int.mul_neg]; omega
rw [this, add_fdiv_of_dvd_right (Int.dvd_mul_right ..), Int.mul_add, mul_fdiv_cancel_left _ h]
omega
@[simp] theorem add_fmod_fmod (m n k : Int) : (m + n.fmod k).fmod k = (m + n).fmod k := by
rw [Int.add_comm, Int.fmod_add_fmod, Int.add_comm]
theorem add_fmod (a b n : Int) : (a + b).fmod n = (a.fmod n + b.fmod n).fmod n := by
simp
theorem add_fmod_eq_add_fmod_right {m n k : Int} (i : Int)
(H : m.fmod n = k.fmod n) : (m + i).fmod n = (k + i).fmod n := by
rw [add_fmod]
conv => rhs; rw [add_fmod]
rw [H]
theorem fmod_add_cancel_right {m n k : Int} (i) : (m + i).fmod n = (k + i).fmod n ↔ m.fmod n = k.fmod n :=
⟨fun H => by
have := add_fmod_eq_add_fmod_right (-i) H
rwa [Int.add_neg_cancel_right, Int.add_neg_cancel_right] at this,
add_fmod_eq_add_fmod_right _⟩
@[simp] theorem mul_fmod_left (a b : Int) : (a * b).fmod b = 0 :=
if h : b = 0 then by simp [h, Int.mul_zero] else by
rw [Int.fmod_def, Int.mul_fdiv_cancel _ h, Int.mul_comm, Int.sub_self]
@[simp] theorem mul_fmod_right (a b : Int) : (a * b).fmod a = 0 := by
rw [Int.mul_comm, mul_fmod_left]
theorem mul_fmod (a b n : Int) : (a * b).fmod n = (a.fmod n * b.fmod n).fmod n := by
conv => lhs; rw [
← fmod_add_mul_fdiv a n, ← fmod_add_fdiv_mul b n, Int.add_mul, Int.mul_add, Int.mul_add,
Int.mul_assoc, Int.mul_assoc, ← Int.mul_add n _ _, add_mul_fmod_self_left,
← Int.mul_assoc, add_mul_fmod_self_right]
@[simp] theorem fmod_self {a : Int} : a.fmod a = 0 := by
have := mul_fmod_left 1 a; rwa [Int.one_mul] at this
@[simp] theorem fmod_fmod_of_dvd (n : Int) {m k : Int}
(h : m k) : (n.fmod k).fmod m = n.fmod m := by
conv => rhs; rw [← fmod_add_mul_fdiv n k]
match k, h with
| _, ⟨t, rfl⟩ => rw [Int.mul_assoc, add_mul_fmod_self_left]
theorem fmod_fmod (a b : Int) : (a.fmod b).fmod b = a.fmod b := by
simp
theorem sub_fmod (a b n : Int) : (a - b).fmod n = (a.fmod n - b.fmod n).fmod n := by
apply (fmod_add_cancel_right b).mp
rw [Int.sub_add_cancel, ← Int.add_fmod_fmod, Int.sub_add_cancel, fmod_fmod]
theorem fmod_eq_zero_of_dvd : ∀ {a b : Int}, a b → b.fmod a = 0
| _, _, ⟨_, rfl⟩ => mul_fmod_right ..
-- `fmod` analogues of `emod` lemmas from above
theorem fmod_eq_of_lt {a b : Int} (H1 : 0 ≤ a) (H2 : a < b) : a.fmod b = a := by
rw [fmod_eq_emod_of_nonneg _ (Int.le_trans H1 (Int.le_of_lt H2)), emod_eq_of_lt H1 H2]
@[simp] protected theorem neg_fmod_neg (a b : Int) : (-a).fmod (-b) = -a.fmod b := by
rw [fmod_def, Int.neg_fdiv_neg, fmod_def, Int.neg_mul]
omega
-- Are `sign_fmod`, `natAbs_fmod` useful?
/-! ### properties of `fdiv` and `fmod` -/
-- Analogues of properties of `ediv` and `emod` from `Bootstrap.lean`
theorem mul_fdiv_cancel_of_fmod_eq_zero {a b : Int} (H : a.fmod b = 0) : b * (a.fdiv b) = a := by
have := fmod_add_mul_fdiv a b; rwa [H, Int.zero_add] at this
theorem fdiv_mul_cancel_of_fmod_eq_zero {a b : Int} (H : a.fmod b = 0) : (a.fdiv b) * b= a := by
rw [Int.mul_comm, mul_fdiv_cancel_of_fmod_eq_zero H]
theorem dvd_of_fmod_eq_zero {a b : Int} (H : b.fmod a = 0) : a b :=
⟨b.fdiv a, (mul_fdiv_cancel_of_fmod_eq_zero H).symm⟩
theorem dvd_iff_fmod_eq_zero {a b : Int} : a b ↔ b.fmod a = 0 :=
⟨fmod_eq_zero_of_dvd, dvd_of_fmod_eq_zero⟩
protected theorem fdiv_mul_cancel {a b : Int} (H : b a) : a.fdiv b * b = a :=
fdiv_mul_cancel_of_fmod_eq_zero (fmod_eq_zero_of_dvd H)
protected theorem mul_fdiv_cancel' {a b : Int} (H : a b) : a * b.fdiv a = b := by
rw [Int.mul_comm, Int.fdiv_mul_cancel H]
protected theorem eq_mul_of_fdiv_eq_right {a b c : Int}
(H1 : b a) (H2 : a.fdiv b = c) : a = b * c := by rw [← H2, Int.mul_fdiv_cancel' H1]
@[simp] theorem neg_fmod_self (a : Int) : (-a).fmod a = 0 := by
rw [← dvd_iff_fmod_eq_zero, Int.dvd_neg]
exact Int.dvd_refl a
theorem lt_fdiv_add_one_mul_self (a : Int) {b : Int} (H : 0 < b) : a < (a.fdiv b + 1) * b := by
rw [Int.add_mul, Int.one_mul, Int.mul_comm]
exact Int.lt_add_of_sub_left_lt <| Int.fmod_def .. ▸ fmod_lt_of_pos _ H
protected theorem fdiv_eq_iff_eq_mul_right {a b c : Int}
(H : b ≠ 0) (H' : b a) : a.fdiv b = c ↔ a = b * c :=
⟨Int.eq_mul_of_fdiv_eq_right H', Int.fdiv_eq_of_eq_mul_right H⟩
protected theorem fdiv_eq_iff_eq_mul_left {a b c : Int}
(H : b ≠ 0) (H' : b a) : a.fdiv b = c ↔ a = c * b := by
rw [Int.mul_comm]; exact Int.fdiv_eq_iff_eq_mul_right H H'
protected theorem eq_mul_of_fdiv_eq_left {a b c : Int}
(H1 : b a) (H2 : a.fdiv b = c) : a = c * b := by
rw [Int.mul_comm, Int.eq_mul_of_fdiv_eq_right H1 H2]
protected theorem eq_zero_of_fdiv_eq_zero {d n : Int} (h : d n) (H : n.fdiv d = 0) : n = 0 := by
rw [← Int.mul_fdiv_cancel' h, H, Int.mul_zero]
@[simp] protected theorem fdiv_left_inj {a b d : Int}
(hda : d a) (hdb : d b) : a.fdiv d = b.fdiv d ↔ a = b := by
refine ⟨fun h => ?_, congrArg (fdiv · d)⟩
rw [← Int.mul_fdiv_cancel' hda, ← Int.mul_fdiv_cancel' hdb, h]
protected theorem mul_fdiv_assoc (a : Int) : ∀ {b c : Int}, c b → (a * b).fdiv c = a * (b.fdiv c)
| _, c, ⟨d, rfl⟩ =>
if cz : c = 0 then by simp [cz, Int.mul_zero] else by
rw [Int.mul_left_comm, Int.mul_fdiv_cancel_left _ cz, Int.mul_fdiv_cancel_left _ cz]
protected theorem mul_fdiv_assoc' (b : Int) {a c : Int} (h : c a) :
(a * b).fdiv c = a.fdiv c * b := by
rw [Int.mul_comm, Int.mul_fdiv_assoc _ h, Int.mul_comm]
theorem neg_fdiv_of_dvd : ∀ {a b : Int}, b a → (-a).fdiv b = -(a.fdiv b)
| _, b, ⟨c, rfl⟩ => by
by_cases bz : b = 0
· simp [bz]
· rw [Int.neg_mul_eq_mul_neg, Int.mul_fdiv_cancel_left _ bz, Int.mul_fdiv_cancel_left _ bz]
theorem sub_fdiv_of_dvd (a : Int) {b c : Int}
(hcb : c b) : (a - b).fdiv c = a.fdiv c - b.fdiv c := by
rw [Int.sub_eq_add_neg, Int.sub_eq_add_neg, Int.add_fdiv_of_dvd_right (Int.dvd_neg.2 hcb)]
congr; exact Int.neg_fdiv_of_dvd hcb
theorem fdiv_dvd_fdiv : ∀ {a b c : Int}, a b → b c → b.fdiv a c.fdiv a
| a, _, _, ⟨b, rfl⟩, ⟨c, rfl⟩ => by
by_cases az : a = 0
· simp [az]
· rw [Int.mul_fdiv_cancel_left _ az, Int.mul_assoc, Int.mul_fdiv_cancel_left _ az]
apply Int.dvd_mul_right
-- Analogues of properties about `ediv` and `emod` from above.
theorem mul_fdiv_cancel_of_dvd {a b : Int} (H : b a) : b * (a.fdiv b) = a :=
mul_fdiv_cancel_of_fmod_eq_zero (fmod_eq_zero_of_dvd H)
theorem fdiv_mul_cancel_of_dvd {a b : Int} (H : b a) : a.fdiv b * b = a :=
fdiv_mul_cancel_of_fmod_eq_zero (fmod_eq_zero_of_dvd H)
theorem fmod_two_eq (x : Int) : x.fmod 2 = 0 x.fmod 2 = 1 := by
have h₁ : 0 ≤ x.fmod 2 := Int.fmod_nonneg_of_pos _ (by decide)
have h₂ : x.fmod 2 < 2 := Int.fmod_lt_of_pos x (by decide)
match x.fmod 2, h₁, h₂ with
| 0, _, _ => simp
| 1, _, _ => simp
theorem add_fmod_eq_add_fmod_left {m n k : Int} (i : Int)
(H : m.fmod n = k.fmod n) : (i + m).fmod n = (i + k).fmod n := by
rw [Int.add_comm, add_fmod_eq_add_fmod_right _ H, Int.add_comm]
theorem fmod_add_cancel_left {m n k i : Int} : (i + m).fmod n = (i + k).fmod n ↔ m.fmod n = k.fmod n := by
rw [Int.add_comm, Int.add_comm i, fmod_add_cancel_right]
theorem fmod_sub_cancel_right {m n k : Int} (i) : (m - i).fmod n = (k - i).fmod n ↔ m.fmod n = k.fmod n :=
fmod_add_cancel_right _
theorem fmod_eq_fmod_iff_fmod_sub_eq_zero {m n k : Int} : m.fmod n = k.fmod n ↔ (m - k).fmod n = 0 :=
(fmod_sub_cancel_right k).symm.trans <| by simp [Int.sub_self]
theorem fmod_sub_cancel_left {m n k : Int} (i) : (i - m).fmod n = (i - k).fmod n ↔ m.fmod n = k.fmod n := by
simp only [fmod_eq_fmod_iff_fmod_sub_eq_zero, ← dvd_iff_fmod_eq_zero,
(by omega : i - m - (i - k) = -(m - k)), Int.dvd_neg]
protected theorem fdiv_fmod_unique {a b r q : Int} (h : 0 < b) :
a.fdiv b = q ∧ a.fmod b = r ↔ r + b * q = a ∧ 0 ≤ r ∧ r < b := by
rw [fdiv_eq_ediv_of_nonneg, fmod_eq_emod_of_nonneg, Int.ediv_emod_unique]
all_goals omega
protected theorem fdiv_fmod_unique' {a b r q : Int} (h : b < 0) :
a.fdiv b = q ∧ a.fmod b = r ↔ r + b * q = a ∧ b < r ∧ r ≤ 0 := by
have := Int.fdiv_fmod_unique (a := -a) (b := -b) (r := -r) (q := q) (by omega)
simp at this
simp [this, Int.neg_mul]
omega
@[simp] theorem mul_fmod_mul_of_pos
{a : Int} (b c : Int) (H : 0 < a) : (a * b).fmod (a * c) = a * (b.fmod c) := by
rw [fmod_def, fmod_def, mul_fdiv_mul_of_pos _ _ H, Int.mul_sub, Int.mul_assoc]
theorem natAbs_fdiv_le_natAbs (a b : Int) : natAbs (a.fdiv b) ≤ natAbs a := by
rw [fdiv_eq_ediv]
split
· simp [natAbs_ediv_le_natAbs]
· rename_i h
simp at h
match a, b, h with
| 0, .negSucc b, h => simp at h
| .ofNat (a + 1), .negSucc 0, h => simp at h
| .ofNat (a + 1), .negSucc (b + 1), h =>
rw [negSucc_eq, ofNat_eq_coe]
norm_cast
rw [Int.ediv_neg, Int.sub_eq_add_neg, ← Int.neg_add, natAbs_neg]
norm_cast
apply Nat.div_lt_self
omega
omega
| .negSucc a, .negSucc b, h =>
simp [negSucc_eq]
norm_cast
rw [Int.neg_ediv, if_neg (by simpa using h.2)]
norm_cast
rw [sign_eq_one_of_pos (by omega), Int.sub_eq_add_neg, ← Int.neg_add, natAbs_neg,
Int.sub_add_cancel, natAbs_neg, natAbs_natCast]
apply Nat.div_le_self
theorem fdiv_le_self {a : Int} (b : Int) (Ha : 0 ≤ a) : a.fdiv b ≤ a := by
have := Int.le_trans le_natAbs (ofNat_le.2 <| natAbs_fdiv_le_natAbs a b)
rwa [natAbs_of_nonneg Ha] at this
theorem dvd_fmod_sub_self {x m : Int} : m x.fmod m - x := by
rw [fmod_eq_emod]
have := dvd_emod_sub_self (x := x) (m := m)
split
· simpa
· have w : x % ↑m + ↑m - x = x % ↑m - x + ↑m := by omega
rw [w]
apply Int.dvd_add this (Int.dvd_refl ↑m)
theorem dvd_self_sub_fmod {x m : Int} : m x - x.fmod m :=
Int.dvd_neg.1 (by simpa only [Int.neg_sub] using dvd_fmod_sub_self)
theorem dvd_self_sub_of_fmod_eq {a b c : Int} (h : a.fmod b = c) :
(b : Int) a - c :=
h ▸ dvd_self_sub_fmod
theorem dvd_sub_self_of_fmod_eq {a b c : Int} (h : a.fmod b = c) :
(b : Int) c - a :=
h ▸ dvd_fmod_sub_self
@[simp] theorem neg_mul_fmod_right (a b : Int) : (-(a * b)).fmod a = 0 := by
rw [← dvd_iff_fmod_eq_zero, Int.dvd_neg]
exact Int.dvd_mul_right a b
@[simp] theorem neg_mul_fmod_left (a b : Int) : (-(a * b)).fmod b = 0 := by
rw [← dvd_iff_fmod_eq_zero, Int.dvd_neg]
exact Int.dvd_mul_left a b
@[simp] theorem fmod_one (a : Int) : a.fmod 1 = 0 := by
simp [fmod_def, Int.one_mul, Int.sub_self]
@[deprecated sub_fmod_right (since := "2025-04-12")]
theorem fmod_sub_cancel (x y : Int) : (x - y).fmod y = x.fmod y :=
sub_fmod_right _ _
@[simp] theorem add_neg_fmod_self (a b : Int) : (a + -b).fmod b = a.fmod b := by
rw [Int.add_neg_eq_sub, sub_fmod_right]
@[simp] theorem neg_add_fmod_self (a b : Int) : (-a + b).fmod a = b.fmod a := by
rw [Int.add_comm, add_neg_fmod_self]
@[deprecated dvd_self_sub_of_fmod_eq (since := "2025-04-12")]
theorem dvd_sub_of_fmod_eq {a b c : Int} (h : a.fmod b = c) : b a - c :=
dvd_self_sub_of_fmod_eq h
theorem fdiv_sign {a b : Int} : a.fdiv (sign b) = a * sign b := by
rw [fdiv_eq_ediv]
rcases sign_trichotomy b with h | h | h <;> simp [h]
protected theorem sign_eq_fdiv_abs (a : Int) : sign a = a.fdiv (natAbs a) :=
if az : a = 0 then by simp [az] else
(Int.fdiv_eq_of_eq_mul_left (ofNat_ne_zero.2 <| natAbs_ne_zero.2 az)
(sign_mul_natAbs _).symm).symm
/-! ### `fdiv` and ordering -/
-- Theorems about `fdiv` and ordering, whose `ediv` analogues are in `Bootstrap.lean`.
theorem mul_fdiv_self_le {x k : Int} (h : 0 < k) : k * (x.fdiv k) ≤ x := by
rw [fdiv_eq_ediv]
have := mul_ediv_self_le (x := x) (k := k)
split <;> simp <;> omega
theorem lt_mul_fdiv_self_add {x k : Int} (h : 0 < k) : x < k * (x.fdiv k) + k := by
rw [fdiv_eq_ediv]
have := lt_mul_ediv_self_add (x := x) h
split <;> simp <;> omega
-- We do not currently prove the theorems about `fdiv` and ordering,
-- whose `ediv` analogues are proved above.
/-! ### bmod -/
@[simp]
theorem emod_bmod (x : Int) (n : Nat) : Int.bmod (x%n) n = Int.bmod x n := by
simp [bmod]
@[deprecated emod_bmod (since := "2025-04-11")]
theorem emod_bmod_congr (x : Int) (n : Nat) : Int.bmod (x%n) n = Int.bmod x n :=
emod_bmod ..
theorem bdiv_add_bmod (x : Int) (m : Nat) : m * bdiv x m + bmod x m = x := by
unfold bdiv bmod
split
· simp_all only [cast_ofNat_Int, Int.mul_zero, emod_zero, Int.zero_add, Int.sub_zero,
ite_self]
· dsimp only
split
· exact mul_ediv_add_emod x m
· rw [Int.mul_add, Int.mul_one, Int.add_assoc, Int.add_comm m, Int.sub_add_cancel]
exact mul_ediv_add_emod x m
theorem bmod_add_bdiv (x : Int) (m : Nat) : bmod x m + m * bdiv x m = x := by
rw [Int.add_comm]; exact bdiv_add_bmod x m
theorem bdiv_add_bmod' (x : Int) (m : Nat) : bdiv x m * m + bmod x m = x := by
rw [Int.mul_comm]; exact bdiv_add_bmod x m
theorem bmod_add_bdiv' (x : Int) (m : Nat) : bmod x m + bdiv x m * m = x := by
rw [Int.add_comm]; exact bdiv_add_bmod' x m
theorem bmod_eq_self_sub_mul_bdiv (x : Int) (m : Nat) : bmod x m = x - m * bdiv x m := by
rw [← Int.add_sub_cancel (bmod x m), bmod_add_bdiv]
theorem bmod_eq_self_sub_bdiv_mul (x : Int) (m : Nat) : bmod x m = x - bdiv x m * m := by
rw [← Int.add_sub_cancel (bmod x m), bmod_add_bdiv']
theorem bmod_pos (x : Int) (m : Nat) (p : x % m < (m + 1) / 2) : bmod x m = x % m := by
simp [bmod_def, p]
theorem bmod_neg (x : Int) (m : Nat) (p : x % m ≥ (m + 1) / 2) : bmod x m = (x % m) - m := by
simp [bmod_def, Int.not_lt.mpr p]
theorem bmod_eq_emod (x : Int) (m : Nat) : bmod x m = x % m - if x % m ≥ (m + 1) / 2 then m else 0 := by
split
· rwa [bmod_neg]
· rw [bmod_pos] <;> simp_all
@[simp]
theorem bmod_one (x : Int) : Int.bmod x 1 = 0 := by
simp [Int.bmod]
@[deprecated bmod_one (since := "2025-04-10")]
abbrev bmod_one_is_zero := @bmod_one
@[simp] theorem add_bmod_right (a : Int) (b : Nat) : (a + b).bmod b = a.bmod b := by
simp [bmod_def]
@[simp] theorem add_bmod_left (a : Nat) (b : Int) : (a + b).bmod a = b.bmod a := by
simp [bmod_def]
@[simp] theorem add_mul_bmod_self_right (a b : Int) (c : Nat) : (a + b * c).bmod c = a.bmod c := by
simp [bmod_def]
@[simp] theorem add_mul_bmod_self_left (a : Int) (b : Nat) (c : Int) : (a + b * c).bmod b = a.bmod b := by
simp [bmod_def]
@[simp] theorem mul_add_bmod_self_right (a : Int) (b : Nat) (c : Int) : (a * b + c).bmod b = c.bmod b := by
simp [bmod_def]
@[simp] theorem mul_add_bmod_self_left (a : Nat) (b c : Int) : (a * b + c).bmod a = c.bmod a := by
simp [bmod_def]
@[simp] theorem sub_bmod_right (a : Int) (b : Nat) : (a - b).bmod b = a.bmod b := by
simp [bmod_def]
@[simp] theorem sub_bmod_left (a : Nat) (b : Int) : (a - b).bmod a = (-b).bmod a := by
simp [bmod_def]
@[simp] theorem sub_mul_bmod_self_right (a b : Int) (c : Nat) : (a - b * c).bmod c = a.bmod c := by
simp [bmod_def]
@[simp] theorem sub_mul_bmod_self_left (a : Int) (b : Nat) (c : Int) : (a - b * c).bmod b = a.bmod b := by
simp [bmod_def]
@[simp] theorem mul_sub_bmod_self_right (a : Int) (b : Nat) (c : Int) : (a * b - c).bmod b = (-c).bmod b := by
simp [bmod_def]
@[simp] theorem mul_sub_bmod_self_left (a : Nat) (b c : Int) : (a * b - c).bmod a = (-c).bmod a := by
simp [bmod_def]
@[simp] theorem add_neg_mul_bmod_self_right (a b : Int) (c : Nat) : (a + -(b * c)).bmod c = a.bmod c := by
simp [bmod_def]
@[simp] theorem add_neg_mul_bmod_self_left (a : Int) (b : Nat) (c : Int) : (a + -(b * c)).bmod b = a.bmod b := by
simp [bmod_def]
@[deprecated add_bmod_right (since := "2025-04-10")]
theorem bmod_add_cancel {x : Int} {n : Nat} : Int.bmod (x + n) n = Int.bmod x n :=
add_bmod_right ..
@[deprecated add_mul_bmod_self_left (since := "2025-04-10")]
theorem bmod_add_mul_cancel (x : Int) (n : Nat) (k : Int) : Int.bmod (x + n * k) n = Int.bmod x n :=
add_mul_bmod_self_left ..
@[deprecated sub_bmod_right (since := "2025-04-10")]
theorem bmod_sub_cancel (x : Int) (n : Nat) : Int.bmod (x - n) n = Int.bmod x n :=
sub_bmod_right ..
@[deprecated sub_mul_bmod_self_left (since := "2025-04-10")]
theorem Int.bmod_sub_mul_cancel (x : Int) (n : Nat) (k : Int) : (x - n * k).bmod n = x.bmod n :=
sub_mul_bmod_self_left ..
@[simp]
theorem emod_add_bmod (x : Int) (n : Nat) : Int.bmod (x % n + y) n = Int.bmod (x + y) n := by
simp [Int.emod_def, Int.sub_eq_add_neg]
rw [←Int.mul_neg, Int.add_right_comm, Int.add_mul_bmod_self_left]
@[deprecated emod_add_bmod (since := "2025-04-11")]
theorem emod_add_bmod_congr (x : Int) (n : Nat) : Int.bmod (x % n + y) n = Int.bmod (x + y) n :=
emod_add_bmod ..
@[simp]
theorem emod_sub_bmod (x : Int) (n : Nat) : Int.bmod (x % n - y) n = Int.bmod (x - y) n := by
simp only [emod_def, Int.sub_eq_add_neg]
rw [←Int.mul_neg, Int.add_right_comm, Int.add_mul_bmod_self_left]
@[deprecated emod_sub_bmod (since := "2025-04-11")]
theorem emod_sub_bmod_congr (x : Int) (n : Nat) : Int.bmod (x % n - y) n = Int.bmod (x - y) n :=
emod_sub_bmod ..
@[simp]
theorem sub_emod_bmod (x : Int) (n : Nat) : Int.bmod (x - y % n) n = Int.bmod (x - y) n := by
simp only [emod_def]
rw [Int.sub_eq_add_neg, Int.neg_sub, Int.sub_eq_add_neg, ← Int.add_assoc, Int.add_right_comm,
Int.add_mul_bmod_self_left, Int.sub_eq_add_neg]
@[deprecated sub_emod_bmod (since := "2025-04-11")]
theorem sub_emod_bmod_congr (x : Int) (n : Nat) : Int.bmod (x - y % n) n = Int.bmod (x - y) n :=
sub_emod_bmod ..
@[simp]
theorem emod_mul_bmod (x : Int) (n : Nat) : Int.bmod (x % n * y) n = Int.bmod (x * y) n := by
simp [Int.emod_def, Int.sub_eq_add_neg]
rw [←Int.mul_neg, Int.add_mul, Int.mul_assoc, Int.add_mul_bmod_self_left]
@[deprecated emod_mul_bmod (since := "2025-04-11")]
theorem emod_mul_bmod_congr (x : Int) (n : Nat) : Int.bmod (x % n * y) n = Int.bmod (x * y) n :=
emod_mul_bmod ..
@[simp]
theorem bmod_add_bmod : Int.bmod (Int.bmod x n + y) n = Int.bmod (x + y) n := by
have := (@add_mul_bmod_self_left (Int.bmod x n + y) n (bdiv x n)).symm
rwa [Int.add_right_comm, bmod_add_bdiv] at this
@[deprecated bmod_add_bmod (since := "2025-04-11")]
theorem bmod_add_bmod_congr : Int.bmod (Int.bmod x n + y) n = Int.bmod (x + y) n :=
bmod_add_bmod ..
@[simp]
theorem bmod_sub_bmod : Int.bmod (Int.bmod x n - y) n = Int.bmod (x - y) n :=
@bmod_add_bmod x n (-y)
@[deprecated bmod_sub_bmod (since := "2025-04-11")]
theorem bmod_sub_bmod_congr : Int.bmod (Int.bmod x n - y) n = Int.bmod (x - y) n :=
bmod_sub_bmod ..
theorem add_bmod_eq_add_bmod_right (i : Int)
(H : bmod x n = bmod y n) : bmod (x + i) n = bmod (y + i) n := by
rw [← bmod_add_bmod, ← @bmod_add_bmod y, H]
theorem bmod_add_cancel_right (i : Int) : bmod (x + i) n = bmod (y + i) n ↔ bmod x n = bmod y n :=
⟨fun H => by
have := add_bmod_eq_add_bmod_right (-i) H
rwa [Int.add_neg_cancel_right, Int.add_neg_cancel_right] at this,
fun H => by rw [← bmod_add_bmod, H, bmod_add_bmod]⟩
theorem bmod_add_cancel_left (i : Int) : bmod (i + x) n = bmod (i + y) n ↔ bmod x n = bmod y n := by
rw [Int.add_comm i, Int.add_comm i, bmod_add_cancel_right]
theorem add_bmod_eq_add_bmod_left (i : Int) (h : bmod x n = bmod y n) :
bmod (i + x) n = bmod (i + y) n := by
simpa [bmod_add_cancel_left]
@[simp] theorem add_bmod_bmod : Int.bmod (x + Int.bmod y n) n = Int.bmod (x + y) n := by
rw [Int.add_comm x, Int.bmod_add_bmod, Int.add_comm y]
@[simp] theorem sub_bmod_bmod : Int.bmod (x - Int.bmod y n) n = Int.bmod (x - y) n := by
apply (bmod_add_cancel_right (bmod y n)).mp
rw [Int.sub_add_cancel, add_bmod_bmod, Int.sub_add_cancel]
@[simp]
theorem bmod_mul_bmod : Int.bmod (Int.bmod x n * y) n = Int.bmod (x * y) n := by
rw [bmod_def x n]
split
next p =>
simp
next p =>
rw [Int.sub_mul, Int.sub_eq_add_neg, ← Int.mul_neg, add_mul_bmod_self_left, emod_mul_bmod]
@[simp] theorem mul_bmod_bmod : Int.bmod (x * Int.bmod y n) n = Int.bmod (x * y) n := by
rw [Int.mul_comm x, bmod_mul_bmod, Int.mul_comm x]
@[simp] theorem add_emod_bmod (x : Int) (n : Nat) : (y + x % n).bmod n = (y + x).bmod n := by
rw [Int.add_comm, emod_add_bmod, Int.add_comm]
@[simp] theorem mul_emod_bmod (x : Int) (n : Nat) : (y * (x % n)).bmod n = (y * x).bmod n := by
rw [Int.mul_comm, emod_mul_bmod, Int.mul_comm]
@[simp] theorem mul_bmod_left (a : Int) (b : Nat) : (a * b).bmod b = 0 := by
simp [bmod_def]; omega
@[simp] theorem mul_bmod_right (a : Nat) (b : Int) : (a * b).bmod a = 0 := by
simp [bmod_def]; omega
theorem mul_bmod (a b : Int) (n : Nat) : (a * b).bmod n = (a.bmod n * b.bmod n).bmod n := by
simp
theorem add_bmod (a b : Int) (n : Nat) : (a + b).bmod n = (a.bmod n + b.bmod n).bmod n := by
simp
theorem sub_bmod (a b : Int) (n : Nat) : (a - b).bmod n = (a.bmod n - b.bmod n).bmod n := by
simp
@[simp] theorem bmod_bmod : bmod (bmod x m) m = bmod x m := by
rw [bmod, bmod_emod, bmod]
@[simp] theorem zero_bmod : Int.bmod 0 m = 0 := by
simp [bmod_def]; omega
@[simp] theorem bmod_zero : Int.bmod m 0 = m := by
simp [bmod_def]
@[simp] theorem bmod_self {a : Nat} : Int.bmod a a = 0 := by
simp [bmod_def]; omega
@[simp] theorem neg_bmod_self {a : Nat} : Int.bmod (-a) a = 0 := by
simp [← Int.zero_sub]
theorem dvd_bmod_sub_self {x : Int} {m : Nat} : (m : Int) bmod x m - x := by
dsimp [bmod]
split
· exact dvd_emod_sub_self
· rw [Int.sub_sub, Int.add_comm, ← Int.sub_sub]
exact Int.dvd_sub dvd_emod_sub_self (Int.dvd_refl _)
theorem dvd_self_sub_bmod {x : Int} {m : Nat} : (m : Int) x - bmod x m :=
Int.dvd_neg.1 (by simpa only [Int.neg_sub] using dvd_bmod_sub_self)
theorem dvd_of_bmod_eq_zero {a : Nat} {b : Int} (h : b.bmod a = 0) : (a : Int) b := by
simpa [h] using dvd_bmod_sub_self (x := b) (m := a)
theorem bmod_eq_zero_of_dvd : {a : Nat} → {b : Int} → (h : (a : Int) b) → b.bmod a = 0
| _, _, ⟨_, rfl⟩ => by simp
theorem dvd_iff_bmod_eq_zero {a : Nat} {b : Int} : (a : Int) b ↔ b.bmod a = 0 :=
⟨bmod_eq_zero_of_dvd, dvd_of_bmod_eq_zero⟩
theorem divExact_eq_bdiv {a : Int} {b : Nat} (h : (b : Int) a) : a.divExact b h = a.bdiv b := by
have := bdiv_add_bmod a b
rw [bmod_eq_zero_of_dvd h, Int.add_zero] at this
rw [divExact_eq_ediv]
conv => lhs; rw [← this]
by_cases h' : (b : Int) = 0
· cases h'
simp_all
· rw [mul_ediv_cancel_left _ h']
theorem le_bmod {x : Int} {m : Nat} (h : 0 < m) : - (m/2) ≤ Int.bmod x m := by
dsimp [bmod]
have v : (m : Int) % 2 = 0 (m : Int) % 2 = 1 := emod_two_eq _
split <;> rename_i w
· refine Int.le_trans ?_ (Int.emod_nonneg _ ?_)
· exact Int.neg_nonpos_of_nonneg (Int.ediv_nonneg (natCast_nonneg _) (by decide))
· exact Int.ne_of_gt (natCast_pos.mpr h)
· simp [Int.not_lt] at w
refine Int.le_trans ?_ (Int.sub_le_sub_right w _)
rw [← mul_ediv_add_emod m 2]
generalize (m : Int) / 2 = q
generalize h : (m : Int) % 2 = r at *
rcases v with rfl | rfl
· rw [Int.add_zero, Int.mul_ediv_cancel_left, Int.add_ediv_of_dvd_left,
Int.mul_ediv_cancel_left, show (1 / 2 : Int) = 0 by decide, Int.add_zero,
Int.neg_eq_neg_one_mul]
conv => rhs; congr; rw [← Int.one_mul q]
rw [← Int.sub_mul, show (1 - 2 : Int) = -1 by decide]
apply Int.le_refl
all_goals try decide
all_goals apply Int.dvd_mul_right
· rw [Int.add_ediv_of_dvd_left, Int.mul_ediv_cancel_left,
show (1 / 2 : Int) = 0 by decide, Int.add_assoc, Int.add_ediv_of_dvd_left,
Int.mul_ediv_cancel_left, show ((1 + 1) / 2 : Int) = 1 by decide, ← Int.sub_sub,
Int.sub_eq_add_neg, Int.sub_eq_add_neg, Int.add_right_comm, Int.add_assoc q,
show (1 + -1 : Int) = 0 by decide, Int.add_zero, ← Int.neg_mul]
rw [Int.neg_eq_neg_one_mul]
conv => rhs; congr; rw [← Int.one_mul q]
rw [← Int.add_mul, show (1 + -2 : Int) = -1 by decide]
apply Int.le_refl
all_goals try decide
all_goals try apply Int.dvd_mul_right
theorem bmod_lt {x : Int} {m : Nat} (h : 0 < m) : bmod x m < (m + 1) / 2 := by
dsimp [bmod]
split
· assumption
· apply Int.lt_of_lt_of_le
· change _ < 0
have : x % m < m := emod_lt_of_pos x (natCast_pos.mpr h)
exact Int.sub_neg_of_lt this
· exact Int.le.intro_sub _ rfl
theorem bmod_eq_iff {a : Int} {b : Nat} {c : Int} (hb : 0 < b) :
a.bmod b = c ↔ -(b / 2) ≤ c ∧ c < (b + 1) / 2 ∧ (b : Int) (c - a) := by
refine ⟨?_, ?_⟩
· rintro rfl
exact ⟨le_bmod hb, bmod_lt hb, dvd_bmod_sub_self⟩
· rintro ⟨h₁, h₂, h₃⟩
rw [← Int.sub_eq_zero]
have := dvd_bmod_sub_self (x := a) (m := b)
have hdvd := Int.dvd_sub this h₃
rw [(by omega : a.bmod b - a - (c - a) = a.bmod b - c)] at hdvd
apply eq_zero_of_dvd_of_natAbs_lt_natAbs hdvd
have := le_bmod (x := a) (m := b) hb
have := bmod_lt (x := a) (m := b) hb
omega
theorem bmod_eq_emod_of_lt {x : Int} {m : Nat} (hx : x % m < (m + 1) / 2) : bmod x m = x % m := by
simp [bmod, hx]
theorem bmod_eq_neg {n : Nat} {m : Int} (hm : 0 ≤ m) (hn : n = 2 * m) : m.bmod n = -m := by
by_cases h : m = 0
· subst h; simp
· rw [Int.bmod_def, hn, if_neg]
· rw [Int.emod_eq_of_lt hm] <;> omega
· simp only [Int.not_lt]
rw [Int.emod_eq_of_lt hm] <;> omega
theorem bmod_le {x : Int} {m : Nat} (h : 0 < m) : bmod x m ≤ (m - 1) / 2 := by
refine lt_add_one_iff.mp ?_
calc
bmod x m < (m + 1) / 2 := bmod_lt h
_ = ((m + 1 - 2) + 2)/2 := by simp
_ = (m - 1) / 2 + 1 := by
rw [add_ediv_of_dvd_right]
· simp +decide only [Int.ediv_self]
congr 2
rw [Int.add_sub_assoc, ← Int.sub_neg]
congr
· trivial
theorem bmod_natAbs_add_one (x : Int) (w : x ≠ -1) : x.bmod (x.natAbs + 1) = -x.sign := by
rw [bmod_eq_iff (by omega)]
obtain (hx|rfl|hx) := Int.lt_trichotomy x 0
· rw [sign_eq_neg_one_iff_neg.2 hx]
exact ⟨by omega, by omega, ⟨1, by omega⟩⟩
· simp
· rw [sign_eq_one_iff_pos.2 hx]
exact ⟨by omega, by omega, ⟨-1, by omega⟩⟩
@[deprecated bmod_natAbs_add_one (since := "2025-04-04")]
abbrev bmod_natAbs_plus_one := @bmod_natAbs_add_one
theorem bmod_self_add_one {x : Nat} : (x : Int).bmod (x + 1) = if x = 0 then 0 else -1 := by
have := bmod_natAbs_add_one x (by omega)
simp only [natAbs_natCast] at this
rw [this]
split <;> simp_all <;> omega
theorem one_bmod_two : Int.bmod 1 2 = -1 := by simp
theorem one_bmod {b : Nat} (h : 3 ≤ b) : Int.bmod 1 b = 1 := by
have hb : 1 % (b : Int) = 1 := by rw [one_emod]; omega
rw [bmod_pos _ _ (by omega), hb]
theorem bmod_two_eq (x : Int) : x.bmod 2 = -1 x.bmod 2 = 0 := by
have := le_bmod (x := x) (m := 2) (by omega)
have := bmod_lt (x := x) (m := 2) (by omega)
omega
theorem bmod_sub_cancel_right (i : Int) : bmod (x - i) n = bmod (y - i) n ↔ bmod x n = bmod y n := by
simp only [Int.sub_eq_add_neg, bmod_add_cancel_right]
theorem bmod_eq_bmod_iff_bmod_sub_eq_zero {m : Int} {n : Nat} {k : Int} : m.bmod n = k.bmod n ↔ (m - k).bmod n = 0 :=
(bmod_sub_cancel_right k).symm.trans <| by simp [Int.sub_self]
theorem bmod_sub_cancel_left (i : Int) : bmod (i - x) n = bmod (i - y) n ↔ bmod x n = bmod y n := by
simp only [bmod_eq_bmod_iff_bmod_sub_eq_zero, ← dvd_iff_bmod_eq_zero,
(by omega : i - x - (i - y) = -(x - y)), Int.dvd_neg]
theorem mod_bmod_mul_of_pos {a : Nat} (b : Int) (c : Nat) (h : 0 < a) (hce : 2 c) :
(a * b).bmod (a * c) = a * (b.bmod c) := by
refine (Nat.eq_zero_or_pos c).elim (by rintro rfl; simp) (fun hc => ?_)
rw [bmod_eq_iff (Nat.mul_pos h hc)]
refine ⟨?_, ?_, ?_⟩
· refine Int.le_trans ?_ (Int.mul_le_mul_of_nonneg_left (le_bmod hc) (by omega : 0 ≤ (a : Int)))
simp only [Int.natCast_mul, Int.mul_neg, Int.neg_le_neg_iff]
rw [Int.le_ediv_iff_mul_le (by omega), Int.mul_assoc]
exact Int.mul_le_mul_of_nonneg_left (by omega) (by omega)
· refine Int.lt_of_lt_of_le (Int.mul_lt_mul_of_pos_left (bmod_lt hc) (by omega)) ?_
rw [Int.natCast_mul, Int.le_ediv_iff_mul_le (by omega)]
obtain ⟨t, rfl⟩ := hce
simp only [Int.natCast_mul, cast_ofNat_Int]
rw [mul_add_ediv_left _ _ (by omega), ediv_eq_zero_of_lt (by omega) (by omega),
Int.add_zero, Int.mul_comm 2, Int.mul_assoc]
exact le.intro 1 rfl
· rw [Int.natCast_mul, ← Int.mul_sub, Int.mul_dvd_mul_iff_left (by omega)]
exact dvd_bmod_sub_self
@[simp]
theorem bmod_neg_bmod : bmod (-(bmod x n)) n = bmod (-x) n := by
apply (bmod_add_cancel_right x).mp
rw [Int.add_left_neg, ← add_bmod_bmod, Int.add_left_neg]
theorem neg_bmod {a : Int} {b : Nat} :
(-a).bmod b = if (b : Int) 2 * a then a.bmod b else -(a.bmod b) := by
refine (Nat.eq_zero_or_pos b).elim (by rintro rfl; split <;> simp_all <;> omega) (fun hb => ?_)
split <;> rename_i h
· rw [bmod_eq_bmod_iff_bmod_sub_eq_zero, ← dvd_iff_bmod_eq_zero]
simpa [(by omega : -a - a = -2 * a), Int.neg_mul] using h
· refine (bmod_eq_iff hb).2 ⟨?_, ?_, ?_⟩
· simp only [Int.neg_le_neg_iff]
have := bmod_le (x := a) hb
omega
· apply Int.neg_lt_of_neg_lt
rw [bmod_def]
split <;> rename_i h'
· exact Int.lt_of_lt_of_le (by omega) (Int.emod_nonneg _ (by omega))
· simp only [Int.not_lt] at h'
apply Int.lt_sub_left_of_add_lt
obtain ⟨c, (rfl|rfl)⟩ : ∃ c, b = 2 * c b = 2 * c + 1 := ⟨b / 2, by omega⟩
· simp only [Int.natCast_mul, cast_ofNat_Int]
rw [Int.mul_add_ediv_left _ _ (by omega), Int.ediv_eq_zero_of_lt (by omega) (by omega)]
simp only [Int.add_zero, ← Int.sub_eq_add_neg]
rw [(by omega : ∀ (i : Int), 2 * i - i = i)]
refine Decidable.by_contra (fun hc => h ?_)
simp only [gt_iff_lt, Nat.zero_lt_succ, Nat.mul_pos_iff_of_pos_left, Int.natCast_mul,
cast_ofNat_Int, Int.not_lt] at *
rw [Int.mul_dvd_mul_iff_left (by omega)]
have := mul_ediv_add_emod a (2 * c)
rw [(by omega : a % (2 * c) = c)] at this
rw [← this]
apply Int.dvd_add _ (by simp)
rw [Int.mul_comm 2, Int.mul_assoc]
apply Int.dvd_mul_right
· omega
· simp only [Int.sub_neg, Int.add_comm, ← Int.sub_eq_add_neg]
rw [dvd_iff_bmod_eq_zero]
simp
-- There seems to be no good statement for `natAbs_bmod`.
@[simp] theorem neg_mul_bmod_left (a : Int) (b : Nat) : (-(a * b)).bmod b = 0 := by
simp [← Int.neg_mul]
@[simp] theorem neg_mul_bmod_right (a : Nat) (b : Int) : (-(a * b)).bmod a = 0 := by
simp [← Int.mul_neg]
@[simp] theorem add_neg_bmod_self (a : Int) (b : Nat) : (a + -b).bmod b = a.bmod b := by
simp [← Int.sub_eq_add_neg]
@[simp] theorem neg_add_bmod_self (a : Nat) (b : Int) : (-a + b).bmod a = b.bmod a := by
simp [Int.add_comm]
theorem dvd_self_sub_of_bmod_eq {a : Int} {b : Nat} {c : Int} (h : a.bmod b = c) :
(b : Int) a - c :=
h ▸ dvd_self_sub_bmod
theorem dvd_sub_self_of_bmod_eq {a : Int} {b : Nat} {c : Int} (h : a.bmod b = c) :
(b : Int) c - a :=
h ▸ dvd_bmod_sub_self
theorem bmod_neg_iff {m : Nat} {x : Int} (h2 : -m ≤ x) (h1 : x < m) :
(x.bmod m) < 0 ↔ (-(m / 2) ≤ x ∧ x < 0) ((m + 1) / 2 ≤ x) := by
simp only [Int.bmod_def]
by_cases xpos : 0 ≤ x
· rw [Int.emod_eq_of_lt xpos (by omega)]; omega
· rw [(Int.add_emod_right ..).symm, Int.emod_eq_of_lt (by omega) (by omega)]; omega
theorem bmod_eq_of_le {n : Int} {m : Nat} (hn' : -(m / 2) ≤ n) (hn : n < (m + 1) / 2) :
n.bmod m = n :=
(Nat.eq_zero_or_pos m).elim (by rintro rfl; simp) (fun hm => by simp_all [bmod_eq_iff])
@[deprecated bmod_eq_of_le (since := "2025-04-11")]
theorem bmod_eq_self_of_le {n : Int} {m : Nat} (hn' : -(m / 2) ≤ n) (hn : n < (m + 1) / 2) :
n.bmod m = n :=
bmod_eq_of_le hn' hn
theorem bmod_bmod_of_dvd {a : Int} {n m : Nat} (hnm : n m) :
(a.bmod m).bmod n = a.bmod n := by
rw [← Int.sub_eq_iff_eq_add.2 (bmod_add_bdiv a m).symm]
obtain ⟨k, rfl⟩ := hnm
simp [Int.mul_assoc]
theorem bmod_eq_of_le_mul_two {x : Int} {y : Nat} (hle : -y ≤ x * 2) (hlt : x * 2 < y) :
x.bmod y = x := by
apply bmod_eq_of_le (by omega) (by omega)
@[deprecated bmod_eq_of_le_mul_two (since := "2025-04-11")]
theorem bmod_eq_self_of_le_mul_two {x : Int} {y : Nat} (hle : -y ≤ x * 2) (hlt : x * 2 < y) :
x.bmod y = x :=
bmod_eq_of_le_mul_two hle hlt
/- ### ediv -/
theorem ediv_lt_self_of_pos_of_ne_one {x y : Int} (hx : 0 < x) (hy : y ≠ 1) :
x / y < x := by
by_cases hy' : 1 < y
· obtain ⟨xn, rfl⟩ := Int.eq_ofNat_of_zero_le (a := x) (by omega)
obtain ⟨yn, rfl⟩ := Int.eq_ofNat_of_zero_le (a := y) (by omega)
rw [← Int.natCast_ediv]
norm_cast
apply Nat.div_lt_self (by omega) (by omega)
· have := @Int.ediv_nonpos_of_nonneg_of_nonpos x y (by omega) (by omega)
omega
theorem ediv_nonneg_of_nonneg_of_nonneg {x y : Int} (hx : 0 ≤ x) (hy : 0 ≤ y) :
0 ≤ x / y := by
obtain ⟨xn, rfl⟩ := Int.eq_ofNat_of_zero_le (a := x) (by omega)
obtain ⟨yn, rfl⟩ := Int.eq_ofNat_of_zero_le (a := y) (by omega)
rw [← Int.natCast_ediv]
exact Int.ofNat_zero_le (xn / yn)
/-- When both x and y are negative we need stricter bounds on x and y
to establish the upper bound of x/y, i.e., x / y < x.natAbs.
In particular, consider the following counter examples:
· (-1) / (-2) = 1 and ¬ 1 < (-1).natAbs
(note that Int.neg_one_ediv already handles `ediv` where the numerator is -1)
· (-2) / (-1) = 2 and ¬ 1 < (-2).natAbs
To exclude these cases, we enforce stricter bounds on the values of x and y.
-/
theorem ediv_lt_natAbs_self_of_lt_neg_one_of_lt_neg_one {x y : Int} (hx : x < -1) (hy : y < -1) :
x / y < x.natAbs := by
obtain ⟨xn, rfl⟩ := Int.eq_negSucc_of_lt_zero (a := x) (by omega)
obtain ⟨yn, rfl⟩ := Int.eq_negSucc_of_lt_zero (a := y) (by omega)
simp only [negSucc_ediv_negSucc, Int.natCast_add, natCast_ediv, cast_ofNat_Int, natAbs_negSucc,
Nat.succ_eq_add_one, Int.add_lt_add_iff_right]
rw_mod_cast [Nat.div_lt_iff_lt_mul (x := xn) (k := yn + 1) (y := xn) (by omega),
show (xn < xn * (yn + 1)) = (1 * xn < (yn + 1) * xn) by rw [Nat.one_mul, Nat.mul_comm]]
apply Nat.mul_lt_mul_of_lt_of_le (a := 1) (b := xn) (c := yn + 1) (d := xn) (by omega) (by omega) (by omega)
theorem self_le_ediv_of_nonpos_of_nonneg {x y : Int} (hx : x ≤ 0) (hy : 0 ≤ y) :
x ≤ x / y := by
by_cases hx' : x = 0
· simp [hx', zero_ediv]
· by_cases hy : y = 0
· simp [hy]; omega
· simp only [Int.le_ediv_iff_mul_le (c := y) (a := x) (b := x) (by omega),
show (x * y ≤ x) = (x * y ≤ x * 1) by rw [Int.mul_one], Int.mul_one]
apply Int.mul_le_mul_of_nonpos_left (a := x) (b := y) (c := (1 : Int)) (by omega) (by omega)
theorem neg_self_le_ediv_of_nonneg_of_nonpos (x y : Int) (hx : 0 ≤ x) (hy : y ≤ 0) :
-x ≤ x / y := by
by_cases hy' : y = 0
· simp [hy']; omega
· obtain ⟨xn, rfl⟩ := Int.eq_ofNat_of_zero_le (a := x) (by omega)
obtain ⟨yn, rfl⟩ := Int.eq_negSucc_of_lt_zero (a := y) (by omega)
rw [show xn = ofNat xn by norm_cast, Int.ofNat_ediv_negSucc (a := xn)]
simp only [ofNat_eq_coe, natCast_ediv, Int.natCast_add, cast_ofNat_Int, Int.neg_le_neg_iff]
norm_cast
apply Nat.le_trans (m := xn) (by exact Nat.div_le_self xn (yn + 1)) (by omega)
/-! Helper theorems for `dvd` simproc -/
protected theorem dvd_eq_true_of_mod_eq_zero {a b : Int} (h : b % a == 0) : (a b) = True := by
simp [Int.dvd_of_emod_eq_zero, eq_of_beq h]
protected theorem dvd_eq_false_of_mod_ne_zero {a b : Int} (h : b % a != 0) : (a b) = False := by
simp [eq_of_beq] at h
simp [Int.dvd_iff_emod_eq_zero, h]
end Int