File: Mathlib/Data/Int/GCD.lean

full_name: Nat.xgcdAux
code: /-- Helper function for the extended GCD algorithm (`Nat.xgcd`). -/
def xgcdAux : ℕ → ℤ → ℤ → ℕ → ℤ → ℤ → ℕ × ℤ × ℤ
  
goal: ℕ → ℤ → ℤ → ℕ → ℤ → ℤ → ℕ × ℤ × ℤ

full_name: Nat.xgcd_zero_left
code: @[simp]
theorem xgcd_zero_left {s t r' s' t'} : xgcdAux 0 s t r' s' t' = (r', s', t') 
goal: Nat.xgcdAux 0 s t r' s' t' = (r', s', t')

full_name: Nat.xgcdAux_rec
code: theorem xgcdAux_rec {r s t r' s' t'} (h : 0 < r) :
    xgcdAux r s t r' s' t' = xgcdAux (r' % r) (s' - r' / r * s) (t' - r' / r * t) r s t 
goal: r.xgcdAux s t r' s' t' = (r' % r).xgcdAux (s' - ↑r' / ↑r * s) (t' - ↑r' / ↑r * t) r s t

full_name: Nat.xgcd
code: /-- Use the extended GCD algorithm to generate the `a` and `b` values
  satisfying `gcd x y = x * a + y * b`. -/
def xgcd (x y : ℕ) : ℤ × ℤ 
goal: ℤ × ℤ

full_name: Nat.gcdA
code: /-- The extended GCD `a` value in the equation `gcd x y = x * a + y * b`. -/
def gcdA (x y : ℕ) : ℤ 
goal: ℤ

full_name: Nat.gcdB
code: /-- The extended GCD `b` value in the equation `gcd x y = x * a + y * b`. -/
def gcdB (x y : ℕ) : ℤ 
goal: ℤ

full_name: Nat.gcdA_zero_left
code: @[simp]
theorem gcdA_zero_left {s : ℕ} : gcdA 0 s = 0 
goal: Nat.gcdA 0 s = 0

full_name: Nat.gcdB_zero_left
code: @[simp]
theorem gcdB_zero_left {s : ℕ} : gcdB 0 s = 1 
goal: Nat.gcdB 0 s = 1

full_name: Nat.gcdA_zero_right
code: @[simp]
theorem gcdA_zero_right {s : ℕ} (h : s ≠ 0) : gcdA s 0 = 1 
goal: s.gcdA 0 = 1

full_name: Nat.gcdB_zero_right
code: @[simp]
theorem gcdB_zero_right {s : ℕ} (h : s ≠ 0) : gcdB s 0 = 0 
goal: s.gcdB 0 = 0

full_name: Nat.xgcdAux_fst
code: @[simp]
theorem xgcdAux_fst (x y) : ∀ s t s' t', (xgcdAux x s t y s' t').1 = gcd x y 
goal: (x.xgcdAux s t y s' t').1 = x.gcd y

full_name: Nat.xgcdAux_val
code: theorem xgcdAux_val (x y) : xgcdAux x 1 0 y 0 1 = (gcd x y, xgcd x y) 
goal: x.xgcdAux 1 0 y 0 1 = (x.gcd y, x.xgcd y)

full_name: Nat.xgcd_val
code: theorem xgcd_val (x y) : xgcd x y = (gcdA x y, gcdB x y) 
goal: x.xgcd y = (x.gcdA y, x.gcdB y)

full_name: _private.Mathlib.Data.Int.GCD.0.Nat.P
code: private def P : ℕ × ℤ × ℤ → Prop
  
goal: ℕ × ℤ × ℤ → Prop

full_name: Nat.xgcdAux_P
code: theorem xgcdAux_P {r r'} :
    ∀ {s t s' t'}, P x y (r, s, t) → P x y (r', s', t') → P x y (xgcdAux r s t r' s' t') 
goal: Nat.P x y (r, s, t) → Nat.P x y (r', s', t') → Nat.P x y (r.xgcdAux s t r' s' t')

full_name: Nat.gcd_eq_gcd_ab
code: /-- **Bézout's lemma**: given `x y : ℕ`, `gcd x y = x * a + y * b`, where `a = gcd_a x y` and
`b = gcd_b x y` are computed by the extended Euclidean algorithm.
-/
theorem gcd_eq_gcd_ab : (gcd x y : ℤ) = x * gcdA x y + y * gcdB x y 
goal: ↑(x.gcd y) = ↑x * x.gcdA y + ↑y * x.gcdB y

full_name: Nat.exists_mul_emod_eq_gcd
code: theorem exists_mul_emod_eq_gcd {k n : ℕ} (hk : gcd n k < k) : ∃ m, n * m % k = gcd n k 
goal: ∃ m, n * m % k = n.gcd k

full_name: Nat.exists_mul_emod_eq_one_of_coprime
code: theorem exists_mul_emod_eq_one_of_coprime {k n : ℕ} (hkn : Coprime n k) (hk : 1 < k) :
    ∃ m, n * m % k = 1 
goal: ∃ m, n * m % k = 1

full_name: Int.gcd_def
code: theorem gcd_def (i j : ℤ) : gcd i j = Nat.gcd i.natAbs j.natAbs 
goal: i.gcd j = i.natAbs.gcd j.natAbs

full_name: Int.gcd_natCast_natCast
code: @[simp, norm_cast] protected lemma gcd_natCast_natCast (m n : ℕ) : gcd ↑m ↑n = m.gcd n 
goal: (↑m).gcd ↑n = m.gcd n

full_name: Int.gcdA
code: /-- The extended GCD `a` value in the equation `gcd x y = x * a + y * b`. -/
def gcdA : ℤ → ℤ → ℤ
  
goal: ℤ → ℤ → ℤ

full_name: Int.gcdB
code: /-- The extended GCD `b` value in the equation `gcd x y = x * a + y * b`. -/
def gcdB : ℤ → ℤ → ℤ
  
goal: ℤ → ℤ → ℤ

full_name: Int.gcd_eq_gcd_ab
code: /-- **Bézout's lemma** -/
theorem gcd_eq_gcd_ab : ∀ x y : ℤ, (gcd x y : ℤ) = x * gcdA x y + y * gcdB x y
  
goal: ↑(x.gcd y) = x * x.gcdA y + y * x.gcdB y

full_name: Int.lcm_def
code: theorem lcm_def (i j : ℤ) : lcm i j = Nat.lcm (natAbs i) (natAbs j) 
goal: i.lcm j = i.natAbs.lcm j.natAbs

full_name: Int.coe_nat_lcm
code: protected theorem coe_nat_lcm (m n : ℕ) : Int.lcm ↑m ↑n = Nat.lcm m n 
goal: (↑m).lcm ↑n = m.lcm n

full_name: Int.dvd_gcd
code: theorem dvd_gcd {i j k : ℤ} (h1 : k ∣ i) (h2 : k ∣ j) : k ∣ gcd i j 
goal: k ∣ ↑(i.gcd j)

full_name: Int.gcd_mul_lcm
code: theorem gcd_mul_lcm (i j : ℤ) : gcd i j * lcm i j = natAbs (i * j) 
goal: i.gcd j * i.lcm j = (i * j).natAbs

full_name: Int.gcd_comm
code: theorem gcd_comm (i j : ℤ) : gcd i j = gcd j i 
goal: i.gcd j = j.gcd i

full_name: Int.gcd_assoc
code: theorem gcd_assoc (i j k : ℤ) : gcd (gcd i j) k = gcd i (gcd j k) 
goal: (↑(i.gcd j)).gcd k = i.gcd ↑(j.gcd k)

full_name: Int.gcd_self
code: @[simp]
theorem gcd_self (i : ℤ) : gcd i i = natAbs i 
goal: i.gcd i = i.natAbs

full_name: Int.gcd_zero_left
code: @[simp]
theorem gcd_zero_left (i : ℤ) : gcd 0 i = natAbs i 
goal: Int.gcd 0 i = i.natAbs

full_name: Int.gcd_zero_right
code: @[simp]
theorem gcd_zero_right (i : ℤ) : gcd i 0 = natAbs i 
goal: i.gcd 0 = i.natAbs

full_name: Int.gcd_mul_left
code: theorem gcd_mul_left (i j k : ℤ) : gcd (i * j) (i * k) = natAbs i * gcd j k 
goal: (i * j).gcd (i * k) = i.natAbs * j.gcd k

full_name: Int.gcd_mul_right
code: theorem gcd_mul_right (i j k : ℤ) : gcd (i * j) (k * j) = gcd i k * natAbs j 
goal: (i * j).gcd (k * j) = i.gcd k * j.natAbs

full_name: Int.gcd_pos_of_ne_zero_left
code: theorem gcd_pos_of_ne_zero_left {i : ℤ} (j : ℤ) (hi : i ≠ 0) : 0 < gcd i j 
goal: 0 < i.gcd j

full_name: Int.gcd_pos_of_ne_zero_right
code: theorem gcd_pos_of_ne_zero_right (i : ℤ) {j : ℤ} (hj : j ≠ 0) : 0 < gcd i j 
goal: 0 < i.gcd j

full_name: Int.gcd_eq_zero_iff
code: theorem gcd_eq_zero_iff {i j : ℤ} : gcd i j = 0 ↔ i = 0 ∧ j = 0 
goal: i.gcd j = 0 ↔ i = 0 ∧ j = 0

full_name: Int.gcd_pos_iff
code: theorem gcd_pos_iff {i j : ℤ} : 0 < gcd i j ↔ i ≠ 0 ∨ j ≠ 0 
goal: 0 < i.gcd j ↔ i ≠ 0 ∨ j ≠ 0

full_name: Int.gcd_div
code: theorem gcd_div {i j k : ℤ} (H1 : k ∣ i) (H2 : k ∣ j) :
    gcd (i / k) (j / k) = gcd i j / natAbs k 
goal: (i / k).gcd (j / k) = i.gcd j / k.natAbs

full_name: Int.gcd_div_gcd_div_gcd
code: theorem gcd_div_gcd_div_gcd {i j : ℤ} (H : 0 < gcd i j) : gcd (i / gcd i j) (j / gcd i j) = 1 
goal: (i / ↑(i.gcd j)).gcd (j / ↑(i.gcd j)) = 1

full_name: Int.gcd_dvd_gcd_of_dvd_left
code: theorem gcd_dvd_gcd_of_dvd_left {i k : ℤ} (j : ℤ) (H : i ∣ k) : gcd i j ∣ gcd k j 
goal: i.gcd j ∣ k.gcd j

full_name: Int.gcd_dvd_gcd_of_dvd_right
code: theorem gcd_dvd_gcd_of_dvd_right {i k : ℤ} (j : ℤ) (H : i ∣ k) : gcd j i ∣ gcd j k 
goal: j.gcd i ∣ j.gcd k

full_name: Int.gcd_dvd_gcd_mul_left
code: theorem gcd_dvd_gcd_mul_left (i j k : ℤ) : gcd i j ∣ gcd (k * i) j 
goal: i.gcd j ∣ (k * i).gcd j

full_name: Int.gcd_dvd_gcd_mul_right
code: theorem gcd_dvd_gcd_mul_right (i j k : ℤ) : gcd i j ∣ gcd (i * k) j 
goal: i.gcd j ∣ (i * k).gcd j

full_name: Int.gcd_dvd_gcd_mul_left_right
code: theorem gcd_dvd_gcd_mul_left_right (i j k : ℤ) : gcd i j ∣ gcd i (k * j) 
goal: i.gcd j ∣ i.gcd (k * j)

full_name: Int.gcd_dvd_gcd_mul_right_right
code: theorem gcd_dvd_gcd_mul_right_right (i j k : ℤ) : gcd i j ∣ gcd i (j * k) 
goal: i.gcd j ∣ i.gcd (j * k)

full_name: Int.gcd_eq_one_of_gcd_mul_right_eq_one_left
code: /-- If `gcd a (m * n) = 1`, then `gcd a m = 1`. -/
theorem gcd_eq_one_of_gcd_mul_right_eq_one_left {a : ℤ} {m n : ℕ} (h : a.gcd (m * n) = 1) :
    a.gcd m = 1 
goal: a.gcd ↑m = 1

full_name: Int.gcd_eq_one_of_gcd_mul_right_eq_one_right
code: /-- If `gcd a (m * n) = 1`, then `gcd a n = 1`. -/
theorem gcd_eq_one_of_gcd_mul_right_eq_one_right {a : ℤ} {m n : ℕ} (h : a.gcd (m * n) = 1) :
    a.gcd n = 1 
goal: a.gcd ↑n = 1

full_name: Int.gcd_eq_left
code: theorem gcd_eq_left {i j : ℤ} (H : i ∣ j) : gcd i j = natAbs i 
goal: i.gcd j = i.natAbs

full_name: Int.gcd_eq_right
code: theorem gcd_eq_right {i j : ℤ} (H : j ∣ i) : gcd i j = natAbs j 
goal: i.gcd j = j.natAbs

full_name: Int.ne_zero_of_gcd
code: theorem ne_zero_of_gcd {x y : ℤ} (hc : gcd x y ≠ 0) : x ≠ 0 ∨ y ≠ 0 
goal: x ≠ 0 ∨ y ≠ 0

full_name: Int.exists_gcd_one
code: theorem exists_gcd_one {m n : ℤ} (H : 0 < gcd m n) :
    ∃ m' n' : ℤ, gcd m' n' = 1 ∧ m = m' * gcd m n ∧ n = n' * gcd m n 
goal: ∃ m' n', m'.gcd n' = 1 ∧ m = m' * ↑(m.gcd n) ∧ n = n' * ↑(m.gcd n)

full_name: Int.exists_gcd_one'
code: theorem exists_gcd_one' {m n : ℤ} (H : 0 < gcd m n) :
    ∃ (g : ℕ) (m' n' : ℤ), 0 < g ∧ gcd m' n' = 1 ∧ m = m' * g ∧ n = n' * g 
goal: ∃ g m' n', 0 < g ∧ m'.gcd n' = 1 ∧ m = m' * ↑g ∧ n = n' * ↑g

full_name: Int.pow_dvd_pow_iff
code: theorem pow_dvd_pow_iff {m n : ℤ} {k : ℕ} (k0 : k ≠ 0) : m ^ k ∣ n ^ k ↔ m ∣ n 
goal: m ^ k ∣ n ^ k ↔ m ∣ n

full_name: Int.gcd_dvd_iff
code: theorem gcd_dvd_iff {a b : ℤ} {n : ℕ} : gcd a b ∣ n ↔ ∃ x y : ℤ, ↑n = a * x + b * y 
goal: a.gcd b ∣ n ↔ ∃ x y, ↑n = a * x + b * y

full_name: Int.gcd_greatest
code: theorem gcd_greatest {a b d : ℤ} (hd_pos : 0 ≤ d) (hda : d ∣ a) (hdb : d ∣ b)
    (hd : ∀ e : ℤ, e ∣ a → e ∣ b → e ∣ d) : d = gcd a b 
goal: d = ↑(a.gcd b)

full_name: Int.dvd_of_dvd_mul_left_of_gcd_one
code: /-- Euclid's lemma: if `a ∣ b * c` and `gcd a c = 1` then `a ∣ b`.
Compare with `IsCoprime.dvd_of_dvd_mul_left` and
`UniqueFactorizationMonoid.dvd_of_dvd_mul_left_of_no_prime_factors` -/
theorem dvd_of_dvd_mul_left_of_gcd_one {a b c : ℤ} (habc : a ∣ b * c) (hab : gcd a c = 1) :
    a ∣ b 
goal: a ∣ b

full_name: Int.dvd_of_dvd_mul_right_of_gcd_one
code: /-- Euclid's lemma: if `a ∣ b * c` and `gcd a b = 1` then `a ∣ c`.
Compare with `IsCoprime.dvd_of_dvd_mul_right` and
`UniqueFactorizationMonoid.dvd_of_dvd_mul_right_of_no_prime_factors` -/
theorem dvd_of_dvd_mul_right_of_gcd_one {a b c : ℤ} (habc : a ∣ b * c) (hab : gcd a b = 1) :
    a ∣ c 
goal: a ∣ c

full_name: Int.gcd_least_linear
code: /-- For nonzero integers `a` and `b`, `gcd a b` is the smallest positive natural number that can be
written in the form `a * x + b * y` for some pair of integers `x` and `y` -/
theorem gcd_least_linear {a b : ℤ} (ha : a ≠ 0) :
    IsLeast { n : ℕ | 0 < n ∧ ∃ x y : ℤ, ↑n = a * x + b * y } (a.gcd b) 
goal: IsLeast {n | 0 < n ∧ ∃ x y, ↑n = a * x + b * y} (a.gcd b)

full_name: Int.lcm_comm
code: theorem lcm_comm (i j : ℤ) : lcm i j = lcm j i 
goal: i.lcm j = j.lcm i

full_name: Int.lcm_assoc
code: theorem lcm_assoc (i j k : ℤ) : lcm (lcm i j) k = lcm i (lcm j k) 
goal: (↑(i.lcm j)).lcm k = i.lcm ↑(j.lcm k)

full_name: Int.lcm_zero_left
code: @[simp]
theorem lcm_zero_left (i : ℤ) : lcm 0 i = 0 
goal: Int.lcm 0 i = 0

full_name: Int.lcm_zero_right
code: @[simp]
theorem lcm_zero_right (i : ℤ) : lcm i 0 = 0 
goal: i.lcm 0 = 0

full_name: Int.lcm_one_left
code: @[simp]
theorem lcm_one_left (i : ℤ) : lcm 1 i = natAbs i 
goal: Int.lcm 1 i = i.natAbs

full_name: Int.lcm_one_right
code: @[simp]
theorem lcm_one_right (i : ℤ) : lcm i 1 = natAbs i 
goal: i.lcm 1 = i.natAbs

full_name: Int.lcm_dvd
code: theorem lcm_dvd {i j k : ℤ} : i ∣ k → j ∣ k → (lcm i j : ℤ) ∣ k 
goal: i ∣ k → j ∣ k → ↑(i.lcm j) ∣ k

full_name: Int.lcm_mul_left
code: theorem lcm_mul_left {m n k : ℤ} : (m * n).lcm (m * k) = natAbs m * n.lcm k 
goal: (m * n).lcm (m * k) = m.natAbs * n.lcm k

full_name: Int.lcm_mul_right
code: theorem lcm_mul_right {m n k : ℤ} : (m * n).lcm (k * n) = m.lcm k * natAbs n 
goal: (m * n).lcm (k * n) = m.lcm k * n.natAbs

full_name: pow_gcd_eq_one
code: @[to_additive gcd_nsmul_eq_zero]
theorem pow_gcd_eq_one {M : Type*} [Monoid M] (x : M) {m n : ℕ} (hm : x ^ m = 1) (hn : x ^ n = 1) :
    x ^ m.gcd n = 1 
goal: x ^ m.gcd n = 1

full_name: gcd_nsmul_eq_zero
code: @[to_additive gcd_nsmul_eq_zero]
theorem pow_gcd_eq_one {M : Type*} [Monoid M] (x : M) {m n : ℕ} (hm : x ^ m = 1) (hn : x ^ n = 1) :
    x ^ m.gcd n = 1 
goal: m.gcd n • x = 0

full_name: Commute.pow_eq_pow_iff_of_coprime
code: protected lemma Commute.pow_eq_pow_iff_of_coprime (hab : Commute a b) (hmn : m.Coprime n) :
    a ^ m = b ^ n ↔ ∃ c, a = c ^ n ∧ b = c ^ m 
goal: a ^ m = b ^ n ↔ ∃ c, a = c ^ n ∧ b = c ^ m

full_name: pow_eq_pow_iff_of_coprime
code: lemma pow_eq_pow_iff_of_coprime (hmn : m.Coprime n) : a ^ m = b ^ n ↔ ∃ c, a = c ^ n ∧ b = c ^ m 
goal: a ^ m = b ^ n ↔ ∃ c, a = c ^ n ∧ b = c ^ m

full_name: pow_mem_range_pow_of_coprime
code: lemma pow_mem_range_pow_of_coprime (hmn : m.Coprime n) (a : α) :
    a ^ m ∈ Set.range (· ^ n : α → α) ↔ a ∈ Set.range (· ^ n : α → α) 
goal: (a ^ m ∈ Set.range fun x => x ^ n) ↔ a ∈ Set.range fun x => x ^ n