File: Mathlib/NumberTheory/PythagoreanTriples.lean

full_name: sq_ne_two_fin_zmod_four
code: theorem sq_ne_two_fin_zmod_four (z : ZMod 4) : z * z ≠ 2 
goal: z * z ≠ 2

full_name: Int.sq_ne_two_mod_four
code: theorem Int.sq_ne_two_mod_four (z : ℤ) : z * z % 4 ≠ 2 
goal: z * z % 4 ≠ 2

full_name: PythagoreanTriple
code: /-- Three integers `x`, `y`, and `z` form a Pythagorean triple if `x * x + y * y = z * z`. -/
def PythagoreanTriple (x y z : ℤ) : Prop 
goal: Prop

full_name: pythagoreanTriple_comm
code: /-- Pythagorean triples are interchangeable, i.e `x * x + y * y = y * y + x * x = z * z`.
This comes from additive commutativity. -/
theorem pythagoreanTriple_comm {x y z : ℤ} : PythagoreanTriple x y z ↔ PythagoreanTriple y x z 
goal: PythagoreanTriple x y z ↔ PythagoreanTriple y x z

full_name: PythagoreanTriple.zero
code: /-- The zeroth Pythagorean triple is all zeros. -/
theorem PythagoreanTriple.zero : PythagoreanTriple 0 0 0 
goal: PythagoreanTriple 0 0 0

full_name: PythagoreanTriple.eq
code: theorem eq : x * x + y * y = z * z 
goal: x * x + y * y = z * z

full_name: PythagoreanTriple.symm
code: @[symm]
theorem symm : PythagoreanTriple y x z 
goal: PythagoreanTriple y x z

full_name: PythagoreanTriple.mul
code: /-- A triple is still a triple if you multiply `x`, `y` and `z`
by a constant `k`. -/
theorem mul (k : ℤ) : PythagoreanTriple (k * x) (k * y) (k * z) 
goal: PythagoreanTriple (k * x) (k * y) (k * z)

full_name: PythagoreanTriple.mul_iff
code: /-- `(k*x, k*y, k*z)` is a Pythagorean triple if and only if
`(x, y, z)` is also a triple. -/
theorem mul_iff (k : ℤ) (hk : k ≠ 0) :
    PythagoreanTriple (k * x) (k * y) (k * z) ↔ PythagoreanTriple x y z 
goal: PythagoreanTriple (k * x) (k * y) (k * z) ↔ PythagoreanTriple x y z

full_name: PythagoreanTriple.IsClassified
code: /-- A Pythagorean triple `x, y, z` is “classified” if there exist integers `k, m, n` such that
either
 * `x = k * (m ^ 2 - n ^ 2)` and `y = k * (2 * m * n)`, or
 * `x = k * (2 * m * n)` and `y = k * (m ^ 2 - n ^ 2)`. -/
@[nolint unusedArguments]
def IsClassified (_ : PythagoreanTriple x y z) 
goal: PythagoreanTriple x y z → Prop

full_name: PythagoreanTriple.IsPrimitiveClassified
code: /-- A primitive Pythagorean triple `x, y, z` is a Pythagorean triple with `x` and `y` coprime.
 Such a triple is “primitively classified” if there exist coprime integers `m, n` such that either
 * `x = m ^ 2 - n ^ 2` and `y = 2 * m * n`, or
 * `x = 2 * m * n` and `y = m ^ 2 - n ^ 2`.
-/
@[nolint unusedArguments]
def IsPrimitiveClassified (_ : PythagoreanTriple x y z) 
goal: PythagoreanTriple x y z → Prop

full_name: PythagoreanTriple.mul_isClassified
code: theorem mul_isClassified (k : ℤ) (hc : h.IsClassified) : (h.mul k).IsClassified 
goal: ⋯.IsClassified

full_name: PythagoreanTriple.even_odd_of_coprime
code: theorem even_odd_of_coprime (hc : Int.gcd x y = 1) :
    x % 2 = 0 ∧ y % 2 = 1 ∨ x % 2 = 1 ∧ y % 2 = 0 
goal: x % 2 = 0 ∧ y % 2 = 1 ∨ x % 2 = 1 ∧ y % 2 = 0

full_name: PythagoreanTriple.gcd_dvd
code: theorem gcd_dvd : (Int.gcd x y : ℤ) ∣ z 
goal: ↑(x.gcd y) ∣ z

full_name: PythagoreanTriple.normalize
code: theorem normalize : PythagoreanTriple (x / Int.gcd x y) (y / Int.gcd x y) (z / Int.gcd x y) 
goal: PythagoreanTriple (x / ↑(x.gcd y)) (y / ↑(x.gcd y)) (z / ↑(x.gcd y))

full_name: PythagoreanTriple.isClassified_of_isPrimitiveClassified
code: theorem isClassified_of_isPrimitiveClassified (hp : h.IsPrimitiveClassified) : h.IsClassified 
goal: h.IsClassified

full_name: PythagoreanTriple.isClassified_of_normalize_isPrimitiveClassified
code: theorem isClassified_of_normalize_isPrimitiveClassified (hc : h.normalize.IsPrimitiveClassified) :
    h.IsClassified 
goal: h.IsClassified

full_name: PythagoreanTriple.ne_zero_of_coprime
code: theorem ne_zero_of_coprime (hc : Int.gcd x y = 1) : z ≠ 0 
goal: z ≠ 0

full_name: PythagoreanTriple.isPrimitiveClassified_of_coprime_of_zero_left
code: theorem isPrimitiveClassified_of_coprime_of_zero_left (hc : Int.gcd x y = 1) (hx : x = 0) :
    h.IsPrimitiveClassified 
goal: h.IsPrimitiveClassified

full_name: PythagoreanTriple.coprime_of_coprime
code: theorem coprime_of_coprime (hc : Int.gcd x y = 1) : Int.gcd y z = 1 
goal: y.gcd z = 1

full_name: circleEquivGen
code: /-- A parameterization of the unit circle that is useful for classifying Pythagorean triples.
 (To be applied in the case where `K = ℚ`.) -/
def circleEquivGen (hk : ∀ x : K, 1 + x ^ 2 ≠ 0) :
    K ≃ { p : K × K // p.1 ^ 2 + p.2 ^ 2 = 1 ∧ p.2 ≠ -1 } 
goal: K ≃ { p // p.1 ^ 2 + p.2 ^ 2 = 1 ∧ p.2 ≠ -1 }

full_name: circleEquivGen_apply
code: @[simp]
theorem circleEquivGen_apply (hk : ∀ x : K, 1 + x ^ 2 ≠ 0) (x : K) :
    (circleEquivGen hk x : K × K) = ⟨2 * x / (1 + x ^ 2), (1 - x ^ 2) / (1 + x ^ 2)⟩ 
goal: ↑((circleEquivGen hk) x) = (2 * x / (1 + x ^ 2), (1 - x ^ 2) / (1 + x ^ 2))

full_name: circleEquivGen_symm_apply
code: @[simp]
theorem circleEquivGen_symm_apply (hk : ∀ x : K, 1 + x ^ 2 ≠ 0)
    (v : { p : K × K // p.1 ^ 2 + p.2 ^ 2 = 1 ∧ p.2 ≠ -1 }) :
    (circleEquivGen hk).symm v = (v : K × K).1 / ((v : K × K).2 + 1) 
goal: (circleEquivGen hk).symm v = (↑v).1 / ((↑v).2 + 1)

full_name: _private.Mathlib.NumberTheory.PythagoreanTriples.0.coprime_sq_sub_sq_add_of_even_odd
code: private theorem coprime_sq_sub_sq_add_of_even_odd {m n : ℤ} (h : Int.gcd m n = 1) (hm : m % 2 = 0)
    (hn : n % 2 = 1) : Int.gcd (m ^ 2 - n ^ 2) (m ^ 2 + n ^ 2) = 1 
goal: (m ^ 2 - n ^ 2).gcd (m ^ 2 + n ^ 2) = 1

full_name: _private.Mathlib.NumberTheory.PythagoreanTriples.0.coprime_sq_sub_sq_add_of_odd_even
code: private theorem coprime_sq_sub_sq_add_of_odd_even {m n : ℤ} (h : Int.gcd m n = 1) (hm : m % 2 = 1)
    (hn : n % 2 = 0) : Int.gcd (m ^ 2 - n ^ 2) (m ^ 2 + n ^ 2) = 1 
goal: (m ^ 2 - n ^ 2).gcd (m ^ 2 + n ^ 2) = 1

full_name: _private.Mathlib.NumberTheory.PythagoreanTriples.0.coprime_sq_sub_mul_of_even_odd
code: private theorem coprime_sq_sub_mul_of_even_odd {m n : ℤ} (h : Int.gcd m n = 1) (hm : m % 2 = 0)
    (hn : n % 2 = 1) : Int.gcd (m ^ 2 - n ^ 2) (2 * m * n) = 1 
goal: (m ^ 2 - n ^ 2).gcd (2 * m * n) = 1

full_name: _private.Mathlib.NumberTheory.PythagoreanTriples.0.coprime_sq_sub_mul_of_odd_even
code: private theorem coprime_sq_sub_mul_of_odd_even {m n : ℤ} (h : Int.gcd m n = 1) (hm : m % 2 = 1)
    (hn : n % 2 = 0) : Int.gcd (m ^ 2 - n ^ 2) (2 * m * n) = 1 
goal: (m ^ 2 - n ^ 2).gcd (2 * m * n) = 1

full_name: _private.Mathlib.NumberTheory.PythagoreanTriples.0.coprime_sq_sub_mul
code: private theorem coprime_sq_sub_mul {m n : ℤ} (h : Int.gcd m n = 1)
    (hmn : m % 2 = 0 ∧ n % 2 = 1 ∨ m % 2 = 1 ∧ n % 2 = 0) :
    Int.gcd (m ^ 2 - n ^ 2) (2 * m * n) = 1 
goal: (m ^ 2 - n ^ 2).gcd (2 * m * n) = 1

full_name: _private.Mathlib.NumberTheory.PythagoreanTriples.0.coprime_sq_sub_sq_sum_of_odd_odd
code: private theorem coprime_sq_sub_sq_sum_of_odd_odd {m n : ℤ} (h : Int.gcd m n = 1) (hm : m % 2 = 1)
    (hn : n % 2 = 1) :
    2 ∣ m ^ 2 + n ^ 2 ∧
      2 ∣ m ^ 2 - n ^ 2 ∧
        (m ^ 2 - n ^ 2) / 2 % 2 = 0 ∧ Int.gcd ((m ^ 2 - n ^ 2) / 2) ((m ^ 2 + n ^ 2) / 2) = 1 
goal: 2 ∣ m ^ 2 + n ^ 2 ∧
  2 ∣ m ^ 2 - n ^ 2 ∧ (m ^ 2 - n ^ 2) / 2 % 2 = 0 ∧ ((m ^ 2 - n ^ 2) / 2).gcd ((m ^ 2 + n ^ 2) / 2) = 1

full_name: PythagoreanTriple.isPrimitiveClassified_aux
code: theorem isPrimitiveClassified_aux (hc : x.gcd y = 1) (hzpos : 0 < z) {m n : ℤ}
    (hm2n2 : 0 < m ^ 2 + n ^ 2) (hv2 : (x : ℚ) / z = 2 * m * n / ((m : ℚ) ^ 2 + (n : ℚ) ^ 2))
    (hw2 : (y : ℚ) / z = ((m : ℚ) ^ 2 - (n : ℚ) ^ 2) / ((m : ℚ) ^ 2 + (n : ℚ) ^ 2))
    (H : Int.gcd (m ^ 2 - n ^ 2) (m ^ 2 + n ^ 2) = 1) (co : Int.gcd m n = 1)
    (pp : m % 2 = 0 ∧ n % 2 = 1 ∨ m % 2 = 1 ∧ n % 2 = 0) : h.IsPrimitiveClassified 
goal: h.IsPrimitiveClassified

full_name: PythagoreanTriple.isPrimitiveClassified_of_coprime_of_odd_of_pos
code: theorem isPrimitiveClassified_of_coprime_of_odd_of_pos (hc : Int.gcd x y = 1) (hyo : y % 2 = 1)
    (hzpos : 0 < z) : h.IsPrimitiveClassified 
goal: h.IsPrimitiveClassified

full_name: PythagoreanTriple.isPrimitiveClassified_of_coprime_of_pos
code: theorem isPrimitiveClassified_of_coprime_of_pos (hc : Int.gcd x y = 1) (hzpos : 0 < z) :
    h.IsPrimitiveClassified 
goal: h.IsPrimitiveClassified

full_name: PythagoreanTriple.isPrimitiveClassified_of_coprime
code: theorem isPrimitiveClassified_of_coprime (hc : Int.gcd x y = 1) : h.IsPrimitiveClassified 
goal: h.IsPrimitiveClassified

full_name: PythagoreanTriple.classified
code: theorem classified : h.IsClassified 
goal: h.IsClassified

full_name: PythagoreanTriple.coprime_classification
code: theorem coprime_classification :
    PythagoreanTriple x y z ∧ Int.gcd x y = 1 ↔
      ∃ m n,
        (x = m ^ 2 - n ^ 2 ∧ y = 2 * m * n ∨ x = 2 * m * n ∧ y = m ^ 2 - n ^ 2) ∧
          (z = m ^ 2 + n ^ 2 ∨ z = -(m ^ 2 + n ^ 2)) ∧
            Int.gcd m n = 1 ∧ (m % 2 = 0 ∧ n % 2 = 1 ∨ m % 2 = 1 ∧ n % 2 = 0) 
goal: PythagoreanTriple x y z ∧ x.gcd y = 1 ↔
  ∃ m n,
    (x = m ^ 2 - n ^ 2 ∧ y = 2 * m * n ∨ x = 2 * m * n ∧ y = m ^ 2 - n ^ 2) ∧
      (z = m ^ 2 + n ^ 2 ∨ z = -(m ^ 2 + n ^ 2)) ∧ m.gcd n = 1 ∧ (m % 2 = 0 ∧ n % 2 = 1 ∨ m % 2 = 1 ∧ n % 2 = 0)

full_name: PythagoreanTriple.coprime_classification'
code: /-- by assuming `x` is odd and `z` is positive we get a slightly more precise classification of
the Pythagorean triple `x ^ 2 + y ^ 2 = z ^ 2`-/
theorem coprime_classification' {x y z : ℤ} (h : PythagoreanTriple x y z)
    (h_coprime : Int.gcd x y = 1) (h_parity : x % 2 = 1) (h_pos : 0 < z) :
    ∃ m n,
      x = m ^ 2 - n ^ 2 ∧
        y = 2 * m * n ∧
          z = m ^ 2 + n ^ 2 ∧
            Int.gcd m n = 1 ∧ (m % 2 = 0 ∧ n % 2 = 1 ∨ m % 2 = 1 ∧ n % 2 = 0) ∧ 0 ≤ m 
goal: ∃ m n,
  x = m ^ 2 - n ^ 2 ∧
    y = 2 * m * n ∧ z = m ^ 2 + n ^ 2 ∧ m.gcd n = 1 ∧ (m % 2 = 0 ∧ n % 2 = 1 ∨ m % 2 = 1 ∧ n % 2 = 0) ∧ 0 ≤ m

full_name: PythagoreanTriple.classification
code: /-- **Formula for Pythagorean Triples** -/
theorem classification :
    PythagoreanTriple x y z ↔
      ∃ k m n,
        (x = k * (m ^ 2 - n ^ 2) ∧ y = k * (2 * m * n) ∨
            x = k * (2 * m * n) ∧ y = k * (m ^ 2 - n ^ 2)) ∧
          (z = k * (m ^ 2 + n ^ 2) ∨ z = -k * (m ^ 2 + n ^ 2)) 
goal: PythagoreanTriple x y z ↔
  ∃ k m n,
    (x = k * (m ^ 2 - n ^ 2) ∧ y = k * (2 * m * n) ∨ x = k * (2 * m * n) ∧ y = k * (m ^ 2 - n ^ 2)) ∧
      (z = k * (m ^ 2 + n ^ 2) ∨ z = -k * (m ^ 2 + n ^ 2))