Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit a839f4d

Browse files
feat(number_theory/quadratic_reciprocity): change order of arguments … (#13311)
…in legendre_sym This is the first step in a major overhaul of the contents of number_theory/quadratic_reciprocity. As a first step, the order of the arguments `a` and `p` to `legendre_sym` is swapped, based on a [poll](https://leanprover.zulipchat.com/#narrow/stream/116395-maths/topic/Quadratic.20Hilbert.20symbol.20over.20.E2.84.9A) on Zulip.
1 parent 4e1102a commit a839f4d

File tree

1 file changed

+22
-16
lines changed

1 file changed

+22
-16
lines changed

src/number_theory/quadratic_reciprocity.lean

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ import data.nat.parity
1313
1414
This file contains results about quadratic residues modulo a prime number.
1515
16+
We define the Legendre symbol `(a / p)` as `legendre_sym p a`.
17+
Note the order of arguments! The advantage of this form is that then `legendre_sym p`
18+
is a multiplicative map.
19+
1620
The main results are the law of quadratic reciprocity, `quadratic_reciprocity`, as well as the
1721
interpretations in terms of existence of square roots depending on the congruence mod 4,
1822
`exists_sq_eq_prime_iff_of_mod_four_eq_one`, and
@@ -348,21 +352,23 @@ variables (p q : ℕ) [fact p.prime] [fact q.prime]
348352

349353
namespace zmod
350354

351-
/-- The Legendre symbol of `a` and `p` is an integer defined as
355+
/-- The Legendre symbol of `a` and `p`, `legendre_sym p a`, is an integer defined as
352356
353357
* `0` if `a` is `0` modulo `p`;
354358
* `1` if `a ^ (p / 2)` is `1` modulo `p`
355359
(by `euler_criterion` this is equivalent to “`a` is a square modulo `p`”);
356360
* `-1` otherwise.
357361
362+
Note the order of the arguments! The advantage of the order chosen here is
363+
that `legendre_sym p` is a multiplicative function `ℤ → ℤ`.
358364
-/
359-
def legendre_sym (a : ) (p : ) : ℤ :=
365+
def legendre_sym (p : ) (a : ) : ℤ :=
360366
if (a : zmod p) = 0 then 0
361367
else if (a : zmod p) ^ (p / 2) = 1 then 1
362368
else -1
363369

364-
lemma legendre_sym_eq_pow (a p : ℕ) [hp : fact p.prime] :
365-
(legendre_sym a p : zmod p) = (a ^ (p / 2)) :=
370+
lemma legendre_sym_eq_pow (p a : ℕ) [hp : fact p.prime] :
371+
(legendre_sym p a : zmod p) = (a ^ (p / 2)) :=
366372
begin
367373
rw legendre_sym,
368374
by_cases ha : (a : zmod p) = 0,
@@ -379,41 +385,41 @@ begin
379385
{ rw [h, if_neg this, int.cast_neg, int.cast_one], } }
380386
end
381387

382-
lemma legendre_sym_eq_one_or_neg_one (a p : ℕ) (ha : (a : zmod p) ≠ 0) :
383-
legendre_sym a p = -1 ∨ legendre_sym a p = 1 :=
388+
lemma legendre_sym_eq_one_or_neg_one (p a : ℕ) (ha : (a : zmod p) ≠ 0) :
389+
legendre_sym p a = -1 ∨ legendre_sym p a = 1 :=
384390
begin
385391
unfold legendre_sym,
386392
split_ifs;
387393
simp only [*, eq_self_iff_true, or_true, true_or, int.cast_coe_nat] at *,
388394
end
389395

390-
lemma legendre_sym_eq_zero_iff (a p : ℕ) :
391-
legendre_sym a p = 0 ↔ (a : zmod p) = 0 :=
396+
lemma legendre_sym_eq_zero_iff (p a : ℕ) :
397+
legendre_sym p a = 0 ↔ (a : zmod p) = 0 :=
392398
begin
393399
split,
394400
{ classical, contrapose,
395-
assume ha, cases legendre_sym_eq_one_or_neg_one a p ha with h h,
401+
assume ha, cases legendre_sym_eq_one_or_neg_one p a ha with h h,
396402
all_goals { rw h, norm_num } },
397403
{ assume ha, rw [legendre_sym, int.cast_coe_nat, if_pos ha] }
398404
end
399405

400406
/-- Gauss' lemma. The legendre symbol can be computed by considering the number of naturals less
401407
than `p/2` such that `(a * x) % p > p / 2` -/
402408
lemma gauss_lemma {a : ℕ} [fact (p % 2 = 1)] (ha0 : (a : zmod p) ≠ 0) :
403-
legendre_sym a p = (-1) ^ ((Ico 1 (p / 2).succ).filter
409+
legendre_sym p a = (-1) ^ ((Ico 1 (p / 2).succ).filter
404410
(λ x : ℕ, p / 2 < (a * x : zmod p).val)).card :=
405-
have (legendre_sym a p : zmod p) = (((-1)^((Ico 1 (p / 2).succ).filter
411+
have (legendre_sym p a : zmod p) = (((-1)^((Ico 1 (p / 2).succ).filter
406412
(λ x : ℕ, p / 2 < (a * x : zmod p).val)).card : ℤ) : zmod p),
407413
by rw [legendre_sym_eq_pow, gauss_lemma_aux₂ p ha0]; simp,
408414
begin
409-
cases legendre_sym_eq_one_or_neg_one a p ha0;
415+
cases legendre_sym_eq_one_or_neg_one p a ha0;
410416
cases neg_one_pow_eq_or ℤ ((Ico 1 (p / 2).succ).filter
411417
(λ x : ℕ, p / 2 < (a * x : zmod p).val)).card;
412418
simp [*, ne_neg_self p one_ne_zero, (ne_neg_self p one_ne_zero).symm] at *
413419
end
414420

415421
lemma legendre_sym_eq_one_iff {a : ℕ} (ha0 : (a : zmod p) ≠ 0) :
416-
legendre_sym a p = 1 ↔ (∃ b : zmod p, b ^ 2 = a) :=
422+
legendre_sym p a = 1 ↔ (∃ b : zmod p, b ^ 2 = a) :=
417423
begin
418424
rw [euler_criterion p ha0, legendre_sym, int.cast_coe_nat, if_neg ha0],
419425
split_ifs,
@@ -422,19 +428,19 @@ begin
422428
end
423429

424430
lemma eisenstein_lemma [fact (p % 2 = 1)] {a : ℕ} (ha1 : a % 2 = 1) (ha0 : (a : zmod p) ≠ 0) :
425-
legendre_sym a p = (-1)^∑ x in Ico 1 (p / 2).succ, (x * a) / p :=
431+
legendre_sym p a = (-1)^∑ x in Ico 1 (p / 2).succ, (x * a) / p :=
426432
by rw [neg_one_pow_eq_pow_mod_two, gauss_lemma p ha0, neg_one_pow_eq_pow_mod_two,
427433
show _ = _, from eisenstein_lemma_aux₂ p ha1 ha0]
428434

429435
/-- **Quadratic reciprocity theorem** -/
430436
theorem quadratic_reciprocity [hp1 : fact (p % 2 = 1)] [hq1 : fact (q % 2 = 1)] (hpq : p ≠ q) :
431-
legendre_sym p q * legendre_sym q p = (-1) ^ ((p / 2) * (q / 2)) :=
437+
legendre_sym q p * legendre_sym p q = (-1) ^ ((p / 2) * (q / 2)) :=
432438
have hpq0 : (p : zmod q) ≠ 0, from prime_ne_zero q p hpq.symm,
433439
have hqp0 : (q : zmod p) ≠ 0, from prime_ne_zero p q hpq,
434440
by rw [eisenstein_lemma q hp1.1 hpq0, eisenstein_lemma p hq1.1 hqp0,
435441
← pow_add, sum_mul_div_add_sum_mul_div_eq_mul q p hpq0, mul_comm]
436442

437-
lemma legendre_sym_two [hp1 : fact (p % 2 = 1)] : legendre_sym 2 p = (-1) ^ (p / 4 + p / 2) :=
443+
lemma legendre_sym_two [hp1 : fact (p % 2 = 1)] : legendre_sym p 2 = (-1) ^ (p / 4 + p / 2) :=
438444
have hp2 : p ≠ 2, from mt (congr_arg (% 2)) (by simpa using hp1.1),
439445
have hp22 : p / 2 / 2 = _ := div_eq_filter_card (show 0 < 2, from dec_trivial)
440446
(nat.div_le_self (p / 2) 2),

0 commit comments

Comments
 (0)