141 lines
5.6 KiB
Text
141 lines
5.6 KiB
Text
/-
|
||
Copyright (c) 2016 Microsoft Corporation. All rights reserved.
|
||
Released under Apache 2.0 license as described in the file LICENSE.
|
||
Authors: Leonardo de Moura, Jeremy Avigad, Mario Carneiro
|
||
-/
|
||
prelude
|
||
import Init.Data.Nat.Div.Basic
|
||
import Init.Meta
|
||
|
||
namespace Nat
|
||
|
||
protected theorem dvd_refl (a : Nat) : a ∣ a := ⟨1, by simp⟩
|
||
|
||
protected theorem dvd_zero (a : Nat) : a ∣ 0 := ⟨0, by simp⟩
|
||
|
||
protected theorem dvd_mul_left (a b : Nat) : a ∣ b * a := ⟨b, Nat.mul_comm b a⟩
|
||
protected theorem dvd_mul_right (a b : Nat) : a ∣ a * b := ⟨b, rfl⟩
|
||
|
||
protected theorem dvd_trans {a b c : Nat} (h₁ : a ∣ b) (h₂ : b ∣ c) : a ∣ c :=
|
||
match h₁, h₂ with
|
||
| ⟨d, (h₃ : b = a * d)⟩, ⟨e, (h₄ : c = b * e)⟩ =>
|
||
⟨d * e, show c = a * (d * e) by simp[h₃,h₄, Nat.mul_assoc]⟩
|
||
|
||
protected theorem eq_zero_of_zero_dvd {a : Nat} (h : 0 ∣ a) : a = 0 :=
|
||
let ⟨c, H'⟩ := h; H'.trans c.zero_mul
|
||
|
||
@[simp] protected theorem zero_dvd {n : Nat} : 0 ∣ n ↔ n = 0 :=
|
||
⟨Nat.eq_zero_of_zero_dvd, fun h => h.symm ▸ Nat.dvd_zero 0⟩
|
||
|
||
protected theorem dvd_add {a b c : Nat} (h₁ : a ∣ b) (h₂ : a ∣ c) : a ∣ b + c :=
|
||
let ⟨d, hd⟩ := h₁; let ⟨e, he⟩ := h₂; ⟨d + e, by simp [Nat.left_distrib, hd, he]⟩
|
||
|
||
protected theorem dvd_add_iff_right {k m n : Nat} (h : k ∣ m) : k ∣ n ↔ k ∣ m + n :=
|
||
⟨Nat.dvd_add h,
|
||
match m, h with
|
||
| _, ⟨d, rfl⟩ => fun ⟨e, he⟩ =>
|
||
⟨e - d, by rw [Nat.mul_sub_left_distrib, ← he, Nat.add_sub_cancel_left]⟩⟩
|
||
|
||
protected theorem dvd_add_iff_left {k m n : Nat} (h : k ∣ n) : k ∣ m ↔ k ∣ m + n := by
|
||
rw [Nat.add_comm]; exact Nat.dvd_add_iff_right h
|
||
|
||
theorem dvd_mod_iff {k m n : Nat} (h: k ∣ n) : k ∣ m % n ↔ k ∣ m := by
|
||
have := Nat.dvd_add_iff_left (m := m % n) <| Nat.dvd_trans h <| Nat.dvd_mul_right n (m / n)
|
||
rwa [mod_add_div] at this
|
||
|
||
theorem le_of_dvd {m n : Nat} (h : 0 < n) : m ∣ n → m ≤ n
|
||
| ⟨k, e⟩ => by
|
||
revert h
|
||
rw [e]
|
||
match k with
|
||
| 0 => intro hn; simp at hn
|
||
| pk+1 =>
|
||
intro
|
||
have := Nat.mul_le_mul_left m (succ_pos pk)
|
||
rwa [Nat.mul_one] at this
|
||
|
||
protected theorem dvd_antisymm : ∀ {m n : Nat}, m ∣ n → n ∣ m → m = n
|
||
| _, 0, _, h₂ => Nat.eq_zero_of_zero_dvd h₂
|
||
| 0, _, h₁, _ => (Nat.eq_zero_of_zero_dvd h₁).symm
|
||
| _+1, _+1, h₁, h₂ => Nat.le_antisymm (le_of_dvd (succ_pos _) h₁) (le_of_dvd (succ_pos _) h₂)
|
||
|
||
theorem pos_of_dvd_of_pos {m n : Nat} (H1 : m ∣ n) (H2 : 0 < n) : 0 < m :=
|
||
Nat.pos_of_ne_zero fun m0 => Nat.ne_of_gt H2 <| Nat.eq_zero_of_zero_dvd (m0 ▸ H1)
|
||
|
||
@[simp] protected theorem one_dvd (n : Nat) : 1 ∣ n := ⟨n, n.one_mul.symm⟩
|
||
|
||
theorem eq_one_of_dvd_one {n : Nat} (H : n ∣ 1) : n = 1 := Nat.dvd_antisymm H n.one_dvd
|
||
|
||
theorem mod_eq_zero_of_dvd {m n : Nat} (H : m ∣ n) : n % m = 0 := by
|
||
let ⟨z, H⟩ := H; rw [H, mul_mod_right]
|
||
|
||
theorem dvd_of_mod_eq_zero {m n : Nat} (H : n % m = 0) : m ∣ n := by
|
||
exists n / m
|
||
have := (mod_add_div n m).symm
|
||
rwa [H, Nat.zero_add] at this
|
||
|
||
theorem dvd_iff_mod_eq_zero {m n : Nat} : m ∣ n ↔ n % m = 0 :=
|
||
⟨mod_eq_zero_of_dvd, dvd_of_mod_eq_zero⟩
|
||
|
||
instance decidable_dvd : @DecidableRel Nat Nat (·∣·) :=
|
||
fun _ _ => decidable_of_decidable_of_iff dvd_iff_mod_eq_zero.symm
|
||
|
||
theorem emod_pos_of_not_dvd {a b : Nat} (h : ¬ a ∣ b) : 0 < b % a := by
|
||
rw [dvd_iff_mod_eq_zero] at h
|
||
exact Nat.pos_of_ne_zero h
|
||
|
||
protected theorem mul_div_cancel' {n m : Nat} (H : n ∣ m) : n * (m / n) = m := by
|
||
have := mod_add_div m n
|
||
rwa [mod_eq_zero_of_dvd H, Nat.zero_add] at this
|
||
|
||
protected theorem div_mul_cancel {n m : Nat} (H : n ∣ m) : m / n * n = m := by
|
||
rw [Nat.mul_comm, Nat.mul_div_cancel' H]
|
||
|
||
@[simp] theorem mod_mod_of_dvd (a : Nat) (h : c ∣ b) : a % b % c = a % c := by
|
||
rw (occs := [2]) [← mod_add_div a b]
|
||
have ⟨x, h⟩ := h
|
||
subst h
|
||
rw [Nat.mul_assoc, add_mul_mod_self_left]
|
||
|
||
protected theorem dvd_of_mul_dvd_mul_left
|
||
(kpos : 0 < k) (H : k * m ∣ k * n) : m ∣ n := by
|
||
let ⟨l, H⟩ := H
|
||
rw [Nat.mul_assoc] at H
|
||
exact ⟨_, Nat.eq_of_mul_eq_mul_left kpos H⟩
|
||
|
||
protected theorem dvd_of_mul_dvd_mul_right (kpos : 0 < k) (H : m * k ∣ n * k) : m ∣ n := by
|
||
rw [Nat.mul_comm m k, Nat.mul_comm n k] at H; exact Nat.dvd_of_mul_dvd_mul_left kpos H
|
||
|
||
theorem dvd_sub {k m n : Nat} (H : n ≤ m) (h₁ : k ∣ m) (h₂ : k ∣ n) : k ∣ m - n :=
|
||
(Nat.dvd_add_iff_left h₂).2 <| by rwa [Nat.sub_add_cancel H]
|
||
|
||
protected theorem mul_dvd_mul {a b c d : Nat} : a ∣ b → c ∣ d → a * c ∣ b * d
|
||
| ⟨e, he⟩, ⟨f, hf⟩ =>
|
||
⟨e * f, by simp [he, hf, Nat.mul_assoc, Nat.mul_left_comm, Nat.mul_comm]⟩
|
||
|
||
protected theorem mul_dvd_mul_left (a : Nat) (h : b ∣ c) : a * b ∣ a * c :=
|
||
Nat.mul_dvd_mul (Nat.dvd_refl a) h
|
||
|
||
protected theorem mul_dvd_mul_right (h: a ∣ b) (c : Nat) : a * c ∣ b * c :=
|
||
Nat.mul_dvd_mul h (Nat.dvd_refl c)
|
||
|
||
@[simp] theorem dvd_one {n : Nat} : n ∣ 1 ↔ n = 1 :=
|
||
⟨eq_one_of_dvd_one, fun h => h.symm ▸ Nat.dvd_refl _⟩
|
||
|
||
protected theorem mul_div_assoc (m : Nat) (H : k ∣ n) : m * n / k = m * (n / k) := by
|
||
match Nat.eq_zero_or_pos k with
|
||
| .inl h0 => rw [h0, Nat.div_zero, Nat.div_zero, Nat.mul_zero]
|
||
| .inr hpos =>
|
||
have h1 : m * n / k = m * (n / k * k) / k := by rw [Nat.div_mul_cancel H]
|
||
rw [h1, ← Nat.mul_assoc, Nat.mul_div_cancel _ hpos]
|
||
|
||
/-! Helper theorems for `dvd` simproc -/
|
||
|
||
protected theorem dvd_eq_true_of_mod_eq_zero {m n : Nat} (h : n % m == 0) : (m ∣ n) = True := by
|
||
simp [Nat.dvd_of_mod_eq_zero, eq_of_beq h]
|
||
|
||
protected theorem dvd_eq_false_of_mod_ne_zero {m n : Nat} (h : n % m != 0) : (m ∣ n) = False := by
|
||
simp [eq_of_beq] at h
|
||
simp [dvd_iff_mod_eq_zero, h]
|
||
|
||
end Nat
|