Definitions/Def_WeierstrassCurve_DivPolyMulFormula.lean
Reduced division polynomials: multiplication formula predicates
Fix a Weierstrass curve W and work with Mathlib's reduced division polynomials \mathrm{pre\Psi}, \Psi^2 = \mathrm{\Psi Sq}, \Phi, together with \Psi_2^2, \Psi_3, \mathrm{pre\Psi}_4. Three predicates are introduced. For a nonsingular affine point (x,y) on W over a field F and m : \mathbb{N}, MFred m h asserts the conjunction \Psi^2_m(x) \ne 0 and x(mP)\,\Psi^2_m(x) = \Phi_m(x), where P = (x,y) and the left-hand factor is xOrZero of m \bullet P, i.e. the x-coordinate of the point, taken to be 0 at the point at infinity. LowTorsionFree m h asserts that kP \ne 0 for every natural k with 1 \le k \le m; it is monotone in m. For W over a commutative ring R and j : \mathbb{Z}, StarIdentity j asserts the polynomial identity, evaluated at every t \in R,
2t\,\Phi_j(\Phi_j + t\Psi^2_j) + b_2 t\,\Phi_j\Psi^2_j + b_4(\Phi_j + t\Psi^2_j)\Psi^2_j + b_6 (\Psi^2_j)^2 = \Phi_{j+1}\Psi^2_{j-1} + \Phi_{j-1}\Psi^2_{j+1},
all terms evaluated at t.
The remaining declarations supply the algebra around these notions: parity-resolved forms of \Psi^2_m, \Phi_m and of the recursions for \mathrm{pre\Psi} at 2m\pm1, 2m+2; the consecutive-index identities (X\Psi^2_m - \Phi_m)^2 = \Psi^2_{m+1}\Psi^2_{m-1}, \Phi_{m+1}\Psi^2_m - \Phi_m\Psi^2_{m+1} = -\mathrm{pre\Psi}_{2m+1} and \Phi_{m+1}\Psi^2_{m-1} - \Phi_{m-1}\Psi^2_{m+1} = -\mathrm{pre\Psi}_{2m}\Psi_2^2; closed forms at small index (\mathrm{pre\Psi}'_5, \mathrm{pre\Psi}'_6, \mathrm{pre\Psi}'_7, \Psi^2_5, \Psi^2_7, \Phi_5); the instances ellipticNet_one to ellipticNet_four of the above identity for j \le 4, each a long explicit expansion in b_2,b_4,b_6,b_8 modulo the relation 4b_8 = b_2b_6 - b_4^2; doubling and addition formulae relating \mathrm{addX} to \Psi_2^2 and \Phi_2; the induction producing MFred from LowTorsionFree together with the star identities; and the consequences linking vanishing of \Psi^2_{m}(x) to mP = 0.
Relation to Mathlib
The division polynomials preΨ, preΨ', ΨSq, Φ, Ψ₂Sq, Ψ₃, preΨ₄ and the relation b_relation are Mathlib's; xOrZero is the project's x-coordinate function on affine points, extended by 0 at infinity. The predicates MFred, LowTorsionFree and StarIdentity are the project's own, as are several variants of Mathlib-style lemmas on addX and slope restated for W.toAffine.
Where it is used
These identities and predicates underlie the comparison between the x-coordinate of mP and the reduced division polynomials, and hence between torsion points and roots of \Psi^2_m; they feed the bounds on p-torsion of an elliptic curve and the Tate-curve x-coordinate alignment used in the net-pairing track.
References
- J. H. Silverman, The Arithmetic of Elliptic Curves, Graduate Texts in Mathematics 106, Springer, 1986, Exercise III.3.7
- J. W. S. Cassels, Lectures on Elliptic Curves, London Mathematical Society Student Texts 24, Cambridge University Press, 1991
References are suggested automatically and have not been individually verified.
English text generated automatically from the Lean source; the Lean statement is authoritative.
- 1,751 lines
- 74 declarations
- used in the statements of 2 theorems and imported by 1 proofs
- imports 3 definition modules
Source file: Definitions/Def_WeierstrassCurve_DivPolyMulFormula.lean
Imported by
Declarations
- lemma
WeierstrassCurve.Affine.sq_sub_negY' - lemma
WeierstrassCurve.Affine.Ψ₂Sq_eval_ne_zero' - lemma
WeierstrassCurve.Affine.Ψ₂Sq_eval_eq_zero_iff_two_smul' - lemma
WeierstrassCurve.Affine.addX_self_mul_Ψ₂Sq' - lemma
WeierstrassCurve.Affine.Ψ₂Sq_comp_duplication' - lemma
WeierstrassCurve.Affine.eval_Ψ₂Sq' - lemma
WeierstrassCurve.Affine.eval_Φ_two' - lemma
WeierstrassCurve.Affine.preΨ'_five - lemma
WeierstrassCurve.Affine.ΨSq_five - lemma
WeierstrassCurve.Affine.X_mul_Ψ₂Sq_sub_Φ_two_eval - lemma
WeierstrassCurve.Affine.X_mul_ΨSq_four_sub_Φ_four_eval - lemma
WeierstrassCurve.Affine.eval_Ψ₂Sq'' - lemma
WeierstrassCurve.Affine.eval_Φ_two'' - lemma
WeierstrassCurve.Affine.sq_sub_negY_eq - lemma
WeierstrassCurve.Affine.addX_self_mul_Ψ₂Sq_eq - lemma
WeierstrassCurve.Affine.X_mul_Ψ₂Sq_sub_Φ_two - lemma
WeierstrassCurve.Affine.Ψ₂Sq_comp_duplication_eq - lemma
WeierstrassCurve.Affine.Φ_comp_duplication_eq - lemma
WeierstrassCurve.Affine.ellipticNet_two - lemma
WeierstrassCurve.Affine.preΨ'_five_eq - lemma
WeierstrassCurve.Affine.preΨ'_seven_eq - lemma
WeierstrassCurve.Affine.ΨSq_seven_eq - lemma
WeierstrassCurve.Affine.eval_Φ_three - lemma
WeierstrassCurve.Affine.eval_Φ_four - lemma
WeierstrassCurve.ΨSq_of_even - lemma
WeierstrassCurve.ΨSq_of_odd - lemma
WeierstrassCurve.Φ_of_even - lemma
WeierstrassCurve.Φ_of_odd - lemma
WeierstrassCurve.preΨ_odd_of_even - lemma
WeierstrassCurve.preΨ_odd_of_odd - lemma
WeierstrassCurve.Φ_two_mul - lemma
WeierstrassCurve.Φ_two_mul_add_one - lemma
WeierstrassCurve.preΨ_two_mul_sub_one_of_even - lemma
WeierstrassCurve.preΨ_two_mul_sub_one_of_odd - lemma
WeierstrassCurve.preΨ_two_mul_add_two - lemma
WeierstrassCurve.X_mul_ΨSq_sub_Φ - lemma
WeierstrassCurve.X_mul_ΨSq_sub_Φ_sq - lemma
WeierstrassCurve.Φ_succ_mul_ΨSq_sub_Φ_mul_ΨSq_succ - lemma
WeierstrassCurve.Φ_succ_mul_ΨSq_pred_sub_Φ_pred_mul_ΨSq_succ - lemma
WeierstrassCurve.preΨ'_five_eq - lemma
WeierstrassCurve.preΨ'_six_eq - lemma
WeierstrassCurve.ΨSq_five_eq - lemma
WeierstrassCurve.Φ_five_eq - lemma
WeierstrassCurve.ellipticNet_one - lemma
WeierstrassCurve.ellipticNet_three - lemma
WeierstrassCurve.ellipticNet_four - def
WeierstrassCurve.Affine.MFred - def
WeierstrassCurve.Affine.LowTorsionFree - lemma
WeierstrassCurve.Affine.LowTorsionFree.mono - theorem
WeierstrassCurve.Affine.mfred_one - theorem
WeierstrassCurve.Affine.mfred_two - theorem
WeierstrassCurve.Affine.mfred_step - theorem
WeierstrassCurve.Affine.mfred_of_forall_star - theorem
WeierstrassCurve.Affine.mfred_three - def
WeierstrassCurve.StarIdentity - theorem
WeierstrassCurve.starIdentity_of_le_four - theorem
WeierstrassCurve.Affine.mfred_of_forall_starIdentity - theorem
WeierstrassCurve.Affine.mfred_of_le_five - theorem
WeierstrassCurve.Affine.mfred_four - theorem
WeierstrassCurve.Affine.mfred_five - lemma
WeierstrassCurve.Affine.star_eval_core - lemma
WeierstrassCurve.Affine.odd_step_core - lemma
WeierstrassCurve.Affine.even_step_core - theorem
WeierstrassCurve.Affine.addX_mul_addX_negY_mul_sq' - lemma
WeierstrassCurve.Affine.x_ne_of_ne_of_ne_neg - theorem
WeierstrassCurve.Affine.mfred_double_succ - theorem
WeierstrassCurve.Affine.mfred_double - theorem
WeierstrassCurve.Affine.mfred_all - theorem
WeierstrassCurve.Affine.nsmul_succ_eq_zero_of_ΨSq_eval_eq_zero - theorem
WeierstrassCurve.Affine.ΨSq_eval_eq_zero_or_of_succ_nsmul_eq_zero - theorem
WeierstrassCurve.Affine.ΨSq_eval_eq_zero_of_succ_nsmul_eq_zero - theorem
WeierstrassCurve.Affine.succ_nsmul_eq_zero_iff_ΨSq_eval_eq_zero - theorem
WeierstrassCurve.Affine.nsmul_eq_zero_of_ΨSq_eval_eq_zero_of_starIdentity - theorem
WeierstrassCurve.Affine.nsmul_six_eq_zero_of_ΨSq_eval_eq_zero
Source
import Mathlib import Definitions.Def_WeierstrassCurve_AddFormula import Definitions.Def_NetPairing_Basic import Definitions.Def_TateCurve_XMultAlignment set_option autoImplicit false open Polynomial local macro "eval_simp" : tactic => `(tactic| simp only [eval_C, eval_X, eval_neg, eval_add, eval_sub, eval_mul, eval_pow, eval_ofNat, eval_zero, eval_one, evalEval]) universe u namespace WeierstrassCurve.Affine variable {F : Type u} [Field F] {W : WeierstrassCurve F} section Prerequisites lemma sq_sub_negY' {x y : F} (h : W.toAffine.Equation x y) : (y - W.toAffine.negY x y) ^ 2 = (W.Ψ₂Sq).eval x := by rw [negY, Ψ₂Sq, b₂, b₄, b₆] eval_simp linear_combination (4 : F) * ((W.toAffine.equation_iff x y).mp h) lemma Ψ₂Sq_eval_ne_zero' {x y : F} (h : W.toAffine.Equation x y) (hy : y ≠ W.toAffine.negY x y) : (W.Ψ₂Sq).eval x ≠ 0 := by rw [← sq_sub_negY' h] exact pow_ne_zero 2 (sub_ne_zero_of_ne hy) lemma Ψ₂Sq_eval_eq_zero_iff_two_smul' [DecidableEq F] {x y : F} (h : W.toAffine.Nonsingular x y) : (W.Ψ₂Sq).eval x = 0 ↔ (2 • Point.some x y h : W.toAffine.Point) = 0 := by rw [two_nsmul] constructor · intro h0 have hy : y = W.toAffine.negY x y := by by_contra hy exact Ψ₂Sq_eval_ne_zero' h.left hy h0 exact Point.add_self_of_Y_eq hy · intro h0 by_cases hy : y = W.toAffine.negY x y · rw [← sq_sub_negY' h.left, sub_eq_zero.mpr hy] ring · exact absurd ((Point.add_self_of_Y_ne hy).symm.trans h0) (Point.some_ne_zero _) lemma addX_self_mul_Ψ₂Sq' [DecidableEq F] {x y : F} (h : W.toAffine.Equation x y) (hy : y ≠ W.toAffine.negY x y) : W.toAffine.addX x x (W.toAffine.slope x x y y) * (W.Ψ₂Sq).eval x = (W.Φ 2).eval x := by have hd : y - W.toAffine.negY x y ≠ 0 := sub_ne_zero_of_ne hy have hℓ : W.toAffine.slope x x y y * (y - W.toAffine.negY x y) = 3 * x ^ 2 + 2 * W.a₂ * x + W.a₄ - W.a₁ * y := by rw [slope_of_Y_ne rfl hy, div_mul_cancel₀ _ hd] rw [addX, ← sq_sub_negY' h, Φ_two, b₄, b₆, b₈, negY] at * eval_simp linear_combination (W.toAffine.slope x x y y * (y - (-y - W.a₁ * x - W.a₃)) + (3 * x ^ 2 + 2 * W.a₂ * x + W.a₄ - W.a₁ * y) + W.a₁ * (y - (-y - W.a₁ * x - W.a₃))) * hℓ + (-(8 * x + W.a₁ ^ 2 + 4 * W.a₂)) * ((W.toAffine.equation_iff x y).mp h) lemma Ψ₂Sq_comp_duplication' (x : F) : 4 * (W.Φ 2).eval x ^ 3 + W.b₂ * ((W.Φ 2).eval x ^ 2 * (W.Ψ₂Sq).eval x) + 2 * W.b₄ * ((W.Φ 2).eval x * (W.Ψ₂Sq).eval x ^ 2) + W.b₆ * (W.Ψ₂Sq).eval x ^ 3 = (W.preΨ₄).eval x ^ 2 := by rw [Φ_two, Ψ₂Sq, preΨ₄, b₂, b₄, b₆, b₈] eval_simp ring end Prerequisites section EvalLemmas lemma eval_Ψ₂Sq' (t : F) : (W.Ψ₂Sq).eval t = 4 * t ^ 3 + W.b₂ * t ^ 2 + 2 * W.b₄ * t + W.b₆ := by rw [Ψ₂Sq]; eval_simp lemma eval_Φ_two' (t : F) : (W.Φ 2).eval t = t ^ 4 - W.b₄ * t ^ 2 - 2 * W.b₆ * t - W.b₈ := by rw [Φ_two]; eval_simp lemma preΨ'_five : W.preΨ' 5 = W.preΨ₄ * W.Ψ₂Sq ^ 2 - W.Ψ₃ ^ 3 := by rw [show (5 : ℕ) = 2 * (0 + 2) + 1 by rfl, preΨ'_odd] simp lemma ΨSq_five : W.ΨSq 5 = (W.preΨ₄ * W.Ψ₂Sq ^ 2 - W.Ψ₃ ^ 3) ^ 2 := by rw [show (5 : ℤ) = ((5 : ℕ) : ℤ) by rfl, ΨSq_ofNat, preΨ'_five, if_neg (by decide : ¬Even (5 : ℕ)), mul_one] lemma X_mul_Ψ₂Sq_sub_Φ_two_eval (t : F) : t * (W.Ψ₂Sq).eval t - (W.Φ 2).eval t = (W.Ψ₃).eval t := by rw [Φ_two, Ψ₂Sq, Ψ₃] eval_simp ring lemma X_mul_ΨSq_four_sub_Φ_four_eval (t : F) : t * ((W.preΨ₄).eval t ^ 2 * (W.Ψ₂Sq).eval t) - (W.Φ 4).eval t = (W.Ψ₃).eval t * ((W.preΨ₄).eval t * (W.Ψ₂Sq).eval t ^ 2 - (W.Ψ₃).eval t ^ 3) := by rw [Φ_four] eval_simp ring end EvalLemmas end WeierstrassCurve.Affine open Polynomial WeierstrassCurve namespace WeierstrassCurve.Affine variable {F : Type u} [Field F] {W : WeierstrassCurve F} section Prerequisites lemma eval_Ψ₂Sq'' (t : F) : (W.Ψ₂Sq).eval t = 4 * t ^ 3 + W.b₂ * t ^ 2 + 2 * W.b₄ * t + W.b₆ := by rw [Ψ₂Sq]; eval_simp lemma eval_Φ_two'' (t : F) : (W.Φ 2).eval t = t ^ 4 - W.b₄ * t ^ 2 - 2 * W.b₆ * t - W.b₈ := by rw [Φ_two]; eval_simp lemma sq_sub_negY_eq {x y : F} (h : W.toAffine.Equation x y) : (y - W.toAffine.negY x y) ^ 2 = (W.Ψ₂Sq).eval x := by rw [negY, Ψ₂Sq, b₂, b₄, b₆] eval_simp linear_combination (4 : F) * ((W.toAffine.equation_iff x y).mp h) lemma addX_self_mul_Ψ₂Sq_eq [DecidableEq F] {x y : F} (h : W.toAffine.Equation x y) (hy : y ≠ W.toAffine.negY x y) : W.toAffine.addX x x (W.toAffine.slope x x y y) * (W.Ψ₂Sq).eval x = (W.Φ 2).eval x := by have hd : y - W.toAffine.negY x y ≠ 0 := sub_ne_zero_of_ne hy have hℓ : W.toAffine.slope x x y y * (y - W.toAffine.negY x y) = 3 * x ^ 2 + 2 * W.a₂ * x + W.a₄ - W.a₁ * y := by rw [slope_of_Y_ne rfl hy, div_mul_cancel₀ _ hd] rw [addX, ← sq_sub_negY_eq h, Φ_two, b₄, b₆, b₈, negY] at * eval_simp linear_combination (W.toAffine.slope x x y y * (y - (-y - W.a₁ * x - W.a₃)) + (3 * x ^ 2 + 2 * W.a₂ * x + W.a₄ - W.a₁ * y) + W.a₁ * (y - (-y - W.a₁ * x - W.a₃))) * hℓ + (-(8 * x + W.a₁ ^ 2 + 4 * W.a₂)) * ((W.toAffine.equation_iff x y).mp h) lemma X_mul_Ψ₂Sq_sub_Φ_two (t : F) : t * (W.Ψ₂Sq).eval t - (W.Φ 2).eval t = (W.Ψ₃).eval t := by rw [Φ_two, Ψ₂Sq, Ψ₃] eval_simp ring lemma Ψ₂Sq_comp_duplication_eq (t : F) : 4 * (W.Φ 2).eval t ^ 3 + W.b₂ * ((W.Φ 2).eval t ^ 2 * (W.Ψ₂Sq).eval t) + 2 * W.b₄ * ((W.Φ 2).eval t * (W.Ψ₂Sq).eval t ^ 2) + W.b₆ * (W.Ψ₂Sq).eval t ^ 3 = (W.preΨ₄).eval t ^ 2 := by rw [Φ_two, Ψ₂Sq, preΨ₄, b₂, b₄, b₆, b₈] eval_simp ring set_option maxHeartbeats 1000000 in lemma Φ_comp_duplication_eq (t : F) : (W.Φ 2).eval t ^ 4 - W.b₄ * ((W.Φ 2).eval t ^ 2 * (W.Ψ₂Sq).eval t ^ 2) - 2 * W.b₆ * ((W.Φ 2).eval t * (W.Ψ₂Sq).eval t ^ 3) - W.b₈ * (W.Ψ₂Sq).eval t ^ 4 = (W.Φ 4).eval t := by rw [Φ_two, Φ_four, Ψ₂Sq, preΨ₄, Ψ₃, b₂, b₄, b₆, b₈] eval_simp ring end Prerequisites set_option maxHeartbeats 1000000 in lemma ellipticNet_two (t : F) : 2 * t * (W.Φ 2).eval t * ((W.Φ 2).eval t + t * (W.Ψ₂Sq).eval t) + W.b₂ * t * ((W.Φ 2).eval t * (W.Ψ₂Sq).eval t) + W.b₄ * (((W.Φ 2).eval t + t * (W.Ψ₂Sq).eval t) * (W.Ψ₂Sq).eval t) + W.b₆ * (W.Ψ₂Sq).eval t ^ 2 = (W.Φ 3).eval t + t * (W.Ψ₃).eval t ^ 2 := by rw [Φ_two, Φ_three, Ψ₂Sq, Ψ₃, preΨ₄, b₂, b₄, b₆, b₈] eval_simp ring section EvalLemmas lemma preΨ'_five_eq : W.preΨ' 5 = W.preΨ₄ * W.Ψ₂Sq ^ 2 - W.Ψ₃ ^ 3 := by rw [show (5 : ℕ) = 2 * (0 + 2) + 1 by rfl, preΨ'_odd] simp lemma preΨ'_seven_eq : W.preΨ' 7 = (W.preΨ₄ * W.Ψ₂Sq ^ 2 - W.Ψ₃ ^ 3) * W.Ψ₃ ^ 3 - W.preΨ₄ ^ 3 * W.Ψ₂Sq ^ 2 := by rw [show (7 : ℕ) = 2 * (1 + 2) + 1 by rfl, preΨ'_odd] simp only [Nat.reduceAdd, preΨ'_two, preΨ'_three, preΨ'_four, Nat.not_even_one, if_false, mul_one, one_mul, preΨ'_five_eq] lemma ΨSq_seven_eq : W.ΨSq 7 = ((W.preΨ₄ * W.Ψ₂Sq ^ 2 - W.Ψ₃ ^ 3) * W.Ψ₃ ^ 3 - W.preΨ₄ ^ 3 * W.Ψ₂Sq ^ 2) ^ 2 := by rw [show (7 : ℤ) = ((7 : ℕ) : ℤ) by rfl, ΨSq_ofNat, preΨ'_seven_eq, if_neg (by decide : ¬Even (7 : ℕ)), mul_one] lemma eval_Φ_three (t : F) : (W.Φ 3).eval t = t * (W.Ψ₃).eval t ^ 2 - (W.preΨ₄).eval t * (W.Ψ₂Sq).eval t := by rw [Φ_three]; eval_simp lemma eval_Φ_four (t : F) : (W.Φ 4).eval t = t * (W.preΨ₄).eval t ^ 2 * (W.Ψ₂Sq).eval t - (W.Ψ₃).eval t * ((W.preΨ₄).eval t * (W.Ψ₂Sq).eval t ^ 2 - (W.Ψ₃).eval t ^ 3) := by rw [Φ_four]; eval_simp end EvalLemmas end WeierstrassCurve.Affine open Polynomial namespace WeierstrassCurve variable {R : Type u} [CommRing R] (W : WeierstrassCurve R) section ParityResolved variable {m : ℤ} lemma ΨSq_of_even (h : Even m) : W.ΨSq m = W.preΨ m ^ 2 * W.Ψ₂Sq := by rw [show W.ΨSq m = W.preΨ m ^ 2 * if Even m then W.Ψ₂Sq else 1 from rfl, if_pos h] lemma ΨSq_of_odd (h : ¬Even m) : W.ΨSq m = W.preΨ m ^ 2 := by rw [show W.ΨSq m = W.preΨ m ^ 2 * if Even m then W.Ψ₂Sq else 1 from rfl, if_neg h, mul_one] lemma Φ_of_even (h : Even m) : W.Φ m = X * W.ΨSq m - W.preΨ (m + 1) * W.preΨ (m - 1) := by rw [show W.Φ m = X * W.ΨSq m - W.preΨ (m + 1) * W.preΨ (m - 1) * if Even m then 1 else W.Ψ₂Sq from rfl, if_pos h, mul_one] lemma Φ_of_odd (h : ¬Even m) : W.Φ m = X * W.ΨSq m - W.preΨ (m + 1) * W.preΨ (m - 1) * W.Ψ₂Sq := by rw [show W.Φ m = X * W.ΨSq m - W.preΨ (m + 1) * W.preΨ (m - 1) * if Even m then 1 else W.Ψ₂Sq from rfl, if_neg h] lemma preΨ_odd_of_even (h : Even m) : W.preΨ (2 * m + 1) = W.preΨ (m + 2) * W.preΨ m ^ 3 * W.Ψ₂Sq ^ 2 - W.preΨ (m - 1) * W.preΨ (m + 1) ^ 3 := by rw [preΨ_odd, if_pos h, if_pos h, mul_one] lemma preΨ_odd_of_odd (h : ¬Even m) : W.preΨ (2 * m + 1) = W.preΨ (m + 2) * W.preΨ m ^ 3 - W.preΨ (m - 1) * W.preΨ (m + 1) ^ 3 * W.Ψ₂Sq ^ 2 := by rw [preΨ_odd, if_neg h, if_neg h, mul_one] end ParityResolved section DoublingRewrite variable (m : ℤ) lemma Φ_two_mul : W.Φ (2 * m) = X * W.ΨSq (2 * m) - W.preΨ (2 * m + 1) * W.preΨ (2 * m - 1) := W.Φ_of_even (even_two_mul m) lemma Φ_two_mul_add_one : W.Φ (2 * m + 1) = X * W.ΨSq (2 * m + 1) - W.preΨ (2 * m + 2) * W.preΨ (2 * m) * W.Ψ₂Sq := by rw [W.Φ_of_odd m.not_even_two_mul_add_one, show 2 * m + 1 + 1 = 2 * m + 2 by ring, add_sub_cancel_right] lemma preΨ_two_mul_sub_one_of_even {m : ℤ} (hm : Even m) : W.preΨ (2 * m - 1) = W.preΨ (m + 1) * W.preΨ (m - 1) ^ 3 - W.preΨ (m - 2) * W.preΨ m ^ 3 * W.Ψ₂Sq ^ 2 := by have h1 : ¬Even (m - 1) := fun h => (Int.even_sub_one.mp h) hm rw [show 2 * m - 1 = 2 * (m - 1) + 1 by ring, W.preΨ_odd_of_odd h1, show m - 1 + 2 = m + 1 by ring, show m - 1 - 1 = m - 2 by ring, show m - 1 + 1 = m by ring] lemma preΨ_two_mul_sub_one_of_odd {m : ℤ} (hm : ¬Even m) : W.preΨ (2 * m - 1) = W.preΨ (m + 1) * W.preΨ (m - 1) ^ 3 * W.Ψ₂Sq ^ 2 - W.preΨ (m - 2) * W.preΨ m ^ 3 := by have h1 : Even (m - 1) := Int.even_sub_one.mpr hm rw [show 2 * m - 1 = 2 * (m - 1) + 1 by ring, W.preΨ_odd_of_even h1, show m - 1 + 2 = m + 1 by ring, show m - 1 - 1 = m - 2 by ring, show m - 1 + 1 = m by ring] lemma preΨ_two_mul_add_two : W.preΨ (2 * m + 2) = W.preΨ m ^ 2 * W.preΨ (m + 1) * W.preΨ (m + 3) - W.preΨ (m - 1) * W.preΨ (m + 1) * W.preΨ (m + 2) ^ 2 := by rw [show 2 * m + 2 = 2 * (m + 1) by ring, preΨ_even, show m + 1 - 1 = m by ring, show m + 1 - 2 = m - 1 by ring, show m + 1 + 2 = m + 3 by ring, show m + 1 + 1 = m + 2 by ring] end DoublingRewrite section ConsecutiveIdentities variable (m : ℤ) lemma X_mul_ΨSq_sub_Φ : X * W.ΨSq m - W.Φ m = W.preΨ (m + 1) * W.preΨ (m - 1) * if Even m then 1 else W.Ψ₂Sq := by rw [show W.Φ m = X * W.ΨSq m - W.preΨ (m + 1) * W.preΨ (m - 1) * if Even m then 1 else W.Ψ₂Sq from rfl] ring lemma X_mul_ΨSq_sub_Φ_sq : (X * W.ΨSq m - W.Φ m) ^ 2 = W.ΨSq (m + 1) * W.ΨSq (m - 1) := by rw [W.X_mul_ΨSq_sub_Φ m] by_cases hm : Even m · have hm1 : ¬Even (m + 1) := fun h => (Int.even_add_one.mp h) hm have hm2 : ¬Even (m - 1) := fun h => (Int.even_sub_one.mp h) hm rw [if_pos hm, W.ΨSq_of_odd hm1, W.ΨSq_of_odd hm2] ring · have hm1 : Even (m + 1) := Int.even_add_one.mpr hm have hm2 : Even (m - 1) := Int.even_sub_one.mpr hm rw [if_neg hm, W.ΨSq_of_even hm1, W.ΨSq_of_even hm2] ring lemma Φ_succ_mul_ΨSq_sub_Φ_mul_ΨSq_succ : W.Φ (m + 1) * W.ΨSq m - W.Φ m * W.ΨSq (m + 1) = -W.preΨ (2 * m + 1) := by by_cases hm : Even m · have hm1 : ¬Even (m + 1) := fun h => (Int.even_add_one.mp h) hm rw [W.Φ_of_odd hm1, W.Φ_of_even hm, W.ΨSq_of_even hm, W.ΨSq_of_odd hm1, W.preΨ_odd_of_even hm, show m + 1 + 1 = m + 2 by ring, add_sub_cancel_right] ring · have hm1 : Even (m + 1) := Int.even_add_one.mpr hm rw [W.Φ_of_even hm1, W.Φ_of_odd hm, W.ΨSq_of_odd hm, W.ΨSq_of_even hm1, W.preΨ_odd_of_odd hm, show m + 1 + 1 = m + 2 by ring, add_sub_cancel_right] ring lemma Φ_succ_mul_ΨSq_pred_sub_Φ_pred_mul_ΨSq_succ : W.Φ (m + 1) * W.ΨSq (m - 1) - W.Φ (m - 1) * W.ΨSq (m + 1) = -(W.preΨ (2 * m) * W.Ψ₂Sq) := by by_cases hm : Even m · have hm1 : ¬Even (m + 1) := fun h => (Int.even_add_one.mp h) hm have hm2 : ¬Even (m - 1) := fun h => (Int.even_sub_one.mp h) hm rw [W.Φ_of_odd hm1, W.Φ_of_odd hm2, W.ΨSq_of_odd hm1, W.ΨSq_of_odd hm2, preΨ_even, show m + 1 + 1 = m + 2 by ring, add_sub_cancel_right, show m - 1 + 1 = m by ring, show m - 1 - 1 = m - 2 by ring] ring · have hm1 : Even (m + 1) := Int.even_add_one.mpr hm have hm2 : Even (m - 1) := Int.even_sub_one.mpr hm rw [W.Φ_of_even hm1, W.Φ_of_even hm2, W.ΨSq_of_even hm1, W.ΨSq_of_even hm2, preΨ_even, show m + 1 + 1 = m + 2 by ring, add_sub_cancel_right, show m - 1 + 1 = m by ring, show m - 1 - 1 = m - 2 by ring] ring end ConsecutiveIdentities section SmallIndex lemma preΨ'_five_eq : W.preΨ' 5 = W.preΨ₄ * W.Ψ₂Sq ^ 2 - W.Ψ₃ ^ 3 := by rw [show (5 : ℕ) = 2 * (0 + 2) + 1 by rfl, preΨ'_odd] simp lemma preΨ'_six_eq : W.preΨ' 6 = W.Ψ₃ * (W.preΨ₄ * W.Ψ₂Sq ^ 2 - W.Ψ₃ ^ 3 - W.preΨ₄ ^ 2) := by rw [show (6 : ℕ) = 2 * (0 + 3) by rfl, preΨ'_even] simp only [Nat.reduceAdd, preΨ'_one, preΨ'_two, preΨ'_three, preΨ'_four, W.preΨ'_five_eq, one_pow, one_mul] ring lemma ΨSq_five_eq : W.ΨSq 5 = (W.preΨ₄ * W.Ψ₂Sq ^ 2 - W.Ψ₃ ^ 3) ^ 2 := by rw [show (5 : ℤ) = ((5 : ℕ) : ℤ) by rfl, ΨSq_ofNat, W.preΨ'_five_eq, if_neg (by decide : ¬Even (5 : ℕ)), mul_one] lemma Φ_five_eq : W.Φ 5 = X * (W.preΨ₄ * W.Ψ₂Sq ^ 2 - W.Ψ₃ ^ 3) ^ 2 - W.Ψ₃ * (W.preΨ₄ * W.Ψ₂Sq ^ 2 - W.Ψ₃ ^ 3 - W.preΨ₄ ^ 2) * W.preΨ₄ * W.Ψ₂Sq := by rw [show (5 : ℤ) = ((4 : ℕ) + 1 : ℤ) by rfl, Φ_ofNat, show (4 : ℕ) + 1 = 5 by rfl, show (4 : ℕ) + 2 = 6 by rfl, if_pos (by decide : Even (4 : ℕ)), if_pos (by decide : Even (4 : ℕ)), preΨ'_four, W.preΨ'_five_eq, W.preΨ'_six_eq] ring end SmallIndex section StarInstances variable (t : R) lemma ellipticNet_one : 2 * t * (W.Φ 1).eval t * ((W.Φ 1).eval t + t * (W.ΨSq 1).eval t) + W.b₂ * t * ((W.Φ 1).eval t * (W.ΨSq 1).eval t) + W.b₄ * (((W.Φ 1).eval t + t * (W.ΨSq 1).eval t) * (W.ΨSq 1).eval t) + W.b₆ * (W.ΨSq 1).eval t ^ 2 = (W.Φ 2).eval t * (W.ΨSq 0).eval t + (W.Φ 0).eval t * (W.ΨSq 2).eval t := by rw [Φ_zero, Φ_one, ΨSq_zero, ΨSq_one, ΨSq_two, Ψ₂Sq] eval_simp ring set_option maxHeartbeats 1600000 in lemma ellipticNet_three : 2 * t * (W.Φ 3).eval t * ((W.Φ 3).eval t + t * (W.ΨSq 3).eval t) + W.b₂ * t * ((W.Φ 3).eval t * (W.ΨSq 3).eval t) + W.b₄ * (((W.Φ 3).eval t + t * (W.ΨSq 3).eval t) * (W.ΨSq 3).eval t) + W.b₆ * (W.ΨSq 3).eval t ^ 2 = (W.Φ 4).eval t * (W.ΨSq 2).eval t + (W.Φ 2).eval t * (W.ΨSq 4).eval t := by rw [Φ_two, Φ_three, Φ_four, ΨSq_two, ΨSq_three, ΨSq_four, Ψ₂Sq, Ψ₃, preΨ₄] eval_simp linear_combination ((24) * t ^ 15 + (26) * t ^ 14 * W.b₂ + (9) * t ^ 13 * W.b₂ ^ 2 + (96) * t ^ 13 * W.b₄ + t ^ 12 * W.b₂ ^ 3 + (63) * t ^ 12 * W.b₂ * W.b₄ + (150) * t ^ 12 * W.b₆ + (10) * t ^ 11 * W.b₂ ^ 2 * W.b₄ + (93) * t ^ 11 * W.b₂ * W.b₆ + (102) * t ^ 11 * W.b₄ ^ 2 + (128) * t ^ 11 * W.b₈ + (14) * t ^ 10 * W.b₂ ^ 2 * W.b₆ + (31) * t ^ 10 * W.b₂ * W.b₄ ^ 2 + (88) * t ^ 10 * W.b₂ * W.b₈ + (261) * t ^ 10 * W.b₄ * W.b₆ + (18) * t ^ 9 * W.b₂ ^ 2 * W.b₈ + (72) * t ^ 9 * W.b₂ * W.b₄ * W.b₆ + (30) * t ^ 9 * W.b₄ ^ 3 + (216) * t ^ 9 * W.b₄ * W.b₈ + (144) * t ^ 9 * W.b₆ ^ 2 + t ^ 8 * W.b₂ ^ 3 * W.b₈ - t ^ 8 * W.b₂ ^ 2 * W.b₄ * W.b₆ + (82) * t ^ 8 * W.b₂ * W.b₄ * W.b₈ + (36) * t ^ 8 * W.b₂ * W.b₆ ^ 2 + (87) * t ^ 8 * W.b₄ ^ 2 * W.b₆ + (192) * t ^ 8 * W.b₆ * W.b₈ + (6) * t ^ 7 * W.b₂ ^ 2 * W.b₄ * W.b₈ - t ^ 7 * W.b₂ ^ 2 * W.b₆ ^ 2 + (-5) * t ^ 7 * W.b₂ * W.b₄ ^ 2 * W.b₆ + (66) * t ^ 7 * W.b₂ * W.b₆ * W.b₈ + (88) * t ^ 7 * W.b₄ ^ 2 * W.b₈ + (72) * t ^ 7 * W.b₄ * W.b₆ ^ 2 + (40) * t ^ 7 * W.b₈ ^ 2 + (4) * t ^ 6 * W.b₂ ^ 2 * W.b₆ * W.b₈ + (11) * t ^ 6 * W.b₂ * W.b₄ ^ 2 * W.b₈ + (-9) * t ^ 6 * W.b₂ * W.b₄ * W.b₆ ^ 2 + (14) * t ^ 6 * W.b₂ * W.b₈ ^ 2 + (-6) * t ^ 6 * W.b₄ ^ 3 * W.b₆ + (126) * t ^ 6 * W.b₄ * W.b₆ * W.b₈ + (15) * t ^ 6 * W.b₆ ^ 3 + t ^ 5 * W.b₂ ^ 2 * W.b₈ ^ 2 + (12) * t ^ 5 * W.b₂ * W.b₄ * W.b₆ * W.b₈ + (-4) * t ^ 5 * W.b₂ * W.b₆ ^ 3 + (6) * t ^ 5 * W.b₄ ^ 3 * W.b₈ + (-15) * t ^ 5 * W.b₄ ^ 2 * W.b₆ ^ 2 + (24) * t ^ 5 * W.b₄ * W.b₈ ^ 2 + (36) * t ^ 5 * W.b₆ ^ 2 * W.b₈ + (3) * t ^ 4 * W.b₂ * W.b₄ * W.b₈ ^ 2 + (2) * t ^ 4 * W.b₂ * W.b₆ ^ 2 * W.b₈ + (7) * t ^ 4 * W.b₄ ^ 2 * W.b₆ * W.b₈ + (-12) * t ^ 4 * W.b₄ * W.b₆ ^ 3 + (10) * t ^ 4 * W.b₆ * W.b₈ ^ 2 + t ^ 3 * W.b₂ * W.b₆ * W.b₈ ^ 2 + (2) * t ^ 3 * W.b₄ ^ 2 * W.b₈ ^ 2 + (-3) * t ^ 3 * W.b₆ ^ 4 + t ^ 2 * W.b₄ * W.b₆ * W.b₈ ^ 2 - t ^ 2 * W.b₆ ^ 3 * W.b₈) * W.b_relation set_option maxRecDepth 16384 in set_option maxHeartbeats 4000000 in lemma ellipticNet_four : 2 * t * (W.Φ 4).eval t * ((W.Φ 4).eval t + t * (W.ΨSq 4).eval t) + W.b₂ * t * ((W.Φ 4).eval t * (W.ΨSq 4).eval t) + W.b₄ * (((W.Φ 4).eval t + t * (W.ΨSq 4).eval t) * (W.ΨSq 4).eval t) + W.b₆ * (W.ΨSq 4).eval t ^ 2 = (W.Φ 5).eval t * (W.ΨSq 3).eval t + (W.Φ 3).eval t * (W.ΨSq 5).eval t := by rw [Φ_three, Φ_four, W.Φ_five_eq, ΨSq_three, ΨSq_four, W.ΨSq_five_eq, Ψ₂Sq, Ψ₃, preΨ₄] eval_simp linear_combination ((80) * t ^ 29 + (180) * t ^ 28 * W.b₂ + (156) * t ^ 27 * W.b₂ ^ 2 + (936) * t ^ 27 * W.b₄ + (65) * t ^ 26 * W.b₂ ^ 3 + (1560) * t ^ 26 * W.b₂ * W.b₄ + (2340) * t ^ 26 * W.b₆ + (13) * t ^ 25 * W.b₂ ^ 4 + (936) * t ^ 25 * W.b₂ ^ 2 * W.b₄ + (3948) * t ^ 25 * W.b₂ * W.b₆ + (3540) * t ^ 25 * W.b₄ ^ 2 + (2928) * t ^ 25 * W.b₈ + t ^ 24 * W.b₂ ^ 5 + (239) * t ^ 24 * W.b₂ ^ 3 * W.b₄ + (2457) * t ^ 24 * W.b₂ ^ 2 * W.b₆ + (4005) * t ^ 24 * W.b₂ * W.b₄ ^ 2 + (5388) * t ^ 24 * W.b₂ * W.b₈ + (16344) * t ^ 24 * W.b₄ * W.b₆ + (22) * t ^ 23 * W.b₂ ^ 4 * W.b₄ + (688) * t ^ 23 * W.b₂ ^ 3 * W.b₆ + (1413) * t ^ 23 * W.b₂ ^ 2 * W.b₄ ^ 2 + (3864) * t ^ 23 * W.b₂ ^ 2 * W.b₈ + (18870) * t ^ 23 * W.b₂ * W.b₄ * W.b₆ + (5094) * t ^ 23 * W.b₄ ^ 3 + (21096) * t ^ 23 * W.b₄ * W.b₈ + (17460) * t ^ 23 * W.b₆ ^ 2 + (83) * t ^ 22 * W.b₂ ^ 4 * W.b₆ + (148) * t ^ 22 * W.b₂ ^ 3 * W.b₄ ^ 2 + (1379) * t ^ 22 * W.b₂ ^ 3 * W.b₈ + (7107) * t ^ 22 * W.b₂ ^ 2 * W.b₄ * W.b₆ + (3117) * t ^ 22 * W.b₂ * W.b₄ ^ 3 + (28380) * t ^ 22 * W.b₂ * W.b₄ * W.b₈ + (20148) * t ^ 22 * W.b₂ * W.b₆ ^ 2 + (32385) * t ^ 22 * W.b₄ ^ 2 * W.b₆ + (41628) * t ^ 22 * W.b₆ * W.b₈ + (3) * t ^ 21 * W.b₂ ^ 5 * W.b₆ + (-3) * t ^ 21 * W.b₂ ^ 4 * W.b₄ ^ 2 + (260) * t ^ 21 * W.b₂ ^ 4 * W.b₈ + (944) * t ^ 21 * W.b₂ ^ 3 * W.b₄ * W.b₆ + (324) * t ^ 21 * W.b₂ ^ 2 * W.b₄ ^ 3 + (14124) * t ^ 21 * W.b₂ ^ 2 * W.b₄ * W.b₈ + (7737) * t ^ 21 * W.b₂ ^ 2 * W.b₆ ^ 2 + (20436) * t ^ 21 * W.b₂ * W.b₄ ^ 2 * W.b₆ + (54684) * t ^ 21 * W.b₂ * W.b₆ * W.b₈ + (1914) * t ^ 21 * W.b₄ ^ 4 + (47556) * t ^ 21 * W.b₄ ^ 2 * W.b₈ + (62604) * t ^ 21 * W.b₄ * W.b₆ ^ 2 + (23136) * t ^ 21 * W.b₈ ^ 2 + (25) * t ^ 20 * W.b₂ ^ 5 * W.b₈ + (18) * t ^ 20 * W.b₂ ^ 4 * W.b₄ * W.b₆ + (-43) * t ^ 20 * W.b₂ ^ 3 * W.b₄ ^ 3 + (3296) * t ^ 20 * W.b₂ ^ 3 * W.b₄ * W.b₈ + (1121) * t ^ 20 * W.b₂ ^ 3 * W.b₆ ^ 2 + (2682) * t ^ 20 * W.b₂ ^ 2 * W.b₄ ^ 2 * W.b₆ + (26523) * t ^ 20 * W.b₂ ^ 2 * W.b₆ * W.b₈ + (-81) * t ^ 20 * W.b₂ * W.b₄ ^ 4 + (42999) * t ^ 20 * W.b₂ * W.b₄ ^ 2 * W.b₈ + (38610) * t ^ 20 * W.b₂ * W.b₄ * W.b₆ ^ 2 + (33240) * t ^ 20 * W.b₂ * W.b₈ ^ 2 + (13257) * t ^ 20 * W.b₄ ^ 3 * W.b₆ + (167052) * t ^ 20 * W.b₄ * W.b₆ * W.b₈ + (37500) * t ^ 20 * W.b₆ ^ 3 + t ^ 19 * W.b₂ ^ 6 * W.b₈ - t ^ 19 * W.b₂ ^ 5 * W.b₄ * W.b₆ + (370) * t ^ 19 * W.b₂ ^ 4 * W.b₄ * W.b₈ + (39) * t ^ 19 * W.b₂ ^ 4 * W.b₆ ^ 2 + (-195) * t ^ 19 * W.b₂ ^ 3 * W.b₄ ^ 2 * W.b₆ + (6036) * t ^ 19 * W.b₂ ^ 3 * W.b₆ * W.b₈ + (-219) * t ^ 19 * W.b₂ ^ 2 * W.b₄ ^ 4 + (13764) * t ^ 19 * W.b₂ ^ 2 * W.b₄ ^ 2 * W.b₈ + (5166) * t ^ 19 * W.b₂ ^ 2 * W.b₄ * W.b₆ ^ 2 + (18552) * t ^ 19 * W.b₂ ^ 2 * W.b₈ ^ 2 + (-936) * t ^ 19 * W.b₂ * W.b₄ ^ 3 * W.b₆ + (142614) * t ^ 19 * W.b₂ * W.b₄ * W.b₆ * W.b₈ + (21654) * t ^ 19 * W.b₂ * W.b₆ ^ 3 + (-630) * t ^ 19 * W.b₄ ^ 5 + (36486) * t ^ 19 * W.b₄ ^ 3 * W.b₈ + (25605) * t ^ 19 * W.b₄ ^ 2 * W.b₆ ^ 2 + (98352) * t ^ 19 * W.b₄ * W.b₈ ^ 2 + (138384) * t ^ 19 * W.b₆ ^ 2 * W.b₈ + (17) * t ^ 18 * W.b₂ ^ 5 * W.b₄ * W.b₈ - t ^ 18 * W.b₂ ^ 5 * W.b₆ ^ 2 + (-16) * t ^ 18 * W.b₂ ^ 4 * W.b₄ ^ 2 * W.b₆ + (659) * t ^ 18 * W.b₂ ^ 4 * W.b₆ * W.b₈ + (1912) * t ^ 18 * W.b₂ ^ 3 * W.b₄ ^ 2 * W.b₈ + (-354) * t ^ 18 * W.b₂ ^ 3 * W.b₄ * W.b₆ ^ 2 + (5234) * t ^ 18 * W.b₂ ^ 3 * W.b₈ ^ 2 + (-1833) * t ^ 18 * W.b₂ ^ 2 * W.b₄ ^ 3 * W.b₆ + (42840) * t ^ 18 * W.b₂ ^ 2 * W.b₄ * W.b₆ * W.b₈ + (2637) * t ^ 18 * W.b₂ ^ 2 * W.b₆ ^ 3 + (-465) * t ^ 18 * W.b₂ * W.b₄ ^ 5 + (21180) * t ^ 18 * W.b₂ * W.b₄ ^ 3 * W.b₈ + (-7260) * t ^ 18 * W.b₂ * W.b₄ ^ 2 * W.b₆ ^ 2 + (99504) * t ^ 18 * W.b₂ * W.b₄ * W.b₈ ^ 2 + (109056) * t ^ 18 * W.b₂ * W.b₆ ^ 2 * W.b₈ + (-6801) * t ^ 18 * W.b₄ ^ 4 * W.b₆ + (144555) * t ^ 18 * W.b₄ ^ 2 * W.b₆ * W.b₈ + (9486) * t ^ 18 * W.b₄ * W.b₆ ^ 3 + (152760) * t ^ 18 * W.b₆ * W.b₈ ^ 2 + (29) * t ^ 17 * W.b₂ ^ 5 * W.b₆ * W.b₈ + (107) * t ^ 17 * W.b₂ ^ 4 * W.b₄ ^ 2 * W.b₈ + (-45) * t ^ 17 * W.b₂ ^ 4 * W.b₄ * W.b₆ ^ 2 + (798) * t ^ 17 * W.b₂ ^ 4 * W.b₈ ^ 2 + (-91) * t ^ 17 * W.b₂ ^ 3 * W.b₄ ^ 3 * W.b₆ + (5412) * t ^ 17 * W.b₂ ^ 3 * W.b₄ * W.b₆ * W.b₈ + (-233) * t ^ 17 * W.b₂ ^ 3 * W.b₆ ^ 3 + (4092) * t ^ 17 * W.b₂ ^ 2 * W.b₄ ^ 3 * W.b₈ + (-5643) * t ^ 17 * W.b₂ ^ 2 * W.b₄ ^ 2 * W.b₆ ^ 2 + (38928) * t ^ 17 * W.b₂ ^ 2 * W.b₄ * W.b₈ ^ 2 + (30204) * t ^ 17 * W.b₂ ^ 2 * W.b₆ ^ 2 * W.b₈ + (-4692) * t ^ 17 * W.b₂ * W.b₄ ^ 4 * W.b₆ + (73728) * t ^ 17 * W.b₂ * W.b₄ ^ 2 * W.b₆ * W.b₈ + (-17256) * t ^ 17 * W.b₂ * W.b₄ * W.b₆ ^ 3 + (142200) * t ^ 17 * W.b₂ * W.b₆ * W.b₈ ^ 2 + (-350) * t ^ 17 * W.b₄ ^ 6 + (9396) * t ^ 17 * W.b₄ ^ 4 * W.b₈ + (-28836) * t ^ 17 * W.b₄ ^ 3 * W.b₆ ^ 2 + (107784) * t ^ 17 * W.b₄ ^ 2 * W.b₈ ^ 2 + (143712) * t ^ 17 * W.b₄ * W.b₆ ^ 2 * W.b₈ + (-9036) * t ^ 17 * W.b₆ ^ 4 + (51744) * t ^ 17 * W.b₈ ^ 3 + (63) * t ^ 16 * W.b₂ ^ 5 * W.b₈ ^ 2 + (241) * t ^ 16 * W.b₂ ^ 4 * W.b₄ * W.b₆ * W.b₈ + (-29) * t ^ 16 * W.b₂ ^ 4 * W.b₆ ^ 3 + (313) * t ^ 16 * W.b₂ ^ 3 * W.b₄ ^ 3 * W.b₈ + (-366) * t ^ 16 * W.b₂ ^ 3 * W.b₄ ^ 2 * W.b₆ ^ 2 + (7454) * t ^ 16 * W.b₂ ^ 3 * W.b₄ * W.b₈ ^ 2 + (3453) * t ^ 16 * W.b₂ ^ 3 * W.b₆ ^ 2 * W.b₈ + (-222) * t ^ 16 * W.b₂ ^ 2 * W.b₄ ^ 4 * W.b₆ + (11070) * t ^ 16 * W.b₂ ^ 2 * W.b₄ ^ 2 * W.b₆ * W.b₈ + (-7350) * t ^ 16 * W.b₂ ^ 2 * W.b₄ * W.b₆ ^ 3 + (51642) * t ^ 16 * W.b₂ ^ 2 * W.b₆ * W.b₈ ^ 2 + (3291) * t ^ 16 * W.b₂ * W.b₄ ^ 4 * W.b₈ + (-17049) * t ^ 16 * W.b₂ * W.b₄ ^ 3 * W.b₆ ^ 2 + (80082) * t ^ 16 * W.b₂ * W.b₄ ^ 2 * W.b₈ ^ 2 + (55956) * t ^ 16 * W.b₂ * W.b₄ * W.b₆ ^ 2 * W.b₈ + (-12561) * t ^ 16 * W.b₂ * W.b₆ ^ 4 + (53416) * t ^ 16 * W.b₂ * W.b₈ ^ 3 + (-3789) * t ^ 16 * W.b₄ ^ 5 * W.b₆ + (22476) * t ^ 16 * W.b₄ ^ 3 * W.b₆ * W.b₈ + (-55650) * t ^ 16 * W.b₄ ^ 2 * W.b₆ ^ 3 + (216624) * t ^ 16 * W.b₄ * W.b₆ * W.b₈ ^ 2 + (5064) * t ^ 16 * W.b₆ ^ 3 * W.b₈ + (2) * t ^ 15 * W.b₂ ^ 6 * W.b₈ ^ 2 + (-4) * t ^ 15 * W.b₂ ^ 5 * W.b₄ * W.b₆ * W.b₈ + (2) * t ^ 15 * W.b₂ ^ 4 * W.b₄ ^ 2 * W.b₆ ^ 2 + (706) * t ^ 15 * W.b₂ ^ 4 * W.b₄ * W.b₈ ^ 2 + (125) * t ^ 15 * W.b₂ ^ 4 * W.b₆ ^ 2 * W.b₈ + (379) * t ^ 15 * W.b₂ ^ 3 * W.b₄ ^ 2 * W.b₆ * W.b₈ + (-463) * t ^ 15 * W.b₂ ^ 3 * W.b₄ * W.b₆ ^ 3 + (9260) * t ^ 15 * W.b₂ ^ 3 * W.b₆ * W.b₈ ^ 2 + (444) * t ^ 15 * W.b₂ ^ 2 * W.b₄ ^ 4 * W.b₈ + (-969) * t ^ 15 * W.b₂ ^ 2 * W.b₄ ^ 3 * W.b₆ ^ 2 + (22278) * t ^ 15 * W.b₂ ^ 2 * W.b₄ ^ 2 * W.b₈ ^ 2 + (3222) * t ^ 15 * W.b₂ ^ 2 * W.b₄ * W.b₆ ^ 2 * W.b₈ + (-3486) * t ^ 15 * W.b₂ ^ 2 * W.b₆ ^ 4 + (22528) * t ^ 15 * W.b₂ ^ 2 * W.b₈ ^ 3 + (-222) * t ^ 15 * W.b₂ * W.b₄ ^ 5 * W.b₆ + (936) * t ^ 15 * W.b₂ * W.b₄ ^ 3 * W.b₆ * W.b₈ + (-27453) * t ^ 15 * W.b₂ * W.b₄ ^ 2 * W.b₆ ^ 3 + (147804) * t ^ 15 * W.b₂ * W.b₄ * W.b₆ * W.b₈ ^ 2 + (-12924) * t ^ 15 * W.b₂ * W.b₆ ^ 3 * W.b₈ + (414) * t ^ 15 * W.b₄ ^ 5 * W.b₈ + (-14781) * t ^ 15 * W.b₄ ^ 4 * W.b₆ ^ 2 + (46764) * t ^ 15 * W.b₄ ^ 3 * W.b₈ ^ 2 + (-27132) * t ^ 15 * W.b₄ ^ 2 * W.b₆ ^ 2 * W.b₈ + (-46854) * t ^ 15 * W.b₄ * W.b₆ ^ 4 + (80048) * t ^ 15 * W.b₄ * W.b₈ ^ 3 + (33288) * t ^ 15 * W.b₆ ^ 2 * W.b₈ ^ 2 + (26) * t ^ 14 * W.b₂ ^ 5 * W.b₄ * W.b₈ ^ 2 + (-4) * t ^ 14 * W.b₂ ^ 5 * W.b₆ ^ 2 * W.b₈ + (-48) * t ^ 14 * W.b₂ ^ 4 * W.b₄ ^ 2 * W.b₆ * W.b₈ + (4) * t ^ 14 * W.b₂ ^ 4 * W.b₄ * W.b₆ ^ 3 + (829) * t ^ 14 * W.b₂ ^ 4 * W.b₆ * W.b₈ ^ 2 + (22) * t ^ 14 * W.b₂ ^ 3 * W.b₄ ^ 3 * W.b₆ ^ 2 + (2788) * t ^ 14 * W.b₂ ^ 3 * W.b₄ ^ 2 * W.b₈ ^ 2 + (-717) * t ^ 14 * W.b₂ ^ 3 * W.b₄ * W.b₆ ^ 2 * W.b₈ + (-188) * t ^ 14 * W.b₂ ^ 3 * W.b₆ ^ 4 + (4990) * t ^ 14 * W.b₂ ^ 3 * W.b₈ ^ 3 + (-855) * t ^ 14 * W.b₂ ^ 2 * W.b₄ ^ 3 * W.b₆ * W.b₈ + (-1314) * t ^ 14 * W.b₂ ^ 2 * W.b₄ ^ 2 * W.b₆ ^ 3 + (37878) * t ^ 14 * W.b₂ ^ 2 * W.b₄ * W.b₆ * W.b₈ ^ 2 + (-6495) * t ^ 14 * W.b₂ ^ 2 * W.b₆ ^ 3 * W.b₈ + (282) * t ^ 14 * W.b₂ * W.b₄ ^ 5 * W.b₈ + (-765) * t ^ 14 * W.b₂ * W.b₄ ^ 4 * W.b₆ ^ 2 + (25854) * t ^ 14 * W.b₂ * W.b₄ ^ 3 * W.b₈ ^ 2 + (-30768) * t ^ 14 * W.b₂ * W.b₄ ^ 2 * W.b₆ ^ 2 * W.b₈ + (-19005) * t ^ 14 * W.b₂ * W.b₄ * W.b₆ ^ 4 + (66664) * t ^ 14 * W.b₂ * W.b₄ * W.b₈ ^ 3 + (16488) * t ^ 14 * W.b₂ * W.b₆ ^ 2 * W.b₈ ^ 2 + (-60) * t ^ 14 * W.b₄ ^ 6 * W.b₆ + (-9309) * t ^ 14 * W.b₄ ^ 4 * W.b₆ * W.b₈ + (-26235) * t ^ 14 * W.b₄ ^ 3 * W.b₆ ^ 3 + (82122) * t ^ 14 * W.b₄ ^ 2 * W.b₆ * W.b₈ ^ 2 + (-85284) * t ^ 14 * W.b₄ * W.b₆ ^ 3 * W.b₈ + (-12519) * t ^ 14 * W.b₆ ^ 5 + (14536) * t ^ 14 * W.b₆ * W.b₈ ^ 3 + (29) * t ^ 13 * W.b₂ ^ 5 * W.b₆ * W.b₈ ^ 2 + (127) * t ^ 13 * W.b₂ ^ 4 * W.b₄ ^ 2 * W.b₈ ^ 2 + (-106) * t ^ 13 * W.b₂ ^ 4 * W.b₄ * W.b₆ ^ 2 * W.b₈ + (2) * t ^ 13 * W.b₂ ^ 4 * W.b₆ ^ 4 + (612) * t ^ 13 * W.b₂ ^ 4 * W.b₈ ^ 3 + (-206) * t ^ 13 * W.b₂ ^ 3 * W.b₄ ^ 3 * W.b₆ * W.b₈ + (73) * t ^ 13 * W.b₂ ^ 3 * W.b₄ ^ 2 * W.b₆ ^ 3 + (4312) * t ^ 13 * W.b₂ ^ 3 * W.b₄ * W.b₆ * W.b₈ ^ 2 + (-925) * t ^ 13 * W.b₂ ^ 3 * W.b₆ ^ 3 * W.b₈ + (81) * t ^ 13 * W.b₂ ^ 2 * W.b₄ ^ 4 * W.b₆ ^ 2 + (5004) * t ^ 13 * W.b₂ ^ 2 * W.b₄ ^ 3 * W.b₈ ^ 2 + (-6111) * t ^ 13 * W.b₂ ^ 2 * W.b₄ ^ 2 * W.b₆ ^ 2 * W.b₈ + (-471) * t ^ 13 * W.b₂ ^ 2 * W.b₄ * W.b₆ ^ 4 + (22200) * t ^ 13 * W.b₂ ^ 2 * W.b₄ * W.b₈ ^ 3 + (3174) * t ^ 13 * W.b₂ ^ 2 * W.b₆ ^ 2 * W.b₈ ^ 2 + (-2484) * t ^ 13 * W.b₂ * W.b₄ ^ 4 * W.b₆ * W.b₈ + (-105) * t ^ 13 * W.b₂ * W.b₄ ^ 3 * W.b₆ ^ 3 + (40872) * t ^ 13 * W.b₂ * W.b₄ ^ 2 * W.b₆ * W.b₈ ^ 2 + (-47340) * t ^ 13 * W.b₂ * W.b₄ * W.b₆ ^ 3 * W.b₈ + (-4074) * t ^ 13 * W.b₂ * W.b₆ ^ 5 + (12536) * t ^ 13 * W.b₂ * W.b₆ * W.b₈ ^ 3 + (60) * t ^ 13 * W.b₄ ^ 6 * W.b₈ + (108) * t ^ 13 * W.b₄ ^ 5 * W.b₆ ^ 2 + (9576) * t ^ 13 * W.b₄ ^ 4 * W.b₈ ^ 2 + (-44412) * t ^ 13 * W.b₄ ^ 3 * W.b₆ ^ 2 * W.b₈ + (-21432) * t ^ 13 * W.b₄ ^ 2 * W.b₆ ^ 4 + (44776) * t ^ 13 * W.b₄ ^ 2 * W.b₈ ^ 3 + (-24936) * t ^ 13 * W.b₄ * W.b₆ ^ 2 * W.b₈ ^ 2 + (-33780) * t ^ 13 * W.b₆ ^ 4 * W.b₈ + (-3760) * t ^ 13 * W.b₈ ^ 4 + (39) * t ^ 12 * W.b₂ ^ 5 * W.b₈ ^ 3 + (148) * t ^ 12 * W.b₂ ^ 4 * W.b₄ * W.b₆ * W.b₈ ^ 2 + (-58) * t ^ 12 * W.b₂ ^ 4 * W.b₆ ^ 3 * W.b₈ + (307) * t ^ 12 * W.b₂ ^ 3 * W.b₄ ^ 3 * W.b₈ ^ 2 + (-561) * t ^ 12 * W.b₂ ^ 3 * W.b₄ ^ 2 * W.b₆ ^ 2 * W.b₈ + (80) * t ^ 12 * W.b₂ ^ 3 * W.b₄ * W.b₆ ^ 4 + (3672) * t ^ 12 * W.b₂ ^ 3 * W.b₄ * W.b₈ ^ 3 + (243) * t ^ 12 * W.b₂ ^ 3 * W.b₆ ^ 2 * W.b₈ ^ 2 + (-408) * t ^ 12 * W.b₂ ^ 2 * W.b₄ ^ 4 * W.b₆ * W.b₈ + (330) * t ^ 12 * W.b₂ ^ 2 * W.b₄ ^ 3 * W.b₆ ^ 3 + (7038) * t ^ 12 * W.b₂ ^ 2 * W.b₄ ^ 2 * W.b₆ * W.b₈ ^ 2 + (-6657) * t ^ 12 * W.b₂ ^ 2 * W.b₄ * W.b₆ ^ 3 * W.b₈ + (96) * t ^ 12 * W.b₂ ^ 2 * W.b₆ ^ 5 + (4998) * t ^ 12 * W.b₂ ^ 2 * W.b₆ * W.b₈ ^ 3 + (123) * t ^ 12 * W.b₂ * W.b₄ ^ 5 * W.b₆ ^ 2 + (4137) * t ^ 12 * W.b₂ * W.b₄ ^ 4 * W.b₈ ^ 2 + (-10965) * t ^ 12 * W.b₂ * W.b₄ ^ 3 * W.b₆ ^ 2 * W.b₈ + (2049) * t ^ 12 * W.b₂ * W.b₄ ^ 2 * W.b₆ ^ 4 + (30798) * t ^ 12 * W.b₂ * W.b₄ ^ 2 * W.b₈ ^ 3 + (-13416) * t ^ 12 * W.b₂ * W.b₄ * W.b₆ ^ 2 * W.b₈ ^ 2 + (-14865) * t ^ 12 * W.b₂ * W.b₆ ^ 4 * W.b₈ + (-2956) * t ^ 12 * W.b₂ * W.b₈ ^ 4 + (-1446) * t ^ 12 * W.b₄ ^ 5 * W.b₆ * W.b₈ + (1833) * t ^ 12 * W.b₄ ^ 4 * W.b₆ ^ 3 + (5862) * t ^ 12 * W.b₄ ^ 3 * W.b₆ * W.b₈ ^ 2 + (-62310) * t ^ 12 * W.b₄ ^ 2 * W.b₆ ^ 3 * W.b₈ + (-6903) * t ^ 12 * W.b₄ * W.b₆ ^ 5 + (2696) * t ^ 12 * W.b₄ * W.b₆ * W.b₈ ^ 3 + (-29280) * t ^ 12 * W.b₆ ^ 3 * W.b₈ ^ 2 + t ^ 11 * W.b₂ ^ 6 * W.b₈ ^ 3 + (-3) * t ^ 11 * W.b₂ ^ 5 * W.b₄ * W.b₆ * W.b₈ ^ 2 + (3) * t ^ 11 * W.b₂ ^ 4 * W.b₄ ^ 2 * W.b₆ ^ 2 * W.b₈ + (294) * t ^ 11 * W.b₂ ^ 4 * W.b₄ * W.b₈ ^ 3 + (-27) * t ^ 11 * W.b₂ ^ 4 * W.b₆ ^ 2 * W.b₈ ^ 2 - t ^ 11 * W.b₂ ^ 3 * W.b₄ ^ 3 * W.b₆ ^ 3 + (167) * t ^ 11 * W.b₂ ^ 3 * W.b₄ ^ 2 * W.b₆ * W.b₈ ^ 2 + (-418) * t ^ 11 * W.b₂ ^ 3 * W.b₄ * W.b₆ ^ 3 * W.b₈ + (29) * t ^ 11 * W.b₂ ^ 3 * W.b₆ ^ 5 + (1020) * t ^ 11 * W.b₂ ^ 3 * W.b₆ * W.b₈ ^ 3 + (393) * t ^ 11 * W.b₂ ^ 2 * W.b₄ ^ 4 * W.b₈ ^ 2 + (-1152) * t ^ 11 * W.b₂ ^ 2 * W.b₄ ^ 3 * W.b₆ ^ 2 * W.b₈ + (468) * t ^ 11 * W.b₂ ^ 2 * W.b₄ ^ 2 * W.b₆ ^ 4 + (7956) * t ^ 11 * W.b₂ ^ 2 * W.b₄ ^ 2 * W.b₈ ^ 3 + (-2070) * t ^ 11 * W.b₂ ^ 2 * W.b₄ * W.b₆ ^ 2 * W.b₈ ^ 2 + (-1512) * t ^ 11 * W.b₂ ^ 2 * W.b₆ ^ 4 * W.b₈ + (-788) * t ^ 11 * W.b₂ ^ 2 * W.b₈ ^ 4 + (-378) * t ^ 11 * W.b₂ * W.b₄ ^ 5 * W.b₆ * W.b₈ + (558) * t ^ 11 * W.b₂ * W.b₄ ^ 4 * W.b₆ ^ 3 + (3384) * t ^ 11 * W.b₂ * W.b₄ ^ 3 * W.b₆ * W.b₈ ^ 2 + (-11775) * t ^ 11 * W.b₂ * W.b₄ ^ 2 * W.b₆ ^ 3 * W.b₈ + (2268) * t ^ 11 * W.b₂ * W.b₄ * W.b₆ ^ 5 + (8172) * t ^ 11 * W.b₂ * W.b₄ * W.b₆ * W.b₈ ^ 3 + (-12984) * t ^ 11 * W.b₂ * W.b₆ ^ 3 * W.b₈ ^ 2 + (66) * t ^ 11 * W.b₄ ^ 6 * W.b₆ ^ 2 + (1278) * t ^ 11 * W.b₄ ^ 5 * W.b₈ ^ 2 + (-5220) * t ^ 11 * W.b₄ ^ 4 * W.b₆ ^ 2 * W.b₈ + (4671) * t ^ 11 * W.b₄ ^ 3 * W.b₆ ^ 4 + (12892) * t ^ 11 * W.b₄ ^ 3 * W.b₈ ^ 3 + (-32682) * t ^ 11 * W.b₄ ^ 2 * W.b₆ ^ 2 * W.b₈ ^ 2 + (-30126) * t ^ 11 * W.b₄ * W.b₆ ^ 4 * W.b₈ + (-6616) * t ^ 11 * W.b₄ * W.b₈ ^ 4 + (-489) * t ^ 11 * W.b₆ ^ 6 + (-13264) * t ^ 11 * W.b₆ ^ 2 * W.b₈ ^ 3 + (9) * t ^ 10 * W.b₂ ^ 5 * W.b₄ * W.b₈ ^ 3 + (-3) * t ^ 10 * W.b₂ ^ 5 * W.b₆ ^ 2 * W.b₈ ^ 2 + (-24) * t ^ 10 * W.b₂ ^ 4 * W.b₄ ^ 2 * W.b₆ * W.b₈ ^ 2 + (6) * t ^ 10 * W.b₂ ^ 4 * W.b₄ * W.b₆ ^ 3 * W.b₈ + (93) * t ^ 10 * W.b₂ ^ 4 * W.b₆ * W.b₈ ^ 3 + (21) * t ^ 10 * W.b₂ ^ 3 * W.b₄ ^ 3 * W.b₆ ^ 2 * W.b₈ + (-3) * t ^ 10 * W.b₂ ^ 3 * W.b₄ ^ 2 * W.b₆ ^ 4 + (864) * t ^ 10 * W.b₂ ^ 3 * W.b₄ ^ 2 * W.b₈ ^ 3 + (-432) * t ^ 10 * W.b₂ ^ 3 * W.b₄ * W.b₆ ^ 2 * W.b₈ ^ 2 + (-63) * t ^ 10 * W.b₂ ^ 3 * W.b₆ ^ 4 * W.b₈ + (-83) * t ^ 10 * W.b₂ ^ 3 * W.b₈ ^ 4 + (-6) * t ^ 10 * W.b₂ ^ 2 * W.b₄ ^ 4 * W.b₆ ^ 3 + (-243) * t ^ 10 * W.b₂ ^ 2 * W.b₄ ^ 3 * W.b₆ * W.b₈ ^ 2 + (-861) * t ^ 10 * W.b₂ ^ 2 * W.b₄ ^ 2 * W.b₆ ^ 3 * W.b₈ + (270) * t ^ 10 * W.b₂ ^ 2 * W.b₄ * W.b₆ ^ 5 + (3824) * t ^ 10 * W.b₂ ^ 2 * W.b₄ * W.b₆ * W.b₈ ^ 3 + (-1689) * t ^ 10 * W.b₂ ^ 2 * W.b₆ ^ 3 * W.b₈ ^ 2 + (255) * t ^ 10 * W.b₂ * W.b₄ ^ 5 * W.b₈ ^ 2 + (-975) * t ^ 10 * W.b₂ * W.b₄ ^ 4 * W.b₆ ^ 2 * W.b₈ + (909) * t ^ 10 * W.b₂ * W.b₄ ^ 3 * W.b₆ ^ 4 + (7356) * t ^ 10 * W.b₂ * W.b₄ ^ 3 * W.b₈ ^ 3 + (-7668) * t ^ 10 * W.b₂ * W.b₄ ^ 2 * W.b₆ ^ 2 * W.b₈ ^ 2 + (-3006) * t ^ 10 * W.b₂ * W.b₄ * W.b₆ ^ 4 * W.b₈ + (-3272) * t ^ 10 * W.b₂ * W.b₄ * W.b₈ ^ 4 + (657) * t ^ 10 * W.b₂ * W.b₆ ^ 6 + (-4272) * t ^ 10 * W.b₂ * W.b₆ ^ 2 * W.b₈ ^ 3 + (-132) * t ^ 10 * W.b₄ ^ 6 * W.b₆ * W.b₈ + (315) * t ^ 10 * W.b₄ ^ 5 * W.b₆ ^ 3 + (-183) * t ^ 10 * W.b₄ ^ 4 * W.b₆ * W.b₈ ^ 2 + (-4077) * t ^ 10 * W.b₄ ^ 3 * W.b₆ ^ 3 * W.b₈ + (4869) * t ^ 10 * W.b₄ ^ 2 * W.b₆ ^ 5 + (-426) * t ^ 10 * W.b₄ ^ 2 * W.b₆ * W.b₈ ^ 3 + (-28800) * t ^ 10 * W.b₄ * W.b₆ ^ 3 * W.b₈ ^ 2 + (-4095) * t ^ 10 * W.b₆ ^ 5 * W.b₈ + (-5340) * t ^ 10 * W.b₆ * W.b₈ ^ 4 + (3) * t ^ 9 * W.b₂ ^ 5 * W.b₆ * W.b₈ ^ 3 + (33) * t ^ 9 * W.b₂ ^ 4 * W.b₄ ^ 2 * W.b₈ ^ 3 + (-33) * t ^ 9 * W.b₂ ^ 4 * W.b₄ * W.b₆ ^ 2 * W.b₈ ^ 2 + (3) * t ^ 9 * W.b₂ ^ 4 * W.b₆ ^ 4 * W.b₈ + (-3) * t ^ 9 * W.b₂ ^ 4 * W.b₈ ^ 4 + (-75) * t ^ 9 * W.b₂ ^ 3 * W.b₄ ^ 3 * W.b₆ * W.b₈ ^ 2 + (51) * t ^ 9 * W.b₂ ^ 3 * W.b₄ ^ 2 * W.b₆ ^ 3 * W.b₈ + (-3) * t ^ 9 * W.b₂ ^ 3 * W.b₄ * W.b₆ ^ 5 + (516) * t ^ 9 * W.b₂ ^ 3 * W.b₄ * W.b₆ * W.b₈ ^ 3 + (-171) * t ^ 9 * W.b₂ ^ 3 * W.b₆ ^ 3 * W.b₈ ^ 2 + (54) * t ^ 9 * W.b₂ ^ 2 * W.b₄ ^ 4 * W.b₆ ^ 2 * W.b₈ + (-21) * t ^ 9 * W.b₂ ^ 2 * W.b₄ ^ 3 * W.b₆ ^ 4 + (1236) * t ^ 9 * W.b₂ ^ 2 * W.b₄ ^ 3 * W.b₈ ^ 3 + (-1569) * t ^ 9 * W.b₂ ^ 2 * W.b₄ ^ 2 * W.b₆ ^ 2 * W.b₈ ^ 2 + (-54) * t ^ 9 * W.b₂ ^ 2 * W.b₄ * W.b₆ ^ 4 * W.b₈ + (-472) * t ^ 9 * W.b₂ ^ 2 * W.b₄ * W.b₈ ^ 4 + (51) * t ^ 9 * W.b₂ ^ 2 * W.b₆ ^ 6 + (44) * t ^ 9 * W.b₂ ^ 2 * W.b₆ ^ 2 * W.b₈ ^ 3 + (-12) * t ^ 9 * W.b₂ * W.b₄ ^ 5 * W.b₆ ^ 3 + (-576) * t ^ 9 * W.b₂ * W.b₄ ^ 4 * W.b₆ * W.b₈ ^ 2 + (-426) * t ^ 9 * W.b₂ * W.b₄ ^ 3 * W.b₆ ^ 3 * W.b₈ + (651) * t ^ 9 * W.b₂ * W.b₄ ^ 2 * W.b₆ ^ 5 + (4544) * t ^ 9 * W.b₂ * W.b₄ ^ 2 * W.b₆ * W.b₈ ^ 3 + (-5760) * t ^ 9 * W.b₂ * W.b₄ * W.b₆ ^ 3 * W.b₈ ^ 2 + (300) * t ^ 9 * W.b₂ * W.b₆ ^ 5 * W.b₈ + (-2404) * t ^ 9 * W.b₂ * W.b₆ * W.b₈ ^ 4 + (66) * t ^ 9 * W.b₄ ^ 6 * W.b₈ ^ 2 + (-264) * t ^ 9 * W.b₄ ^ 5 * W.b₆ ^ 2 * W.b₈ + (543) * t ^ 9 * W.b₄ ^ 4 * W.b₆ ^ 4 + (2460) * t ^ 9 * W.b₄ ^ 4 * W.b₈ ^ 3 + (-5100) * t ^ 9 * W.b₄ ^ 3 * W.b₆ ^ 2 * W.b₈ ^ 2 + (1752) * t ^ 9 * W.b₄ ^ 2 * W.b₆ ^ 4 * W.b₈ + (-3164) * t ^ 9 * W.b₄ ^ 2 * W.b₈ ^ 4 + (2232) * t ^ 9 * W.b₄ * W.b₆ ^ 6 + (-9792) * t ^ 9 * W.b₄ * W.b₆ ^ 2 * W.b₈ ^ 3 + (-5460) * t ^ 9 * W.b₆ ^ 4 * W.b₈ ^ 2 + (-400) * t ^ 9 * W.b₈ ^ 5 + (21) * t ^ 8 * W.b₂ ^ 4 * W.b₄ * W.b₆ * W.b₈ ^ 3 + (-9) * t ^ 8 * W.b₂ ^ 4 * W.b₆ ^ 3 * W.b₈ ^ 2 + (63) * t ^ 8 * W.b₂ ^ 3 * W.b₄ ^ 3 * W.b₈ ^ 3 + (-129) * t ^ 8 * W.b₂ ^ 3 * W.b₄ ^ 2 * W.b₆ ^ 2 * W.b₈ ^ 2 + (39) * t ^ 8 * W.b₂ ^ 3 * W.b₄ * W.b₆ ^ 4 * W.b₈ + (-21) * t ^ 8 * W.b₂ ^ 3 * W.b₄ * W.b₈ ^ 4 - t ^ 8 * W.b₂ ^ 3 * W.b₆ ^ 6 + (63) * t ^ 8 * W.b₂ ^ 3 * W.b₆ ^ 2 * W.b₈ ^ 3 + (-114) * t ^ 8 * W.b₂ ^ 2 * W.b₄ ^ 4 * W.b₆ * W.b₈ ^ 2 + (153) * t ^ 8 * W.b₂ ^ 2 * W.b₄ ^ 3 * W.b₆ ^ 3 * W.b₈ + (-27) * t ^ 8 * W.b₂ ^ 2 * W.b₄ ^ 2 * W.b₆ ^ 5 + (1050) * t ^ 8 * W.b₂ ^ 2 * W.b₄ ^ 2 * W.b₆ * W.b₈ ^ 3 + (-924) * t ^ 8 * W.b₂ ^ 2 * W.b₄ * W.b₆ ^ 3 * W.b₈ ^ 2 + (63) * t ^ 8 * W.b₂ ^ 2 * W.b₆ ^ 5 * W.b₈ + (-307) * t ^ 8 * W.b₂ ^ 2 * W.b₆ * W.b₈ ^ 4 + (60) * t ^ 8 * W.b₂ * W.b₄ ^ 5 * W.b₆ ^ 2 * W.b₈ + (-48) * t ^ 8 * W.b₂ * W.b₄ ^ 4 * W.b₆ ^ 4 + (861) * t ^ 8 * W.b₂ * W.b₄ ^ 4 * W.b₈ ^ 3 + (-2079) * t ^ 8 * W.b₂ * W.b₄ ^ 3 * W.b₆ ^ 2 * W.b₈ ^ 2 + (522) * t ^ 8 * W.b₂ * W.b₄ ^ 2 * W.b₆ ^ 4 * W.b₈ + (-823) * t ^ 8 * W.b₂ * W.b₄ ^ 2 * W.b₈ ^ 4 + (192) * t ^ 8 * W.b₂ * W.b₄ * W.b₆ ^ 6 + (-36) * t ^ 8 * W.b₂ * W.b₄ * W.b₆ ^ 2 * W.b₈ ^ 3 + (-639) * t ^ 8 * W.b₂ * W.b₆ ^ 4 * W.b₈ ^ 2 + (-180) * t ^ 8 * W.b₂ * W.b₈ ^ 5 + (-8) * t ^ 8 * W.b₄ ^ 6 * W.b₆ ^ 3 + (-285) * t ^ 8 * W.b₄ ^ 5 * W.b₆ * W.b₈ ^ 2 + (153) * t ^ 8 * W.b₄ ^ 4 * W.b₆ ^ 3 * W.b₈ + (405) * t ^ 8 * W.b₄ ^ 3 * W.b₆ ^ 5 + (1868) * t ^ 8 * W.b₄ ^ 3 * W.b₆ * W.b₈ ^ 3 + (-3150) * t ^ 8 * W.b₄ ^ 2 * W.b₆ ^ 3 * W.b₈ ^ 2 + (2718) * t ^ 8 * W.b₄ * W.b₆ ^ 5 * W.b₈ + (-4104) * t ^ 8 * W.b₄ * W.b₆ * W.b₈ ^ 4 + (369) * t ^ 8 * W.b₆ ^ 7 + (-2616) * t ^ 8 * W.b₆ ^ 3 * W.b₈ ^ 3 + (3) * t ^ 7 * W.b₂ ^ 4 * W.b₆ ^ 2 * W.b₈ ^ 3 + (57) * t ^ 7 * W.b₂ ^ 3 * W.b₄ ^ 2 * W.b₆ * W.b₈ ^ 3 + (-63) * t ^ 7 * W.b₂ ^ 3 * W.b₄ * W.b₆ ^ 3 * W.b₈ ^ 2 + (9) * t ^ 7 * W.b₂ ^ 3 * W.b₆ ^ 5 * W.b₈ + (-12) * t ^ 7 * W.b₂ ^ 3 * W.b₆ * W.b₈ ^ 4 + (66) * t ^ 7 * W.b₂ ^ 2 * W.b₄ ^ 4 * W.b₈ ^ 3 + (-231) * t ^ 7 * W.b₂ ^ 2 * W.b₄ ^ 3 * W.b₆ ^ 2 * W.b₈ ^ 2 + (153) * t ^ 7 * W.b₂ ^ 2 * W.b₄ ^ 2 * W.b₆ ^ 4 * W.b₈ + (-51) * t ^ 7 * W.b₂ ^ 2 * W.b₄ ^ 2 * W.b₈ ^ 4 + (-15) * t ^ 7 * W.b₂ ^ 2 * W.b₄ * W.b₆ ^ 6 + (258) * t ^ 7 * W.b₂ ^ 2 * W.b₄ * W.b₆ ^ 2 * W.b₈ ^ 3 + (-126) * t ^ 7 * W.b₂ ^ 2 * W.b₆ ^ 4 * W.b₈ ^ 2 + (-24) * t ^ 7 * W.b₂ ^ 2 * W.b₈ ^ 5 + (-84) * t ^ 7 * W.b₂ * W.b₄ ^ 5 * W.b₆ * W.b₈ ^ 2 + (192) * t ^ 7 * W.b₂ * W.b₄ ^ 4 * W.b₆ ^ 3 * W.b₈ + (-75) * t ^ 7 * W.b₂ * W.b₄ ^ 3 * W.b₆ ^ 5 + (936) * t ^ 7 * W.b₂ * W.b₄ ^ 3 * W.b₆ * W.b₈ ^ 3 + (-1503) * t ^ 7 * W.b₂ * W.b₄ ^ 2 * W.b₆ ^ 3 * W.b₈ ^ 2 + (426) * t ^ 7 * W.b₂ * W.b₄ * W.b₆ ^ 5 * W.b₈ + (-914) * t ^ 7 * W.b₂ * W.b₄ * W.b₆ * W.b₈ ^ 4 + (15) * t ^ 7 * W.b₂ * W.b₆ ^ 7 + (-68) * t ^ 7 * W.b₂ * W.b₆ ^ 3 * W.b₈ ^ 3 + (24) * t ^ 7 * W.b₄ ^ 6 * W.b₆ ^ 2 * W.b₈ + (-36) * t ^ 7 * W.b₄ ^ 5 * W.b₆ ^ 4 + (234) * t ^ 7 * W.b₄ ^ 5 * W.b₈ ^ 3 + (-921) * t ^ 7 * W.b₄ ^ 4 * W.b₆ ^ 2 * W.b₈ ^ 2 + (642) * t ^ 7 * W.b₄ ^ 3 * W.b₆ ^ 4 * W.b₈ + (-434) * t ^ 7 * W.b₄ ^ 3 * W.b₈ ^ 4 + (102) * t ^ 7 * W.b₄ ^ 2 * W.b₆ ^ 6 + (372) * t ^ 7 * W.b₄ ^ 2 * W.b₆ ^ 2 * W.b₈ ^ 3 + (390) * t ^ 7 * W.b₄ * W.b₆ ^ 4 * W.b₈ ^ 2 + (-280) * t ^ 7 * W.b₄ * W.b₈ ^ 5 + (678) * t ^ 7 * W.b₆ ^ 6 * W.b₈ + (-1020) * t ^ 7 * W.b₆ ^ 2 * W.b₈ ^ 4 + (15) * t ^ 6 * W.b₂ ^ 3 * W.b₄ * W.b₆ ^ 2 * W.b₈ ^ 3 + (-9) * t ^ 6 * W.b₂ ^ 3 * W.b₆ ^ 4 * W.b₈ ^ 2 - t ^ 6 * W.b₂ ^ 3 * W.b₈ ^ 5 + (75) * t ^ 6 * W.b₂ ^ 2 * W.b₄ ^ 3 * W.b₆ * W.b₈ ^ 3 + (-153) * t ^ 6 * W.b₂ ^ 2 * W.b₄ ^ 2 * W.b₆ ^ 3 * W.b₈ ^ 2 + (63) * t ^ 6 * W.b₂ ^ 2 * W.b₄ * W.b₆ ^ 5 * W.b₈ + (-49) * t ^ 6 * W.b₂ ^ 2 * W.b₄ * W.b₆ * W.b₈ ^ 4 + (-3) * t ^ 6 * W.b₂ ^ 2 * W.b₆ ^ 7 + (27) * t ^ 6 * W.b₂ ^ 2 * W.b₆ ^ 3 * W.b₈ ^ 3 + (36) * t ^ 6 * W.b₂ * W.b₄ ^ 5 * W.b₈ ^ 3 + (-192) * t ^ 6 * W.b₂ * W.b₄ ^ 4 * W.b₆ ^ 2 * W.b₈ ^ 2 + (231) * t ^ 6 * W.b₂ * W.b₄ ^ 3 * W.b₆ ^ 4 * W.b₈ + (-51) * t ^ 6 * W.b₂ * W.b₄ ^ 3 * W.b₈ ^ 4 + (-57) * t ^ 6 * W.b₂ * W.b₄ ^ 2 * W.b₆ ^ 6 + (368) * t ^ 6 * W.b₂ * W.b₄ ^ 2 * W.b₆ ^ 2 * W.b₈ ^ 3 + (-345) * t ^ 6 * W.b₂ * W.b₄ * W.b₆ ^ 4 * W.b₈ ^ 2 + (-68) * t ^ 6 * W.b₂ * W.b₄ * W.b₈ ^ 5 + (75) * t ^ 6 * W.b₂ * W.b₆ ^ 6 * W.b₈ + (-172) * t ^ 6 * W.b₂ * W.b₆ ^ 2 * W.b₈ ^ 4 + (-24) * t ^ 6 * W.b₄ ^ 6 * W.b₆ * W.b₈ ^ 2 + (84) * t ^ 6 * W.b₄ ^ 5 * W.b₆ ^ 3 * W.b₈ + (-66) * t ^ 6 * W.b₄ ^ 4 * W.b₆ ^ 5 + (309) * t ^ 6 * W.b₄ ^ 4 * W.b₆ * W.b₈ ^ 3 + (-777) * t ^ 6 * W.b₄ ^ 3 * W.b₆ ^ 3 * W.b₈ ^ 2 + (462) * t ^ 6 * W.b₄ ^ 2 * W.b₆ ^ 5 * W.b₈ + (-587) * t ^ 6 * W.b₄ ^ 2 * W.b₆ * W.b₈ ^ 4 + (-18) * t ^ 6 * W.b₄ * W.b₆ ^ 7 + (452) * t ^ 6 * W.b₄ * W.b₆ ^ 3 * W.b₈ ^ 3 + (375) * t ^ 6 * W.b₆ ^ 5 * W.b₈ ^ 2 + (-100) * t ^ 6 * W.b₆ * W.b₈ ^ 5 + t ^ 5 * W.b₂ ^ 3 * W.b₆ ^ 3 * W.b₈ ^ 3 + (27) * t ^ 5 * W.b₂ ^ 2 * W.b₄ ^ 2 * W.b₆ ^ 2 * W.b₈ ^ 3 + (-39) * t ^ 5 * W.b₂ ^ 2 * W.b₄ * W.b₆ ^ 4 * W.b₈ ^ 2 + (-4) * t ^ 5 * W.b₂ ^ 2 * W.b₄ * W.b₈ ^ 5 + (9) * t ^ 5 * W.b₂ ^ 2 * W.b₆ ^ 6 * W.b₈ + (-7) * t ^ 5 * W.b₂ ^ 2 * W.b₆ ^ 2 * W.b₈ ^ 4 + (48) * t ^ 5 * W.b₂ * W.b₄ ^ 4 * W.b₆ * W.b₈ ^ 3 + (-153) * t ^ 5 * W.b₂ * W.b₄ ^ 3 * W.b₆ ^ 3 * W.b₈ ^ 2 + (129) * t ^ 5 * W.b₂ * W.b₄ ^ 2 * W.b₆ ^ 5 * W.b₈ + (-60) * t ^ 5 * W.b₂ * W.b₄ ^ 2 * W.b₆ * W.b₈ ^ 4 + (-21) * t ^ 5 * W.b₂ * W.b₄ * W.b₆ ^ 7 + (100) * t ^ 5 * W.b₂ * W.b₄ * W.b₆ ^ 3 * W.b₈ ^ 3 + (-18) * t ^ 5 * W.b₂ * W.b₆ ^ 5 * W.b₈ ^ 2 + (-20) * t ^ 5 * W.b₂ * W.b₆ * W.b₈ ^ 5 + (8) * t ^ 5 * W.b₄ ^ 6 * W.b₈ ^ 3 + (-60) * t ^ 5 * W.b₄ ^ 5 * W.b₆ ^ 2 * W.b₈ ^ 2 + (114) * t ^ 5 * W.b₄ ^ 4 * W.b₆ ^ 4 * W.b₈ + (-18) * t ^ 5 * W.b₄ ^ 4 * W.b₈ ^ 4 + (-63) * t ^ 5 * W.b₄ ^ 3 * W.b₆ ^ 6 + (172) * t ^ 5 * W.b₄ ^ 3 * W.b₆ ^ 2 * W.b₈ ^ 3 + (-264) * t ^ 5 * W.b₄ ^ 2 * W.b₆ ^ 4 * W.b₈ ^ 2 + (-44) * t ^ 5 * W.b₄ ^ 2 * W.b₈ ^ 5 + (108) * t ^ 5 * W.b₄ * W.b₆ ^ 6 * W.b₈ + (-132) * t ^ 5 * W.b₄ * W.b₆ ^ 2 * W.b₈ ^ 4 + (-9) * t ^ 5 * W.b₆ ^ 8 + (196) * t ^ 5 * W.b₆ ^ 4 * W.b₈ ^ 3 + (3) * t ^ 4 * W.b₂ ^ 2 * W.b₄ * W.b₆ ^ 3 * W.b₈ ^ 3 + (-3) * t ^ 4 * W.b₂ ^ 2 * W.b₆ ^ 5 * W.b₈ ^ 2 - t ^ 4 * W.b₂ ^ 2 * W.b₆ * W.b₈ ^ 5 + (21) * t ^ 4 * W.b₂ * W.b₄ ^ 3 * W.b₆ ^ 2 * W.b₈ ^ 3 + (-51) * t ^ 4 * W.b₂ * W.b₄ ^ 2 * W.b₆ ^ 4 * W.b₈ ^ 2 + (-5) * t ^ 4 * W.b₂ * W.b₄ ^ 2 * W.b₈ ^ 5 + (33) * t ^ 4 * W.b₂ * W.b₄ * W.b₆ ^ 6 * W.b₈ + (-10) * t ^ 4 * W.b₂ * W.b₄ * W.b₆ ^ 2 * W.b₈ ^ 4 + (-3) * t ^ 4 * W.b₂ * W.b₆ ^ 8 + (17) * t ^ 4 * W.b₂ * W.b₆ ^ 4 * W.b₈ ^ 3 + (12) * t ^ 4 * W.b₄ ^ 5 * W.b₆ * W.b₈ ^ 3 + (-54) * t ^ 4 * W.b₄ ^ 4 * W.b₆ ^ 3 * W.b₈ ^ 2 + (75) * t ^ 4 * W.b₄ ^ 3 * W.b₆ ^ 5 * W.b₈ + (-23) * t ^ 4 * W.b₄ ^ 3 * W.b₆ * W.b₈ ^ 4 + (-33) * t ^ 4 * W.b₄ ^ 2 * W.b₆ ^ 7 + (70) * t ^ 4 * W.b₄ ^ 2 * W.b₆ ^ 3 * W.b₈ ^ 3 + (-51) * t ^ 4 * W.b₄ * W.b₆ ^ 5 * W.b₈ ^ 2 + (-20) * t ^ 4 * W.b₄ * W.b₆ * W.b₈ ^ 5 + (3) * t ^ 4 * W.b₆ ^ 7 * W.b₈ + (20) * t ^ 4 * W.b₆ ^ 3 * W.b₈ ^ 4 + (3) * t ^ 3 * W.b₂ * W.b₄ ^ 2 * W.b₆ ^ 3 * W.b₈ ^ 3 + (-6) * t ^ 3 * W.b₂ * W.b₄ * W.b₆ ^ 5 * W.b₈ ^ 2 + (-2) * t ^ 3 * W.b₂ * W.b₄ * W.b₆ * W.b₈ ^ 5 + (3) * t ^ 3 * W.b₂ * W.b₆ ^ 7 * W.b₈ + (2) * t ^ 3 * W.b₂ * W.b₆ ^ 3 * W.b₈ ^ 4 + (6) * t ^ 3 * W.b₄ ^ 4 * W.b₆ ^ 2 * W.b₈ ^ 3 + (-21) * t ^ 3 * W.b₄ ^ 3 * W.b₆ ^ 4 * W.b₈ ^ 2 + (-2) * t ^ 3 * W.b₄ ^ 3 * W.b₈ ^ 5 + (24) * t ^ 3 * W.b₄ ^ 2 * W.b₆ ^ 6 * W.b₈ + (-3) * t ^ 3 * W.b₄ ^ 2 * W.b₆ ^ 2 * W.b₈ ^ 4 + (-9) * t ^ 3 * W.b₄ * W.b₆ ^ 8 + (14) * t ^ 3 * W.b₄ * W.b₆ ^ 4 * W.b₈ ^ 3 + (-9) * t ^ 3 * W.b₆ ^ 6 * W.b₈ ^ 2 + t ^ 2 * W.b₄ ^ 3 * W.b₆ ^ 3 * W.b₈ ^ 3 + (-3) * t ^ 2 * W.b₄ ^ 2 * W.b₆ ^ 5 * W.b₈ ^ 2 - t ^ 2 * W.b₄ ^ 2 * W.b₆ * W.b₈ ^ 5 + (3) * t ^ 2 * W.b₄ * W.b₆ ^ 7 * W.b₈ + (2) * t ^ 2 * W.b₄ * W.b₆ ^ 3 * W.b₈ ^ 4 - t ^ 2 * W.b₆ ^ 9 - t ^ 2 * W.b₆ ^ 5 * W.b₈ ^ 3) * W.b_relation end StarInstances end WeierstrassCurve open Polynomial namespace WeierstrassCurve.Affine variable {F : Type u} [Field F] [DecidableEq F] {W : WeierstrassCurve F} section Statement def MFred (m : ℕ) {x y : F} (h : W.toAffine.Nonsingular x y) : Prop := (W.ΨSq (m : ℤ)).eval x ≠ 0 ∧ (m • (Point.some x y h : W.toAffine.Point)).xOrZero * (W.ΨSq (m : ℤ)).eval x = (W.Φ (m : ℤ)).eval x def LowTorsionFree (m : ℕ) {x y : F} (h : W.toAffine.Nonsingular x y) : Prop := ∀ k : ℕ, 1 ≤ k → k ≤ m → k • (Point.some x y h : W.toAffine.Point) ≠ 0 lemma LowTorsionFree.mono {m n : ℕ} (hmn : m ≤ n) {x y : F} {h : W.toAffine.Nonsingular x y} (hf : LowTorsionFree n h) : LowTorsionFree m h := fun k hk1 hkm => hf k hk1 (hkm.trans hmn) end Statement section BaseCases theorem mfred_one {x y : F} (h : W.toAffine.Nonsingular x y) : MFred 1 h := by constructor · rw [Nat.cast_one, ΨSq_one] simp · rw [Nat.cast_one, ΨSq_one, Φ_one, one_nsmul, Point.xOrZero_some] simp theorem mfred_two {x y : F} (h : W.toAffine.Nonsingular x y) (h2 : (2 • (Point.some x y h : W.toAffine.Point)) ≠ 0) : MFred 2 h := by have hy : y ≠ W.toAffine.negY x y := fun hy => h2 (by rw [two_nsmul]; exact Point.add_self_of_Y_eq hy) have hcast : ((2 : ℕ) : ℤ) = 2 := by norm_num have hΨ2 : (W.Ψ₂Sq).eval x ≠ 0 := Ψ₂Sq_eval_ne_zero' h.left hy constructor · rw [hcast, ΨSq_two] exact hΨ2 · have hns2 : W.toAffine.Nonsingular (W.toAffine.addX x x (W.toAffine.slope x x y y)) (W.toAffine.addY x x y (W.toAffine.slope x x y y)) := nonsingular_add h h fun hxy => hy hxy.right have h2P : (2 • (Point.some x y h : W.toAffine.Point)) = Point.some _ _ hns2 := by rw [two_nsmul]; exact Point.add_self_of_Y_ne hy rw [hcast, ΨSq_two, h2P, Point.xOrZero_some] exact addX_self_mul_Ψ₂Sq' h.left hy end BaseCases section Step theorem mfred_step {m : ℕ} (hm : 1 ≤ m) {x y : F} (h : W.toAffine.Nonsingular x y) (hfree : LowTorsionFree (m + 2) h) (ih1 : MFred m h) (ih2 : MFred (m + 1) h) (hstar : 2 * x * (W.Φ ((m : ℤ) + 1)).eval x * ((W.Φ ((m : ℤ) + 1)).eval x + x * (W.ΨSq ((m : ℤ) + 1)).eval x) + W.b₂ * x * ((W.Φ ((m : ℤ) + 1)).eval x * (W.ΨSq ((m : ℤ) + 1)).eval x) + W.b₄ * (((W.Φ ((m : ℤ) + 1)).eval x + x * (W.ΨSq ((m : ℤ) + 1)).eval x) * (W.ΨSq ((m : ℤ) + 1)).eval x) + W.b₆ * (W.ΨSq ((m : ℤ) + 1)).eval x ^ 2 = (W.Φ ((m : ℤ) + 2)).eval x * (W.ΨSq (m : ℤ)).eval x + (W.Φ (m : ℤ)).eval x * (W.ΨSq ((m : ℤ) + 2)).eval x) : MFred (m + 2) h := by have hc1 : ((m + 1 : ℕ) : ℤ) = (m : ℤ) + 1 := by push_cast; ring have hc2 : ((m + 2 : ℕ) : ℤ) = (m : ℤ) + 2 := by push_cast; ring have hS1ne : (W.ΨSq (m : ℤ)).eval x ≠ 0 := ih1.1 have hS2ne : (W.ΨSq ((m : ℤ) + 1)).eval x ≠ 0 := by have h' := ih2.1; rwa [hc1] at h' have hQne : ((m + 1) • (Point.some x y h : W.toAffine.Point)) ≠ 0 := hfree (m + 1) (by omega) (by omega) obtain ⟨xq, yq, hq, hQeq⟩ : ∃ (xq yq : F) (hq : W.toAffine.Nonsingular xq yq), ((m + 1) • (Point.some x y h : W.toAffine.Point)) = Point.some xq yq hq := by cases hQP : ((m + 1) • (Point.some x y h : W.toAffine.Point)) with | zero => exact absurd hQP hQne | @some xq yq hq => exact ⟨xq, yq, hq, rfl⟩ have hIH2eq : xq * (W.ΨSq ((m : ℤ) + 1)).eval x = (W.Φ ((m : ℤ) + 1)).eval x := by have h2 := ih2.2 rw [hQeq, Point.xOrZero_some, hc1] at h2 exact h2 have hxqx : xq ≠ x := by intro hxx rcases Y_eq_of_X_eq hq.left h.left hxx with hyy | hyy · apply hfree m hm (by omega) have hQ1 : ((m + 1) • (Point.some x y h : W.toAffine.Point)) = Point.some x y h := by rw [hQeq]; subst hxx; subst hyy rw [Subsingleton.elim hq h] have h0 : (m • (Point.some x y h : W.toAffine.Point)) + Point.some x y h = 0 + Point.some x y h := by rw [zero_add, ← succ_nsmul, hQ1] exact add_right_cancel h0 · apply hfree (m + 2) (by omega) le_rfl have hQ1 : ((m + 1) • (Point.some x y h : W.toAffine.Point)) = -(Point.some x y h : W.toAffine.Point) := by rw [hQeq, Point.neg_some] subst hxx; subst hyy exact congrArg _ (Subsingleton.elim _ _) have hsucc : ((m + 2) • (Point.some x y h : W.toAffine.Point)) = ((m + 1) • (Point.some x y h : W.toAffine.Point)) + Point.some x y h := succ_nsmul _ _ rw [hsucc, hQ1, neg_add_cancel] have hIH1eq : W.toAffine.addX xq x (W.toAffine.slope xq x yq (W.toAffine.negY x y)) * (W.ΨSq (m : ℤ)).eval x = (W.Φ (m : ℤ)).eval x := by have h1 := ih1.2 have hrearr : (m • (Point.some x y h : W.toAffine.Point)) = ((m + 1) • (Point.some x y h : W.toAffine.Point)) + (-(Point.some x y h : W.toAffine.Point)) := by rw [succ_nsmul, add_neg_cancel_right] rw [hrearr, hQeq, Point.neg_some, Point.add_of_X_ne hxqx, Point.xOrZero_some] at h1 exact h1 have hsum := addX_add_addX_negY_mul_sq' (W := W) hq.left h.left hxqx have hpoly := W.X_mul_ΨSq_sub_Φ_sq ((m : ℤ) + 1) rw [show ((m : ℤ) + 1 + 1) = (m : ℤ) + 2 by ring, show ((m : ℤ) + 1 - 1) = (m : ℤ) by ring] at hpoly have hev := congrArg (Polynomial.eval x) hpoly simp only [eval_pow, eval_sub, eval_mul, eval_X] at hev have hd2 : ((xq - x) * (W.ΨSq ((m : ℤ) + 1)).eval x) ^ 2 = (W.ΨSq ((m : ℤ) + 2)).eval x * (W.ΨSq (m : ℤ)).eval x := by linear_combination ((xq - 2 * x) * (W.ΨSq ((m : ℤ) + 1)).eval x + (W.Φ ((m : ℤ) + 1)).eval x) * hIH2eq + hev have hd2ne : ((xq - x) * (W.ΨSq ((m : ℤ) + 1)).eval x) ^ 2 ≠ 0 := pow_ne_zero 2 (mul_ne_zero (sub_ne_zero_of_ne hxqx) hS2ne) have hS3ne : (W.ΨSq ((m : ℤ) + 2)).eval x ≠ 0 := by intro h0 apply hd2ne rw [hd2, h0, zero_mul] have hkey : W.toAffine.addX xq x (W.toAffine.slope xq x yq y) * (W.ΨSq ((m : ℤ) + 2)).eval x * ((W.ΨSq (m : ℤ)).eval x) ^ 2 = (W.Φ ((m : ℤ) + 2)).eval x * ((W.ΨSq (m : ℤ)).eval x) ^ 2 := by linear_combination ((W.ΨSq (m : ℤ)).eval x * ((W.ΨSq ((m : ℤ) + 1)).eval x) ^ 2) * hsum + (-(W.toAffine.addX xq x (W.toAffine.slope xq x yq y) + W.toAffine.addX xq x (W.toAffine.slope xq x yq (W.toAffine.negY x y))) * (W.ΨSq (m : ℤ)).eval x) * hd2 + ((W.ΨSq (m : ℤ)).eval x) * hstar + (-((W.ΨSq ((m : ℤ) + 2)).eval x * (W.ΨSq (m : ℤ)).eval x)) * hIH1eq + ((W.ΨSq (m : ℤ)).eval x * (2 * x * ((W.Φ ((m : ℤ) + 1)).eval x + xq * (W.ΨSq ((m : ℤ) + 1)).eval x + x * (W.ΨSq ((m : ℤ) + 1)).eval x) + W.b₂ * x * (W.ΨSq ((m : ℤ) + 1)).eval x + W.b₄ * (W.ΨSq ((m : ℤ) + 1)).eval x)) * hIH2eq constructor · rw [hc2] exact hS3ne · have hsucc2 : ((m + 2) • (Point.some x y h : W.toAffine.Point)) = ((m + 1) • (Point.some x y h : W.toAffine.Point)) + Point.some x y h := succ_nsmul _ _ rw [hc2, hsucc2, hQeq, Point.add_of_X_ne hxqx, Point.xOrZero_some] exact mul_right_cancel₀ (pow_ne_zero 2 hS1ne) hkey end Step section Shell theorem mfred_of_forall_star (M : ℕ) {x y : F} (h : W.toAffine.Nonsingular x y) (hfree : LowTorsionFree M h) (hstar : ∀ j : ℤ, 2 ≤ j → j + 1 ≤ (M : ℤ) → 2 * x * (W.Φ j).eval x * ((W.Φ j).eval x + x * (W.ΨSq j).eval x) + W.b₂ * x * ((W.Φ j).eval x * (W.ΨSq j).eval x) + W.b₄ * (((W.Φ j).eval x + x * (W.ΨSq j).eval x) * (W.ΨSq j).eval x) + W.b₆ * (W.ΨSq j).eval x ^ 2 = (W.Φ (j + 1)).eval x * (W.ΨSq (j - 1)).eval x + (W.Φ (j - 1)).eval x * (W.ΨSq (j + 1)).eval x) : ∀ m : ℕ, 1 ≤ m → m ≤ M → MFred m h := by intro m induction m using Nat.strong_induction_on with | _ m ih => intro hm1 hmM by_cases hone : m = 1 · subst hone; exact mfred_one h by_cases htwo : m = 2 · subst htwo; exact mfred_two h (hfree 2 one_le_two hmM) obtain ⟨k, rfl⟩ : ∃ k, m = k + 3 := ⟨m - 3, by omega⟩ have ih1 : MFred (k + 1) h := ih (k + 1) (by omega) (by omega) (by omega) have ih2 : MFred (k + 2) h := ih (k + 2) (by omega) (by omega) (by omega) have hs := hstar (((k + 1 : ℕ) : ℤ) + 1) (by push_cast; omega) (by push_cast; omega) rw [show ((k + 1 : ℕ) : ℤ) + 1 + 1 = ((k + 1 : ℕ) : ℤ) + 2 by ring, add_sub_cancel_right] at hs exact mfred_step (by omega) h (hfree.mono (by omega)) ih1 ih2 hs theorem mfred_three {x y : F} (h : W.toAffine.Nonsingular x y) (hfree : LowTorsionFree 3 h) : MFred 3 h := by refine mfred_of_forall_star 3 h hfree (fun j hj2 hj3 => ?_) 3 (by norm_num) le_rfl have hj : j = 2 := by omega subst hj rw [show (2 : ℤ) + 1 = 3 by norm_num, show (2 : ℤ) - 1 = 1 by norm_num, ΨSq_one, Φ_one, ΨSq_three, ΨSq_two] simp only [eval_one, eval_X, eval_pow, mul_one] linear_combination ellipticNet_two (W := W) x end Shell end WeierstrassCurve.Affine open Polynomial namespace WeierstrassCurve section StarIdentityDef variable {R : Type u} [CommRing R] (W : WeierstrassCurve R) def StarIdentity (j : ℤ) : Prop := ∀ t : R, 2 * t * (W.Φ j).eval t * ((W.Φ j).eval t + t * (W.ΨSq j).eval t) + W.b₂ * t * ((W.Φ j).eval t * (W.ΨSq j).eval t) + W.b₄ * (((W.Φ j).eval t + t * (W.ΨSq j).eval t) * (W.ΨSq j).eval t) + W.b₆ * (W.ΨSq j).eval t ^ 2 = (W.Φ (j + 1)).eval t * (W.ΨSq (j - 1)).eval t + (W.Φ (j - 1)).eval t * (W.ΨSq (j + 1)).eval t end StarIdentityDef section BaseSet variable {F : Type u} [Field F] (W : WeierstrassCurve F) theorem starIdentity_of_le_four (j : ℤ) (h1 : 1 ≤ j) (h4 : j ≤ 4) : W.StarIdentity j := by intro t have hj : j = 1 ∨ j = 2 ∨ j = 3 ∨ j = 4 := by omega rcases hj with rfl | rfl | rfl | rfl · rw [show (1 : ℤ) + 1 = 2 by norm_num, show (1 : ℤ) - 1 = 0 by norm_num] linear_combination W.ellipticNet_one t · rw [show (2 : ℤ) + 1 = 3 by norm_num, show (2 : ℤ) - 1 = 1 by norm_num, ΨSq_one, Φ_one, ΨSq_three, ΨSq_two] simp only [eval_one, eval_X, eval_pow, mul_one] linear_combination Affine.ellipticNet_two (W := W) t · rw [show (3 : ℤ) + 1 = 4 by norm_num, show (3 : ℤ) - 1 = 2 by norm_num] linear_combination W.ellipticNet_three t · rw [show (4 : ℤ) + 1 = 5 by norm_num, show (4 : ℤ) - 1 = 3 by norm_num] linear_combination W.ellipticNet_four t end BaseSet namespace Affine variable {F : Type u} [Field F] [DecidableEq F] {W : WeierstrassCurve F} theorem mfred_of_forall_starIdentity (M : ℕ) {x y : F} (h : W.toAffine.Nonsingular x y) (hfree : LowTorsionFree M h) (hstar : ∀ j : ℤ, 2 ≤ j → j + 1 ≤ (M : ℤ) → W.StarIdentity j) : ∀ m : ℕ, 1 ≤ m → m ≤ M → MFred m h := mfred_of_forall_star M h hfree fun j hj2 hjM => hstar j hj2 hjM x theorem mfred_of_le_five {M : ℕ} (hM : M ≤ 5) {x y : F} (h : W.toAffine.Nonsingular x y) (hfree : LowTorsionFree M h) : ∀ m : ℕ, 1 ≤ m → m ≤ M → MFred m h := by refine mfred_of_forall_starIdentity M h hfree fun j hj2 hjM => ?_ have hM5 : (M : ℤ) ≤ 5 := by exact_mod_cast hM exact W.starIdentity_of_le_four j (by omega) (by omega) theorem mfred_four {x y : F} (h : W.toAffine.Nonsingular x y) (hfree : LowTorsionFree 4 h) : MFred 4 h := mfred_of_le_five (by norm_num) h hfree 4 (by norm_num) le_rfl theorem mfred_five {x y : F} (h : W.toAffine.Nonsingular x y) (hfree : LowTorsionFree 5 h) : MFred 5 h := mfred_of_le_five le_rfl h hfree 5 (by norm_num) le_rfl end Affine end WeierstrassCurve open Polynomial namespace WeierstrassCurve.Affine variable {F : Type u} [Field F] {W : WeierstrassCurve F} section AbstractCores variable {x xa xb xg xd xs x2 Sk Sk1 Skm Sk2 Fk Fk1 Fkm Fk2 p1 p0 p2 pm Qe P2e S2 F2 b2 b4 b6 b8 : F} private lemma star_eval_core {xj xjm xjp Sj Sjm Sjp Fj Fjm Fjp : F} (hMj : xj * Sj = Fj) (hMjm : xjm * Sjm = Fjm) (hMjp : xjp * Sjp = Fjp) (hsum : (xjp + xjm) * (xj - x) ^ 2 = 2 * (xj * x) * (xj + x) + b2 * (xj * x) + b4 * (xj + x) + b6) (hd3 : (x * Sj - Fj) ^ 2 = Sjp * Sjm) : 2 * x * Fj * (Fj + x * Sj) + b2 * x * (Fj * Sj) + b4 * ((Fj + x * Sj) * Sj) + b6 * Sj ^ 2 = Fjp * Sjm + Fjm * Sjp := by linear_combination ((xjp + xjm) * (Sj * xj - 2 * x * Sj + Fj) - (2 * x * (Fj + xj * Sj) + 2 * x ^ 2 * Sj + b2 * x * Sj + b4 * Sj)) * hMj + (-Sj ^ 2) * hsum + (xjp + xjm) * hd3 + Sjm * hMjp + Sjp * hMjm private lemma odd_step_core (hM0 : xa * Sk = Fk) (hMm : xg * Skm = Fkm) (hM1 : xb * Sk1 = Fk1) (hM2 : xd * Sk2 = Fk2) (hD1 : Fk1 * Sk - Fk * Sk1 = -p1) (hD2a : Fk1 * Skm - Fkm * Sk1 = -(p0 * Qe)) (hD2b : Fk2 * Sk - Fk * Sk2 = -(p2 * Qe)) (hD3a : (x * Sk - Fk) ^ 2 = Sk1 * Skm) (hD3b : (x * Sk1 - Fk1) ^ 2 = Sk2 * Sk) (hPsi : S2 = p1 ^ 2) (hPhi : F2 = x * S2 - p2 * p0 * Qe) (hg1 : (xs + x) * (xb - xa) ^ 2 = 2 * (xb * xa) * (xb + xa) + b2 * (xb * xa) + b4 * (xb + xa) + b6) (hg2 : (xd + xa) * (xb - x) ^ 2 = 2 * (xb * x) * (xb + x) + b2 * (xb * x) + b4 * (xb + x) + b6) (hg3 : (xb + xg) * (xa - x) ^ 2 = 2 * (xa * x) * (xa + x) + b2 * (xa * x) + b4 * (xa + x) + b6) (hg3p : xb * xg * (xa - x) ^ 2 = (xa * x) ^ 2 - b4 * (xa * x) - b6 * (xa + x) - b8) (hbrel : 4 * b8 = b2 * b6 - b4 ^ 2) (hQv : Qe = 4 * x ^ 3 + b2 * x ^ 2 + 2 * b4 * x + b6) (hSkne : Sk ≠ 0) (hSk1ne : Sk1 ≠ 0) (hbane : xb ≠ xa) : S2 ≠ 0 ∧ xs * S2 * Qe = F2 * Qe := by have hp1 : p1 = -(Sk * Sk1 * (xb - xa)) := by linear_combination hD1 + Sk * hM1 - Sk1 * hM0 have hP0 : p0 * Qe = -(Sk1 * Skm * (xb - xg)) := by linear_combination hD2a + Skm * hM1 - Sk1 * hMm have hP2 : p2 * Qe = -(Sk * Sk2 * (xd - xa)) := by linear_combination hD2b + Sk * hM2 - Sk2 * hM0 have hSpk : Sk1 * Skm = Sk ^ 2 * (x - xa) ^ 2 := by linear_combination -hD3a + (2 * x * Sk - Fk - xa * Sk) * hM0 have hSpk1 : Sk2 * Sk = Sk1 ^ 2 * (x - xb) ^ 2 := by linear_combination -hD3b + (2 * x * Sk1 - Fk1 - xb * Sk1) * hM1 have hcore : (xs - x) * (xb - xa) ^ 2 * Qe + (x - xa) ^ 2 * (x - xb) ^ 2 * (xd - xa) * (xb - xg) = 0 := by linear_combination Qe * hg1 + ((x - xa) ^ 2 * (xb - xg)) * hg2 + (-(2 * (xb * x) * (xb + x) + b2 * (xb * x) + b4 * (xb + x) + b6 - 2 * xa * (xb - x) ^ 2) - 4 * xb * (x - xa) * (x - xb)) * hg3 + (4 * (x - xa) * (x - xb)) * hg3p + (-((x - xa) * (x - xb))) * hbrel + (2 * (xa * xb) * (xa + xb) + b2 * (xa * xb) + b4 * (xa + xb) + b6 - 2 * x * (xa - xb) ^ 2) * hQv refine ⟨?_, ?_⟩ · rw [hPsi, hp1] exact pow_ne_zero 2 (neg_ne_zero.mpr (mul_ne_zero (mul_ne_zero hSkne hSk1ne) (sub_ne_zero.mpr hbane))) · linear_combination (-Qe) * hPhi + (Qe * (xs - x)) * hPsi + (Qe * (xs - x) * (Sk * Sk1 * xa - Sk * Sk1 * xb + p1)) * hp1 + (Qe * p0) * hP2 + (Sk * Sk2 * (xa - xd)) * hP0 + (-(Sk * Sk2 * (xa - xd) * (xb - xg))) * hSpk + (-(Sk ^ 2 * (x - xa) ^ 2 * (xa - xd) * (xb - xg))) * hSpk1 + (Sk ^ 2 * Sk1 ^ 2) * hcore private lemma even_step_core (hM0 : xa * Sk = Fk) (hMm : xg * Skm = Fkm) (hM1 : xb * Sk1 = Fk1) (hD1 : Fk1 * Sk - Fk * Sk1 = -p1) (hD1m : Fk * Skm - Fkm * Sk = -pm) (hD2a : Fk1 * Skm - Fkm * Sk1 = -(p0 * Qe)) (hD3a : (x * Sk - Fk) ^ 2 = Sk1 * Skm) (hPsi : S2 = p0 ^ 2 * Qe) (hPhi : F2 = x * S2 - p1 * pm) (hg4 : (xs + x2) * (xb - xg) ^ 2 = 2 * (xb * xg) * (xb + xg) + b2 * (xb * xg) + b4 * (xb + xg) + b6) (hdup : x2 * Qe = P2e) (hg3 : (xb + xg) * (xa - x) ^ 2 = 2 * (xa * x) * (xa + x) + b2 * (xa * x) + b4 * (xa + x) + b6) (hg3p : xb * xg * (xa - x) ^ 2 = (xa * x) ^ 2 - b4 * (xa * x) - b6 * (xa + x) - b8) (hbrel : 4 * b8 = b2 * b6 - b4 ^ 2) (hQv : Qe = 4 * x ^ 3 + b2 * x ^ 2 + 2 * b4 * x + b6) (hP2v : P2e = x ^ 4 - b4 * x ^ 2 - 2 * b6 * x - b8) (hQne : Qe ≠ 0) (hSk1ne : Sk1 ≠ 0) (hSkmne : Skm ≠ 0) (haxne : xa ≠ x) (hbgne : xb ≠ xg) : S2 ≠ 0 ∧ xs * S2 * Qe = F2 * Qe := by have hp1 : p1 = -(Sk * Sk1 * (xb - xa)) := by linear_combination hD1 + Sk * hM1 - Sk1 * hM0 have hpm : pm = -(Sk * Skm * (xa - xg)) := by linear_combination hD1m + Skm * hM0 - Sk * hMm have hP0 : p0 * Qe = -(Sk1 * Skm * (xb - xg)) := by linear_combination hD2a + Skm * hM1 - Sk1 * hMm have hSpk : Sk1 * Skm = Sk ^ 2 * (x - xa) ^ 2 := by linear_combination -hD3a + (2 * x * Sk - Fk - xa * Sk) * hM0 have hbig : ((xs - x) * (x - xa) ^ 2 * (xb - xg) ^ 2 + (xb - xa) * (xa - xg) * Qe) * (Qe * (xa - x) ^ 2) = 0 := by rw [hQv, hP2v] at hdup rw [hQv] linear_combination (b2 * x ^ 6 - 4 * b2 * x ^ 5 * xa + 6 * b2 * x ^ 4 * xa ^ 2 - 4 * b2 * x ^ 3 * xa ^ 3 + b2 * x ^ 2 * xa ^ 4 + 4 * x ^ 7 - 16 * x ^ 6 * xa + 24 * x ^ 5 * xa ^ 2 - 16 * x ^ 4 * xa ^ 3 + 4 * x ^ 3 * xa ^ 4 + 2 * b4 * x ^ 5 - 8 * b4 * x ^ 4 * xa + 12 * b4 * x ^ 3 * xa ^ 2 - 8 * b4 * x ^ 2 * xa ^ 3 + 2 * b4 * x * xa ^ 4 + b6 * x ^ 4 - 4 * b6 * x ^ 3 * xa + 6 * b6 * x ^ 2 * xa ^ 2 - 4 * b6 * x * xa ^ 3 + b6 * xa ^ 4) * hg4 + (-x ^ 4 * xb ^ 2 + 2 * x ^ 4 * xb * xg - x ^ 4 * xg ^ 2 + 4 * x ^ 3 * xa * xb ^ 2 - 8 * x ^ 3 * xa * xb * xg + 4 * x ^ 3 * xa * xg ^ 2 - 6 * x ^ 2 * xa ^ 2 * xb ^ 2 + 12 * x ^ 2 * xa ^ 2 * xb * xg - 6 * x ^ 2 * xa ^ 2 * xg ^ 2 + 4 * x * xa ^ 3 * xb ^ 2 - 8 * x * xa ^ 3 * xb * xg + 4 * x * xa ^ 3 * xg ^ 2 - xa ^ 4 * xb ^ 2 + 2 * xa ^ 4 * xb * xg - xa ^ 4 * xg ^ 2) * hdup + (b2 * x ^ 5 * xa - b2 * x ^ 5 * xb - b2 * x ^ 5 * xg - 2 * b2 * x ^ 4 * xa ^ 2 + 2 * b2 * x ^ 4 * xa * xb + 2 * b2 * x ^ 4 * xa * xg + 2 * b2 * x ^ 4 * xb * xg - b2 * x ^ 3 * xa ^ 2 * xb - b2 * x ^ 3 * xa ^ 2 * xg - 4 * b2 * x ^ 3 * xa * xb * xg + 2 * b2 * x ^ 2 * xa ^ 2 * xb * xg + 6 * x ^ 6 * xa - 5 * x ^ 6 * xb - 5 * x ^ 6 * xg - 10 * x ^ 5 * xa ^ 2 + 10 * x ^ 5 * xa * xb + 10 * x ^ 5 * xa * xg + 8 * x ^ 5 * xb * xg - 5 * x ^ 4 * xa ^ 2 * xb - 5 * x ^ 4 * xa ^ 2 * xg - 16 * x ^ 4 * xa * xb * xg + 8 * x ^ 3 * xa ^ 2 * xb * xg + b2 * b4 * x ^ 2 * xa ^ 2 - b4 * x ^ 5 + b4 * x ^ 4 * xa - b4 * x ^ 4 * xb - b4 * x ^ 4 * xg + 2 * b4 * x ^ 3 * xa ^ 2 + 2 * b4 * x ^ 3 * xa * xb + 2 * b4 * x ^ 3 * xa * xg + 4 * b4 * x ^ 3 * xb * xg - b4 * x ^ 2 * xa ^ 2 * xb - b4 * x ^ 2 * xa ^ 2 * xg - 8 * b4 * x ^ 2 * xa * xb * xg + 4 * b4 * x * xa ^ 2 * xb * xg - b2 * b6 * x ^ 3 + 3 * b2 * b6 * x ^ 2 * xa + b4 ^ 2 * x ^ 3 - b4 ^ 2 * x ^ 2 * xa + 2 * b4 ^ 2 * x * xa ^ 2 - 5 * b6 * x ^ 4 + 10 * b6 * x ^ 3 * xa + b6 * x ^ 3 * xb + b6 * x ^ 3 * xg + 2 * b6 * x ^ 2 * xa ^ 2 - 2 * b6 * x ^ 2 * xa * xb - 2 * b6 * x ^ 2 * xa * xg + 2 * b6 * x ^ 2 * xb * xg + b6 * x * xa ^ 2 * xb + b6 * x * xa ^ 2 * xg - 4 * b6 * x * xa * xb * xg + 2 * b6 * xa ^ 2 * xb * xg + b2 * b8 * x * xa + b4 * b6 * x ^ 2 + 3 * b4 * b6 * x * xa + b4 * b6 * xa ^ 2 + 2 * b8 * x ^ 2 * xa + b8 * x ^ 2 * xb + b8 * x ^ 2 * xg + 2 * b8 * x * xa ^ 2 - 2 * b8 * x * xa * xb - 2 * b8 * x * xa * xg + b8 * xa ^ 2 * xb + b8 * xa ^ 2 * xg + b4 * b8 * x + b4 * b8 * xa + b6 ^ 2 * x + b6 ^ 2 * xa + b6 * b8) * hg3 + (b2 ^ 2 * x ^ 2 * xa ^ 2 - 4 * b2 * x ^ 4 * xa + 12 * b2 * x ^ 3 * xa ^ 2 + 4 * x ^ 6 - 24 * x ^ 5 * xa + 36 * x ^ 4 * xa ^ 2 + 2 * b2 * b4 * x ^ 2 * xa + 2 * b2 * b4 * x * xa ^ 2 - 4 * b4 * x ^ 4 + 8 * b4 * x ^ 3 * xa + 12 * b4 * x ^ 2 * xa ^ 2 + b2 * b6 * x ^ 2 + b2 * b6 * xa ^ 2 + 4 * b4 ^ 2 * x * xa - 4 * b6 * x ^ 3 + 12 * b6 * x ^ 2 * xa + 2 * b4 * b6 * x + 2 * b4 * b6 * xa - 4 * b8 * x ^ 2 + 8 * b8 * x * xa - 4 * b8 * xa ^ 2 + b6 ^ 2) * hg3p + (b2 * x ^ 4 * xa - 2 * b2 * x ^ 3 * xa ^ 2 + b2 * x ^ 2 * xa ^ 3 - x ^ 6 + 6 * x ^ 5 * xa - 9 * x ^ 4 * xa ^ 2 + 4 * x ^ 3 * xa ^ 3 + b4 * x ^ 4 - 3 * b4 * x ^ 2 * xa ^ 2 + 2 * b4 * x * xa ^ 3 + 2 * b6 * x ^ 3 - 3 * b6 * x ^ 2 * xa + b6 * xa ^ 3 + b8 * x ^ 2 - 2 * b8 * x * xa + b8 * xa ^ 2) * hbrel have hcoreE : (xs - x) * (x - xa) ^ 2 * (xb - xg) ^ 2 + (xb - xa) * (xa - xg) * Qe = 0 := (mul_eq_zero.mp hbig).resolve_right (mul_ne_zero hQne (pow_ne_zero 2 (sub_ne_zero.mpr (fun hE => haxne hE)))) have hp0ne : p0 * Qe ≠ 0 := by rw [hP0] exact neg_ne_zero.mpr (mul_ne_zero (mul_ne_zero hSk1ne hSkmne) (sub_ne_zero.mpr hbgne)) refine ⟨?_, ?_⟩ · intro hS20 apply hp0ne have h0 : p0 ^ 2 * Qe = 0 := by rw [← hPsi]; exact hS20 rcases mul_eq_zero.mp h0 with h | h · rcases pow_eq_zero_iff (n := 2) (by norm_num) |>.mp h with h' rw [h', zero_mul] · exact absurd h hQne · linear_combination (-Qe) * hPhi + (Qe * (xs - x)) * hPsi + (Qe * pm) * hp1 + (Qe * Sk * Sk1 * (xa - xb)) * hpm + ((xs - x) * (Qe * p0 - Sk1 * Skm * xb + Sk1 * Skm * xg)) * hP0 + ((xs - x) * (xb - xg) ^ 2 * (Sk ^ 2 * (xa - x) ^ 2 + Sk1 * Skm) - Qe * Sk ^ 2 * (xa - xb) * (xa - xg)) * hSpk + (Sk ^ 4 * (xa - x) ^ 2) * hcoreE end AbstractCores variable [DecidableEq F] theorem addX_mul_addX_negY_mul_sq' {x₁ x₂ y₁ y₂ : F} (h₁ : W.toAffine.Equation x₁ y₁) (h₂ : W.toAffine.Equation x₂ y₂) (hx : x₁ ≠ x₂) : W.toAffine.addX x₁ x₂ (W.toAffine.slope x₁ x₂ y₁ y₂) * W.toAffine.addX x₁ x₂ (W.toAffine.slope x₁ x₂ y₁ (W.toAffine.negY x₂ y₂)) * (x₁ - x₂) ^ 2 = (x₁ * x₂) ^ 2 - W.b₄ * (x₁ * x₂) - W.b₆ * (x₁ + x₂) - W.b₈ := Affine.addX_mul_addX_negY_mul_sq (W := W.toAffine) h₁ h₂ hx omit [DecidableEq F] in lemma x_ne_of_ne_of_ne_neg {x₁ y₁ x₂ y₂ : F} (h₁ : W.toAffine.Nonsingular x₁ y₁) (h₂ : W.toAffine.Nonsingular x₂ y₂) (hne : (Point.some x₁ y₁ h₁ : W.toAffine.Point) ≠ Point.some x₂ y₂ h₂) (hne' : (Point.some x₁ y₁ h₁ : W.toAffine.Point) ≠ -Point.some x₂ y₂ h₂) : x₁ ≠ x₂ := by intro hxx rcases Y_eq_of_X_eq h₁.left h₂.left hxx with hyy | hyy · subst hxx; subst hyy exact hne (by rw [Subsingleton.elim h₁ h₂]) · subst hxx; subst hyy exact hne' (by rw [Point.neg_some]) set_option maxHeartbeats 800000 in theorem mfred_double_succ {n : ℕ} (hn : 1 ≤ n) {x y : F} (h : W.toAffine.Nonsingular x y) (hfree : LowTorsionFree (2 * n + 3) h) (ih0 : MFred n h) (ih1 : MFred (n + 1) h) (ih2 : MFred (n + 2) h) (ih3 : MFred (n + 3) h) : MFred (2 * n + 3) h := by have hc1 : ((n + 1 : ℕ) : ℤ) = (n : ℤ) + 1 := by push_cast; ring have hc2 : ((n + 2 : ℕ) : ℤ) = (n : ℤ) + 2 := by push_cast; ring have hc3 : ((n + 3 : ℕ) : ℤ) = (n : ℤ) + 3 := by push_cast; ring have hc23 : ((2 * n + 3 : ℕ) : ℤ) = 2 * (n : ℤ) + 3 := by push_cast; ring have hy2 : y ≠ W.toAffine.negY x y := fun hy => hfree 2 one_le_two (by omega) (by rw [two_nsmul]; exact Point.add_self_of_Y_eq hy) have hQne : (W.Ψ₂Sq).eval x ≠ 0 := Ψ₂Sq_eval_ne_zero' h.left hy2 obtain ⟨xa, ya, ha, haeq⟩ : ∃ (xa ya : F) (ha : W.toAffine.Nonsingular xa ya), ((n + 1) • (Point.some x y h : W.toAffine.Point)) = Point.some xa ya ha := by cases hE : ((n + 1) • (Point.some x y h : W.toAffine.Point)) with | zero => exact absurd hE (hfree (n + 1) (by omega) (by omega)) | @some xa ya ha => exact ⟨xa, ya, ha, rfl⟩ obtain ⟨xb, yb, hb, hbeq⟩ : ∃ (xb yb : F) (hb : W.toAffine.Nonsingular xb yb), ((n + 2) • (Point.some x y h : W.toAffine.Point)) = Point.some xb yb hb := by cases hE : ((n + 2) • (Point.some x y h : W.toAffine.Point)) with | zero => exact absurd hE (hfree (n + 2) (by omega) (by omega)) | @some xb yb hb => exact ⟨xb, yb, hb, rfl⟩ have hax : xa ≠ x := by refine x_ne_of_ne_of_ne_neg ha h ?_ ?_ · intro hE refine hfree n hn (by omega) (add_right_cancel (b := (Point.some x y h)) ?_) rw [← succ_nsmul, haeq, hE, zero_add] · intro hE refine hfree (n + 2) (by omega) (by omega) ?_ rw [show n + 2 = (n + 1) + 1 by ring, succ_nsmul, haeq, hE, neg_add_cancel] have hbx : xb ≠ x := by refine x_ne_of_ne_of_ne_neg hb h ?_ ?_ · intro hE refine hfree (n + 1) (by omega) (by omega) (add_right_cancel (b := (Point.some x y h)) ?_) rw [← succ_nsmul, show (n + 1) + 1 = n + 2 by ring, hbeq, hE, zero_add] · intro hE refine hfree (n + 3) (by omega) (by omega) ?_ rw [show n + 3 = (n + 2) + 1 by ring, succ_nsmul, hbeq, hE, neg_add_cancel] have hba : xb ≠ xa := by refine x_ne_of_ne_of_ne_neg hb ha ?_ ?_ · intro hE refine hfree 1 le_rfl (by omega) ?_ rw [one_nsmul] refine add_left_cancel (a := ((n + 1) • (Point.some x y h : W.toAffine.Point))) ?_ rw [add_zero, ← succ_nsmul, show (n + 1) + 1 = n + 2 by ring, hbeq, hE, ← haeq] · intro hE refine hfree (2 * n + 3) (by omega) le_rfl ?_ rw [show 2 * n + 3 = (n + 2) + (n + 1) by ring, add_nsmul, hbeq, haeq, hE, neg_add_cancel] have hrearr0 : (n • (Point.some x y h : W.toAffine.Point)) = ((n + 1) • (Point.some x y h : W.toAffine.Point)) + -(Point.some x y h) := by rw [succ_nsmul, add_neg_cancel_right] have hrearr3 : ((n + 3) • (Point.some x y h : W.toAffine.Point)) = ((n + 2) • (Point.some x y h : W.toAffine.Point)) + (Point.some x y h) := by rw [show n + 3 = (n + 2) + 1 by ring, succ_nsmul] have hrearrS : ((2 * n + 3) • (Point.some x y h : W.toAffine.Point)) = ((n + 2) • (Point.some x y h : W.toAffine.Point)) + ((n + 1) • (Point.some x y h : W.toAffine.Point)) := by rw [show 2 * n + 3 = (n + 2) + (n + 1) by ring, add_nsmul] have hM0 : xa * (W.ΨSq ((n : ℤ) + 1)).eval x = (W.Φ ((n : ℤ) + 1)).eval x := by have h1 := ih1.2 rwa [haeq, Point.xOrZero_some, hc1] at h1 have hM1 : xb * (W.ΨSq ((n : ℤ) + 2)).eval x = (W.Φ ((n : ℤ) + 2)).eval x := by have h1 := ih2.2 rwa [hbeq, Point.xOrZero_some, hc2] at h1 have hMm : W.toAffine.addX xa x (W.toAffine.slope xa x ya (W.toAffine.negY x y)) * (W.ΨSq (n : ℤ)).eval x = (W.Φ (n : ℤ)).eval x := by have h1 := ih0.2 rwa [hrearr0, haeq, Point.neg_some, Point.add_of_X_ne hax, Point.xOrZero_some] at h1 have hM2 : W.toAffine.addX xb x (W.toAffine.slope xb x yb y) * (W.ΨSq ((n : ℤ) + 3)).eval x = (W.Φ ((n : ℤ) + 3)).eval x := by have h1 := ih3.2 rwa [hrearr3, hbeq, Point.add_of_X_ne hbx, Point.xOrZero_some, hc3] at h1 have hbdec : ((n + 2) • (Point.some x y h : W.toAffine.Point)) = Point.some xa ya ha + Point.some x y h := by rw [show n + 2 = (n + 1) + 1 by ring, succ_nsmul, haeq] have hbid : W.toAffine.addX xa x (W.toAffine.slope xa x ya y) = xb := by rw [Point.add_of_X_ne hax] at hbdec simpa using congrArg Point.xOrZero (hbdec.symm.trans hbeq) have hadec : ((n + 1) • (Point.some x y h : W.toAffine.Point)) = Point.some xb yb hb + -(Point.some x y h) := by have h0 : ((n + 2) • (Point.some x y h : W.toAffine.Point)) = ((n + 1) • (Point.some x y h : W.toAffine.Point)) + (Point.some x y h) := by rw [show n + 2 = (n + 1) + 1 by ring, succ_nsmul] rw [← hbeq, h0] abel have haid : W.toAffine.addX xb x (W.toAffine.slope xb x yb (W.toAffine.negY x y)) = xa := by rw [Point.neg_some, Point.add_of_X_ne hbx] at hadec simpa using congrArg Point.xOrZero (hadec.symm.trans haeq) have hxdec : (Point.some x y h : W.toAffine.Point) = Point.some xb yb hb + -(Point.some xa ya ha) := by have h0 : (Point.some x y h : W.toAffine.Point) = ((n + 2) • (Point.some x y h : W.toAffine.Point)) - ((n + 1) • (Point.some x y h : W.toAffine.Point)) := by rw [show n + 2 = (n + 1) + 1 by ring, succ_nsmul] abel rw [h0, hbeq, haeq, sub_eq_add_neg] have hxid : W.toAffine.addX xb xa (W.toAffine.slope xb xa yb (W.toAffine.negY xa ya)) = x := by rw [Point.neg_some, Point.add_of_X_ne hba] at hxdec simpa using congrArg Point.xOrZero hxdec.symm have hg3 := addX_add_addX_negY_mul_sq' (W := W) ha.left h.left hax rw [hbid] at hg3 have hg3p := addX_mul_addX_negY_mul_sq' (W := W) ha.left h.left hax rw [hbid] at hg3p have hg2 := addX_add_addX_negY_mul_sq' (W := W) hb.left h.left hbx rw [haid] at hg2 have hg1 := addX_add_addX_negY_mul_sq' (W := W) hb.left ha.left hba rw [hxid] at hg1 have hD1 : (W.Φ ((n : ℤ) + 2)).eval x * (W.ΨSq ((n : ℤ) + 1)).eval x - (W.Φ ((n : ℤ) + 1)).eval x * (W.ΨSq ((n : ℤ) + 2)).eval x = -(W.preΨ (2 * (n : ℤ) + 3)).eval x := by have hpoly := W.Φ_succ_mul_ΨSq_sub_Φ_mul_ΨSq_succ ((n : ℤ) + 1) rw [show (n : ℤ) + 1 + 1 = (n : ℤ) + 2 by ring, show 2 * ((n : ℤ) + 1) + 1 = 2 * (n : ℤ) + 3 by ring] at hpoly have hev := congrArg (Polynomial.eval x) hpoly simpa only [eval_sub, eval_mul, eval_neg] using hev have hD2a : (W.Φ ((n : ℤ) + 2)).eval x * (W.ΨSq (n : ℤ)).eval x - (W.Φ (n : ℤ)).eval x * (W.ΨSq ((n : ℤ) + 2)).eval x = -((W.preΨ (2 * (n : ℤ) + 2)).eval x * (W.Ψ₂Sq).eval x) := by have hpoly := W.Φ_succ_mul_ΨSq_pred_sub_Φ_pred_mul_ΨSq_succ ((n : ℤ) + 1) rw [show (n : ℤ) + 1 + 1 = (n : ℤ) + 2 by ring, show (n : ℤ) + 1 - 1 = (n : ℤ) by ring, show 2 * ((n : ℤ) + 1) = 2 * (n : ℤ) + 2 by ring] at hpoly have hev := congrArg (Polynomial.eval x) hpoly simpa only [eval_sub, eval_mul, eval_neg] using hev have hD2b : (W.Φ ((n : ℤ) + 3)).eval x * (W.ΨSq ((n : ℤ) + 1)).eval x - (W.Φ ((n : ℤ) + 1)).eval x * (W.ΨSq ((n : ℤ) + 3)).eval x = -((W.preΨ (2 * (n : ℤ) + 4)).eval x * (W.Ψ₂Sq).eval x) := by have hpoly := W.Φ_succ_mul_ΨSq_pred_sub_Φ_pred_mul_ΨSq_succ ((n : ℤ) + 2) rw [show (n : ℤ) + 2 + 1 = (n : ℤ) + 3 by ring, show (n : ℤ) + 2 - 1 = (n : ℤ) + 1 by ring, show 2 * ((n : ℤ) + 2) = 2 * (n : ℤ) + 4 by ring] at hpoly have hev := congrArg (Polynomial.eval x) hpoly simpa only [eval_sub, eval_mul, eval_neg] using hev have hD3a : (x * (W.ΨSq ((n : ℤ) + 1)).eval x - (W.Φ ((n : ℤ) + 1)).eval x) ^ 2 = (W.ΨSq ((n : ℤ) + 2)).eval x * (W.ΨSq (n : ℤ)).eval x := by have hpoly := W.X_mul_ΨSq_sub_Φ_sq ((n : ℤ) + 1) rw [show (n : ℤ) + 1 + 1 = (n : ℤ) + 2 by ring, show (n : ℤ) + 1 - 1 = (n : ℤ) by ring] at hpoly have hev := congrArg (Polynomial.eval x) hpoly simpa only [eval_pow, eval_sub, eval_mul, eval_X] using hev have hD3b : (x * (W.ΨSq ((n : ℤ) + 2)).eval x - (W.Φ ((n : ℤ) + 2)).eval x) ^ 2 = (W.ΨSq ((n : ℤ) + 3)).eval x * (W.ΨSq ((n : ℤ) + 1)).eval x := by have hpoly := W.X_mul_ΨSq_sub_Φ_sq ((n : ℤ) + 2) rw [show (n : ℤ) + 2 + 1 = (n : ℤ) + 3 by ring, show (n : ℤ) + 2 - 1 = (n : ℤ) + 1 by ring] at hpoly have hev := congrArg (Polynomial.eval x) hpoly simpa only [eval_pow, eval_sub, eval_mul, eval_X] using hev have hPsi : (W.ΨSq (2 * (n : ℤ) + 3)).eval x = ((W.preΨ (2 * (n : ℤ) + 3)).eval x) ^ 2 := by have hodd : ¬ Even (2 * (n : ℤ) + 3) := by rintro ⟨r, hr⟩ omega have hev := congrArg (Polynomial.eval x) (W.ΨSq_of_odd hodd) simpa only [eval_pow] using hev have hPhi : (W.Φ (2 * (n : ℤ) + 3)).eval x = x * (W.ΨSq (2 * (n : ℤ) + 3)).eval x - (W.preΨ (2 * (n : ℤ) + 4)).eval x * (W.preΨ (2 * (n : ℤ) + 2)).eval x * (W.Ψ₂Sq).eval x := by have hpoly := W.Φ_two_mul_add_one ((n : ℤ) + 1) rw [show 2 * ((n : ℤ) + 1) + 1 = 2 * (n : ℤ) + 3 by ring, show 2 * ((n : ℤ) + 1) + 2 = 2 * (n : ℤ) + 4 by ring, show 2 * ((n : ℤ) + 1) = 2 * (n : ℤ) + 2 by ring] at hpoly have hev := congrArg (Polynomial.eval x) hpoly simpa only [eval_sub, eval_mul, eval_X] using hev have hSkne : (W.ΨSq ((n : ℤ) + 1)).eval x ≠ 0 := by have h1 := ih1.1; rwa [hc1] at h1 have hSk1ne : (W.ΨSq ((n : ℤ) + 2)).eval x ≠ 0 := by have h1 := ih2.1; rwa [hc2] at h1 obtain ⟨hS2ne, hmain⟩ := odd_step_core hM0 hMm hM1 hM2 hD1 hD2a hD2b hD3a hD3b hPsi hPhi hg1 hg2 hg3 hg3p W.b_relation (eval_Ψ₂Sq' x) hSkne hSk1ne hba constructor · rwa [hc23] · rw [hc23, hrearrS, hbeq, haeq, Point.add_of_X_ne hba, Point.xOrZero_some] exact mul_right_cancel₀ hQne hmain set_option maxHeartbeats 800000 in theorem mfred_double {n : ℕ} (hn : 1 ≤ n) {x y : F} (h : W.toAffine.Nonsingular x y) (hfree : LowTorsionFree (2 * n + 2) h) (ih0 : MFred n h) (ih1 : MFred (n + 1) h) (ih2 : MFred (n + 2) h) : MFred (2 * n + 2) h := by have hc1 : ((n + 1 : ℕ) : ℤ) = (n : ℤ) + 1 := by push_cast; ring have hc2 : ((n + 2 : ℕ) : ℤ) = (n : ℤ) + 2 := by push_cast; ring have hc22 : ((2 * n + 2 : ℕ) : ℤ) = 2 * (n : ℤ) + 2 := by push_cast; ring have hy2 : y ≠ W.toAffine.negY x y := fun hy => hfree 2 one_le_two (by omega) (by rw [two_nsmul]; exact Point.add_self_of_Y_eq hy) have hQne : (W.Ψ₂Sq).eval x ≠ 0 := Ψ₂Sq_eval_ne_zero' h.left hy2 obtain ⟨xa, ya, ha, haeq⟩ : ∃ (xa ya : F) (ha : W.toAffine.Nonsingular xa ya), ((n + 1) • (Point.some x y h : W.toAffine.Point)) = Point.some xa ya ha := by cases hE : ((n + 1) • (Point.some x y h : W.toAffine.Point)) with | zero => exact absurd hE (hfree (n + 1) (by omega) (by omega)) | @some xa ya ha => exact ⟨xa, ya, ha, rfl⟩ obtain ⟨xb, yb, hb, hbeq⟩ : ∃ (xb yb : F) (hb : W.toAffine.Nonsingular xb yb), ((n + 2) • (Point.some x y h : W.toAffine.Point)) = Point.some xb yb hb := by cases hE : ((n + 2) • (Point.some x y h : W.toAffine.Point)) with | zero => exact absurd hE (hfree (n + 2) (by omega) (by omega)) | @some xb yb hb => exact ⟨xb, yb, hb, rfl⟩ obtain ⟨xg, yg, hgc, hgeq⟩ : ∃ (xg yg : F) (hgc : W.toAffine.Nonsingular xg yg), (n • (Point.some x y h : W.toAffine.Point)) = Point.some xg yg hgc := by cases hE : (n • (Point.some x y h : W.toAffine.Point)) with | zero => exact absurd hE (hfree n hn (by omega)) | @some xg yg hgc => exact ⟨xg, yg, hgc, rfl⟩ obtain ⟨x2, y2, h2c, h2eq⟩ : ∃ (x2 y2 : F) (h2c : W.toAffine.Nonsingular x2 y2), ((2 : ℕ) • (Point.some x y h : W.toAffine.Point)) = Point.some x2 y2 h2c := by cases hE : ((2 : ℕ) • (Point.some x y h : W.toAffine.Point)) with | zero => exact absurd hE (hfree 2 one_le_two (by omega)) | @some x2 y2 h2c => exact ⟨x2, y2, h2c, rfl⟩ have hax : xa ≠ x := by refine x_ne_of_ne_of_ne_neg ha h ?_ ?_ · intro hE refine hfree n hn (by omega) (add_right_cancel (b := (Point.some x y h)) ?_) rw [← succ_nsmul, haeq, hE, zero_add] · intro hE refine hfree (n + 2) (by omega) (by omega) ?_ rw [show n + 2 = (n + 1) + 1 by ring, succ_nsmul, haeq, hE, neg_add_cancel] have hbg : xb ≠ xg := by refine x_ne_of_ne_of_ne_neg hb hgc ?_ ?_ · intro hE refine hfree 2 one_le_two (by omega) (add_right_cancel (b := (n • (Point.some x y h : W.toAffine.Point))) ?_) rw [← add_nsmul, show 2 + n = n + 2 by ring, hbeq, hE, zero_add, ← hgeq] · intro hE refine hfree (2 * n + 2) (by omega) le_rfl ?_ rw [show 2 * n + 2 = (n + 2) + n by ring, add_nsmul, hbeq, hgeq, hE, neg_add_cancel] have hM0 : xa * (W.ΨSq ((n : ℤ) + 1)).eval x = (W.Φ ((n : ℤ) + 1)).eval x := by have h1 := ih1.2 rwa [haeq, Point.xOrZero_some, hc1] at h1 have hM1 : xb * (W.ΨSq ((n : ℤ) + 2)).eval x = (W.Φ ((n : ℤ) + 2)).eval x := by have h1 := ih2.2 rwa [hbeq, Point.xOrZero_some, hc2] at h1 have hMm : xg * (W.ΨSq (n : ℤ)).eval x = (W.Φ (n : ℤ)).eval x := by have h1 := ih0.2 rwa [hgeq, Point.xOrZero_some] at h1 have hbdec : ((n + 2) • (Point.some x y h : W.toAffine.Point)) = Point.some xa ya ha + Point.some x y h := by rw [show n + 2 = (n + 1) + 1 by ring, succ_nsmul, haeq] have hbid : W.toAffine.addX xa x (W.toAffine.slope xa x ya y) = xb := by rw [Point.add_of_X_ne hax] at hbdec simpa using congrArg Point.xOrZero (hbdec.symm.trans hbeq) have hgdec : (n • (Point.some x y h : W.toAffine.Point)) = Point.some xa ya ha + -(Point.some x y h) := by rw [← haeq, succ_nsmul, add_neg_cancel_right] have hgid : W.toAffine.addX xa x (W.toAffine.slope xa x ya (W.toAffine.negY x y)) = xg := by rw [Point.neg_some, Point.add_of_X_ne hax] at hgdec simpa using congrArg Point.xOrZero (hgdec.symm.trans hgeq) have h2dec_pair : ((2 : ℕ) • (Point.some x y h : W.toAffine.Point)) = Point.some xb yb hb + -(Point.some xg yg hgc) := by have h0 : ((2 : ℕ) • (Point.some x y h : W.toAffine.Point)) = ((n + 2) • (Point.some x y h : W.toAffine.Point)) - (n • (Point.some x y h : W.toAffine.Point)) := by rw [show n + 2 = 2 + n by ring, add_nsmul] abel rw [h0, hbeq, hgeq, sub_eq_add_neg] have hx2id_pair : W.toAffine.addX xb xg (W.toAffine.slope xb xg yb (W.toAffine.negY xg yg)) = x2 := by rw [Point.neg_some, Point.add_of_X_ne hbg] at h2dec_pair simpa using congrArg Point.xOrZero (h2dec_pair.symm.trans h2eq) have h2dec_dup : ((2 : ℕ) • (Point.some x y h : W.toAffine.Point)) = Point.some x y h + Point.some x y h := two_nsmul _ have hx2id_dup : W.toAffine.addX x x (W.toAffine.slope x x y y) = x2 := by rw [Point.add_self_of_Y_ne hy2] at h2dec_dup simpa using congrArg Point.xOrZero (h2dec_dup.symm.trans h2eq) have hg3 := addX_add_addX_negY_mul_sq' (W := W) ha.left h.left hax rw [hbid, hgid] at hg3 have hg3p := addX_mul_addX_negY_mul_sq' (W := W) ha.left h.left hax rw [hbid, hgid] at hg3p have hg4 := addX_add_addX_negY_mul_sq' (W := W) hb.left hgc.left hbg rw [hx2id_pair] at hg4 have hdup := addX_self_mul_Ψ₂Sq' (W := W) h.left hy2 rw [hx2id_dup] at hdup have hD1 : (W.Φ ((n : ℤ) + 2)).eval x * (W.ΨSq ((n : ℤ) + 1)).eval x - (W.Φ ((n : ℤ) + 1)).eval x * (W.ΨSq ((n : ℤ) + 2)).eval x = -(W.preΨ (2 * (n : ℤ) + 3)).eval x := by have hpoly := W.Φ_succ_mul_ΨSq_sub_Φ_mul_ΨSq_succ ((n : ℤ) + 1) rw [show (n : ℤ) + 1 + 1 = (n : ℤ) + 2 by ring, show 2 * ((n : ℤ) + 1) + 1 = 2 * (n : ℤ) + 3 by ring] at hpoly have hev := congrArg (Polynomial.eval x) hpoly simpa only [eval_sub, eval_mul, eval_neg] using hev have hD1m : (W.Φ ((n : ℤ) + 1)).eval x * (W.ΨSq (n : ℤ)).eval x - (W.Φ (n : ℤ)).eval x * (W.ΨSq ((n : ℤ) + 1)).eval x = -(W.preΨ (2 * (n : ℤ) + 1)).eval x := by have hpoly := W.Φ_succ_mul_ΨSq_sub_Φ_mul_ΨSq_succ ((n : ℤ)) have hev := congrArg (Polynomial.eval x) hpoly simpa only [eval_sub, eval_mul, eval_neg] using hev have hD2a : (W.Φ ((n : ℤ) + 2)).eval x * (W.ΨSq (n : ℤ)).eval x - (W.Φ (n : ℤ)).eval x * (W.ΨSq ((n : ℤ) + 2)).eval x = -((W.preΨ (2 * (n : ℤ) + 2)).eval x * (W.Ψ₂Sq).eval x) := by have hpoly := W.Φ_succ_mul_ΨSq_pred_sub_Φ_pred_mul_ΨSq_succ ((n : ℤ) + 1) rw [show (n : ℤ) + 1 + 1 = (n : ℤ) + 2 by ring, show (n : ℤ) + 1 - 1 = (n : ℤ) by ring, show 2 * ((n : ℤ) + 1) = 2 * (n : ℤ) + 2 by ring] at hpoly have hev := congrArg (Polynomial.eval x) hpoly simpa only [eval_sub, eval_mul, eval_neg] using hev have hD3a : (x * (W.ΨSq ((n : ℤ) + 1)).eval x - (W.Φ ((n : ℤ) + 1)).eval x) ^ 2 = (W.ΨSq ((n : ℤ) + 2)).eval x * (W.ΨSq (n : ℤ)).eval x := by have hpoly := W.X_mul_ΨSq_sub_Φ_sq ((n : ℤ) + 1) rw [show (n : ℤ) + 1 + 1 = (n : ℤ) + 2 by ring, show (n : ℤ) + 1 - 1 = (n : ℤ) by ring] at hpoly have hev := congrArg (Polynomial.eval x) hpoly simpa only [eval_pow, eval_sub, eval_mul, eval_X] using hev have hPsi : (W.ΨSq (2 * (n : ℤ) + 2)).eval x = ((W.preΨ (2 * (n : ℤ) + 2)).eval x) ^ 2 * (W.Ψ₂Sq).eval x := by have heven : Even (2 * (n : ℤ) + 2) := ⟨(n : ℤ) + 1, by ring⟩ have hev := congrArg (Polynomial.eval x) (W.ΨSq_of_even heven) simpa only [eval_mul, eval_pow] using hev have hPhi : (W.Φ (2 * (n : ℤ) + 2)).eval x = x * (W.ΨSq (2 * (n : ℤ) + 2)).eval x - (W.preΨ (2 * (n : ℤ) + 3)).eval x * (W.preΨ (2 * (n : ℤ) + 1)).eval x := by have hpoly := W.Φ_two_mul ((n : ℤ) + 1) rw [show 2 * ((n : ℤ) + 1) = 2 * (n : ℤ) + 2 by ring, show 2 * (n : ℤ) + 2 + 1 = 2 * (n : ℤ) + 3 by ring, show 2 * (n : ℤ) + 2 - 1 = 2 * (n : ℤ) + 1 by ring] at hpoly have hev := congrArg (Polynomial.eval x) hpoly simpa only [eval_sub, eval_mul, eval_X] using hev have hSk1ne : (W.ΨSq ((n : ℤ) + 2)).eval x ≠ 0 := by have h1 := ih2.1; rwa [hc2] at h1 have hSkmne : (W.ΨSq (n : ℤ)).eval x ≠ 0 := ih0.1 obtain ⟨hS2ne, hmain⟩ := even_step_core hM0 hMm hM1 hD1 hD1m hD2a hD3a hPsi hPhi hg4 hdup hg3 hg3p W.b_relation (eval_Ψ₂Sq' x) (eval_Φ_two' x) hQne hSk1ne hSkmne hax hbg have hrearrS : ((2 * n + 2) • (Point.some x y h : W.toAffine.Point)) = ((n + 2) • (Point.some x y h : W.toAffine.Point)) + (n • (Point.some x y h : W.toAffine.Point)) := by rw [show 2 * n + 2 = (n + 2) + n by ring, add_nsmul] constructor · rwa [hc22] · rw [hc22, hrearrS, hbeq, hgeq, Point.add_of_X_ne hbg, Point.xOrZero_some] exact mul_right_cancel₀ hQne hmain theorem mfred_all {x y : F} (h : W.toAffine.Nonsingular x y) (m : ℕ) (hm : 1 ≤ m) (hfree : LowTorsionFree m h) : MFred m h := by induction m using Nat.strong_induction_on with | _ m ih => by_cases h5 : m ≤ 5 · exact mfred_of_le_five h5 h hfree m hm le_rfl · rcases Nat.even_or_odd m with hev | hodd · obtain ⟨q, rfl⟩ : ∃ q, m = 2 * q + 2 := by obtain ⟨r, hr⟩ := hev exact ⟨r - 1, by omega⟩ exact mfred_double (by omega) h hfree (ih q (by omega) (by omega) (hfree.mono (by omega))) (ih (q + 1) (by omega) (by omega) (hfree.mono (by omega))) (ih (q + 2) (by omega) (by omega) (hfree.mono (by omega))) · obtain ⟨q, rfl⟩ : ∃ q, m = 2 * q + 3 := by obtain ⟨r, hr⟩ := hodd exact ⟨r - 1, by omega⟩ exact mfred_double_succ (by omega) h hfree (ih q (by omega) (by omega) (hfree.mono (by omega))) (ih (q + 1) (by omega) (by omega) (hfree.mono (by omega))) (ih (q + 2) (by omega) (by omega) (hfree.mono (by omega))) (ih (q + 3) (by omega) (by omega) (hfree.mono (by omega))) end WeierstrassCurve.Affine open Polynomial namespace WeierstrassCurve.Affine variable {F : Type u} [Field F] [DecidableEq F] {W : WeierstrassCurve F} section RootToTorsion theorem nsmul_succ_eq_zero_of_ΨSq_eval_eq_zero {m : ℕ} (hm : 2 ≤ m) {x y : F} (h : W.toAffine.Nonsingular x y) (hfree : LowTorsionFree m h) (hmf : MFred m h) (hroot : (W.ΨSq ((m : ℤ) + 1)).eval x = 0) : (m + 1) • (Point.some x y h : W.toAffine.Point) = 0 := by have hpoly := W.X_mul_ΨSq_sub_Φ_sq (m : ℤ) have hev := congrArg (Polynomial.eval x) hpoly simp only [eval_pow, eval_sub, eval_mul, eval_X] at hev have hsq : (x * (W.ΨSq (m : ℤ)).eval x - (W.Φ (m : ℤ)).eval x) ^ 2 = 0 := by rw [hev, hroot, zero_mul] have hxΦ : x * (W.ΨSq (m : ℤ)).eval x = (W.Φ (m : ℤ)).eval x := sub_eq_zero.mp (pow_eq_zero_iff (by norm_num : (2 : ℕ) ≠ 0) |>.mp hsq) have hmPne : (m • (Point.some x y h : W.toAffine.Point)) ≠ 0 := hfree m (by omega) le_rfl obtain ⟨xm, ym, hm', hmPeq⟩ : ∃ (xm ym : F) (hm' : W.toAffine.Nonsingular xm ym), (m • (Point.some x y h : W.toAffine.Point)) = Point.some xm ym hm' := by cases hmP : (m • (Point.some x y h : W.toAffine.Point)) with | zero => exact absurd hmP hmPne | @some xm ym hm' => exact ⟨xm, ym, hm', rfl⟩ have hxm : xm = x := by have h2 := hmf.2 rw [hmPeq, Point.xOrZero_some] at h2 exact mul_right_cancel₀ hmf.1 (h2.trans hxΦ.symm) rcases Y_eq_of_X_eq hm'.left h.left hxm with hyy | hyy · exfalso have hmP_P : (m • (Point.some x y h : W.toAffine.Point)) = Point.some x y h := by rw [hmPeq] subst hxm; subst hyy exact congrArg _ (Subsingleton.elim _ _) have hsucc : ((m - 1) + 1) • (Point.some x y h : W.toAffine.Point) = (m - 1) • (Point.some x y h : W.toAffine.Point) + Point.some x y h := succ_nsmul _ _ rw [show m - 1 + 1 = m by omega] at hsucc have hcontra : (m - 1) • (Point.some x y h : W.toAffine.Point) + Point.some x y h = 0 + Point.some x y h := by rw [zero_add, ← hsucc, hmP_P] exact hfree (m - 1) (by omega) (by omega) (add_right_cancel hcontra) · have hmPneg : (m • (Point.some x y h : W.toAffine.Point)) = -(Point.some x y h : W.toAffine.Point) := by rw [hmPeq, Point.neg_some] subst hxm; subst hyy exact congrArg _ (Subsingleton.elim _ _) calc (m + 1) • (Point.some x y h : W.toAffine.Point) = m • (Point.some x y h : W.toAffine.Point) + Point.some x y h := succ_nsmul _ _ _ = -(Point.some x y h : W.toAffine.Point) + Point.some x y h := by rw [hmPneg] _ = 0 := neg_add_cancel _ end RootToTorsion section TorsionToRoot theorem ΨSq_eval_eq_zero_or_of_succ_nsmul_eq_zero {m : ℕ} {x y : F} (h : W.toAffine.Nonsingular x y) (hmf : MFred m h) (hkill : (m + 1) • (Point.some x y h : W.toAffine.Point) = 0) : (W.ΨSq ((m : ℤ) + 1)).eval x = 0 ∨ (W.ΨSq ((m : ℤ) - 1)).eval x = 0 := by have hmPneg : (m • (Point.some x y h : W.toAffine.Point)) = -(Point.some x y h : W.toAffine.Point) := by have hsucc : (m + 1) • (Point.some x y h : W.toAffine.Point) = m • (Point.some x y h : W.toAffine.Point) + Point.some x y h := succ_nsmul _ _ rw [hsucc] at hkill exact eq_neg_of_add_eq_zero_left hkill have hxΦ : x * (W.ΨSq (m : ℤ)).eval x = (W.Φ (m : ℤ)).eval x := by have h2 := hmf.2 rw [hmPneg, Point.neg_some, Point.xOrZero_some] at h2 exact h2 have hpoly := W.X_mul_ΨSq_sub_Φ_sq (m : ℤ) have hev := congrArg (Polynomial.eval x) hpoly simp only [eval_pow, eval_sub, eval_mul, eval_X] at hev have hprod : (W.ΨSq ((m : ℤ) + 1)).eval x * (W.ΨSq ((m : ℤ) - 1)).eval x = 0 := by rw [← hev, sub_eq_zero_of_eq hxΦ] ring exact mul_eq_zero.mp hprod theorem ΨSq_eval_eq_zero_of_succ_nsmul_eq_zero {m : ℕ} (hm : 4 ≤ m) {x y : F} (h : W.toAffine.Nonsingular x y) (hfree : LowTorsionFree m h) (hmf : MFred m h) (hmf' : MFred (m - 2) h) (hkill : (m + 1) • (Point.some x y h : W.toAffine.Point) = 0) : (W.ΨSq ((m : ℤ) + 1)).eval x = 0 := by rcases ΨSq_eval_eq_zero_or_of_succ_nsmul_eq_zero h hmf hkill with hgood | hbad · exact hgood · exfalso have hbad' : (W.ΨSq (((m - 2 : ℕ) : ℤ) + 1)).eval x = 0 := by rw [show (((m - 2 : ℕ) : ℤ) + 1) = (m : ℤ) - 1 by omega] exact hbad have hzero := nsmul_succ_eq_zero_of_ΨSq_eval_eq_zero (m := m - 2) (by omega) h (hfree.mono (by omega)) hmf' hbad' rw [show m - 2 + 1 = m - 1 by omega] at hzero exact hfree (m - 1) (by omega) (by omega) hzero theorem succ_nsmul_eq_zero_iff_ΨSq_eval_eq_zero {m : ℕ} (hm : 4 ≤ m) {x y : F} (h : W.toAffine.Nonsingular x y) (hfree : LowTorsionFree m h) (hmf : MFred m h) (hmf' : MFred (m - 2) h) : (m + 1) • (Point.some x y h : W.toAffine.Point) = 0 ↔ (W.ΨSq ((m : ℤ) + 1)).eval x = 0 := ⟨ΨSq_eval_eq_zero_of_succ_nsmul_eq_zero hm h hfree hmf hmf', nsmul_succ_eq_zero_of_ΨSq_eval_eq_zero (by omega) h hfree hmf⟩ end TorsionToRoot section StarForm theorem nsmul_eq_zero_of_ΨSq_eval_eq_zero_of_starIdentity {n : ℕ} (hn : 3 ≤ n) {x y : F} (h : W.toAffine.Nonsingular x y) (hfree : LowTorsionFree (n - 1) h) (hstar : ∀ j : ℤ, 2 ≤ j → j + 2 ≤ (n : ℤ) → W.StarIdentity j) (hroot : (W.ΨSq (n : ℤ)).eval x = 0) : n • (Point.some x y h : W.toAffine.Point) = 0 := by have hmf : MFred (n - 1) h := by refine mfred_of_forall_starIdentity (n - 1) h hfree (fun j hj2 hjM => hstar j hj2 (by omega)) (n - 1) (by omega) le_rfl have hroot' : (W.ΨSq (((n - 1 : ℕ) : ℤ) + 1)).eval x = 0 := by rw [show (((n - 1 : ℕ) : ℤ) + 1) = (n : ℤ) by omega] exact hroot have hzero := nsmul_succ_eq_zero_of_ΨSq_eval_eq_zero (m := n - 1) (by omega) h hfree hmf hroot' rwa [show n - 1 + 1 = n by omega] at hzero theorem nsmul_six_eq_zero_of_ΨSq_eval_eq_zero {x y : F} (h : W.toAffine.Nonsingular x y) (hfree : LowTorsionFree 5 h) (hroot : (W.ΨSq (6 : ℤ)).eval x = 0) : 6 • (Point.some x y h : W.toAffine.Point) = 0 := by have h6 := nsmul_eq_zero_of_ΨSq_eval_eq_zero_of_starIdentity (n := 6) (by norm_num) h (by simpa using hfree) (fun j hj2 hj6 => W.starIdentity_of_le_four j (by omega) (by omega)) (by exact_mod_cast hroot) simpa using h6 end StarForm end WeierstrassCurve.Affine