l3lab/ntp-mathlib huggingface dataset:
/-- Multiplication and `scaleRoots` commute up to a power of `r`. The factor disappears if we
assume that the product of the leading coeffs does not vanish. See `Polynomial.mul_scaleRoots'`. -/
lemma mul_scaleRoots (p q : R[X]) (r : R) :
    r ^ (natDegree p + natDegree q - natDegree (p * q)) • (p * q).scaleRoots r =
      p.scaleRoots r * q.scaleRoots r := by
  ext n; simp only [coeff_scaleRoots, coeff_smul, smul_eq_mul]
  trans (∑ x in Finset.antidiagonal n, coeff p x.1 * coeff q x.2) *
    r ^ (natDegree p + natDegree q - n)
  · rw [← coeff_mul]
    cases lt_or_le (natDegree (p * q)) n with
    | inl h => simp only [coeff_eq_zero_of_natDegree_lt h, zero_mul, mul_zero]
    | inr h =>
      rw [mul_comm, mul_assoc, ← pow_add, add_comm, tsub_add_tsub_cancel natDegree_mul_le h]
  · rw [coeff_mul, Finset.sum_mul]
    apply Finset.sum_congr rfl
    simp only [Finset.mem_antidiagonal, coeff_scaleRoots, Prod.forall]
    intros a b e
    

Proof state:
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝³ : Semiring S
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Field K
p q : R[X]
r : R
n a b : ℕ
e : a + b = n
⊢ coeff p a * coeff q b * r ^ (natDegree p + natDegree q - n) =
    coeff p a * r ^ (natDegree p - a) * (coeff q b * r ^ (natDegree q - b))

Next tactic:
cases lt_or_le (natDegree p) a with
    | inl h => simp only [coeff_eq_zero_of_natDegree_lt h, zero_mul, mul_zero]
    | inr ha =>
      cases lt_or_le (natDegree q) b with
      | inl h => simp only [coeff_eq_zero_of_natDegree_lt h, zero_mul, mul_zero]
      | inr hb =>
        simp only [← e, mul_assoc, mul_comm (r ^ (_ - a)), ← pow_add]
        rw [add_comm (_ - _), tsub_add_tsub_comm ha hb]
/-- Multiplication and `scaleRoots` commute up to a power of `r`. The factor disappears if we
assume that the product of the leading coeffs does not vanish. See `Polynomial.mul_scaleRoots'`. -/
lemma mul_scaleRoots (p q : R[X]) (r : R) :
    r ^ (natDegree p + natDegree q - natDegree (p * q)) • (p * q).scaleRoots r =
      p.scaleRoots r * q.scaleRoots r := by
  ext n; simp only [coeff_scaleRoots, coeff_smul, smul_eq_mul]
  trans (∑ x in Finset.antidiagonal n, coeff p x.1 * coeff q x.2) *
    r ^ (natDegree p + natDegree q - n)
  · rw [← coeff_mul]
    cases lt_or_le (natDegree (p * q)) n with
    | inl h => simp only [coeff_eq_zero_of_natDegree_lt h, zero_mul, mul_zero]
    | inr h =>
      rw [mul_comm, mul_assoc, ← pow_add, add_comm, tsub_add_tsub_cancel natDegree_mul_le h]
  · rw [coeff_mul, Finset.sum_mul]
    apply Finset.sum_congr rfl
    simp only [Finset.mem_antidiagonal, coeff_scaleRoots, Prod.forall]
    intros a b e
    

Proof state:
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝³ : Semiring S
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Field K
p q : R[X]
r : R
n a b : ℕ
e : a + b = n
x✝ : natDegree p < a ∨ a ≤ natDegree p
⊢ coeff p a * coeff q b * r ^ (natDegree p + natDegree q - n) =
    coeff p a * r ^ (natDegree p - a) * (coeff q b * r ^ (natDegree q - b))

Next tactic:
cases lt_or_le (natDegree p) a with
    | inl h => simp only [coeff_eq_zero_of_natDegree_lt h, zero_mul, mul_zero]
    | inr ha =>
      cases lt_or_le (natDegree q) b with
      | inl h => simp only [coeff_eq_zero_of_natDegree_lt h, zero_mul, mul_zero]
      | inr hb =>
        simp only [← e, mul_assoc, mul_comm (r ^ (_ - a)), ← pow_add]
        rw [add_comm (_ - _), tsub_add_tsub_comm ha hb]
/-- Multiplication and `scaleRoots` commute up to a power of `r`. The factor disappears if we
assume that the product of the leading coeffs does not vanish. See `Polynomial.mul_scaleRoots'`. -/
lemma mul_scaleRoots (p q : R[X]) (r : R) :
    r ^ (natDegree p + natDegree q - natDegree (p * q)) • (p * q).scaleRoots r =
      p.scaleRoots r * q.scaleRoots r := by
  ext n; simp only [coeff_scaleRoots, coeff_smul, smul_eq_mul]
  trans (∑ x in Finset.antidiagonal n, coeff p x.1 * coeff q x.2) *
    r ^ (natDegree p + natDegree q - n)
  · rw [← coeff_mul]
    cases lt_or_le (natDegree (p * q)) n with
    | inl h => simp only [coeff_eq_zero_of_natDegree_lt h, zero_mul, mul_zero]
    | inr h =>
      rw [mul_comm, mul_assoc, ← pow_add, add_comm, tsub_add_tsub_cancel natDegree_mul_le h]
  · rw [coeff_mul, Finset.sum_mul]
    apply Finset.sum_congr rfl
    simp only [Finset.mem_antidiagonal, coeff_scaleRoots, Prod.forall]
    intros a b e
    cases lt_or_le (natDegree p) a with
    

Proof state:
case inl
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝³ : Semiring S
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Field K
p q : R[X]
r : R
n a b : ℕ
e : a + b = n
h : natDegree p < a
⊢ coeff p a * coeff q b * r ^ (natDegree p + natDegree q - n) =
    coeff p a * r ^ (natDegree p - a) * (coeff q b * r ^ (natDegree q - b))

Next tactic:
| inl h => simp only [coeff_eq_zero_of_natDegree_lt h, zero_mul, mul_zero]
/-- Multiplication and `scaleRoots` commute up to a power of `r`. The factor disappears if we
assume that the product of the leading coeffs does not vanish. See `Polynomial.mul_scaleRoots'`. -/
lemma mul_scaleRoots (p q : R[X]) (r : R) :
    r ^ (natDegree p + natDegree q - natDegree (p * q)) • (p * q).scaleRoots r =
      p.scaleRoots r * q.scaleRoots r := by
  ext n; simp only [coeff_scaleRoots, coeff_smul, smul_eq_mul]
  trans (∑ x in Finset.antidiagonal n, coeff p x.1 * coeff q x.2) *
    r ^ (natDegree p + natDegree q - n)
  · rw [← coeff_mul]
    cases lt_or_le (natDegree (p * q)) n with
    | inl h => simp only [coeff_eq_zero_of_natDegree_lt h, zero_mul, mul_zero]
    | inr h =>
      rw [mul_comm, mul_assoc, ← pow_add, add_comm, tsub_add_tsub_cancel natDegree_mul_le h]
  · rw [coeff_mul, Finset.sum_mul]
    apply Finset.sum_congr rfl
    simp only [Finset.mem_antidiagonal, coeff_scaleRoots, Prod.forall]
    intros a b e
    cases lt_or_le (natDegree p) a with
    | inl h => 

Proof state:
case inl
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝³ : Semiring S
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Field K
p q : R[X]
r : R
n a b : ℕ
e : a + b = n
h : natDegree p < a
⊢ coeff p a * coeff q b * r ^ (natDegree p + natDegree q - n) =
    coeff p a * r ^ (natDegree p - a) * (coeff q b * r ^ (natDegree q - b))

Next tactic:
simp only [coeff_eq_zero_of_natDegree_lt h, zero_mul, mul_zero]
/-- Multiplication and `scaleRoots` commute up to a power of `r`. The factor disappears if we
assume that the product of the leading coeffs does not vanish. See `Polynomial.mul_scaleRoots'`. -/
lemma mul_scaleRoots (p q : R[X]) (r : R) :
    r ^ (natDegree p + natDegree q - natDegree (p * q)) • (p * q).scaleRoots r =
      p.scaleRoots r * q.scaleRoots r := by
  ext n; simp only [coeff_scaleRoots, coeff_smul, smul_eq_mul]
  trans (∑ x in Finset.antidiagonal n, coeff p x.1 * coeff q x.2) *
    r ^ (natDegree p + natDegree q - n)
  · rw [← coeff_mul]
    cases lt_or_le (natDegree (p * q)) n with
    | inl h => simp only [coeff_eq_zero_of_natDegree_lt h, zero_mul, mul_zero]
    | inr h =>
      rw [mul_comm, mul_assoc, ← pow_add, add_comm, tsub_add_tsub_cancel natDegree_mul_le h]
  · rw [coeff_mul, Finset.sum_mul]
    apply Finset.sum_congr rfl
    simp only [Finset.mem_antidiagonal, coeff_scaleRoots, Prod.forall]
    intros a b e
    cases lt_or_le (natDegree p) a with
    | inl h => simp only [coeff_eq_zero_of_natDegree_lt h, zero_mul, mul_zero]
    

Proof state:
case inr
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝³ : Semiring S
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Field K
p q : R[X]
r : R
n a b : ℕ
e : a + b = n
ha : a ≤ natDegree p
⊢ coeff p a * coeff q b * r ^ (natDegree p + natDegree q - n) =
    coeff p a * r ^ (natDegree p - a) * (coeff q b * r ^ (natDegree q - b))

Next tactic:
| inr ha =>
      cases lt_or_le (natDegree q) b with
      | inl h => simp only [coeff_eq_zero_of_natDegree_lt h, zero_mul, mul_zero]
      | inr hb =>
        simp only [← e, mul_assoc, mul_comm (r ^ (_ - a)), ← pow_add]
        rw [add_comm (_ - _), tsub_add_tsub_comm ha hb]
/-- Multiplication and `scaleRoots` commute up to a power of `r`. The factor disappears if we
assume that the product of the leading coeffs does not vanish. See `Polynomial.mul_scaleRoots'`. -/
lemma mul_scaleRoots (p q : R[X]) (r : R) :
    r ^ (natDegree p + natDegree q - natDegree (p * q)) • (p * q).scaleRoots r =
      p.scaleRoots r * q.scaleRoots r := by
  ext n; simp only [coeff_scaleRoots, coeff_smul, smul_eq_mul]
  trans (∑ x in Finset.antidiagonal n, coeff p x.1 * coeff q x.2) *
    r ^ (natDegree p + natDegree q - n)
  · rw [← coeff_mul]
    cases lt_or_le (natDegree (p * q)) n with
    | inl h => simp only [coeff_eq_zero_of_natDegree_lt h, zero_mul, mul_zero]
    | inr h =>
      rw [mul_comm, mul_assoc, ← pow_add, add_comm, tsub_add_tsub_cancel natDegree_mul_le h]
  · rw [coeff_mul, Finset.sum_mul]
    apply Finset.sum_congr rfl
    simp only [Finset.mem_antidiagonal, coeff_scaleRoots, Prod.forall]
    intros a b e
    cases lt_or_le (natDegree p) a with
    | inl h => simp only [coeff_eq_zero_of_natDegree_lt h, zero_mul, mul_zero]
    | inr ha =>
      

Proof state:
case inr
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝³ : Semiring S
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Field K
p q : R[X]
r : R
n a b : ℕ
e : a + b = n
ha : a ≤ natDegree p
⊢ coeff p a * coeff q b * r ^ (natDegree p + natDegree q - n) =
    coeff p a * r ^ (natDegree p - a) * (coeff q b * r ^ (natDegree q - b))

Next tactic:
cases lt_or_le (natDegree q) b with
      | inl h => simp only [coeff_eq_zero_of_natDegree_lt h, zero_mul, mul_zero]
      | inr hb =>
        simp only [← e, mul_assoc, mul_comm (r ^ (_ - a)), ← pow_add]
        rw [add_comm (_ - _), tsub_add_tsub_comm ha hb]
/-- Multiplication and `scaleRoots` commute up to a power of `r`. The factor disappears if we
assume that the product of the leading coeffs does not vanish. See `Polynomial.mul_scaleRoots'`. -/
lemma mul_scaleRoots (p q : R[X]) (r : R) :
    r ^ (natDegree p + natDegree q - natDegree (p * q)) • (p * q).scaleRoots r =
      p.scaleRoots r * q.scaleRoots r := by
  ext n; simp only [coeff_scaleRoots, coeff_smul, smul_eq_mul]
  trans (∑ x in Finset.antidiagonal n, coeff p x.1 * coeff q x.2) *
    r ^ (natDegree p + natDegree q - n)
  · rw [← coeff_mul]
    cases lt_or_le (natDegree (p * q)) n with
    | inl h => simp only [coeff_eq_zero_of_natDegree_lt h, zero_mul, mul_zero]
    | inr h =>
      rw [mul_comm, mul_assoc, ← pow_add, add_comm, tsub_add_tsub_cancel natDegree_mul_le h]
  · rw [coeff_mul, Finset.sum_mul]
    apply Finset.sum_congr rfl
    simp only [Finset.mem_antidiagonal, coeff_scaleRoots, Prod.forall]
    intros a b e
    cases lt_or_le (natDegree p) a with
    | inl h => simp only [coeff_eq_zero_of_natDegree_lt h, zero_mul, mul_zero]
    | inr ha =>
      

Proof state:
case inr
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝³ : Semiring S
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Field K
p q : R[X]
r : R
n a b : ℕ
e : a + b = n
ha : a ≤ natDegree p
x✝ : natDegree q < b ∨ b ≤ natDegree q
⊢ coeff p a * coeff q b * r ^ (natDegree p + natDegree q - n) =
    coeff p a * r ^ (natDegree p - a) * (coeff q b * r ^ (natDegree q - b))

Next tactic:
cases lt_or_le (natDegree q) b with
      | inl h => simp only [coeff_eq_zero_of_natDegree_lt h, zero_mul, mul_zero]
      | inr hb =>
        simp only [← e, mul_assoc, mul_comm (r ^ (_ - a)), ← pow_add]
        rw [add_comm (_ - _), tsub_add_tsub_comm ha hb]
/-- Multiplication and `scaleRoots` commute up to a power of `r`. The factor disappears if we
assume that the product of the leading coeffs does not vanish. See `Polynomial.mul_scaleRoots'`. -/
lemma mul_scaleRoots (p q : R[X]) (r : R) :
    r ^ (natDegree p + natDegree q - natDegree (p * q)) • (p * q).scaleRoots r =
      p.scaleRoots r * q.scaleRoots r := by
  ext n; simp only [coeff_scaleRoots, coeff_smul, smul_eq_mul]
  trans (∑ x in Finset.antidiagonal n, coeff p x.1 * coeff q x.2) *
    r ^ (natDegree p + natDegree q - n)
  · rw [← coeff_mul]
    cases lt_or_le (natDegree (p * q)) n with
    | inl h => simp only [coeff_eq_zero_of_natDegree_lt h, zero_mul, mul_zero]
    | inr h =>
      rw [mul_comm, mul_assoc, ← pow_add, add_comm, tsub_add_tsub_cancel natDegree_mul_le h]
  · rw [coeff_mul, Finset.sum_mul]
    apply Finset.sum_congr rfl
    simp only [Finset.mem_antidiagonal, coeff_scaleRoots, Prod.forall]
    intros a b e
    cases lt_or_le (natDegree p) a with
    | inl h => simp only [coeff_eq_zero_of_natDegree_lt h, zero_mul, mul_zero]
    | inr ha =>
      cases lt_or_le (natDegree q) b with
      

Proof state:
case inr.inl
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝³ : Semiring S
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Field K
p q : R[X]
r : R
n a b : ℕ
e : a + b = n
ha : a ≤ natDegree p
h : natDegree q < b
⊢ coeff p a * coeff q b * r ^ (natDegree p + natDegree q - n) =
    coeff p a * r ^ (natDegree p - a) * (coeff q b * r ^ (natDegree q - b))

Next tactic:
| inl h => simp only [coeff_eq_zero_of_natDegree_lt h, zero_mul, mul_zero]
/-- Multiplication and `scaleRoots` commute up to a power of `r`. The factor disappears if we
assume that the product of the leading coeffs does not vanish. See `Polynomial.mul_scaleRoots'`. -/
lemma mul_scaleRoots (p q : R[X]) (r : R) :
    r ^ (natDegree p + natDegree q - natDegree (p * q)) • (p * q).scaleRoots r =
      p.scaleRoots r * q.scaleRoots r := by
  ext n; simp only [coeff_scaleRoots, coeff_smul, smul_eq_mul]
  trans (∑ x in Finset.antidiagonal n, coeff p x.1 * coeff q x.2) *
    r ^ (natDegree p + natDegree q - n)
  · rw [← coeff_mul]
    cases lt_or_le (natDegree (p * q)) n with
    | inl h => simp only [coeff_eq_zero_of_natDegree_lt h, zero_mul, mul_zero]
    | inr h =>
      rw [mul_comm, mul_assoc, ← pow_add, add_comm, tsub_add_tsub_cancel natDegree_mul_le h]
  · rw [coeff_mul, Finset.sum_mul]
    apply Finset.sum_congr rfl
    simp only [Finset.mem_antidiagonal, coeff_scaleRoots, Prod.forall]
    intros a b e
    cases lt_or_le (natDegree p) a with
    | inl h => simp only [coeff_eq_zero_of_natDegree_lt h, zero_mul, mul_zero]
    | inr ha =>
      cases lt_or_le (natDegree q) b with
      | inl h => 

Proof state:
case inr.inl
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝³ : Semiring S
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Field K
p q : R[X]
r : R
n a b : ℕ
e : a + b = n
ha : a ≤ natDegree p
h : natDegree q < b
⊢ coeff p a * coeff q b * r ^ (natDegree p + natDegree q - n) =
    coeff p a * r ^ (natDegree p - a) * (coeff q b * r ^ (natDegree q - b))

Next tactic:
simp only [coeff_eq_zero_of_natDegree_lt h, zero_mul, mul_zero]
/-- Multiplication and `scaleRoots` commute up to a power of `r`. The factor disappears if we
assume that the product of the leading coeffs does not vanish. See `Polynomial.mul_scaleRoots'`. -/
lemma mul_scaleRoots (p q : R[X]) (r : R) :
    r ^ (natDegree p + natDegree q - natDegree (p * q)) • (p * q).scaleRoots r =
      p.scaleRoots r * q.scaleRoots r := by
  ext n; simp only [coeff_scaleRoots, coeff_smul, smul_eq_mul]
  trans (∑ x in Finset.antidiagonal n, coeff p x.1 * coeff q x.2) *
    r ^ (natDegree p + natDegree q - n)
  · rw [← coeff_mul]
    cases lt_or_le (natDegree (p * q)) n with
    | inl h => simp only [coeff_eq_zero_of_natDegree_lt h, zero_mul, mul_zero]
    | inr h =>
      rw [mul_comm, mul_assoc, ← pow_add, add_comm, tsub_add_tsub_cancel natDegree_mul_le h]
  · rw [coeff_mul, Finset.sum_mul]
    apply Finset.sum_congr rfl
    simp only [Finset.mem_antidiagonal, coeff_scaleRoots, Prod.forall]
    intros a b e
    cases lt_or_le (natDegree p) a with
    | inl h => simp only [coeff_eq_zero_of_natDegree_lt h, zero_mul, mul_zero]
    | inr ha =>
      cases lt_or_le (natDegree q) b with
      | inl h => simp only [coeff_eq_zero_of_natDegree_lt h, zero_mul, mul_zero]
      

Proof state:
case inr.inr
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝³ : Semiring S
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Field K
p q : R[X]
r : R
n a b : ℕ
e : a + b = n
ha : a ≤ natDegree p
hb : b ≤ natDegree q
⊢ coeff p a * coeff q b * r ^ (natDegree p + natDegree q - n) =
    coeff p a * r ^ (natDegree p - a) * (coeff q b * r ^ (natDegree q - b))

Next tactic:
| inr hb =>
        simp only [← e, mul_assoc, mul_comm (r ^ (_ - a)), ← pow_add]
        rw [add_comm (_ - _), tsub_add_tsub_comm ha hb]
/-- Multiplication and `scaleRoots` commute up to a power of `r`. The factor disappears if we
assume that the product of the leading coeffs does not vanish. See `Polynomial.mul_scaleRoots'`. -/
lemma mul_scaleRoots (p q : R[X]) (r : R) :
    r ^ (natDegree p + natDegree q - natDegree (p * q)) • (p * q).scaleRoots r =
      p.scaleRoots r * q.scaleRoots r := by
  ext n; simp only [coeff_scaleRoots, coeff_smul, smul_eq_mul]
  trans (∑ x in Finset.antidiagonal n, coeff p x.1 * coeff q x.2) *
    r ^ (natDegree p + natDegree q - n)
  · rw [← coeff_mul]
    cases lt_or_le (natDegree (p * q)) n with
    | inl h => simp only [coeff_eq_zero_of_natDegree_lt h, zero_mul, mul_zero]
    | inr h =>
      rw [mul_comm, mul_assoc, ← pow_add, add_comm, tsub_add_tsub_cancel natDegree_mul_le h]
  · rw [coeff_mul, Finset.sum_mul]
    apply Finset.sum_congr rfl
    simp only [Finset.mem_antidiagonal, coeff_scaleRoots, Prod.forall]
    intros a b e
    cases lt_or_le (natDegree p) a with
    | inl h => simp only [coeff_eq_zero_of_natDegree_lt h, zero_mul, mul_zero]
    | inr ha =>
      cases lt_or_le (natDegree q) b with
      | inl h => simp only [coeff_eq_zero_of_natDegree_lt h, zero_mul, mul_zero]
      | inr hb =>
        

Proof state:
case inr.inr
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝³ : Semiring S
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Field K
p q : R[X]
r : R
n a b : ℕ
e : a + b = n
ha : a ≤ natDegree p
hb : b ≤ natDegree q
⊢ coeff p a * coeff q b * r ^ (natDegree p + natDegree q - n) =
    coeff p a * r ^ (natDegree p - a) * (coeff q b * r ^ (natDegree q - b))

Next tactic:
simp only [← e, mul_assoc, mul_comm (r ^ (_ - a)), ← pow_add]
/-- Multiplication and `scaleRoots` commute up to a power of `r`. The factor disappears if we
assume that the product of the leading coeffs does not vanish. See `Polynomial.mul_scaleRoots'`. -/
lemma mul_scaleRoots (p q : R[X]) (r : R) :
    r ^ (natDegree p + natDegree q - natDegree (p * q)) • (p * q).scaleRoots r =
      p.scaleRoots r * q.scaleRoots r := by
  ext n; simp only [coeff_scaleRoots, coeff_smul, smul_eq_mul]
  trans (∑ x in Finset.antidiagonal n, coeff p x.1 * coeff q x.2) *
    r ^ (natDegree p + natDegree q - n)
  · rw [← coeff_mul]
    cases lt_or_le (natDegree (p * q)) n with
    | inl h => simp only [coeff_eq_zero_of_natDegree_lt h, zero_mul, mul_zero]
    | inr h =>
      rw [mul_comm, mul_assoc, ← pow_add, add_comm, tsub_add_tsub_cancel natDegree_mul_le h]
  · rw [coeff_mul, Finset.sum_mul]
    apply Finset.sum_congr rfl
    simp only [Finset.mem_antidiagonal, coeff_scaleRoots, Prod.forall]
    intros a b e
    cases lt_or_le (natDegree p) a with
    | inl h => simp only [coeff_eq_zero_of_natDegree_lt h, zero_mul, mul_zero]
    | inr ha =>
      cases lt_or_le (natDegree q) b with
      | inl h => simp only [coeff_eq_zero_of_natDegree_lt h, zero_mul, mul_zero]
      | inr hb =>
        simp only [← e, mul_assoc, mul_comm (r ^ (_ - a)), ← pow_add]
        

Proof state:
case inr.inr
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝³ : Semiring S
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Field K
p q : R[X]
r : R
n a b : ℕ
e : a + b = n
ha : a ≤ natDegree p
hb : b ≤ natDegree q
⊢ coeff p a * (coeff q b * r ^ (natDegree p + natDegree q - (a + b))) =
    coeff p a * (coeff q b * r ^ (natDegree q - b + (natDegree p - a)))

Next tactic:
rw [add_comm (_ - _), tsub_add_tsub_comm ha hb]
lemma mul_scaleRoots' (p q : R[X]) (r : R) (h : leadingCoeff p * leadingCoeff q ≠ 0) :
    (p * q).scaleRoots r = p.scaleRoots r * q.scaleRoots r := by
  

Proof state:
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝³ : Semiring S
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Field K
p q : R[X]
r : R
h : leadingCoeff p * leadingCoeff q ≠ 0
⊢ scaleRoots (p * q) r = scaleRoots p r * scaleRoots q r

Next tactic:
rw [← mul_scaleRoots, natDegree_mul' h, tsub_self, pow_zero, one_smul]
lemma mul_scaleRoots_of_noZeroDivisors (p q : R[X]) (r : R) [NoZeroDivisors R] :
    (p * q).scaleRoots r = p.scaleRoots r * q.scaleRoots r := by
  

Proof state:
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝⁴ : Semiring S
inst✝³ : CommSemiring R
inst✝² : Semiring A
inst✝¹ : Field K
p q : R[X]
r : R
inst✝ : NoZeroDivisors R
⊢ scaleRoots (p * q) r = scaleRoots p r * scaleRoots q r

Next tactic:
by_cases hp : p = 0
lemma mul_scaleRoots_of_noZeroDivisors (p q : R[X]) (r : R) [NoZeroDivisors R] :
    (p * q).scaleRoots r = p.scaleRoots r * q.scaleRoots r := by
  by_cases hp : p = 0; · 

Proof state:
case pos
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝⁴ : Semiring S
inst✝³ : CommSemiring R
inst✝² : Semiring A
inst✝¹ : Field K
p q : R[X]
r : R
inst✝ : NoZeroDivisors R
hp : p = 0
⊢ scaleRoots (p * q) r = scaleRoots p r * scaleRoots q r

Next tactic:
simp [hp]
lemma mul_scaleRoots_of_noZeroDivisors (p q : R[X]) (r : R) [NoZeroDivisors R] :
    (p * q).scaleRoots r = p.scaleRoots r * q.scaleRoots r := by
  by_cases hp : p = 0; · simp [hp]
  

Proof state:
case neg
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝⁴ : Semiring S
inst✝³ : CommSemiring R
inst✝² : Semiring A
inst✝¹ : Field K
p q : R[X]
r : R
inst✝ : NoZeroDivisors R
hp : ¬p = 0
⊢ scaleRoots (p * q) r = scaleRoots p r * scaleRoots q r

Next tactic:
by_cases hq : q = 0
lemma mul_scaleRoots_of_noZeroDivisors (p q : R[X]) (r : R) [NoZeroDivisors R] :
    (p * q).scaleRoots r = p.scaleRoots r * q.scaleRoots r := by
  by_cases hp : p = 0; · simp [hp]
  by_cases hq : q = 0; · 

Proof state:
case pos
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝⁴ : Semiring S
inst✝³ : CommSemiring R
inst✝² : Semiring A
inst✝¹ : Field K
p q : R[X]
r : R
inst✝ : NoZeroDivisors R
hp : ¬p = 0
hq : q = 0
⊢ scaleRoots (p * q) r = scaleRoots p r * scaleRoots q r

Next tactic:
simp [hq]
lemma mul_scaleRoots_of_noZeroDivisors (p q : R[X]) (r : R) [NoZeroDivisors R] :
    (p * q).scaleRoots r = p.scaleRoots r * q.scaleRoots r := by
  by_cases hp : p = 0; · simp [hp]
  by_cases hq : q = 0; · simp [hq]
  

Proof state:
case neg
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝⁴ : Semiring S
inst✝³ : CommSemiring R
inst✝² : Semiring A
inst✝¹ : Field K
p q : R[X]
r : R
inst✝ : NoZeroDivisors R
hp : ¬p = 0
hq : ¬q = 0
⊢ scaleRoots (p * q) r = scaleRoots p r * scaleRoots q r

Next tactic:
apply mul_scaleRoots'
lemma mul_scaleRoots_of_noZeroDivisors (p q : R[X]) (r : R) [NoZeroDivisors R] :
    (p * q).scaleRoots r = p.scaleRoots r * q.scaleRoots r := by
  by_cases hp : p = 0; · simp [hp]
  by_cases hq : q = 0; · simp [hq]
  apply mul_scaleRoots'
  

Proof state:
case neg.h
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝⁴ : Semiring S
inst✝³ : CommSemiring R
inst✝² : Semiring A
inst✝¹ : Field K
p q : R[X]
r : R
inst✝ : NoZeroDivisors R
hp : ¬p = 0
hq : ¬q = 0
⊢ leadingCoeff p * leadingCoeff q ≠ 0

Next tactic:
simp only [ne_eq, mul_eq_zero, leadingCoeff_eq_zero, hp, hq, or_self, not_false_eq_true]
lemma add_scaleRoots_of_natDegree_eq (p q : R[X]) (r : R) (h : natDegree p = natDegree q) :
    r ^ (natDegree p - natDegree (p + q)) • (p + q).scaleRoots r =
      p.scaleRoots r + q.scaleRoots r := by
  

Proof state:
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝³ : Semiring S
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Field K
p q : R[X]
r : R
h : natDegree p = natDegree q
⊢ r ^ (natDegree p - natDegree (p + q)) • scaleRoots (p + q) r = scaleRoots p r + scaleRoots q r

Next tactic:
ext n