l3lab/ntp-mathlib huggingface dataset:
lemma nonsingular_iff (x y : R) : W.nonsingular x y ↔
    W.equation x y ∧ (W.a₁ * y ≠ 3 * x ^ 2 + 2 * W.a₂ * x + W.a₄ ∨ y ≠ -y - W.a₁ * x - W.a₃) := by
  

Proof state:
R : Type u
inst✝ : CommRing R
W : Affine R
x y : R
⊢ W.nonsingular x y ↔ W.equation x y ∧ (W.a₁ * y ≠ 3 * x ^ 2 + 2 * W.a₂ * x + W.a₄ ∨ y ≠ -y - W.a₁ * x - W.a₃)

Next tactic:
rw [nonsingular_iff', sub_ne_zero, ← sub_ne_zero (a := y)]
lemma nonsingular_iff (x y : R) : W.nonsingular x y ↔
    W.equation x y ∧ (W.a₁ * y ≠ 3 * x ^ 2 + 2 * W.a₂ * x + W.a₄ ∨ y ≠ -y - W.a₁ * x - W.a₃) := by
  rw [nonsingular_iff', sub_ne_zero, ← sub_ne_zero (a := y)]
  

Proof state:
R : Type u
inst✝ : CommRing R
W : Affine R
x y : R
⊢ W.equation x y ∧ (W.a₁ * y ≠ 3 * x ^ 2 + 2 * W.a₂ * x + W.a₄ ∨ 2 * y + W.a₁ * x + W.a₃ ≠ 0) ↔
    W.equation x y ∧ (W.a₁ * y ≠ 3 * x ^ 2 + 2 * W.a₂ * x + W.a₄ ∨ y - (-y - W.a₁ * x - W.a₃) ≠ 0)

Next tactic:
congr! 3
lemma nonsingular_iff (x y : R) : W.nonsingular x y ↔
    W.equation x y ∧ (W.a₁ * y ≠ 3 * x ^ 2 + 2 * W.a₂ * x + W.a₄ ∨ y ≠ -y - W.a₁ * x - W.a₃) := by
  rw [nonsingular_iff', sub_ne_zero, ← sub_ne_zero (a := y)]
  congr! 3
  

Proof state:
case a.h.e'_2.h.e'_2.h.e'_2
R : Type u
inst✝ : CommRing R
W : Affine R
x y : R
⊢ 2 * y + W.a₁ * x + W.a₃ = y - (-y - W.a₁ * x - W.a₃)

Next tactic:
ring1
@[simp]
lemma nonsingular_zero : W.nonsingular 0 0 ↔ W.a₆ = 0 ∧ (W.a₃ ≠ 0 ∨ W.a₄ ≠ 0) := by
  

Proof state:
R : Type u
inst✝ : CommRing R
W : Affine R
⊢ W.nonsingular 0 0 ↔ W.a₆ = 0 ∧ (W.a₃ ≠ 0 ∨ W.a₄ ≠ 0)

Next tactic:
rw [nonsingular, equation_zero, C_0, eval_polynomialX_zero, neg_ne_zero,
    eval_polynomialY_zero, or_comm]
lemma nonsingular_iff_variableChange (x y : R) :
    W.nonsingular x y ↔ (W.variableChange ⟨1, x, 0, y⟩).toAffine.nonsingular 0 0 := by
  

Proof state:
R : Type u
inst✝ : CommRing R
W : Affine R
x y : R
⊢ W.nonsingular x y ↔ (W.variableChange { u := 1, r := x, s := 0, t := y }).toAffine.nonsingular 0 0

Next tactic:
rw [nonsingular_iff', equation_iff_variableChange, equation_zero, ← neg_ne_zero, or_comm,
    nonsingular_zero, variableChange_a₃, variableChange_a₄, inv_one, Units.val_one]
lemma nonsingular_iff_variableChange (x y : R) :
    W.nonsingular x y ↔ (W.variableChange ⟨1, x, 0, y⟩).toAffine.nonsingular 0 0 := by
  rw [nonsingular_iff', equation_iff_variableChange, equation_zero, ← neg_ne_zero, or_comm,
    nonsingular_zero, variableChange_a₃, variableChange_a₄, inv_one, Units.val_one]
  

Proof state:
R : Type u
inst✝ : CommRing R
W : Affine R
x y : R
⊢ (W.variableChange { u := 1, r := x, s := 0, t := y }).toAffine.a₆ = 0 ∧
      (2 * y + W.a₁ * x + W.a₃ ≠ 0 ∨ -(W.a₁ * y - (3 * x ^ 2 + 2 * W.a₂ * x + W.a₄)) ≠ 0) ↔
    (W.variableChange { u := 1, r := x, s := 0, t := y }).toAffine.a₆ = 0 ∧
      (1 ^ 3 * (W.a₃ + { u := 1, r := x, s := 0, t := y }.r * W.a₁ + 2 * { u := 1, r := x, s := 0, t := y }.t) ≠ 0 ∨
        1 ^ 4 *
            (W.a₄ - { u := 1, r := x, s := 0, t := y }.s * W.a₃ + 2 * { u := 1, r := x, s := 0, t := y }.r * W.a₂ -
                  ({ u := 1, r := x, s := 0, t := y }.t +
                      { u := 1, r := x, s := 0, t := y }.r * { u := 1, r := x, s := 0, t := y }.s) *
                    W.a₁ +
                3 * { u := 1, r := x, s := 0, t := y }.r ^ 2 -
              2 * { u := 1, r := x, s := 0, t := y }.s * { u := 1, r := x, s := 0, t := y }.t) ≠
          0)

Next tactic:
simp only [variableChange]
lemma nonsingular_iff_variableChange (x y : R) :
    W.nonsingular x y ↔ (W.variableChange ⟨1, x, 0, y⟩).toAffine.nonsingular 0 0 := by
  rw [nonsingular_iff', equation_iff_variableChange, equation_zero, ← neg_ne_zero, or_comm,
    nonsingular_zero, variableChange_a₃, variableChange_a₄, inv_one, Units.val_one]
  simp only [variableChange]
  

Proof state:
R : Type u
inst✝ : CommRing R
W : Affine R
x y : R
⊢ ↑1⁻¹ ^ 6 * (W.a₆ + x * W.a₄ + x ^ 2 * W.a₂ + x ^ 3 - y * W.a₃ - y ^ 2 - x * y * W.a₁) = 0 ∧
      (2 * y + W.a₁ * x + W.a₃ ≠ 0 ∨ -(W.a₁ * y - (3 * x ^ 2 + 2 * W.a₂ * x + W.a₄)) ≠ 0) ↔
    ↑1⁻¹ ^ 6 * (W.a₆ + x * W.a₄ + x ^ 2 * W.a₂ + x ^ 3 - y * W.a₃ - y ^ 2 - x * y * W.a₁) = 0 ∧
      (1 ^ 3 * (W.a₃ + x * W.a₁ + 2 * y) ≠ 0 ∨
        1 ^ 4 * (W.a₄ - 0 * W.a₃ + 2 * x * W.a₂ - (y + x * 0) * W.a₁ + 3 * x ^ 2 - 2 * 0 * y) ≠ 0)

Next tactic:
congr! 3
lemma nonsingular_iff_variableChange (x y : R) :
    W.nonsingular x y ↔ (W.variableChange ⟨1, x, 0, y⟩).toAffine.nonsingular 0 0 := by
  rw [nonsingular_iff', equation_iff_variableChange, equation_zero, ← neg_ne_zero, or_comm,
    nonsingular_zero, variableChange_a₃, variableChange_a₄, inv_one, Units.val_one]
  simp only [variableChange]
  congr! 3 <;> 

Proof state:
case a.h.e'_2.h.e'_1.h.e'_2
R : Type u
inst✝ : CommRing R
W : Affine R
x y : R
⊢ 2 * y + W.a₁ * x + W.a₃ = 1 ^ 3 * (W.a₃ + x * W.a₁ + 2 * y)

Next tactic:
ring1
lemma nonsingular_iff_variableChange (x y : R) :
    W.nonsingular x y ↔ (W.variableChange ⟨1, x, 0, y⟩).toAffine.nonsingular 0 0 := by
  rw [nonsingular_iff', equation_iff_variableChange, equation_zero, ← neg_ne_zero, or_comm,
    nonsingular_zero, variableChange_a₃, variableChange_a₄, inv_one, Units.val_one]
  simp only [variableChange]
  congr! 3 <;> 

Proof state:
case a.h.e'_2.h.e'_2.h.e'_2
R : Type u
inst✝ : CommRing R
W : Affine R
x y : R
⊢ -(W.a₁ * y - (3 * x ^ 2 + 2 * W.a₂ * x + W.a₄)) =
    1 ^ 4 * (W.a₄ - 0 * W.a₃ + 2 * x * W.a₂ - (y + x * 0) * W.a₁ + 3 * x ^ 2 - 2 * 0 * y)

Next tactic:
ring1
lemma nonsingular_zero_of_Δ_ne_zero (h : W.equation 0 0) (hΔ : W.Δ ≠ 0) : W.nonsingular 0 0 := by
  

Proof state:
R : Type u
inst✝ : CommRing R
W : Affine R
h : W.equation 0 0
hΔ : W.Δ ≠ 0
⊢ W.nonsingular 0 0

Next tactic:
simp only [equation_zero, nonsingular_zero] at *
lemma nonsingular_zero_of_Δ_ne_zero (h : W.equation 0 0) (hΔ : W.Δ ≠ 0) : W.nonsingular 0 0 := by
  simp only [equation_zero, nonsingular_zero] at *
  

Proof state:
R : Type u
inst✝ : CommRing R
W : Affine R
hΔ : W.Δ ≠ 0
h : W.a₆ = 0
⊢ W.a₆ = 0 ∧ (W.a₃ ≠ 0 ∨ W.a₄ ≠ 0)

Next tactic:
contrapose! hΔ
lemma nonsingular_zero_of_Δ_ne_zero (h : W.equation 0 0) (hΔ : W.Δ ≠ 0) : W.nonsingular 0 0 := by
  simp only [equation_zero, nonsingular_zero] at *
  contrapose! hΔ
  

Proof state:
R : Type u
inst✝ : CommRing R
W : Affine R
h : W.a₆ = 0
hΔ : W.a₆ = 0 → W.a₃ = 0 ∧ W.a₄ = 0
⊢ W.Δ = 0

Next tactic:
simp only [b₂, b₄, b₆, b₈, Δ, h, hΔ]
lemma nonsingular_zero_of_Δ_ne_zero (h : W.equation 0 0) (hΔ : W.Δ ≠ 0) : W.nonsingular 0 0 := by
  simp only [equation_zero, nonsingular_zero] at *
  contrapose! hΔ
  simp only [b₂, b₄, b₆, b₈, Δ, h, hΔ]
  

Proof state:
R : Type u
inst✝ : CommRing R
W : Affine R
h : W.a₆ = 0
hΔ : W.a₆ = 0 → W.a₃ = 0 ∧ W.a₄ = 0
⊢ -(W.a₁ ^ 2 + 4 * W.a₂) ^ 2 * (W.a₁ ^ 2 * 0 + 4 * W.a₂ * 0 - W.a₁ * 0 * 0 + W.a₂ * 0 ^ 2 - 0 ^ 2) -
          8 * (2 * 0 + W.a₁ * 0) ^ 3 -
        27 * (0 ^ 2 + 4 * 0) ^ 2 +
      9 * (W.a₁ ^ 2 + 4 * W.a₂) * (2 * 0 + W.a₁ * 0) * (0 ^ 2 + 4 * 0) =
    0

Next tactic:
ring1
/-- A Weierstrass curve is nonsingular at every point if its discriminant is non-zero. -/
lemma nonsingular_of_Δ_ne_zero {x y : R} (h : W.equation x y) (hΔ : W.Δ ≠ 0) : W.nonsingular x y :=
  (W.nonsingular_iff_variableChange x y).mpr <|
    nonsingular_zero_of_Δ_ne_zero _ ((W.equation_iff_variableChange x y).mp h) <| by
      

Proof state:
R : Type u
inst✝ : CommRing R
W : Affine R
x y : R
h : W.equation x y
hΔ : W.Δ ≠ 0
⊢ (W.variableChange { u := 1, r := x, s := 0, t := y }).toAffine.Δ ≠ 0

Next tactic:
rwa [variableChange_Δ, inv_one, Units.val_one, one_pow, one_mul]
lemma negY_negY (x y : R) : W.negY x (W.negY x y) = y := by
  

Proof state:
R : Type u
inst✝ : CommRing R
W : Affine R
x y : R
⊢ W.negY x (W.negY x y) = y

Next tactic:
simp only [negY]
lemma negY_negY (x y : R) : W.negY x (W.negY x y) = y := by
  simp only [negY]
  

Proof state:
R : Type u
inst✝ : CommRing R
W : Affine R
x y : R
⊢ -(-y - W.a₁ * x - W.a₃) - W.a₁ * x - W.a₃ = y

Next tactic:
ring1
lemma eval_negPolynomial (x y : R) : (W.negPolynomial.eval <| C y).eval x = W.negY x y := by
  

Proof state:
R : Type u
inst✝ : CommRing R
W : Affine R
x y : R
⊢ eval x (eval (C y) W.negPolynomial) = W.negY x y

Next tactic:
rw [negY, sub_sub, negPolynomial]
lemma eval_negPolynomial (x y : R) : (W.negPolynomial.eval <| C y).eval x = W.negY x y := by
  rw [negY, sub_sub, negPolynomial]
  

Proof state:
R : Type u
inst✝ : CommRing R
W : Affine R
x y : R
⊢ eval x (eval (C y) (-Y - C (C W.a₁ * Y + C W.a₃))) = -y - (W.a₁ * x + W.a₃)

Next tactic:
eval_simp
lemma C_addPolynomial (x y L : R) : C (W.addPolynomial x y L) =
    (Y - C (linePolynomial x y L)) * (W.negPolynomial - C (linePolynomial x y L)) +
      W.polynomial := by
  

Proof state:
R : Type u
inst✝ : CommRing R
W : Affine R
x y L : R
⊢ C (W.addPolynomial x y L) =
    (Y - C (x.linePolynomial y L)) * (W.negPolynomial - C (x.linePolynomial y L)) + W.polynomial

Next tactic:
rw [addPolynomial, linePolynomial, polynomial, negPolynomial]
lemma C_addPolynomial (x y L : R) : C (W.addPolynomial x y L) =
    (Y - C (linePolynomial x y L)) * (W.negPolynomial - C (linePolynomial x y L)) +
      W.polynomial := by
  rw [addPolynomial, linePolynomial, polynomial, negPolynomial]
  

Proof state:
R : Type u
inst✝ : CommRing R
W : Affine R
x y L : R
⊢ C
      (eval (C L * (Y - C x) + C y)
        (Y ^ 2 + C (C W.a₁ * Y + C W.a₃) * Y - C (Y ^ 3 + C W.a₂ * Y ^ 2 + C W.a₄ * Y + C W.a₆))) =
    (Y - C (C L * (Y - C x) + C y)) * (-Y - C (C W.a₁ * Y + C W.a₃) - C (C L * (Y - C x) + C y)) +
      (Y ^ 2 + C (C W.a₁ * Y + C W.a₃) * Y - C (Y ^ 3 + C W.a₂ * Y ^ 2 + C W.a₄ * Y + C W.a₆))

Next tactic:
eval_simp
lemma C_addPolynomial (x y L : R) : C (W.addPolynomial x y L) =
    (Y - C (linePolynomial x y L)) * (W.negPolynomial - C (linePolynomial x y L)) +
      W.polynomial := by
  rw [addPolynomial, linePolynomial, polynomial, negPolynomial]
  eval_simp
  

Proof state:
R : Type u
inst✝ : CommRing R
W : Affine R
x y L : R
⊢ C
      ((C L * (Y - C x) + C y) ^ 2 + (C W.a₁ * Y + C W.a₃) * (C L * (Y - C x) + C y) -
        (Y ^ 3 + C W.a₂ * Y ^ 2 + C W.a₄ * Y + C W.a₆)) =
    (Y - C (C L * (Y - C x) + C y)) * (-Y - C (C W.a₁ * Y + C W.a₃) - C (C L * (Y - C x) + C y)) +
      (Y ^ 2 + C (C W.a₁ * Y + C W.a₃) * Y - C (Y ^ 3 + C W.a₂ * Y ^ 2 + C W.a₄ * Y + C W.a₆))

Next tactic:
C_simp
lemma C_addPolynomial (x y L : R) : C (W.addPolynomial x y L) =
    (Y - C (linePolynomial x y L)) * (W.negPolynomial - C (linePolynomial x y L)) +
      W.polynomial := by
  rw [addPolynomial, linePolynomial, polynomial, negPolynomial]
  eval_simp
  C_simp
  

Proof state:
R : Type u
inst✝ : CommRing R
W : Affine R
x y L : R
⊢ (C (C L) * (C Y - C (C x)) + C (C y)) ^ 2 + (C (C W.a₁) * C Y + C (C W.a₃)) * (C (C L) * (C Y - C (C x)) + C (C y)) -
      (C Y ^ 3 + C (C W.a₂) * C Y ^ 2 + C (C W.a₄) * C Y + C (C W.a₆)) =
    (Y - (C (C L) * (C Y - C (C x)) + C (C y))) *
        (-Y - (C (C W.a₁) * C Y + C (C W.a₃)) - (C (C L) * (C Y - C (C x)) + C (C y))) +
      (Y ^ 2 + (C (C W.a₁) * C Y + C (C W.a₃)) * Y - (C Y ^ 3 + C (C W.a₂) * C Y ^ 2 + C (C W.a₄) * C Y + C (C W.a₆)))

Next tactic:
ring1
lemma addPolynomial_eq (x y L : R) : W.addPolynomial x y L = -Cubic.toPoly
    ⟨1, -L ^ 2 - W.a₁ * L + W.a₂,
      2 * x * L ^ 2 + (W.a₁ * x - 2 * y - W.a₃) * L + (-W.a₁ * y + W.a₄),
      -x ^ 2 * L ^ 2 + (2 * x * y + W.a₃ * x) * L - (y ^ 2 + W.a₃ * y - W.a₆)⟩ := by
  

Proof state:
R : Type u
inst✝ : CommRing R
W : Affine R
x y L : R
⊢ W.addPolynomial x y L =
    -Cubic.toPoly
        { a := 1, b := -L ^ 2 - W.a₁ * L + W.a₂,
          c := 2 * x * L ^ 2 + (W.a₁ * x - 2 * y - W.a₃) * L + (-W.a₁ * y + W.a₄),
          d := -x ^ 2 * L ^ 2 + (2 * x * y + W.a₃ * x) * L - (y ^ 2 + W.a₃ * y - W.a₆) }

Next tactic:
rw [addPolynomial, linePolynomial, polynomial, Cubic.toPoly]
lemma addPolynomial_eq (x y L : R) : W.addPolynomial x y L = -Cubic.toPoly
    ⟨1, -L ^ 2 - W.a₁ * L + W.a₂,
      2 * x * L ^ 2 + (W.a₁ * x - 2 * y - W.a₃) * L + (-W.a₁ * y + W.a₄),
      -x ^ 2 * L ^ 2 + (2 * x * y + W.a₃ * x) * L - (y ^ 2 + W.a₃ * y - W.a₆)⟩ := by
  rw [addPolynomial, linePolynomial, polynomial, Cubic.toPoly]
  

Proof state:
R : Type u
inst✝ : CommRing R
W : Affine R
x y L : R
⊢ eval (C L * (Y - C x) + C y)
      (Y ^ 2 + C (C W.a₁ * Y + C W.a₃) * Y - C (Y ^ 3 + C W.a₂ * Y ^ 2 + C W.a₄ * Y + C W.a₆)) =
    -(C
                { a := 1, b := -L ^ 2 - W.a₁ * L + W.a₂,
                    c := 2 * x * L ^ 2 + (W.a₁ * x - 2 * y - W.a₃) * L + (-W.a₁ * y + W.a₄),
                    d := -x ^ 2 * L ^ 2 + (2 * x * y + W.a₃ * x) * L - (y ^ 2 + W.a₃ * y - W.a₆) }.a *
              Y ^ 3 +
            C
                { a := 1, b := -L ^ 2 - W.a₁ * L + W.a₂,
                    c := 2 * x * L ^ 2 + (W.a₁ * x - 2 * y - W.a₃) * L + (-W.a₁ * y + W.a₄),
                    d := -x ^ 2 * L ^ 2 + (2 * x * y + W.a₃ * x) * L - (y ^ 2 + W.a₃ * y - W.a₆) }.b *
              Y ^ 2 +
          C
              { a := 1, b := -L ^ 2 - W.a₁ * L + W.a₂,
                  c := 2 * x * L ^ 2 + (W.a₁ * x - 2 * y - W.a₃) * L + (-W.a₁ * y + W.a₄),
                  d := -x ^ 2 * L ^ 2 + (2 * x * y + W.a₃ * x) * L - (y ^ 2 + W.a₃ * y - W.a₆) }.c *
            Y +
        C
          { a := 1, b := -L ^ 2 - W.a₁ * L + W.a₂,
              c := 2 * x * L ^ 2 + (W.a₁ * x - 2 * y - W.a₃) * L + (-W.a₁ * y + W.a₄),
              d := -x ^ 2 * L ^ 2 + (2 * x * y + W.a₃ * x) * L - (y ^ 2 + W.a₃ * y - W.a₆) }.d)

Next tactic:
eval_simp
lemma addPolynomial_eq (x y L : R) : W.addPolynomial x y L = -Cubic.toPoly
    ⟨1, -L ^ 2 - W.a₁ * L + W.a₂,
      2 * x * L ^ 2 + (W.a₁ * x - 2 * y - W.a₃) * L + (-W.a₁ * y + W.a₄),
      -x ^ 2 * L ^ 2 + (2 * x * y + W.a₃ * x) * L - (y ^ 2 + W.a₃ * y - W.a₆)⟩ := by
  rw [addPolynomial, linePolynomial, polynomial, Cubic.toPoly]
  eval_simp
  

Proof state:
R : Type u
inst✝ : CommRing R
W : Affine R
x y L : R
⊢ (C L * (Y - C x) + C y) ^ 2 + (C W.a₁ * Y + C W.a₃) * (C L * (Y - C x) + C y) -
      (Y ^ 3 + C W.a₂ * Y ^ 2 + C W.a₄ * Y + C W.a₆) =
    -(C 1 * Y ^ 3 + C (-L ^ 2 - W.a₁ * L + W.a₂) * Y ^ 2 +
          C (2 * x * L ^ 2 + (W.a₁ * x - 2 * y - W.a₃) * L + (-W.a₁ * y + W.a₄)) * Y +
        C (-x ^ 2 * L ^ 2 + (2 * x * y + W.a₃ * x) * L - (y ^ 2 + W.a₃ * y - W.a₆)))

Next tactic:
C_simp
lemma addPolynomial_eq (x y L : R) : W.addPolynomial x y L = -Cubic.toPoly
    ⟨1, -L ^ 2 - W.a₁ * L + W.a₂,
      2 * x * L ^ 2 + (W.a₁ * x - 2 * y - W.a₃) * L + (-W.a₁ * y + W.a₄),
      -x ^ 2 * L ^ 2 + (2 * x * y + W.a₃ * x) * L - (y ^ 2 + W.a₃ * y - W.a₆)⟩ := by
  rw [addPolynomial, linePolynomial, polynomial, Cubic.toPoly]
  eval_simp
  C_simp
  

Proof state:
R : Type u
inst✝ : CommRing R
W : Affine R
x y L : R
⊢ (C L * (Y - C x) + C y) ^ 2 + (C W.a₁ * Y + C W.a₃) * (C L * (Y - C x) + C y) -
      (Y ^ 3 + C W.a₂ * Y ^ 2 + C W.a₄ * Y + C W.a₆) =
    -(1 * Y ^ 3 + (-C L ^ 2 - C W.a₁ * C L + C W.a₂) * Y ^ 2 +
          (2 * C x * C L ^ 2 + (C W.a₁ * C x - 2 * C y - C W.a₃) * C L + (-C W.a₁ * C y + C W.a₄)) * Y +
        (-C x ^ 2 * C L ^ 2 + (2 * C x * C y + C W.a₃ * C x) * C L - (C y ^ 2 + C W.a₃ * C y - C W.a₆)))

Next tactic:
ring1
lemma equation_neg_iff (x y : R) : W.equation x (W.negY x y) ↔ W.equation x y := by
  

Proof state:
R : Type u
inst✝ : CommRing R
W : Affine R
x y : R
⊢ W.equation x (W.negY x y) ↔ W.equation x y

Next tactic:
rw [equation_iff, equation_iff, negY]
lemma equation_neg_iff (x y : R) : W.equation x (W.negY x y) ↔ W.equation x y := by
  rw [equation_iff, equation_iff, negY]
  

Proof state:
R : Type u
inst✝ : CommRing R
W : Affine R
x y : R
⊢ (-y - W.a₁ * x - W.a₃) ^ 2 + W.a₁ * x * (-y - W.a₁ * x - W.a₃) + W.a₃ * (-y - W.a₁ * x - W.a₃) =
      x ^ 3 + W.a₂ * x ^ 2 + W.a₄ * x + W.a₆ ↔
    y ^ 2 + W.a₁ * x * y + W.a₃ * y = x ^ 3 + W.a₂ * x ^ 2 + W.a₄ * x + W.a₆

Next tactic:
congr! 1
lemma equation_neg_iff (x y : R) : W.equation x (W.negY x y) ↔ W.equation x y := by
  rw [equation_iff, equation_iff, negY]
  congr! 1
  

Proof state:
case a.h.e'_2
R : Type u
inst✝ : CommRing R
W : Affine R
x y : R
⊢ (-y - W.a₁ * x - W.a₃) ^ 2 + W.a₁ * x * (-y - W.a₁ * x - W.a₃) + W.a₃ * (-y - W.a₁ * x - W.a₃) =
    y ^ 2 + W.a₁ * x * y + W.a₃ * y

Next tactic:
ring1
lemma nonsingular_neg_iff (x y : R) : W.nonsingular x (W.negY x y) ↔ W.nonsingular x y := by
  

Proof state:
R : Type u
inst✝ : CommRing R
W : Affine R
x y : R
⊢ W.nonsingular x (W.negY x y) ↔ W.nonsingular x y

Next tactic:
rw [nonsingular_iff, equation_neg_iff, ← negY, negY_negY, ← @ne_comm _ y, nonsingular_iff]
lemma nonsingular_neg_iff (x y : R) : W.nonsingular x (W.negY x y) ↔ W.nonsingular x y := by
  rw [nonsingular_iff, equation_neg_iff, ← negY, negY_negY, ← @ne_comm _ y, nonsingular_iff]
  

Proof state:
R : Type u
inst✝ : CommRing R
W : Affine R
x y : R
⊢ W.equation x y ∧ (W.a₁ * W.negY x y ≠ 3 * x ^ 2 + 2 * W.a₂ * x + W.a₄ ∨ y ≠ W.negY x y) ↔
    W.equation x y ∧ (W.a₁ * y ≠ 3 * x ^ 2 + 2 * W.a₂ * x + W.a₄ ∨ y ≠ -y - W.a₁ * x - W.a₃)

Next tactic:
exact and_congr_right' <| (iff_congr not_and_or.symm not_and_or.symm).mpr <|
    not_congr <| and_congr_left fun h => by rw [← h]
lemma nonsingular_neg_iff (x y : R) : W.nonsingular x (W.negY x y) ↔ W.nonsingular x y := by
  rw [nonsingular_iff, equation_neg_iff, ← negY, negY_negY, ← @ne_comm _ y, nonsingular_iff]
  exact and_congr_right' <| (iff_congr not_and_or.symm not_and_or.symm).mpr <|
    not_congr <| and_congr_left fun h => by 

Proof state:
R : Type u
inst✝ : CommRing R
W : Affine R
x y : R
h : y = W.negY x y
⊢ W.a₁ * W.negY x y = 3 * x ^ 2 + 2 * W.a₂ * x + W.a₄ ↔ W.a₁ * y = 3 * x ^ 2 + 2 * W.a₂ * x + W.a₄

Next tactic:
rw [← h]
lemma equation_add_iff (x₁ x₂ y₁ L : R) :
    W.equation (W.addX x₁ x₂ L) (W.addY' x₁ x₂ y₁ L) ↔
      (W.addPolynomial x₁ y₁ L).eval (W.addX x₁ x₂ L) = 0 := by
  

Proof state:
R : Type u
inst✝ : CommRing R
W : Affine R
x₁ x₂ y₁ L : R
⊢ W.equation (W.addX x₁ x₂ L) (W.addY' x₁ x₂ y₁ L) ↔ eval (W.addX x₁ x₂ L) (W.addPolynomial x₁ y₁ L) = 0

Next tactic:
rw [equation, addY', addPolynomial, linePolynomial, polynomial]
lemma equation_add_iff (x₁ x₂ y₁ L : R) :
    W.equation (W.addX x₁ x₂ L) (W.addY' x₁ x₂ y₁ L) ↔
      (W.addPolynomial x₁ y₁ L).eval (W.addX x₁ x₂ L) = 0 := by
  rw [equation, addY', addPolynomial, linePolynomial, polynomial]
  

Proof state:
R : Type u
inst✝ : CommRing R
W : Affine R
x₁ x₂ y₁ L : R
⊢ eval (W.addX x₁ x₂ L)
        (eval (C (L * (W.addX x₁ x₂ L - x₁) + y₁))
          (Y ^ 2 + C (C W.a₁ * Y + C W.a₃) * Y - C (Y ^ 3 + C W.a₂ * Y ^ 2 + C W.a₄ * Y + C W.a₆))) =
      0 ↔
    eval (W.addX x₁ x₂ L)
        (eval (C L * (Y - C x₁) + C y₁)
          (Y ^ 2 + C (C W.a₁ * Y + C W.a₃) * Y - C (Y ^ 3 + C W.a₂ * Y ^ 2 + C W.a₄ * Y + C W.a₆))) =
      0

Next tactic:
eval_simp
lemma nonsingular_add_of_eval_derivative_ne_zero {x₁ x₂ y₁ L : R}
    (hx' : W.equation (W.addX x₁ x₂ L) (W.addY' x₁ x₂ y₁ L))
    (hx : (W.addPolynomial x₁ y₁ L).derivative.eval (W.addX x₁ x₂ L) ≠ 0) :
    W.nonsingular (W.addX x₁ x₂ L) (W.addY' x₁ x₂ y₁ L) := by
  

Proof state:
R : Type u
inst✝ : CommRing R
W : Affine R
x₁ x₂ y₁ L : R
hx' : W.equation (W.addX x₁ x₂ L) (W.addY' x₁ x₂ y₁ L)
hx : eval (W.addX x₁ x₂ L) (derivative (W.addPolynomial x₁ y₁ L)) ≠ 0
⊢ W.nonsingular (W.addX x₁ x₂ L) (W.addY' x₁ x₂ y₁ L)

Next tactic:
rw [nonsingular, and_iff_right hx', addY', polynomialX, polynomialY]
lemma nonsingular_add_of_eval_derivative_ne_zero {x₁ x₂ y₁ L : R}
    (hx' : W.equation (W.addX x₁ x₂ L) (W.addY' x₁ x₂ y₁ L))
    (hx : (W.addPolynomial x₁ y₁ L).derivative.eval (W.addX x₁ x₂ L) ≠ 0) :
    W.nonsingular (W.addX x₁ x₂ L) (W.addY' x₁ x₂ y₁ L) := by
  rw [nonsingular, and_iff_right hx', addY', polynomialX, polynomialY]
  

Proof state:
R : Type u
inst✝ : CommRing R
W : Affine R
x₁ x₂ y₁ L : R
hx' : W.equation (W.addX x₁ x₂ L) (W.addY' x₁ x₂ y₁ L)
hx : eval (W.addX x₁ x₂ L) (derivative (W.addPolynomial x₁ y₁ L)) ≠ 0
⊢ eval (W.addX x₁ x₂ L)
        (eval (C (L * (W.addX x₁ x₂ L - x₁) + y₁)) (C (C W.a₁) * Y - C (C 3 * Y ^ 2 + C (2 * W.a₂) * Y + C W.a₄))) ≠
      0 ∨
    eval (W.addX x₁ x₂ L) (eval (C (L * (W.addX x₁ x₂ L - x₁) + y₁)) (C (C 2) * Y + C (C W.a₁ * Y + C W.a₃))) ≠ 0

Next tactic:
eval_simp
lemma nonsingular_add_of_eval_derivative_ne_zero {x₁ x₂ y₁ L : R}
    (hx' : W.equation (W.addX x₁ x₂ L) (W.addY' x₁ x₂ y₁ L))
    (hx : (W.addPolynomial x₁ y₁ L).derivative.eval (W.addX x₁ x₂ L) ≠ 0) :
    W.nonsingular (W.addX x₁ x₂ L) (W.addY' x₁ x₂ y₁ L) := by
  rw [nonsingular, and_iff_right hx', addY', polynomialX, polynomialY]
  eval_simp
  

Proof state:
R : Type u
inst✝ : CommRing R
W : Affine R
x₁ x₂ y₁ L : R
hx' : W.equation (W.addX x₁ x₂ L) (W.addY' x₁ x₂ y₁ L)
hx : eval (W.addX x₁ x₂ L) (derivative (W.addPolynomial x₁ y₁ L)) ≠ 0
⊢ W.a₁ * (L * (W.addX x₁ x₂ L - x₁) + y₁) - (3 * W.addX x₁ x₂ L ^ 2 + 2 * W.a₂ * W.addX x₁ x₂ L + W.a₄) ≠ 0 ∨
    2 * (L * (W.addX x₁ x₂ L - x₁) + y₁) + (W.a₁ * W.addX x₁ x₂ L + W.a₃) ≠ 0

Next tactic:
contrapose! hx
lemma nonsingular_add_of_eval_derivative_ne_zero {x₁ x₂ y₁ L : R}
    (hx' : W.equation (W.addX x₁ x₂ L) (W.addY' x₁ x₂ y₁ L))
    (hx : (W.addPolynomial x₁ y₁ L).derivative.eval (W.addX x₁ x₂ L) ≠ 0) :
    W.nonsingular (W.addX x₁ x₂ L) (W.addY' x₁ x₂ y₁ L) := by
  rw [nonsingular, and_iff_right hx', addY', polynomialX, polynomialY]
  eval_simp
  contrapose! hx
  

Proof state:
R : Type u
inst✝ : CommRing R
W : Affine R
x₁ x₂ y₁ L : R
hx' : W.equation (W.addX x₁ x₂ L) (W.addY' x₁ x₂ y₁ L)
hx :
  W.a₁ * (L * (W.addX x₁ x₂ L - x₁) + y₁) - (3 * W.addX x₁ x₂ L ^ 2 + 2 * W.a₂ * W.addX x₁ x₂ L + W.a₄) = 0 ∧
    2 * (L * (W.addX x₁ x₂ L - x₁) + y₁) + (W.a₁ * W.addX x₁ x₂ L + W.a₃) = 0
⊢ eval (W.addX x₁ x₂ L) (derivative (W.addPolynomial x₁ y₁ L)) = 0

Next tactic:
rw [addPolynomial, linePolynomial, polynomial]
lemma nonsingular_add_of_eval_derivative_ne_zero {x₁ x₂ y₁ L : R}
    (hx' : W.equation (W.addX x₁ x₂ L) (W.addY' x₁ x₂ y₁ L))
    (hx : (W.addPolynomial x₁ y₁ L).derivative.eval (W.addX x₁ x₂ L) ≠ 0) :
    W.nonsingular (W.addX x₁ x₂ L) (W.addY' x₁ x₂ y₁ L) := by
  rw [nonsingular, and_iff_right hx', addY', polynomialX, polynomialY]
  eval_simp
  contrapose! hx
  rw [addPolynomial, linePolynomial, polynomial]
  

Proof state:
R : Type u
inst✝ : CommRing R
W : Affine R
x₁ x₂ y₁ L : R
hx' : W.equation (W.addX x₁ x₂ L) (W.addY' x₁ x₂ y₁ L)
hx :
  W.a₁ * (L * (W.addX x₁ x₂ L - x₁) + y₁) - (3 * W.addX x₁ x₂ L ^ 2 + 2 * W.a₂ * W.addX x₁ x₂ L + W.a₄) = 0 ∧
    2 * (L * (W.addX x₁ x₂ L - x₁) + y₁) + (W.a₁ * W.addX x₁ x₂ L + W.a₃) = 0
⊢ eval (W.addX x₁ x₂ L)
      (derivative
        (eval (C L * (Y - C x₁) + C y₁)
          (Y ^ 2 + C (C W.a₁ * Y + C W.a₃) * Y - C (Y ^ 3 + C W.a₂ * Y ^ 2 + C W.a₄ * Y + C W.a₆)))) =
    0

Next tactic:
eval_simp
lemma nonsingular_add_of_eval_derivative_ne_zero {x₁ x₂ y₁ L : R}
    (hx' : W.equation (W.addX x₁ x₂ L) (W.addY' x₁ x₂ y₁ L))
    (hx : (W.addPolynomial x₁ y₁ L).derivative.eval (W.addX x₁ x₂ L) ≠ 0) :
    W.nonsingular (W.addX x₁ x₂ L) (W.addY' x₁ x₂ y₁ L) := by
  rw [nonsingular, and_iff_right hx', addY', polynomialX, polynomialY]
  eval_simp
  contrapose! hx
  rw [addPolynomial, linePolynomial, polynomial]
  eval_simp
  

Proof state:
R : Type u
inst✝ : CommRing R
W : Affine R
x₁ x₂ y₁ L : R
hx' : W.equation (W.addX x₁ x₂ L) (W.addY' x₁ x₂ y₁ L)
hx :
  W.a₁ * (L * (W.addX x₁ x₂ L - x₁) + y₁) - (3 * W.addX x₁ x₂ L ^ 2 + 2 * W.a₂ * W.addX x₁ x₂ L + W.a₄) = 0 ∧
    2 * (L * (W.addX x₁ x₂ L - x₁) + y₁) + (W.a₁ * W.addX x₁ x₂ L + W.a₃) = 0
⊢ eval (W.addX x₁ x₂ L)
      (derivative
        ((C L * (Y - C x₁) + C y₁) ^ 2 + (C W.a₁ * Y + C W.a₃) * (C L * (Y - C x₁) + C y₁) -
          (Y ^ 3 + C W.a₂ * Y ^ 2 + C W.a₄ * Y + C W.a₆))) =
    0

Next tactic:
derivative_simp