@@ -87,19 +87,25 @@ theorem ZMod.isSquare_neg_one_mul {m n : ℕ} (hc : m.Coprime n) (hm : IsSquare
8787 exact ⟨(x, y), rfl⟩
8888 simpa only [RingEquiv.map_neg_one] using this.map (ZMod.chineseRemainder hc).symm
8989
90- /-- If a prime `p` divides `n` such that `-1` is a square modulo `n`, then `p % 4 ≠ 3`. -/
91- theorem Nat.Prime.mod_four_ne_three_of_dvd_isSquare_neg_one {p n : ℕ} (hpp : p.Prime) (hp : p ∣ n)
92- (hs : IsSquare (-1 : ZMod n)) : p % 4 ≠ 3 := by
93- obtain ⟨y, h⟩ := ZMod.isSquare_neg_one_of_dvd hp hs
90+ /-- If `p` is a prime factor of `n` such that `-1` is a square modulo `n`, then `p % 4 ≠ 3`. -/
91+ theorem Nat.mod_four_ne_three_of_mem_primeFactors_of_isSquare_neg_one {p n : ℕ}
92+ (hp : p ∈ n.primeFactors) ( hs : IsSquare (-1 : ZMod n)) : p % 4 ≠ 3 := by
93+ obtain ⟨y, h⟩ := ZMod.isSquare_neg_one_of_dvd (Nat.dvd_of_mem_primeFactors hp) hs
9494 rw [← sq, eq_comm, show (-1 : ZMod p) = -1 ^ 2 by ring] at h
95- haveI : Fact p.Prime := ⟨hpp ⟩
95+ haveI : Fact p.Prime := ⟨Nat.prime_of_mem_primeFactors hp ⟩
9696 exact ZMod.mod_four_ne_three_of_sq_eq_neg_sq' one_ne_zero h
9797
98+ @ [deprecated "Note that the statement now uses `Nat.primeFactors`, \
99+ you can use `Nat.mem_primeFactors` to get the previous formulation" (since := "2025-10-15" )]
100+ alias Nat.Prime.mod_four_ne_three_of_dvd_isSquare_neg_one :=
101+ Nat.mod_four_ne_three_of_mem_primeFactors_of_isSquare_neg_one
102+
98103/-- If `n` is a squarefree natural number, then `-1` is a square modulo `n` if and only if
99- `n` is not divisible by a prime `q` such that `q % 4 = 3`. -/
100- theorem ZMod.isSquare_neg_one_iff {n : ℕ} (hn : Squarefree n) :
101- IsSquare (-1 : ZMod n) ↔ ∀ {q : ℕ}, q.Prime → q ∣ n → q % 4 ≠ 3 := by
102- refine ⟨fun H q hqp hqd => hqp.mod_four_ne_three_of_dvd_isSquare_neg_one hqd H, fun H => ?_⟩
104+ `n` does not have a prime factor `q` such that `q % 4 = 3`. -/
105+ theorem ZMod.isSquare_neg_one_iff_forall_mem_primeFactors_mod_four_ne_three {n : ℕ}
106+ (hn : Squarefree n) : IsSquare (-1 : ZMod n) ↔ ∀ q ∈ n.primeFactors, q % 4 ≠ 3 := by
107+ refine ⟨fun H q hq ↦ Nat.mod_four_ne_three_of_mem_primeFactors_of_isSquare_neg_one hq H,
108+ fun H ↦ ?_⟩
103109 induction n using induction_on_primes with
104110 | zero => exact False.elim (hn.ne_zero rfl)
105111 | one => exact ⟨0 , by simp only [mul_zero, eq_iff_true_of_subsingleton]⟩
@@ -108,22 +114,31 @@ theorem ZMod.isSquare_neg_one_iff {n : ℕ} (hn : Squarefree n) :
108114 have hcp : p.Coprime n := by
109115 by_contra hc
110116 exact hpp.not_isUnit (hn p <| mul_dvd_mul_left p <| hpp.dvd_iff_not_coprime.mpr hc)
111- have hp₁ := ZMod.exists_sq_eq_neg_one_iff.mpr (H hpp (dvd_mul_right p n))
112- exact ZMod.isSquare_neg_one_mul hcp hp₁
113- (ih hn.of_mul_right fun hqp hqd => H hqp <| dvd_mul_of_dvd_right hqd _)
117+ have hp₁ := ZMod.exists_sq_eq_neg_one_iff.mpr <| H _ <|
118+ Nat.mem_primeFactors.mpr ⟨hpp, Nat.dvd_mul_right .., Squarefree.ne_zero hn⟩
119+ exact ZMod.isSquare_neg_one_mul hcp hp₁ <| ih hn.of_mul_right fun q hqp => H q <|
120+ Nat.mem_primeFactors.mpr ⟨Nat.prime_of_mem_primeFactors hqp,
121+ dvd_mul_of_dvd_right (Nat.dvd_of_mem_primeFactors hqp) _, Squarefree.ne_zero hn⟩
122+
123+ @ [deprecated "Note that the statement now uses `Nat.primeFactors`, \
124+ you can use `Nat.mem_primeFactors` and `Squarefree.ne_zero` to get the previous formulation"
125+ (since := "2025-10-15" )]
126+ alias ZMod.isSquare_neg_one_iff :=
127+ ZMod.isSquare_neg_one_iff_forall_mem_primeFactors_mod_four_ne_three
114128
115129/-- If `n` is a squarefree natural number, then `-1` is a square modulo `n` if and only if
116130`n` has no divisor `q` that is `≡ 3 mod 4`. -/
117131theorem ZMod.isSquare_neg_one_iff' {n : ℕ} (hn : Squarefree n) :
118132 IsSquare (-1 : ZMod n) ↔ ∀ {q : ℕ}, q ∣ n → q % 4 ≠ 3 := by
119133 have help : ∀ a b : ZMod 4 , a ≠ 3 → b ≠ 3 → a * b ≠ 3 := by decide
120- rw [ZMod.isSquare_neg_one_iff hn]
121- refine ⟨?_, fun H q _ => H⟩
134+ rw [ZMod.isSquare_neg_one_iff_forall_mem_primeFactors_mod_four_ne_three hn]
135+ refine ⟨?_, fun H q hq => H <| Nat.dvd_of_mem_primeFactors hq ⟩
122136 intro H
123137 refine @induction_on_primes _ ?_ ?_ (fun p q hp hq hpq => ?_)
124138 · exact fun _ => by simp
125139 · exact fun _ => by simp
126- · replace hp := H hp (dvd_of_mul_right_dvd hpq)
140+ · replace hp := H _ <|
141+ Nat.mem_primeFactors.mpr ⟨hp, dvd_of_mul_right_dvd hpq, Squarefree.ne_zero hn⟩
127142 replace hq := hq (dvd_of_mul_left_dvd hpq)
128143 rw [show 3 = 3 % 4 by simp, Ne, ← ZMod.natCast_eq_natCast_iff'] at hp hq ⊢
129144 rw [Nat.cast_mul]
@@ -200,31 +215,25 @@ every prime `q` such that `q % 4 = 3` in the prime factorization of `n` is even.
200215(The assumption `0 < n` is not present, since for `n = 0`, both sides are satisfied;
201216the right-hand side holds, since `padicValNat q 0 = 0` by definition.) -/
202217theorem Nat.eq_sq_add_sq_iff {n : ℕ} :
203- (∃ x y : ℕ , n = x ^ 2 + y ^ 2 ) ↔ ∀ {q : ℕ}, q.Prime → q % 4 = 3 → Even (padicValNat q n) := by
218+ (∃ x y, n = x ^ 2 + y ^ 2 ) ↔ ∀ q ∈ n.primeFactors, q % 4 = 3 → Even (padicValNat q n) := by
204219 rcases n.eq_zero_or_pos with (rfl | hn₀)
205- · exact ⟨fun _ q _ _ => (@ padicValNat.zero q) .symm ▸ Even.zero, fun _ => ⟨0 , 0 , rfl⟩⟩
220+ · exact ⟨fun _ q _ _ ↦ padicValNat.zero.symm ▸ Even.zero, fun _ ↦ ⟨0 , 0 , rfl⟩⟩
206221 -- now `0 < n`
207- rw [Nat.eq_sq_add_sq_iff_eq_sq_mul]
208- refine ⟨fun H q hq h => ?_, fun H => ?_⟩
209- · obtain ⟨a, b, h₁, h₂⟩ := H
210- have hqb := padicValNat.eq_zero_of_not_dvd fun hf =>
211- (hq.mod_four_ne_three_of_dvd_isSquare_neg_one hf h₂) h
212- have hab : a ^ 2 * b ≠ 0 := h₁ ▸ hn₀.ne'
213- have ha₂ := left_ne_zero_of_mul hab
214- have ha := mt sq_eq_zero_iff.mpr ha₂
215- have hb := right_ne_zero_of_mul hab
216- haveI hqi : Fact q.Prime := ⟨hq⟩
217- simp_rw [h₁, padicValNat.mul ha₂ hb, padicValNat.pow 2 ha, hqb, add_zero]
218- exact even_two_mul _
219- · obtain ⟨b, a, hb₀, ha₀, hab, hb⟩ := Nat.sq_mul_squarefree_of_pos hn₀
220- refine ⟨a, b, hab.symm, (ZMod.isSquare_neg_one_iff hb).mpr fun {q} hqp hqb hq4 => ?_⟩
221- refine Nat.not_even_iff_odd.2 ?_ (H hqp hq4)
222- have hqb' : padicValNat q b = 1 :=
223- b.factorization_def hqp ▸ le_antisymm (hb.natFactorization_le_one _)
224- ((hqp.dvd_iff_one_le_factorization hb₀.ne').mp hqb)
225- haveI hqi : Fact q.Prime := ⟨hqp⟩
226- simp_rw [← hab, padicValNat.mul (pow_ne_zero 2 ha₀.ne') hb₀.ne', hqb',
227- padicValNat.pow 2 ha₀.ne']
228- exact odd_two_mul_add_one _
222+ refine eq_sq_add_sq_iff_eq_sq_mul.trans ⟨fun ⟨a, b, h₁, h₂⟩ q hq h ↦ ?_, fun H ↦ ?_⟩
223+ · haveI : Fact q.Prime := ⟨prime_of_mem_primeFactors hq⟩
224+ have : q ∣ b → q ∈ b.primeFactors := by grind [mem_primeFactors]
225+ grind [padicValNat.mul, padicValNat.pow,
226+ padicValNat.eq_zero_of_not_dvd, mod_four_ne_three_of_mem_primeFactors_of_isSquare_neg_one]
227+ · obtain ⟨b, a, hb₀, ha₀, hab, hb⟩ := sq_mul_squarefree_of_pos hn₀
228+ refine ⟨a, b, hab.symm, ZMod.isSquare_neg_one_iff_forall_mem_primeFactors_mod_four_ne_three hb
229+ |>.mpr fun q hq hq4 ↦ ?_⟩
230+ haveI : Fact q.Prime := ⟨prime_of_mem_primeFactors hq⟩
231+ have := Nat.primeFactors_mono <| Dvd.intro_left _ hab
232+ have : b.factorization q = 1 := by grind [Squarefree.natFactorization_le_one,
233+ Prime.dvd_iff_one_le_factorization, prime_of_mem_primeFactors, dvd_of_mem_primeFactors]
234+ grind [factorization_def, prime_of_mem_primeFactors, padicValNat.mul, padicValNat.pow]
229235
230236end Main
237+
238+ instance {n : ℕ} : Decidable (∃ x y, n = x ^ 2 + y ^ 2 ) :=
239+ decidable_of_iff' _ Nat.eq_sq_add_sq_iff
0 commit comments