Module docstring
{}
{}
Nat.gcd
definition
(m n : @& Nat) : Nat
/--
Computes the greatest common divisor of two natural numbers. The GCD of two natural numbers is the
largest natural number that evenly divides both.
In particular, the GCD of a number and `0` is the number itself.
This reference implementation via the Euclidean algorithm is overridden in both the kernel and the
compiler to efficiently evaluate using arbitrary-precision arithmetic. The definition provided here
is the logical model.
Examples:
* `Nat.gcd 10 15 = 5`
* `Nat.gcd 0 5 = 5`
* `Nat.gcd 7 0 = 7`
-/
@[extern "lean_nat_gcd"]
def gcd (m n : @& Nat) : Nat :=
if m = 0 then
n
else
gcd (n % m) m
termination_by m
decreasing_by simp_wf; apply mod_lt _ (zero_lt_of_ne_zero _); assumption
Nat.gcd_zero_left
theorem
(y : Nat) : gcd 0 y = y
@[simp] theorem gcd_zero_left (y : Nat) : gcd 0 y = y := by
rw [gcd]; rfl
Nat.gcd_succ
theorem
(x y : Nat) : gcd (succ x) y = gcd (y % succ x) (succ x)
Nat.gcd_add_one
theorem
(x y : Nat) : gcd (x + 1) y = gcd (y % (x + 1)) (x + 1)
theorem gcd_add_one (x y : Nat) : gcd (x + 1) y = gcd (y % (x + 1)) (x + 1) := by
rw [gcd]; rfl
Nat.gcd_def
theorem
(x y : Nat) : gcd x y = if x = 0 then y else gcd (y % x) x
theorem gcd_def (x y : Nat) : gcd x y = if x = 0 then y else gcd (y % x) x := by
cases x <;> simp [Nat.gcd_add_one]
Nat.gcd_one_left
theorem
(n : Nat) : gcd 1 n = 1
@[simp] theorem gcd_one_left (n : Nat) : gcd 1 n = 1 := by
rw [gcd_succ, mod_one]
rfl
Nat.gcd_zero_right
theorem
(n : Nat) : gcd n 0 = n
@[simp] theorem gcd_zero_right (n : Nat) : gcd n 0 = n := by
cases n with
| zero => simp [gcd_succ]
| succ n =>
-- `simp [gcd_succ]` produces an invalid term unless `gcd_succ` is proved with `id rfl` instead
rw [gcd_succ]
exact gcd_zero_left _
Nat.instLawfulIdentityGcdOfNat
instance
: Std.LawfulIdentity gcd 0
instance : Std.LawfulIdentity gcd 0 where
left_id := gcd_zero_left
right_id := gcd_zero_right
Nat.gcd_self
theorem
(n : Nat) : gcd n n = n
Nat.instIdempotentOpGcd
instance
: Std.IdempotentOp gcd
instance : Std.IdempotentOp gcd := ⟨gcd_self⟩
Nat.gcd_rec
theorem
(m n : Nat) : gcd m n = gcd (n % m) m
Nat.gcd.induction
theorem
{P : Nat → Nat → Prop} (m n : Nat) (H0 : ∀ n, P 0 n) (H1 : ∀ m n, 0 < m → P (n % m) m → P m n) : P m n
@[elab_as_elim] theorem gcd.induction {P : Nat → Nat → Prop} (m n : Nat)
(H0 : ∀n, P 0 n) (H1 : ∀ m n, 0 < m → P (n % m) m → P m n) : P m n :=
Nat.strongRecOn (motive := fun m => ∀ n, P m n) m
(fun
| 0, _ => H0
| _+1, IH => fun _ => H1 _ _ (succ_pos _) (IH _ (mod_lt _ (succ_pos _)) _) )
n
Nat.gcd_dvd
theorem
(m n : Nat) : (gcd m n ∣ m) ∧ (gcd m n ∣ n)
theorem gcd_dvd (m n : Nat) : (gcd m n ∣ m) ∧ (gcd m n ∣ n) := by
induction m, n using gcd.induction with
| H0 n => rw [gcd_zero_left]; exact ⟨Nat.dvd_zero n, Nat.dvd_refl n⟩
| H1 m n _ IH => rw [← gcd_rec] at IH; exact ⟨IH.2, (dvd_mod_iff IH.2).1 IH.1⟩
Nat.gcd_dvd_left
theorem
(m n : Nat) : gcd m n ∣ m
theorem gcd_dvd_left (m n : Nat) : gcdgcd m n ∣ m := (gcd_dvd m n).left
Nat.gcd_dvd_right
theorem
(m n : Nat) : gcd m n ∣ n
theorem gcd_dvd_right (m n : Nat) : gcdgcd m n ∣ n := (gcd_dvd m n).right
Nat.gcd_le_left
theorem
(n) (h : 0 < m) : gcd m n ≤ m
theorem gcd_le_left (n) (h : 0 < m) : gcd m n ≤ m := le_of_dvd h <| gcd_dvd_left m n
Nat.gcd_le_right
theorem
(n) (h : 0 < n) : gcd m n ≤ n
theorem gcd_le_right (n) (h : 0 < n) : gcd m n ≤ n := le_of_dvd h <| gcd_dvd_right m n
Nat.dvd_gcd
theorem
: k ∣ m → k ∣ n → k ∣ gcd m n
theorem dvd_gcd : k ∣ m → k ∣ n → k ∣ gcd m n := by
induction m, n using gcd.induction with intro km kn
| H0 n => rw [gcd_zero_left]; exact kn
| H1 n m _ IH => rw [gcd_rec]; exact IH ((dvd_mod_iff km).2 kn) km
Nat.dvd_gcd_iff
theorem
: k ∣ gcd m n ↔ k ∣ m ∧ k ∣ n
Nat.gcd_comm
theorem
(m n : Nat) : gcd m n = gcd n m
theorem gcd_comm (m n : Nat) : gcd m n = gcd n m :=
Nat.dvd_antisymm
(dvd_gcd (gcd_dvd_right m n) (gcd_dvd_left m n))
(dvd_gcd (gcd_dvd_right n m) (gcd_dvd_left n m))
Nat.instCommutativeGcd
instance
: Std.Commutative gcd
instance : Std.Commutative gcd := ⟨gcd_comm⟩
Nat.gcd_eq_left_iff_dvd
theorem
: gcd m n = m ↔ m ∣ n
Nat.gcd_eq_right_iff_dvd
theorem
: gcd n m = m ↔ m ∣ n
theorem gcd_eq_right_iff_dvd : gcdgcd n m = m ↔ m ∣ n := by
rw [gcd_comm]; exact gcd_eq_left_iff_dvd
Nat.gcd_assoc
theorem
(m n k : Nat) : gcd (gcd m n) k = gcd m (gcd n k)
theorem gcd_assoc (m n k : Nat) : gcd (gcd m n) k = gcd m (gcd n k) :=
Nat.dvd_antisymm
(dvd_gcd
(Nat.dvd_trans (gcd_dvd_left (gcd m n) k) (gcd_dvd_left m n))
(dvd_gcd (Nat.dvd_trans (gcd_dvd_left (gcd m n) k) (gcd_dvd_right m n))
(gcd_dvd_right (gcd m n) k)))
(dvd_gcd
(dvd_gcd (gcd_dvd_left m (gcd n k))
(Nat.dvd_trans (gcd_dvd_right m (gcd n k)) (gcd_dvd_left n k)))
(Nat.dvd_trans (gcd_dvd_right m (gcd n k)) (gcd_dvd_right n k)))
Nat.gcd_one_right
theorem
(n : Nat) : gcd n 1 = 1
@[simp] theorem gcd_one_right (n : Nat) : gcd n 1 = 1 := (gcd_comm n 1).trans (gcd_one_left n)
Nat.gcd_mul_left
theorem
(m n k : Nat) : gcd (m * n) (m * k) = m * gcd n k
theorem gcd_mul_left (m n k : Nat) : gcd (m * n) (m * k) = m * gcd n k := by
induction n, k using gcd.induction with
| H0 k => simp
| H1 n k _ IH => rwa [← mul_mod_mul_left, ← gcd_rec, ← gcd_rec] at IH
Nat.gcd_mul_right
theorem
(m n k : Nat) : gcd (m * n) (k * n) = gcd m k * n
theorem gcd_mul_right (m n k : Nat) : gcd (m * n) (k * n) = gcd m k * n := by
rw [Nat.mul_comm m n, Nat.mul_comm k n, Nat.mul_comm (gcd m k) n, gcd_mul_left]
Nat.gcd_pos_of_pos_left
theorem
{m : Nat} (n : Nat) (mpos : 0 < m) : 0 < gcd m n
theorem gcd_pos_of_pos_left {m : Nat} (n : Nat) (mpos : 0 < m) : 0 < gcd m n :=
pos_of_dvd_of_pos (gcd_dvd_left m n) mpos
Nat.gcd_pos_of_pos_right
theorem
(m : Nat) {n : Nat} (npos : 0 < n) : 0 < gcd m n
theorem gcd_pos_of_pos_right (m : Nat) {n : Nat} (npos : 0 < n) : 0 < gcd m n :=
pos_of_dvd_of_pos (gcd_dvd_right m n) npos
Nat.div_gcd_pos_of_pos_left
theorem
(b : Nat) (h : 0 < a) : 0 < a / a.gcd b
theorem div_gcd_pos_of_pos_left (b : Nat) (h : 0 < a) : 0 < a / a.gcd b :=
(Nat.le_div_iff_mul_le <| Nat.gcd_pos_of_pos_left _ h).2 (Nat.one_mul _ ▸ Nat.gcd_le_left _ h)
Nat.div_gcd_pos_of_pos_right
theorem
(a : Nat) (h : 0 < b) : 0 < b / a.gcd b
theorem div_gcd_pos_of_pos_right (a : Nat) (h : 0 < b) : 0 < b / a.gcd b :=
(Nat.le_div_iff_mul_le <| Nat.gcd_pos_of_pos_right _ h).2 (Nat.one_mul _ ▸ Nat.gcd_le_right _ h)
Nat.gcd_ne_zero_left
theorem
: m ≠ 0 → gcd m n ≠ 0
theorem gcd_ne_zero_left : m ≠ 0 → gcdgcd m n ≠ 0 := mt eq_zero_of_gcd_eq_zero_left
Nat.gcd_ne_zero_right
theorem
: n ≠ 0 → gcd m n ≠ 0
theorem gcd_ne_zero_right : n ≠ 0 → gcdgcd m n ≠ 0 := mt eq_zero_of_gcd_eq_zero_right
Nat.gcd_div
theorem
{m n k : Nat} (H1 : k ∣ m) (H2 : k ∣ n) : gcd (m / k) (n / k) = gcd m n / k
theorem gcd_div {m n k : Nat} (H1 : k ∣ m) (H2 : k ∣ n) :
gcd (m / k) (n / k) = gcd m n / k :=
match eq_zero_or_pos k with
| .inl H0 => by simp [H0]
| .inr H3 => by
apply Nat.eq_of_mul_eq_mul_right H3
rw [Nat.div_mul_cancel (dvd_gcd H1 H2), ← gcd_mul_right,
Nat.div_mul_cancel H1, Nat.div_mul_cancel H2]
Nat.gcd_dvd_gcd_of_dvd_left
theorem
{m k : Nat} (n : Nat) (H : m ∣ k) : gcd m n ∣ gcd k n
theorem gcd_dvd_gcd_of_dvd_left {m k : Nat} (n : Nat) (H : m ∣ k) : gcdgcd m n ∣ gcd k n :=
dvd_gcd (Nat.dvd_trans (gcd_dvd_left m n) H) (gcd_dvd_right m n)
Nat.gcd_dvd_gcd_of_dvd_right
theorem
{m k : Nat} (n : Nat) (H : m ∣ k) : gcd n m ∣ gcd n k
theorem gcd_dvd_gcd_of_dvd_right {m k : Nat} (n : Nat) (H : m ∣ k) : gcdgcd n m ∣ gcd n k :=
dvd_gcd (gcd_dvd_left n m) (Nat.dvd_trans (gcd_dvd_right n m) H)
Nat.gcd_dvd_gcd_mul_left_left
theorem
(m n k : Nat) : gcd m n ∣ gcd (k * m) n
theorem gcd_dvd_gcd_mul_left_left (m n k : Nat) : gcdgcd m n ∣ gcd (k * m) n :=
gcd_dvd_gcd_of_dvd_left _ (Nat.dvd_mul_left _ _)
Nat.gcd_dvd_gcd_mul_left
theorem
(m n k : Nat) : gcd m n ∣ gcd (k * m) n
@[deprecated gcd_dvd_gcd_mul_left_left (since := "2025-04-01")]
theorem gcd_dvd_gcd_mul_left (m n k : Nat) : gcdgcd m n ∣ gcd (k * m) n :=
gcd_dvd_gcd_mul_left_left m n k
Nat.gcd_dvd_gcd_mul_right_left
theorem
(m n k : Nat) : gcd m n ∣ gcd (m * k) n
theorem gcd_dvd_gcd_mul_right_left (m n k : Nat) : gcdgcd m n ∣ gcd (m * k) n :=
gcd_dvd_gcd_of_dvd_left _ (Nat.dvd_mul_right _ _)
Nat.gcd_dvd_gcd_mul_right
theorem
(m n k : Nat) : gcd m n ∣ gcd (m * k) n
@[deprecated gcd_dvd_gcd_mul_right_left (since := "2025-04-01")]
theorem gcd_dvd_gcd_mul_right (m n k : Nat) : gcdgcd m n ∣ gcd (m * k) n :=
gcd_dvd_gcd_mul_right_left m n k
Nat.gcd_dvd_gcd_mul_left_right
theorem
(m n k : Nat) : gcd m n ∣ gcd m (k * n)
theorem gcd_dvd_gcd_mul_left_right (m n k : Nat) : gcdgcd m n ∣ gcd m (k * n) :=
gcd_dvd_gcd_of_dvd_right _ (Nat.dvd_mul_left _ _)
Nat.gcd_dvd_gcd_mul_right_right
theorem
(m n k : Nat) : gcd m n ∣ gcd m (n * k)
theorem gcd_dvd_gcd_mul_right_right (m n k : Nat) : gcdgcd m n ∣ gcd m (n * k) :=
gcd_dvd_gcd_of_dvd_right _ (Nat.dvd_mul_right _ _)
Nat.gcd_eq_left
theorem
{m n : Nat} (H : m ∣ n) : gcd m n = m
theorem gcd_eq_left {m n : Nat} (H : m ∣ n) : gcd m n = m :=
Nat.dvd_antisymm (gcd_dvd_left _ _) (dvd_gcd (Nat.dvd_refl _) H)
Nat.gcd_eq_right
theorem
{m n : Nat} (H : n ∣ m) : gcd m n = n
theorem gcd_eq_right {m n : Nat} (H : n ∣ m) : gcd m n = n := by
rw [gcd_comm, gcd_eq_left H]
Nat.gcd_right_eq_iff
theorem
{m n n' : Nat} : gcd m n = gcd m n' ↔ ∀ k, k ∣ m → (k ∣ n ↔ k ∣ n')
theorem gcd_right_eq_iff {m n n' : Nat} : gcdgcd m n = gcd m n' ↔ ∀ k, k ∣ m → (k ∣ n ↔ k ∣ n') := by
refine ⟨fun h k hkm => ⟨fun hkn => ?_, fun hkn' => ?_⟩, fun h => Nat.dvd_antisymm ?_ ?_⟩
· exact Nat.dvd_trans (h ▸ dvd_gcd hkm hkn) (Nat.gcd_dvd_right m n')
· exact Nat.dvd_trans (h ▸ dvd_gcd hkm hkn') (Nat.gcd_dvd_right m n)
· exact dvd_gcd_iff.2 ⟨gcd_dvd_left _ _, (h _ (gcd_dvd_left _ _)).1 (gcd_dvd_right _ _)⟩
· exact dvd_gcd_iff.2 ⟨gcd_dvd_left _ _, (h _ (gcd_dvd_left _ _)).2 (gcd_dvd_right _ _)⟩
Nat.gcd_left_eq_iff
theorem
{m m' n : Nat} : gcd m n = gcd m' n ↔ ∀ k, k ∣ n → (k ∣ m ↔ k ∣ m')
theorem gcd_left_eq_iff {m m' n : Nat} : gcdgcd m n = gcd m' n ↔ ∀ k, k ∣ n → (k ∣ m ↔ k ∣ m') := by
rw [gcd_comm m n, gcd_comm m' n, gcd_right_eq_iff]
Nat.gcd_mul_left_left
theorem
(m n : Nat) : gcd (m * n) n = n
@[simp] theorem gcd_mul_left_left (m n : Nat) : gcd (m * n) n = n :=
Nat.dvd_antisymm (gcd_dvd_right _ _) (dvd_gcd (Nat.dvd_mul_left _ _) (Nat.dvd_refl _))
Nat.gcd_mul_left_right
theorem
(m n : Nat) : gcd n (m * n) = n
@[simp] theorem gcd_mul_left_right (m n : Nat) : gcd n (m * n) = n := by
rw [gcd_comm, gcd_mul_left_left]
Nat.gcd_mul_right_left
theorem
(m n : Nat) : gcd (n * m) n = n
@[simp] theorem gcd_mul_right_left (m n : Nat) : gcd (n * m) n = n := by
rw [Nat.mul_comm, gcd_mul_left_left]
Nat.gcd_mul_right_right
theorem
(m n : Nat) : gcd n (n * m) = n
@[simp] theorem gcd_mul_right_right (m n : Nat) : gcd n (n * m) = n := by
rw [gcd_comm, gcd_mul_right_left]
Nat.gcd_gcd_self_right_left
theorem
(m n : Nat) : gcd m (gcd m n) = gcd m n
@[simp] theorem gcd_gcd_self_right_left (m n : Nat) : gcd m (gcd m n) = gcd m n :=
Nat.dvd_antisymm (gcd_dvd_right _ _) (dvd_gcd (gcd_dvd_left _ _) (Nat.dvd_refl _))
Nat.gcd_gcd_self_right_right
theorem
(m n : Nat) : gcd m (gcd n m) = gcd n m
@[simp] theorem gcd_gcd_self_right_right (m n : Nat) : gcd m (gcd n m) = gcd n m := by
rw [gcd_comm n m, gcd_gcd_self_right_left]
Nat.gcd_gcd_self_left_right
theorem
(m n : Nat) : gcd (gcd n m) m = gcd n m
@[simp] theorem gcd_gcd_self_left_right (m n : Nat) : gcd (gcd n m) m = gcd n m := by
rw [gcd_comm, gcd_gcd_self_right_right]
Nat.gcd_gcd_self_left_left
theorem
(m n : Nat) : gcd (gcd m n) m = gcd m n
@[simp] theorem gcd_gcd_self_left_left (m n : Nat) : gcd (gcd m n) m = gcd m n := by
rw [gcd_comm m n, gcd_gcd_self_left_right]
Nat.gcd_add_mul_right_right
theorem
(m n k : Nat) : gcd m (n + k * m) = gcd m n
Nat.gcd_add_mul_self
theorem
(m n k : Nat) : gcd m (n + k * m) = gcd m n
@[deprecated gcd_add_mul_right_right (since := "2025-03-31")]
theorem gcd_add_mul_self (m n k : Nat) : gcd m (n + k * m) = gcd m n :=
gcd_add_mul_right_right _ _ _
Nat.gcd_add_mul_left_right
theorem
(m n k : Nat) : gcd m (n + m * k) = gcd m n
@[simp] theorem gcd_add_mul_left_right (m n k : Nat) : gcd m (n + m * k) = gcd m n := by
rw [Nat.mul_comm, gcd_add_mul_right_right]
Nat.gcd_mul_right_add_right
theorem
(m n k : Nat) : gcd m (k * m + n) = gcd m n
@[simp] theorem gcd_mul_right_add_right (m n k : Nat) : gcd m (k * m + n) = gcd m n := by
rw [Nat.add_comm, gcd_add_mul_right_right]
Nat.gcd_mul_left_add_right
theorem
(m n k : Nat) : gcd m (m * k + n) = gcd m n
@[simp] theorem gcd_mul_left_add_right (m n k : Nat) : gcd m (m * k + n) = gcd m n := by
rw [Nat.add_comm, gcd_add_mul_left_right]
Nat.gcd_add_mul_right_left
theorem
(m n k : Nat) : gcd (n + k * m) m = gcd n m
@[simp] theorem gcd_add_mul_right_left (m n k : Nat) : gcd (n + k * m) m = gcd n m := by
rw [gcd_comm, gcd_add_mul_right_right, gcd_comm]
Nat.gcd_add_mul_left_left
theorem
(m n k : Nat) : gcd (n + m * k) m = gcd n m
@[simp] theorem gcd_add_mul_left_left (m n k : Nat) : gcd (n + m * k) m = gcd n m := by
rw [Nat.mul_comm, gcd_add_mul_right_left]
Nat.gcd_mul_right_add_left
theorem
(m n k : Nat) : gcd (k * m + n) m = gcd n m
@[simp] theorem gcd_mul_right_add_left (m n k : Nat) : gcd (k * m + n) m = gcd n m := by
rw [Nat.add_comm, gcd_add_mul_right_left]
Nat.gcd_mul_left_add_left
theorem
(m n k : Nat) : gcd (m * k + n) m = gcd n m
@[simp] theorem gcd_mul_left_add_left (m n k : Nat) : gcd (m * k + n) m = gcd n m := by
rw [Nat.add_comm, gcd_add_mul_left_left]
Nat.gcd_add_self_right
theorem
(m n : Nat) : gcd m (n + m) = gcd m n
@[simp] theorem gcd_add_self_right (m n : Nat) : gcd m (n + m) = gcd m n := by
simpa using gcd_add_mul_right_right _ _ 1
Nat.gcd_self_add_right
theorem
(m n : Nat) : gcd m (m + n) = gcd m n
@[simp] theorem gcd_self_add_right (m n : Nat) : gcd m (m + n) = gcd m n := by
simpa using gcd_mul_right_add_right _ _ 1
Nat.gcd_add_self_left
theorem
(m n : Nat) : gcd (n + m) m = gcd n m
@[simp] theorem gcd_add_self_left (m n : Nat) : gcd (n + m) m = gcd n m := by
simpa using gcd_add_mul_right_left _ _ 1
Nat.gcd_self_add_left
theorem
(m n : Nat) : gcd (m + n) m = gcd n m
@[simp] theorem gcd_self_add_left (m n : Nat) : gcd (m + n) m = gcd n m := by
simpa using gcd_mul_right_add_left _ _ 1
Nat.gcd_add_left_left_of_dvd
theorem
{m k : Nat} (n : Nat) : m ∣ k → gcd (k + n) m = gcd n m
@[simp] theorem gcd_add_left_left_of_dvd {m k : Nat} (n : Nat) :
m ∣ k → gcd (k + n) m = gcd n m := by
rintro ⟨l, rfl⟩; exact gcd_mul_left_add_left m n l
Nat.gcd_add_right_left_of_dvd
theorem
{m k : Nat} (n : Nat) : m ∣ k → gcd (n + k) m = gcd n m
@[simp] theorem gcd_add_right_left_of_dvd {m k : Nat} (n : Nat) :
m ∣ k → gcd (n + k) m = gcd n m := by
rintro ⟨l, rfl⟩; exact gcd_add_mul_left_left m n l
Nat.gcd_add_left_right_of_dvd
theorem
{n k : Nat} (m : Nat) : n ∣ k → gcd n (k + m) = gcd n m
@[simp] theorem gcd_add_left_right_of_dvd {n k : Nat} (m : Nat) :
n ∣ k → gcd n (k + m) = gcd n m := by
rintro ⟨l, rfl⟩; exact gcd_mul_left_add_right n m l
Nat.gcd_add_right_right_of_dvd
theorem
{n k : Nat} (m : Nat) : n ∣ k → gcd n (m + k) = gcd n m
@[simp] theorem gcd_add_right_right_of_dvd {n k : Nat} (m : Nat) :
n ∣ k → gcd n (m + k) = gcd n m := by
rintro ⟨l, rfl⟩; exact gcd_add_mul_left_right n m l
Nat.gcd_sub_mul_right_right
theorem
{m n k : Nat} (h : k * m ≤ n) : gcd m (n - k * m) = gcd m n
@[simp] theorem gcd_sub_mul_right_right {m n k : Nat} (h : k * m ≤ n) :
gcd m (n - k * m) = gcd m n := by
rw [← gcd_add_mul_right_right m (n - k * m) k, Nat.sub_add_cancel h]
Nat.gcd_sub_mul_left_right
theorem
{m n k : Nat} (h : m * k ≤ n) : gcd m (n - m * k) = gcd m n
@[simp] theorem gcd_sub_mul_left_right {m n k : Nat} (h : m * k ≤ n) :
gcd m (n - m * k) = gcd m n := by
rw [← gcd_add_mul_left_right m (n - m * k) k, Nat.sub_add_cancel h]
Nat.gcd_mul_right_sub_right
theorem
{m n k : Nat} (h : n ≤ k * m) : gcd m (k * m - n) = gcd m n
@[simp] theorem gcd_mul_right_sub_right {m n k : Nat} (h : n ≤ k * m) :
gcd m (k * m - n) = gcd m n :=
gcd_right_eq_iff.2 fun _ hl => dvd_sub_iff_right h (Nat.dvd_mul_left_of_dvd hl _)
Nat.gcd_mul_left_sub_right
theorem
{m n k : Nat} (h : n ≤ m * k) : gcd m (m * k - n) = gcd m n
@[simp] theorem gcd_mul_left_sub_right {m n k : Nat} (h : n ≤ m * k) :
gcd m (m * k - n) = gcd m n := by
rw [Nat.mul_comm, gcd_mul_right_sub_right (Nat.mul_comm _ _ ▸ h)]
Nat.gcd_sub_mul_right_left
theorem
{m n k : Nat} (h : k * m ≤ n) : gcd (n - k * m) m = gcd n m
@[simp] theorem gcd_sub_mul_right_left {m n k : Nat} (h : k * m ≤ n) :
gcd (n - k * m) m = gcd n m := by
rw [gcd_comm, gcd_sub_mul_right_right h, gcd_comm]
Nat.gcd_sub_mul_left_left
theorem
{m n k : Nat} (h : m * k ≤ n) : gcd (n - m * k) m = gcd n m
@[simp] theorem gcd_sub_mul_left_left {m n k : Nat} (h : m * k ≤ n) :
gcd (n - m * k) m = gcd n m := by
rw [Nat.mul_comm, gcd_sub_mul_right_left (Nat.mul_comm _ _ ▸ h)]
Nat.gcd_mul_right_sub_left
theorem
{m n k : Nat} (h : n ≤ k * m) : gcd (k * m - n) m = gcd n m
@[simp] theorem gcd_mul_right_sub_left {m n k : Nat} (h : n ≤ k * m) :
gcd (k * m - n) m = gcd n m := by
rw [gcd_comm, gcd_mul_right_sub_right h, gcd_comm]
Nat.gcd_mul_left_sub_left
theorem
{m n k : Nat} (h : n ≤ m * k) : gcd (m * k - n) m = gcd n m
@[simp] theorem gcd_mul_left_sub_left {m n k : Nat} (h : n ≤ m * k) :
gcd (m * k - n) m = gcd n m := by
rw [Nat.mul_comm, gcd_mul_right_sub_left (Nat.mul_comm _ _ ▸ h)]
Nat.gcd_sub_self_right
theorem
{m n : Nat} (h : m ≤ n) : gcd m (n - m) = gcd m n
@[simp] theorem gcd_sub_self_right {m n : Nat} (h : m ≤ n) : gcd m (n - m) = gcd m n := by
simpa using gcd_sub_mul_right_right (k := 1) (by simpa using h)
Nat.gcd_self_sub_right
theorem
{m n : Nat} (h : n ≤ m) : gcd m (m - n) = gcd m n
@[simp] theorem gcd_self_sub_right {m n : Nat} (h : n ≤ m) : gcd m (m - n) = gcd m n := by
simpa using gcd_mul_right_sub_right (k := 1) (by simpa using h)
Nat.gcd_sub_self_left
theorem
{m n : Nat} (h : m ≤ n) : gcd (n - m) m = gcd n m
@[simp] theorem gcd_sub_self_left {m n : Nat} (h : m ≤ n) : gcd (n - m) m = gcd n m := by
simpa using gcd_sub_mul_right_left (k := 1) (by simpa using h)
Nat.gcd_self_sub_left
theorem
{m n : Nat} (h : n ≤ m) : gcd (m - n) m = gcd n m
@[simp] theorem gcd_self_sub_left {m n : Nat} (h : n ≤ m) : gcd (m - n) m = gcd n m := by
simpa using gcd_mul_right_sub_left (k := 1) (by simpa using h)
Nat.gcd_sub_left_left_of_dvd
theorem
{n k : Nat} (m : Nat) (h : n ≤ k) : m ∣ k → gcd (k - n) m = gcd n m
@[simp] theorem gcd_sub_left_left_of_dvd {n k : Nat} (m : Nat) (h : n ≤ k) :
m ∣ k → gcd (k - n) m = gcd n m := by
rintro ⟨l, rfl⟩; exact gcd_mul_left_sub_left h
Nat.gcd_sub_right_left_of_dvd
theorem
{n k : Nat} (m : Nat) (h : k ≤ n) : m ∣ k → gcd (n - k) m = gcd n m
@[simp] theorem gcd_sub_right_left_of_dvd {n k : Nat} (m : Nat) (h : k ≤ n) :
m ∣ k → gcd (n - k) m = gcd n m := by
rintro ⟨l, rfl⟩; exact gcd_sub_mul_left_left h
Nat.gcd_sub_left_right_of_dvd
theorem
{m k : Nat} (n : Nat) (h : m ≤ k) : n ∣ k → gcd n (k - m) = gcd n m
@[simp] theorem gcd_sub_left_right_of_dvd {m k : Nat} (n : Nat) (h : m ≤ k) :
n ∣ k → gcd n (k - m) = gcd n m := by
rintro ⟨l, rfl⟩; exact gcd_mul_left_sub_right h
Nat.gcd_sub_right_right_of_dvd
theorem
{m k : Nat} (n : Nat) (h : k ≤ m) : n ∣ k → gcd n (m - k) = gcd n m
@[simp] theorem gcd_sub_right_right_of_dvd {m k : Nat} (n : Nat) (h : k ≤ m) :
n ∣ k → gcd n (m - k) = gcd n m := by
rintro ⟨l, rfl⟩; exact gcd_sub_mul_left_right h
Nat.gcd_eq_zero_iff
theorem
{i j : Nat} : gcd i j = 0 ↔ i = 0 ∧ j = 0
@[simp] theorem gcd_eq_zero_iff {i j : Nat} : gcdgcd i j = 0 ↔ i = 0 ∧ j = 0 :=
⟨fun h => ⟨eq_zero_of_gcd_eq_zero_left h, eq_zero_of_gcd_eq_zero_right h⟩,
fun h => by simp [h]⟩
Nat.gcd_eq_iff
theorem
{a b : Nat} : gcd a b = g ↔ g ∣ a ∧ g ∣ b ∧ (∀ c, c ∣ a → c ∣ b → c ∣ g)
/-- Characterization of the value of `Nat.gcd`. -/
theorem gcd_eq_iff {a b : Nat} :
gcdgcd a b = g ↔ g ∣ a ∧ g ∣ b ∧ (∀ c, c ∣ a → c ∣ b → c ∣ g) := by
constructor
· rintro rfl
exact ⟨gcd_dvd_left _ _, gcd_dvd_right _ _, fun _ => Nat.dvd_gcd⟩
· rintro ⟨ha, hb, hc⟩
apply Nat.dvd_antisymm
· apply hc
· exact gcd_dvd_left a b
· exact gcd_dvd_right a b
· exact Nat.dvd_gcd ha hb
Nat.dvdProdDvdOfDvdProd
definition
{k m n : Nat} (h : k ∣ m * n) : { d : { m' // m' ∣ m } × { n' // n' ∣ n } // k = d.1.val * d.2.val }
/-- Represent a divisor of `m * n` as a product of a divisor of `m` and a divisor of `n`. -/
def dvdProdDvdOfDvdProd {k m n : Nat} (h : k ∣ m * n) :
{d : {m' // m' ∣ m} × {n' // n' ∣ n} // k = d.1.val * d.2.val} :=
if h0 : gcd k m = 0 then
⟨⟨⟨0, eq_zero_of_gcd_eq_zero_right h0 ▸ Nat.dvd_refl 0⟩,
⟨n, Nat.dvd_refl n⟩⟩,
eq_zero_of_gcd_eq_zero_left h0 ▸ (Nat.zero_mul n).symm⟩
else by
have hd : gcd k m * (k / gcd k m) = k := Nat.mul_div_cancel' (gcd_dvd_left k m)
refine ⟨⟨⟨gcd k m, gcd_dvd_right k m⟩, ⟨k / gcd k m, ?_⟩⟩, hd.symm⟩
apply Nat.dvd_of_mul_dvd_mul_left (Nat.pos_of_ne_zero h0)
rw [hd, ← gcd_mul_right]
exact Nat.dvd_gcd (Nat.dvd_mul_right _ _) h
Nat.prod_dvd_and_dvd_of_dvd_prod
definition
{k m n : Nat} (H : k ∣ m * n) : { d : { m' // m' ∣ m } × { n' // n' ∣ n } // k = d.1.val * d.2.val }
@[inherit_doc dvdProdDvdOfDvdProd, deprecated dvdProdDvdOfDvdProd (since := "2025-04-01")]
def prod_dvd_and_dvd_of_dvd_prod {k m n : Nat} (H : k ∣ m * n) :
{d : {m' // m' ∣ m} × {n' // n' ∣ n} // k = d.1.val * d.2.val} :=
dvdProdDvdOfDvdProd H
Nat.dvd_mul
theorem
{k m n : Nat} : k ∣ m * n ↔ ∃ k₁ k₂, k₁ ∣ m ∧ k₂ ∣ n ∧ k₁ * k₂ = k
protected theorem dvd_mul {k m n : Nat} : k ∣ m * nk ∣ m * n ↔ ∃ k₁ k₂, k₁ ∣ m ∧ k₂ ∣ n ∧ k₁ * k₂ = k := by
refine ⟨fun h => ?_, ?_⟩
· obtain ⟨⟨⟨k₁, hk₁⟩, ⟨k₂, hk₂⟩⟩, rfl⟩ := dvdProdDvdOfDvdProd h
exact ⟨k₁, k₂, hk₁, hk₂, rfl⟩
· rintro ⟨k₁, k₂, hk₁, hk₂, rfl⟩
exact Nat.mul_dvd_mul hk₁ hk₂
Nat.gcd_mul_dvd_mul_gcd
theorem
(k m n : Nat) : gcd k (m * n) ∣ gcd k m * gcd k n
theorem gcd_mul_dvd_mul_gcd (k m n : Nat) : gcdgcd k (m * n) ∣ gcd k m * gcd k n := by
let ⟨⟨⟨m', hm'⟩, ⟨n', hn'⟩⟩, (h : gcd k (m * n) = m' * n')⟩ :=
dvdProdDvdOfDvdProd <| gcd_dvd_right k (m * n)
rw [h]
have h' : m' * n' ∣ k := h ▸ gcd_dvd_left ..
exact Nat.mul_dvd_mul
(dvd_gcd (Nat.dvd_trans (Nat.dvd_mul_right m' n') h') hm')
(dvd_gcd (Nat.dvd_trans (Nat.dvd_mul_left n' m') h') hn')
Nat.dvd_gcd_mul_iff_dvd_mul
theorem
{k n m : Nat} : k ∣ gcd k n * m ↔ k ∣ n * m
theorem dvd_gcd_mul_iff_dvd_mul {k n m : Nat} : k ∣ gcd k n * mk ∣ gcd k n * m ↔ k ∣ n * m := by
refine ⟨(Nat.dvd_trans · <| Nat.mul_dvd_mul_right (k.gcd_dvd_right n) m), fun ⟨y, hy⟩ ↦ ?_⟩
rw [← gcd_mul_right, hy, gcd_mul_left]
exact Nat.dvd_mul_right k (gcd m y)
Nat.dvd_mul_gcd_iff_dvd_mul
theorem
{k n m : Nat} : k ∣ n * gcd k m ↔ k ∣ n * m
theorem dvd_mul_gcd_iff_dvd_mul {k n m : Nat} : k ∣ n * gcd k mk ∣ n * gcd k m ↔ k ∣ n * m := by
rw [Nat.mul_comm, dvd_gcd_mul_iff_dvd_mul, Nat.mul_comm]
Nat.dvd_gcd_mul_gcd_iff_dvd_mul
theorem
{k n m : Nat} : k ∣ gcd k n * gcd k m ↔ k ∣ n * m
theorem dvd_gcd_mul_gcd_iff_dvd_mul {k n m : Nat} : k ∣ gcd k n * gcd k mk ∣ gcd k n * gcd k m ↔ k ∣ n * m := by
rw [dvd_gcd_mul_iff_dvd_mul, dvd_mul_gcd_iff_dvd_mul]
Nat.gcd_eq_one_iff
theorem
{m n : Nat} : gcd m n = 1 ↔ ∀ c, c ∣ m → c ∣ n → c = 1
theorem gcd_eq_one_iff {m n : Nat} : gcdgcd m n = 1 ↔ ∀ c, c ∣ m → c ∣ n → c = 1 := by
simp [gcd_eq_iff]
Nat.gcd_mul_right_right_of_gcd_eq_one
theorem
{n m k : Nat} : gcd n m = 1 → gcd n (m * k) = gcd n k
theorem gcd_mul_right_right_of_gcd_eq_one {n m k : Nat} : gcd n m = 1 → gcd n (m * k) = gcd n k := by
rw [gcd_right_eq_iff, gcd_eq_one_iff]
refine fun h l hl₁ => ⟨?_, fun a => Nat.dvd_mul_left_of_dvd a m⟩
rw [Nat.dvd_mul]
rintro ⟨k₁, k₂, hk₁, hk₂, rfl⟩
obtain rfl : k₁ = 1 := h _ (Nat.dvd_trans (Nat.dvd_mul_right k₁ k₂) hl₁) hk₁
simpa
Nat.gcd_mul_left_right_of_gcd_eq_one
theorem
{n m k : Nat} (h : gcd n m = 1) : gcd n (k * m) = gcd n k
theorem gcd_mul_left_right_of_gcd_eq_one {n m k : Nat} (h : gcd n m = 1) :
gcd n (k * m) = gcd n k := by
rw [Nat.mul_comm, gcd_mul_right_right_of_gcd_eq_one h]
Nat.gcd_mul_right_left_of_gcd_eq_one
theorem
{n m k : Nat} (h : gcd n m = 1) : gcd (n * k) m = gcd k m
theorem gcd_mul_right_left_of_gcd_eq_one {n m k : Nat} (h : gcd n m = 1) :
gcd (n * k) m = gcd k m := by
rw [gcd_comm, gcd_mul_right_right_of_gcd_eq_one (gcd_comm _ _ ▸ h), gcd_comm]
Nat.gcd_mul_left_left_of_gcd_eq_one
theorem
{n m k : Nat} (h : gcd n m = 1) : gcd (k * n) m = gcd k m
theorem gcd_mul_left_left_of_gcd_eq_one {n m k : Nat} (h : gcd n m = 1) :
gcd (k * n) m = gcd k m := by
rw [Nat.mul_comm, gcd_mul_right_left_of_gcd_eq_one h]
Nat.gcd_pow_left_of_gcd_eq_one
theorem
{k n m : Nat} (h : gcd n m = 1) : gcd (n ^ k) m = 1
theorem gcd_pow_left_of_gcd_eq_one {k n m : Nat} (h : gcd n m = 1) : gcd (n ^ k) m = 1 := by
induction k with
| zero => simp [Nat.pow_zero]
| succ k ih => rw [Nat.pow_succ, gcd_mul_left_left_of_gcd_eq_one h, ih]
Nat.gcd_pow_right_of_gcd_eq_one
theorem
{k n m : Nat} (h : gcd n m = 1) : gcd n (m ^ k) = 1
theorem gcd_pow_right_of_gcd_eq_one {k n m : Nat} (h : gcd n m = 1) : gcd n (m ^ k) = 1 := by
rw [gcd_comm, gcd_pow_left_of_gcd_eq_one (gcd_comm _ _ ▸ h)]
Nat.pow_gcd_pow_of_gcd_eq_one
theorem
{k l n m : Nat} (h : gcd n m = 1) : gcd (n ^ k) (m ^ l) = 1
theorem pow_gcd_pow_of_gcd_eq_one {k l n m : Nat} (h : gcd n m = 1) : gcd (n ^ k) (m ^ l) = 1 :=
gcd_pow_left_of_gcd_eq_one (gcd_pow_right_of_gcd_eq_one h)
Nat.gcd_div_gcd_div_gcd_of_pos_left
theorem
{n m : Nat} (h : 0 < n) : gcd (n / gcd n m) (m / gcd n m) = 1
theorem gcd_div_gcd_div_gcd_of_pos_left {n m : Nat} (h : 0 < n) :
gcd (n / gcd n m) (m / gcd n m) = 1 := by
rw [gcd_div (gcd_dvd_left _ _) (gcd_dvd_right _ _), Nat.div_self (gcd_pos_of_pos_left _ h)]
Nat.gcd_div_gcd_div_gcd_of_pos_right
theorem
{n m : Nat} (h : 0 < m) : gcd (n / gcd n m) (m / gcd n m) = 1
theorem gcd_div_gcd_div_gcd_of_pos_right {n m : Nat} (h : 0 < m) :
gcd (n / gcd n m) (m / gcd n m) = 1 := by
rw [gcd_div (gcd_dvd_left _ _) (gcd_dvd_right _ _), Nat.div_self (gcd_pos_of_pos_right _ h)]
Nat.pow_gcd_pow
theorem
{k n m : Nat} : gcd (n ^ k) (m ^ k) = (gcd n m) ^ k
theorem pow_gcd_pow {k n m : Nat} : gcd (n ^ k) (m ^ k) = (gcd n m) ^ k := by
refine (Nat.eq_zero_or_pos n).elim (by rintro rfl; cases k <;> simp [Nat.pow_zero]) (fun hn => ?_)
conv => lhs; rw [← Nat.div_mul_cancel (gcd_dvd_left n m)]
conv => lhs; arg 2; rw [← Nat.div_mul_cancel (gcd_dvd_right n m)]
rw [Nat.mul_pow, Nat.mul_pow, gcd_mul_right, pow_gcd_pow_of_gcd_eq_one, Nat.one_mul]
exact gcd_div_gcd_div_gcd_of_pos_left hn
Nat.pow_dvd_pow_iff
theorem
{a b n : Nat} (h : n ≠ 0) : a ^ n ∣ b ^ n ↔ a ∣ b
theorem pow_dvd_pow_iff {a b n : Nat} (h : n ≠ 0) : a ^ n ∣ b ^ na ^ n ∣ b ^ n ↔ a ∣ b := by
rw [← gcd_eq_left_iff_dvd, ← gcd_eq_left_iff_dvd, pow_gcd_pow, Nat.pow_left_inj h]