[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizationMonoid α
⊢ (fun x => x * ↑(normUnit x)) 0 = 0
[PROOFSTEP]
simp only [normUnit_zero]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizationMonoid α
⊢ 0 * ↑1 = 0
[PROOFSTEP]
exact mul_one (0 : α)
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizationMonoid α
⊢ ZeroHom.toFun { toFun := fun x => x * ↑(normUnit x), map_zero' := (_ : (fun x => x * ↑(normUnit x)) 0 = 0) } 1 = 1
[PROOFSTEP]
dsimp only
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizationMonoid α
⊢ 1 * ↑(normUnit 1) = 1
[PROOFSTEP]
rw [normUnit_one, one_mul]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizationMonoid α
⊢ ↑1 = 1
[PROOFSTEP]
rfl
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizationMonoid α
x y : α
hx : x = 0
⊢ ZeroHom.toFun { toFun := fun x => x * ↑(normUnit x), map_zero' := (_ : (fun x => x * ↑(normUnit x)) 0 = 0) } (x * y) =
    ZeroHom.toFun { toFun := fun x => x * ↑(normUnit x), map_zero' := (_ : (fun x => x * ↑(normUnit x)) 0 = 0) } x *
      ZeroHom.toFun { toFun := fun x => x * ↑(normUnit x), map_zero' := (_ : (fun x => x * ↑(normUnit x)) 0 = 0) } y
[PROOFSTEP]
dsimp only
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizationMonoid α
x y : α
hx : x = 0
⊢ x * y * ↑(normUnit (x * y)) = x * ↑(normUnit x) * (y * ↑(normUnit y))
[PROOFSTEP]
rw [hx, zero_mul, zero_mul, zero_mul]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizationMonoid α
x y : α
hx : ¬x = 0
hy : y = 0
⊢ ZeroHom.toFun { toFun := fun x => x * ↑(normUnit x), map_zero' := (_ : (fun x => x * ↑(normUnit x)) 0 = 0) } (x * y) =
    ZeroHom.toFun { toFun := fun x => x * ↑(normUnit x), map_zero' := (_ : (fun x => x * ↑(normUnit x)) 0 = 0) } x *
      ZeroHom.toFun { toFun := fun x => x * ↑(normUnit x), map_zero' := (_ : (fun x => x * ↑(normUnit x)) 0 = 0) } y
[PROOFSTEP]
dsimp only
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizationMonoid α
x y : α
hx : ¬x = 0
hy : y = 0
⊢ x * y * ↑(normUnit (x * y)) = x * ↑(normUnit x) * (y * ↑(normUnit y))
[PROOFSTEP]
rw [hy, mul_zero, zero_mul, mul_zero]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizationMonoid α
x y : α
hx : ¬x = 0
hy : ¬y = 0
⊢ ZeroHom.toFun { toFun := fun x => x * ↑(normUnit x), map_zero' := (_ : (fun x => x * ↑(normUnit x)) 0 = 0) } (x * y) =
    ZeroHom.toFun { toFun := fun x => x * ↑(normUnit x), map_zero' := (_ : (fun x => x * ↑(normUnit x)) 0 = 0) } x *
      ZeroHom.toFun { toFun := fun x => x * ↑(normUnit x), map_zero' := (_ : (fun x => x * ↑(normUnit x)) 0 = 0) } y
[PROOFSTEP]
simp only [normUnit_mul hx hy, Units.val_mul]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizationMonoid α
x y : α
hx : ¬x = 0
hy : ¬y = 0
⊢ x * y * (↑(normUnit x) * ↑(normUnit y)) = x * ↑(normUnit x) * (y * ↑(normUnit y))
[PROOFSTEP]
simp only [mul_assoc, mul_left_comm y]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizationMonoid α
u : αˣ
⊢ ↑normalize ↑u = 1
[PROOFSTEP]
simp
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizationMonoid α
x : α
⊢ x = 0 → ↑normalize x = 0
[PROOFSTEP]
rintro rfl
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizationMonoid α
⊢ ↑normalize 0 = 0
[PROOFSTEP]
exact normalize_zero
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizationMonoid α
a : α
⊢ normUnit (a * ↑(normUnit a)) = 1
[PROOFSTEP]
nontriviality α using Subsingleton.elim a 0
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizationMonoid α
a : α
✝ : Nontrivial α
⊢ normUnit (a * ↑(normUnit a)) = 1
[PROOFSTEP]
obtain rfl | h := eq_or_ne a 0
[GOAL]
case inl
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizationMonoid α
✝ : Nontrivial α
⊢ normUnit (0 * ↑(normUnit 0)) = 1
[PROOFSTEP]
rw [normUnit_zero, zero_mul, normUnit_zero]
[GOAL]
case inr
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizationMonoid α
a : α
✝ : Nontrivial α
h : a ≠ 0
⊢ normUnit (a * ↑(normUnit a)) = 1
[PROOFSTEP]
rw [normUnit_mul h (Units.ne_zero _), normUnit_coe_units, mul_inv_eq_one]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizationMonoid α
x : α
⊢ ↑normalize (↑normalize x) = ↑normalize x
[PROOFSTEP]
simp
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizationMonoid α
a b : α
hab : a ∣ b
hba : b ∣ a
⊢ ↑normalize a = ↑normalize b
[PROOFSTEP]
nontriviality α
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizationMonoid α
a b : α
hab : a ∣ b
hba : b ∣ a
✝ : Nontrivial α
⊢ ↑normalize a = ↑normalize b
[PROOFSTEP]
rcases associated_of_dvd_dvd hab hba with ⟨u, rfl⟩
[GOAL]
case intro
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizationMonoid α
a : α
✝ : Nontrivial α
u : αˣ
hab : a ∣ a * ↑u
hba : a * ↑u ∣ a
⊢ ↑normalize a = ↑normalize (a * ↑u)
[PROOFSTEP]
refine' by_cases (by rintro rfl; simp only [zero_mul]) fun ha : a ≠ 0 => _
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizationMonoid α
a : α
✝ : Nontrivial α
u : αˣ
hab : a ∣ a * ↑u
hba : a * ↑u ∣ a
⊢ a = 0 → ↑normalize a = ↑normalize (a * ↑u)
[PROOFSTEP]
rintro rfl
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizationMonoid α
✝ : Nontrivial α
u : αˣ
hab : 0 ∣ 0 * ↑u
hba : 0 * ↑u ∣ 0
⊢ ↑normalize 0 = ↑normalize (0 * ↑u)
[PROOFSTEP]
simp only [zero_mul]
[GOAL]
case intro
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizationMonoid α
a : α
✝ : Nontrivial α
u : αˣ
hab : a ∣ a * ↑u
hba : a * ↑u ∣ a
ha : a ≠ 0
⊢ ↑normalize a = ↑normalize (a * ↑u)
[PROOFSTEP]
suffices a * ↑(normUnit a) = a * ↑u * ↑(normUnit a) * ↑u⁻¹ by
  simpa only [normalize_apply, mul_assoc, normUnit_mul ha u.ne_zero, normUnit_coe_units]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizationMonoid α
a : α
✝ : Nontrivial α
u : αˣ
hab : a ∣ a * ↑u
hba : a * ↑u ∣ a
ha : a ≠ 0
this : a * ↑(normUnit a) = a * ↑u * ↑(normUnit a) * ↑u⁻¹
⊢ ↑normalize a = ↑normalize (a * ↑u)
[PROOFSTEP]
simpa only [normalize_apply, mul_assoc, normUnit_mul ha u.ne_zero, normUnit_coe_units]
[GOAL]
case intro
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizationMonoid α
a : α
✝ : Nontrivial α
u : αˣ
hab : a ∣ a * ↑u
hba : a * ↑u ∣ a
ha : a ≠ 0
⊢ a * ↑(normUnit a) = a * ↑u * ↑(normUnit a) * ↑u⁻¹
[PROOFSTEP]
calc
  a * ↑(normUnit a) = a * ↑(normUnit a) * ↑u * ↑u⁻¹ := (Units.mul_inv_cancel_right _ _).symm
  _ = a * ↑u * ↑(normUnit a) * ↑u⁻¹ := by rw [mul_right_comm a]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizationMonoid α
a : α
✝ : Nontrivial α
u : αˣ
hab : a ∣ a * ↑u
hba : a * ↑u ∣ a
ha : a ≠ 0
⊢ a * ↑(normUnit a) * ↑u * ↑u⁻¹ = a * ↑u * ↑(normUnit a) * ↑u⁻¹
[PROOFSTEP]
rw [mul_right_comm a]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizationMonoid α
a b : Associates α
x✝¹ x✝ : α
⊢ Associates.out (Quotient.mk (Associated.setoid α) x✝¹ * Quotient.mk (Associated.setoid α) x✝) =
    Associates.out (Quotient.mk (Associated.setoid α) x✝¹) * Associates.out (Quotient.mk (Associated.setoid α) x✝)
[PROOFSTEP]
simp only [Associates.quotient_mk_eq_mk, out_mk, mk_mul_mk, normalize.map_mul]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizationMonoid α
a : α
b : Associates α
⊢ ∀ (a_1 : α),
    a ∣ Associates.out (Quotient.mk (Associated.setoid α) a_1) ↔ Associates.mk a ≤ Quotient.mk (Associated.setoid α) a_1
[PROOFSTEP]
simp [Associates.out_mk, Associates.quotient_mk_eq_mk, mk_le_mk_iff_dvd_iff]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizationMonoid α
a : α
b : Associates α
⊢ ∀ (a_1 : α),
    Associates.out (Quotient.mk (Associated.setoid α) a_1) ∣ a ↔ Quotient.mk (Associated.setoid α) a_1 ≤ Associates.mk a
[PROOFSTEP]
simp [Associates.out_mk, Associates.quotient_mk_eq_mk, mk_le_mk_iff_dvd_iff]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b : α
h : gcd a b = 0
⊢ a = 0 ∧ b = 0
[PROOFSTEP]
let ⟨ca, ha⟩ := gcd_dvd_left a b
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b : α
h : gcd a b = 0
ca : α
ha : a = gcd a b * ca
⊢ a = 0 ∧ b = 0
[PROOFSTEP]
let ⟨cb, hb⟩ := gcd_dvd_right a b
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b : α
h : gcd a b = 0
ca : α
ha : a = gcd a b * ca
cb : α
hb : b = gcd a b * cb
⊢ a = 0 ∧ b = 0
[PROOFSTEP]
rw [h, zero_mul] at ha hb 
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b : α
h : gcd a b = 0
ca : α
ha : a = 0
cb : α
hb : b = 0
⊢ a = 0 ∧ b = 0
[PROOFSTEP]
exact ⟨ha, hb⟩
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b : α
x✝ : a = 0 ∧ b = 0
ha : a = 0
hb : b = 0
⊢ gcd a b = 0
[PROOFSTEP]
rw [ha, hb, ← zero_dvd_iff]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b : α
x✝ : a = 0 ∧ b = 0
ha : a = 0
hb : b = 0
⊢ 0 ∣ gcd 0 0
[PROOFSTEP]
apply dvd_gcd
[GOAL]
case a
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b : α
x✝ : a = 0 ∧ b = 0
ha : a = 0
hb : b = 0
⊢ 0 ∣ 0
[PROOFSTEP]
rfl
[GOAL]
case a
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b : α
x✝ : a = 0 ∧ b = 0
ha : a = 0
hb : b = 0
⊢ 0 ∣ 0
[PROOFSTEP]
rfl
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizedGCDMonoid α
a b c : α
⊢ a = 0 → gcd (a * b) (a * c) = ↑normalize a * gcd b c
[PROOFSTEP]
rintro rfl
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizedGCDMonoid α
b c : α
⊢ gcd (0 * b) (0 * c) = ↑normalize 0 * gcd b c
[PROOFSTEP]
simp only [zero_mul, gcd_zero_left, normalize_zero]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizedGCDMonoid α
a b c : α
ha : a ≠ 0
this : gcd (a * b) (a * c) = ↑normalize (a * gcd b c)
⊢ gcd (a * b) (a * c) = ↑normalize a * gcd b c
[PROOFSTEP]
simpa
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
⊢ Associated (gcd (a * b) (a * c)) (a * gcd b c)
[PROOFSTEP]
obtain rfl | ha := eq_or_ne a 0
[GOAL]
case inl
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
b c : α
⊢ Associated (gcd (0 * b) (0 * c)) (0 * gcd b c)
[PROOFSTEP]
simp only [zero_mul, gcd_zero_left']
[GOAL]
case inr
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
ha : a ≠ 0
⊢ Associated (gcd (a * b) (a * c)) (a * gcd b c)
[PROOFSTEP]
obtain ⟨d, eq⟩ := dvd_gcd (dvd_mul_right a b) (dvd_mul_right a c)
[GOAL]
case inr.intro
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
ha : a ≠ 0
d : α
eq : gcd (a * b) (a * c) = a * d
⊢ Associated (gcd (a * b) (a * c)) (a * gcd b c)
[PROOFSTEP]
apply associated_of_dvd_dvd
[GOAL]
case inr.intro.hab
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
ha : a ≠ 0
d : α
eq : gcd (a * b) (a * c) = a * d
⊢ gcd (a * b) (a * c) ∣ a * gcd b c
[PROOFSTEP]
rw [eq]
[GOAL]
case inr.intro.hab
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
ha : a ≠ 0
d : α
eq : gcd (a * b) (a * c) = a * d
⊢ a * d ∣ a * gcd b c
[PROOFSTEP]
apply mul_dvd_mul_left
[GOAL]
case inr.intro.hab.h
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
ha : a ≠ 0
d : α
eq : gcd (a * b) (a * c) = a * d
⊢ d ∣ gcd b c
[PROOFSTEP]
exact
  dvd_gcd ((mul_dvd_mul_iff_left ha).1 <| eq ▸ gcd_dvd_left _ _) ((mul_dvd_mul_iff_left ha).1 <| eq ▸ gcd_dvd_right _ _)
[GOAL]
case inr.intro.hba
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
ha : a ≠ 0
d : α
eq : gcd (a * b) (a * c) = a * d
⊢ a * gcd b c ∣ gcd (a * b) (a * c)
[PROOFSTEP]
exact dvd_gcd (mul_dvd_mul_left a <| gcd_dvd_left _ _) (mul_dvd_mul_left a <| gcd_dvd_right _ _)
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizedGCDMonoid α
a b c : α
⊢ gcd (b * a) (c * a) = gcd b c * ↑normalize a
[PROOFSTEP]
simp only [mul_comm, gcd_mul_left]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
⊢ Associated (gcd (b * a) (c * a)) (gcd b c * a)
[PROOFSTEP]
simp only [mul_comm, gcd_mul_left']
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizedGCDMonoid α
a b : α
h : ↑normalize b = b
⊢ gcd a b = b ↔ b ∣ a
[PROOFSTEP]
simpa only [gcd_comm a b] using gcd_eq_left_iff b a h
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
m n k : α
H : k ∣ m * n
⊢ k ∣ m * gcd k n
[PROOFSTEP]
rw [mul_comm] at H ⊢
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
m n k : α
H : k ∣ n * m
⊢ k ∣ gcd k n * m
[PROOFSTEP]
exact dvd_gcd_mul_of_dvd_mul H
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
m n k : α
H : k ∣ m * n
⊢ ∃ d₁ d₂, d₁ ∣ m ∧ d₂ ∣ n ∧ k = d₁ * d₂
[PROOFSTEP]
by_cases h0 : gcd k m = 0
[GOAL]
case pos
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
m n k : α
H : k ∣ m * n
h0 : gcd k m = 0
⊢ ∃ d₁ d₂, d₁ ∣ m ∧ d₂ ∣ n ∧ k = d₁ * d₂
[PROOFSTEP]
rw [gcd_eq_zero_iff] at h0 
[GOAL]
case pos
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
m n k : α
H : k ∣ m * n
h0 : k = 0 ∧ m = 0
⊢ ∃ d₁ d₂, d₁ ∣ m ∧ d₂ ∣ n ∧ k = d₁ * d₂
[PROOFSTEP]
rcases h0 with ⟨rfl, rfl⟩
[GOAL]
case pos.intro
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
n : α
H : 0 ∣ 0 * n
⊢ ∃ d₁ d₂, d₁ ∣ 0 ∧ d₂ ∣ n ∧ 0 = d₁ * d₂
[PROOFSTEP]
refine' ⟨0, n, dvd_refl 0, dvd_refl n, _⟩
[GOAL]
case pos.intro
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
n : α
H : 0 ∣ 0 * n
⊢ 0 = 0 * n
[PROOFSTEP]
simp
[GOAL]
case neg
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
m n k : α
H : k ∣ m * n
h0 : ¬gcd k m = 0
⊢ ∃ d₁ d₂, d₁ ∣ m ∧ d₂ ∣ n ∧ k = d₁ * d₂
[PROOFSTEP]
obtain ⟨a, ha⟩ := gcd_dvd_left k m
[GOAL]
case neg.intro
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
m n k : α
H : k ∣ m * n
h0 : ¬gcd k m = 0
a : α
ha : k = gcd k m * a
⊢ ∃ d₁ d₂, d₁ ∣ m ∧ d₂ ∣ n ∧ k = d₁ * d₂
[PROOFSTEP]
refine' ⟨gcd k m, a, gcd_dvd_right _ _, _, ha⟩
[GOAL]
case neg.intro
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
m n k : α
H : k ∣ m * n
h0 : ¬gcd k m = 0
a : α
ha : k = gcd k m * a
⊢ a ∣ n
[PROOFSTEP]
suffices h : gcd k m * a ∣ gcd k m * n
[GOAL]
case neg.intro
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
m n k : α
H : k ∣ m * n
h0 : ¬gcd k m = 0
a : α
ha : k = gcd k m * a
h : gcd k m * a ∣ gcd k m * n
⊢ a ∣ n
[PROOFSTEP]
cases' h with b hb
[GOAL]
case neg.intro.intro
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
m n k : α
H : k ∣ m * n
h0 : ¬gcd k m = 0
a : α
ha : k = gcd k m * a
b : α
hb : gcd k m * n = gcd k m * a * b
⊢ a ∣ n
[PROOFSTEP]
use b
[GOAL]
case h
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
m n k : α
H : k ∣ m * n
h0 : ¬gcd k m = 0
a : α
ha : k = gcd k m * a
b : α
hb : gcd k m * n = gcd k m * a * b
⊢ n = a * b
[PROOFSTEP]
rw [mul_assoc] at hb 
[GOAL]
case h
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
m n k : α
H : k ∣ m * n
h0 : ¬gcd k m = 0
a : α
ha : k = gcd k m * a
b : α
hb : gcd k m * n = gcd k m * (a * b)
⊢ n = a * b
[PROOFSTEP]
apply mul_left_cancel₀ h0 hb
[GOAL]
case h
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
m n k : α
H : k ∣ m * n
h0 : ¬gcd k m = 0
a : α
ha : k = gcd k m * a
⊢ gcd k m * a ∣ gcd k m * n
[PROOFSTEP]
rw [← ha]
[GOAL]
case h
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
m n k : α
H : k ∣ m * n
h0 : ¬gcd k m = 0
a : α
ha : k = gcd k m * a
⊢ k ∣ gcd k m * n
[PROOFSTEP]
exact dvd_gcd_mul_of_dvd_mul H
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
k m n : α
⊢ k ∣ m * n ↔ ∃ d₁ d₂, d₁ ∣ m ∧ d₂ ∣ n ∧ k = d₁ * d₂
[PROOFSTEP]
refine' ⟨exists_dvd_and_dvd_of_dvd_mul, _⟩
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
k m n : α
⊢ (∃ d₁ d₂, d₁ ∣ m ∧ d₂ ∣ n ∧ k = d₁ * d₂) → k ∣ m * n
[PROOFSTEP]
rintro ⟨d₁, d₂, hy, hz, rfl⟩
[GOAL]
case intro.intro.intro.intro
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
m n d₁ d₂ : α
hy : d₁ ∣ m
hz : d₂ ∣ n
⊢ d₁ * d₂ ∣ m * n
[PROOFSTEP]
exact mul_dvd_mul hy hz
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
k m n : α
⊢ gcd k (m * n) ∣ gcd k m * gcd k n
[PROOFSTEP]
obtain ⟨m', n', hm', hn', h⟩ := exists_dvd_and_dvd_of_dvd_mul (gcd_dvd_right k (m * n))
[GOAL]
case intro.intro.intro.intro
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
k m n m' n' : α
hm' : m' ∣ m
hn' : n' ∣ n
h : gcd k (m * n) = m' * n'
⊢ gcd k (m * n) ∣ gcd k m * gcd k n
[PROOFSTEP]
replace h : gcd k (m * n) = m' * n' := h
[GOAL]
case intro.intro.intro.intro
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
k m n m' n' : α
hm' : m' ∣ m
hn' : n' ∣ n
h : gcd k (m * n) = m' * n'
⊢ gcd k (m * n) ∣ gcd k m * gcd k n
[PROOFSTEP]
rw [h]
[GOAL]
case intro.intro.intro.intro
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
k m n m' n' : α
hm' : m' ∣ m
hn' : n' ∣ n
h : gcd k (m * n) = m' * n'
⊢ m' * n' ∣ gcd k m * gcd k n
[PROOFSTEP]
have hm'n' : m' * n' ∣ k := h ▸ gcd_dvd_left _ _
[GOAL]
case intro.intro.intro.intro
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
k m n m' n' : α
hm' : m' ∣ m
hn' : n' ∣ n
h : gcd k (m * n) = m' * n'
hm'n' : m' * n' ∣ k
⊢ m' * n' ∣ gcd k m * gcd k n
[PROOFSTEP]
apply mul_dvd_mul
[GOAL]
case intro.intro.intro.intro.a
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
k m n m' n' : α
hm' : m' ∣ m
hn' : n' ∣ n
h : gcd k (m * n) = m' * n'
hm'n' : m' * n' ∣ k
⊢ m' ∣ gcd k m
[PROOFSTEP]
have hm'k : m' ∣ k := (dvd_mul_right m' n').trans hm'n'
[GOAL]
case intro.intro.intro.intro.a
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
k m n m' n' : α
hm' : m' ∣ m
hn' : n' ∣ n
h : gcd k (m * n) = m' * n'
hm'n' : m' * n' ∣ k
hm'k : m' ∣ k
⊢ m' ∣ gcd k m
[PROOFSTEP]
exact dvd_gcd hm'k hm'
[GOAL]
case intro.intro.intro.intro.a
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
k m n m' n' : α
hm' : m' ∣ m
hn' : n' ∣ n
h : gcd k (m * n) = m' * n'
hm'n' : m' * n' ∣ k
⊢ n' ∣ gcd k n
[PROOFSTEP]
have hn'k : n' ∣ k := (dvd_mul_left n' m').trans hm'n'
[GOAL]
case intro.intro.intro.intro.a
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
k m n m' n' : α
hm' : m' ∣ m
hn' : n' ∣ n
h : gcd k (m * n) = m' * n'
hm'n' : m' * n' ∣ k
hn'k : n' ∣ k
⊢ n' ∣ gcd k n
[PROOFSTEP]
exact dvd_gcd hn'k hn'
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b : α
k : ℕ
⊢ gcd a (b ^ k) ∣ gcd a b ^ k
[PROOFSTEP]
by_cases hg : gcd a b = 0
[GOAL]
case pos
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b : α
k : ℕ
hg : gcd a b = 0
⊢ gcd a (b ^ k) ∣ gcd a b ^ k
[PROOFSTEP]
rw [gcd_eq_zero_iff] at hg 
[GOAL]
case pos
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b : α
k : ℕ
hg : a = 0 ∧ b = 0
⊢ gcd a (b ^ k) ∣ gcd a b ^ k
[PROOFSTEP]
rcases hg with ⟨rfl, rfl⟩
[GOAL]
case pos.intro
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
k : ℕ
⊢ gcd 0 (0 ^ k) ∣ gcd 0 0 ^ k
[PROOFSTEP]
exact (gcd_zero_left' (0 ^ k : α)).dvd.trans (pow_dvd_pow_of_dvd (gcd_zero_left' (0 : α)).symm.dvd _)
[GOAL]
case neg
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b : α
k : ℕ
hg : ¬gcd a b = 0
⊢ gcd a (b ^ k) ∣ gcd a b ^ k
[PROOFSTEP]
induction' k with k hk
[GOAL]
case neg.zero
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b : α
hg : ¬gcd a b = 0
⊢ gcd a (b ^ Nat.zero) ∣ gcd a b ^ Nat.zero
[PROOFSTEP]
rw [pow_zero, pow_zero]
[GOAL]
case neg.zero
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b : α
hg : ¬gcd a b = 0
⊢ gcd a 1 ∣ 1
[PROOFSTEP]
exact (gcd_one_right' a).dvd
[GOAL]
case neg.succ
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b : α
hg : ¬gcd a b = 0
k : ℕ
hk : gcd a (b ^ k) ∣ gcd a b ^ k
⊢ gcd a (b ^ Nat.succ k) ∣ gcd a b ^ Nat.succ k
[PROOFSTEP]
rw [pow_succ, pow_succ]
[GOAL]
case neg.succ
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b : α
hg : ¬gcd a b = 0
k : ℕ
hk : gcd a (b ^ k) ∣ gcd a b ^ k
⊢ gcd a (b * b ^ k) ∣ gcd a b * gcd a b ^ k
[PROOFSTEP]
trans gcd a b * gcd a (b ^ k)
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b : α
hg : ¬gcd a b = 0
k : ℕ
hk : gcd a (b ^ k) ∣ gcd a b ^ k
⊢ gcd a (b * b ^ k) ∣ gcd a b * gcd a (b ^ k)
[PROOFSTEP]
exact gcd_mul_dvd_mul_gcd a b (b ^ k)
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b : α
hg : ¬gcd a b = 0
k : ℕ
hk : gcd a (b ^ k) ∣ gcd a b ^ k
⊢ gcd a b * gcd a (b ^ k) ∣ gcd a b * gcd a b ^ k
[PROOFSTEP]
exact (mul_dvd_mul_iff_left hg).mpr hk
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c d₁ d₂ : α
ha : a ≠ 0
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
hc : c = d₁ * d₂
hd₁ : d₁ ∣ a
⊢ d₁ ^ k ≠ 0 ∧ d₁ ^ k ∣ a
[PROOFSTEP]
have h1 : IsUnit (gcd (d₁ ^ k) b) := by
  apply isUnit_of_dvd_one
  trans gcd d₁ b ^ k
  · exact gcd_pow_left_dvd_pow_gcd
  · apply IsUnit.dvd
    apply IsUnit.pow
    apply isUnit_of_dvd_one
    apply dvd_trans _ hab.dvd
    apply gcd_dvd_gcd hd₁ (dvd_refl b)
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c d₁ d₂ : α
ha : a ≠ 0
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
hc : c = d₁ * d₂
hd₁ : d₁ ∣ a
⊢ IsUnit (gcd (d₁ ^ k) b)
[PROOFSTEP]
apply isUnit_of_dvd_one
[GOAL]
case h
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c d₁ d₂ : α
ha : a ≠ 0
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
hc : c = d₁ * d₂
hd₁ : d₁ ∣ a
⊢ gcd (d₁ ^ k) b ∣ 1
[PROOFSTEP]
trans gcd d₁ b ^ k
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c d₁ d₂ : α
ha : a ≠ 0
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
hc : c = d₁ * d₂
hd₁ : d₁ ∣ a
⊢ gcd (d₁ ^ k) b ∣ gcd d₁ b ^ k
[PROOFSTEP]
exact gcd_pow_left_dvd_pow_gcd
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c d₁ d₂ : α
ha : a ≠ 0
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
hc : c = d₁ * d₂
hd₁ : d₁ ∣ a
⊢ gcd d₁ b ^ k ∣ 1
[PROOFSTEP]
apply IsUnit.dvd
[GOAL]
case hu
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c d₁ d₂ : α
ha : a ≠ 0
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
hc : c = d₁ * d₂
hd₁ : d₁ ∣ a
⊢ IsUnit (gcd d₁ b ^ k)
[PROOFSTEP]
apply IsUnit.pow
[GOAL]
case hu.a
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c d₁ d₂ : α
ha : a ≠ 0
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
hc : c = d₁ * d₂
hd₁ : d₁ ∣ a
⊢ IsUnit (gcd d₁ b)
[PROOFSTEP]
apply isUnit_of_dvd_one
[GOAL]
case hu.a.h
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c d₁ d₂ : α
ha : a ≠ 0
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
hc : c = d₁ * d₂
hd₁ : d₁ ∣ a
⊢ gcd d₁ b ∣ 1
[PROOFSTEP]
apply dvd_trans _ hab.dvd
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c d₁ d₂ : α
ha : a ≠ 0
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
hc : c = d₁ * d₂
hd₁ : d₁ ∣ a
⊢ gcd d₁ b ∣ gcd a b
[PROOFSTEP]
apply gcd_dvd_gcd hd₁ (dvd_refl b)
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c d₁ d₂ : α
ha : a ≠ 0
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
hc : c = d₁ * d₂
hd₁ : d₁ ∣ a
h1 : IsUnit (gcd (d₁ ^ k) b)
⊢ d₁ ^ k ≠ 0 ∧ d₁ ^ k ∣ a
[PROOFSTEP]
have h2 : d₁ ^ k ∣ a * b := by
  use d₂ ^ k
  rw [h, hc]
  exact mul_pow d₁ d₂ k
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c d₁ d₂ : α
ha : a ≠ 0
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
hc : c = d₁ * d₂
hd₁ : d₁ ∣ a
h1 : IsUnit (gcd (d₁ ^ k) b)
⊢ d₁ ^ k ∣ a * b
[PROOFSTEP]
use d₂ ^ k
[GOAL]
case h
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c d₁ d₂ : α
ha : a ≠ 0
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
hc : c = d₁ * d₂
hd₁ : d₁ ∣ a
h1 : IsUnit (gcd (d₁ ^ k) b)
⊢ a * b = d₁ ^ k * d₂ ^ k
[PROOFSTEP]
rw [h, hc]
[GOAL]
case h
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c d₁ d₂ : α
ha : a ≠ 0
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
hc : c = d₁ * d₂
hd₁ : d₁ ∣ a
h1 : IsUnit (gcd (d₁ ^ k) b)
⊢ (d₁ * d₂) ^ k = d₁ ^ k * d₂ ^ k
[PROOFSTEP]
exact mul_pow d₁ d₂ k
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c d₁ d₂ : α
ha : a ≠ 0
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
hc : c = d₁ * d₂
hd₁ : d₁ ∣ a
h1 : IsUnit (gcd (d₁ ^ k) b)
h2 : d₁ ^ k ∣ a * b
⊢ d₁ ^ k ≠ 0 ∧ d₁ ^ k ∣ a
[PROOFSTEP]
rw [mul_comm] at h2 
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c d₁ d₂ : α
ha : a ≠ 0
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
hc : c = d₁ * d₂
hd₁ : d₁ ∣ a
h1 : IsUnit (gcd (d₁ ^ k) b)
h2 : d₁ ^ k ∣ b * a
⊢ d₁ ^ k ≠ 0 ∧ d₁ ^ k ∣ a
[PROOFSTEP]
have h3 : d₁ ^ k ∣ a := by
  apply (dvd_gcd_mul_of_dvd_mul h2).trans
  rw [IsUnit.mul_left_dvd _ _ _ h1]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c d₁ d₂ : α
ha : a ≠ 0
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
hc : c = d₁ * d₂
hd₁ : d₁ ∣ a
h1 : IsUnit (gcd (d₁ ^ k) b)
h2 : d₁ ^ k ∣ b * a
⊢ d₁ ^ k ∣ a
[PROOFSTEP]
apply (dvd_gcd_mul_of_dvd_mul h2).trans
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c d₁ d₂ : α
ha : a ≠ 0
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
hc : c = d₁ * d₂
hd₁ : d₁ ∣ a
h1 : IsUnit (gcd (d₁ ^ k) b)
h2 : d₁ ^ k ∣ b * a
⊢ gcd (d₁ ^ k) b * a ∣ a
[PROOFSTEP]
rw [IsUnit.mul_left_dvd _ _ _ h1]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c d₁ d₂ : α
ha : a ≠ 0
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
hc : c = d₁ * d₂
hd₁ : d₁ ∣ a
h1 : IsUnit (gcd (d₁ ^ k) b)
h2 : d₁ ^ k ∣ b * a
h3 : d₁ ^ k ∣ a
⊢ d₁ ^ k ≠ 0 ∧ d₁ ^ k ∣ a
[PROOFSTEP]
have h4 : d₁ ^ k ≠ 0 := by
  intro hdk
  rw [hdk] at h3 
  apply absurd (zero_dvd_iff.mp h3) ha
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c d₁ d₂ : α
ha : a ≠ 0
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
hc : c = d₁ * d₂
hd₁ : d₁ ∣ a
h1 : IsUnit (gcd (d₁ ^ k) b)
h2 : d₁ ^ k ∣ b * a
h3 : d₁ ^ k ∣ a
⊢ d₁ ^ k ≠ 0
[PROOFSTEP]
intro hdk
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c d₁ d₂ : α
ha : a ≠ 0
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
hc : c = d₁ * d₂
hd₁ : d₁ ∣ a
h1 : IsUnit (gcd (d₁ ^ k) b)
h2 : d₁ ^ k ∣ b * a
h3 : d₁ ^ k ∣ a
hdk : d₁ ^ k = 0
⊢ False
[PROOFSTEP]
rw [hdk] at h3 
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c d₁ d₂ : α
ha : a ≠ 0
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
hc : c = d₁ * d₂
hd₁ : d₁ ∣ a
h1 : IsUnit (gcd (d₁ ^ k) b)
h2 : d₁ ^ k ∣ b * a
h3 : 0 ∣ a
hdk : d₁ ^ k = 0
⊢ False
[PROOFSTEP]
apply absurd (zero_dvd_iff.mp h3) ha
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c d₁ d₂ : α
ha : a ≠ 0
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
hc : c = d₁ * d₂
hd₁ : d₁ ∣ a
h1 : IsUnit (gcd (d₁ ^ k) b)
h2 : d₁ ^ k ∣ b * a
h3 : d₁ ^ k ∣ a
h4 : d₁ ^ k ≠ 0
⊢ d₁ ^ k ≠ 0 ∧ d₁ ^ k ∣ a
[PROOFSTEP]
exact ⟨h4, h3⟩
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
⊢ ∃ d, Associated (d ^ k) a
[PROOFSTEP]
cases subsingleton_or_nontrivial α
[GOAL]
case inl
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
h✝ : Subsingleton α
⊢ ∃ d, Associated (d ^ k) a
[PROOFSTEP]
use 0
[GOAL]
case h
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
h✝ : Subsingleton α
⊢ Associated (0 ^ k) a
[PROOFSTEP]
rw [Subsingleton.elim a (0 ^ k)]
[GOAL]
case inr
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
h✝ : Nontrivial α
⊢ ∃ d, Associated (d ^ k) a
[PROOFSTEP]
by_cases ha : a = 0
[GOAL]
case pos
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
h✝ : Nontrivial α
ha : a = 0
⊢ ∃ d, Associated (d ^ k) a
[PROOFSTEP]
use 0
[GOAL]
case h
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
h✝ : Nontrivial α
ha : a = 0
⊢ Associated (0 ^ k) a
[PROOFSTEP]
rw [ha]
[GOAL]
case h
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
h✝ : Nontrivial α
ha : a = 0
⊢ Associated (0 ^ k) 0
[PROOFSTEP]
obtain rfl | hk := k.eq_zero_or_pos
[GOAL]
case h.inl
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd a b)
h✝ : Nontrivial α
ha : a = 0
h : a * b = c ^ 0
⊢ Associated (0 ^ 0) 0
[PROOFSTEP]
exfalso
[GOAL]
case h.inl.h
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd a b)
h✝ : Nontrivial α
ha : a = 0
h : a * b = c ^ 0
⊢ False
[PROOFSTEP]
revert h
[GOAL]
case h.inl.h
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd a b)
h✝ : Nontrivial α
ha : a = 0
⊢ a * b = c ^ 0 → False
[PROOFSTEP]
rw [ha, zero_mul, pow_zero]
[GOAL]
case h.inl.h
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd a b)
h✝ : Nontrivial α
ha : a = 0
⊢ 0 = 1 → False
[PROOFSTEP]
apply zero_ne_one
[GOAL]
case h.inr
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
h✝ : Nontrivial α
ha : a = 0
hk : k > 0
⊢ Associated (0 ^ k) 0
[PROOFSTEP]
rw [zero_pow hk]
[GOAL]
case neg
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
h✝ : Nontrivial α
ha : ¬a = 0
⊢ ∃ d, Associated (d ^ k) a
[PROOFSTEP]
by_cases hb : b = 0
[GOAL]
case pos
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
h✝ : Nontrivial α
ha : ¬a = 0
hb : b = 0
⊢ ∃ d, Associated (d ^ k) a
[PROOFSTEP]
use 1
[GOAL]
case h
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
h✝ : Nontrivial α
ha : ¬a = 0
hb : b = 0
⊢ Associated (1 ^ k) a
[PROOFSTEP]
rw [one_pow]
[GOAL]
case h
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
h✝ : Nontrivial α
ha : ¬a = 0
hb : b = 0
⊢ Associated 1 a
[PROOFSTEP]
apply (associated_one_iff_isUnit.mpr hab).symm.trans
[GOAL]
case h
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
h✝ : Nontrivial α
ha : ¬a = 0
hb : b = 0
⊢ Associated (gcd a b) a
[PROOFSTEP]
rw [hb]
[GOAL]
case h
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
h✝ : Nontrivial α
ha : ¬a = 0
hb : b = 0
⊢ Associated (gcd a 0) a
[PROOFSTEP]
exact gcd_zero_right' a
[GOAL]
case neg
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
h✝ : Nontrivial α
ha : ¬a = 0
hb : ¬b = 0
⊢ ∃ d, Associated (d ^ k) a
[PROOFSTEP]
obtain rfl | hk := k.eq_zero_or_pos
[GOAL]
case neg.inl
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd a b)
h✝ : Nontrivial α
ha : ¬a = 0
hb : ¬b = 0
h : a * b = c ^ 0
⊢ ∃ d, Associated (d ^ 0) a
[PROOFSTEP]
use 1
[GOAL]
case h
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd a b)
h✝ : Nontrivial α
ha : ¬a = 0
hb : ¬b = 0
h : a * b = c ^ 0
⊢ Associated (1 ^ 0) a
[PROOFSTEP]
rw [pow_zero] at h ⊢
[GOAL]
case h
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd a b)
h✝ : Nontrivial α
ha : ¬a = 0
hb : ¬b = 0
h : a * b = 1
⊢ Associated 1 a
[PROOFSTEP]
use Units.mkOfMulEqOne _ _ h
[GOAL]
case h
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd a b)
h✝ : Nontrivial α
ha : ¬a = 0
hb : ¬b = 0
h : a * b = 1
⊢ 1 * ↑(Units.mkOfMulEqOne a b h) = a
[PROOFSTEP]
rw [Units.val_mkOfMulEqOne, one_mul]
[GOAL]
case neg.inr
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
h✝ : Nontrivial α
ha : ¬a = 0
hb : ¬b = 0
hk : k > 0
⊢ ∃ d, Associated (d ^ k) a
[PROOFSTEP]
have hc : c ∣ a * b := by
  rw [h]
  exact dvd_pow_self _ hk.ne'
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
h✝ : Nontrivial α
ha : ¬a = 0
hb : ¬b = 0
hk : k > 0
⊢ c ∣ a * b
[PROOFSTEP]
rw [h]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
h✝ : Nontrivial α
ha : ¬a = 0
hb : ¬b = 0
hk : k > 0
⊢ c ∣ c ^ k
[PROOFSTEP]
exact dvd_pow_self _ hk.ne'
[GOAL]
case neg.inr
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
h✝ : Nontrivial α
ha : ¬a = 0
hb : ¬b = 0
hk : k > 0
hc : c ∣ a * b
⊢ ∃ d, Associated (d ^ k) a
[PROOFSTEP]
obtain ⟨d₁, d₂, hd₁, hd₂, hc⟩ := exists_dvd_and_dvd_of_dvd_mul hc
[GOAL]
case neg.inr.intro.intro.intro.intro
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
h✝ : Nontrivial α
ha : ¬a = 0
hb : ¬b = 0
hk : k > 0
hc✝ : c ∣ a * b
d₁ d₂ : α
hd₁ : d₁ ∣ a
hd₂ : d₂ ∣ b
hc : c = d₁ * d₂
⊢ ∃ d, Associated (d ^ k) a
[PROOFSTEP]
use d₁
[GOAL]
case h
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
h✝ : Nontrivial α
ha : ¬a = 0
hb : ¬b = 0
hk : k > 0
hc✝ : c ∣ a * b
d₁ d₂ : α
hd₁ : d₁ ∣ a
hd₂ : d₂ ∣ b
hc : c = d₁ * d₂
⊢ Associated (d₁ ^ k) a
[PROOFSTEP]
obtain ⟨h0₁, ⟨a', ha'⟩⟩ := pow_dvd_of_mul_eq_pow ha hab h hc hd₁
[GOAL]
case h.intro.intro
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd a b)
k : ℕ
h : a * b = c ^ k
h✝ : Nontrivial α
ha : ¬a = 0
hb : ¬b = 0
hk : k > 0
hc✝ : c ∣ a * b
d₁ d₂ : α
hd₁ : d₁ ∣ a
hd₂ : d₂ ∣ b
hc : c = d₁ * d₂
h0₁ : d₁ ^ k ≠ 0
a' : α
ha' : a = d₁ ^ k * a'
⊢ Associated (d₁ ^ k) a
[PROOFSTEP]
rw [mul_comm] at h hc 
[GOAL]
case h.intro.intro
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd a b)
k : ℕ
h : b * a = c ^ k
h✝ : Nontrivial α
ha : ¬a = 0
hb : ¬b = 0
hk : k > 0
hc✝ : c ∣ a * b
d₁ d₂ : α
hd₁ : d₁ ∣ a
hd₂ : d₂ ∣ b
hc : c = d₂ * d₁
h0₁ : d₁ ^ k ≠ 0
a' : α
ha' : a = d₁ ^ k * a'
⊢ Associated (d₁ ^ k) a
[PROOFSTEP]
rw [(gcd_comm' a b).isUnit_iff] at hab 
[GOAL]
case h.intro.intro
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd b a)
k : ℕ
h : b * a = c ^ k
h✝ : Nontrivial α
ha : ¬a = 0
hb : ¬b = 0
hk : k > 0
hc✝ : c ∣ a * b
d₁ d₂ : α
hd₁ : d₁ ∣ a
hd₂ : d₂ ∣ b
hc : c = d₂ * d₁
h0₁ : d₁ ^ k ≠ 0
a' : α
ha' : a = d₁ ^ k * a'
⊢ Associated (d₁ ^ k) a
[PROOFSTEP]
obtain ⟨h0₂, ⟨b', hb'⟩⟩ := pow_dvd_of_mul_eq_pow hb hab h hc hd₂
[GOAL]
case h.intro.intro.intro.intro
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd b a)
k : ℕ
h : b * a = c ^ k
h✝ : Nontrivial α
ha : ¬a = 0
hb : ¬b = 0
hk : k > 0
hc✝ : c ∣ a * b
d₁ d₂ : α
hd₁ : d₁ ∣ a
hd₂ : d₂ ∣ b
hc : c = d₂ * d₁
h0₁ : d₁ ^ k ≠ 0
a' : α
ha' : a = d₁ ^ k * a'
h0₂ : d₂ ^ k ≠ 0
b' : α
hb' : b = d₂ ^ k * b'
⊢ Associated (d₁ ^ k) a
[PROOFSTEP]
rw [ha', hb', hc, mul_pow] at h 
[GOAL]
case h.intro.intro.intro.intro
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd b a)
k : ℕ
h✝ : Nontrivial α
ha : ¬a = 0
hb : ¬b = 0
hk : k > 0
hc✝ : c ∣ a * b
d₁ d₂ : α
hd₁ : d₁ ∣ a
hd₂ : d₂ ∣ b
hc : c = d₂ * d₁
h0₁ : d₁ ^ k ≠ 0
a' : α
ha' : a = d₁ ^ k * a'
h0₂ : d₂ ^ k ≠ 0
b' : α
h : d₂ ^ k * b' * (d₁ ^ k * a') = d₂ ^ k * d₁ ^ k
hb' : b = d₂ ^ k * b'
⊢ Associated (d₁ ^ k) a
[PROOFSTEP]
have h' : a' * b' = 1 := by
  apply (mul_right_inj' h0₁).mp
  rw [mul_one]
  apply (mul_right_inj' h0₂).mp
  rw [← h]
  rw [mul_assoc, mul_comm a', ← mul_assoc _ b', ← mul_assoc b', mul_comm b']
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd b a)
k : ℕ
h✝ : Nontrivial α
ha : ¬a = 0
hb : ¬b = 0
hk : k > 0
hc✝ : c ∣ a * b
d₁ d₂ : α
hd₁ : d₁ ∣ a
hd₂ : d₂ ∣ b
hc : c = d₂ * d₁
h0₁ : d₁ ^ k ≠ 0
a' : α
ha' : a = d₁ ^ k * a'
h0₂ : d₂ ^ k ≠ 0
b' : α
h : d₂ ^ k * b' * (d₁ ^ k * a') = d₂ ^ k * d₁ ^ k
hb' : b = d₂ ^ k * b'
⊢ a' * b' = 1
[PROOFSTEP]
apply (mul_right_inj' h0₁).mp
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd b a)
k : ℕ
h✝ : Nontrivial α
ha : ¬a = 0
hb : ¬b = 0
hk : k > 0
hc✝ : c ∣ a * b
d₁ d₂ : α
hd₁ : d₁ ∣ a
hd₂ : d₂ ∣ b
hc : c = d₂ * d₁
h0₁ : d₁ ^ k ≠ 0
a' : α
ha' : a = d₁ ^ k * a'
h0₂ : d₂ ^ k ≠ 0
b' : α
h : d₂ ^ k * b' * (d₁ ^ k * a') = d₂ ^ k * d₁ ^ k
hb' : b = d₂ ^ k * b'
⊢ d₁ ^ k * (a' * b') = d₁ ^ k * 1
[PROOFSTEP]
rw [mul_one]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd b a)
k : ℕ
h✝ : Nontrivial α
ha : ¬a = 0
hb : ¬b = 0
hk : k > 0
hc✝ : c ∣ a * b
d₁ d₂ : α
hd₁ : d₁ ∣ a
hd₂ : d₂ ∣ b
hc : c = d₂ * d₁
h0₁ : d₁ ^ k ≠ 0
a' : α
ha' : a = d₁ ^ k * a'
h0₂ : d₂ ^ k ≠ 0
b' : α
h : d₂ ^ k * b' * (d₁ ^ k * a') = d₂ ^ k * d₁ ^ k
hb' : b = d₂ ^ k * b'
⊢ d₁ ^ k * (a' * b') = d₁ ^ k
[PROOFSTEP]
apply (mul_right_inj' h0₂).mp
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd b a)
k : ℕ
h✝ : Nontrivial α
ha : ¬a = 0
hb : ¬b = 0
hk : k > 0
hc✝ : c ∣ a * b
d₁ d₂ : α
hd₁ : d₁ ∣ a
hd₂ : d₂ ∣ b
hc : c = d₂ * d₁
h0₁ : d₁ ^ k ≠ 0
a' : α
ha' : a = d₁ ^ k * a'
h0₂ : d₂ ^ k ≠ 0
b' : α
h : d₂ ^ k * b' * (d₁ ^ k * a') = d₂ ^ k * d₁ ^ k
hb' : b = d₂ ^ k * b'
⊢ d₂ ^ k * (d₁ ^ k * (a' * b')) = d₂ ^ k * d₁ ^ k
[PROOFSTEP]
rw [← h]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd b a)
k : ℕ
h✝ : Nontrivial α
ha : ¬a = 0
hb : ¬b = 0
hk : k > 0
hc✝ : c ∣ a * b
d₁ d₂ : α
hd₁ : d₁ ∣ a
hd₂ : d₂ ∣ b
hc : c = d₂ * d₁
h0₁ : d₁ ^ k ≠ 0
a' : α
ha' : a = d₁ ^ k * a'
h0₂ : d₂ ^ k ≠ 0
b' : α
h : d₂ ^ k * b' * (d₁ ^ k * a') = d₂ ^ k * d₁ ^ k
hb' : b = d₂ ^ k * b'
⊢ d₂ ^ k * (d₁ ^ k * (a' * b')) = d₂ ^ k * b' * (d₁ ^ k * a')
[PROOFSTEP]
rw [mul_assoc, mul_comm a', ← mul_assoc _ b', ← mul_assoc b', mul_comm b']
[GOAL]
case h.intro.intro.intro.intro
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd b a)
k : ℕ
h✝ : Nontrivial α
ha : ¬a = 0
hb : ¬b = 0
hk : k > 0
hc✝ : c ∣ a * b
d₁ d₂ : α
hd₁ : d₁ ∣ a
hd₂ : d₂ ∣ b
hc : c = d₂ * d₁
h0₁ : d₁ ^ k ≠ 0
a' : α
ha' : a = d₁ ^ k * a'
h0₂ : d₂ ^ k ≠ 0
b' : α
h : d₂ ^ k * b' * (d₁ ^ k * a') = d₂ ^ k * d₁ ^ k
hb' : b = d₂ ^ k * b'
h' : a' * b' = 1
⊢ Associated (d₁ ^ k) a
[PROOFSTEP]
use Units.mkOfMulEqOne _ _ h'
[GOAL]
case h
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
hab : IsUnit (gcd b a)
k : ℕ
h✝ : Nontrivial α
ha : ¬a = 0
hb : ¬b = 0
hk : k > 0
hc✝ : c ∣ a * b
d₁ d₂ : α
hd₁ : d₁ ∣ a
hd₂ : d₂ ∣ b
hc : c = d₂ * d₁
h0₁ : d₁ ^ k ≠ 0
a' : α
ha' : a = d₁ ^ k * a'
h0₂ : d₂ ^ k ≠ 0
b' : α
h : d₂ ^ k * b' * (d₁ ^ k * a') = d₂ ^ k * d₁ ^ k
hb' : b = d₂ ^ k * b'
h' : a' * b' = 1
⊢ d₁ ^ k * ↑(Units.mkOfMulEqOne a' b' h') = a
[PROOFSTEP]
rw [Units.val_mkOfMulEqOne, ha']
[GOAL]
α✝ : Type u_1
inst✝² : CancelCommMonoidWithZero α✝
α : Type u_2
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
x y x' y' : α
ex : x = gcd x y * x'
ey : y = gcd x y * y'
h : gcd x y ≠ 0
⊢ IsUnit (gcd x' y')
[PROOFSTEP]
rw [← associated_one_iff_isUnit]
[GOAL]
α✝ : Type u_1
inst✝² : CancelCommMonoidWithZero α✝
α : Type u_2
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
x y x' y' : α
ex : x = gcd x y * x'
ey : y = gcd x y * y'
h : gcd x y ≠ 0
⊢ Associated (gcd x' y') 1
[PROOFSTEP]
refine' Associated.of_mul_left _ (Associated.refl <| gcd x y) h
[GOAL]
α✝ : Type u_1
inst✝² : CancelCommMonoidWithZero α✝
α : Type u_2
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
x y x' y' : α
ex : x = gcd x y * x'
ey : y = gcd x y * y'
h : gcd x y ≠ 0
⊢ Associated (gcd x y * gcd x' y') (gcd x y * 1)
[PROOFSTEP]
convert (gcd_mul_left' (gcd x y) x' y').symm using 1
[GOAL]
case h.e'_4
α✝ : Type u_1
inst✝² : CancelCommMonoidWithZero α✝
α : Type u_2
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
x y x' y' : α
ex : x = gcd x y * x'
ey : y = gcd x y * y'
h : gcd x y ≠ 0
⊢ gcd x y * 1 = gcd (gcd x y * x') (gcd x y * y')
[PROOFSTEP]
rw [← ex, ← ey, mul_one]
[GOAL]
α✝ : Type u_1
inst✝² : CancelCommMonoidWithZero α✝
α : Type u_2
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
x y : α
⊢ ∃ x' y', x = gcd x y * x' ∧ y = gcd x y * y' ∧ IsUnit (gcd x' y')
[PROOFSTEP]
by_cases h : gcd x y = 0
[GOAL]
case pos
α✝ : Type u_1
inst✝² : CancelCommMonoidWithZero α✝
α : Type u_2
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
x y : α
h : gcd x y = 0
⊢ ∃ x' y', x = gcd x y * x' ∧ y = gcd x y * y' ∧ IsUnit (gcd x' y')
[PROOFSTEP]
obtain ⟨rfl, rfl⟩ := (gcd_eq_zero_iff x y).1 h
[GOAL]
case pos.intro
α✝ : Type u_1
inst✝² : CancelCommMonoidWithZero α✝
α : Type u_2
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
h : gcd 0 0 = 0
⊢ ∃ x' y', 0 = gcd 0 0 * x' ∧ 0 = gcd 0 0 * y' ∧ IsUnit (gcd x' y')
[PROOFSTEP]
simp_rw [← associated_one_iff_isUnit]
[GOAL]
case pos.intro
α✝ : Type u_1
inst✝² : CancelCommMonoidWithZero α✝
α : Type u_2
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
h : gcd 0 0 = 0
⊢ ∃ x' y', 0 = gcd 0 0 * x' ∧ 0 = gcd 0 0 * y' ∧ Associated (gcd x' y') 1
[PROOFSTEP]
exact ⟨1, 1, by rw [h, zero_mul], by rw [h, zero_mul], gcd_one_left' 1⟩
[GOAL]
α✝ : Type u_1
inst✝² : CancelCommMonoidWithZero α✝
α : Type u_2
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
h : gcd 0 0 = 0
⊢ 0 = gcd 0 0 * 1
[PROOFSTEP]
rw [h, zero_mul]
[GOAL]
α✝ : Type u_1
inst✝² : CancelCommMonoidWithZero α✝
α : Type u_2
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
h : gcd 0 0 = 0
⊢ 0 = gcd 0 0 * 1
[PROOFSTEP]
rw [h, zero_mul]
[GOAL]
case neg
α✝ : Type u_1
inst✝² : CancelCommMonoidWithZero α✝
α : Type u_2
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
x y : α
h : ¬gcd x y = 0
⊢ ∃ x' y', x = gcd x y * x' ∧ y = gcd x y * y' ∧ IsUnit (gcd x' y')
[PROOFSTEP]
obtain ⟨x', ex⟩ := gcd_dvd_left x y
[GOAL]
case neg.intro
α✝ : Type u_1
inst✝² : CancelCommMonoidWithZero α✝
α : Type u_2
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
x y : α
h : ¬gcd x y = 0
x' : α
ex : x = gcd x y * x'
⊢ ∃ x' y', x = gcd x y * x' ∧ y = gcd x y * y' ∧ IsUnit (gcd x' y')
[PROOFSTEP]
obtain ⟨y', ey⟩ := gcd_dvd_right x y
[GOAL]
case neg.intro.intro
α✝ : Type u_1
inst✝² : CancelCommMonoidWithZero α✝
α : Type u_2
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
x y : α
h : ¬gcd x y = 0
x' : α
ex : x = gcd x y * x'
y' : α
ey : y = gcd x y * y'
⊢ ∃ x' y', x = gcd x y * x' ∧ y = gcd x y * y' ∧ IsUnit (gcd x' y')
[PROOFSTEP]
exact ⟨x', y', ex, ey, isUnit_gcd_of_eq_mul_gcd ex ey h⟩
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
⊢ lcm a b ∣ c ↔ a ∣ c ∧ b ∣ c
[PROOFSTEP]
by_cases h : a = 0 ∨ b = 0
[GOAL]
case pos
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
h : a = 0 ∨ b = 0
⊢ lcm a b ∣ c ↔ a ∣ c ∧ b ∣ c
[PROOFSTEP]
rcases h with (rfl | rfl)
[GOAL]
case pos.inl
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
b c : α
⊢ lcm 0 b ∣ c ↔ 0 ∣ c ∧ b ∣ c
[PROOFSTEP]
simp (config := { contextual := true }) only [iff_def, lcm_zero_left, lcm_zero_right, zero_dvd_iff, dvd_zero,
  eq_self_iff_true, and_true_iff, imp_true_iff]
[GOAL]
case pos.inr
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a c : α
⊢ lcm a 0 ∣ c ↔ a ∣ c ∧ 0 ∣ c
[PROOFSTEP]
simp (config := { contextual := true }) only [iff_def, lcm_zero_left, lcm_zero_right, zero_dvd_iff, dvd_zero,
  eq_self_iff_true, and_true_iff, imp_true_iff]
[GOAL]
case neg
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
h : ¬(a = 0 ∨ b = 0)
⊢ lcm a b ∣ c ↔ a ∣ c ∧ b ∣ c
[PROOFSTEP]
obtain ⟨h1, h2⟩ := not_or.1 h
[GOAL]
case neg.intro
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
h : ¬(a = 0 ∨ b = 0)
h1 : ¬a = 0
h2 : ¬b = 0
⊢ lcm a b ∣ c ↔ a ∣ c ∧ b ∣ c
[PROOFSTEP]
have h : gcd a b ≠ 0 := fun H => h1 ((gcd_eq_zero_iff _ _).1 H).1
[GOAL]
case neg.intro
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b c : α
h✝ : ¬(a = 0 ∨ b = 0)
h1 : ¬a = 0
h2 : ¬b = 0
h : gcd a b ≠ 0
⊢ lcm a b ∣ c ↔ a ∣ c ∧ b ∣ c
[PROOFSTEP]
rw [← mul_dvd_mul_iff_left h, (gcd_mul_lcm a b).dvd_iff_dvd_left, ← (gcd_mul_right' c a b).dvd_iff_dvd_right,
  dvd_gcd_iff, mul_comm b c, mul_dvd_mul_iff_left h1, mul_dvd_mul_iff_right h2, and_comm]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b : α
h : lcm a b = 0
⊢ a = 0 ∨ b = 0
[PROOFSTEP]
have : Associated (a * b) 0 := (gcd_mul_lcm a b).symm.trans <| by rw [h, mul_zero]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b : α
h : lcm a b = 0
⊢ Associated (gcd a b * lcm a b) 0
[PROOFSTEP]
rw [h, mul_zero]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b : α
h : lcm a b = 0
this : Associated (a * b) 0
⊢ a = 0 ∨ b = 0
[PROOFSTEP]
rwa [← mul_eq_zero, ← associated_zero_iff_eq_zero]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b : α
⊢ a = 0 ∨ b = 0 → lcm a b = 0
[PROOFSTEP]
rintro (rfl | rfl) <;> [apply lcm_zero_left; apply lcm_zero_right]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a b : α
⊢ a = 0 ∨ b = 0 → lcm a b = 0
[PROOFSTEP]
rintro (rfl | rfl)
[GOAL]
case inl
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
b : α
⊢ lcm 0 b = 0
[PROOFSTEP]
apply lcm_zero_left
[GOAL]
case inr
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
a : α
⊢ lcm a 0 = 0
[PROOFSTEP]
apply lcm_zero_right
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizedGCDMonoid α
a b : α
x✝ : a ∣ 1 ∧ b ∣ 1
c : α
hc : 1 = a * c
d : α
hd : 1 = b * d
⊢ lcm ↑(Units.mkOfMulEqOne a c (_ : a * c = 1)) ↑(Units.mkOfMulEqOne b d (_ : b * d = 1)) = 1
[PROOFSTEP]
rw [lcm_units_coe_left, normalize_coe_units]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizedGCDMonoid α
a b c : α
⊢ a = 0 → lcm (a * b) (a * c) = ↑normalize a * lcm b c
[PROOFSTEP]
rintro rfl
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizedGCDMonoid α
b c : α
⊢ lcm (0 * b) (0 * c) = ↑normalize 0 * lcm b c
[PROOFSTEP]
simp only [zero_mul, lcm_zero_left, normalize_zero]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizedGCDMonoid α
a b c : α
ha : a ≠ 0
this : lcm (a * b) (a * c) = ↑normalize (a * lcm b c)
⊢ lcm (a * b) (a * c) = ↑normalize a * lcm b c
[PROOFSTEP]
simpa
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizedGCDMonoid α
a b c : α
⊢ lcm (b * a) (c * a) = lcm b c * ↑normalize a
[PROOFSTEP]
simp only [mul_comm, lcm_mul_left]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : NormalizedGCDMonoid α
a b : α
h : ↑normalize b = b
⊢ lcm a b = b ↔ a ∣ b
[PROOFSTEP]
simpa only [lcm_comm b a] using lcm_eq_left_iff b a h
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
x : α
hi : Irreducible x
a b : α
h : x ∣ a * b
⊢ x ∣ a ∨ x ∣ b
[PROOFSTEP]
cases' gcd_dvd_left x a with y hy
[GOAL]
case intro
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
x : α
hi : Irreducible x
a b : α
h : x ∣ a * b
y : α
hy : x = gcd x a * y
⊢ x ∣ a ∨ x ∣ b
[PROOFSTEP]
cases' hi.isUnit_or_isUnit hy with hu hu
[GOAL]
case intro.inl
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
x : α
hi : Irreducible x
a b : α
h : x ∣ a * b
y : α
hy : x = gcd x a * y
hu : IsUnit (gcd x a)
⊢ x ∣ a ∨ x ∣ b
[PROOFSTEP]
right
[GOAL]
case intro.inl.h
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
x : α
hi : Irreducible x
a b : α
h : x ∣ a * b
y : α
hy : x = gcd x a * y
hu : IsUnit (gcd x a)
⊢ x ∣ b
[PROOFSTEP]
trans gcd (x * b) (a * b)
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
x : α
hi : Irreducible x
a b : α
h : x ∣ a * b
y : α
hy : x = gcd x a * y
hu : IsUnit (gcd x a)
⊢ x ∣ gcd (x * b) (a * b)
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
x : α
hi : Irreducible x
a b : α
h : x ∣ a * b
y : α
hy : x = gcd x a * y
hu : IsUnit (gcd x a)
⊢ gcd (x * b) (a * b) ∣ b
[PROOFSTEP]
apply dvd_gcd (dvd_mul_right x b) h
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
x : α
hi : Irreducible x
a b : α
h : x ∣ a * b
y : α
hy : x = gcd x a * y
hu : IsUnit (gcd x a)
⊢ gcd (x * b) (a * b) ∣ b
[PROOFSTEP]
rw [(gcd_mul_right' b x a).dvd_iff_dvd_left]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
x : α
hi : Irreducible x
a b : α
h : x ∣ a * b
y : α
hy : x = gcd x a * y
hu : IsUnit (gcd x a)
⊢ gcd x a * b ∣ b
[PROOFSTEP]
exact (associated_unit_mul_left _ _ hu).dvd
[GOAL]
case intro.inr
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
x : α
hi : Irreducible x
a b : α
h : x ∣ a * b
y : α
hy : x = gcd x a * y
hu : IsUnit y
⊢ x ∣ a ∨ x ∣ b
[PROOFSTEP]
left
[GOAL]
case intro.inr.h
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
x : α
hi : Irreducible x
a b : α
h : x ∣ a * b
y : α
hy : x = gcd x a * y
hu : IsUnit y
⊢ x ∣ a
[PROOFSTEP]
rw [hy]
[GOAL]
case intro.inr.h
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : GCDMonoid α
x : α
hi : Irreducible x
a b : α
h : x ∣ a * b
y : α
hy : x = gcd x a * y
hu : IsUnit y
⊢ gcd x a * y ∣ a
[PROOFSTEP]
exact dvd_trans (associated_mul_unit_left _ _ hu).dvd (gcd_dvd_right x a)
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Unique αˣ
x✝ : NormalizationMonoid α
u : α → αˣ
normUnit_zero✝ : u 0 = 1
normUnit_mul✝ : ∀ {a b : α}, a ≠ 0 → b ≠ 0 → u (a * b) = u a * u b
normUnit_coe_units✝ : ∀ (u_1 : αˣ), u ↑u_1 = u_1⁻¹
⊢ { normUnit := u, normUnit_zero := normUnit_zero✝, normUnit_mul := normUnit_mul✝,
      normUnit_coe_units := normUnit_coe_units✝ } =
    default
[PROOFSTEP]
congr
[GOAL]
case e_normUnit
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Unique αˣ
x✝ : NormalizationMonoid α
u : α → αˣ
normUnit_zero✝ : u 0 = 1
normUnit_mul✝ : ∀ {a b : α}, a ≠ 0 → b ≠ 0 → u (a * b) = u a * u b
normUnit_coe_units✝ : ∀ (u_1 : αˣ), u ↑u_1 = u_1⁻¹
⊢ u = fun x => 1
[PROOFSTEP]
simp
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Unique αˣ
g₁ g₂ : GCDMonoid α
⊢ g₁ = g₂
[PROOFSTEP]
have hgcd : g₁.gcd = g₂.gcd := by
  ext a b
  refine'
    associated_iff_eq.mp
      (associated_of_dvd_dvd _ _)
        -- Porting note: Lean4 seems to need help specifying `g₁` and `g₂`
  · exact dvd_gcd (@gcd_dvd_left _ _ g₁ _ _) (@gcd_dvd_right _ _ g₁ _ _)
  · exact @dvd_gcd _ _ g₁ _ _ _ (@gcd_dvd_left _ _ g₂ _ _) (@gcd_dvd_right _ _ g₂ _ _)
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Unique αˣ
g₁ g₂ : GCDMonoid α
⊢ gcd = gcd
[PROOFSTEP]
ext a b
[GOAL]
case h.h
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Unique αˣ
g₁ g₂ : GCDMonoid α
a b : α
⊢ gcd a b = gcd a b
[PROOFSTEP]
refine'
  associated_iff_eq.mp
    (associated_of_dvd_dvd _ _)
      -- Porting note: Lean4 seems to need help specifying `g₁` and `g₂`
[GOAL]
case h.h.refine'_1
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Unique αˣ
g₁ g₂ : GCDMonoid α
a b : α
⊢ gcd a b ∣ gcd a b
[PROOFSTEP]
exact dvd_gcd (@gcd_dvd_left _ _ g₁ _ _) (@gcd_dvd_right _ _ g₁ _ _)
[GOAL]
case h.h.refine'_2
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Unique αˣ
g₁ g₂ : GCDMonoid α
a b : α
⊢ gcd a b ∣ gcd a b
[PROOFSTEP]
exact @dvd_gcd _ _ g₁ _ _ _ (@gcd_dvd_left _ _ g₂ _ _) (@gcd_dvd_right _ _ g₂ _ _)
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Unique αˣ
g₁ g₂ : GCDMonoid α
hgcd : gcd = gcd
⊢ g₁ = g₂
[PROOFSTEP]
have hlcm : g₁.lcm = g₂.lcm := by
  ext a b
  refine' associated_iff_eq.mp (associated_of_dvd_dvd _ _)
  · exact (@lcm_dvd_iff _ _ g₁ ..).mpr ⟨@dvd_lcm_left _ _ g₂ _ _, @dvd_lcm_right _ _ g₂ _ _⟩
  · exact lcm_dvd_iff.mpr ⟨@dvd_lcm_left _ _ g₁ _ _, @dvd_lcm_right _ _ g₁ _ _⟩
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Unique αˣ
g₁ g₂ : GCDMonoid α
hgcd : gcd = gcd
⊢ lcm = lcm
[PROOFSTEP]
ext a b
[GOAL]
case h.h
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Unique αˣ
g₁ g₂ : GCDMonoid α
hgcd : gcd = gcd
a b : α
⊢ lcm a b = lcm a b
[PROOFSTEP]
refine' associated_iff_eq.mp (associated_of_dvd_dvd _ _)
[GOAL]
case h.h.refine'_1
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Unique αˣ
g₁ g₂ : GCDMonoid α
hgcd : gcd = gcd
a b : α
⊢ lcm a b ∣ lcm a b
[PROOFSTEP]
exact (@lcm_dvd_iff _ _ g₁ ..).mpr ⟨@dvd_lcm_left _ _ g₂ _ _, @dvd_lcm_right _ _ g₂ _ _⟩
[GOAL]
case h.h.refine'_2
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Unique αˣ
g₁ g₂ : GCDMonoid α
hgcd : gcd = gcd
a b : α
⊢ lcm a b ∣ lcm a b
[PROOFSTEP]
exact lcm_dvd_iff.mpr ⟨@dvd_lcm_left _ _ g₁ _ _, @dvd_lcm_right _ _ g₁ _ _⟩
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Unique αˣ
g₁ g₂ : GCDMonoid α
hgcd : gcd = gcd
hlcm : lcm = lcm
⊢ g₁ = g₂
[PROOFSTEP]
cases g₁
[GOAL]
case mk
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Unique αˣ
g₂ : GCDMonoid α
gcd✝ lcm✝ : α → α → α
gcd_dvd_left✝ : ∀ (a b : α), gcd✝ a b ∣ a
gcd_dvd_right✝ : ∀ (a b : α), gcd✝ a b ∣ b
dvd_gcd✝ : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd✝ c b
gcd_mul_lcm✝ : ∀ (a b : α), Associated (gcd✝ a b * lcm✝ a b) (a * b)
lcm_zero_left✝ : ∀ (a : α), lcm✝ 0 a = 0
lcm_zero_right✝ : ∀ (a : α), lcm✝ a 0 = 0
hgcd : gcd = gcd
hlcm : lcm = lcm
⊢ { gcd := gcd✝, lcm := lcm✝, gcd_dvd_left := gcd_dvd_left✝, gcd_dvd_right := gcd_dvd_right✝, dvd_gcd := dvd_gcd✝,
      gcd_mul_lcm := gcd_mul_lcm✝, lcm_zero_left := lcm_zero_left✝, lcm_zero_right := lcm_zero_right✝ } =
    g₂
[PROOFSTEP]
cases g₂
[GOAL]
case mk.mk
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Unique αˣ
gcd✝¹ lcm✝¹ : α → α → α
gcd_dvd_left✝¹ : ∀ (a b : α), gcd✝¹ a b ∣ a
gcd_dvd_right✝¹ : ∀ (a b : α), gcd✝¹ a b ∣ b
dvd_gcd✝¹ : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd✝¹ c b
gcd_mul_lcm✝¹ : ∀ (a b : α), Associated (gcd✝¹ a b * lcm✝¹ a b) (a * b)
lcm_zero_left✝¹ : ∀ (a : α), lcm✝¹ 0 a = 0
lcm_zero_right✝¹ : ∀ (a : α), lcm✝¹ a 0 = 0
gcd✝ lcm✝ : α → α → α
gcd_dvd_left✝ : ∀ (a b : α), gcd✝ a b ∣ a
gcd_dvd_right✝ : ∀ (a b : α), gcd✝ a b ∣ b
dvd_gcd✝ : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd✝ c b
gcd_mul_lcm✝ : ∀ (a b : α), Associated (gcd✝ a b * lcm✝ a b) (a * b)
lcm_zero_left✝ : ∀ (a : α), lcm✝ 0 a = 0
lcm_zero_right✝ : ∀ (a : α), lcm✝ a 0 = 0
hgcd : gcd = gcd
hlcm : lcm = lcm
⊢ { gcd := gcd✝¹, lcm := lcm✝¹, gcd_dvd_left := gcd_dvd_left✝¹, gcd_dvd_right := gcd_dvd_right✝¹, dvd_gcd := dvd_gcd✝¹,
      gcd_mul_lcm := gcd_mul_lcm✝¹, lcm_zero_left := lcm_zero_left✝¹, lcm_zero_right := lcm_zero_right✝¹ } =
    { gcd := gcd✝, lcm := lcm✝, gcd_dvd_left := gcd_dvd_left✝, gcd_dvd_right := gcd_dvd_right✝, dvd_gcd := dvd_gcd✝,
      gcd_mul_lcm := gcd_mul_lcm✝, lcm_zero_left := lcm_zero_left✝, lcm_zero_right := lcm_zero_right✝ }
[PROOFSTEP]
dsimp only at hgcd hlcm 
[GOAL]
case mk.mk
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Unique αˣ
gcd✝¹ lcm✝¹ : α → α → α
gcd_dvd_left✝¹ : ∀ (a b : α), gcd✝¹ a b ∣ a
gcd_dvd_right✝¹ : ∀ (a b : α), gcd✝¹ a b ∣ b
dvd_gcd✝¹ : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd✝¹ c b
gcd_mul_lcm✝¹ : ∀ (a b : α), Associated (gcd✝¹ a b * lcm✝¹ a b) (a * b)
lcm_zero_left✝¹ : ∀ (a : α), lcm✝¹ 0 a = 0
lcm_zero_right✝¹ : ∀ (a : α), lcm✝¹ a 0 = 0
gcd✝ lcm✝ : α → α → α
gcd_dvd_left✝ : ∀ (a b : α), gcd✝ a b ∣ a
gcd_dvd_right✝ : ∀ (a b : α), gcd✝ a b ∣ b
dvd_gcd✝ : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd✝ c b
gcd_mul_lcm✝ : ∀ (a b : α), Associated (gcd✝ a b * lcm✝ a b) (a * b)
lcm_zero_left✝ : ∀ (a : α), lcm✝ 0 a = 0
lcm_zero_right✝ : ∀ (a : α), lcm✝ a 0 = 0
hgcd : gcd✝¹ = gcd✝
hlcm : lcm✝¹ = lcm✝
⊢ { gcd := gcd✝¹, lcm := lcm✝¹, gcd_dvd_left := gcd_dvd_left✝¹, gcd_dvd_right := gcd_dvd_right✝¹, dvd_gcd := dvd_gcd✝¹,
      gcd_mul_lcm := gcd_mul_lcm✝¹, lcm_zero_left := lcm_zero_left✝¹, lcm_zero_right := lcm_zero_right✝¹ } =
    { gcd := gcd✝, lcm := lcm✝, gcd_dvd_left := gcd_dvd_left✝, gcd_dvd_right := gcd_dvd_right✝, dvd_gcd := dvd_gcd✝,
      gcd_mul_lcm := gcd_mul_lcm✝, lcm_zero_left := lcm_zero_left✝, lcm_zero_right := lcm_zero_right✝ }
[PROOFSTEP]
simp only [hgcd, hlcm]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Unique αˣ
⊢ ∀ (a b : NormalizedGCDMonoid α), a = b
[PROOFSTEP]
intro a b
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Unique αˣ
a b : NormalizedGCDMonoid α
⊢ a = b
[PROOFSTEP]
cases' a with a_norm a_gcd
[GOAL]
case mk
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Unique αˣ
b : NormalizedGCDMonoid α
a_norm : NormalizationMonoid α
a_gcd : GCDMonoid α
normalize_gcd✝ : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
normalize_lcm✝ : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
⊢ NormalizedGCDMonoid.mk normalize_gcd✝ normalize_lcm✝ = b
[PROOFSTEP]
cases' b with b_norm b_gcd
[GOAL]
case mk.mk
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Unique αˣ
a_norm : NormalizationMonoid α
a_gcd : GCDMonoid α
normalize_gcd✝¹ : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
normalize_lcm✝¹ : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
b_norm : NormalizationMonoid α
b_gcd : GCDMonoid α
normalize_gcd✝ : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
normalize_lcm✝ : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
⊢ NormalizedGCDMonoid.mk normalize_gcd✝¹ normalize_lcm✝¹ = NormalizedGCDMonoid.mk normalize_gcd✝ normalize_lcm✝
[PROOFSTEP]
have := Subsingleton.elim a_gcd b_gcd
[GOAL]
case mk.mk
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Unique αˣ
a_norm : NormalizationMonoid α
a_gcd : GCDMonoid α
normalize_gcd✝¹ : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
normalize_lcm✝¹ : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
b_norm : NormalizationMonoid α
b_gcd : GCDMonoid α
normalize_gcd✝ : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
normalize_lcm✝ : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
this : a_gcd = b_gcd
⊢ NormalizedGCDMonoid.mk normalize_gcd✝¹ normalize_lcm✝¹ = NormalizedGCDMonoid.mk normalize_gcd✝ normalize_lcm✝
[PROOFSTEP]
subst this
[GOAL]
case mk.mk
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Unique αˣ
a_norm : NormalizationMonoid α
a_gcd : GCDMonoid α
normalize_gcd✝¹ : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
normalize_lcm✝¹ : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
b_norm : NormalizationMonoid α
normalize_gcd✝ : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
normalize_lcm✝ : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
⊢ NormalizedGCDMonoid.mk normalize_gcd✝¹ normalize_lcm✝¹ = NormalizedGCDMonoid.mk normalize_gcd✝ normalize_lcm✝
[PROOFSTEP]
have := Subsingleton.elim a_norm b_norm
[GOAL]
case mk.mk
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Unique αˣ
a_norm : NormalizationMonoid α
a_gcd : GCDMonoid α
normalize_gcd✝¹ : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
normalize_lcm✝¹ : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
b_norm : NormalizationMonoid α
normalize_gcd✝ : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
normalize_lcm✝ : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
this : a_norm = b_norm
⊢ NormalizedGCDMonoid.mk normalize_gcd✝¹ normalize_lcm✝¹ = NormalizedGCDMonoid.mk normalize_gcd✝ normalize_lcm✝
[PROOFSTEP]
subst this
[GOAL]
case mk.mk
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Unique αˣ
a_norm : NormalizationMonoid α
a_gcd : GCDMonoid α
normalize_gcd✝¹ : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
normalize_lcm✝¹ : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
normalize_gcd✝ : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
normalize_lcm✝ : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
⊢ NormalizedGCDMonoid.mk normalize_gcd✝¹ normalize_lcm✝¹ = NormalizedGCDMonoid.mk normalize_gcd✝ normalize_lcm✝
[PROOFSTEP]
rfl
[GOAL]
α : Type u_1
inst✝² : CommRing α
inst✝¹ : IsDomain α
inst✝ : NormalizedGCDMonoid α
a b c : α
h : a ∣ b - c
⊢ gcd a b = gcd a c
[PROOFSTEP]
apply dvd_antisymm_of_normalize_eq (normalize_gcd _ _) (normalize_gcd _ _)
[GOAL]
case hab
α : Type u_1
inst✝² : CommRing α
inst✝¹ : IsDomain α
inst✝ : NormalizedGCDMonoid α
a b c : α
h : a ∣ b - c
⊢ gcd a b ∣ gcd a c
[PROOFSTEP]
rw [dvd_gcd_iff]
[GOAL]
case hba
α : Type u_1
inst✝² : CommRing α
inst✝¹ : IsDomain α
inst✝ : NormalizedGCDMonoid α
a b c : α
h : a ∣ b - c
⊢ gcd a c ∣ gcd a b
[PROOFSTEP]
rw [dvd_gcd_iff]
[GOAL]
case hab
α : Type u_1
inst✝² : CommRing α
inst✝¹ : IsDomain α
inst✝ : NormalizedGCDMonoid α
a b c : α
h : a ∣ b - c
⊢ gcd a b ∣ a ∧ gcd a b ∣ c
[PROOFSTEP]
refine' ⟨gcd_dvd_left _ _, _⟩
[GOAL]
case hba
α : Type u_1
inst✝² : CommRing α
inst✝¹ : IsDomain α
inst✝ : NormalizedGCDMonoid α
a b c : α
h : a ∣ b - c
⊢ gcd a c ∣ a ∧ gcd a c ∣ b
[PROOFSTEP]
refine' ⟨gcd_dvd_left _ _, _⟩
[GOAL]
case hab
α : Type u_1
inst✝² : CommRing α
inst✝¹ : IsDomain α
inst✝ : NormalizedGCDMonoid α
a b c : α
h : a ∣ b - c
⊢ gcd a b ∣ c
[PROOFSTEP]
rcases h with ⟨d, hd⟩
[GOAL]
case hab.intro
α : Type u_1
inst✝² : CommRing α
inst✝¹ : IsDomain α
inst✝ : NormalizedGCDMonoid α
a b c d : α
hd : b - c = a * d
⊢ gcd a b ∣ c
[PROOFSTEP]
rcases gcd_dvd_right a b with ⟨e, he⟩
[GOAL]
case hab.intro.intro
α : Type u_1
inst✝² : CommRing α
inst✝¹ : IsDomain α
inst✝ : NormalizedGCDMonoid α
a b c d : α
hd : b - c = a * d
e : α
he : b = gcd a b * e
⊢ gcd a b ∣ c
[PROOFSTEP]
rcases gcd_dvd_left a b with ⟨f, hf⟩
[GOAL]
case hab.intro.intro.intro
α : Type u_1
inst✝² : CommRing α
inst✝¹ : IsDomain α
inst✝ : NormalizedGCDMonoid α
a b c d : α
hd : b - c = a * d
e : α
he : b = gcd a b * e
f : α
hf : a = gcd a b * f
⊢ gcd a b ∣ c
[PROOFSTEP]
use e - f * d
[GOAL]
case h
α : Type u_1
inst✝² : CommRing α
inst✝¹ : IsDomain α
inst✝ : NormalizedGCDMonoid α
a b c d : α
hd : b - c = a * d
e : α
he : b = gcd a b * e
f : α
hf : a = gcd a b * f
⊢ c = gcd a b * (e - f * d)
[PROOFSTEP]
rw [mul_sub, ← he, ← mul_assoc, ← hf, ← hd, sub_sub_cancel]
[GOAL]
case hba
α : Type u_1
inst✝² : CommRing α
inst✝¹ : IsDomain α
inst✝ : NormalizedGCDMonoid α
a b c : α
h : a ∣ b - c
⊢ gcd a c ∣ b
[PROOFSTEP]
rcases h with ⟨d, hd⟩
[GOAL]
case hba.intro
α : Type u_1
inst✝² : CommRing α
inst✝¹ : IsDomain α
inst✝ : NormalizedGCDMonoid α
a b c d : α
hd : b - c = a * d
⊢ gcd a c ∣ b
[PROOFSTEP]
rcases gcd_dvd_right a c with ⟨e, he⟩
[GOAL]
case hba.intro.intro
α : Type u_1
inst✝² : CommRing α
inst✝¹ : IsDomain α
inst✝ : NormalizedGCDMonoid α
a b c d : α
hd : b - c = a * d
e : α
he : c = gcd a c * e
⊢ gcd a c ∣ b
[PROOFSTEP]
rcases gcd_dvd_left a c with ⟨f, hf⟩
[GOAL]
case hba.intro.intro.intro
α : Type u_1
inst✝² : CommRing α
inst✝¹ : IsDomain α
inst✝ : NormalizedGCDMonoid α
a b c d : α
hd : b - c = a * d
e : α
he : c = gcd a c * e
f : α
hf : a = gcd a c * f
⊢ gcd a c ∣ b
[PROOFSTEP]
use e + f * d
[GOAL]
case h
α : Type u_1
inst✝² : CommRing α
inst✝¹ : IsDomain α
inst✝ : NormalizedGCDMonoid α
a b c d : α
hd : b - c = a * d
e : α
he : c = gcd a c * e
f : α
hf : a = gcd a c * f
⊢ b = gcd a c * (e + f * d)
[PROOFSTEP]
rw [mul_add, ← he, ← mul_assoc, ← hf, ← hd, ← add_sub_assoc, add_comm c b, add_sub_cancel]
[GOAL]
α : Type u_1
inst✝² : CommRing α
inst✝¹ : IsDomain α
inst✝ : NormalizedGCDMonoid α
a b c : α
h : a ∣ b - c
⊢ gcd b a = gcd c a
[PROOFSTEP]
rw [gcd_comm _ a, gcd_comm _ a, gcd_eq_of_dvd_sub_right h]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
f : Associates α →* α
hinv : Function.RightInverse (↑f) Associates.mk
a b : α
ha : a ≠ 0
hb : b ≠ 0
⊢ (fun a => if a = 0 then 1 else Classical.choose (_ : Associated a (↑f (Associates.mk a)))) (a * b) =
    (fun a => if a = 0 then 1 else Classical.choose (_ : Associated a (↑f (Associates.mk a)))) a *
      (fun a => if a = 0 then 1 else Classical.choose (_ : Associated a (↑f (Associates.mk a)))) b
[PROOFSTEP]
simp_rw [if_neg (mul_ne_zero ha hb), if_neg ha, if_neg hb, Units.ext_iff, Units.val_mul]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
f : Associates α →* α
hinv : Function.RightInverse (↑f) Associates.mk
a b : α
ha : a ≠ 0
hb : b ≠ 0
⊢ ↑(Classical.choose (_ : Associated (a * b) (↑f (Associates.mk (a * b))))) =
    ↑(Classical.choose (_ : Associated a (↑f (Associates.mk a)))) *
      ↑(Classical.choose (_ : Associated b (↑f (Associates.mk b))))
[PROOFSTEP]
suffices
  a * b * ↑(Classical.choose (associated_map_mk hinv (a * b))) =
    a * ↑(Classical.choose (associated_map_mk hinv a)) * (b * ↑(Classical.choose (associated_map_mk hinv b)))
  by
  apply
    mul_left_cancel₀ (mul_ne_zero ha hb)
      _
        -- Porting note: original `simpa` fails with `unexpected bound variable #1`
              -- simpa only [mul_assoc, mul_comm, mul_left_comm] using this
  rw [this, mul_assoc, ← mul_assoc _ b, mul_comm _ b, ← mul_assoc, ← mul_assoc, mul_assoc (a * b)]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
f : Associates α →* α
hinv : Function.RightInverse (↑f) Associates.mk
a b : α
ha : a ≠ 0
hb : b ≠ 0
this :
  a * b * ↑(Classical.choose (_ : Associated (a * b) (↑f (Associates.mk (a * b))))) =
    a * ↑(Classical.choose (_ : Associated a (↑f (Associates.mk a)))) *
      (b * ↑(Classical.choose (_ : Associated b (↑f (Associates.mk b)))))
⊢ ↑(Classical.choose (_ : Associated (a * b) (↑f (Associates.mk (a * b))))) =
    ↑(Classical.choose (_ : Associated a (↑f (Associates.mk a)))) *
      ↑(Classical.choose (_ : Associated b (↑f (Associates.mk b))))
[PROOFSTEP]
apply
  mul_left_cancel₀ (mul_ne_zero ha hb)
    _
      -- Porting note: original `simpa` fails with `unexpected bound variable #1`
            -- simpa only [mul_assoc, mul_comm, mul_left_comm] using this
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
f : Associates α →* α
hinv : Function.RightInverse (↑f) Associates.mk
a b : α
ha : a ≠ 0
hb : b ≠ 0
this :
  a * b * ↑(Classical.choose (_ : Associated (a * b) (↑f (Associates.mk (a * b))))) =
    a * ↑(Classical.choose (_ : Associated a (↑f (Associates.mk a)))) *
      (b * ↑(Classical.choose (_ : Associated b (↑f (Associates.mk b)))))
⊢ a * b * ↑(Classical.choose (_ : Associated (a * b) (↑f (Associates.mk (a * b))))) =
    a * b *
      (↑(Classical.choose (_ : Associated a (↑f (Associates.mk a)))) *
        ↑(Classical.choose (_ : Associated b (↑f (Associates.mk b)))))
[PROOFSTEP]
rw [this, mul_assoc, ← mul_assoc _ b, mul_comm _ b, ← mul_assoc, ← mul_assoc, mul_assoc (a * b)]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
f : Associates α →* α
hinv : Function.RightInverse (↑f) Associates.mk
a b : α
ha : a ≠ 0
hb : b ≠ 0
⊢ a * b * ↑(Classical.choose (_ : Associated (a * b) (↑f (Associates.mk (a * b))))) =
    a * ↑(Classical.choose (_ : Associated a (↑f (Associates.mk a)))) *
      (b * ↑(Classical.choose (_ : Associated b (↑f (Associates.mk b)))))
[PROOFSTEP]
rw [map_mk_unit_aux hinv a, map_mk_unit_aux hinv (a * b), map_mk_unit_aux hinv b, ← MonoidHom.map_mul,
  Associates.mk_mul_mk]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
f : Associates α →* α
hinv : Function.RightInverse (↑f) Associates.mk
u : αˣ
⊢ (fun a => if a = 0 then 1 else Classical.choose (_ : Associated a (↑f (Associates.mk a)))) ↑u = u⁻¹
[PROOFSTEP]
nontriviality α
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
f : Associates α →* α
hinv : Function.RightInverse (↑f) Associates.mk
u : αˣ
✝ : Nontrivial α
⊢ (fun a => if a = 0 then 1 else Classical.choose (_ : Associated a (↑f (Associates.mk a)))) ↑u = u⁻¹
[PROOFSTEP]
simp_rw [if_neg (Units.ne_zero u), Units.ext_iff]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
f : Associates α →* α
hinv : Function.RightInverse (↑f) Associates.mk
u : αˣ
✝ : Nontrivial α
⊢ ↑(Classical.choose (_ : Associated (↑u) (↑f (Associates.mk ↑u)))) = ↑u⁻¹
[PROOFSTEP]
apply mul_left_cancel₀ (Units.ne_zero u)
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
f : Associates α →* α
hinv : Function.RightInverse (↑f) Associates.mk
u : αˣ
✝ : Nontrivial α
⊢ ↑u * ↑(Classical.choose (_ : Associated (↑u) (↑f (Associates.mk ↑u)))) = ↑u * ↑u⁻¹
[PROOFSTEP]
rw [Units.mul_inv, map_mk_unit_aux hinv u, Associates.mk_eq_mk_iff_associated.2 (associated_one_iff_isUnit.2 ⟨u, rfl⟩),
  Associates.mk_one, MonoidHom.map_one]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
a b : α
⊢ Associated (gcd a b * (fun a b => if a = 0 then 0 else Classical.choose (_ : gcd a b ∣ a * b)) a b) (a * b)
[PROOFSTEP]
dsimp only
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
a b : α
⊢ Associated (gcd a b * if a = 0 then 0 else Classical.choose (_ : gcd a b ∣ a * b)) (a * b)
[PROOFSTEP]
split_ifs with a0
[GOAL]
case pos
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
a b : α
a0 : a = 0
⊢ Associated (gcd a b * 0) (a * b)
[PROOFSTEP]
rw [mul_zero, a0, zero_mul]
[GOAL]
case neg
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
a b : α
a0 : ¬a = 0
⊢ Associated (gcd a b * Classical.choose (_ : gcd a b ∣ a * b)) (a * b)
[PROOFSTEP]
rw [← Classical.choose_spec ((gcd_dvd_left a b).trans (Dvd.intro b rfl))]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
a : α
⊢ (fun a b => if a = 0 then 0 else Classical.choose (_ : gcd a b ∣ a * b)) a 0 = 0
[PROOFSTEP]
dsimp only
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
a : α
⊢ (if a = 0 then 0 else Classical.choose (_ : gcd a 0 ∣ a * 0)) = 0
[PROOFSTEP]
split_ifs with a0
[GOAL]
case pos
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
a : α
a0 : a = 0
⊢ 0 = 0
[PROOFSTEP]
rfl
[GOAL]
case neg
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
a : α
a0 : ¬a = 0
⊢ Classical.choose (_ : gcd a 0 ∣ a * 0) = 0
[PROOFSTEP]
have h := (Classical.choose_spec ((gcd_dvd_left a 0).trans (Dvd.intro 0 rfl))).symm
[GOAL]
case neg
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
a : α
a0 : ¬a = 0
h : gcd a 0 * Classical.choose (_ : gcd a 0 ∣ a * 0) = a * 0
⊢ Classical.choose (_ : gcd a 0 ∣ a * 0) = 0
[PROOFSTEP]
have a0' : gcd a 0 ≠ 0 := by
  contrapose! a0
  rw [← associated_zero_iff_eq_zero, ← a0]
  exact associated_of_dvd_dvd (dvd_gcd (dvd_refl a) (dvd_zero a)) (gcd_dvd_left _ _)
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
a : α
a0 : ¬a = 0
h : gcd a 0 * Classical.choose (_ : gcd a 0 ∣ a * 0) = a * 0
⊢ gcd a 0 ≠ 0
[PROOFSTEP]
contrapose! a0
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
a : α
h : gcd a 0 * Classical.choose (_ : gcd a 0 ∣ a * 0) = a * 0
a0 : gcd a 0 = 0
⊢ a = 0
[PROOFSTEP]
rw [← associated_zero_iff_eq_zero, ← a0]
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
a : α
h : gcd a 0 * Classical.choose (_ : gcd a 0 ∣ a * 0) = a * 0
a0 : gcd a 0 = 0
⊢ Associated a (gcd a 0)
[PROOFSTEP]
exact associated_of_dvd_dvd (dvd_gcd (dvd_refl a) (dvd_zero a)) (gcd_dvd_left _ _)
[GOAL]
case neg
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
a : α
a0 : ¬a = 0
h : gcd a 0 * Classical.choose (_ : gcd a 0 ∣ a * 0) = a * 0
a0' : gcd a 0 ≠ 0
⊢ Classical.choose (_ : gcd a 0 ∣ a * 0) = 0
[PROOFSTEP]
apply Or.resolve_left (mul_eq_zero.1 _) a0'
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
a : α
a0 : ¬a = 0
h : gcd a 0 * Classical.choose (_ : gcd a 0 ∣ a * 0) = a * 0
a0' : gcd a 0 ≠ 0
⊢ gcd a 0 * Classical.choose (_ : gcd a 0 ∣ a * 0) = 0
[PROOFSTEP]
rw [h, mul_zero]
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
normalize_gcd : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
src✝ : NormalizationMonoid α := inferInstance
a b : α
⊢ Associated (gcd a b * (fun a b => if a = 0 then 0 else Classical.choose (_ : gcd a b ∣ ↑normalize (a * b))) a b)
    (a * b)
[PROOFSTEP]
dsimp only
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
normalize_gcd : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
src✝ : NormalizationMonoid α := inferInstance
a b : α
⊢ Associated (gcd a b * if a = 0 then 0 else Classical.choose (_ : gcd a b ∣ ↑normalize (a * b))) (a * b)
[PROOFSTEP]
split_ifs with a0
[GOAL]
case pos
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
normalize_gcd : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
src✝ : NormalizationMonoid α := inferInstance
a b : α
a0 : a = 0
⊢ Associated (gcd a b * 0) (a * b)
[PROOFSTEP]
rw [mul_zero, a0, zero_mul]
[GOAL]
case neg
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
normalize_gcd : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
src✝ : NormalizationMonoid α := inferInstance
a b : α
a0 : ¬a = 0
⊢ Associated (gcd a b * Classical.choose (_ : gcd a b ∣ ↑normalize (a * b))) (a * b)
[PROOFSTEP]
rw [← Classical.choose_spec (dvd_normalize_iff.2 ((gcd_dvd_left a b).trans (Dvd.intro b rfl)))]
[GOAL]
case neg
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
normalize_gcd : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
src✝ : NormalizationMonoid α := inferInstance
a b : α
a0 : ¬a = 0
⊢ Associated (↑normalize (a * b)) (a * b)
[PROOFSTEP]
exact normalize_associated (a * b)
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
normalize_gcd : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
src✝ : NormalizationMonoid α := inferInstance
a : α
⊢ (fun a b => if a = 0 then 0 else Classical.choose (_ : gcd a b ∣ ↑normalize (a * b))) a 0 = 0
[PROOFSTEP]
dsimp only
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
normalize_gcd : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
src✝ : NormalizationMonoid α := inferInstance
a : α
⊢ (if a = 0 then 0 else Classical.choose (_ : gcd a 0 ∣ ↑normalize (a * 0))) = 0
[PROOFSTEP]
split_ifs with a0
[GOAL]
case pos
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
normalize_gcd : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
src✝ : NormalizationMonoid α := inferInstance
a : α
a0 : a = 0
⊢ 0 = 0
[PROOFSTEP]
rfl
[GOAL]
case neg
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
normalize_gcd : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
src✝ : NormalizationMonoid α := inferInstance
a : α
a0 : ¬a = 0
⊢ Classical.choose (_ : gcd a 0 ∣ ↑normalize (a * 0)) = 0
[PROOFSTEP]
rw [← normalize_eq_zero] at a0 
[GOAL]
case neg
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
normalize_gcd : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
src✝ : NormalizationMonoid α := inferInstance
a : α
a0✝ : ¬a = 0
a0 : ¬↑normalize a = 0
⊢ Classical.choose (_ : gcd a 0 ∣ ↑normalize (a * 0)) = 0
[PROOFSTEP]
have h := (Classical.choose_spec (dvd_normalize_iff.2 ((gcd_dvd_left a 0).trans (Dvd.intro 0 rfl)))).symm
[GOAL]
case neg
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
normalize_gcd : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
src✝ : NormalizationMonoid α := inferInstance
a : α
a0✝ : ¬a = 0
a0 : ¬↑normalize a = 0
h : gcd a 0 * Classical.choose (_ : gcd a 0 ∣ ↑normalize (a * 0)) = ↑normalize (a * 0)
⊢ Classical.choose (_ : gcd a 0 ∣ ↑normalize (a * 0)) = 0
[PROOFSTEP]
have gcd0 : gcd a 0 = normalize a := by
  rw [← normalize_gcd]
  exact normalize_eq_normalize (gcd_dvd_left _ _) (dvd_gcd (dvd_refl a) (dvd_zero a))
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
normalize_gcd : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
src✝ : NormalizationMonoid α := inferInstance
a : α
a0✝ : ¬a = 0
a0 : ¬↑normalize a = 0
h : gcd a 0 * Classical.choose (_ : gcd a 0 ∣ ↑normalize (a * 0)) = ↑normalize (a * 0)
⊢ gcd a 0 = ↑normalize a
[PROOFSTEP]
rw [← normalize_gcd]
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
normalize_gcd : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
src✝ : NormalizationMonoid α := inferInstance
a : α
a0✝ : ¬a = 0
a0 : ¬↑normalize a = 0
h : gcd a 0 * Classical.choose (_ : gcd a 0 ∣ ↑normalize (a * 0)) = ↑normalize (a * 0)
⊢ ↑normalize (gcd a 0) = ↑normalize a
[PROOFSTEP]
exact normalize_eq_normalize (gcd_dvd_left _ _) (dvd_gcd (dvd_refl a) (dvd_zero a))
[GOAL]
case neg
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
normalize_gcd : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
src✝ : NormalizationMonoid α := inferInstance
a : α
a0✝ : ¬a = 0
a0 : ¬↑normalize a = 0
h : gcd a 0 * Classical.choose (_ : gcd a 0 ∣ ↑normalize (a * 0)) = ↑normalize (a * 0)
gcd0 : gcd a 0 = ↑normalize a
⊢ Classical.choose (_ : gcd a 0 ∣ ↑normalize (a * 0)) = 0
[PROOFSTEP]
rw [← gcd0] at a0 
[GOAL]
case neg
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
normalize_gcd : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
src✝ : NormalizationMonoid α := inferInstance
a : α
a0✝ : ¬a = 0
a0 : ¬gcd a 0 = 0
h : gcd a 0 * Classical.choose (_ : gcd a 0 ∣ ↑normalize (a * 0)) = ↑normalize (a * 0)
gcd0 : gcd a 0 = ↑normalize a
⊢ Classical.choose (_ : gcd a 0 ∣ ↑normalize (a * 0)) = 0
[PROOFSTEP]
apply Or.resolve_left (mul_eq_zero.1 _) a0
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
normalize_gcd : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
src✝ : NormalizationMonoid α := inferInstance
a : α
a0✝ : ¬a = 0
a0 : ¬gcd a 0 = 0
h : gcd a 0 * Classical.choose (_ : gcd a 0 ∣ ↑normalize (a * 0)) = ↑normalize (a * 0)
gcd0 : gcd a 0 = ↑normalize a
⊢ gcd a 0 * Classical.choose (_ : gcd a 0 ∣ ↑normalize (a * 0)) = 0
[PROOFSTEP]
rw [h, mul_zero, normalize_zero]
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
normalize_gcd : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
src✝ : NormalizationMonoid α := inferInstance
a b : α
⊢ ↑normalize (lcm a b) = lcm a b
[PROOFSTEP]
dsimp [normalize]
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
normalize_gcd : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
src✝ : NormalizationMonoid α := inferInstance
a b : α
⊢ (if a = 0 then 0 else Classical.choose (_ : gcd a b ∣ a * b * ↑(normUnit (a * b)))) *
      ↑(normUnit (if a = 0 then 0 else Classical.choose (_ : gcd a b ∣ a * b * ↑(normUnit (a * b))))) =
    if a = 0 then 0 else Classical.choose (_ : gcd a b ∣ a * b * ↑(normUnit (a * b)))
[PROOFSTEP]
split_ifs with a0
[GOAL]
case pos
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
normalize_gcd : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
src✝ : NormalizationMonoid α := inferInstance
a b : α
a0 : a = 0
⊢ 0 * ↑(normUnit 0) = 0
[PROOFSTEP]
exact @normalize_zero α _ _
[GOAL]
case neg
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
normalize_gcd : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
src✝ : NormalizationMonoid α := inferInstance
a b : α
a0 : ¬a = 0
⊢ Classical.choose (_ : gcd a b ∣ a * b * ↑(normUnit (a * b))) *
      ↑(normUnit (Classical.choose (_ : gcd a b ∣ a * b * ↑(normUnit (a * b))))) =
    Classical.choose (_ : gcd a b ∣ a * b * ↑(normUnit (a * b)))
[PROOFSTEP]
have := (Classical.choose_spec (dvd_normalize_iff.2 ((gcd_dvd_left a b).trans (Dvd.intro b rfl)))).symm
[GOAL]
case neg
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
normalize_gcd : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
src✝ : NormalizationMonoid α := inferInstance
a b : α
a0 : ¬a = 0
this : gcd a b * Classical.choose (_ : gcd a b ∣ ↑normalize (a * b)) = ↑normalize (a * b)
⊢ Classical.choose (_ : gcd a b ∣ a * b * ↑(normUnit (a * b))) *
      ↑(normUnit (Classical.choose (_ : gcd a b ∣ a * b * ↑(normUnit (a * b))))) =
    Classical.choose (_ : gcd a b ∣ a * b * ↑(normUnit (a * b)))
[PROOFSTEP]
set l := Classical.choose (dvd_normalize_iff.2 ((gcd_dvd_left a b).trans (Dvd.intro b rfl)))
[GOAL]
case neg
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
normalize_gcd : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
src✝ : NormalizationMonoid α := inferInstance
a b : α
a0 : ¬a = 0
l : α := Classical.choose (_ : gcd a b ∣ ↑normalize (a * b))
this : gcd a b * l = ↑normalize (a * b)
⊢ l * ↑(normUnit l) = l
[PROOFSTEP]
obtain rfl | hb :=
  eq_or_ne b
    0
      -- Porting note: using `simp only` causes the propositions inside `Classical.choose` to
              -- differ, so `set` is unable to produce `l = 0` inside `this`. See
              -- https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/
              -- Classical.2Echoose/near/317491179
[GOAL]
case neg.inl
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
normalize_gcd : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
src✝ : NormalizationMonoid α := inferInstance
a : α
a0 : ¬a = 0
l : α := Classical.choose (_ : gcd a 0 ∣ ↑normalize (a * 0))
this : gcd a 0 * l = ↑normalize (a * 0)
⊢ l * ↑(normUnit l) = l
[PROOFSTEP]
rw [mul_zero a, normalize_zero, mul_eq_zero] at this 
[GOAL]
case neg.inl
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
normalize_gcd : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
src✝ : NormalizationMonoid α := inferInstance
a : α
a0 : ¬a = 0
l : α := Classical.choose (_ : gcd a 0 ∣ ↑normalize (a * 0))
this : gcd a 0 = 0 ∨ l = 0
⊢ l * ↑(normUnit l) = l
[PROOFSTEP]
obtain ha | hl := this
[GOAL]
case neg.inl.inl
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
normalize_gcd : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
src✝ : NormalizationMonoid α := inferInstance
a : α
a0 : ¬a = 0
l : α := Classical.choose (_ : gcd a 0 ∣ ↑normalize (a * 0))
ha : gcd a 0 = 0
⊢ l * ↑(normUnit l) = l
[PROOFSTEP]
apply (a0 _).elim
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
normalize_gcd : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
src✝ : NormalizationMonoid α := inferInstance
a : α
a0 : ¬a = 0
l : α := Classical.choose (_ : gcd a 0 ∣ ↑normalize (a * 0))
ha : gcd a 0 = 0
⊢ a = 0
[PROOFSTEP]
rw [← zero_dvd_iff, ← ha]
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
normalize_gcd : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
src✝ : NormalizationMonoid α := inferInstance
a : α
a0 : ¬a = 0
l : α := Classical.choose (_ : gcd a 0 ∣ ↑normalize (a * 0))
ha : gcd a 0 = 0
⊢ gcd a 0 ∣ a
[PROOFSTEP]
exact gcd_dvd_left _ _
[GOAL]
case neg.inl.inr
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
normalize_gcd : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
src✝ : NormalizationMonoid α := inferInstance
a : α
a0 : ¬a = 0
l : α := Classical.choose (_ : gcd a 0 ∣ ↑normalize (a * 0))
hl : l = 0
⊢ l * ↑(normUnit l) = l
[PROOFSTEP]
rw [hl, zero_mul]
[GOAL]
case neg.inr
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
normalize_gcd : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
src✝ : NormalizationMonoid α := inferInstance
a b : α
a0 : ¬a = 0
l : α := Classical.choose (_ : gcd a b ∣ ↑normalize (a * b))
this : gcd a b * l = ↑normalize (a * b)
hb : b ≠ 0
⊢ l * ↑(normUnit l) = l
[PROOFSTEP]
have h1 : gcd a b ≠ 0 := by
  have hab : a * b ≠ 0 := mul_ne_zero a0 hb
  contrapose! hab
  rw [← normalize_eq_zero, ← this, hab, zero_mul]
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
normalize_gcd : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
src✝ : NormalizationMonoid α := inferInstance
a b : α
a0 : ¬a = 0
l : α := Classical.choose (_ : gcd a b ∣ ↑normalize (a * b))
this : gcd a b * l = ↑normalize (a * b)
hb : b ≠ 0
⊢ gcd a b ≠ 0
[PROOFSTEP]
have hab : a * b ≠ 0 := mul_ne_zero a0 hb
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
normalize_gcd : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
src✝ : NormalizationMonoid α := inferInstance
a b : α
a0 : ¬a = 0
l : α := Classical.choose (_ : gcd a b ∣ ↑normalize (a * b))
this : gcd a b * l = ↑normalize (a * b)
hb : b ≠ 0
hab : a * b ≠ 0
⊢ gcd a b ≠ 0
[PROOFSTEP]
contrapose! hab
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
normalize_gcd : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
src✝ : NormalizationMonoid α := inferInstance
a b : α
a0 : ¬a = 0
l : α := Classical.choose (_ : gcd a b ∣ ↑normalize (a * b))
this : gcd a b * l = ↑normalize (a * b)
hb : b ≠ 0
hab : gcd a b = 0
⊢ a * b = 0
[PROOFSTEP]
rw [← normalize_eq_zero, ← this, hab, zero_mul]
[GOAL]
case neg.inr
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
normalize_gcd : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
src✝ : NormalizationMonoid α := inferInstance
a b : α
a0 : ¬a = 0
l : α := Classical.choose (_ : gcd a b ∣ ↑normalize (a * b))
this : gcd a b * l = ↑normalize (a * b)
hb : b ≠ 0
h1 : gcd a b ≠ 0
⊢ l * ↑(normUnit l) = l
[PROOFSTEP]
have h2 : normalize (gcd a b * l) = gcd a b * l := by rw [this, normalize_idem]
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
normalize_gcd : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
src✝ : NormalizationMonoid α := inferInstance
a b : α
a0 : ¬a = 0
l : α := Classical.choose (_ : gcd a b ∣ ↑normalize (a * b))
this : gcd a b * l = ↑normalize (a * b)
hb : b ≠ 0
h1 : gcd a b ≠ 0
⊢ ↑normalize (gcd a b * l) = gcd a b * l
[PROOFSTEP]
rw [this, normalize_idem]
[GOAL]
case neg.inr
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
normalize_gcd : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
src✝ : NormalizationMonoid α := inferInstance
a b : α
a0 : ¬a = 0
l : α := Classical.choose (_ : gcd a b ∣ ↑normalize (a * b))
this : gcd a b * l = ↑normalize (a * b)
hb : b ≠ 0
h1 : gcd a b ≠ 0
h2 : ↑normalize (gcd a b * l) = gcd a b * l
⊢ l * ↑(normUnit l) = l
[PROOFSTEP]
rw [← normalize_gcd] at this 
[GOAL]
case neg.inr
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
gcd : α → α → α
gcd_dvd_left : ∀ (a b : α), gcd a b ∣ a
gcd_dvd_right : ∀ (a b : α), gcd a b ∣ b
dvd_gcd : ∀ {a b c : α}, a ∣ c → a ∣ b → a ∣ gcd c b
normalize_gcd : ∀ (a b : α), ↑normalize (gcd a b) = gcd a b
src✝ : NormalizationMonoid α := inferInstance
a b : α
a0 : ¬a = 0
l : α := Classical.choose (_ : gcd a b ∣ ↑normalize (a * b))
this : ↑normalize (gcd a b) * l = ↑normalize (a * b)
hb : b ≠ 0
h1 : gcd a b ≠ 0
h2 : ↑normalize (gcd a b * l) = gcd a b * l
⊢ l * ↑(normUnit l) = l
[PROOFSTEP]
rwa [normalize.map_mul, normalize_gcd, mul_right_inj' h1] at h2 
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b : α
⊢ (fun a b => if a = 0 then b else if b = 0 then a else Classical.choose (_ : lcm a b ∣ a * b)) a b ∣ a
[PROOFSTEP]
dsimp only
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b : α
⊢ (if a = 0 then b else if b = 0 then a else Classical.choose (_ : lcm a b ∣ a * b)) ∣ a
[PROOFSTEP]
split_ifs with h h_1
[GOAL]
case pos
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b : α
h : a = 0
⊢ b ∣ a
[PROOFSTEP]
rw [h]
[GOAL]
case pos
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b : α
h : a = 0
⊢ b ∣ 0
[PROOFSTEP]
apply dvd_zero
[GOAL]
case pos
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b : α
h : ¬a = 0
h_1 : b = 0
⊢ a ∣ a
[PROOFSTEP]
exact dvd_rfl
[GOAL]
case neg
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b : α
h : ¬a = 0
h_1 : ¬b = 0
⊢ Classical.choose (_ : lcm a b ∣ a * b) ∣ a
[PROOFSTEP]
have h0 : lcm a b ≠ 0 := by
  intro con
  have h := lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
  rw [con, zero_dvd_iff, mul_eq_zero] at h 
  cases h
  · exact absurd ‹a = 0› h
  · exact absurd ‹b = 0› h_1
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b : α
h : ¬a = 0
h_1 : ¬b = 0
⊢ lcm a b ≠ 0
[PROOFSTEP]
intro con
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b : α
h : ¬a = 0
h_1 : ¬b = 0
con : lcm a b = 0
⊢ False
[PROOFSTEP]
have h := lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b : α
h✝ : ¬a = 0
h_1 : ¬b = 0
con : lcm a b = 0
h : lcm a b ∣ a * b
⊢ False
[PROOFSTEP]
rw [con, zero_dvd_iff, mul_eq_zero] at h 
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b : α
h✝ : ¬a = 0
h_1 : ¬b = 0
con : lcm a b = 0
h : a = 0 ∨ b = 0
⊢ False
[PROOFSTEP]
cases h
[GOAL]
case inl
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b : α
h : ¬a = 0
h_1 : ¬b = 0
con : lcm a b = 0
h✝ : a = 0
⊢ False
[PROOFSTEP]
exact absurd ‹a = 0› h
[GOAL]
case inr
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b : α
h : ¬a = 0
h_1 : ¬b = 0
con : lcm a b = 0
h✝ : b = 0
⊢ False
[PROOFSTEP]
exact absurd ‹b = 0› h_1
[GOAL]
case neg
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b : α
h : ¬a = 0
h_1 : ¬b = 0
h0 : lcm a b ≠ 0
⊢ Classical.choose (_ : lcm a b ∣ a * b) ∣ a
[PROOFSTEP]
rw [← mul_dvd_mul_iff_left h0, ← Classical.choose_spec (exists_gcd a b), mul_comm, mul_dvd_mul_iff_right h]
[GOAL]
case neg
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b : α
h : ¬a = 0
h_1 : ¬b = 0
h0 : lcm a b ≠ 0
⊢ b ∣ lcm a b
[PROOFSTEP]
apply dvd_lcm_right
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b : α
⊢ (fun a b => if a = 0 then b else if b = 0 then a else Classical.choose (_ : lcm a b ∣ a * b)) a b ∣ b
[PROOFSTEP]
dsimp only
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b : α
⊢ (if a = 0 then b else if b = 0 then a else Classical.choose (_ : lcm a b ∣ a * b)) ∣ b
[PROOFSTEP]
split_ifs with h h_1
[GOAL]
case pos
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b : α
h : a = 0
⊢ b ∣ b
[PROOFSTEP]
exact dvd_rfl
[GOAL]
case pos
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b : α
h : ¬a = 0
h_1 : b = 0
⊢ a ∣ b
[PROOFSTEP]
rw [h_1]
[GOAL]
case pos
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b : α
h : ¬a = 0
h_1 : b = 0
⊢ a ∣ 0
[PROOFSTEP]
apply dvd_zero
[GOAL]
case neg
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b : α
h : ¬a = 0
h_1 : ¬b = 0
⊢ Classical.choose (_ : lcm a b ∣ a * b) ∣ b
[PROOFSTEP]
have h0 : lcm a b ≠ 0 := by
  intro con
  have h := lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
  rw [con, zero_dvd_iff, mul_eq_zero] at h 
  cases h
  · exact absurd ‹a = 0› h
  · exact absurd ‹b = 0› h_1
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b : α
h : ¬a = 0
h_1 : ¬b = 0
⊢ lcm a b ≠ 0
[PROOFSTEP]
intro con
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b : α
h : ¬a = 0
h_1 : ¬b = 0
con : lcm a b = 0
⊢ False
[PROOFSTEP]
have h := lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b : α
h✝ : ¬a = 0
h_1 : ¬b = 0
con : lcm a b = 0
h : lcm a b ∣ a * b
⊢ False
[PROOFSTEP]
rw [con, zero_dvd_iff, mul_eq_zero] at h 
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b : α
h✝ : ¬a = 0
h_1 : ¬b = 0
con : lcm a b = 0
h : a = 0 ∨ b = 0
⊢ False
[PROOFSTEP]
cases h
[GOAL]
case inl
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b : α
h : ¬a = 0
h_1 : ¬b = 0
con : lcm a b = 0
h✝ : a = 0
⊢ False
[PROOFSTEP]
exact absurd ‹a = 0› h
[GOAL]
case inr
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b : α
h : ¬a = 0
h_1 : ¬b = 0
con : lcm a b = 0
h✝ : b = 0
⊢ False
[PROOFSTEP]
exact absurd ‹b = 0› h_1
[GOAL]
case neg
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b : α
h : ¬a = 0
h_1 : ¬b = 0
h0 : lcm a b ≠ 0
⊢ Classical.choose (_ : lcm a b ∣ a * b) ∣ b
[PROOFSTEP]
rw [← mul_dvd_mul_iff_left h0, ← Classical.choose_spec (exists_gcd a b), mul_dvd_mul_iff_right h_1]
[GOAL]
case neg
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b : α
h : ¬a = 0
h_1 : ¬b = 0
h0 : lcm a b ≠ 0
⊢ a ∣ lcm a b
[PROOFSTEP]
apply dvd_lcm_left
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b c : α
ac : a ∣ c
ab : a ∣ b
⊢ a ∣ (fun a b => if a = 0 then b else if b = 0 then a else Classical.choose (_ : lcm a b ∣ a * b)) c b
[PROOFSTEP]
dsimp only
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b c : α
ac : a ∣ c
ab : a ∣ b
⊢ a ∣ if c = 0 then b else if b = 0 then c else Classical.choose (_ : lcm c b ∣ c * b)
[PROOFSTEP]
split_ifs with h h_1
[GOAL]
case pos
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b c : α
ac : a ∣ c
ab : a ∣ b
h : c = 0
⊢ a ∣ b
[PROOFSTEP]
exact ab
[GOAL]
case pos
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b c : α
ac : a ∣ c
ab : a ∣ b
h : ¬c = 0
h_1 : b = 0
⊢ a ∣ c
[PROOFSTEP]
exact ac
[GOAL]
case neg
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b c : α
ac : a ∣ c
ab : a ∣ b
h : ¬c = 0
h_1 : ¬b = 0
⊢ a ∣ Classical.choose (_ : lcm c b ∣ c * b)
[PROOFSTEP]
have h0 : lcm c b ≠ 0 := by
  intro con
  have h := lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left c rfl)
  rw [con, zero_dvd_iff, mul_eq_zero] at h 
  cases h
  · exact absurd ‹c = 0› h
  · exact absurd ‹b = 0› h_1
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b c : α
ac : a ∣ c
ab : a ∣ b
h : ¬c = 0
h_1 : ¬b = 0
⊢ lcm c b ≠ 0
[PROOFSTEP]
intro con
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b c : α
ac : a ∣ c
ab : a ∣ b
h : ¬c = 0
h_1 : ¬b = 0
con : lcm c b = 0
⊢ False
[PROOFSTEP]
have h := lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left c rfl)
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b c : α
ac : a ∣ c
ab : a ∣ b
h✝ : ¬c = 0
h_1 : ¬b = 0
con : lcm c b = 0
h : lcm c b ∣ c * b
⊢ False
[PROOFSTEP]
rw [con, zero_dvd_iff, mul_eq_zero] at h 
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b c : α
ac : a ∣ c
ab : a ∣ b
h✝ : ¬c = 0
h_1 : ¬b = 0
con : lcm c b = 0
h : c = 0 ∨ b = 0
⊢ False
[PROOFSTEP]
cases h
[GOAL]
case inl
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b c : α
ac : a ∣ c
ab : a ∣ b
h : ¬c = 0
h_1 : ¬b = 0
con : lcm c b = 0
h✝ : c = 0
⊢ False
[PROOFSTEP]
exact absurd ‹c = 0› h
[GOAL]
case inr
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b c : α
ac : a ∣ c
ab : a ∣ b
h : ¬c = 0
h_1 : ¬b = 0
con : lcm c b = 0
h✝ : b = 0
⊢ False
[PROOFSTEP]
exact absurd ‹b = 0› h_1
[GOAL]
case neg
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b c : α
ac : a ∣ c
ab : a ∣ b
h : ¬c = 0
h_1 : ¬b = 0
h0 : lcm c b ≠ 0
⊢ a ∣ Classical.choose (_ : lcm c b ∣ c * b)
[PROOFSTEP]
rw [← mul_dvd_mul_iff_left h0, ← Classical.choose_spec (exists_gcd c b)]
[GOAL]
case neg
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b c : α
ac : a ∣ c
ab : a ∣ b
h : ¬c = 0
h_1 : ¬b = 0
h0 : lcm c b ≠ 0
⊢ lcm c b * a ∣ c * b
[PROOFSTEP]
rcases ab with ⟨d, rfl⟩
[GOAL]
case neg.intro
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a c : α
ac : a ∣ c
h : ¬c = 0
d : α
h_1 : ¬a * d = 0
h0 : lcm c (a * d) ≠ 0
⊢ lcm c (a * d) * a ∣ c * (a * d)
[PROOFSTEP]
rw [mul_eq_zero] at ‹a * d ≠ 0› 
[GOAL]
case neg.intro
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a c : α
ac : a ∣ c
h : ¬c = 0
d : α
h_1 : ¬(a = 0 ∨ d = 0)
h0 : lcm c (a * d) ≠ 0
⊢ lcm c (a * d) * a ∣ c * (a * d)
[PROOFSTEP]
push_neg at h_1 
[GOAL]
case neg.intro
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a c : α
ac : a ∣ c
h : ¬c = 0
d : α
h0 : lcm c (a * d) ≠ 0
h_1 : a ≠ 0 ∧ d ≠ 0
⊢ lcm c (a * d) * a ∣ c * (a * d)
[PROOFSTEP]
rw [mul_comm a, ← mul_assoc, mul_dvd_mul_iff_right h_1.1]
[GOAL]
case neg.intro
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a c : α
ac : a ∣ c
h : ¬c = 0
d : α
h0 : lcm c (a * d) ≠ 0
h_1 : a ≠ 0 ∧ d ≠ 0
⊢ lcm c (d * a) ∣ c * d
[PROOFSTEP]
apply lcm_dvd (Dvd.intro d rfl)
[GOAL]
case neg.intro
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a c : α
ac : a ∣ c
h : ¬c = 0
d : α
h0 : lcm c (a * d) ≠ 0
h_1 : a ≠ 0 ∧ d ≠ 0
⊢ d * a ∣ c * d
[PROOFSTEP]
rw [mul_comm, mul_dvd_mul_iff_right h_1.2]
[GOAL]
case neg.intro
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a c : α
ac : a ∣ c
h : ¬c = 0
d : α
h0 : lcm c (a * d) ≠ 0
h_1 : a ≠ 0 ∧ d ≠ 0
⊢ a ∣ c
[PROOFSTEP]
apply ac
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b : α
⊢ Associated
    ((fun a b => if a = 0 then b else if b = 0 then a else Classical.choose (_ : lcm a b ∣ a * b)) a b * lcm a b)
    (a * b)
[PROOFSTEP]
dsimp only
[GOAL]
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b : α
⊢ Associated ((if a = 0 then b else if b = 0 then a else Classical.choose (_ : lcm a b ∣ a * b)) * lcm a b) (a * b)
[PROOFSTEP]
split_ifs with h h_1
[GOAL]
case pos
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b : α
h : a = 0
⊢ Associated (b * lcm a b) (a * b)
[PROOFSTEP]
rw [h, eq_zero_of_zero_dvd (dvd_lcm_left _ _), mul_zero, zero_mul]
[GOAL]
case pos
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b : α
h : ¬a = 0
h_1 : b = 0
⊢ Associated (a * lcm a b) (a * b)
[PROOFSTEP]
rw [h_1, eq_zero_of_zero_dvd (dvd_lcm_right _ _), mul_zero]
[GOAL]
case neg
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
exists_gcd : ∀ (a b : α), lcm a b ∣ a * b := fun a b => lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
a b : α
h : ¬a = 0
h_1 : ¬b = 0
⊢ Associated (Classical.choose (_ : lcm a b ∣ a * b) * lcm a b) (a * b)
[PROOFSTEP]
rw [mul_comm, ← Classical.choose_spec (exists_gcd a b)]
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
⊢ (fun a b =>
        if a = 0 then ↑normalize b
        else if b = 0 then ↑normalize a else Classical.choose (_ : lcm a b ∣ ↑normalize (a * b)))
      a b ∣
    a
[PROOFSTEP]
dsimp only
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
⊢ (if a = 0 then ↑normalize b
    else if b = 0 then ↑normalize a else Classical.choose (_ : lcm a b ∣ ↑normalize (a * b))) ∣
    a
[PROOFSTEP]
split_ifs with h h_1
[GOAL]
case pos
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : a = 0
⊢ ↑normalize b ∣ a
[PROOFSTEP]
rw [h]
[GOAL]
case pos
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : a = 0
⊢ ↑normalize b ∣ 0
[PROOFSTEP]
apply dvd_zero
[GOAL]
case pos
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : ¬a = 0
h_1 : b = 0
⊢ ↑normalize a ∣ a
[PROOFSTEP]
exact (normalize_associated _).dvd
[GOAL]
case neg
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : ¬a = 0
h_1 : ¬b = 0
⊢ Classical.choose (_ : lcm a b ∣ ↑normalize (a * b)) ∣ a
[PROOFSTEP]
have h0 : lcm a b ≠ 0 := by
  intro con
  have h := lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
  rw [con, zero_dvd_iff, mul_eq_zero] at h 
  cases h
  · exact absurd ‹a = 0› h
  · exact absurd ‹b = 0› h_1
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : ¬a = 0
h_1 : ¬b = 0
⊢ lcm a b ≠ 0
[PROOFSTEP]
intro con
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : ¬a = 0
h_1 : ¬b = 0
con : lcm a b = 0
⊢ False
[PROOFSTEP]
have h := lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h✝ : ¬a = 0
h_1 : ¬b = 0
con : lcm a b = 0
h : lcm a b ∣ a * b
⊢ False
[PROOFSTEP]
rw [con, zero_dvd_iff, mul_eq_zero] at h 
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h✝ : ¬a = 0
h_1 : ¬b = 0
con : lcm a b = 0
h : a = 0 ∨ b = 0
⊢ False
[PROOFSTEP]
cases h
[GOAL]
case inl
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : ¬a = 0
h_1 : ¬b = 0
con : lcm a b = 0
h✝ : a = 0
⊢ False
[PROOFSTEP]
exact absurd ‹a = 0› h
[GOAL]
case inr
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : ¬a = 0
h_1 : ¬b = 0
con : lcm a b = 0
h✝ : b = 0
⊢ False
[PROOFSTEP]
exact absurd ‹b = 0› h_1
[GOAL]
case neg
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : ¬a = 0
h_1 : ¬b = 0
h0 : lcm a b ≠ 0
⊢ Classical.choose (_ : lcm a b ∣ ↑normalize (a * b)) ∣ a
[PROOFSTEP]
rw [← mul_dvd_mul_iff_left h0, ← Classical.choose_spec (exists_gcd a b), normalize_dvd_iff, mul_comm,
  mul_dvd_mul_iff_right h]
[GOAL]
case neg
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : ¬a = 0
h_1 : ¬b = 0
h0 : lcm a b ≠ 0
⊢ b ∣ lcm a b
[PROOFSTEP]
apply dvd_lcm_right
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
⊢ (fun a b =>
        if a = 0 then ↑normalize b
        else if b = 0 then ↑normalize a else Classical.choose (_ : lcm a b ∣ ↑normalize (a * b)))
      a b ∣
    b
[PROOFSTEP]
dsimp only
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
⊢ (if a = 0 then ↑normalize b
    else if b = 0 then ↑normalize a else Classical.choose (_ : lcm a b ∣ ↑normalize (a * b))) ∣
    b
[PROOFSTEP]
split_ifs with h h_1
[GOAL]
case pos
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : a = 0
⊢ ↑normalize b ∣ b
[PROOFSTEP]
exact (normalize_associated _).dvd
[GOAL]
case pos
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : ¬a = 0
h_1 : b = 0
⊢ ↑normalize a ∣ b
[PROOFSTEP]
rw [h_1]
[GOAL]
case pos
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : ¬a = 0
h_1 : b = 0
⊢ ↑normalize a ∣ 0
[PROOFSTEP]
apply dvd_zero
[GOAL]
case neg
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : ¬a = 0
h_1 : ¬b = 0
⊢ Classical.choose (_ : lcm a b ∣ ↑normalize (a * b)) ∣ b
[PROOFSTEP]
have h0 : lcm a b ≠ 0 := by
  intro con
  have h := lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
  rw [con, zero_dvd_iff, mul_eq_zero] at h 
  cases h
  · exact absurd ‹a = 0› h
  · exact absurd ‹b = 0› h_1
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : ¬a = 0
h_1 : ¬b = 0
⊢ lcm a b ≠ 0
[PROOFSTEP]
intro con
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : ¬a = 0
h_1 : ¬b = 0
con : lcm a b = 0
⊢ False
[PROOFSTEP]
have h := lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h✝ : ¬a = 0
h_1 : ¬b = 0
con : lcm a b = 0
h : lcm a b ∣ a * b
⊢ False
[PROOFSTEP]
rw [con, zero_dvd_iff, mul_eq_zero] at h 
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h✝ : ¬a = 0
h_1 : ¬b = 0
con : lcm a b = 0
h : a = 0 ∨ b = 0
⊢ False
[PROOFSTEP]
cases h
[GOAL]
case inl
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : ¬a = 0
h_1 : ¬b = 0
con : lcm a b = 0
h✝ : a = 0
⊢ False
[PROOFSTEP]
exact absurd ‹a = 0› h
[GOAL]
case inr
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : ¬a = 0
h_1 : ¬b = 0
con : lcm a b = 0
h✝ : b = 0
⊢ False
[PROOFSTEP]
exact absurd ‹b = 0› h_1
[GOAL]
case neg
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : ¬a = 0
h_1 : ¬b = 0
h0 : lcm a b ≠ 0
⊢ Classical.choose (_ : lcm a b ∣ ↑normalize (a * b)) ∣ b
[PROOFSTEP]
rw [← mul_dvd_mul_iff_left h0, ← Classical.choose_spec (exists_gcd a b), normalize_dvd_iff, mul_dvd_mul_iff_right h_1]
[GOAL]
case neg
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : ¬a = 0
h_1 : ¬b = 0
h0 : lcm a b ≠ 0
⊢ a ∣ lcm a b
[PROOFSTEP]
apply dvd_lcm_left
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b c : α
ac : a ∣ c
ab : a ∣ b
⊢ a ∣
    (fun a b =>
        if a = 0 then ↑normalize b
        else if b = 0 then ↑normalize a else Classical.choose (_ : lcm a b ∣ ↑normalize (a * b)))
      c b
[PROOFSTEP]
dsimp only
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b c : α
ac : a ∣ c
ab : a ∣ b
⊢ a ∣
    if c = 0 then ↑normalize b else if b = 0 then ↑normalize c else Classical.choose (_ : lcm c b ∣ ↑normalize (c * b))
[PROOFSTEP]
split_ifs with h h_1
[GOAL]
case pos
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b c : α
ac : a ∣ c
ab : a ∣ b
h : c = 0
⊢ a ∣ ↑normalize b
[PROOFSTEP]
apply dvd_normalize_iff.2 ab
[GOAL]
case pos
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b c : α
ac : a ∣ c
ab : a ∣ b
h : ¬c = 0
h_1 : b = 0
⊢ a ∣ ↑normalize c
[PROOFSTEP]
apply dvd_normalize_iff.2 ac
[GOAL]
case neg
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b c : α
ac : a ∣ c
ab : a ∣ b
h : ¬c = 0
h_1 : ¬b = 0
⊢ a ∣ Classical.choose (_ : lcm c b ∣ ↑normalize (c * b))
[PROOFSTEP]
have h0 : lcm c b ≠ 0 := by
  intro con
  have h := lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left c rfl)
  rw [con, zero_dvd_iff, mul_eq_zero] at h 
  cases h
  · exact absurd ‹c = 0› h
  · exact absurd ‹b = 0› h_1
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b c : α
ac : a ∣ c
ab : a ∣ b
h : ¬c = 0
h_1 : ¬b = 0
⊢ lcm c b ≠ 0
[PROOFSTEP]
intro con
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b c : α
ac : a ∣ c
ab : a ∣ b
h : ¬c = 0
h_1 : ¬b = 0
con : lcm c b = 0
⊢ False
[PROOFSTEP]
have h := lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left c rfl)
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b c : α
ac : a ∣ c
ab : a ∣ b
h✝ : ¬c = 0
h_1 : ¬b = 0
con : lcm c b = 0
h : lcm c b ∣ c * b
⊢ False
[PROOFSTEP]
rw [con, zero_dvd_iff, mul_eq_zero] at h 
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b c : α
ac : a ∣ c
ab : a ∣ b
h✝ : ¬c = 0
h_1 : ¬b = 0
con : lcm c b = 0
h : c = 0 ∨ b = 0
⊢ False
[PROOFSTEP]
cases h
[GOAL]
case inl
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b c : α
ac : a ∣ c
ab : a ∣ b
h : ¬c = 0
h_1 : ¬b = 0
con : lcm c b = 0
h✝ : c = 0
⊢ False
[PROOFSTEP]
exact absurd ‹c = 0› h
[GOAL]
case inr
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b c : α
ac : a ∣ c
ab : a ∣ b
h : ¬c = 0
h_1 : ¬b = 0
con : lcm c b = 0
h✝ : b = 0
⊢ False
[PROOFSTEP]
exact absurd ‹b = 0› h_1
[GOAL]
case neg
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b c : α
ac : a ∣ c
ab : a ∣ b
h : ¬c = 0
h_1 : ¬b = 0
h0 : lcm c b ≠ 0
⊢ a ∣ Classical.choose (_ : lcm c b ∣ ↑normalize (c * b))
[PROOFSTEP]
rw [← mul_dvd_mul_iff_left h0, ←
  Classical.choose_spec (dvd_normalize_iff.2 (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left c rfl))), dvd_normalize_iff]
[GOAL]
case neg
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b c : α
ac : a ∣ c
ab : a ∣ b
h : ¬c = 0
h_1 : ¬b = 0
h0 : lcm c b ≠ 0
⊢ lcm c b * a ∣ c * b
[PROOFSTEP]
rcases ab with ⟨d, rfl⟩
[GOAL]
case neg.intro
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a c : α
ac : a ∣ c
h : ¬c = 0
d : α
h_1 : ¬a * d = 0
h0 : lcm c (a * d) ≠ 0
⊢ lcm c (a * d) * a ∣ c * (a * d)
[PROOFSTEP]
rw [mul_eq_zero] at h_1 
[GOAL]
case neg.intro
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a c : α
ac : a ∣ c
h : ¬c = 0
d : α
h_1 : ¬(a = 0 ∨ d = 0)
h0 : lcm c (a * d) ≠ 0
⊢ lcm c (a * d) * a ∣ c * (a * d)
[PROOFSTEP]
push_neg at h_1 
[GOAL]
case neg.intro
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a c : α
ac : a ∣ c
h : ¬c = 0
d : α
h0 : lcm c (a * d) ≠ 0
h_1 : a ≠ 0 ∧ d ≠ 0
⊢ lcm c (a * d) * a ∣ c * (a * d)
[PROOFSTEP]
rw [mul_comm a, ← mul_assoc, mul_dvd_mul_iff_right h_1.1]
[GOAL]
case neg.intro
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a c : α
ac : a ∣ c
h : ¬c = 0
d : α
h0 : lcm c (a * d) ≠ 0
h_1 : a ≠ 0 ∧ d ≠ 0
⊢ lcm c (d * a) ∣ c * d
[PROOFSTEP]
apply lcm_dvd (Dvd.intro d rfl)
[GOAL]
case neg.intro
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a c : α
ac : a ∣ c
h : ¬c = 0
d : α
h0 : lcm c (a * d) ≠ 0
h_1 : a ≠ 0 ∧ d ≠ 0
⊢ d * a ∣ c * d
[PROOFSTEP]
rw [mul_comm, mul_dvd_mul_iff_right h_1.2]
[GOAL]
case neg.intro
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a c : α
ac : a ∣ c
h : ¬c = 0
d : α
h0 : lcm c (a * d) ≠ 0
h_1 : a ≠ 0 ∧ d ≠ 0
⊢ a ∣ c
[PROOFSTEP]
apply ac
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
⊢ Associated
    ((fun a b =>
          if a = 0 then ↑normalize b
          else if b = 0 then ↑normalize a else Classical.choose (_ : lcm a b ∣ ↑normalize (a * b)))
        a b *
      lcm a b)
    (a * b)
[PROOFSTEP]
dsimp only
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
⊢ Associated
    ((if a = 0 then ↑normalize b
      else if b = 0 then ↑normalize a else Classical.choose (_ : lcm a b ∣ ↑normalize (a * b))) *
      lcm a b)
    (a * b)
[PROOFSTEP]
split_ifs with h h_1
[GOAL]
case pos
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : a = 0
⊢ Associated (↑normalize b * lcm a b) (a * b)
[PROOFSTEP]
rw [h, eq_zero_of_zero_dvd (dvd_lcm_left _ _), mul_zero, zero_mul]
[GOAL]
case pos
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : ¬a = 0
h_1 : b = 0
⊢ Associated (↑normalize a * lcm a b) (a * b)
[PROOFSTEP]
rw [h_1, eq_zero_of_zero_dvd (dvd_lcm_right _ _), mul_zero, mul_zero]
[GOAL]
case neg
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : ¬a = 0
h_1 : ¬b = 0
⊢ Associated (Classical.choose (_ : lcm a b ∣ ↑normalize (a * b)) * lcm a b) (a * b)
[PROOFSTEP]
rw [mul_comm, ← Classical.choose_spec (exists_gcd a b)]
[GOAL]
case neg
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : ¬a = 0
h_1 : ¬b = 0
⊢ Associated (↑normalize (a * b)) (a * b)
[PROOFSTEP]
exact normalize_associated (a * b)
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
⊢ ↑normalize (gcd a b) = gcd a b
[PROOFSTEP]
dsimp [normalize]
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
⊢ (if a = 0 then b * ↑(normUnit b)
      else if b = 0 then a * ↑(normUnit a) else Classical.choose (_ : lcm a b ∣ a * b * ↑(normUnit (a * b)))) *
      ↑(normUnit
          (if a = 0 then b * ↑(normUnit b)
          else if b = 0 then a * ↑(normUnit a) else Classical.choose (_ : lcm a b ∣ a * b * ↑(normUnit (a * b))))) =
    if a = 0 then b * ↑(normUnit b)
    else if b = 0 then a * ↑(normUnit a) else Classical.choose (_ : lcm a b ∣ a * b * ↑(normUnit (a * b)))
[PROOFSTEP]
split_ifs with h h_1
[GOAL]
case pos
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : a = 0
⊢ b * ↑(normUnit b) * ↑(normUnit (b * ↑(normUnit b))) = b * ↑(normUnit b)
[PROOFSTEP]
apply normalize_idem
[GOAL]
case pos
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : ¬a = 0
h_1 : b = 0
⊢ a * ↑(normUnit a) * ↑(normUnit (a * ↑(normUnit a))) = a * ↑(normUnit a)
[PROOFSTEP]
apply normalize_idem
[GOAL]
case neg
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : ¬a = 0
h_1 : ¬b = 0
⊢ Classical.choose (_ : lcm a b ∣ a * b * ↑(normUnit (a * b))) *
      ↑(normUnit (Classical.choose (_ : lcm a b ∣ a * b * ↑(normUnit (a * b))))) =
    Classical.choose (_ : lcm a b ∣ a * b * ↑(normUnit (a * b)))
[PROOFSTEP]
have h0 : lcm a b ≠ 0 := by
  intro con
  have h := lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
  rw [con, zero_dvd_iff, mul_eq_zero] at h 
  cases h
  · exact absurd ‹a = 0› h
  · exact absurd ‹b = 0› h_1
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : ¬a = 0
h_1 : ¬b = 0
⊢ lcm a b ≠ 0
[PROOFSTEP]
intro con
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : ¬a = 0
h_1 : ¬b = 0
con : lcm a b = 0
⊢ False
[PROOFSTEP]
have h := lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl)
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h✝ : ¬a = 0
h_1 : ¬b = 0
con : lcm a b = 0
h : lcm a b ∣ a * b
⊢ False
[PROOFSTEP]
rw [con, zero_dvd_iff, mul_eq_zero] at h 
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h✝ : ¬a = 0
h_1 : ¬b = 0
con : lcm a b = 0
h : a = 0 ∨ b = 0
⊢ False
[PROOFSTEP]
cases h
[GOAL]
case inl
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : ¬a = 0
h_1 : ¬b = 0
con : lcm a b = 0
h✝ : a = 0
⊢ False
[PROOFSTEP]
exact absurd ‹a = 0› h
[GOAL]
case inr
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : ¬a = 0
h_1 : ¬b = 0
con : lcm a b = 0
h✝ : b = 0
⊢ False
[PROOFSTEP]
exact absurd ‹b = 0› h_1
[GOAL]
case neg
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : ¬a = 0
h_1 : ¬b = 0
h0 : lcm a b ≠ 0
⊢ Classical.choose (_ : lcm a b ∣ a * b * ↑(normUnit (a * b))) *
      ↑(normUnit (Classical.choose (_ : lcm a b ∣ a * b * ↑(normUnit (a * b))))) =
    Classical.choose (_ : lcm a b ∣ a * b * ↑(normUnit (a * b)))
[PROOFSTEP]
apply mul_left_cancel₀ h0
[GOAL]
case neg
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : ¬a = 0
h_1 : ¬b = 0
h0 : lcm a b ≠ 0
⊢ lcm a b *
      (Classical.choose (_ : lcm a b ∣ a * b * ↑(normUnit (a * b))) *
        ↑(normUnit (Classical.choose (_ : lcm a b ∣ a * b * ↑(normUnit (a * b)))))) =
    lcm a b * Classical.choose (_ : lcm a b ∣ a * b * ↑(normUnit (a * b)))
[PROOFSTEP]
refine' _root_.trans _ (Classical.choose_spec (exists_gcd a b))
[GOAL]
case neg
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : ¬a = 0
h_1 : ¬b = 0
h0 : lcm a b ≠ 0
⊢ lcm a b *
      (Classical.choose (_ : lcm a b ∣ a * b * ↑(normUnit (a * b))) *
        ↑(normUnit (Classical.choose (_ : lcm a b ∣ a * b * ↑(normUnit (a * b)))))) =
    ↑normalize (a * b)
[PROOFSTEP]
conv_lhs =>
  congr
  rw [← normalize_lcm a b]
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : ¬a = 0
h_1 : ¬b = 0
h0 : lcm a b ≠ 0
| lcm a b *
    (Classical.choose (_ : lcm a b ∣ a * b * ↑(normUnit (a * b))) *
      ↑(normUnit (Classical.choose (_ : lcm a b ∣ a * b * ↑(normUnit (a * b))))))
[PROOFSTEP]
  congr
  rw [← normalize_lcm a b]
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : ¬a = 0
h_1 : ¬b = 0
h0 : lcm a b ≠ 0
| lcm a b *
    (Classical.choose (_ : lcm a b ∣ a * b * ↑(normUnit (a * b))) *
      ↑(normUnit (Classical.choose (_ : lcm a b ∣ a * b * ↑(normUnit (a * b))))))
[PROOFSTEP]
  congr
  rw [← normalize_lcm a b]
[GOAL]
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : ¬a = 0
h_1 : ¬b = 0
h0 : lcm a b ≠ 0
| lcm a b *
    (Classical.choose (_ : lcm a b ∣ a * b * ↑(normUnit (a * b))) *
      ↑(normUnit (Classical.choose (_ : lcm a b ∣ a * b * ↑(normUnit (a * b))))))
[PROOFSTEP]
congr
[GOAL]
case a
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : ¬a = 0
h_1 : ¬b = 0
h0 : lcm a b ≠ 0
| lcm a b
case a
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : ¬a = 0
h_1 : ¬b = 0
h0 : lcm a b ≠ 0
| Classical.choose (_ : lcm a b ∣ a * b * ↑(normUnit (a * b))) *
    ↑(normUnit (Classical.choose (_ : lcm a b ∣ a * b * ↑(normUnit (a * b)))))
[PROOFSTEP]
rw [← normalize_lcm a b]
[GOAL]
case neg
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : DecidableEq α
lcm : α → α → α
dvd_lcm_left : ∀ (a b : α), a ∣ lcm a b
dvd_lcm_right : ∀ (a b : α), b ∣ lcm a b
lcm_dvd : ∀ {a b c : α}, c ∣ a → b ∣ a → lcm c b ∣ a
normalize_lcm : ∀ (a b : α), ↑normalize (lcm a b) = lcm a b
exists_gcd : ∀ (a b : α), lcm a b ∣ ↑normalize (a * b) :=
  fun a b => Iff.mpr dvd_normalize_iff (lcm_dvd (Dvd.intro b rfl) (Dvd.intro_left a rfl))
src✝ : NormalizationMonoid α := inferInstance
a b : α
h : ¬a = 0
h_1 : ¬b = 0
h0 : lcm a b ≠ 0
⊢ ↑normalize (lcm a b) *
      (Classical.choose (_ : lcm a b ∣ a * b * ↑(normUnit (a * b))) *
        ↑(normUnit (Classical.choose (_ : lcm a b ∣ a * b * ↑(normUnit (a * b)))))) =
    ↑normalize (a * b)
[PROOFSTEP]
erw [← normalize.map_mul, ← Classical.choose_spec (exists_gcd a b), normalize_idem]
[GOAL]
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
x y : G₀
x0 : x ≠ 0
y0 : y ≠ 0
⊢ ↑((fun x => if h : x = 0 then 1 else (Units.mk0 x h)⁻¹) (x * y)) =
    ↑((fun x => if h : x = 0 then 1 else (Units.mk0 x h)⁻¹) x * (fun x => if h : x = 0 then 1 else (Units.mk0 x h)⁻¹) y)
[PROOFSTEP]
dsimp only
[GOAL]
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
x y : G₀
x0 : x ≠ 0
y0 : y ≠ 0
⊢ ↑(if h : x * y = 0 then 1 else (Units.mk0 (x * y) h)⁻¹) =
    ↑((if h : x = 0 then 1 else (Units.mk0 x h)⁻¹) * if h : y = 0 then 1 else (Units.mk0 y h)⁻¹)
[PROOFSTEP]
split_ifs with h
[GOAL]
case pos
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
x y : G₀
x0 : x ≠ 0
y0 : y ≠ 0
h : x * y = 0
⊢ ↑1 = ↑((Units.mk0 x x0)⁻¹ * (Units.mk0 y y0)⁻¹)
[PROOFSTEP]
rw [mul_eq_zero] at h 
[GOAL]
case pos
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
x y : G₀
x0 : x ≠ 0
y0 : y ≠ 0
h : x = 0 ∨ y = 0
⊢ ↑1 = ↑((Units.mk0 x x0)⁻¹ * (Units.mk0 y y0)⁻¹)
[PROOFSTEP]
cases h
[GOAL]
case pos.inl
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
x y : G₀
x0 : x ≠ 0
y0 : y ≠ 0
h✝ : x = 0
⊢ ↑1 = ↑((Units.mk0 x x0)⁻¹ * (Units.mk0 y y0)⁻¹)
[PROOFSTEP]
exact absurd ‹x = 0› x0
[GOAL]
case pos.inr
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
x y : G₀
x0 : x ≠ 0
y0 : y ≠ 0
h✝ : y = 0
⊢ ↑1 = ↑((Units.mk0 x x0)⁻¹ * (Units.mk0 y y0)⁻¹)
[PROOFSTEP]
exact absurd ‹y = 0› y0
[GOAL]
case neg
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
x y : G₀
x0 : x ≠ 0
y0 : y ≠ 0
h : ¬x * y = 0
⊢ ↑(Units.mk0 (x * y) h)⁻¹ = ↑((Units.mk0 x x0)⁻¹ * (Units.mk0 y y0)⁻¹)
[PROOFSTEP]
rw [Units.mk0_mul, mul_inv_rev, mul_comm]
[GOAL]
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
u : G₀ˣ
⊢ (fun x => if h : x = 0 then 1 else (Units.mk0 x h)⁻¹) ↑u = u⁻¹
[PROOFSTEP]
dsimp only
[GOAL]
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
u : G₀ˣ
⊢ (if h : ↑u = 0 then 1 else (Units.mk0 (↑u) h)⁻¹) = u⁻¹
[PROOFSTEP]
rw [dif_neg (Units.ne_zero _), Units.mk0_val]
[GOAL]
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
a b : G₀
⊢ (fun a b => if a = 0 ∧ b = 0 then 0 else 1) a b ∣ a
[PROOFSTEP]
dsimp only
[GOAL]
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
a b : G₀
⊢ (if a = 0 ∧ b = 0 then 0 else 1) ∣ a
[PROOFSTEP]
split_ifs with h
[GOAL]
case pos
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
a b : G₀
h : a = 0 ∧ b = 0
⊢ 0 ∣ a
[PROOFSTEP]
rw [h.1]
[GOAL]
case neg
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
a b : G₀
h : ¬(a = 0 ∧ b = 0)
⊢ 1 ∣ a
[PROOFSTEP]
exact one_dvd _
[GOAL]
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
a b : G₀
⊢ (fun a b => if a = 0 ∧ b = 0 then 0 else 1) a b ∣ b
[PROOFSTEP]
dsimp only
[GOAL]
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
a b : G₀
⊢ (if a = 0 ∧ b = 0 then 0 else 1) ∣ b
[PROOFSTEP]
split_ifs with h
[GOAL]
case pos
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
a b : G₀
h : a = 0 ∧ b = 0
⊢ 0 ∣ b
[PROOFSTEP]
rw [h.2]
[GOAL]
case neg
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
a b : G₀
h : ¬(a = 0 ∧ b = 0)
⊢ 1 ∣ b
[PROOFSTEP]
exact one_dvd _
[GOAL]
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
a b c : G₀
hac : a ∣ c
hab : a ∣ b
⊢ a ∣ (fun a b => if a = 0 ∧ b = 0 then 0 else 1) c b
[PROOFSTEP]
dsimp only
[GOAL]
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
a b c : G₀
hac : a ∣ c
hab : a ∣ b
⊢ a ∣ if c = 0 ∧ b = 0 then 0 else 1
[PROOFSTEP]
split_ifs with h
[GOAL]
case pos
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
a b c : G₀
hac : a ∣ c
hab : a ∣ b
h : c = 0 ∧ b = 0
⊢ a ∣ 0
[PROOFSTEP]
apply dvd_zero
[GOAL]
case neg
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
a b c : G₀
hac : a ∣ c
hab : a ∣ b
h : ¬(c = 0 ∧ b = 0)
⊢ a ∣ 1
[PROOFSTEP]
rw [not_and_or] at h 
[GOAL]
case neg
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
a b c : G₀
hac : a ∣ c
hab : a ∣ b
h : ¬c = 0 ∨ ¬b = 0
⊢ a ∣ 1
[PROOFSTEP]
cases h
[GOAL]
case neg.inl
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
a b c : G₀
hac : a ∣ c
hab : a ∣ b
h✝ : ¬c = 0
⊢ a ∣ 1
[PROOFSTEP]
refine' isUnit_iff_dvd_one.mp (isUnit_of_dvd_unit _ (IsUnit.mk0 _ ‹c ≠ 0›))
[GOAL]
case neg.inl
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
a b c : G₀
hac : a ∣ c
hab : a ∣ b
h✝ : ¬c = 0
⊢ a ∣ c
[PROOFSTEP]
exact hac
[GOAL]
case neg.inr
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
a b c : G₀
hac : a ∣ c
hab : a ∣ b
h✝ : ¬b = 0
⊢ a ∣ 1
[PROOFSTEP]
refine' isUnit_iff_dvd_one.mp (isUnit_of_dvd_unit _ (IsUnit.mk0 _ ‹b ≠ 0›))
[GOAL]
case neg.inr
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
a b c : G₀
hac : a ∣ c
hab : a ∣ b
h✝ : ¬b = 0
⊢ a ∣ b
[PROOFSTEP]
exact hab
[GOAL]
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
a b : G₀
⊢ Associated ((fun a b => if a = 0 ∧ b = 0 then 0 else 1) a b * (fun a b => if a = 0 ∨ b = 0 then 0 else 1) a b) (a * b)
[PROOFSTEP]
by_cases ha : a = 0
[GOAL]
case pos
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
a b : G₀
ha : a = 0
⊢ Associated ((fun a b => if a = 0 ∧ b = 0 then 0 else 1) a b * (fun a b => if a = 0 ∨ b = 0 then 0 else 1) a b) (a * b)
[PROOFSTEP]
simp only [ha, true_and, true_or, ite_true, mul_zero, zero_mul]
[GOAL]
case pos
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
a b : G₀
ha : a = 0
⊢ Associated 0 0
[PROOFSTEP]
exact Associated.refl _
[GOAL]
case neg
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
a b : G₀
ha : ¬a = 0
⊢ Associated ((fun a b => if a = 0 ∧ b = 0 then 0 else 1) a b * (fun a b => if a = 0 ∨ b = 0 then 0 else 1) a b) (a * b)
[PROOFSTEP]
by_cases hb : b = 0
[GOAL]
case pos
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
a b : G₀
ha : ¬a = 0
hb : b = 0
⊢ Associated ((fun a b => if a = 0 ∧ b = 0 then 0 else 1) a b * (fun a b => if a = 0 ∨ b = 0 then 0 else 1) a b) (a * b)
[PROOFSTEP]
simp only [hb, and_true, or_true, ite_true, mul_zero]
[GOAL]
case pos
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
a b : G₀
ha : ¬a = 0
hb : b = 0
⊢ Associated 0 0
[PROOFSTEP]
exact
  Associated.refl
    _
      -- Porting note: need `dsimp only`
[GOAL]
case neg
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
a b : G₀
ha : ¬a = 0
hb : ¬b = 0
⊢ Associated ((fun a b => if a = 0 ∧ b = 0 then 0 else 1) a b * (fun a b => if a = 0 ∨ b = 0 then 0 else 1) a b) (a * b)
[PROOFSTEP]
dsimp only
[GOAL]
case neg
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
a b : G₀
ha : ¬a = 0
hb : ¬b = 0
⊢ Associated ((if a = 0 ∧ b = 0 then 0 else 1) * if a = 0 ∨ b = 0 then 0 else 1) (a * b)
[PROOFSTEP]
rw [if_neg (not_and_of_not_left _ ha), one_mul, if_neg (not_or_of_not ha hb)]
[GOAL]
case neg
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
a b : G₀
ha : ¬a = 0
hb : ¬b = 0
⊢ Associated 1 (a * b)
[PROOFSTEP]
exact (associated_one_iff_isUnit.mpr ((IsUnit.mk0 _ ha).mul (IsUnit.mk0 _ hb))).symm
[GOAL]
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
a b : G₀
h : a = 0 ∧ b = 0
⊢ ↑normalize (gcd a b) = gcd a b
[PROOFSTEP]
simp [if_pos h]
[GOAL]
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
a b : G₀
h : ¬(a = 0 ∧ b = 0)
⊢ ↑normalize (gcd a b) = gcd a b
[PROOFSTEP]
simp [if_neg h]
[GOAL]
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
a b : G₀
h : a = 0 ∨ b = 0
⊢ ↑normalize (lcm a b) = lcm a b
[PROOFSTEP]
simp [if_pos h]
[GOAL]
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
a b : G₀
h : ¬(a = 0 ∨ b = 0)
⊢ ↑normalize (lcm a b) = lcm a b
[PROOFSTEP]
simp [if_neg h]
[GOAL]
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
a : G₀
h0 : a ≠ 0
⊢ ↑(normUnit a) = a⁻¹
[PROOFSTEP]
simp [normUnit, h0]
[GOAL]
α : Type u_1
G₀ : Type u_2
inst✝¹ : CommGroupWithZero G₀
inst✝ : DecidableEq G₀
a : G₀
h0 : a ≠ 0
⊢ ↑normalize a = 1
[PROOFSTEP]
simp [normalize_apply, h0]
