number_theory.legendre_symbol.basic
⟷
Mathlib.NumberTheory.LegendreSymbol.Basic
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.
(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)
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -316,7 +316,7 @@ 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 ⊢
+ simp_rw [← ZMod.intCast_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
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -60,7 +60,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
-/
@@ -268,10 +268,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
-/
@@ -284,7 +284,7 @@ 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
+ 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
@@ -300,13 +300,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
-/
@@ -317,7 +317,7 @@ theorem prime_dvd_of_eq_neg_one {p : ℕ} [Fact p.Prime] {a : ℤ} (h : legendre
(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
+ 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
-/
@@ -368,8 +368,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'
-/
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -283,7 +283,7 @@ theorem eq_one_of_sq_sub_mul_sq_eq_zero' {p : ℕ} [Fact p.Prime] {a : ℤ} (ha
{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,
+ 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?
mathlib commit https://github.com/leanprover-community/mathlib/commit/ce64cd319bb6b3e82f31c2d38e79080d377be451
@@ -3,7 +3,7 @@ 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.QuadraticChar.Basic
+import NumberTheory.LegendreSymbol.QuadraticChar.Basic
#align_import number_theory.legendre_symbol.basic from "leanprover-community/mathlib"@"e160cefedc932ce41c7049bf0c4b0f061d06216e"
mathlib commit https://github.com/leanprover-community/mathlib/commit/8ea5598db6caeddde6cb734aa179cc2408dbd345
@@ -2,14 +2,11 @@
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.basic
-! leanprover-community/mathlib commit e160cefedc932ce41c7049bf0c4b0f061d06216e
-! Please do not edit these lines, except to modify the commit id
-! if you have ported upstream changes.
-/
import Mathbin.NumberTheory.LegendreSymbol.QuadraticChar.Basic
+#align_import number_theory.legendre_symbol.basic from "leanprover-community/mathlib"@"e160cefedc932ce41c7049bf0c4b0f061d06216e"
+
/-!
# Legendre symbol
mathlib commit https://github.com/leanprover-community/mathlib/commit/0723536a0522d24fc2f159a096fb3304bef77472
@@ -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.basic
-! leanprover-community/mathlib commit 5b2fe80501ff327b9109fb09b7cc8c325cd0d7d9
+! leanprover-community/mathlib commit e160cefedc932ce41c7049bf0c4b0f061d06216e
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
@@ -13,6 +13,9 @@ import Mathbin.NumberTheory.LegendreSymbol.QuadraticChar.Basic
/-!
# Legendre symbol
+> THIS FILE IS SYNCHRONIZED WITH MATHLIB4.
+> Any changes to this file require a corresponding PR to mathlib4.
+
This file contains results about Legendre symbols.
We define the Legendre symbol $\Bigl(\frac{a}{p}\Bigr)$ as `legendre_sym p a`.
mathlib commit https://github.com/leanprover-community/mathlib/commit/2a0ce625dbb0ffbc7d1316597de0b25c1ec75303
@@ -47,6 +47,7 @@ namespace ZMod
variable (p : ℕ) [Fact p.Prime]
+#print ZMod.euler_criterion_units /-
/-- 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
@@ -61,7 +62,9 @@ theorem euler_criterion_units (x : (ZMod p)ˣ) : (∃ y : (ZMod p)ˣ, y ^ 2 = x)
rw [hs]
rwa [card p] at h₀
#align zmod.euler_criterion_units ZMod.euler_criterion_units
+-/
+#print ZMod.euler_criterion /-
/-- 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
@@ -72,7 +75,9 @@ theorem euler_criterion {a : ZMod p} (ha : a ≠ 0) : IsSquare (a : ZMod p) ↔
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
+-/
+#print ZMod.pow_div_two_eq_neg_one_or_one /-
/-- 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 :=
@@ -82,6 +87,7 @@ theorem pow_div_two_eq_neg_one_or_one {a : ZMod p} (ha : a ≠ 0) :
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
@@ -98,6 +104,7 @@ open ZMod
variable (p : ℕ) [Fact p.Prime]
+#print legendreSym /-
/-- The Legendre symbol of `a : ℤ` and a prime `p`, `legendre_sym p a`,
is an integer defined as
@@ -111,9 +118,11 @@ that `legendre_sym p` is a multiplicative function `ℤ → ℤ`.
def legendreSym (a : ℤ) : ℤ :=
quadraticChar (ZMod p) a
#align legendre_sym legendreSym
+-/
namespace legendreSym
+#print legendreSym.eq_pow /-
/-- 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
@@ -131,36 +140,50 @@ theorem eq_pow (a : ℤ) : (legendreSym p a : ZMod p) = a ^ (p / 2) :=
· convert quadraticChar_eq_pow_of_char_ne_two' hc (a : ZMod p)
exact (card p).symm
#align legendre_sym.eq_pow legendreSym.eq_pow
+-/
+#print legendreSym.eq_one_or_neg_one /-
/-- 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
+-/
+#print legendreSym.eq_neg_one_iff_not_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
+-/
+#print legendreSym.eq_zero_iff /-
/-- 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
+-/
+#print legendreSym.at_zero /-
@[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
+-/
+#print legendreSym.at_one /-
@[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
+-/
+#print legendreSym.mul /-
/-- 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
+-/
+#print legendreSym.hom /-
/-- The Legendre symbol is a homomorphism of monoids with zero. -/
@[simps]
def hom : ℤ →*₀ ℤ where
@@ -169,45 +192,62 @@ def hom : ℤ →*₀ ℤ where
map_one' := at_one p
map_mul' := legendreSym.mul p
#align legendre_sym.hom legendreSym.hom
+-/
+#print legendreSym.sq_one /-
/-- 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
+-/
+#print 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'
+-/
+#print legendreSym.mod /-
/-- 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
+-/
+#print legendreSym.eq_one_iff /-
/-- 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
+-/
+#print 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'
+-/
+#print legendreSym.eq_neg_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
+-/
+#print 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'
+-/
+#print legendreSym.card_sqrts /-
/-- 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
@@ -222,6 +262,7 @@ section QuadraticForm
namespace legendreSym
+#print 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 `y ≠ 0`. -/
theorem eq_one_of_sq_sub_mul_sq_eq_zero {p : ℕ} [Fact p.Prime] {a : ℤ} (ha : (a : ZMod p) ≠ 0)
@@ -233,7 +274,9 @@ theorem eq_one_of_sq_sub_mul_sq_eq_zero {p : ℕ} [Fact p.Prime] {a : ℤ} (ha :
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
+-/
+#print 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)
@@ -247,7 +290,9 @@ theorem eq_one_of_sq_sub_mul_sq_eq_zero' {p : ℕ} [Fact p.Prime] {a : ℤ} (ha
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'
+-/
+#print legendreSym.eq_zero_mod_of_eq_neg_one /-
/-- 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)
@@ -264,7 +309,9 @@ theorem eq_zero_mod_of_eq_neg_one {p : ℕ} [Fact p.Prime] {a : ℤ} (h : legend
· 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
+-/
+#print legendreSym.prime_dvd_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 :=
@@ -273,6 +320,7 @@ theorem prime_dvd_of_eq_neg_one {p : ℕ} [Fact p.Prime] {a : ℤ} (h : legendre
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
@@ -291,23 +339,30 @@ variable {p : ℕ} [Fact p.Prime]
open ZMod
+#print legendreSym.at_neg_one /-
/-- `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
+#print ZMod.exists_sq_eq_neg_one_iff /-
/-- `-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
+-/
+#print ZMod.mod_four_ne_three_of_sq_eq_neg_one /-
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
+-/
+#print ZMod.mod_four_ne_three_of_sq_eq_neg_sq' /-
/-- 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 :=
@@ -316,11 +371,14 @@ theorem mod_four_ne_three_of_sq_eq_neg_sq' {x y : ZMod p} (hy : y ≠ 0) (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'
+-/
+#print 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
mathlib commit https://github.com/leanprover-community/mathlib/commit/893964fc28cefbcffc7cb784ed00a2895b4e65cf
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.
@@ -182,7 +182,7 @@ theorem sq_one' {a : ℤ} (ha : (a : ZMod p) ≠ 0) : legendreSym p (a ^ 2) = 1
/-- 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]
+ simp only [legendreSym, intCast_mod]
#align legendre_sym.mod legendreSym.mod
/-- When `p ∤ a`, then `legendreSym p a = 1` iff `a` is a square mod `p`. -/
@@ -263,7 +263,7 @@ theorem eq_zero_mod_of_eq_neg_one {p : ℕ} [Fact p.Prime] {a : ℤ} (h : legend
/-- If `legendreSym 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 ⊢
+ simp_rw [← ZMod.intCast_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
I removed some of the tactics that were not used and are hopefully uncontroversial arising from the linter at #11308.
As the commit messages should convey, the removed tactics are, essentially,
push_cast
norm_cast
congr
norm_num
dsimp
funext
intro
infer_instance
@@ -127,8 +127,6 @@ theorem eq_pow (a : ℤ) : (legendreSym p a : ZMod p) = (a : ZMod p) ^ (p / 2) :
· tauto
· simp
· convert quadraticChar_eq_pow_of_char_ne_two' hc (a : ZMod p)
- norm_cast
- congr
exact (card p).symm
#align legendre_sym.eq_pow legendreSym.eq_pow
f ^ n
(#9617)
This involves moving lemmas from Algebra.GroupPower.Ring
to Algebra.GroupWithZero.Basic
and changing some 0 < n
assumptions to n ≠ 0
.
From LeanAPAP
@@ -115,7 +115,7 @@ theorem eq_pow (a : ℤ) : (legendreSym p a : ZMod p) = (a : ZMod p) ^ (p / 2) :
rcases 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))]
+ zero_pow (Nat.div_pos (@Fact.out p.Prime).two_le (succ_pos 1)).ne']
norm_cast
· have := (ringChar_zmod_n p).symm.trans hc
-- p = 2
@@ -241,8 +241,7 @@ theorem eq_one_of_sq_sub_mul_sq_eq_zero' {p : ℕ} [Fact p.Prime] {a : ℤ} (ha
{x y : ZMod p} (hx : x ≠ 0) (hxy : x ^ 2 - a * y ^ 2 = 0) : legendreSym p a = 1 := by
haveI hy : y ≠ 0 := by
rintro rfl
- rw [zero_pow' 2 (by norm_num), mul_zero, sub_zero, pow_eq_zero_iff
- (by norm_num : 0 < 2)] at hxy
+ rw [zero_pow two_ne_zero, mul_zero, sub_zero, sq_eq_zero_iff] at hxy
exact hx hxy
exact 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'
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
.
@@ -112,7 +112,7 @@ namespace legendreSym
/-- We have the congruence `legendreSym p a ≡ a ^ (p / 2) mod p`. -/
theorem eq_pow (a : ℤ) : (legendreSym p a : ZMod p) = (a : ZMod p) ^ (p / 2) := by
- cases' eq_or_ne (ringChar (ZMod p)) 2 with hc hc
+ rcases 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))]
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>
@@ -193,7 +193,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'
/-- `legendreSym p a = -1` iff `a` is a nonsquare mod `p`. -/
@@ -265,7 +265,7 @@ theorem eq_zero_mod_of_eq_neg_one {p : ℕ} [Fact p.Prime] {a : ℤ} (h : legend
/-- If `legendreSym 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
+ (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
@@ -311,7 +311,7 @@ theorem mod_four_ne_three_of_sq_eq_neg_sq' {x y : ZMod p} (hy : y ≠ 0) (hxy :
@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 )
+ 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) :
Mathlib.Init.Data.Int.CompLemmas
was ported from core, and was never really intended for outside use. Nevertheless, people started using it. (Surprise!)
This PR removes one out of the two uses in Mathlib.
If anyone would like to do the other in a separate PR, please do! You would need to reprove
theorem natAbs_add_nonneg {a b : ℤ} (wa : 0 ≤ a) (wb : 0 ≤ b) :
Int.natAbs (a + b) = Int.natAbs a + Int.natAbs b := sorry
theorem natAbs_add_neg {a b : ℤ} (wa : a < 0) (wb : b < 0) :
Int.natAbs (a + b) = Int.natAbs a + Int.natAbs b := sorry
Co-authored-by: Scott Morrison <scott.morrison@gmail.com>
@@ -3,7 +3,6 @@ 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 Mathlib.Init.Data.Int.CompLemmas
import Mathlib.NumberTheory.LegendreSymbol.QuadraticChar.Basic
#align_import number_theory.legendre_symbol.basic from "leanprover-community/mathlib"@"5b2fe80501ff327b9109fb09b7cc8c325cd0d7d9"
@@ -255,7 +254,7 @@ theorem eq_zero_mod_of_eq_neg_one {p : ℕ} [Fact p.Prime] {a : ℤ} (h : legend
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
+ simp at h
by_contra hf
cases' imp_iff_or_not.mp (not_and'.mp hf) with hx hy
· rw [eq_one_of_sq_sub_mul_sq_eq_zero' ha hx hxy, eq_neg_self_iff] at h
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).
@@ -230,7 +230,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
- simp only [MulZeroClass.zero_mul] at hxy
+ simp only [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⟩
@@ -242,7 +242,7 @@ theorem eq_one_of_sq_sub_mul_sq_eq_zero' {p : ℕ} [Fact p.Prime] {a : ℤ} (ha
{x y : ZMod p} (hx : x ≠ 0) (hxy : x ^ 2 - a * y ^ 2 = 0) : legendreSym p a = 1 := by
haveI hy : y ≠ 0 := by
rintro rfl
- rw [zero_pow' 2 (by norm_num), MulZeroClass.mul_zero, sub_zero, pow_eq_zero_iff
+ rw [zero_pow' 2 (by norm_num), mul_zero, sub_zero, pow_eq_zero_iff
(by norm_num : 0 < 2)] at hxy
exact hx hxy
exact eq_one_of_sq_sub_mul_sq_eq_zero ha hy hxy
@@ -178,7 +178,7 @@ theorem sq_one {a : ℤ} (ha : (a : ZMod p) ≠ 0) : legendreSym p a ^ 2 = 1 :=
/-- 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
- dsimp only [legendreSym]
+ dsimp only [legendreSym]
rw [Int.cast_pow]
exact quadraticChar_sq_one' ha
#align legendre_sym.sq_one' legendreSym.sq_one'
@@ -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.basic
-! 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.Init.Data.Int.CompLemmas
import Mathlib.NumberTheory.LegendreSymbol.QuadraticChar.Basic
+#align_import number_theory.legendre_symbol.basic from "leanprover-community/mathlib"@"5b2fe80501ff327b9109fb09b7cc8c325cd0d7d9"
+
/-!
# Legendre symbol
@@ -181,7 +181,9 @@ theorem sq_one {a : ℤ} (ha : (a : ZMod p) ≠ 0) : legendreSym p a ^ 2 = 1 :=
/-- 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
+ dsimp only [legendreSym]
+ rw [Int.cast_pow]
+ exact quadraticChar_sq_one' ha
#align legendre_sym.sq_one' legendreSym.sq_one'
/-- The Legendre symbol depends only on `a` mod `p`. -/
@@ -65,7 +65,8 @@ theorem euler_criterion_units (x : (ZMod p)ˣ) : (∃ y : (ZMod p)ˣ, y ^ 2 = x)
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⟩
+ constructor
+ · rintro ⟨y, hy⟩; exact ⟨y, hy.symm⟩
· rintro ⟨y, rfl⟩
have hy : y ≠ 0 := by
rintro rfl
@@ -126,7 +127,9 @@ theorem eq_pow (a : ℤ) : (legendreSym p a : ZMod p) = (a : ZMod p) ^ (p / 2) :
rw [legendreSym, quadraticChar_eq_one_of_char_two hc ha]
revert ha
push_cast
- generalize (a : ZMod 2) = b; fin_cases b; tauto; simp
+ generalize (a : ZMod 2) = b; fin_cases b
+ · tauto
+ · simp
· convert quadraticChar_eq_pow_of_char_ne_two' hc (a : ZMod p)
norm_cast
congr
@@ -8,6 +8,7 @@ Authors: Chris Hughes, Michael Stoll
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
+import Mathlib.Init.Data.Int.CompLemmas
import Mathlib.NumberTheory.LegendreSymbol.QuadraticChar.Basic
/-!
@@ -252,8 +253,7 @@ theorem eq_zero_mod_of_eq_neg_one {p : ℕ} [Fact p.Prime] {a : ℤ} (h : legend
have ha : (a : ZMod p) ≠ 0 := by
intro hf
rw [(eq_zero_iff p a).mpr hf] at h
- -- porting note: `zero_ne_neg_of_ne` not ported. Fixed by using `linarith` instead
- linarith
+ exact Int.zero_ne_neg_of_ne zero_ne_one h
by_contra hf
cases' imp_iff_or_not.mp (not_and'.mp hf) with hx hy
· rw [eq_one_of_sq_sub_mul_sq_eq_zero' ha hx hxy, eq_neg_self_iff] at h
The unported dependencies are