-- Mathlib/Algebra/Polynomial/PartialFractions.lean
theorem div_eq_quo_add_rem_div_add_rem_div (f : R[X]) {g₁ g₂ : R[X]} (hg₁ : g₁.Monic)
    (hg₂ : g₂.Monic) (hcoprime : IsCoprime g₁ g₂) :
    ∃ q r₁ r₂ : R[X],
      r₁.degree < g₁.degree ∧
        r₂.degree < g₂.degree ∧ (f : K) / (↑g₁ * ↑g₂) = ↑q + ↑r₁ / ↑g₁ + ↑r₂ / ↑g₂

Proof state:
case intro.intro
R : Type
inst✝⁴ : CommRing R
inst✝³ : IsDomain R
K : Type
inst✝² : Field K
inst✝¹ : Algebra R[X] K
inst✝ : IsFractionRing R[X] K
f g₁ g₂ : R[X]
hg₁ : g₁.Monic
hg₂ : g₂.Monic
c d : R[X]
hcd : c * g₁ + d * g₂ = 1
hg₁' : ↑g₁ ≠ 0
hg₂' : ↑g₂ ≠ 0
hfc : f * c %ₘ g₂ + g₂ * (f * c /ₘ g₂) = f * c
⊢ ↑f / (↑g₁ * ↑g₂) = ↑(f * d /ₘ g₁ + f * c /ₘ g₂) + ↑(f * d %ₘ g₁) / ↑g₁ + ↑(f * c %ₘ g₂) / ↑g₂

Tactic:
have hfd := modByMonic_add_div (f * d) hg₁

Result:
case intro.intro
R : Type
inst✝⁴ : CommRing R
inst✝³ : IsDomain R
K : Type
inst✝² : Field K
inst✝¹ : Algebra R[X] K
inst✝ : IsFractionRing R[X] K
f g₁ g₂ : R[X]
hg₁ : g₁.Monic
hg₂ : g₂.Monic
c d : R[X]
hcd : c * g₁ + d * g₂ = 1
hg₁' : ↑g₁ ≠ 0
hg₂' : ↑g₂ ≠ 0
hfc : f * c %ₘ g₂ + g₂ * (f * c /ₘ g₂) = f * c
hfd : f * d %ₘ g₁ + g₁ * (f * d /ₘ g₁) = f * d
⊢ ↑f / (↑g₁ * ↑g₂) = ↑(f * d /ₘ g₁ + f * c /ₘ g₂) + ↑(f * d %ₘ g₁) / ↑g₁ + ↑(f * c %ₘ g₂) / ↑g₂

Proof state:
case intro.intro
R : Type
inst✝⁴ : CommRing R
inst✝³ : IsDomain R
K : Type
inst✝² : Field K
inst✝¹ : Algebra R[X] K
inst✝ : IsFractionRing R[X] K
f g₁ g₂ : R[X]
hg₁ : g₁.Monic
hg₂ : g₂.Monic
c d : R[X]
hcd : c * g₁ + d * g₂ = 1
hg₁' : ↑g₁ ≠ 0
hg₂' : ↑g₂ ≠ 0
⊢ ↑f / (↑g₁ * ↑g₂) = ↑(f * d /ₘ g₁ + f * c /ₘ g₂) + ↑(f * d %ₘ g₁) / ↑g₁ + ↑(f * c %ₘ g₂) / ↑g₂

Tactic:
have hfc := modByMonic_add_div (f * c) hg₂

Result:
case intro.intro
R : Type
inst✝⁴ : CommRing R
inst✝³ : IsDomain R
K : Type
inst✝² : Field K
inst✝¹ : Algebra R[X] K
inst✝ : IsFractionRing R[X] K
f g₁ g₂ : R[X]
hg₁ : g₁.Monic
hg₂ : g₂.Monic
c d : R[X]
hcd : c * g₁ + d * g₂ = 1
hg₁' : ↑g₁ ≠ 0
hg₂' : ↑g₂ ≠ 0
hfc : f * c %ₘ g₂ + g₂ * (f * c /ₘ g₂) = f * c
⊢ ↑f / (↑g₁ * ↑g₂) = ↑(f * d /ₘ g₁ + f * c /ₘ g₂) + ↑(f * d %ₘ g₁) / ↑g₁ + ↑(f * c %ₘ g₂) / ↑g₂

Proof state:
R : Type
inst✝⁴ : CommRing R
inst✝³ : IsDomain R
K : Type
inst✝² : Field K
inst✝¹ : Algebra R[X] K
inst✝ : IsFractionRing R[X] K
f g₁ g₂ : R[X]
hg₁ : g₁.Monic
hg₂ : g₂.Monic
c d : R[X]
hcd : c * g₁ + d * g₂ = 1
⊢ ¬g₁ = 0

Tactic:
exact hg₁.ne_zero

Result:
no goals

Proof state:
case intro.intro
R : Type
inst✝⁴ : CommRing R
inst✝³ : IsDomain R
K : Type
inst✝² : Field K
inst✝¹ : Algebra R[X] K
inst✝ : IsFractionRing R[X] K
f g₁ g₂ : R[X]
hg₁ : g₁.Monic
hg₂ : g₂.Monic
c d : R[X]
hcd : c * g₁ + d * g₂ = 1
⊢ ↑f / (↑g₁ * ↑g₂) = ↑(f * d /ₘ g₁ + f * c /ₘ g₂) + ↑(f * d %ₘ g₁) / ↑g₁ + ↑(f * c %ₘ g₂) / ↑g₂

Tactic:
have hg₁' : (↑g₁ : K) ≠ 0 := by
  norm_cast
  exact hg₁.ne_zero

Result:
case intro.intro
R : Type
inst✝⁴ : CommRing R
inst✝³ : IsDomain R
K : Type
inst✝² : Field K
inst✝¹ : Algebra R[X] K
inst✝ : IsFractionRing R[X] K
f g₁ g₂ : R[X]
hg₁ : g₁.Monic
hg₂ : g₂.Monic
c d : R[X]
hcd : c * g₁ + d * g₂ = 1
hg₁' : ↑g₁ ≠ 0
⊢ ↑f / (↑g₁ * ↑g₂) = ↑(f * d /ₘ g₁ + f * c /ₘ g₂) + ↑(f * d %ₘ g₁) / ↑g₁ + ↑(f * c %ₘ g₂) / ↑g₂

Proof state:
case intro.intro
R : Type
inst✝⁴ : CommRing R
inst✝³ : IsDomain R
K : Type
inst✝² : Field K
inst✝¹ : Algebra R[X] K
inst✝ : IsFractionRing R[X] K
f g₁ g₂ : R[X]
hg₁ : g₁.Monic
hg₂ : g₂.Monic
c d : R[X]
hcd : c * g₁ + d * g₂ = 1
hg₁' : ↑g₁ ≠ 0
hg₂' : ↑g₂ ≠ 0
hfc : f * c %ₘ g₂ + g₂ * (f * c /ₘ g₂) = f * c
hfd : f * d %ₘ g₁ + g₁ * (f * d /ₘ g₁) = f * d
⊢ ↑f =
    (((algebraMap R[X] K) (f * d /ₘ g₁) + (algebraMap R[X] K) (f * c /ₘ g₂)) * ↑g₁ + ↑(f * d %ₘ g₁)) * ↑g₂ +
      ↑(f * c %ₘ g₂) * ↑g₁

Tactic:
norm_cast

Result:
case intro.intro
R : Type
inst✝⁴ : CommRing R
inst✝³ : IsDomain R
K : Type
inst✝² : Field K
inst✝¹ : Algebra R[X] K
inst✝ : IsFractionRing R[X] K
f g₁ g₂ : R[X]
hg₁ : g₁.Monic
hg₂ : g₂.Monic
c d : R[X]
hcd : c * g₁ + d * g₂ = 1
hg₁' : ↑g₁ ≠ 0
hg₂' : ↑g₂ ≠ 0
hfc : f * c %ₘ g₂ + g₂ * (f * c /ₘ g₂) = f * c
hfd : f * d %ₘ g₁ + g₁ * (f * d /ₘ g₁) = f * d
⊢ f = ((f * d /ₘ g₁ + f * c /ₘ g₂) * g₁ + f * d %ₘ g₁) * g₂ + f * c %ₘ g₂ * g₁

Proof state:
R : Type
inst✝⁴ : CommRing R
inst✝³ : IsDomain R
K : Type
inst✝² : Field K
inst✝¹ : Algebra R[X] K
inst✝ : IsFractionRing R[X] K
f g₁ g₂ : R[X]
hg₁ : g₁.Monic
hg₂ : g₂.Monic
c d : R[X]
hcd : c * g₁ + d * g₂ = 1
hg₁' : ↑g₁ ≠ 0
⊢ ↑g₂ ≠ 0

Tactic:
norm_cast

Result:
R : Type
inst✝⁴ : CommRing R
inst✝³ : IsDomain R
K : Type
inst✝² : Field K
inst✝¹ : Algebra R[X] K
inst✝ : IsFractionRing R[X] K
f g₁ g₂ : R[X]
hg₁ : g₁.Monic
hg₂ : g₂.Monic
c d : R[X]
hcd : c * g₁ + d * g₂ = 1
hg₁' : ↑g₁ ≠ 0
⊢ ¬g₂ = 0

Proof state:
case intro.intro
R : Type
inst✝⁴ : CommRing R
inst✝³ : IsDomain R
K : Type
inst✝² : Field K
inst✝¹ : Algebra R[X] K
inst✝ : IsFractionRing R[X] K
f g₁ g₂ : R[X]
hg₁ : g₁.Monic
hg₂ : g₂.Monic
c d : R[X]
hcd : c * g₁ + d * g₂ = 1
⊢ ∃ q r₁ r₂, r₁.degree < g₁.degree ∧ r₂.degree < g₂.degree ∧ ↑f / (↑g₁ * ↑g₂) = ↑q + ↑r₁ / ↑g₁ + ↑r₂ / ↑g₂

Tactic:
refine
  ⟨f * d /ₘ g₁ + f * c /ₘ g₂, f * d %ₘ g₁, f * c %ₘ g₂, degree_modByMonic_lt _ hg₁,
    degree_modByMonic_lt _ hg₂, ?_⟩

Result:
case intro.intro
R : Type
inst✝⁴ : CommRing R
inst✝³ : IsDomain R
K : Type
inst✝² : Field K
inst✝¹ : Algebra R[X] K
inst✝ : IsFractionRing R[X] K
f g₁ g₂ : R[X]
hg₁ : g₁.Monic
hg₂ : g₂.Monic
c d : R[X]
hcd : c * g₁ + d * g₂ = 1
⊢ ↑f / (↑g₁ * ↑g₂) = ↑(f * d /ₘ g₁ + f * c /ₘ g₂) + ↑(f * d %ₘ g₁) / ↑g₁ + ↑(f * c %ₘ g₂) / ↑g₂

Proof state:
case intro.intro
R : Type
inst✝⁴ : CommRing R
inst✝³ : IsDomain R
K : Type
inst✝² : Field K
inst✝¹ : Algebra R[X] K
inst✝ : IsFractionRing R[X] K
f g₁ g₂ : R[X]
hg₁ : g₁.Monic
hg₂ : g₂.Monic
c d : R[X]
hcd : c * g₁ + d * g₂ = 1
hg₁' : ↑g₁ ≠ 0
⊢ ↑f / (↑g₁ * ↑g₂) = ↑(f * d /ₘ g₁ + f * c /ₘ g₂) + ↑(f * d %ₘ g₁) / ↑g₁ + ↑(f * c %ₘ g₂) / ↑g₂

Tactic:
have hg₂' : (↑g₂ : K) ≠ 0 := by
  norm_cast
  exact hg₂.ne_zero

Result:
case intro.intro
R : Type
inst✝⁴ : CommRing R
inst✝³ : IsDomain R
K : Type
inst✝² : Field K
inst✝¹ : Algebra R[X] K
inst✝ : IsFractionRing R[X] K
f g₁ g₂ : R[X]
hg₁ : g₁.Monic
hg₂ : g₂.Monic
c d : R[X]
hcd : c * g₁ + d * g₂ = 1
hg₁' : ↑g₁ ≠ 0
hg₂' : ↑g₂ ≠ 0
⊢ ↑f / (↑g₁ * ↑g₂) = ↑(f * d /ₘ g₁ + f * c /ₘ g₂) + ↑(f * d %ₘ g₁) / ↑g₁ + ↑(f * c %ₘ g₂) / ↑g₂

Proof state:
case intro.intro
R : Type
inst✝⁴ : CommRing R
inst✝³ : IsDomain R
K : Type
inst✝² : Field K
inst✝¹ : Algebra R[X] K
inst✝ : IsFractionRing R[X] K
f g₁ g₂ : R[X]
hg₁ : g₁.Monic
hg₂ : g₂.Monic
c d : R[X]
hcd : c * g₁ + d * g₂ = 1
hg₁' : ↑g₁ ≠ 0
hg₂' : ↑g₂ ≠ 0
hfc : f * c %ₘ g₂ + g₂ * (f * c /ₘ g₂) = f * c
hfd : f * d %ₘ g₁ + g₁ * (f * d /ₘ g₁) = f * d
⊢ f = ((f * d /ₘ g₁ + f * c /ₘ g₂) * g₁ + f * d %ₘ g₁) * g₂ + f * c %ₘ g₂ * g₁

Tactic:
linear_combination -1 * f * hcd + -1 * g₁ * hfc + -1 * g₂ * hfd

Result:
no goals

Proof state:
R : Type
inst✝⁴ : CommRing R
inst✝³ : IsDomain R
K : Type
inst✝² : Field K
inst✝¹ : Algebra R[X] K
inst✝ : IsFractionRing R[X] K
f g₁ g₂ : R[X]
hg₁ : g₁.Monic
hg₂ : g₂.Monic
c d : R[X]
hcd : c * g₁ + d * g₂ = 1
⊢ ↑g₁ ≠ 0

Tactic:
norm_cast

Result:
R : Type
inst✝⁴ : CommRing R
inst✝³ : IsDomain R
K : Type
inst✝² : Field K
inst✝¹ : Algebra R[X] K
inst✝ : IsFractionRing R[X] K
f g₁ g₂ : R[X]
hg₁ : g₁.Monic
hg₂ : g₂.Monic
c d : R[X]
hcd : c * g₁ + d * g₂ = 1
⊢ ¬g₁ = 0

Proof state:
R : Type
inst✝⁴ : CommRing R
inst✝³ : IsDomain R
K : Type
inst✝² : Field K
inst✝¹ : Algebra R[X] K
inst✝ : IsFractionRing R[X] K
f g₁ g₂ : R[X]
hg₁ : g₁.Monic
hg₂ : g₂.Monic
hcoprime : IsCoprime g₁ g₂
⊢ ∃ q r₁ r₂, r₁.degree < g₁.degree ∧ r₂.degree < g₂.degree ∧ ↑f / (↑g₁ * ↑g₂) = ↑q + ↑r₁ / ↑g₁ + ↑r₂ / ↑g₂

Tactic:
rcases hcoprime with ⟨c, d, hcd⟩

Result:
case intro.intro
R : Type
inst✝⁴ : CommRing R
inst✝³ : IsDomain R
K : Type
inst✝² : Field K
inst✝¹ : Algebra R[X] K
inst✝ : IsFractionRing R[X] K
f g₁ g₂ : R[X]
hg₁ : g₁.Monic
hg₂ : g₂.Monic
c d : R[X]
hcd : c * g₁ + d * g₂ = 1
⊢ ∃ q r₁ r₂, r₁.degree < g₁.degree ∧ r₂.degree < g₂.degree ∧ ↑f / (↑g₁ * ↑g₂) = ↑q + ↑r₁ / ↑g₁ + ↑r₂ / ↑g₂