l3lab/ntp-mathlib huggingface dataset:
theorem num_den_mk {q : ℚ} {n d : ℤ} (hd : d ≠ 0) (qdf : q = n /. d) :
    ∃ c : ℤ, n = c * q.num ∧ d = c * q.den := by
  obtain rfl | hn := eq_or_ne n 0
  · simp [qdf]
  have : q.num * d = n * ↑q.den := by
    refine' (divInt_eq_iff _ hd).mp _
    · 

Proof state:
case refine'_1
q : ℚ
n d : ℤ
hd : d ≠ 0
qdf : q = n /. d
hn : n ≠ 0
⊢ ↑q.den ≠ 0

Next tactic:
exact Int.coe_nat_ne_zero.mpr (Rat.den_nz _)
theorem num_den_mk {q : ℚ} {n d : ℤ} (hd : d ≠ 0) (qdf : q = n /. d) :
    ∃ c : ℤ, n = c * q.num ∧ d = c * q.den := by
  obtain rfl | hn := eq_or_ne n 0
  · simp [qdf]
  have : q.num * d = n * ↑q.den := by
    refine' (divInt_eq_iff _ hd).mp _
    · exact Int.coe_nat_ne_zero.mpr (Rat.den_nz _)
    · 

Proof state:
case refine'_2
q : ℚ
n d : ℤ
hd : d ≠ 0
qdf : q = n /. d
hn : n ≠ 0
⊢ q.num /. ↑q.den = n /. d

Next tactic:
rwa [num_den]
theorem num_den_mk {q : ℚ} {n d : ℤ} (hd : d ≠ 0) (qdf : q = n /. d) :
    ∃ c : ℤ, n = c * q.num ∧ d = c * q.den := by
  obtain rfl | hn := eq_or_ne n 0
  · simp [qdf]
  have : q.num * d = n * ↑q.den := by
    refine' (divInt_eq_iff _ hd).mp _
    · exact Int.coe_nat_ne_zero.mpr (Rat.den_nz _)
    · rwa [num_den]
  

Proof state:
case inr
q : ℚ
n d : ℤ
hd : d ≠ 0
qdf : q = n /. d
hn : n ≠ 0
this : q.num * d = n * ↑q.den
⊢ ∃ c, n = c * q.num ∧ d = c * ↑q.den

Next tactic:
have hqdn : q.num ∣ n := by
    rw [qdf]
    exact Rat.num_dvd _ hd
theorem num_den_mk {q : ℚ} {n d : ℤ} (hd : d ≠ 0) (qdf : q = n /. d) :
    ∃ c : ℤ, n = c * q.num ∧ d = c * q.den := by
  obtain rfl | hn := eq_or_ne n 0
  · simp [qdf]
  have : q.num * d = n * ↑q.den := by
    refine' (divInt_eq_iff _ hd).mp _
    · exact Int.coe_nat_ne_zero.mpr (Rat.den_nz _)
    · rwa [num_den]
  have hqdn : q.num ∣ n := by
    

Proof state:
q : ℚ
n d : ℤ
hd : d ≠ 0
qdf : q = n /. d
hn : n ≠ 0
this : q.num * d = n * ↑q.den
⊢ q.num ∣ n

Next tactic:
rw [qdf]
theorem num_den_mk {q : ℚ} {n d : ℤ} (hd : d ≠ 0) (qdf : q = n /. d) :
    ∃ c : ℤ, n = c * q.num ∧ d = c * q.den := by
  obtain rfl | hn := eq_or_ne n 0
  · simp [qdf]
  have : q.num * d = n * ↑q.den := by
    refine' (divInt_eq_iff _ hd).mp _
    · exact Int.coe_nat_ne_zero.mpr (Rat.den_nz _)
    · rwa [num_den]
  have hqdn : q.num ∣ n := by
    rw [qdf]
    

Proof state:
q : ℚ
n d : ℤ
hd : d ≠ 0
qdf : q = n /. d
hn : n ≠ 0
this : q.num * d = n * ↑q.den
⊢ (n /. d).num ∣ n

Next tactic:
exact Rat.num_dvd _ hd
theorem num_den_mk {q : ℚ} {n d : ℤ} (hd : d ≠ 0) (qdf : q = n /. d) :
    ∃ c : ℤ, n = c * q.num ∧ d = c * q.den := by
  obtain rfl | hn := eq_or_ne n 0
  · simp [qdf]
  have : q.num * d = n * ↑q.den := by
    refine' (divInt_eq_iff _ hd).mp _
    · exact Int.coe_nat_ne_zero.mpr (Rat.den_nz _)
    · rwa [num_den]
  have hqdn : q.num ∣ n := by
    rw [qdf]
    exact Rat.num_dvd _ hd
  

Proof state:
case inr
q : ℚ
n d : ℤ
hd : d ≠ 0
qdf : q = n /. d
hn : n ≠ 0
this : q.num * d = n * ↑q.den
hqdn : q.num ∣ n
⊢ ∃ c, n = c * q.num ∧ d = c * ↑q.den

Next tactic:
refine' ⟨n / q.num, _, _⟩
theorem num_den_mk {q : ℚ} {n d : ℤ} (hd : d ≠ 0) (qdf : q = n /. d) :
    ∃ c : ℤ, n = c * q.num ∧ d = c * q.den := by
  obtain rfl | hn := eq_or_ne n 0
  · simp [qdf]
  have : q.num * d = n * ↑q.den := by
    refine' (divInt_eq_iff _ hd).mp _
    · exact Int.coe_nat_ne_zero.mpr (Rat.den_nz _)
    · rwa [num_den]
  have hqdn : q.num ∣ n := by
    rw [qdf]
    exact Rat.num_dvd _ hd
  refine' ⟨n / q.num, _, _⟩
  · 

Proof state:
case inr.refine'_1
q : ℚ
n d : ℤ
hd : d ≠ 0
qdf : q = n /. d
hn : n ≠ 0
this : q.num * d = n * ↑q.den
hqdn : q.num ∣ n
⊢ n = n / q.num * q.num

Next tactic:
rw [Int.ediv_mul_cancel hqdn]
theorem num_den_mk {q : ℚ} {n d : ℤ} (hd : d ≠ 0) (qdf : q = n /. d) :
    ∃ c : ℤ, n = c * q.num ∧ d = c * q.den := by
  obtain rfl | hn := eq_or_ne n 0
  · simp [qdf]
  have : q.num * d = n * ↑q.den := by
    refine' (divInt_eq_iff _ hd).mp _
    · exact Int.coe_nat_ne_zero.mpr (Rat.den_nz _)
    · rwa [num_den]
  have hqdn : q.num ∣ n := by
    rw [qdf]
    exact Rat.num_dvd _ hd
  refine' ⟨n / q.num, _, _⟩
  · rw [Int.ediv_mul_cancel hqdn]
  · 

Proof state:
case inr.refine'_2
q : ℚ
n d : ℤ
hd : d ≠ 0
qdf : q = n /. d
hn : n ≠ 0
this : q.num * d = n * ↑q.den
hqdn : q.num ∣ n
⊢ d = n / q.num * ↑q.den

Next tactic:
refine' Int.eq_mul_div_of_mul_eq_mul_of_dvd_left _ hqdn this
theorem num_den_mk {q : ℚ} {n d : ℤ} (hd : d ≠ 0) (qdf : q = n /. d) :
    ∃ c : ℤ, n = c * q.num ∧ d = c * q.den := by
  obtain rfl | hn := eq_or_ne n 0
  · simp [qdf]
  have : q.num * d = n * ↑q.den := by
    refine' (divInt_eq_iff _ hd).mp _
    · exact Int.coe_nat_ne_zero.mpr (Rat.den_nz _)
    · rwa [num_den]
  have hqdn : q.num ∣ n := by
    rw [qdf]
    exact Rat.num_dvd _ hd
  refine' ⟨n / q.num, _, _⟩
  · rw [Int.ediv_mul_cancel hqdn]
  · refine' Int.eq_mul_div_of_mul_eq_mul_of_dvd_left _ hqdn this
    

Proof state:
case inr.refine'_2
q : ℚ
n d : ℤ
hd : d ≠ 0
qdf : q = n /. d
hn : n ≠ 0
this : q.num * d = n * ↑q.den
hqdn : q.num ∣ n
⊢ q.num ≠ 0

Next tactic:
rw [qdf]
theorem num_den_mk {q : ℚ} {n d : ℤ} (hd : d ≠ 0) (qdf : q = n /. d) :
    ∃ c : ℤ, n = c * q.num ∧ d = c * q.den := by
  obtain rfl | hn := eq_or_ne n 0
  · simp [qdf]
  have : q.num * d = n * ↑q.den := by
    refine' (divInt_eq_iff _ hd).mp _
    · exact Int.coe_nat_ne_zero.mpr (Rat.den_nz _)
    · rwa [num_den]
  have hqdn : q.num ∣ n := by
    rw [qdf]
    exact Rat.num_dvd _ hd
  refine' ⟨n / q.num, _, _⟩
  · rw [Int.ediv_mul_cancel hqdn]
  · refine' Int.eq_mul_div_of_mul_eq_mul_of_dvd_left _ hqdn this
    rw [qdf]
    

Proof state:
case inr.refine'_2
q : ℚ
n d : ℤ
hd : d ≠ 0
qdf : q = n /. d
hn : n ≠ 0
this : q.num * d = n * ↑q.den
hqdn : q.num ∣ n
⊢ (n /. d).num ≠ 0

Next tactic:
exact Rat.num_ne_zero_of_ne_zero ((divInt_ne_zero hd).mpr hn)
theorem num_mk (n d : ℤ) : (n /. d).num = d.sign * n / n.gcd d := by
  

Proof state:
n d : ℤ
⊢ (n /. d).num = Int.sign d * n / ↑(Int.gcd n d)

Next tactic:
rcases d with ((_ | _) | _)
theorem num_mk (n d : ℤ) : (n /. d).num = d.sign * n / n.gcd d := by
  rcases d with ((_ | _) | _) <;>
  

Proof state:
case ofNat.zero
n : ℤ
⊢ (n /. Int.ofNat Nat.zero).num = Int.sign (Int.ofNat Nat.zero) * n / ↑(Int.gcd n (Int.ofNat Nat.zero))

Next tactic:
rw [← Int.div_eq_ediv_of_dvd]
theorem num_mk (n d : ℤ) : (n /. d).num = d.sign * n / n.gcd d := by
  rcases d with ((_ | _) | _) <;>
  

Proof state:
case ofNat.succ
n : ℤ
n✝ : ℕ
⊢ (n /. Int.ofNat (Nat.succ n✝)).num = Int.sign (Int.ofNat (Nat.succ n✝)) * n / ↑(Int.gcd n (Int.ofNat (Nat.succ n✝)))

Next tactic:
rw [← Int.div_eq_ediv_of_dvd]
theorem num_mk (n d : ℤ) : (n /. d).num = d.sign * n / n.gcd d := by
  rcases d with ((_ | _) | _) <;>
  

Proof state:
case negSucc
n : ℤ
a✝ : ℕ
⊢ (n /. Int.negSucc a✝).num = Int.sign (Int.negSucc a✝) * n / ↑(Int.gcd n (Int.negSucc a✝))

Next tactic:
rw [← Int.div_eq_ediv_of_dvd]
theorem num_mk (n d : ℤ) : (n /. d).num = d.sign * n / n.gcd d := by
  rcases d with ((_ | _) | _) <;>
  rw [← Int.div_eq_ediv_of_dvd] <;>
  

Proof state:
case ofNat.zero
n : ℤ
⊢ (n /. Int.ofNat Nat.zero).num = Int.div (Int.sign (Int.ofNat Nat.zero) * n) ↑(Int.gcd n (Int.ofNat Nat.zero))

Next tactic:
simp [divInt, mkRat, Rat.normalize, Nat.succPNat, Int.sign, Int.gcd, -Nat.cast_succ,
    Int.zero_ediv, Int.ofNat_dvd_left, Nat.gcd_dvd_left]
theorem num_mk (n d : ℤ) : (n /. d).num = d.sign * n / n.gcd d := by
  rcases d with ((_ | _) | _) <;>
  rw [← Int.div_eq_ediv_of_dvd] <;>
  

Proof state:
case ofNat.zero
n : ℤ
⊢ ↑(Int.gcd n (Int.ofNat Nat.zero)) ∣ Int.sign (Int.ofNat Nat.zero) * n

Next tactic:
simp [divInt, mkRat, Rat.normalize, Nat.succPNat, Int.sign, Int.gcd, -Nat.cast_succ,
    Int.zero_ediv, Int.ofNat_dvd_left, Nat.gcd_dvd_left]
theorem num_mk (n d : ℤ) : (n /. d).num = d.sign * n / n.gcd d := by
  rcases d with ((_ | _) | _) <;>
  rw [← Int.div_eq_ediv_of_dvd] <;>
  

Proof state:
case ofNat.succ
n : ℤ
n✝ : ℕ
⊢ (n /. Int.ofNat (Nat.succ n✝)).num =
    Int.div (Int.sign (Int.ofNat (Nat.succ n✝)) * n) ↑(Int.gcd n (Int.ofNat (Nat.succ n✝)))

Next tactic:
simp [divInt, mkRat, Rat.normalize, Nat.succPNat, Int.sign, Int.gcd, -Nat.cast_succ,
    Int.zero_ediv, Int.ofNat_dvd_left, Nat.gcd_dvd_left]
theorem num_mk (n d : ℤ) : (n /. d).num = d.sign * n / n.gcd d := by
  rcases d with ((_ | _) | _) <;>
  rw [← Int.div_eq_ediv_of_dvd] <;>
  

Proof state:
case ofNat.succ
n : ℤ
n✝ : ℕ
⊢ ↑(Int.gcd n (Int.ofNat (Nat.succ n✝))) ∣ Int.sign (Int.ofNat (Nat.succ n✝)) * n

Next tactic:
simp [divInt, mkRat, Rat.normalize, Nat.succPNat, Int.sign, Int.gcd, -Nat.cast_succ,
    Int.zero_ediv, Int.ofNat_dvd_left, Nat.gcd_dvd_left]
theorem num_mk (n d : ℤ) : (n /. d).num = d.sign * n / n.gcd d := by
  rcases d with ((_ | _) | _) <;>
  rw [← Int.div_eq_ediv_of_dvd] <;>
  

Proof state:
case negSucc
n : ℤ
a✝ : ℕ
⊢ (n /. Int.negSucc a✝).num = Int.div (Int.sign (Int.negSucc a✝) * n) ↑(Int.gcd n (Int.negSucc a✝))

Next tactic:
simp [divInt, mkRat, Rat.normalize, Nat.succPNat, Int.sign, Int.gcd, -Nat.cast_succ,
    Int.zero_ediv, Int.ofNat_dvd_left, Nat.gcd_dvd_left]
theorem num_mk (n d : ℤ) : (n /. d).num = d.sign * n / n.gcd d := by
  rcases d with ((_ | _) | _) <;>
  rw [← Int.div_eq_ediv_of_dvd] <;>
  

Proof state:
case negSucc
n : ℤ
a✝ : ℕ
⊢ ↑(Int.gcd n (Int.negSucc a✝)) ∣ Int.sign (Int.negSucc a✝) * n

Next tactic:
simp [divInt, mkRat, Rat.normalize, Nat.succPNat, Int.sign, Int.gcd, -Nat.cast_succ,
    Int.zero_ediv, Int.ofNat_dvd_left, Nat.gcd_dvd_left]
theorem den_mk (n d : ℤ) : (n /. d).den = if d = 0 then 1 else d.natAbs / n.gcd d := by
  

Proof state:
n d : ℤ
⊢ (n /. d).den = if d = 0 then 1 else Int.natAbs d / Int.gcd n d

Next tactic:
rcases d with ((_ | _) | _)
theorem den_mk (n d : ℤ) : (n /. d).den = if d = 0 then 1 else d.natAbs / n.gcd d := by
  rcases d with ((_ | _) | _) <;>
    

Proof state:
case ofNat.zero
n : ℤ
⊢ (n /. Int.ofNat Nat.zero).den =
    if Int.ofNat Nat.zero = 0 then 1 else Int.natAbs (Int.ofNat Nat.zero) / Int.gcd n (Int.ofNat Nat.zero)

Next tactic:
simp [divInt, mkRat, Rat.normalize, Nat.succPNat, Int.sign, Int.gcd, -Nat.cast_succ]
theorem den_mk (n d : ℤ) : (n /. d).den = if d = 0 then 1 else d.natAbs / n.gcd d := by
  rcases d with ((_ | _) | _) <;>
    

Proof state:
case ofNat.succ
n : ℤ
n✝ : ℕ
⊢ (n /. Int.ofNat (Nat.succ n✝)).den =
    if Int.ofNat (Nat.succ n✝) = 0 then 1
    else Int.natAbs (Int.ofNat (Nat.succ n✝)) / Int.gcd n (Int.ofNat (Nat.succ n✝))

Next tactic:
simp [divInt, mkRat, Rat.normalize, Nat.succPNat, Int.sign, Int.gcd, -Nat.cast_succ]
theorem den_mk (n d : ℤ) : (n /. d).den = if d = 0 then 1 else d.natAbs / n.gcd d := by
  rcases d with ((_ | _) | _) <;>
    

Proof state:
case negSucc
n : ℤ
a✝ : ℕ
⊢ (n /. Int.negSucc a✝).den = if Int.negSucc a✝ = 0 then 1 else Int.natAbs (Int.negSucc a✝) / Int.gcd n (Int.negSucc a✝)

Next tactic:
simp [divInt, mkRat, Rat.normalize, Nat.succPNat, Int.sign, Int.gcd, -Nat.cast_succ]
theorem add_den_dvd (q₁ q₂ : ℚ) : (q₁ + q₂).den ∣ q₁.den * q₂.den := by
  

Proof state:
q₁ q₂ : ℚ
⊢ (q₁ + q₂).den ∣ q₁.den * q₂.den

Next tactic:
rw [add_def, normalize_eq]
theorem add_den_dvd (q₁ q₂ : ℚ) : (q₁ + q₂).den ∣ q₁.den * q₂.den := by
  rw [add_def, normalize_eq]
  

Proof state:
q₁ q₂ : ℚ
⊢ (mk'
        ((q₁.num * ↑q₂.den + q₂.num * ↑q₁.den) /
          ↑(Nat.gcd (Int.natAbs (q₁.num * ↑q₂.den + q₂.num * ↑q₁.den)) (q₁.den * q₂.den)))
        (q₁.den * q₂.den / Nat.gcd (Int.natAbs (q₁.num * ↑q₂.den + q₂.num * ↑q₁.den)) (q₁.den * q₂.den))).den ∣
    q₁.den * q₂.den

Next tactic:
apply Nat.div_dvd_of_dvd
theorem add_den_dvd (q₁ q₂ : ℚ) : (q₁ + q₂).den ∣ q₁.den * q₂.den := by
  rw [add_def, normalize_eq]
  apply Nat.div_dvd_of_dvd
  

Proof state:
case h
q₁ q₂ : ℚ
⊢ Nat.gcd (Int.natAbs (q₁.num * ↑q₂.den + q₂.num * ↑q₁.den)) (q₁.den * q₂.den) ∣ q₁.den * q₂.den

Next tactic:
apply Nat.gcd_dvd_right
theorem mul_den_dvd (q₁ q₂ : ℚ) : (q₁ * q₂).den ∣ q₁.den * q₂.den := by
  

Proof state:
q₁ q₂ : ℚ
⊢ (q₁ * q₂).den ∣ q₁.den * q₂.den

Next tactic:
rw [mul_def, normalize_eq]
theorem mul_den_dvd (q₁ q₂ : ℚ) : (q₁ * q₂).den ∣ q₁.den * q₂.den := by
  rw [mul_def, normalize_eq]
  

Proof state:
q₁ q₂ : ℚ
⊢ (mk' (q₁.num * q₂.num / ↑(Nat.gcd (Int.natAbs (q₁.num * q₂.num)) (q₁.den * q₂.den)))
        (q₁.den * q₂.den / Nat.gcd (Int.natAbs (q₁.num * q₂.num)) (q₁.den * q₂.den))).den ∣
    q₁.den * q₂.den

Next tactic:
apply Nat.div_dvd_of_dvd
theorem mul_den_dvd (q₁ q₂ : ℚ) : (q₁ * q₂).den ∣ q₁.den * q₂.den := by
  rw [mul_def, normalize_eq]
  apply Nat.div_dvd_of_dvd
  

Proof state:
case h
q₁ q₂ : ℚ
⊢ Nat.gcd (Int.natAbs (q₁.num * q₂.num)) (q₁.den * q₂.den) ∣ q₁.den * q₂.den

Next tactic:
apply Nat.gcd_dvd_right
theorem mul_num (q₁ q₂ : ℚ) :
    (q₁ * q₂).num = q₁.num * q₂.num / Nat.gcd (q₁.num * q₂.num).natAbs (q₁.den * q₂.den) := by
  

Proof state:
q₁ q₂ : ℚ
⊢ (q₁ * q₂).num = q₁.num * q₂.num / ↑(Nat.gcd (Int.natAbs (q₁.num * q₂.num)) (q₁.den * q₂.den))

Next tactic:
rw [mul_def, normalize_eq]
theorem mul_den (q₁ q₂ : ℚ) :
    (q₁ * q₂).den =
      q₁.den * q₂.den / Nat.gcd (q₁.num * q₂.num).natAbs (q₁.den * q₂.den) := by
  

Proof state:
q₁ q₂ : ℚ
⊢ (q₁ * q₂).den = q₁.den * q₂.den / Nat.gcd (Int.natAbs (q₁.num * q₂.num)) (q₁.den * q₂.den)

Next tactic:
rw [mul_def, normalize_eq]
theorem mul_self_num (q : ℚ) : (q * q).num = q.num * q.num := by
  

Proof state:
q : ℚ
⊢ (q * q).num = q.num * q.num

Next tactic:
rw [mul_num, Int.natAbs_mul, Nat.Coprime.gcd_eq_one, Int.ofNat_one, Int.ediv_one]
theorem mul_self_num (q : ℚ) : (q * q).num = q.num * q.num := by
  rw [mul_num, Int.natAbs_mul, Nat.Coprime.gcd_eq_one, Int.ofNat_one, Int.ediv_one]
  

Proof state:
q : ℚ
⊢ Nat.Coprime (Int.natAbs q.num * Int.natAbs q.num) (q.den * q.den)

Next tactic:
exact (q.reduced.mul_right q.reduced).mul (q.reduced.mul_right q.reduced)
theorem mul_self_den (q : ℚ) : (q * q).den = q.den * q.den := by
  

Proof state:
q : ℚ
⊢ (q * q).den = q.den * q.den

Next tactic:
rw [Rat.mul_den, Int.natAbs_mul, Nat.Coprime.gcd_eq_one, Nat.div_one]
theorem mul_self_den (q : ℚ) : (q * q).den = q.den * q.den := by
  rw [Rat.mul_den, Int.natAbs_mul, Nat.Coprime.gcd_eq_one, Nat.div_one]
  

Proof state:
q : ℚ
⊢ Nat.Coprime (Int.natAbs q.num * Int.natAbs q.num) (q.den * q.den)

Next tactic:
exact (q.reduced.mul_right q.reduced).mul (q.reduced.mul_right q.reduced)
theorem add_num_den (q r : ℚ) :
    q + r = (q.num * r.den + q.den * r.num : ℤ) /. (↑q.den * ↑r.den : ℤ) := by
  

Proof state:
q r : ℚ
⊢ q + r = (q.num * ↑r.den + ↑q.den * r.num) /. (↑q.den * ↑r.den)

Next tactic:
have hqd : (q.den : ℤ) ≠ 0 := Int.coe_nat_ne_zero_iff_pos.2 q.den_pos
theorem add_num_den (q r : ℚ) :
    q + r = (q.num * r.den + q.den * r.num : ℤ) /. (↑q.den * ↑r.den : ℤ) := by
  have hqd : (q.den : ℤ) ≠ 0 := Int.coe_nat_ne_zero_iff_pos.2 q.den_pos
  

Proof state:
q r : ℚ
hqd : ↑q.den ≠ 0
⊢ q + r = (q.num * ↑r.den + ↑q.den * r.num) /. (↑q.den * ↑r.den)

Next tactic:
have hrd : (r.den : ℤ) ≠ 0 := Int.coe_nat_ne_zero_iff_pos.2 r.den_pos
theorem add_num_den (q r : ℚ) :
    q + r = (q.num * r.den + q.den * r.num : ℤ) /. (↑q.den * ↑r.den : ℤ) := by
  have hqd : (q.den : ℤ) ≠ 0 := Int.coe_nat_ne_zero_iff_pos.2 q.den_pos
  have hrd : (r.den : ℤ) ≠ 0 := Int.coe_nat_ne_zero_iff_pos.2 r.den_pos
  

Proof state:
q r : ℚ
hqd : ↑q.den ≠ 0
hrd : ↑r.den ≠ 0
⊢ q + r = (q.num * ↑r.den + ↑q.den * r.num) /. (↑q.den * ↑r.den)

Next tactic:
conv_lhs => rw [← @num_den q, ← @num_den r, Rat.add_def'' hqd hrd]
theorem add_num_den (q r : ℚ) :
    q + r = (q.num * r.den + q.den * r.num : ℤ) /. (↑q.den * ↑r.den : ℤ) := by
  have hqd : (q.den : ℤ) ≠ 0 := Int.coe_nat_ne_zero_iff_pos.2 q.den_pos
  have hrd : (r.den : ℤ) ≠ 0 := Int.coe_nat_ne_zero_iff_pos.2 r.den_pos
  conv_lhs => 

Proof state:
q r : ℚ
hqd : ↑q.den ≠ 0
hrd : ↑r.den ≠ 0
| q + r

Next tactic:
rw [← @num_den q, ← @num_den r, Rat.add_def'' hqd hrd]
theorem add_num_den (q r : ℚ) :
    q + r = (q.num * r.den + q.den * r.num : ℤ) /. (↑q.den * ↑r.den : ℤ) := by
  have hqd : (q.den : ℤ) ≠ 0 := Int.coe_nat_ne_zero_iff_pos.2 q.den_pos
  have hrd : (r.den : ℤ) ≠ 0 := Int.coe_nat_ne_zero_iff_pos.2 r.den_pos
  conv_lhs => rw [← @num_den q, ← @num_den r, Rat.add_def'' hqd hrd]
  

Proof state:
q r : ℚ
hqd : ↑q.den ≠ 0
hrd : ↑r.den ≠ 0
⊢ (q.num * ↑r.den + r.num * ↑q.den) /. (↑q.den * ↑r.den) = (q.num * ↑r.den + ↑q.den * r.num) /. (↑q.den * ↑r.den)

Next tactic:
rw [mul_comm r.num q.den]
theorem exists_eq_mul_div_num_and_eq_mul_div_den (n : ℤ) {d : ℤ} (d_ne_zero : d ≠ 0) :
    ∃ c : ℤ, n = c * ((n : ℚ) / d).num ∧ (d : ℤ) = c * ((n : ℚ) / d).den :=
  haveI : (n : ℚ) / d = Rat.divInt n d := by 

Proof state:
n d : ℤ
d_ne_zero : d ≠ 0
⊢ ↑n / ↑d = n /. d

Next tactic:
rw [← Rat.divInt_eq_div]
theorem mul_num_den' (q r : ℚ) :
    (q * r).num * q.den * r.den = q.num * r.num * (q * r).den := by
  

Proof state:
q r : ℚ
⊢ (q * r).num * ↑q.den * ↑r.den = q.num * r.num * ↑(q * r).den

Next tactic:
let s := q.num * r.num /. (q.den * r.den : ℤ)
theorem mul_num_den' (q r : ℚ) :
    (q * r).num * q.den * r.den = q.num * r.num * (q * r).den := by
  let s := q.num * r.num /. (q.den * r.den : ℤ)
  

Proof state:
q r : ℚ
s : ℚ := q.num * r.num /. (↑q.den * ↑r.den)
⊢ (q * r).num * ↑q.den * ↑r.den = q.num * r.num * ↑(q * r).den

Next tactic:
have hs : (q.den * r.den : ℤ) ≠ 0 := Int.coe_nat_ne_zero_iff_pos.mpr (mul_pos q.pos r.pos)
theorem mul_num_den' (q r : ℚ) :
    (q * r).num * q.den * r.den = q.num * r.num * (q * r).den := by
  let s := q.num * r.num /. (q.den * r.den : ℤ)
  have hs : (q.den * r.den : ℤ) ≠ 0 := Int.coe_nat_ne_zero_iff_pos.mpr (mul_pos q.pos r.pos)
  

Proof state:
q r : ℚ
s : ℚ := q.num * r.num /. (↑q.den * ↑r.den)
hs : ↑q.den * ↑r.den ≠ 0
⊢ (q * r).num * ↑q.den * ↑r.den = q.num * r.num * ↑(q * r).den

Next tactic:
obtain ⟨c, ⟨c_mul_num, c_mul_den⟩⟩ :=
    exists_eq_mul_div_num_and_eq_mul_div_den (q.num * r.num) hs
theorem mul_num_den' (q r : ℚ) :
    (q * r).num * q.den * r.den = q.num * r.num * (q * r).den := by
  let s := q.num * r.num /. (q.den * r.den : ℤ)
  have hs : (q.den * r.den : ℤ) ≠ 0 := Int.coe_nat_ne_zero_iff_pos.mpr (mul_pos q.pos r.pos)
  obtain ⟨c, ⟨c_mul_num, c_mul_den⟩⟩ :=
    exists_eq_mul_div_num_and_eq_mul_div_den (q.num * r.num) hs
  

Proof state:
case intro.intro
q r : ℚ
s : ℚ := q.num * r.num /. (↑q.den * ↑r.den)
hs : ↑q.den * ↑r.den ≠ 0
c : ℤ
c_mul_num : q.num * r.num = c * (↑(q.num * r.num) / ↑(↑q.den * ↑r.den)).num
c_mul_den : ↑q.den * ↑r.den = c * ↑(↑(q.num * r.num) / ↑(↑q.den * ↑r.den)).den
⊢ (q * r).num * ↑q.den * ↑r.den = q.num * r.num * ↑(q * r).den

Next tactic:
rw [c_mul_num, mul_assoc, mul_comm]
theorem mul_num_den' (q r : ℚ) :
    (q * r).num * q.den * r.den = q.num * r.num * (q * r).den := by
  let s := q.num * r.num /. (q.den * r.den : ℤ)
  have hs : (q.den * r.den : ℤ) ≠ 0 := Int.coe_nat_ne_zero_iff_pos.mpr (mul_pos q.pos r.pos)
  obtain ⟨c, ⟨c_mul_num, c_mul_den⟩⟩ :=
    exists_eq_mul_div_num_and_eq_mul_div_den (q.num * r.num) hs
  rw [c_mul_num, mul_assoc, mul_comm]
  

Proof state:
case intro.intro
q r : ℚ
s : ℚ := q.num * r.num /. (↑q.den * ↑r.den)
hs : ↑q.den * ↑r.den ≠ 0
c : ℤ
c_mul_num : q.num * r.num = c * (↑(q.num * r.num) / ↑(↑q.den * ↑r.den)).num
c_mul_den : ↑q.den * ↑r.den = c * ↑(↑(q.num * r.num) / ↑(↑q.den * ↑r.den)).den
⊢ ↑q.den * ↑r.den * (q * r).num = c * (↑(q.num * r.num) / ↑(↑q.den * ↑r.den)).num * ↑(q * r).den

Next tactic:
nth_rw 1 [c_mul_den]
theorem mul_num_den' (q r : ℚ) :
    (q * r).num * q.den * r.den = q.num * r.num * (q * r).den := by
  let s := q.num * r.num /. (q.den * r.den : ℤ)
  have hs : (q.den * r.den : ℤ) ≠ 0 := Int.coe_nat_ne_zero_iff_pos.mpr (mul_pos q.pos r.pos)
  obtain ⟨c, ⟨c_mul_num, c_mul_den⟩⟩ :=
    exists_eq_mul_div_num_and_eq_mul_div_den (q.num * r.num) hs
  rw [c_mul_num, mul_assoc, mul_comm]
  nth_rw 1 [c_mul_den]
  

Proof state:
case intro.intro
q r : ℚ
s : ℚ := q.num * r.num /. (↑q.den * ↑r.den)
hs : ↑q.den * ↑r.den ≠ 0
c : ℤ
c_mul_num : q.num * r.num = c * (↑(q.num * r.num) / ↑(↑q.den * ↑r.den)).num
c_mul_den : ↑q.den * ↑r.den = c * ↑(↑(q.num * r.num) / ↑(↑q.den * ↑r.den)).den
⊢ c * ↑(↑(q.num * r.num) / ↑(↑q.den * ↑r.den)).den * (q * r).num =
    c * (↑(q.num * r.num) / ↑(↑q.den * ↑r.den)).num * ↑(q * r).den

Next tactic:
repeat' rw [Int.mul_assoc]
theorem mul_num_den' (q r : ℚ) :
    (q * r).num * q.den * r.den = q.num * r.num * (q * r).den := by
  let s := q.num * r.num /. (q.den * r.den : ℤ)
  have hs : (q.den * r.den : ℤ) ≠ 0 := Int.coe_nat_ne_zero_iff_pos.mpr (mul_pos q.pos r.pos)
  obtain ⟨c, ⟨c_mul_num, c_mul_den⟩⟩ :=
    exists_eq_mul_div_num_and_eq_mul_div_den (q.num * r.num) hs
  rw [c_mul_num, mul_assoc, mul_comm]
  nth_rw 1 [c_mul_den]
  repeat' 

Proof state:
case intro.intro
q r : ℚ
s : ℚ := q.num * r.num /. (↑q.den * ↑r.den)
hs : ↑q.den * ↑r.den ≠ 0
c : ℤ
c_mul_num : q.num * r.num = c * (↑(q.num * r.num) / ↑(↑q.den * ↑r.den)).num
c_mul_den : ↑q.den * ↑r.den = c * ↑(↑(q.num * r.num) / ↑(↑q.den * ↑r.den)).den
⊢ c * ↑(↑(q.num * r.num) / ↑(↑q.den * ↑r.den)).den * (q * r).num =
    c * (↑(q.num * r.num) / ↑(↑q.den * ↑r.den)).num * ↑(q * r).den

Next tactic:
rw [Int.mul_assoc]
theorem mul_num_den' (q r : ℚ) :
    (q * r).num * q.den * r.den = q.num * r.num * (q * r).den := by
  let s := q.num * r.num /. (q.den * r.den : ℤ)
  have hs : (q.den * r.den : ℤ) ≠ 0 := Int.coe_nat_ne_zero_iff_pos.mpr (mul_pos q.pos r.pos)
  obtain ⟨c, ⟨c_mul_num, c_mul_den⟩⟩ :=
    exists_eq_mul_div_num_and_eq_mul_div_den (q.num * r.num) hs
  rw [c_mul_num, mul_assoc, mul_comm]
  nth_rw 1 [c_mul_den]
  repeat' 

Proof state:
case intro.intro
q r : ℚ
s : ℚ := q.num * r.num /. (↑q.den * ↑r.den)
hs : ↑q.den * ↑r.den ≠ 0
c : ℤ
c_mul_num : q.num * r.num = c * (↑(q.num * r.num) / ↑(↑q.den * ↑r.den)).num
c_mul_den : ↑q.den * ↑r.den = c * ↑(↑(q.num * r.num) / ↑(↑q.den * ↑r.den)).den
⊢ c * (↑(↑(q.num * r.num) / ↑(↑q.den * ↑r.den)).den * (q * r).num) =
    c * (↑(q.num * r.num) / ↑(↑q.den * ↑r.den)).num * ↑(q * r).den

Next tactic:
rw [Int.mul_assoc]
theorem mul_num_den' (q r : ℚ) :
    (q * r).num * q.den * r.den = q.num * r.num * (q * r).den := by
  let s := q.num * r.num /. (q.den * r.den : ℤ)
  have hs : (q.den * r.den : ℤ) ≠ 0 := Int.coe_nat_ne_zero_iff_pos.mpr (mul_pos q.pos r.pos)
  obtain ⟨c, ⟨c_mul_num, c_mul_den⟩⟩ :=
    exists_eq_mul_div_num_and_eq_mul_div_den (q.num * r.num) hs
  rw [c_mul_num, mul_assoc, mul_comm]
  nth_rw 1 [c_mul_den]
  repeat' 

Proof state:
case intro.intro
q r : ℚ
s : ℚ := q.num * r.num /. (↑q.den * ↑r.den)
hs : ↑q.den * ↑r.den ≠ 0
c : ℤ
c_mul_num : q.num * r.num = c * (↑(q.num * r.num) / ↑(↑q.den * ↑r.den)).num
c_mul_den : ↑q.den * ↑r.den = c * ↑(↑(q.num * r.num) / ↑(↑q.den * ↑r.den)).den
⊢ c * (↑(↑(q.num * r.num) / ↑(↑q.den * ↑r.den)).den * (q * r).num) =
    c * ((↑(q.num * r.num) / ↑(↑q.den * ↑r.den)).num * ↑(q * r).den)

Next tactic:
rw [Int.mul_assoc]
theorem mul_num_den' (q r : ℚ) :
    (q * r).num * q.den * r.den = q.num * r.num * (q * r).den := by
  let s := q.num * r.num /. (q.den * r.den : ℤ)
  have hs : (q.den * r.den : ℤ) ≠ 0 := Int.coe_nat_ne_zero_iff_pos.mpr (mul_pos q.pos r.pos)
  obtain ⟨c, ⟨c_mul_num, c_mul_den⟩⟩ :=
    exists_eq_mul_div_num_and_eq_mul_div_den (q.num * r.num) hs
  rw [c_mul_num, mul_assoc, mul_comm]
  nth_rw 1 [c_mul_den]
  repeat' rw [Int.mul_assoc]
  

Proof state:
case intro.intro
q r : ℚ
s : ℚ := q.num * r.num /. (↑q.den * ↑r.den)
hs : ↑q.den * ↑r.den ≠ 0
c : ℤ
c_mul_num : q.num * r.num = c * (↑(q.num * r.num) / ↑(↑q.den * ↑r.den)).num
c_mul_den : ↑q.den * ↑r.den = c * ↑(↑(q.num * r.num) / ↑(↑q.den * ↑r.den)).den
⊢ c * (↑(↑(q.num * r.num) / ↑(↑q.den * ↑r.den)).den * (q * r).num) =
    c * ((↑(q.num * r.num) / ↑(↑q.den * ↑r.den)).num * ↑(q * r).den)

Next tactic:
apply mul_eq_mul_left_iff.2
theorem mul_num_den' (q r : ℚ) :
    (q * r).num * q.den * r.den = q.num * r.num * (q * r).den := by
  let s := q.num * r.num /. (q.den * r.den : ℤ)
  have hs : (q.den * r.den : ℤ) ≠ 0 := Int.coe_nat_ne_zero_iff_pos.mpr (mul_pos q.pos r.pos)
  obtain ⟨c, ⟨c_mul_num, c_mul_den⟩⟩ :=
    exists_eq_mul_div_num_and_eq_mul_div_den (q.num * r.num) hs
  rw [c_mul_num, mul_assoc, mul_comm]
  nth_rw 1 [c_mul_den]
  repeat' rw [Int.mul_assoc]
  apply mul_eq_mul_left_iff.2
  

Proof state:
case intro.intro
q r : ℚ
s : ℚ := q.num * r.num /. (↑q.den * ↑r.den)
hs : ↑q.den * ↑r.den ≠ 0
c : ℤ
c_mul_num : q.num * r.num = c * (↑(q.num * r.num) / ↑(↑q.den * ↑r.den)).num
c_mul_den : ↑q.den * ↑r.den = c * ↑(↑(q.num * r.num) / ↑(↑q.den * ↑r.den)).den
⊢ ↑(↑(q.num * r.num) / ↑(↑q.den * ↑r.den)).den * (q * r).num =
      (↑(q.num * r.num) / ↑(↑q.den * ↑r.den)).num * ↑(q * r).den ∨
    c = 0

Next tactic:
rw [or_iff_not_imp_right]