l3lab/ntp-mathlib huggingface dataset:
theorem scaleRoots_eval₂_mul_of_commute {p : S[X]} (f : S →+* A) (a : A) (s : S)
    (hsa : Commute (f s) a) (hf : ∀ s₁ s₂, Commute (f s₁) (f s₂)) :
    eval₂ f (f s * a) (scaleRoots p s) = f s ^ p.natDegree * eval₂ f a p := by
   calc
    _ = (scaleRoots p s).support.sum fun i =>
          f (coeff p i * s ^ (p.natDegree - i)) * (f s * a) ^ i :=
      by simp [eval₂_eq_sum, sum_def]
    _ = p.support.sum fun i => f (coeff p i * s ^ (p.natDegree - i)) * (f s * a) ^ i :=
      (Finset.sum_subset (support_scaleRoots_le p s) fun i _hi hi' => by
        let this : coeff p i * s ^ (p.natDegree - i) = 0 := by simpa using hi'
        simp [this])
    _ = p.support.sum fun i : ℕ => f (p.coeff i) * f s ^ (p.natDegree - i + i) * a ^ i :=
      (Finset.sum_congr rfl fun i _hi => by
        simp_rw [f.map_mul, f.map_pow, pow_add, hsa.mul_pow, mul_assoc])
    _ = p.support.sum fun i : ℕ => f s ^ p.natDegree * (f (p.coeff i) * a ^ i) :=
      (Finset.sum_congr rfl fun i hi => by
        rw [mul_assoc, ← map_pow, (hf _ _).left_comm, map_pow, tsub_add_cancel_of_le]
        

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 : S[X]
f : S →+* A
a : A
s : S
hsa : Commute (f s) a
hf : ∀ (s₁ s₂ : S), Commute (f s₁) (f s₂)
i : ℕ
hi : i ∈ support p
⊢ i ≤ natDegree p

Next tactic:
exact le_natDegree_of_ne_zero (Polynomial.mem_support_iff.mp hi)
theorem scaleRoots_eval₂_mul_of_commute {p : S[X]} (f : S →+* A) (a : A) (s : S)
    (hsa : Commute (f s) a) (hf : ∀ s₁ s₂, Commute (f s₁) (f s₂)) :
    eval₂ f (f s * a) (scaleRoots p s) = f s ^ p.natDegree * eval₂ f a p := by
   calc
    _ = (scaleRoots p s).support.sum fun i =>
          f (coeff p i * s ^ (p.natDegree - i)) * (f s * a) ^ i :=
      by simp [eval₂_eq_sum, sum_def]
    _ = p.support.sum fun i => f (coeff p i * s ^ (p.natDegree - i)) * (f s * a) ^ i :=
      (Finset.sum_subset (support_scaleRoots_le p s) fun i _hi hi' => by
        let this : coeff p i * s ^ (p.natDegree - i) = 0 := by simpa using hi'
        simp [this])
    _ = p.support.sum fun i : ℕ => f (p.coeff i) * f s ^ (p.natDegree - i + i) * a ^ i :=
      (Finset.sum_congr rfl fun i _hi => by
        simp_rw [f.map_mul, f.map_pow, pow_add, hsa.mul_pow, mul_assoc])
    _ = p.support.sum fun i : ℕ => f s ^ p.natDegree * (f (p.coeff i) * a ^ i) :=
      (Finset.sum_congr rfl fun i hi => by
        rw [mul_assoc, ← map_pow, (hf _ _).left_comm, map_pow, tsub_add_cancel_of_le]
        exact le_natDegree_of_ne_zero (Polynomial.mem_support_iff.mp hi))
    _ = f s ^ p.natDegree * p.support.sum fun i : ℕ => f (p.coeff i) * a ^ i := Finset.mul_sum.symm
    _ = f s ^ p.natDegree * eval₂ f a p := 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 : S[X]
f : S →+* A
a : A
s : S
hsa : Commute (f s) a
hf : ∀ (s₁ s₂ : S), Commute (f s₁) (f s₂)
⊢ f s ^ natDegree p * ∑ i in support p, f (coeff p i) * a ^ i = f s ^ natDegree p * eval₂ f a p

Next tactic:
simp [eval₂_eq_sum, sum_def]
theorem scaleRoots_eval₂_eq_zero {p : S[X]} (f : S →+* R) {r : R} {s : S} (hr : eval₂ f r p = 0) :
    eval₂ f (f s * r) (scaleRoots p s) = 0 := 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 : S[X]
f : S →+* R
r : R
s : S
hr : eval₂ f r p = 0
⊢ eval₂ f (f s * r) (scaleRoots p s) = 0

Next tactic:
rw [scaleRoots_eval₂_mul, hr, mul_zero]
theorem scaleRoots_aeval_eq_zero [Algebra R A] {p : R[X]} {a : A} {r : R} (ha : aeval a p = 0) :
    aeval (algebraMap R A r * a) (scaleRoots p r) = 0 := 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
inst✝ : Algebra R A
p : R[X]
a : A
r : R
ha : (aeval a) p = 0
⊢ (aeval ((algebraMap R A) r * a)) (scaleRoots p r) = 0

Next tactic:
rw [aeval_def, scaleRoots_eval₂_mul_of_commute, ← aeval_def, ha, mul_zero]
theorem scaleRoots_aeval_eq_zero [Algebra R A] {p : R[X]} {a : A} {r : R} (ha : aeval a p = 0) :
    aeval (algebraMap R A r * a) (scaleRoots p r) = 0 := by
  rw [aeval_def, scaleRoots_eval₂_mul_of_commute, ← aeval_def, ha, mul_zero]
  · 

Proof state:
case hsa
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
inst✝ : Algebra R A
p : R[X]
a : A
r : R
ha : (aeval a) p = 0
⊢ Commute ((algebraMap R A) r) a

Next tactic:
apply Algebra.commutes
theorem scaleRoots_aeval_eq_zero [Algebra R A] {p : R[X]} {a : A} {r : R} (ha : aeval a p = 0) :
    aeval (algebraMap R A r * a) (scaleRoots p r) = 0 := by
  rw [aeval_def, scaleRoots_eval₂_mul_of_commute, ← aeval_def, ha, mul_zero]
  · apply Algebra.commutes
  · 

Proof state:
case hf
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
inst✝ : Algebra R A
p : R[X]
a : A
r : R
ha : (aeval a) p = 0
⊢ ∀ (s₁ s₂ : R), Commute ((algebraMap R A) s₁) ((algebraMap R A) s₂)

Next tactic:
intros
theorem scaleRoots_aeval_eq_zero [Algebra R A] {p : R[X]} {a : A} {r : R} (ha : aeval a p = 0) :
    aeval (algebraMap R A r * a) (scaleRoots p r) = 0 := by
  rw [aeval_def, scaleRoots_eval₂_mul_of_commute, ← aeval_def, ha, mul_zero]
  · apply Algebra.commutes
  · intros; 

Proof state:
case hf
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
inst✝ : Algebra R A
p : R[X]
a : A
r : R
ha : (aeval a) p = 0
s₁✝ s₂✝ : R
⊢ Commute ((algebraMap R A) s₁✝) ((algebraMap R A) s₂✝)

Next tactic:
rw [Commute, SemiconjBy, ← map_mul, ← map_mul, mul_comm]
theorem scaleRoots_eval₂_eq_zero_of_eval₂_div_eq_zero {p : S[X]} {f : S →+* K}
    (hf : Function.Injective f) {r s : S} (hr : eval₂ f (f r / f s) p = 0)
    (hs : s ∈ nonZeroDivisors S) : eval₂ f (f r) (scaleRoots p s) = 0 := 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 : S[X]
f : S →+* K
hf : Function.Injective ⇑f
r s : S
hr : eval₂ f (f r / f s) p = 0
hs : s ∈ nonZeroDivisors S
⊢ eval₂ f (f r) (scaleRoots p s) = 0

Next tactic:
nontriviality S using Subsingleton.eq_zero
theorem scaleRoots_eval₂_eq_zero_of_eval₂_div_eq_zero {p : S[X]} {f : S →+* K}
    (hf : Function.Injective f) {r s : S} (hr : eval₂ f (f r / f s) p = 0)
    (hs : s ∈ nonZeroDivisors S) : eval₂ f (f r) (scaleRoots p s) = 0 := by
  nontriviality S using Subsingleton.eq_zero
  

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 : S[X]
f : S →+* K
hf : Function.Injective ⇑f
r s : S
hr : eval₂ f (f r / f s) p = 0
hs : s ∈ nonZeroDivisors S
✝ : Nontrivial S
⊢ eval₂ f (f r) (scaleRoots p s) = 0

Next tactic:
convert @scaleRoots_eval₂_eq_zero _ _ _ _ p f _ s hr
theorem scaleRoots_eval₂_eq_zero_of_eval₂_div_eq_zero {p : S[X]} {f : S →+* K}
    (hf : Function.Injective f) {r s : S} (hr : eval₂ f (f r / f s) p = 0)
    (hs : s ∈ nonZeroDivisors S) : eval₂ f (f r) (scaleRoots p s) = 0 := by
  nontriviality S using Subsingleton.eq_zero
  convert @scaleRoots_eval₂_eq_zero _ _ _ _ p f _ s hr
  

Proof state:
case h.e'_2.h.e'_6
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 : S[X]
f : S →+* K
hf : Function.Injective ⇑f
r s : S
hr : eval₂ f (f r / f s) p = 0
hs : s ∈ nonZeroDivisors S
✝ : Nontrivial S
⊢ f r = f s * (f r / f s)

Next tactic:
rw [← mul_div_assoc, mul_comm, mul_div_cancel]
theorem scaleRoots_eval₂_eq_zero_of_eval₂_div_eq_zero {p : S[X]} {f : S →+* K}
    (hf : Function.Injective f) {r s : S} (hr : eval₂ f (f r / f s) p = 0)
    (hs : s ∈ nonZeroDivisors S) : eval₂ f (f r) (scaleRoots p s) = 0 := by
  nontriviality S using Subsingleton.eq_zero
  convert @scaleRoots_eval₂_eq_zero _ _ _ _ p f _ s hr
  rw [← mul_div_assoc, mul_comm, mul_div_cancel]
  

Proof state:
case h.e'_2.h.e'_6.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 : S[X]
f : S →+* K
hf : Function.Injective ⇑f
r s : S
hr : eval₂ f (f r / f s) p = 0
hs : s ∈ nonZeroDivisors S
✝ : Nontrivial S
⊢ f s ≠ 0

Next tactic:
exact map_ne_zero_of_mem_nonZeroDivisors _ hf hs
@[simp]
lemma scaleRoots_mul (p : R[X]) (r s) :
    p.scaleRoots (r * s) = (p.scaleRoots r).scaleRoots s := 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 : R[X]
r s : R
⊢ scaleRoots p (r * s) = scaleRoots (scaleRoots p r) s

Next tactic:
ext
@[simp]
lemma scaleRoots_mul (p : R[X]) (r s) :
    p.scaleRoots (r * s) = (p.scaleRoots r).scaleRoots s := by
  ext; 

Proof state:
case a
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 : R[X]
r s : R
n✝ : ℕ
⊢ coeff (scaleRoots p (r * s)) n✝ = coeff (scaleRoots (scaleRoots p r) s) n✝

Next tactic:
simp [mul_pow, mul_assoc]
/-- 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
  

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
⊢ r ^ (natDegree p + natDegree q - natDegree (p * q)) • scaleRoots (p * q) r = scaleRoots p r * scaleRoots q r

Next tactic:
ext n
/-- 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; 

Proof state:
case a
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 : ℕ
⊢ coeff (r ^ (natDegree p + natDegree q - natDegree (p * q)) • scaleRoots (p * q) r) n =
    coeff (scaleRoots p r * scaleRoots q r) n

Next tactic:
simp only [coeff_scaleRoots, coeff_smul, smul_eq_mul]
/-- 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]
  

Proof state:
case a
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 : ℕ
⊢ r ^ (natDegree p + natDegree q - natDegree (p * q)) * (coeff (p * q) n * r ^ (natDegree (p * q) - n)) =
    coeff (scaleRoots p r * scaleRoots q r) n

Next tactic:
trans (∑ x in Finset.antidiagonal n, coeff p x.1 * coeff q x.2) *
    r ^ (natDegree p + natDegree q - n)
/-- 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)
  · 

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 : ℕ
⊢ r ^ (natDegree p + natDegree q - natDegree (p * q)) * (coeff (p * q) n * r ^ (natDegree (p * q) - n)) =
    (∑ x in Finset.antidiagonal n, coeff p x.1 * coeff q x.2) * r ^ (natDegree p + natDegree q - n)

Next tactic:
rw [← coeff_mul]
/-- 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]
    

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 : ℕ
⊢ r ^ (natDegree p + natDegree q - natDegree (p * q)) * (coeff (p * q) n * r ^ (natDegree (p * q) - n)) =
    coeff (p * q) n * r ^ (natDegree p + natDegree q - n)

Next tactic:
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]
/-- 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]
    

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 : ℕ
x✝ : natDegree (p * q) < n ∨ n ≤ natDegree (p * q)
⊢ r ^ (natDegree p + natDegree q - natDegree (p * q)) * (coeff (p * q) n * r ^ (natDegree (p * q) - n)) =
    coeff (p * q) n * r ^ (natDegree p + natDegree q - n)

Next tactic:
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]
/-- 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
    

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 : ℕ
h : natDegree (p * q) < n
⊢ r ^ (natDegree p + natDegree q - natDegree (p * q)) * (coeff (p * q) n * r ^ (natDegree (p * q) - n)) =
    coeff (p * q) n * r ^ (natDegree p + natDegree q - n)

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 => 

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 : ℕ
h : natDegree (p * q) < n
⊢ r ^ (natDegree p + natDegree q - natDegree (p * q)) * (coeff (p * q) n * r ^ (natDegree (p * q) - n)) =
    coeff (p * q) n * r ^ (natDegree p + natDegree q - n)

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]
    

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 : ℕ
h : n ≤ natDegree (p * q)
⊢ r ^ (natDegree p + natDegree q - natDegree (p * q)) * (coeff (p * q) n * r ^ (natDegree (p * q) - n)) =
    coeff (p * q) n * r ^ (natDegree p + natDegree q - n)

Next tactic:
| inr h =>
      rw [mul_comm, mul_assoc, ← pow_add, add_comm, tsub_add_tsub_cancel natDegree_mul_le h]
/-- 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 =>
      

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 : ℕ
h : n ≤ natDegree (p * q)
⊢ r ^ (natDegree p + natDegree q - natDegree (p * q)) * (coeff (p * q) n * r ^ (natDegree (p * q) - n)) =
    coeff (p * q) n * r ^ (natDegree p + natDegree q - n)

Next tactic:
rw [mul_comm, mul_assoc, ← pow_add, add_comm, tsub_add_tsub_cancel natDegree_mul_le h]
/-- 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]
  · 

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 : ℕ
⊢ (∑ x in Finset.antidiagonal n, coeff p x.1 * coeff q x.2) * r ^ (natDegree p + natDegree q - n) =
    coeff (scaleRoots p r * scaleRoots q r) n

Next tactic:
rw [coeff_mul, Finset.sum_mul]
/-- 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]
    

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 : ℕ
⊢ ∑ x in Finset.antidiagonal n, coeff p x.1 * coeff q x.2 * r ^ (natDegree p + natDegree q - n) =
    ∑ x in Finset.antidiagonal n, coeff (scaleRoots p r) x.1 * coeff (scaleRoots q r) x.2

Next tactic:
apply Finset.sum_congr rfl
/-- 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
    

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 : ℕ
⊢ ∀ x ∈ Finset.antidiagonal n,
    coeff p x.1 * coeff q x.2 * r ^ (natDegree p + natDegree q - n) =
      coeff (scaleRoots p r) x.1 * coeff (scaleRoots q r) x.2

Next tactic:
simp only [Finset.mem_antidiagonal, coeff_scaleRoots, Prod.forall]
/-- 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]
    

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 : ℕ),
    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:
intros a b e