-- Mathlib/AlgebraicGeometry/EllipticCurve/DivisionPolynomial/Degree.lean
private lemma natDegree_coeff_preΨ' (n : ℕ) :
    (W.preΨ' n).natDegree ≤ expDegree n ∧ (W.preΨ' n).coeff (expDegree n) = expCoeff n

Proof state:
case even.right
R : Type u
inst✝ : CommRing R
W : WeierstrassCurve R
dm : ∀ {m n : ℕ} {p q : R[X]}, p.natDegree ≤ m → q.natDegree ≤ n → (p * q).natDegree ≤ m + n :=
  fun {m n} {p q} => natDegree_mul_le_of_le
dp : ∀ {m n : ℕ} {p : R[X]}, p.natDegree ≤ m → (p ^ n).natDegree ≤ n * m := fun {m n} {p} => natDegree_pow_le_of_le n
cm : ∀ {m n : ℕ} {p q : R[X]}, p.natDegree ≤ m → q.natDegree ≤ n → (p * q).coeff (m + n) = p.coeff m * q.coeff n :=
  fun {m n} {p q} => coeff_mul_of_natDegree_le
cp : ∀ {m n : ℕ} {p : R[X]}, p.natDegree ≤ n → (p ^ m).coeff (m * n) = p.coeff n ^ m :=
  fun {m n} {p} => coeff_pow_of_natDegree_le
m : ℕ
h₁ :
  (W.preΨ' (m + 1)).natDegree ≤ WeierstrassCurve.expDegree (m + 1) ∧
    (W.preΨ' (m + 1)).coeff (WeierstrassCurve.expDegree (m + 1)) = ↑(WeierstrassCurve.expCoeff (m + 1))
h₂ :
  (W.preΨ' (m + 2)).natDegree ≤ WeierstrassCurve.expDegree (m + 2) ∧
    (W.preΨ' (m + 2)).coeff (WeierstrassCurve.expDegree (m + 2)) = ↑(WeierstrassCurve.expCoeff (m + 2))
h₃ :
  (W.preΨ' (m + 3)).natDegree ≤ WeierstrassCurve.expDegree (m + 3) ∧
    (W.preΨ' (m + 3)).coeff (WeierstrassCurve.expDegree (m + 3)) = ↑(WeierstrassCurve.expCoeff (m + 3))
h₄ :
  (W.preΨ' (m + 4)).natDegree ≤ WeierstrassCurve.expDegree (m + 4) ∧
    (W.preΨ' (m + 4)).coeff (WeierstrassCurve.expDegree (m + 4)) = ↑(WeierstrassCurve.expCoeff (m + 4))
h₅ :
  (W.preΨ' (m + 5)).natDegree ≤ WeierstrassCurve.expDegree (m + 5) ∧
    (W.preΨ' (m + 5)).coeff (WeierstrassCurve.expDegree (m + 5)) = ↑(WeierstrassCurve.expCoeff (m + 5))
⊢ (W.preΨ' (2 * (m + 3))).coeff (WeierstrassCurve.expDegree (2 * (m + 3))) = ↑(WeierstrassCurve.expCoeff (2 * (m + 3)))

Tactic:
nth_rw 1 [preΨ'_even, coeff_sub, (expDegree_rec m).1.1, cm (dm (dp h₂.1) h₃.1) h₅.1,
  cm (dp h₂.1) h₃.1, cp h₂.1, h₂.2, h₃.2, h₅.2, (expDegree_rec m).1.2,
  cm (dm h₁.1 h₃.1) (dp h₄.1), cm h₁.1 h₃.1, h₁.2, cp h₄.1, h₃.2, h₄.2, (expCoeff_rec m).1]

Result:
case even.right
R : Type u
inst✝ : CommRing R
W : WeierstrassCurve R
dm : ∀ {m n : ℕ} {p q : R[X]}, p.natDegree ≤ m → q.natDegree ≤ n → (p * q).natDegree ≤ m + n :=
  fun {m n} {p q} => natDegree_mul_le_of_le
dp : ∀ {m n : ℕ} {p : R[X]}, p.natDegree ≤ m → (p ^ n).natDegree ≤ n * m := fun {m n} {p} => natDegree_pow_le_of_le n
cm : ∀ {m n : ℕ} {p q : R[X]}, p.natDegree ≤ m → q.natDegree ≤ n → (p * q).coeff (m + n) = p.coeff m * q.coeff n :=
  fun {m n} {p q} => coeff_mul_of_natDegree_le
cp : ∀ {m n : ℕ} {p : R[X]}, p.natDegree ≤ n → (p ^ m).coeff (m * n) = p.coeff n ^ m :=
  fun {m n} {p} => coeff_pow_of_natDegree_le
m : ℕ
h₁ :
  (W.preΨ' (m + 1)).natDegree ≤ WeierstrassCurve.expDegree (m + 1) ∧
    (W.preΨ' (m + 1)).coeff (WeierstrassCurve.expDegree (m + 1)) = ↑(WeierstrassCurve.expCoeff (m + 1))
h₂ :
  (W.preΨ' (m + 2)).natDegree ≤ WeierstrassCurve.expDegree (m + 2) ∧
    (W.preΨ' (m + 2)).coeff (WeierstrassCurve.expDegree (m + 2)) = ↑(WeierstrassCurve.expCoeff (m + 2))
h₃ :
  (W.preΨ' (m + 3)).natDegree ≤ WeierstrassCurve.expDegree (m + 3) ∧
    (W.preΨ' (m + 3)).coeff (WeierstrassCurve.expDegree (m + 3)) = ↑(WeierstrassCurve.expCoeff (m + 3))
h₄ :
  (W.preΨ' (m + 4)).natDegree ≤ WeierstrassCurve.expDegree (m + 4) ∧
    (W.preΨ' (m + 4)).coeff (WeierstrassCurve.expDegree (m + 4)) = ↑(WeierstrassCurve.expCoeff (m + 4))
h₅ :
  (W.preΨ' (m + 5)).natDegree ≤ WeierstrassCurve.expDegree (m + 5) ∧
    (W.preΨ' (m + 5)).coeff (WeierstrassCurve.expDegree (m + 5)) = ↑(WeierstrassCurve.expCoeff (m + 5))
⊢ ↑(WeierstrassCurve.expCoeff (m + 2)) ^ 2 * ↑(WeierstrassCurve.expCoeff (m + 3)) *
        ↑(WeierstrassCurve.expCoeff (m + 5)) -
      ↑(WeierstrassCurve.expCoeff (m + 1)) * ↑(WeierstrassCurve.expCoeff (m + 3)) *
        ↑(WeierstrassCurve.expCoeff (m + 4)) ^ 2 =
    ↑(WeierstrassCurve.expCoeff (m + 2) ^ 2 * WeierstrassCurve.expCoeff (m + 3) * WeierstrassCurve.expCoeff (m + 5) -
        WeierstrassCurve.expCoeff (m + 1) * WeierstrassCurve.expCoeff (m + 3) * WeierstrassCurve.expCoeff (m + 4) ^ 2)

Proof state:
R : Type u
inst✝ : CommRing R
W : WeierstrassCurve R
n : ℕ
⊢ (W.preΨ' n).natDegree ≤ WeierstrassCurve.expDegree n ∧
    (W.preΨ' n).coeff (WeierstrassCurve.expDegree n) = ↑(WeierstrassCurve.expCoeff n)

Tactic:
let dm {m n p q} : _ → _ → (p * q : R[X]).natDegree ≤ m + n := natDegree_mul_le_of_le

Result:
R : Type u
inst✝ : CommRing R
W : WeierstrassCurve R
n : ℕ
dm : ∀ {m n : ℕ} {p q : R[X]}, p.natDegree ≤ m → q.natDegree ≤ n → (p * q).natDegree ≤ m + n :=
  fun {m n} {p q} => natDegree_mul_le_of_le
⊢ (W.preΨ' n).natDegree ≤ WeierstrassCurve.expDegree n ∧
    (W.preΨ' n).coeff (WeierstrassCurve.expDegree n) = ↑(WeierstrassCurve.expCoeff n)

Proof state:
case odd.left.refine_2
R : Type u
inst✝ : CommRing R
W : WeierstrassCurve R
dm : ∀ {m n : ℕ} {p q : R[X]}, p.natDegree ≤ m → q.natDegree ≤ n → (p * q).natDegree ≤ m + n :=
  fun {m n} {p q} => natDegree_mul_le_of_le
dp : ∀ {m n : ℕ} {p : R[X]}, p.natDegree ≤ m → (p ^ n).natDegree ≤ n * m := fun {m n} {p} => natDegree_pow_le_of_le n
cm : ∀ {m n : ℕ} {p q : R[X]}, p.natDegree ≤ m → q.natDegree ≤ n → (p * q).coeff (m + n) = p.coeff m * q.coeff n :=
  fun {m n} {p q} => coeff_mul_of_natDegree_le
cp : ∀ {m n : ℕ} {p : R[X]}, p.natDegree ≤ n → (p ^ m).coeff (m * n) = p.coeff n ^ m :=
  fun {m n} {p} => coeff_pow_of_natDegree_le
m : ℕ
h₁ :
  (W.preΨ' (m + 1)).natDegree ≤ WeierstrassCurve.expDegree (m + 1) ∧
    (W.preΨ' (m + 1)).coeff (WeierstrassCurve.expDegree (m + 1)) = ↑(WeierstrassCurve.expCoeff (m + 1))
h₂ :
  (W.preΨ' (m + 2)).natDegree ≤ WeierstrassCurve.expDegree (m + 2) ∧
    (W.preΨ' (m + 2)).coeff (WeierstrassCurve.expDegree (m + 2)) = ↑(WeierstrassCurve.expCoeff (m + 2))
h₃ :
  (W.preΨ' (m + 3)).natDegree ≤ WeierstrassCurve.expDegree (m + 3) ∧
    (W.preΨ' (m + 3)).coeff (WeierstrassCurve.expDegree (m + 3)) = ↑(WeierstrassCurve.expCoeff (m + 3))
h₄ :
  (W.preΨ' (m + 4)).natDegree ≤ WeierstrassCurve.expDegree (m + 4) ∧
    (W.preΨ' (m + 4)).coeff (WeierstrassCurve.expDegree (m + 4)) = ↑(WeierstrassCurve.expCoeff (m + 4))
⊢ (if Even m then 1 else W.Ψ₂Sq ^ 2).natDegree ≤ if Even m then 0 else 2 * 3

Tactic:
split_ifs <;>
simp only [apply_ite natDegree, natDegree_one.le, dp W.natDegree_Ψ₂Sq_le]

Result:
no goals

Proof state:
case odd.right
R : Type u
inst✝ : CommRing R
W : WeierstrassCurve R
dm : ∀ {m n : ℕ} {p q : R[X]}, p.natDegree ≤ m → q.natDegree ≤ n → (p * q).natDegree ≤ m + n :=
  fun {m n} {p q} => natDegree_mul_le_of_le
dp : ∀ {m n : ℕ} {p : R[X]}, p.natDegree ≤ m → (p ^ n).natDegree ≤ n * m := fun {m n} {p} => natDegree_pow_le_of_le n
cm : ∀ {m n : ℕ} {p q : R[X]}, p.natDegree ≤ m → q.natDegree ≤ n → (p * q).coeff (m + n) = p.coeff m * q.coeff n :=
  fun {m n} {p q} => coeff_mul_of_natDegree_le
cp : ∀ {m n : ℕ} {p : R[X]}, p.natDegree ≤ n → (p ^ m).coeff (m * n) = p.coeff n ^ m :=
  fun {m n} {p} => coeff_pow_of_natDegree_le
m : ℕ
h₁ :
  (W.preΨ' (m + 1)).natDegree ≤ WeierstrassCurve.expDegree (m + 1) ∧
    (W.preΨ' (m + 1)).coeff (WeierstrassCurve.expDegree (m + 1)) = ↑(WeierstrassCurve.expCoeff (m + 1))
h₂ :
  (W.preΨ' (m + 2)).natDegree ≤ WeierstrassCurve.expDegree (m + 2) ∧
    (W.preΨ' (m + 2)).coeff (WeierstrassCurve.expDegree (m + 2)) = ↑(WeierstrassCurve.expCoeff (m + 2))
h₃ :
  (W.preΨ' (m + 3)).natDegree ≤ WeierstrassCurve.expDegree (m + 3) ∧
    (W.preΨ' (m + 3)).coeff (WeierstrassCurve.expDegree (m + 3)) = ↑(WeierstrassCurve.expCoeff (m + 3))
h₄ :
  (W.preΨ' (m + 4)).natDegree ≤ WeierstrassCurve.expDegree (m + 4) ∧
    (W.preΨ' (m + 4)).coeff (WeierstrassCurve.expDegree (m + 4)) = ↑(WeierstrassCurve.expCoeff (m + 4))
⊢ (if Even m then W.Ψ₂Sq ^ 2 else 1).natDegree ≤ if Even m then 2 * 3 else 0

Tactic:
split_ifs <;>
simp only [apply_ite natDegree, natDegree_one.le, dp W.natDegree_Ψ₂Sq_le]

Result:
no goals