number_theory.legendre_symbol.quadratic_reciprocityMathlib.NumberTheory.LegendreSymbol.QuadraticReciprocity

This file has been ported!

Changes since the initial port

The following section lists changes to this file in mathlib3 and mathlib4 that occured after the initial port. Most recent changes are shown first. Hovering over a commit will show all commits associated with the same mathlib3 commit.

Changes in mathlib3

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(last sync)

Changes in mathlib3port

mathlib3
mathlib3port
Diff
@@ -88,7 +88,7 @@ theorem exists_sq_eq_two_iff : IsSquare (2 : ZMod p) ↔ p % 8 = 1 ∨ p % 8 = 7
   by
   rw [FiniteField.isSquare_two_iff, card p]
   have h₁ := prime.mod_two_eq_one_iff_ne_two.mpr hp
-  rw [← mod_mod_of_dvd p (by norm_num : 2 ∣ 8)] at h₁ 
+  rw [← mod_mod_of_dvd p (by norm_num : 2 ∣ 8)] at h₁
   have h₂ := mod_lt p (by norm_num : 0 < 8)
   revert h₂ h₁
   generalize hm : p % 8 = m; clear! p
@@ -102,7 +102,7 @@ theorem exists_sq_eq_neg_two_iff : IsSquare (-2 : ZMod p) ↔ p % 8 = 1 ∨ p %
   by
   rw [FiniteField.isSquare_neg_two_iff, card p]
   have h₁ := prime.mod_two_eq_one_iff_ne_two.mpr hp
-  rw [← mod_mod_of_dvd p (by norm_num : 2 ∣ 8)] at h₁ 
+  rw [← mod_mod_of_dvd p (by norm_num : 2 ∣ 8)] at h₁
   have h₂ := mod_lt p (by norm_num : 0 < 8)
   revert h₂ h₁
   generalize hm : p % 8 = m; clear! p
@@ -141,7 +141,7 @@ theorem quadratic_reciprocity (hp : p ≠ 2) (hq : q ≠ 2) (hpq : p ≠ q) :
   have hq₂ := (ring_char_zmod_n q).substr hq
   have h :=
     quadraticChar_odd_prime ((ring_char_zmod_n p).substr hp) hq ((ring_char_zmod_n p).substr hpq)
-  rw [card p] at h 
+  rw [card p] at h
   have nc : ∀ n r : ℕ, ((n : ℤ) : ZMod r) = n := fun n r => by norm_cast
   have nc' : (((-1) ^ (p / 2) : ℤ) : ZMod q) = (-1) ^ (p / 2) := by norm_cast
   rw [legendreSym, legendreSym, nc, nc, h, map_mul, mul_rotate', mul_comm (p / 2), ← pow_two,
Diff
@@ -3,8 +3,8 @@ Copyright (c) 2018 Chris Hughes. All rights reserved.
 Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Chris Hughes, Michael Stoll
 -/
-import Mathbin.NumberTheory.LegendreSymbol.Basic
-import Mathbin.NumberTheory.LegendreSymbol.QuadraticChar.GaussSum
+import NumberTheory.LegendreSymbol.Basic
+import NumberTheory.LegendreSymbol.QuadraticChar.GaussSum
 
 #align_import number_theory.legendre_symbol.quadratic_reciprocity from "leanprover-community/mathlib"@"08b63ab58a6ec1157ebeafcbbe6c7a3fb3c9f6d5"
 
Diff
@@ -2,15 +2,12 @@
 Copyright (c) 2018 Chris Hughes. All rights reserved.
 Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Chris Hughes, Michael Stoll
-
-! This file was ported from Lean 3 source module number_theory.legendre_symbol.quadratic_reciprocity
-! leanprover-community/mathlib commit 08b63ab58a6ec1157ebeafcbbe6c7a3fb3c9f6d5
-! Please do not edit these lines, except to modify the commit id
-! if you have ported upstream changes.
 -/
 import Mathbin.NumberTheory.LegendreSymbol.Basic
 import Mathbin.NumberTheory.LegendreSymbol.QuadraticChar.GaussSum
 
+#align_import number_theory.legendre_symbol.quadratic_reciprocity from "leanprover-community/mathlib"@"08b63ab58a6ec1157ebeafcbbe6c7a3fb3c9f6d5"
+
 /-!
 # Quadratic reciprocity.
 
Diff
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Chris Hughes, Michael Stoll
 
 ! This file was ported from Lean 3 source module number_theory.legendre_symbol.quadratic_reciprocity
-! leanprover-community/mathlib commit 5b2fe80501ff327b9109fb09b7cc8c325cd0d7d9
+! leanprover-community/mathlib commit 08b63ab58a6ec1157ebeafcbbe6c7a3fb3c9f6d5
 ! Please do not edit these lines, except to modify the commit id
 ! if you have ported upstream changes.
 -/
@@ -14,6 +14,9 @@ import Mathbin.NumberTheory.LegendreSymbol.QuadraticChar.GaussSum
 /-!
 # Quadratic reciprocity.
 
+> THIS FILE IS SYNCHRONIZED WITH MATHLIB4.
+> Any changes to this file require a corresponding PR to mathlib4.
+
 ## Main results
 
 We prove the law of quadratic reciprocity, see `legendre_sym.quadratic_reciprocity` and
Diff
@@ -60,17 +60,21 @@ namespace legendreSym
 
 variable (hp : p ≠ 2)
 
+#print legendreSym.at_two /-
 /-- `legendre_sym p 2` is given by `χ₈ p`. -/
 theorem at_two : legendreSym p 2 = χ₈ p := by
   simp only [legendreSym, card p, quadraticChar_two ((ring_char_zmod_n p).substr hp), Int.cast_bit0,
     Int.cast_one]
 #align legendre_sym.at_two legendreSym.at_two
+-/
 
+#print legendreSym.at_neg_two /-
 /-- `legendre_sym p (-2)` is given by `χ₈' p`. -/
 theorem at_neg_two : legendreSym p (-2) = χ₈' p := by
   simp only [legendreSym, card p, quadraticChar_neg_two ((ring_char_zmod_n p).substr hp),
     Int.cast_bit0, Int.cast_one, Int.cast_neg]
 #align legendre_sym.at_neg_two legendreSym.at_neg_two
+-/
 
 end legendreSym
 
@@ -78,6 +82,7 @@ namespace ZMod
 
 variable (hp : p ≠ 2)
 
+#print ZMod.exists_sq_eq_two_iff /-
 /-- `2` is a square modulo an odd prime `p` iff `p` is congruent to `1` or `7` mod `8`. -/
 theorem exists_sq_eq_two_iff : IsSquare (2 : ZMod p) ↔ p % 8 = 1 ∨ p % 8 = 7 :=
   by
@@ -89,7 +94,9 @@ theorem exists_sq_eq_two_iff : IsSquare (2 : ZMod p) ↔ p % 8 = 1 ∨ p % 8 = 7
   generalize hm : p % 8 = m; clear! p
   decide!
 #align zmod.exists_sq_eq_two_iff ZMod.exists_sq_eq_two_iff
+-/
 
+#print ZMod.exists_sq_eq_neg_two_iff /-
 /-- `-2` is a square modulo an odd prime `p` iff `p` is congruent to `1` or `3` mod `8`. -/
 theorem exists_sq_eq_neg_two_iff : IsSquare (-2 : ZMod p) ↔ p % 8 = 1 ∨ p % 8 = 3 :=
   by
@@ -101,6 +108,7 @@ theorem exists_sq_eq_neg_two_iff : IsSquare (-2 : ZMod p) ↔ p % 8 = 1 ∨ p %
   generalize hm : p % 8 = m; clear! p
   decide!
 #align zmod.exists_sq_eq_neg_two_iff ZMod.exists_sq_eq_neg_two_iff
+-/
 
 end ZMod
 
@@ -122,6 +130,7 @@ namespace legendreSym
 
 open ZMod
 
+#print legendreSym.quadratic_reciprocity /-
 /-- The Law of Quadratic Reciprocity: if `p` and `q` are distinct odd primes, then
 `(q / p) * (p / q) = (-1)^((p-1)(q-1)/4)`. -/
 theorem quadratic_reciprocity (hp : p ≠ 2) (hq : q ≠ 2) (hpq : p ≠ q) :
@@ -139,7 +148,9 @@ theorem quadratic_reciprocity (hp : p ≠ 2) (hq : q ≠ 2) (hpq : p ≠ q) :
     quadraticChar_sq_one (prime_ne_zero q p hpq.symm), mul_one, pow_mul, χ₄_eq_neg_one_pow hp₁, nc',
     map_pow, quadraticChar_neg_one hq₂, card q, χ₄_eq_neg_one_pow hq₁]
 #align legendre_sym.quadratic_reciprocity legendreSym.quadratic_reciprocity
+-/
 
+#print legendreSym.quadratic_reciprocity' /-
 /-- The Law of Quadratic Reciprocity: if `p` and `q` are odd primes, then
 `(q / p) = (-1)^((p-1)(q-1)/4) * (p / q)`. -/
 theorem quadratic_reciprocity' (hp : p ≠ 2) (hq : q ≠ 2) :
@@ -152,7 +163,9 @@ theorem quadratic_reciprocity' (hp : p ≠ 2) (hq : q ≠ 2) :
     have : ((q : ℤ) : ZMod p) ≠ 0 := by exact_mod_cast prime_ne_zero p q h
     simpa only [mul_assoc, ← pow_two, sq_one p this, mul_one] using qr
 #align legendre_sym.quadratic_reciprocity' legendreSym.quadratic_reciprocity'
+-/
 
+#print legendreSym.quadratic_reciprocity_one_mod_four /-
 /-- The Law of Quadratic Reciprocity: if `p` and `q` are odd primes and `p % 4 = 1`,
 then `(q / p) = (p / q)`. -/
 theorem quadratic_reciprocity_one_mod_four (hp : p % 4 = 1) (hq : q ≠ 2) :
@@ -160,7 +173,9 @@ theorem quadratic_reciprocity_one_mod_four (hp : p % 4 = 1) (hq : q ≠ 2) :
   rw [quadratic_reciprocity' (prime.mod_two_eq_one_iff_ne_two.mp (odd_of_mod_four_eq_one hp)) hq,
     pow_mul, neg_one_pow_div_two_of_one_mod_four hp, one_pow, one_mul]
 #align legendre_sym.quadratic_reciprocity_one_mod_four legendreSym.quadratic_reciprocity_one_mod_four
+-/
 
+#print legendreSym.quadratic_reciprocity_three_mod_four /-
 /-- The Law of Quadratic Reciprocity: if `p` and `q` are primes that are both congruent
 to `3` mod `4`, then `(q / p) = -(p / q)`. -/
 theorem quadratic_reciprocity_three_mod_four (hp : p % 4 = 3) (hq : q % 4 = 3) :
@@ -170,6 +185,7 @@ theorem quadratic_reciprocity_three_mod_four (hp : p % 4 = 3) (hq : q % 4 = 3) :
   rw [quadratic_reciprocity', pow_mul, nop hp, nop hq, neg_one_mul] <;>
     rwa [← prime.mod_two_eq_one_iff_ne_two, odd_of_mod_four_eq_three]
 #align legendre_sym.quadratic_reciprocity_three_mod_four legendreSym.quadratic_reciprocity_three_mod_four
+-/
 
 end legendreSym
 
@@ -177,6 +193,7 @@ namespace ZMod
 
 open legendreSym
 
+#print ZMod.exists_sq_eq_prime_iff_of_mod_four_eq_one /-
 /-- If `p` and `q` are odd primes and `p % 4 = 1`, then `q` is a square mod `p` iff
 `p` is a square mod `q`. -/
 theorem exists_sq_eq_prime_iff_of_mod_four_eq_one (hp1 : p % 4 = 1) (hq1 : q ≠ 2) :
@@ -188,7 +205,9 @@ theorem exists_sq_eq_prime_iff_of_mod_four_eq_one (hp1 : p % 4 = 1) (hq1 : q ≠
     rw [← eq_one_iff' p (prime_ne_zero p q h), ← eq_one_iff' q (prime_ne_zero q p h.symm),
       quadratic_reciprocity_one_mod_four hp1 hq1]
 #align zmod.exists_sq_eq_prime_iff_of_mod_four_eq_one ZMod.exists_sq_eq_prime_iff_of_mod_four_eq_one
+-/
 
+#print ZMod.exists_sq_eq_prime_iff_of_mod_four_eq_three /-
 /-- If `p` and `q` are distinct primes that are both congruent to `3` mod `4`, then `q` is
 a square mod `p` iff `p` is a nonsquare mod `q`. -/
 theorem exists_sq_eq_prime_iff_of_mod_four_eq_three (hp3 : p % 4 = 3) (hq3 : q % 4 = 3)
@@ -196,6 +215,7 @@ theorem exists_sq_eq_prime_iff_of_mod_four_eq_three (hp3 : p % 4 = 3) (hq3 : q %
   rw [← eq_one_iff' p (prime_ne_zero p q hpq), ← eq_neg_one_iff' q,
     quadratic_reciprocity_three_mod_four hp3 hq3, neg_inj]
 #align zmod.exists_sq_eq_prime_iff_of_mod_four_eq_three ZMod.exists_sq_eq_prime_iff_of_mod_four_eq_three
+-/
 
 end ZMod
 
Diff
@@ -4,23 +4,15 @@ Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Chris Hughes, Michael Stoll
 
 ! This file was ported from Lean 3 source module number_theory.legendre_symbol.quadratic_reciprocity
-! leanprover-community/mathlib commit 74a27133cf29446a0983779e37c8f829a85368f3
+! leanprover-community/mathlib commit 5b2fe80501ff327b9109fb09b7cc8c325cd0d7d9
 ! Please do not edit these lines, except to modify the commit id
 ! if you have ported upstream changes.
 -/
-import Mathbin.NumberTheory.LegendreSymbol.QuadraticChar
+import Mathbin.NumberTheory.LegendreSymbol.Basic
+import Mathbin.NumberTheory.LegendreSymbol.QuadraticChar.GaussSum
 
 /-!
-# Legendre symbol and quadratic reciprocity.
-
-This file contains results about quadratic residues modulo a prime number.
-
-We define the Legendre symbol $\Bigl(\frac{a}{p}\Bigr)$ as `legendre_sym p a`.
-Note the order of arguments! The advantage of this form is that then `legendre_sym p`
-is a multiplicative map.
-
-The Legendre symbol is used to define the Jacobi symbol, `jacobi_sym a b`, for integers `a`
-and (odd) natural numbers `b`, which extends the Legendre symbol.
+# Quadratic reciprocity.
 
 ## Main results
 
@@ -39,7 +31,7 @@ We also prove the supplementary laws that give conditions for when `-1` or `2`
 ## Implementation notes
 
 The proofs use results for quadratic characters on arbitrary finite fields
-from `number_theory.legendre_symbol.quadratic_char`, which in turn are based on
+from `number_theory.legendre_symbol.quadratic_char.gauss_sum`, which in turn are based on
 properties of quadratic Gauss sums as provided by `number_theory.legendre_symbol.gauss_sum`.
 
 ## Tags
@@ -50,289 +42,12 @@ quadratic residue, quadratic nonresidue, Legendre symbol, quadratic reciprocity
 
 open Nat
 
-section Euler
-
-namespace ZMod
-
-variable (p : ℕ) [Fact p.Prime]
-
-/-- Euler's Criterion: A unit `x` of `zmod p` is a square if and only if `x ^ (p / 2) = 1`. -/
-theorem euler_criterion_units (x : (ZMod p)ˣ) : (∃ y : (ZMod p)ˣ, y ^ 2 = x) ↔ x ^ (p / 2) = 1 :=
-  by
-  by_cases hc : p = 2
-  · subst hc
-    simp only [eq_iff_true_of_subsingleton, exists_const]
-  · have h₀ := FiniteField.unit_isSquare_iff (by rwa [ring_char_zmod_n]) x
-    have hs : (∃ y : (ZMod p)ˣ, y ^ 2 = x) ↔ IsSquare x :=
-      by
-      rw [isSquare_iff_exists_sq x]
-      simp_rw [eq_comm]
-    rw [hs]
-    rwa [card p] at h₀ 
-#align zmod.euler_criterion_units ZMod.euler_criterion_units
-
-/-- Euler's Criterion: a nonzero `a : zmod p` is a square if and only if `x ^ (p / 2) = 1`. -/
-theorem euler_criterion {a : ZMod p} (ha : a ≠ 0) : IsSquare (a : ZMod p) ↔ a ^ (p / 2) = 1 :=
-  by
-  apply (iff_congr _ (by simp [Units.ext_iff])).mp (euler_criterion_units p (Units.mk0 a ha))
-  simp only [Units.ext_iff, sq, Units.val_mk0, Units.val_mul]
-  constructor; · rintro ⟨y, hy⟩; exact ⟨y, hy.symm⟩
-  · rintro ⟨y, rfl⟩
-    have hy : y ≠ 0 := by rintro rfl; simpa [zero_pow] using ha
-    refine' ⟨Units.mk0 y hy, _⟩; simp
-#align zmod.euler_criterion ZMod.euler_criterion
-
-/-- If `a : zmod p` is nonzero, then `a^(p/2)` is either `1` or `-1`. -/
-theorem pow_div_two_eq_neg_one_or_one {a : ZMod p} (ha : a ≠ 0) :
-    a ^ (p / 2) = 1 ∨ a ^ (p / 2) = -1 :=
-  by
-  cases' prime.eq_two_or_odd (Fact.out p.prime) with hp2 hp_odd
-  · subst p; revert a ha; decide
-  rw [← mul_self_eq_one_iff, ← pow_add, ← two_mul, two_mul_odd_div_two hp_odd]
-  exact pow_card_sub_one_eq_one ha
-#align zmod.pow_div_two_eq_neg_one_or_one ZMod.pow_div_two_eq_neg_one_or_one
-
-end ZMod
-
-end Euler
-
-section Legendre
-
-/-!
-### Definition of the Legendre symbol and basic properties
--/
-
-
-open ZMod
-
-variable (p : ℕ) [Fact p.Prime]
-
-/-- The Legendre symbol of `a : ℤ` and a prime `p`, `legendre_sym p a`,
-is an integer defined as
-
-* `0` if `a` is `0` modulo `p`;
-* `1` if `a` is a nonzero square modulo `p`
-* `-1` otherwise.
-
-Note the order of the arguments! The advantage of the order chosen here is
-that `legendre_sym p` is a multiplicative function `ℤ → ℤ`.
--/
-def legendreSym (a : ℤ) : ℤ :=
-  quadraticChar (ZMod p) a
-#align legendre_sym legendreSym
-
-namespace legendreSym
-
-/-- We have the congruence `legendre_sym p a ≡ a ^ (p / 2) mod p`. -/
-theorem eq_pow (a : ℤ) : (legendreSym p a : ZMod p) = a ^ (p / 2) :=
-  by
-  cases' eq_or_ne (ringChar (ZMod p)) 2 with hc hc
-  · by_cases ha : (a : ZMod p) = 0
-    · rw [legendreSym, ha, quadraticChar_zero,
-        zero_pow (Nat.div_pos (Fact.out p.prime).two_le (succ_pos 1))]
-      norm_cast
-    · have := (ring_char_zmod_n p).symm.trans hc
-      -- p = 2
-      subst p
-      rw [legendreSym, quadraticChar_eq_one_of_char_two hc ha]
-      revert ha
-      generalize (a : ZMod 2) = b; revert b; decide
-  · convert quadraticChar_eq_pow_of_char_ne_two' hc (a : ZMod p)
-    exact (card p).symm
-#align legendre_sym.eq_pow legendreSym.eq_pow
-
-/-- If `p ∤ a`, then `legendre_sym p a` is `1` or `-1`. -/
-theorem eq_one_or_neg_one {a : ℤ} (ha : (a : ZMod p) ≠ 0) :
-    legendreSym p a = 1 ∨ legendreSym p a = -1 :=
-  quadraticChar_dichotomy ha
-#align legendre_sym.eq_one_or_neg_one legendreSym.eq_one_or_neg_one
-
-theorem eq_neg_one_iff_not_one {a : ℤ} (ha : (a : ZMod p) ≠ 0) :
-    legendreSym p a = -1 ↔ ¬legendreSym p a = 1 :=
-  quadraticChar_eq_neg_one_iff_not_one ha
-#align legendre_sym.eq_neg_one_iff_not_one legendreSym.eq_neg_one_iff_not_one
-
-/-- The Legendre symbol of `p` and `a` is zero iff `p ∣ a`. -/
-theorem eq_zero_iff (a : ℤ) : legendreSym p a = 0 ↔ (a : ZMod p) = 0 :=
-  quadraticChar_eq_zero_iff
-#align legendre_sym.eq_zero_iff legendreSym.eq_zero_iff
-
-@[simp]
-theorem at_zero : legendreSym p 0 = 0 := by rw [legendreSym, Int.cast_zero, MulChar.map_zero]
-#align legendre_sym.at_zero legendreSym.at_zero
-
-@[simp]
-theorem at_one : legendreSym p 1 = 1 := by rw [legendreSym, Int.cast_one, MulChar.map_one]
-#align legendre_sym.at_one legendreSym.at_one
-
-/-- The Legendre symbol is multiplicative in `a` for `p` fixed. -/
-protected theorem mul (a b : ℤ) : legendreSym p (a * b) = legendreSym p a * legendreSym p b := by
-  simp only [legendreSym, Int.cast_mul, map_mul]
-#align legendre_sym.mul legendreSym.mul
-
-/-- The Legendre symbol is a homomorphism of monoids with zero. -/
-@[simps]
-def hom : ℤ →*₀ ℤ where
-  toFun := legendreSym p
-  map_zero' := at_zero p
-  map_one' := at_one p
-  map_mul' := legendreSym.mul p
-#align legendre_sym.hom legendreSym.hom
-
-/-- The square of the symbol is 1 if `p ∤ a`. -/
-theorem sq_one {a : ℤ} (ha : (a : ZMod p) ≠ 0) : legendreSym p a ^ 2 = 1 :=
-  quadraticChar_sq_one ha
-#align legendre_sym.sq_one legendreSym.sq_one
-
-/-- The Legendre symbol of `a^2` at `p` is 1 if `p ∤ a`. -/
-theorem sq_one' {a : ℤ} (ha : (a : ZMod p) ≠ 0) : legendreSym p (a ^ 2) = 1 := by
-  exact_mod_cast quadraticChar_sq_one' ha
-#align legendre_sym.sq_one' legendreSym.sq_one'
-
-/-- The Legendre symbol depends only on `a` mod `p`. -/
-protected theorem mod (a : ℤ) : legendreSym p a = legendreSym p (a % p) := by
-  simp only [legendreSym, int_cast_mod]
-#align legendre_sym.mod legendreSym.mod
-
-/-- When `p ∤ a`, then `legendre_sym p a = 1` iff `a` is a square mod `p`. -/
-theorem eq_one_iff {a : ℤ} (ha0 : (a : ZMod p) ≠ 0) : legendreSym p a = 1 ↔ IsSquare (a : ZMod p) :=
-  quadraticChar_one_iff_isSquare ha0
-#align legendre_sym.eq_one_iff legendreSym.eq_one_iff
-
-theorem eq_one_iff' {a : ℕ} (ha0 : (a : ZMod p) ≠ 0) :
-    legendreSym p a = 1 ↔ IsSquare (a : ZMod p) := by rw [eq_one_iff]; norm_cast; exact_mod_cast ha0
-#align legendre_sym.eq_one_iff' legendreSym.eq_one_iff'
-
-/-- `legendre_sym p a = -1` iff `a` is a nonsquare mod `p`. -/
-theorem eq_neg_one_iff {a : ℤ} : legendreSym p a = -1 ↔ ¬IsSquare (a : ZMod p) :=
-  quadraticChar_neg_one_iff_not_isSquare
-#align legendre_sym.eq_neg_one_iff legendreSym.eq_neg_one_iff
-
-theorem eq_neg_one_iff' {a : ℕ} : legendreSym p a = -1 ↔ ¬IsSquare (a : ZMod p) := by
-  rw [eq_neg_one_iff]; norm_cast
-#align legendre_sym.eq_neg_one_iff' legendreSym.eq_neg_one_iff'
-
-/-- The number of square roots of `a` modulo `p` is determined by the Legendre symbol. -/
-theorem card_sqrts (hp : p ≠ 2) (a : ℤ) :
-    ↑{x : ZMod p | x ^ 2 = a}.toFinset.card = legendreSym p a + 1 :=
-  quadraticChar_card_sqrts ((ringChar_zmod_n p).substr hp) a
-#align legendre_sym.card_sqrts legendreSym.card_sqrts
-
-end legendreSym
-
-end Legendre
-
-section QuadraticForm
-
-/-!
-### Applications to binary quadratic forms
--/
-
-
-namespace legendreSym
-
-/-- The Legendre symbol `legendre_sym p a = 1` if there is a solution in `ℤ/pℤ`
-of the equation `x^2 - a*y^2 = 0` with `y ≠ 0`. -/
-theorem eq_one_of_sq_sub_mul_sq_eq_zero {p : ℕ} [Fact p.Prime] {a : ℤ} (ha : (a : ZMod p) ≠ 0)
-    {x y : ZMod p} (hy : y ≠ 0) (hxy : x ^ 2 - a * y ^ 2 = 0) : legendreSym p a = 1 :=
-  by
-  apply_fun (· * y⁻¹ ^ 2) at hxy 
-  simp only [MulZeroClass.zero_mul] at hxy 
-  rw [(by ring : (x ^ 2 - ↑a * y ^ 2) * y⁻¹ ^ 2 = (x * y⁻¹) ^ 2 - a * (y * y⁻¹) ^ 2),
-    mul_inv_cancel hy, one_pow, mul_one, sub_eq_zero, pow_two] at hxy 
-  exact (eq_one_iff p ha).mpr ⟨x * y⁻¹, hxy.symm⟩
-#align legendre_sym.eq_one_of_sq_sub_mul_sq_eq_zero legendreSym.eq_one_of_sq_sub_mul_sq_eq_zero
-
-/-- The Legendre symbol `legendre_sym p a = 1` if there is a solution in `ℤ/pℤ`
-of the equation `x^2 - a*y^2 = 0` with `x ≠ 0`. -/
-theorem eq_one_of_sq_sub_mul_sq_eq_zero' {p : ℕ} [Fact p.Prime] {a : ℤ} (ha : (a : ZMod p) ≠ 0)
-    {x y : ZMod p} (hx : x ≠ 0) (hxy : x ^ 2 - a * y ^ 2 = 0) : legendreSym p a = 1 :=
-  haveI hy : y ≠ 0 := by
-    rintro rfl
-    rw [zero_pow' 2 (by norm_num), MulZeroClass.mul_zero, sub_zero,
-      pow_eq_zero_iff (by norm_num : 0 < 2)] at hxy 
-    exacts [hx hxy, inferInstance]
-  -- why is the instance not inferred automatically?
-    eq_one_of_sq_sub_mul_sq_eq_zero
-    ha hy hxy
-#align legendre_sym.eq_one_of_sq_sub_mul_sq_eq_zero' legendreSym.eq_one_of_sq_sub_mul_sq_eq_zero'
-
-/-- If `legendre_sym p a = -1`, then the only solution of `x^2 - a*y^2 = 0` in `ℤ/pℤ`
-is the trivial one. -/
-theorem eq_zero_mod_of_eq_neg_one {p : ℕ} [Fact p.Prime] {a : ℤ} (h : legendreSym p a = -1)
-    {x y : ZMod p} (hxy : x ^ 2 - a * y ^ 2 = 0) : x = 0 ∧ y = 0 :=
-  by
-  have ha : (a : ZMod p) ≠ 0 := by
-    intro hf
-    rw [(eq_zero_iff p a).mpr hf] at h 
-    exact Int.zero_ne_neg_of_ne zero_ne_one h
-  by_contra hf
-  cases' not_and_distrib.mp hf with hx hy
-  · rw [eq_one_of_sq_sub_mul_sq_eq_zero' ha hx hxy, eq_neg_self_iff] at h 
-    exact one_ne_zero h
-  · rw [eq_one_of_sq_sub_mul_sq_eq_zero ha hy hxy, eq_neg_self_iff] at h 
-    exact one_ne_zero h
-#align legendre_sym.eq_zero_mod_of_eq_neg_one legendreSym.eq_zero_mod_of_eq_neg_one
-
-/-- If `legendre_sym p a = -1` and `p` divides `x^2 - a*y^2`, then `p` must divide `x` and `y`. -/
-theorem prime_dvd_of_eq_neg_one {p : ℕ} [Fact p.Prime] {a : ℤ} (h : legendreSym p a = -1) {x y : ℤ}
-    (hxy : ↑p ∣ x ^ 2 - a * y ^ 2) : ↑p ∣ x ∧ ↑p ∣ y :=
-  by
-  simp_rw [← ZMod.int_cast_zmod_eq_zero_iff_dvd] at hxy ⊢
-  push_cast at hxy 
-  exact eq_zero_mod_of_eq_neg_one h hxy
-#align legendre_sym.prime_dvd_of_eq_neg_one legendreSym.prime_dvd_of_eq_neg_one
-
-end legendreSym
-
-end QuadraticForm
-
 section Values
 
-/-!
-### The value of the Legendre symbol at `-1`
-
-See `jacobi_sym.at_neg_one` for the corresponding statement for the Jacobi symbol.
--/
-
-
 variable {p : ℕ} [Fact p.Prime]
 
 open ZMod
 
-/-- `legendre_sym p (-1)` is given by `χ₄ p`. -/
-theorem legendreSym.at_neg_one (hp : p ≠ 2) : legendreSym p (-1) = χ₄ p := by
-  simp only [legendreSym, card p, quadraticChar_neg_one ((ring_char_zmod_n p).substr hp),
-    Int.cast_neg, Int.cast_one]
-#align legendre_sym.at_neg_one legendreSym.at_neg_one
-
-namespace ZMod
-
-/-- `-1` is a square in `zmod p` iff `p` is not congruent to `3` mod `4`. -/
-theorem exists_sq_eq_neg_one_iff : IsSquare (-1 : ZMod p) ↔ p % 4 ≠ 3 := by
-  rw [FiniteField.isSquare_neg_one_iff, card p]
-#align zmod.exists_sq_eq_neg_one_iff ZMod.exists_sq_eq_neg_one_iff
-
-theorem mod_four_ne_three_of_sq_eq_neg_one {y : ZMod p} (hy : y ^ 2 = -1) : p % 4 ≠ 3 :=
-  exists_sq_eq_neg_one_iff.1 ⟨y, hy ▸ pow_two y⟩
-#align zmod.mod_four_ne_three_of_sq_eq_neg_one ZMod.mod_four_ne_three_of_sq_eq_neg_one
-
-/-- If two nonzero squares are negatives of each other in `zmod p`, then `p % 4 ≠ 3`. -/
-theorem mod_four_ne_three_of_sq_eq_neg_sq' {x y : ZMod p} (hy : y ≠ 0) (hxy : x ^ 2 = -y ^ 2) :
-    p % 4 ≠ 3 :=
-  @mod_four_ne_three_of_sq_eq_neg_one p _ (x / y)
-    (by
-      apply_fun fun z => z / y ^ 2 at hxy 
-      rwa [neg_div, ← div_pow, ← div_pow, div_self hy, one_pow] at hxy )
-#align zmod.mod_four_ne_three_of_sq_eq_neg_sq' ZMod.mod_four_ne_three_of_sq_eq_neg_sq'
-
-theorem mod_four_ne_three_of_sq_eq_neg_sq {x y : ZMod p} (hx : x ≠ 0) (hxy : x ^ 2 = -y ^ 2) :
-    p % 4 ≠ 3 :=
-  mod_four_ne_three_of_sq_eq_neg_sq' hx (neg_eq_iff_eq_neg.mpr hxy).symm
-#align zmod.mod_four_ne_three_of_sq_eq_neg_sq ZMod.mod_four_ne_three_of_sq_eq_neg_sq
-
-end ZMod
-
 /-!
 ### The value of the Legendre symbol at `2` and `-2`
 
Diff
@@ -345,8 +345,6 @@ namespace legendreSym
 
 variable (hp : p ≠ 2)
 
-include hp
-
 /-- `legendre_sym p 2` is given by `χ₈ p`. -/
 theorem at_two : legendreSym p 2 = χ₈ p := by
   simp only [legendreSym, card p, quadraticChar_two ((ring_char_zmod_n p).substr hp), Int.cast_bit0,
@@ -365,8 +363,6 @@ namespace ZMod
 
 variable (hp : p ≠ 2)
 
-include hp
-
 /-- `2` is a square modulo an odd prime `p` iff `p` is congruent to `1` or `7` mod `8`. -/
 theorem exists_sq_eq_two_iff : IsSquare (2 : ZMod p) ↔ p % 8 = 1 ∨ p % 8 = 7 :=
   by
Diff
@@ -214,7 +214,7 @@ theorem eq_neg_one_iff' {a : ℕ} : legendreSym p a = -1 ↔ ¬IsSquare (a : ZMo
 
 /-- The number of square roots of `a` modulo `p` is determined by the Legendre symbol. -/
 theorem card_sqrts (hp : p ≠ 2) (a : ℤ) :
-    ↑{ x : ZMod p | x ^ 2 = a }.toFinset.card = legendreSym p a + 1 :=
+    ↑{x : ZMod p | x ^ 2 = a}.toFinset.card = legendreSym p a + 1 :=
   quadraticChar_card_sqrts ((ringChar_zmod_n p).substr hp) a
 #align legendre_sym.card_sqrts legendreSym.card_sqrts
 
@@ -236,7 +236,7 @@ of the equation `x^2 - a*y^2 = 0` with `y ≠ 0`. -/
 theorem eq_one_of_sq_sub_mul_sq_eq_zero {p : ℕ} [Fact p.Prime] {a : ℤ} (ha : (a : ZMod p) ≠ 0)
     {x y : ZMod p} (hy : y ≠ 0) (hxy : x ^ 2 - a * y ^ 2 = 0) : legendreSym p a = 1 :=
   by
-  apply_fun (· * y⁻¹ ^ 2)  at hxy 
+  apply_fun (· * y⁻¹ ^ 2) at hxy 
   simp only [MulZeroClass.zero_mul] at hxy 
   rw [(by ring : (x ^ 2 - ↑a * y ^ 2) * y⁻¹ ^ 2 = (x * y⁻¹) ^ 2 - a * (y * y⁻¹) ^ 2),
     mul_inv_cancel hy, one_pow, mul_one, sub_eq_zero, pow_two] at hxy 
@@ -322,7 +322,7 @@ theorem mod_four_ne_three_of_sq_eq_neg_sq' {x y : ZMod p} (hy : y ≠ 0) (hxy :
     p % 4 ≠ 3 :=
   @mod_four_ne_three_of_sq_eq_neg_one p _ (x / y)
     (by
-      apply_fun fun z => z / y ^ 2  at hxy 
+      apply_fun fun z => z / y ^ 2 at hxy 
       rwa [neg_div, ← div_pow, ← div_pow, div_self hy, one_pow] at hxy )
 #align zmod.mod_four_ne_three_of_sq_eq_neg_sq' ZMod.mod_four_ne_three_of_sq_eq_neg_sq'
 
Diff
@@ -68,7 +68,7 @@ theorem euler_criterion_units (x : (ZMod p)ˣ) : (∃ y : (ZMod p)ˣ, y ^ 2 = x)
       rw [isSquare_iff_exists_sq x]
       simp_rw [eq_comm]
     rw [hs]
-    rwa [card p] at h₀
+    rwa [card p] at h₀ 
 #align zmod.euler_criterion_units ZMod.euler_criterion_units
 
 /-- Euler's Criterion: a nonzero `a : zmod p` is a square if and only if `x ^ (p / 2) = 1`. -/
@@ -236,10 +236,10 @@ of the equation `x^2 - a*y^2 = 0` with `y ≠ 0`. -/
 theorem eq_one_of_sq_sub_mul_sq_eq_zero {p : ℕ} [Fact p.Prime] {a : ℤ} (ha : (a : ZMod p) ≠ 0)
     {x y : ZMod p} (hy : y ≠ 0) (hxy : x ^ 2 - a * y ^ 2 = 0) : legendreSym p a = 1 :=
   by
-  apply_fun (· * y⁻¹ ^ 2)  at hxy
-  simp only [MulZeroClass.zero_mul] at hxy
+  apply_fun (· * y⁻¹ ^ 2)  at hxy 
+  simp only [MulZeroClass.zero_mul] at hxy 
   rw [(by ring : (x ^ 2 - ↑a * y ^ 2) * y⁻¹ ^ 2 = (x * y⁻¹) ^ 2 - a * (y * y⁻¹) ^ 2),
-    mul_inv_cancel hy, one_pow, mul_one, sub_eq_zero, pow_two] at hxy
+    mul_inv_cancel hy, one_pow, mul_one, sub_eq_zero, pow_two] at hxy 
   exact (eq_one_iff p ha).mpr ⟨x * y⁻¹, hxy.symm⟩
 #align legendre_sym.eq_one_of_sq_sub_mul_sq_eq_zero legendreSym.eq_one_of_sq_sub_mul_sq_eq_zero
 
@@ -250,8 +250,8 @@ theorem eq_one_of_sq_sub_mul_sq_eq_zero' {p : ℕ} [Fact p.Prime] {a : ℤ} (ha
   haveI hy : y ≠ 0 := by
     rintro rfl
     rw [zero_pow' 2 (by norm_num), MulZeroClass.mul_zero, sub_zero,
-      pow_eq_zero_iff (by norm_num : 0 < 2)] at hxy
-    exacts[hx hxy, inferInstance]
+      pow_eq_zero_iff (by norm_num : 0 < 2)] at hxy 
+    exacts [hx hxy, inferInstance]
   -- why is the instance not inferred automatically?
     eq_one_of_sq_sub_mul_sq_eq_zero
     ha hy hxy
@@ -264,13 +264,13 @@ theorem eq_zero_mod_of_eq_neg_one {p : ℕ} [Fact p.Prime] {a : ℤ} (h : legend
   by
   have ha : (a : ZMod p) ≠ 0 := by
     intro hf
-    rw [(eq_zero_iff p a).mpr hf] at h
+    rw [(eq_zero_iff p a).mpr hf] at h 
     exact Int.zero_ne_neg_of_ne zero_ne_one h
   by_contra hf
   cases' not_and_distrib.mp hf with hx hy
-  · rw [eq_one_of_sq_sub_mul_sq_eq_zero' ha hx hxy, eq_neg_self_iff] at h
+  · rw [eq_one_of_sq_sub_mul_sq_eq_zero' ha hx hxy, eq_neg_self_iff] at h 
     exact one_ne_zero h
-  · rw [eq_one_of_sq_sub_mul_sq_eq_zero ha hy hxy, eq_neg_self_iff] at h
+  · rw [eq_one_of_sq_sub_mul_sq_eq_zero ha hy hxy, eq_neg_self_iff] at h 
     exact one_ne_zero h
 #align legendre_sym.eq_zero_mod_of_eq_neg_one legendreSym.eq_zero_mod_of_eq_neg_one
 
@@ -278,8 +278,8 @@ theorem eq_zero_mod_of_eq_neg_one {p : ℕ} [Fact p.Prime] {a : ℤ} (h : legend
 theorem prime_dvd_of_eq_neg_one {p : ℕ} [Fact p.Prime] {a : ℤ} (h : legendreSym p a = -1) {x y : ℤ}
     (hxy : ↑p ∣ x ^ 2 - a * y ^ 2) : ↑p ∣ x ∧ ↑p ∣ y :=
   by
-  simp_rw [← ZMod.int_cast_zmod_eq_zero_iff_dvd] at hxy⊢
-  push_cast at hxy
+  simp_rw [← ZMod.int_cast_zmod_eq_zero_iff_dvd] at hxy ⊢
+  push_cast at hxy 
   exact eq_zero_mod_of_eq_neg_one h hxy
 #align legendre_sym.prime_dvd_of_eq_neg_one legendreSym.prime_dvd_of_eq_neg_one
 
@@ -322,8 +322,8 @@ theorem mod_four_ne_three_of_sq_eq_neg_sq' {x y : ZMod p} (hy : y ≠ 0) (hxy :
     p % 4 ≠ 3 :=
   @mod_four_ne_three_of_sq_eq_neg_one p _ (x / y)
     (by
-      apply_fun fun z => z / y ^ 2  at hxy
-      rwa [neg_div, ← div_pow, ← div_pow, div_self hy, one_pow] at hxy)
+      apply_fun fun z => z / y ^ 2  at hxy 
+      rwa [neg_div, ← div_pow, ← div_pow, div_self hy, one_pow] at hxy )
 #align zmod.mod_four_ne_three_of_sq_eq_neg_sq' ZMod.mod_four_ne_three_of_sq_eq_neg_sq'
 
 theorem mod_four_ne_three_of_sq_eq_neg_sq {x y : ZMod p} (hx : x ≠ 0) (hxy : x ^ 2 = -y ^ 2) :
@@ -372,7 +372,7 @@ theorem exists_sq_eq_two_iff : IsSquare (2 : ZMod p) ↔ p % 8 = 1 ∨ p % 8 = 7
   by
   rw [FiniteField.isSquare_two_iff, card p]
   have h₁ := prime.mod_two_eq_one_iff_ne_two.mpr hp
-  rw [← mod_mod_of_dvd p (by norm_num : 2 ∣ 8)] at h₁
+  rw [← mod_mod_of_dvd p (by norm_num : 2 ∣ 8)] at h₁ 
   have h₂ := mod_lt p (by norm_num : 0 < 8)
   revert h₂ h₁
   generalize hm : p % 8 = m; clear! p
@@ -384,7 +384,7 @@ theorem exists_sq_eq_neg_two_iff : IsSquare (-2 : ZMod p) ↔ p % 8 = 1 ∨ p %
   by
   rw [FiniteField.isSquare_neg_two_iff, card p]
   have h₁ := prime.mod_two_eq_one_iff_ne_two.mpr hp
-  rw [← mod_mod_of_dvd p (by norm_num : 2 ∣ 8)] at h₁
+  rw [← mod_mod_of_dvd p (by norm_num : 2 ∣ 8)] at h₁ 
   have h₂ := mod_lt p (by norm_num : 0 < 8)
   revert h₂ h₁
   generalize hm : p % 8 = m; clear! p
@@ -421,7 +421,7 @@ theorem quadratic_reciprocity (hp : p ≠ 2) (hq : q ≠ 2) (hpq : p ≠ q) :
   have hq₂ := (ring_char_zmod_n q).substr hq
   have h :=
     quadraticChar_odd_prime ((ring_char_zmod_n p).substr hp) hq ((ring_char_zmod_n p).substr hpq)
-  rw [card p] at h
+  rw [card p] at h 
   have nc : ∀ n r : ℕ, ((n : ℤ) : ZMod r) = n := fun n r => by norm_cast
   have nc' : (((-1) ^ (p / 2) : ℤ) : ZMod q) = (-1) ^ (p / 2) := by norm_cast
   rw [legendreSym, legendreSym, nc, nc, h, map_mul, mul_rotate', mul_comm (p / 2), ← pow_two,
Diff
@@ -76,15 +76,10 @@ theorem euler_criterion {a : ZMod p} (ha : a ≠ 0) : IsSquare (a : ZMod p) ↔
   by
   apply (iff_congr _ (by simp [Units.ext_iff])).mp (euler_criterion_units p (Units.mk0 a ha))
   simp only [Units.ext_iff, sq, Units.val_mk0, Units.val_mul]
-  constructor;
-  · rintro ⟨y, hy⟩
-    exact ⟨y, hy.symm⟩
+  constructor; · rintro ⟨y, hy⟩; exact ⟨y, hy.symm⟩
   · rintro ⟨y, rfl⟩
-    have hy : y ≠ 0 := by
-      rintro rfl
-      simpa [zero_pow] using ha
-    refine' ⟨Units.mk0 y hy, _⟩
-    simp
+    have hy : y ≠ 0 := by rintro rfl; simpa [zero_pow] using ha
+    refine' ⟨Units.mk0 y hy, _⟩; simp
 #align zmod.euler_criterion ZMod.euler_criterion
 
 /-- If `a : zmod p` is nonzero, then `a^(p/2)` is either `1` or `-1`. -/
@@ -92,9 +87,7 @@ theorem pow_div_two_eq_neg_one_or_one {a : ZMod p} (ha : a ≠ 0) :
     a ^ (p / 2) = 1 ∨ a ^ (p / 2) = -1 :=
   by
   cases' prime.eq_two_or_odd (Fact.out p.prime) with hp2 hp_odd
-  · subst p
-    revert a ha
-    decide
+  · subst p; revert a ha; decide
   rw [← mul_self_eq_one_iff, ← pow_add, ← two_mul, two_mul_odd_div_two hp_odd]
   exact pow_card_sub_one_eq_one ha
 #align zmod.pow_div_two_eq_neg_one_or_one ZMod.pow_div_two_eq_neg_one_or_one
@@ -143,9 +136,7 @@ theorem eq_pow (a : ℤ) : (legendreSym p a : ZMod p) = a ^ (p / 2) :=
       subst p
       rw [legendreSym, quadraticChar_eq_one_of_char_two hc ha]
       revert ha
-      generalize (a : ZMod 2) = b
-      revert b
-      decide
+      generalize (a : ZMod 2) = b; revert b; decide
   · convert quadraticChar_eq_pow_of_char_ne_two' hc (a : ZMod p)
     exact (card p).symm
 #align legendre_sym.eq_pow legendreSym.eq_pow
@@ -209,11 +200,7 @@ theorem eq_one_iff {a : ℤ} (ha0 : (a : ZMod p) ≠ 0) : legendreSym p a = 1 
 #align legendre_sym.eq_one_iff legendreSym.eq_one_iff
 
 theorem eq_one_iff' {a : ℕ} (ha0 : (a : ZMod p) ≠ 0) :
-    legendreSym p a = 1 ↔ IsSquare (a : ZMod p) :=
-  by
-  rw [eq_one_iff]
-  norm_cast
-  exact_mod_cast ha0
+    legendreSym p a = 1 ↔ IsSquare (a : ZMod p) := by rw [eq_one_iff]; norm_cast; exact_mod_cast ha0
 #align legendre_sym.eq_one_iff' legendreSym.eq_one_iff'
 
 /-- `legendre_sym p a = -1` iff `a` is a nonsquare mod `p`. -/
@@ -221,10 +208,8 @@ theorem eq_neg_one_iff {a : ℤ} : legendreSym p a = -1 ↔ ¬IsSquare (a : ZMod
   quadraticChar_neg_one_iff_not_isSquare
 #align legendre_sym.eq_neg_one_iff legendreSym.eq_neg_one_iff
 
-theorem eq_neg_one_iff' {a : ℕ} : legendreSym p a = -1 ↔ ¬IsSquare (a : ZMod p) :=
-  by
-  rw [eq_neg_one_iff]
-  norm_cast
+theorem eq_neg_one_iff' {a : ℕ} : legendreSym p a = -1 ↔ ¬IsSquare (a : ZMod p) := by
+  rw [eq_neg_one_iff]; norm_cast
 #align legendre_sym.eq_neg_one_iff' legendreSym.eq_neg_one_iff'
 
 /-- The number of square roots of `a` modulo `p` is determined by the Legendre symbol. -/
Diff
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Chris Hughes, Michael Stoll
 
 ! This file was ported from Lean 3 source module number_theory.legendre_symbol.quadratic_reciprocity
-! leanprover-community/mathlib commit 2196ab363eb097c008d4497125e0dde23fb36db2
+! leanprover-community/mathlib commit 74a27133cf29446a0983779e37c8f829a85368f3
 ! Please do not edit these lines, except to modify the commit id
 ! if you have ported upstream changes.
 -/
@@ -237,6 +237,71 @@ end legendreSym
 
 end Legendre
 
+section QuadraticForm
+
+/-!
+### Applications to binary quadratic forms
+-/
+
+
+namespace legendreSym
+
+/-- The Legendre symbol `legendre_sym p a = 1` if there is a solution in `ℤ/pℤ`
+of the equation `x^2 - a*y^2 = 0` with `y ≠ 0`. -/
+theorem eq_one_of_sq_sub_mul_sq_eq_zero {p : ℕ} [Fact p.Prime] {a : ℤ} (ha : (a : ZMod p) ≠ 0)
+    {x y : ZMod p} (hy : y ≠ 0) (hxy : x ^ 2 - a * y ^ 2 = 0) : legendreSym p a = 1 :=
+  by
+  apply_fun (· * y⁻¹ ^ 2)  at hxy
+  simp only [MulZeroClass.zero_mul] at hxy
+  rw [(by ring : (x ^ 2 - ↑a * y ^ 2) * y⁻¹ ^ 2 = (x * y⁻¹) ^ 2 - a * (y * y⁻¹) ^ 2),
+    mul_inv_cancel hy, one_pow, mul_one, sub_eq_zero, pow_two] at hxy
+  exact (eq_one_iff p ha).mpr ⟨x * y⁻¹, hxy.symm⟩
+#align legendre_sym.eq_one_of_sq_sub_mul_sq_eq_zero legendreSym.eq_one_of_sq_sub_mul_sq_eq_zero
+
+/-- The Legendre symbol `legendre_sym p a = 1` if there is a solution in `ℤ/pℤ`
+of the equation `x^2 - a*y^2 = 0` with `x ≠ 0`. -/
+theorem eq_one_of_sq_sub_mul_sq_eq_zero' {p : ℕ} [Fact p.Prime] {a : ℤ} (ha : (a : ZMod p) ≠ 0)
+    {x y : ZMod p} (hx : x ≠ 0) (hxy : x ^ 2 - a * y ^ 2 = 0) : legendreSym p a = 1 :=
+  haveI hy : y ≠ 0 := by
+    rintro rfl
+    rw [zero_pow' 2 (by norm_num), MulZeroClass.mul_zero, sub_zero,
+      pow_eq_zero_iff (by norm_num : 0 < 2)] at hxy
+    exacts[hx hxy, inferInstance]
+  -- why is the instance not inferred automatically?
+    eq_one_of_sq_sub_mul_sq_eq_zero
+    ha hy hxy
+#align legendre_sym.eq_one_of_sq_sub_mul_sq_eq_zero' legendreSym.eq_one_of_sq_sub_mul_sq_eq_zero'
+
+/-- If `legendre_sym p a = -1`, then the only solution of `x^2 - a*y^2 = 0` in `ℤ/pℤ`
+is the trivial one. -/
+theorem eq_zero_mod_of_eq_neg_one {p : ℕ} [Fact p.Prime] {a : ℤ} (h : legendreSym p a = -1)
+    {x y : ZMod p} (hxy : x ^ 2 - a * y ^ 2 = 0) : x = 0 ∧ y = 0 :=
+  by
+  have ha : (a : ZMod p) ≠ 0 := by
+    intro hf
+    rw [(eq_zero_iff p a).mpr hf] at h
+    exact Int.zero_ne_neg_of_ne zero_ne_one h
+  by_contra hf
+  cases' not_and_distrib.mp hf with hx hy
+  · rw [eq_one_of_sq_sub_mul_sq_eq_zero' ha hx hxy, eq_neg_self_iff] at h
+    exact one_ne_zero h
+  · rw [eq_one_of_sq_sub_mul_sq_eq_zero ha hy hxy, eq_neg_self_iff] at h
+    exact one_ne_zero h
+#align legendre_sym.eq_zero_mod_of_eq_neg_one legendreSym.eq_zero_mod_of_eq_neg_one
+
+/-- If `legendre_sym p a = -1` and `p` divides `x^2 - a*y^2`, then `p` must divide `x` and `y`. -/
+theorem prime_dvd_of_eq_neg_one {p : ℕ} [Fact p.Prime] {a : ℤ} (h : legendreSym p a = -1) {x y : ℤ}
+    (hxy : ↑p ∣ x ^ 2 - a * y ^ 2) : ↑p ∣ x ∧ ↑p ∣ y :=
+  by
+  simp_rw [← ZMod.int_cast_zmod_eq_zero_iff_dvd] at hxy⊢
+  push_cast at hxy
+  exact eq_zero_mod_of_eq_neg_one h hxy
+#align legendre_sym.prime_dvd_of_eq_neg_one legendreSym.prime_dvd_of_eq_neg_one
+
+end legendreSym
+
+end QuadraticForm
+
 section Values
 
 /-!
Diff
@@ -230,7 +230,7 @@ theorem eq_neg_one_iff' {a : ℕ} : legendreSym p a = -1 ↔ ¬IsSquare (a : ZMo
 /-- The number of square roots of `a` modulo `p` is determined by the Legendre symbol. -/
 theorem card_sqrts (hp : p ≠ 2) (a : ℤ) :
     ↑{ x : ZMod p | x ^ 2 = a }.toFinset.card = legendreSym p a + 1 :=
-  quadraticChar_card_sqrts ((ringChar_zMod_n p).substr hp) a
+  quadraticChar_card_sqrts ((ringChar_zmod_n p).substr hp) a
 #align legendre_sym.card_sqrts legendreSym.card_sqrts
 
 end legendreSym
Diff
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Chris Hughes, Michael Stoll
 
 ! This file was ported from Lean 3 source module number_theory.legendre_symbol.quadratic_reciprocity
-! leanprover-community/mathlib commit e1452ef24e117a92df20b6d45f80b53cabe5a177
+! leanprover-community/mathlib commit 2196ab363eb097c008d4497125e0dde23fb36db2
 ! Please do not edit these lines, except to modify the commit id
 ! if you have ported upstream changes.
 -/
@@ -278,7 +278,7 @@ theorem mod_four_ne_three_of_sq_eq_neg_sq' {x y : ZMod p} (hy : y ≠ 0) (hxy :
 
 theorem mod_four_ne_three_of_sq_eq_neg_sq {x y : ZMod p} (hx : x ≠ 0) (hxy : x ^ 2 = -y ^ 2) :
     p % 4 ≠ 3 :=
-  mod_four_ne_three_of_sq_eq_neg_sq' hx (eq_neg_iff_eq_neg.1 hxy)
+  mod_four_ne_three_of_sq_eq_neg_sq' hx (neg_eq_iff_eq_neg.mpr hxy).symm
 #align zmod.mod_four_ne_three_of_sq_eq_neg_sq ZMod.mod_four_ne_three_of_sq_eq_neg_sq
 
 end ZMod
Diff
@@ -386,7 +386,7 @@ theorem quadratic_reciprocity' (hp : p ≠ 2) (hq : q ≠ 2) :
   by
   cases' eq_or_ne p q with h h
   · subst p
-    rw [(eq_zero_iff q q).mpr (by exact_mod_cast nat_cast_self q), mul_zero]
+    rw [(eq_zero_iff q q).mpr (by exact_mod_cast nat_cast_self q), MulZeroClass.mul_zero]
   · have qr := congr_arg (· * legendreSym p q) (quadratic_reciprocity hp hq h)
     have : ((q : ℤ) : ZMod p) ≠ 0 := by exact_mod_cast prime_ne_zero p q h
     simpa only [mul_assoc, ← pow_two, sq_one p this, mul_one] using qr

Changes in mathlib4

mathlib3
mathlib4
chore: Rename nat_cast/int_cast/rat_cast to natCast/intCast/ratCast (#11486)

Now that I am defining NNRat.cast, I want a definitive answer to this naming issue. Plenty of lemmas in mathlib already use natCast/intCast/ratCast over nat_cast/int_cast/rat_cast, and this matches with the general expectation that underscore-separated name parts correspond to a single declaration.

Diff
@@ -139,7 +139,7 @@ theorem quadratic_reciprocity' (hp : p ≠ 2) (hq : q ≠ 2) :
     legendreSym q p = (-1) ^ (p / 2 * (q / 2)) * legendreSym p q := by
   rcases eq_or_ne p q with h | h
   · subst p
-    rw [(eq_zero_iff q q).mpr (mod_cast nat_cast_self q), mul_zero]
+    rw [(eq_zero_iff q q).mpr (mod_cast natCast_self q), mul_zero]
   · have qr := congr_arg (· * legendreSym p q) (quadratic_reciprocity hp hq h)
     have : ((q : ℤ) : ZMod p) ≠ 0 := mod_cast prime_ne_zero p q h
     simpa only [mul_assoc, ← pow_two, sq_one p this, mul_one] using qr
chore: classify was decide! porting notes (#11044)

Classifies by adding issue number #11043 to porting notes claiming:

was decide!

Diff
@@ -82,7 +82,7 @@ theorem exists_sq_eq_two_iff : IsSquare (2 : ZMod p) ↔ p % 8 = 1 ∨ p % 8 = 7
   have h₂ := mod_lt p (by norm_num : 0 < 8)
   revert h₂ h₁
   generalize p % 8 = m; clear! p
-  intros; interval_cases m <;> simp_all -- Porting note: was `decide!`
+  intros; interval_cases m <;> simp_all -- Porting note (#11043): was `decide!`
 #align zmod.exists_sq_eq_two_iff ZMod.exists_sq_eq_two_iff
 
 /-- `-2` is a square modulo an odd prime `p` iff `p` is congruent to `1` or `3` mod `8`. -/
@@ -93,7 +93,7 @@ theorem exists_sq_eq_neg_two_iff : IsSquare (-2 : ZMod p) ↔ p % 8 = 1 ∨ p %
   have h₂ := mod_lt p (by norm_num : 0 < 8)
   revert h₂ h₁
   generalize p % 8 = m; clear! p
-  intros; interval_cases m <;> simp_all -- Porting note: was `decide!`
+  intros; interval_cases m <;> simp_all -- Porting note (#11043): was `decide!`
 #align zmod.exists_sq_eq_neg_two_iff ZMod.exists_sq_eq_neg_two_iff
 
 end ZMod
chore: remove uses of cases' (#9171)

I literally went through and regex'd some uses of cases', replacing them with rcases; this is meant to be a low effort PR as I hope that tools can do this in the future.

rcases is an easier replacement than cases, though with better tools we could in future do a second pass converting simple rcases added here (and existing ones) to cases.

Diff
@@ -137,7 +137,7 @@ theorem quadratic_reciprocity (hp : p ≠ 2) (hq : q ≠ 2) (hpq : p ≠ q) :
 `(q / p) = (-1)^((p-1)(q-1)/4) * (p / q)`. -/
 theorem quadratic_reciprocity' (hp : p ≠ 2) (hq : q ≠ 2) :
     legendreSym q p = (-1) ^ (p / 2 * (q / 2)) * legendreSym p q := by
-  cases' eq_or_ne p q with h h
+  rcases eq_or_ne p q with h | h
   · subst p
     rw [(eq_zero_iff q q).mpr (mod_cast nat_cast_self q), mul_zero]
   · have qr := congr_arg (· * legendreSym p q) (quadratic_reciprocity hp hq h)
@@ -172,7 +172,7 @@ open legendreSym
 `p` is a square mod `q`. -/
 theorem exists_sq_eq_prime_iff_of_mod_four_eq_one (hp1 : p % 4 = 1) (hq1 : q ≠ 2) :
     IsSquare (q : ZMod p) ↔ IsSquare (p : ZMod q) := by
-  cases' eq_or_ne p q with h h
+  rcases eq_or_ne p q with h | h
   · subst p; rfl
   · rw [← eq_one_iff' p (prime_ne_zero p q h), ← eq_one_iff' q (prime_ne_zero q p h.symm),
       quadratic_reciprocity_one_mod_four hp1 hq1]
chore: replace exact_mod_cast tactic with mod_cast elaborator where possible (#8404)

We still have the exact_mod_cast tactic, used in a few places, which somehow (?) works a little bit harder to prevent the expected type influencing the elaboration of the term. I would like to get to the bottom of this, and it will be easier once the only usages of exact_mod_cast are the ones that don't work using the term elaborator by itself.

Co-authored-by: Scott Morrison <scott.morrison@gmail.com>

Diff
@@ -139,9 +139,9 @@ theorem quadratic_reciprocity' (hp : p ≠ 2) (hq : q ≠ 2) :
     legendreSym q p = (-1) ^ (p / 2 * (q / 2)) * legendreSym p q := by
   cases' eq_or_ne p q with h h
   · subst p
-    rw [(eq_zero_iff q q).mpr (by exact_mod_cast nat_cast_self q), mul_zero]
+    rw [(eq_zero_iff q q).mpr (mod_cast nat_cast_self q), mul_zero]
   · have qr := congr_arg (· * legendreSym p q) (quadratic_reciprocity hp hq h)
-    have : ((q : ℤ) : ZMod p) ≠ 0 := by exact_mod_cast prime_ne_zero p q h
+    have : ((q : ℤ) : ZMod p) ≠ 0 := mod_cast prime_ne_zero p q h
     simpa only [mul_assoc, ← pow_two, sq_one p this, mul_one] using qr
 #align legendre_sym.quadratic_reciprocity' legendreSym.quadratic_reciprocity'
 
chore: bump to v4.3.0-rc2 (#8366)

PR contents

This is the supremum of

along with some minor fixes from failures on nightly-testing as Mathlib master is merged into it.

Note that some PRs for changes that are already compatible with the current toolchain and will be necessary have already been split out: #8380.

I am hopeful that in future we will be able to progressively merge adaptation PRs into a bump/v4.X.0 branch, so we never end up with a "big merge" like this. However one of these adaptation PRs (#8056) predates my new scheme for combined CI, and it wasn't possible to keep that PR viable in the meantime.

Lean PRs involved in this bump

In particular this includes adjustments for the Lean PRs

leanprover/lean4#2778

We can get rid of all the

local macro_rules | `($x ^ $y) => `(HPow.hPow $x $y) -- Porting note: See issue [lean4#2220](https://github.com/leanprover/lean4/pull/2220)

macros across Mathlib (and in any projects that want to write natural number powers of reals).

leanprover/lean4#2722

Changes the default behaviour of simp to (config := {decide := false}). This makes simp (and consequentially norm_num) less powerful, but also more consistent, and less likely to blow up in long failures. This requires a variety of changes: changing some previously by simp or norm_num to decide or rfl, or adding (config := {decide := true}).

leanprover/lean4#2783

This changed the behaviour of simp so that simp [f] will only unfold "fully applied" occurrences of f. The old behaviour can be recovered with simp (config := { unfoldPartialApp := true }). We may in future add a syntax for this, e.g. simp [!f]; please provide feedback! In the meantime, we have made the following changes:

  • switching to using explicit lemmas that have the intended level of application
  • (config := { unfoldPartialApp := true }) in some places, to recover the old behaviour
  • Using @[eqns] to manually adjust the equation lemmas for a particular definition, recovering the old behaviour just for that definition. See #8371, where we do this for Function.comp and Function.flip.

This change in Lean may require further changes down the line (e.g. adding the !f syntax, and/or upstreaming the special treatment for Function.comp and Function.flip, and/or removing this special treatment). Please keep an open and skeptical mind about these changes!

Co-authored-by: leanprover-community-mathlib4-bot <leanprover-community-mathlib4-bot@users.noreply.github.com> Co-authored-by: Scott Morrison <scott.morrison@gmail.com> Co-authored-by: Eric Wieser <wieser.eric@gmail.com> Co-authored-by: Mauricio Collares <mauricio@collares.org>

Diff
@@ -78,7 +78,7 @@ variable (hp : p ≠ 2)
 theorem exists_sq_eq_two_iff : IsSquare (2 : ZMod p) ↔ p % 8 = 1 ∨ p % 8 = 7 := by
   rw [FiniteField.isSquare_two_iff, card p]
   have h₁ := Prime.mod_two_eq_one_iff_ne_two.mpr hp
-  rw [← mod_mod_of_dvd p (by norm_num : 2 ∣ 8)] at h₁
+  rw [← mod_mod_of_dvd p (by decide : 2 ∣ 8)] at h₁
   have h₂ := mod_lt p (by norm_num : 0 < 8)
   revert h₂ h₁
   generalize p % 8 = m; clear! p
@@ -89,7 +89,7 @@ theorem exists_sq_eq_two_iff : IsSquare (2 : ZMod p) ↔ p % 8 = 1 ∨ p % 8 = 7
 theorem exists_sq_eq_neg_two_iff : IsSquare (-2 : ZMod p) ↔ p % 8 = 1 ∨ p % 8 = 3 := by
   rw [FiniteField.isSquare_neg_two_iff, card p]
   have h₁ := Prime.mod_two_eq_one_iff_ne_two.mpr hp
-  rw [← mod_mod_of_dvd p (by norm_num : 2 ∣ 8)] at h₁
+  rw [← mod_mod_of_dvd p (by decide : 2 ∣ 8)] at h₁
   have h₂ := mod_lt p (by norm_num : 0 < 8)
   revert h₂ h₁
   generalize p % 8 = m; clear! p
chore: drop MulZeroClass. in mul_zero/zero_mul (#6682)

Search&replace MulZeroClass.mul_zero -> mul_zero, MulZeroClass.zero_mul -> zero_mul.

These were introduced by Mathport, as the full name of mul_zero is actually MulZeroClass.mul_zero (it's exported with the short name).

Diff
@@ -139,7 +139,7 @@ theorem quadratic_reciprocity' (hp : p ≠ 2) (hq : q ≠ 2) :
     legendreSym q p = (-1) ^ (p / 2 * (q / 2)) * legendreSym p q := by
   cases' eq_or_ne p q with h h
   · subst p
-    rw [(eq_zero_iff q q).mpr (by exact_mod_cast nat_cast_self q), MulZeroClass.mul_zero]
+    rw [(eq_zero_iff q q).mpr (by exact_mod_cast nat_cast_self q), mul_zero]
   · have qr := congr_arg (· * legendreSym p q) (quadratic_reciprocity hp hq h)
     have : ((q : ℤ) : ZMod p) ≠ 0 := by exact_mod_cast prime_ne_zero p q h
     simpa only [mul_assoc, ← pow_two, sq_one p this, mul_one] using qr
chore: script to replace headers with #align_import statements (#5979)

Open in Gitpod

Co-authored-by: Eric Wieser <wieser.eric@gmail.com> Co-authored-by: Scott Morrison <scott.morrison@gmail.com>

Diff
@@ -2,15 +2,12 @@
 Copyright (c) 2018 Chris Hughes. All rights reserved.
 Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Chris Hughes, Michael Stoll
-
-! This file was ported from Lean 3 source module number_theory.legendre_symbol.quadratic_reciprocity
-! leanprover-community/mathlib commit 5b2fe80501ff327b9109fb09b7cc8c325cd0d7d9
-! Please do not edit these lines, except to modify the commit id
-! if you have ported upstream changes.
 -/
 import Mathlib.NumberTheory.LegendreSymbol.Basic
 import Mathlib.NumberTheory.LegendreSymbol.QuadraticChar.GaussSum
 
+#align_import number_theory.legendre_symbol.quadratic_reciprocity from "leanprover-community/mathlib"@"5b2fe80501ff327b9109fb09b7cc8c325cd0d7d9"
+
 /-!
 # Quadratic reciprocity.
 
feat: port NumberTheory.LegendreSymbol.QuadraticReciprocity (#5483)

Dependencies 12 + 1020

1021 files ported (98.8%)
437203 lines ported (98.7%)
Show graph

The unported dependencies are

The following 1 dependencies have changed in mathlib3 since they were ported, which may complicate porting this file