l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem coeff_pow_mul_natDegree (p : R[X]) (n : ℕ) :
    (p ^ n).coeff (n * p.natDegree) = p.leadingCoeff ^ n := by
  induction' n with i hi
  · simp
  · rw [pow_succ', pow_succ', Nat.succ_mul]
    by_cases hp1 : p.leadingCoeff ^ i = 0
    · rw [hp1, zero_mul]
      by_cases hp2 : p ^ i = 0
      · rw [hp2, zero_mul, coeff_zero]
      · apply coeff_eq_zero_of_natDegree_lt
        

Proof state:
case neg.h
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p✝ q : R[X]
ι : Type u_1
p : R[X]
i : ℕ
hi : coeff (p ^ i) (i * natDegree p) = leadingCoeff p ^ i
hp1 : leadingCoeff p ^ i = 0
hp2 : ¬p ^ i = 0
⊢ natDegree (p ^ i * p) < i * natDegree p + natDegree p

Next tactic:
have h1 : (p ^ i).natDegree < i * p.natDegree := by
          refine lt_of_le_of_ne natDegree_pow_le fun h => hp2 ?_
          rw [← h, hp1] at hi
          exact leadingCoeff_eq_zero.mp hi
@[simp]
theorem coeff_pow_mul_natDegree (p : R[X]) (n : ℕ) :
    (p ^ n).coeff (n * p.natDegree) = p.leadingCoeff ^ n := by
  induction' n with i hi
  · simp
  · rw [pow_succ', pow_succ', Nat.succ_mul]
    by_cases hp1 : p.leadingCoeff ^ i = 0
    · rw [hp1, zero_mul]
      by_cases hp2 : p ^ i = 0
      · rw [hp2, zero_mul, coeff_zero]
      · apply coeff_eq_zero_of_natDegree_lt
        have h1 : (p ^ i).natDegree < i * p.natDegree := by
          

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p✝ q : R[X]
ι : Type u_1
p : R[X]
i : ℕ
hi : coeff (p ^ i) (i * natDegree p) = leadingCoeff p ^ i
hp1 : leadingCoeff p ^ i = 0
hp2 : ¬p ^ i = 0
⊢ natDegree (p ^ i) < i * natDegree p

Next tactic:
refine lt_of_le_of_ne natDegree_pow_le fun h => hp2 ?_
@[simp]
theorem coeff_pow_mul_natDegree (p : R[X]) (n : ℕ) :
    (p ^ n).coeff (n * p.natDegree) = p.leadingCoeff ^ n := by
  induction' n with i hi
  · simp
  · rw [pow_succ', pow_succ', Nat.succ_mul]
    by_cases hp1 : p.leadingCoeff ^ i = 0
    · rw [hp1, zero_mul]
      by_cases hp2 : p ^ i = 0
      · rw [hp2, zero_mul, coeff_zero]
      · apply coeff_eq_zero_of_natDegree_lt
        have h1 : (p ^ i).natDegree < i * p.natDegree := by
          refine lt_of_le_of_ne natDegree_pow_le fun h => hp2 ?_
          

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p✝ q : R[X]
ι : Type u_1
p : R[X]
i : ℕ
hi : coeff (p ^ i) (i * natDegree p) = leadingCoeff p ^ i
hp1 : leadingCoeff p ^ i = 0
hp2 : ¬p ^ i = 0
h : natDegree (p ^ i) = i * natDegree p
⊢ p ^ i = 0

Next tactic:
rw [← h, hp1] at hi
@[simp]
theorem coeff_pow_mul_natDegree (p : R[X]) (n : ℕ) :
    (p ^ n).coeff (n * p.natDegree) = p.leadingCoeff ^ n := by
  induction' n with i hi
  · simp
  · rw [pow_succ', pow_succ', Nat.succ_mul]
    by_cases hp1 : p.leadingCoeff ^ i = 0
    · rw [hp1, zero_mul]
      by_cases hp2 : p ^ i = 0
      · rw [hp2, zero_mul, coeff_zero]
      · apply coeff_eq_zero_of_natDegree_lt
        have h1 : (p ^ i).natDegree < i * p.natDegree := by
          refine lt_of_le_of_ne natDegree_pow_le fun h => hp2 ?_
          rw [← h, hp1] at hi
          

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p✝ q : R[X]
ι : Type u_1
p : R[X]
i : ℕ
hi : coeff (p ^ i) (natDegree (p ^ i)) = 0
hp1 : leadingCoeff p ^ i = 0
hp2 : ¬p ^ i = 0
h : natDegree (p ^ i) = i * natDegree p
⊢ p ^ i = 0

Next tactic:
exact leadingCoeff_eq_zero.mp hi
@[simp]
theorem coeff_pow_mul_natDegree (p : R[X]) (n : ℕ) :
    (p ^ n).coeff (n * p.natDegree) = p.leadingCoeff ^ n := by
  induction' n with i hi
  · simp
  · rw [pow_succ', pow_succ', Nat.succ_mul]
    by_cases hp1 : p.leadingCoeff ^ i = 0
    · rw [hp1, zero_mul]
      by_cases hp2 : p ^ i = 0
      · rw [hp2, zero_mul, coeff_zero]
      · apply coeff_eq_zero_of_natDegree_lt
        have h1 : (p ^ i).natDegree < i * p.natDegree := by
          refine lt_of_le_of_ne natDegree_pow_le fun h => hp2 ?_
          rw [← h, hp1] at hi
          exact leadingCoeff_eq_zero.mp hi
        

Proof state:
case neg.h
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p✝ q : R[X]
ι : Type u_1
p : R[X]
i : ℕ
hi : coeff (p ^ i) (i * natDegree p) = leadingCoeff p ^ i
hp1 : leadingCoeff p ^ i = 0
hp2 : ¬p ^ i = 0
h1 : natDegree (p ^ i) < i * natDegree p
⊢ natDegree (p ^ i * p) < i * natDegree p + natDegree p

Next tactic:
calc
          (p ^ i * p).natDegree ≤ (p ^ i).natDegree + p.natDegree := natDegree_mul_le
          _ < i * p.natDegree + p.natDegree := add_lt_add_right h1 _
@[simp]
theorem coeff_pow_mul_natDegree (p : R[X]) (n : ℕ) :
    (p ^ n).coeff (n * p.natDegree) = p.leadingCoeff ^ n := by
  induction' n with i hi
  · simp
  · rw [pow_succ', pow_succ', Nat.succ_mul]
    by_cases hp1 : p.leadingCoeff ^ i = 0
    · rw [hp1, zero_mul]
      by_cases hp2 : p ^ i = 0
      · rw [hp2, zero_mul, coeff_zero]
      · apply coeff_eq_zero_of_natDegree_lt
        have h1 : (p ^ i).natDegree < i * p.natDegree := by
          refine lt_of_le_of_ne natDegree_pow_le fun h => hp2 ?_
          rw [← h, hp1] at hi
          exact leadingCoeff_eq_zero.mp hi
        calc
          (p ^ i * p).natDegree ≤ (p ^ i).natDegree + p.natDegree := natDegree_mul_le
          _ < i * p.natDegree + p.natDegree := add_lt_add_right h1 _

    · 

Proof state:
case neg
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p✝ q : R[X]
ι : Type u_1
p : R[X]
i : ℕ
hi : coeff (p ^ i) (i * natDegree p) = leadingCoeff p ^ i
hp1 : ¬leadingCoeff p ^ i = 0
⊢ coeff (p ^ i * p) (i * natDegree p + natDegree p) = leadingCoeff p ^ i * leadingCoeff p

Next tactic:
rw [← natDegree_pow' hp1, ← leadingCoeff_pow' hp1]
@[simp]
theorem coeff_pow_mul_natDegree (p : R[X]) (n : ℕ) :
    (p ^ n).coeff (n * p.natDegree) = p.leadingCoeff ^ n := by
  induction' n with i hi
  · simp
  · rw [pow_succ', pow_succ', Nat.succ_mul]
    by_cases hp1 : p.leadingCoeff ^ i = 0
    · rw [hp1, zero_mul]
      by_cases hp2 : p ^ i = 0
      · rw [hp2, zero_mul, coeff_zero]
      · apply coeff_eq_zero_of_natDegree_lt
        have h1 : (p ^ i).natDegree < i * p.natDegree := by
          refine lt_of_le_of_ne natDegree_pow_le fun h => hp2 ?_
          rw [← h, hp1] at hi
          exact leadingCoeff_eq_zero.mp hi
        calc
          (p ^ i * p).natDegree ≤ (p ^ i).natDegree + p.natDegree := natDegree_mul_le
          _ < i * p.natDegree + p.natDegree := add_lt_add_right h1 _

    · rw [← natDegree_pow' hp1, ← leadingCoeff_pow' hp1]
      

Proof state:
case neg
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p✝ q : R[X]
ι : Type u_1
p : R[X]
i : ℕ
hi : coeff (p ^ i) (i * natDegree p) = leadingCoeff p ^ i
hp1 : ¬leadingCoeff p ^ i = 0
⊢ coeff (p ^ i * p) (natDegree (p ^ i) + natDegree p) = leadingCoeff (p ^ i) * leadingCoeff p

Next tactic:
exact coeff_mul_degree_add_degree _ _
theorem coeff_mul_add_eq_of_natDegree_le {df dg : ℕ} {g : R[X]}
    (hdf : natDegree f ≤ df) (hdg : natDegree g ≤ dg) :
    (f * g).coeff (df + dg) = f.coeff df * g.coeff dg := by
  

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
f : R[X]
df dg : ℕ
g : R[X]
hdf : natDegree f ≤ df
hdg : natDegree g ≤ dg
⊢ coeff (f * g) (df + dg) = coeff f df * coeff g dg

Next tactic:
rw [coeff_mul, Finset.sum_eq_single_of_mem (df, dg)]
theorem coeff_mul_add_eq_of_natDegree_le {df dg : ℕ} {g : R[X]}
    (hdf : natDegree f ≤ df) (hdg : natDegree g ≤ dg) :
    (f * g).coeff (df + dg) = f.coeff df * g.coeff dg := by
  rw [coeff_mul, Finset.sum_eq_single_of_mem (df, dg)]
  · 

Proof state:
case h
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
f : R[X]
df dg : ℕ
g : R[X]
hdf : natDegree f ≤ df
hdg : natDegree g ≤ dg
⊢ (df, dg) ∈ antidiagonal (df + dg)

Next tactic:
rw [mem_antidiagonal]
theorem coeff_mul_add_eq_of_natDegree_le {df dg : ℕ} {g : R[X]}
    (hdf : natDegree f ≤ df) (hdg : natDegree g ≤ dg) :
    (f * g).coeff (df + dg) = f.coeff df * g.coeff dg := by
  rw [coeff_mul, Finset.sum_eq_single_of_mem (df, dg)]
  · rw [mem_antidiagonal]
  

Proof state:
case h₀
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
f : R[X]
df dg : ℕ
g : R[X]
hdf : natDegree f ≤ df
hdg : natDegree g ≤ dg
⊢ ∀ b ∈ antidiagonal (df + dg), b ≠ (df, dg) → coeff f b.1 * coeff g b.2 = 0

Next tactic:
rintro ⟨df', dg'⟩ hmem hne
theorem coeff_mul_add_eq_of_natDegree_le {df dg : ℕ} {g : R[X]}
    (hdf : natDegree f ≤ df) (hdg : natDegree g ≤ dg) :
    (f * g).coeff (df + dg) = f.coeff df * g.coeff dg := by
  rw [coeff_mul, Finset.sum_eq_single_of_mem (df, dg)]
  · rw [mem_antidiagonal]
  rintro ⟨df', dg'⟩ hmem hne
  

Proof state:
case h₀.mk
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
f : R[X]
df dg : ℕ
g : R[X]
hdf : natDegree f ≤ df
hdg : natDegree g ≤ dg
df' dg' : ℕ
hmem : (df', dg') ∈ antidiagonal (df + dg)
hne : (df', dg') ≠ (df, dg)
⊢ coeff f (df', dg').1 * coeff g (df', dg').2 = 0

Next tactic:
obtain h | hdf' := lt_or_le df df'
theorem coeff_mul_add_eq_of_natDegree_le {df dg : ℕ} {g : R[X]}
    (hdf : natDegree f ≤ df) (hdg : natDegree g ≤ dg) :
    (f * g).coeff (df + dg) = f.coeff df * g.coeff dg := by
  rw [coeff_mul, Finset.sum_eq_single_of_mem (df, dg)]
  · rw [mem_antidiagonal]
  rintro ⟨df', dg'⟩ hmem hne
  obtain h | hdf' := lt_or_le df df'
  · 

Proof state:
case h₀.mk.inl
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
f : R[X]
df dg : ℕ
g : R[X]
hdf : natDegree f ≤ df
hdg : natDegree g ≤ dg
df' dg' : ℕ
hmem : (df', dg') ∈ antidiagonal (df + dg)
hne : (df', dg') ≠ (df, dg)
h : df < df'
⊢ coeff f (df', dg').1 * coeff g (df', dg').2 = 0

Next tactic:
rw [coeff_eq_zero_of_natDegree_lt (hdf.trans_lt h), zero_mul]
theorem coeff_mul_add_eq_of_natDegree_le {df dg : ℕ} {g : R[X]}
    (hdf : natDegree f ≤ df) (hdg : natDegree g ≤ dg) :
    (f * g).coeff (df + dg) = f.coeff df * g.coeff dg := by
  rw [coeff_mul, Finset.sum_eq_single_of_mem (df, dg)]
  · rw [mem_antidiagonal]
  rintro ⟨df', dg'⟩ hmem hne
  obtain h | hdf' := lt_or_le df df'
  · rw [coeff_eq_zero_of_natDegree_lt (hdf.trans_lt h), zero_mul]
  

Proof state:
case h₀.mk.inr
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
f : R[X]
df dg : ℕ
g : R[X]
hdf : natDegree f ≤ df
hdg : natDegree g ≤ dg
df' dg' : ℕ
hmem : (df', dg') ∈ antidiagonal (df + dg)
hne : (df', dg') ≠ (df, dg)
hdf' : df' ≤ df
⊢ coeff f (df', dg').1 * coeff g (df', dg').2 = 0

Next tactic:
obtain h | hdg' := lt_or_le dg dg'
theorem coeff_mul_add_eq_of_natDegree_le {df dg : ℕ} {g : R[X]}
    (hdf : natDegree f ≤ df) (hdg : natDegree g ≤ dg) :
    (f * g).coeff (df + dg) = f.coeff df * g.coeff dg := by
  rw [coeff_mul, Finset.sum_eq_single_of_mem (df, dg)]
  · rw [mem_antidiagonal]
  rintro ⟨df', dg'⟩ hmem hne
  obtain h | hdf' := lt_or_le df df'
  · rw [coeff_eq_zero_of_natDegree_lt (hdf.trans_lt h), zero_mul]
  obtain h | hdg' := lt_or_le dg dg'
  · 

Proof state:
case h₀.mk.inr.inl
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
f : R[X]
df dg : ℕ
g : R[X]
hdf : natDegree f ≤ df
hdg : natDegree g ≤ dg
df' dg' : ℕ
hmem : (df', dg') ∈ antidiagonal (df + dg)
hne : (df', dg') ≠ (df, dg)
hdf' : df' ≤ df
h : dg < dg'
⊢ coeff f (df', dg').1 * coeff g (df', dg').2 = 0

Next tactic:
rw [coeff_eq_zero_of_natDegree_lt (hdg.trans_lt h), mul_zero]
theorem coeff_mul_add_eq_of_natDegree_le {df dg : ℕ} {g : R[X]}
    (hdf : natDegree f ≤ df) (hdg : natDegree g ≤ dg) :
    (f * g).coeff (df + dg) = f.coeff df * g.coeff dg := by
  rw [coeff_mul, Finset.sum_eq_single_of_mem (df, dg)]
  · rw [mem_antidiagonal]
  rintro ⟨df', dg'⟩ hmem hne
  obtain h | hdf' := lt_or_le df df'
  · rw [coeff_eq_zero_of_natDegree_lt (hdf.trans_lt h), zero_mul]
  obtain h | hdg' := lt_or_le dg dg'
  · rw [coeff_eq_zero_of_natDegree_lt (hdg.trans_lt h), mul_zero]
  

Proof state:
case h₀.mk.inr.inr
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
f : R[X]
df dg : ℕ
g : R[X]
hdf : natDegree f ≤ df
hdg : natDegree g ≤ dg
df' dg' : ℕ
hmem : (df', dg') ∈ antidiagonal (df + dg)
hne : (df', dg') ≠ (df, dg)
hdf' : df' ≤ df
hdg' : dg' ≤ dg
⊢ coeff f (df', dg').1 * coeff g (df', dg').2 = 0

Next tactic:
obtain ⟨rfl, rfl⟩ :=
    (add_eq_add_iff_eq_and_eq hdf' hdg').mp (mem_antidiagonal.1 hmem)
theorem coeff_mul_add_eq_of_natDegree_le {df dg : ℕ} {g : R[X]}
    (hdf : natDegree f ≤ df) (hdg : natDegree g ≤ dg) :
    (f * g).coeff (df + dg) = f.coeff df * g.coeff dg := by
  rw [coeff_mul, Finset.sum_eq_single_of_mem (df, dg)]
  · rw [mem_antidiagonal]
  rintro ⟨df', dg'⟩ hmem hne
  obtain h | hdf' := lt_or_le df df'
  · rw [coeff_eq_zero_of_natDegree_lt (hdf.trans_lt h), zero_mul]
  obtain h | hdg' := lt_or_le dg dg'
  · rw [coeff_eq_zero_of_natDegree_lt (hdg.trans_lt h), mul_zero]
  obtain ⟨rfl, rfl⟩ :=
    (add_eq_add_iff_eq_and_eq hdf' hdg').mp (mem_antidiagonal.1 hmem)
  

Proof state:
case h₀.mk.inr.inr.intro
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
f g : R[X]
df' dg' : ℕ
hdf : natDegree f ≤ df'
hdf' : df' ≤ df'
hdg : natDegree g ≤ dg'
hdg' : dg' ≤ dg'
hmem : (df', dg') ∈ antidiagonal (df' + dg')
hne : (df', dg') ≠ (df', dg')
⊢ coeff f (df', dg').1 * coeff g (df', dg').2 = 0

Next tactic:
exact (hne rfl).elim
theorem zero_le_degree_iff : 0 ≤ degree p ↔ p ≠ 0 := by
  

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
⊢ 0 ≤ degree p ↔ p ≠ 0

Next tactic:
rw [← not_lt, Nat.WithBot.lt_zero_iff, degree_eq_bot]
theorem natDegree_eq_zero_iff_degree_le_zero : p.natDegree = 0 ↔ p.degree ≤ 0 := by
  

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
⊢ natDegree p = 0 ↔ degree p ≤ 0

Next tactic:
rw [← nonpos_iff_eq_zero, natDegree_le_iff_degree_le, Nat.cast_zero]
theorem degree_le_iff_coeff_zero (f : R[X]) (n : WithBot ℕ) :
    degree f ≤ n ↔ ∀ m : ℕ, n < m → coeff f m = 0 := by
  -- Porting note: `Nat.cast_withBot` is required.
  

Proof state:
R : Type u
S : Type v
a b c d : R
n✝ m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
f : R[X]
n : WithBot ℕ
⊢ degree f ≤ n ↔ ∀ (m : ℕ), n < ↑m → coeff f m = 0

Next tactic:
simp only [degree, Finset.max, Finset.sup_le_iff, mem_support_iff, Ne.def, ← not_le,
    not_imp_comm, Nat.cast_withBot]
theorem degree_lt_iff_coeff_zero (f : R[X]) (n : ℕ) :
    degree f < n ↔ ∀ m : ℕ, n ≤ m → coeff f m = 0 := by
  

Proof state:
R : Type u
S : Type v
a b c d : R
n✝ m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
f : R[X]
n : ℕ
⊢ degree f < ↑n ↔ ∀ (m : ℕ), n ≤ m → coeff f m = 0

Next tactic:
simp only [degree, Finset.sup_lt_iff (WithBot.bot_lt_coe n), mem_support_iff,
    WithBot.coe_lt_coe, ← @not_le ℕ, max_eq_sup_coe, Nat.cast_withBot, Ne.def, not_imp_not]
theorem degree_smul_le (a : R) (p : R[X]) : degree (a • p) ≤ degree p := by
  

Proof state:
R : Type u
S : Type v
a✝ b c d : R
n m : ℕ
inst✝ : Semiring R
p✝ q : R[X]
ι : Type u_1
a : R
p : R[X]
⊢ degree (a • p) ≤ degree p

Next tactic:
refine (degree_le_iff_coeff_zero _ _).2 fun m hm => ?_
theorem degree_smul_le (a : R) (p : R[X]) : degree (a • p) ≤ degree p := by
  refine (degree_le_iff_coeff_zero _ _).2 fun m hm => ?_
  

Proof state:
R : Type u
S : Type v
a✝ b c d : R
n m✝ : ℕ
inst✝ : Semiring R
p✝ q : R[X]
ι : Type u_1
a : R
p : R[X]
m : ℕ
hm : degree p < ↑m
⊢ coeff (a • p) m = 0

Next tactic:
rw [degree_lt_iff_coeff_zero] at hm
theorem degree_smul_le (a : R) (p : R[X]) : degree (a • p) ≤ degree p := by
  refine (degree_le_iff_coeff_zero _ _).2 fun m hm => ?_
  rw [degree_lt_iff_coeff_zero] at hm
  

Proof state:
R : Type u
S : Type v
a✝ b c d : R
n m✝ : ℕ
inst✝ : Semiring R
p✝ q : R[X]
ι : Type u_1
a : R
p : R[X]
m : ℕ
hm : ∀ (m_1 : ℕ), m ≤ m_1 → coeff p m_1 = 0
⊢ coeff (a • p) m = 0

Next tactic:
simp [hm m le_rfl]
theorem degree_lt_degree_mul_X (hp : p ≠ 0) : p.degree < (p * X).degree := by
  

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
hp : p ≠ 0
⊢ degree p < degree (p * X)

Next tactic:
haveI := Nontrivial.of_polynomial_ne hp
theorem degree_lt_degree_mul_X (hp : p ≠ 0) : p.degree < (p * X).degree := by
  haveI := Nontrivial.of_polynomial_ne hp
  

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
hp : p ≠ 0
this : Nontrivial R
⊢ degree p < degree (p * X)

Next tactic:
have : leadingCoeff p * leadingCoeff X ≠ 0 := by simpa
theorem degree_lt_degree_mul_X (hp : p ≠ 0) : p.degree < (p * X).degree := by
  haveI := Nontrivial.of_polynomial_ne hp
  have : leadingCoeff p * leadingCoeff X ≠ 0 := by 

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
hp : p ≠ 0
this : Nontrivial R
⊢ leadingCoeff p * leadingCoeff X ≠ 0

Next tactic:
simpa
theorem degree_lt_degree_mul_X (hp : p ≠ 0) : p.degree < (p * X).degree := by
  haveI := Nontrivial.of_polynomial_ne hp
  have : leadingCoeff p * leadingCoeff X ≠ 0 := by simpa
  

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
hp : p ≠ 0
this✝ : Nontrivial R
this : leadingCoeff p * leadingCoeff X ≠ 0
⊢ degree p < degree (p * X)

Next tactic:
erw [degree_mul' this, degree_eq_natDegree hp, degree_X, ← WithBot.coe_one,
    ← WithBot.coe_add, WithBot.coe_lt_coe]
theorem degree_lt_degree_mul_X (hp : p ≠ 0) : p.degree < (p * X).degree := by
  haveI := Nontrivial.of_polynomial_ne hp
  have : leadingCoeff p * leadingCoeff X ≠ 0 := by simpa
  erw [degree_mul' this, degree_eq_natDegree hp, degree_X, ← WithBot.coe_one,
    ← WithBot.coe_add, WithBot.coe_lt_coe]; 

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
hp : p ≠ 0
this✝ : Nontrivial R
this : leadingCoeff p * leadingCoeff X ≠ 0
⊢ ↑(natDegree p) < ↑(natDegree p) + 1

Next tactic:
exact Nat.lt_succ_self _
theorem eq_C_coeff_zero_iff_natDegree_eq_zero : p = C (p.coeff 0) ↔ p.natDegree = 0 :=
  ⟨fun h ↦ by 

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
h : p = C (coeff p 0)
⊢ natDegree p = 0

Next tactic:
rw [h, natDegree_C]
theorem eq_one_of_monic_natDegree_zero (hf : p.Monic) (hfd : p.natDegree = 0) : p = 1 := by
  

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
hf : Monic p
hfd : natDegree p = 0
⊢ p = 1

Next tactic:
rw [Monic.def, leadingCoeff, hfd] at hf
theorem eq_one_of_monic_natDegree_zero (hf : p.Monic) (hfd : p.natDegree = 0) : p = 1 := by
  rw [Monic.def, leadingCoeff, hfd] at hf
  

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
hf : coeff p 0 = 1
hfd : natDegree p = 0
⊢ p = 1

Next tactic:
rw [eq_C_of_natDegree_eq_zero hfd, hf, map_one]
theorem le_natDegree_of_coe_le_degree (hdeg : ↑n ≤ p.degree) : n ≤ p.natDegree :=
  -- Porting note: `.. ▸ ..` → `rwa [..] at ..`
  WithBot.coe_le_coe.mp <| by
    

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
hdeg : ↑n ≤ degree p
⊢ ↑n ≤ ↑(natDegree p)

Next tactic:
rwa [degree_eq_natDegree <| ne_zero_of_coe_le_degree hdeg] at hdeg
theorem degree_C_lt_degree_C_mul_X (ha : a ≠ 0) : degree (C b) < degree (C a * X) := by
  

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
ha : a ≠ 0
⊢ degree (C b) < degree (C a * X)

Next tactic:
simpa only [degree_C_mul_X ha] using degree_C_lt
@[simp]
theorem degree_linear (ha : a ≠ 0) : degree (C a * X + C b) = 1 := by
  

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
ha : a ≠ 0
⊢ degree (C a * X + C b) = 1

Next tactic:
rw [degree_add_eq_left_of_degree_lt <| degree_C_lt_degree_C_mul_X ha, degree_C_mul_X ha]
theorem natDegree_linear (ha : a ≠ 0) : natDegree (C a * X + C b) = 1 := by
  

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
ha : a ≠ 0
⊢ natDegree (C a * X + C b) = 1

Next tactic:
rw [natDegree_add_C, natDegree_C_mul_X a ha]
@[simp]
theorem leadingCoeff_linear (ha : a ≠ 0) : leadingCoeff (C a * X + C b) = a := by
  

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
ha : a ≠ 0
⊢ leadingCoeff (C a * X + C b) = a

Next tactic:
rw [add_comm, leadingCoeff_add_of_degree_lt (degree_C_lt_degree_C_mul_X ha),
    leadingCoeff_C_mul_X]
theorem degree_quadratic_le : degree (C a * X ^ 2 + C b * X + C c) ≤ 2 := by
  

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
⊢ degree (C a * X ^ 2 + C b * X + C c) ≤ 2

Next tactic:
simpa only [add_assoc] using
    degree_add_le_of_degree_le (degree_C_mul_X_pow_le 2 a)
      (le_trans degree_linear_le <| WithBot.coe_le_coe.mpr one_le_two)
theorem degree_linear_lt_degree_C_mul_X_sq (ha : a ≠ 0) :
    degree (C b * X + C c) < degree (C a * X ^ 2) := by
  

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
ha : a ≠ 0
⊢ degree (C b * X + C c) < degree (C a * X ^ 2)

Next tactic:
simpa only [degree_C_mul_X_pow 2 ha] using degree_linear_lt
@[simp]
theorem degree_quadratic (ha : a ≠ 0) : degree (C a * X ^ 2 + C b * X + C c) = 2 := by
  

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
ha : a ≠ 0
⊢ degree (C a * X ^ 2 + C b * X + C c) = 2

Next tactic:
rw [add_assoc, degree_add_eq_left_of_degree_lt <| degree_linear_lt_degree_C_mul_X_sq ha,
    degree_C_mul_X_pow 2 ha]
@[simp]
theorem degree_quadratic (ha : a ≠ 0) : degree (C a * X ^ 2 + C b * X + C c) = 2 := by
  rw [add_assoc, degree_add_eq_left_of_degree_lt <| degree_linear_lt_degree_C_mul_X_sq ha,
    degree_C_mul_X_pow 2 ha]
  

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
ha : a ≠ 0
⊢ ↑2 = 2

Next tactic:
rfl
@[simp]
theorem leadingCoeff_quadratic (ha : a ≠ 0) : leadingCoeff (C a * X ^ 2 + C b * X + C c) = a := by
  

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
ha : a ≠ 0
⊢ leadingCoeff (C a * X ^ 2 + C b * X + C c) = a

Next tactic:
rw [add_assoc, add_comm, leadingCoeff_add_of_degree_lt <| degree_linear_lt_degree_C_mul_X_sq ha,
    leadingCoeff_C_mul_X_pow]
theorem degree_cubic_le : degree (C a * X ^ 3 + C b * X ^ 2 + C c * X + C d) ≤ 3 := by
  

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
⊢ degree (C a * X ^ 3 + C b * X ^ 2 + C c * X + C d) ≤ 3

Next tactic:
simpa only [add_assoc] using
    degree_add_le_of_degree_le (degree_C_mul_X_pow_le 3 a)
      (le_trans degree_quadratic_le <| WithBot.coe_le_coe.mpr <| Nat.le_succ 2)
theorem degree_quadratic_lt_degree_C_mul_X_cb (ha : a ≠ 0) :
    degree (C b * X ^ 2 + C c * X + C d) < degree (C a * X ^ 3) := by
  

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
ha : a ≠ 0
⊢ degree (C b * X ^ 2 + C c * X + C d) < degree (C a * X ^ 3)

Next tactic:
simpa only [degree_C_mul_X_pow 3 ha] using degree_quadratic_lt
@[simp]
theorem degree_cubic (ha : a ≠ 0) : degree (C a * X ^ 3 + C b * X ^ 2 + C c * X + C d) = 3 := by
  

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
ha : a ≠ 0
⊢ degree (C a * X ^ 3 + C b * X ^ 2 + C c * X + C d) = 3

Next tactic:
rw [add_assoc, add_assoc, ← add_assoc (C b * X ^ 2),
    degree_add_eq_left_of_degree_lt <| degree_quadratic_lt_degree_C_mul_X_cb ha,
    degree_C_mul_X_pow 3 ha]
@[simp]
theorem degree_cubic (ha : a ≠ 0) : degree (C a * X ^ 3 + C b * X ^ 2 + C c * X + C d) = 3 := by
  rw [add_assoc, add_assoc, ← add_assoc (C b * X ^ 2),
    degree_add_eq_left_of_degree_lt <| degree_quadratic_lt_degree_C_mul_X_cb ha,
    degree_C_mul_X_pow 3 ha]
  

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
ha : a ≠ 0
⊢ ↑3 = 3

Next tactic:
rfl
@[simp]
theorem leadingCoeff_cubic (ha : a ≠ 0) :
    leadingCoeff (C a * X ^ 3 + C b * X ^ 2 + C c * X + C d) = a := by
  

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
ha : a ≠ 0
⊢ leadingCoeff (C a * X ^ 3 + C b * X ^ 2 + C c * X + C d) = a

Next tactic:
rw [add_assoc, add_assoc, ← add_assoc (C b * X ^ 2), add_comm,
    leadingCoeff_add_of_degree_lt <| degree_quadratic_lt_degree_C_mul_X_cb ha,
    leadingCoeff_C_mul_X_pow]