File: Mathlib/NumberTheory/LegendreSymbol/GaussEisensteinLemmas.lean

full_name: ZMod.Ico_map_valMinAbs_natAbs_eq_Ico_map_id
code: /-- The image of the map sending a nonzero natural number `x ≤ p / 2` to the absolute value
  of the integer in `(-p/2, p/2]` that is congruent to `a * x mod p` is the set
  of nonzero natural numbers `x` such that `x ≤ p / 2`. -/
theorem Ico_map_valMinAbs_natAbs_eq_Ico_map_id (p : ℕ) [hp : Fact p.Prime] (a : ZMod p)
    (hap : a ≠ 0) : ((Ico 1 (p / 2).succ).1.map fun (x : ℕ) => (a * x).valMinAbs.natAbs) =
    (Ico 1 (p / 2).succ).1.map fun a => a 
goal: Multiset.map (fun x => (a * ↑x).valMinAbs.natAbs) (Finset.Ico 1 (p / 2).succ).val =
  Multiset.map (fun a => a) (Finset.Ico 1 (p / 2).succ).val

full_name: _private.Mathlib.NumberTheory.LegendreSymbol.GaussEisensteinLemmas.0.ZMod.gauss_lemma_aux₁
code: private theorem gauss_lemma_aux₁ (p : ℕ) [Fact p.Prime] {a : ℤ}
    (hap : (a : ZMod p) ≠ 0) : (a ^ (p / 2) * (p / 2)! : ZMod p) =
    (-1 : ZMod p) ^ ((Ico 1 (p / 2).succ).filter fun x : ℕ =>
      ¬(a * x : ZMod p).val ≤ p / 2).card * (p / 2)! 
goal: ↑a ^ (p / 2) * ↑(p / 2)! =
  (-1) ^ (Finset.filter (fun x => ¬(↑a * ↑x).val ≤ p / 2) (Finset.Ico 1 (p / 2).succ)).card * ↑(p / 2)!

full_name: ZMod.gauss_lemma_aux
code: theorem gauss_lemma_aux (p : ℕ) [hp : Fact p.Prime] {a : ℤ}
    (hap : (a : ZMod p) ≠ 0) : (↑a ^ (p / 2) : ZMod p) =
    ((-1) ^ ((Ico 1 (p / 2).succ).filter fun x : ℕ => p / 2 < (a * x : ZMod p).val).card :) 
goal: ↑a ^ (p / 2) = ↑((-1) ^ (Finset.filter (fun x => p / 2 < (↑a * ↑x).val) (Finset.Ico 1 (p / 2).succ)).card)

full_name: ZMod.gauss_lemma
code: /-- **Gauss' lemma**. The Legendre symbol can be computed by considering the number of naturals less
  than `p/2` such that `(a * x) % p > p / 2`. -/
theorem gauss_lemma {p : ℕ} [h : Fact p.Prime] {a : ℤ} (hp : p ≠ 2) (ha0 : (a : ZMod p) ≠ 0) :
    legendreSym p a = (-1) ^ ((Ico 1 (p / 2).succ).filter fun x : ℕ =>
      p / 2 < (a * x : ZMod p).val).card 
goal: legendreSym p a = (-1) ^ (Finset.filter (fun x => p / 2 < (↑a * ↑x).val) (Finset.Ico 1 (p / 2).succ)).card

full_name: _private.Mathlib.NumberTheory.LegendreSymbol.GaussEisensteinLemmas.0.ZMod.eisenstein_lemma_aux₁
code: private theorem eisenstein_lemma_aux₁ (p : ℕ) [Fact p.Prime] [hp2 : Fact (p % 2 = 1)] {a : ℕ}
    (hap : (a : ZMod p) ≠ 0) : ((∑ x ∈ Ico 1 (p / 2).succ, a * x : ℕ) : ZMod 2) =
    ((Ico 1 (p / 2).succ).filter fun x : ℕ => p / 2 < (a * x : ZMod p).val).card +
      ∑ x ∈ Ico 1 (p / 2).succ, x + (∑ x ∈ Ico 1 (p / 2).succ, a * x / p : ℕ) 
goal: ↑(∑ x ∈ Finset.Ico 1 (p / 2).succ, a * x) =
  ↑(Finset.filter (fun x => p / 2 < (↑a * ↑x).val) (Finset.Ico 1 (p / 2).succ)).card +
      ↑(∑ x ∈ Finset.Ico 1 (p / 2).succ, x) +
    ↑(∑ x ∈ Finset.Ico 1 (p / 2).succ, a * x / p)

full_name: ZMod.eisenstein_lemma_aux
code: theorem eisenstein_lemma_aux (p : ℕ) [Fact p.Prime] [Fact (p % 2 = 1)] {a : ℕ} (ha2 : a % 2 = 1)
    (hap : (a : ZMod p) ≠ 0) :
    ((Ico 1 (p / 2).succ).filter fun x : ℕ => p / 2 < (a * x : ZMod p).val).card ≡
      ∑ x ∈ Ico 1 (p / 2).succ, x * a / p [MOD 2] 
goal: (Finset.filter (fun x => p / 2 < (↑a * ↑x).val) (Finset.Ico 1 (p / 2).succ)).card ≡
  ∑ x ∈ Finset.Ico 1 (p / 2).succ, x * a / p [MOD 2]

full_name: ZMod.div_eq_filter_card
code: theorem div_eq_filter_card {a b c : ℕ} (hb0 : 0 < b) (hc : a / b ≤ c) :
    a / b = ((Ico 1 c.succ).filter fun x => x * b ≤ a).card 
goal: a / b = (Finset.filter (fun x => x * b ≤ a) (Finset.Ico 1 c.succ)).card

full_name: _private.Mathlib.NumberTheory.LegendreSymbol.GaussEisensteinLemmas.0.ZMod.sum_Ico_eq_card_lt
code: /-- The given sum is the number of integer points in the triangle formed by the diagonal of the
  rectangle `(0, p/2) × (0, q/2)`. -/
private theorem sum_Ico_eq_card_lt {p q : ℕ} :
    ∑ a ∈ Ico 1 (p / 2).succ, a * q / p =
    ((Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ).filter fun x : ℕ × ℕ =>
      x.2 * p ≤ x.1 * q).card 
goal: ∑ a ∈ Finset.Ico 1 (p / 2).succ, a * q / p =
  (Finset.filter (fun x => x.2 * p ≤ x.1 * q) (Finset.Ico 1 (p / 2).succ ×ˢ Finset.Ico 1 (q / 2).succ)).card

full_name: ZMod.sum_mul_div_add_sum_mul_div_eq_mul
code: /-- Each of the sums in this lemma is the cardinality of the set of integer points in each of the
  two triangles formed by the diagonal of the rectangle `(0, p/2) × (0, q/2)`. Adding them
  gives the number of points in the rectangle. -/
theorem sum_mul_div_add_sum_mul_div_eq_mul (p q : ℕ) [hp : Fact p.Prime] (hq0 : (q : ZMod p) ≠ 0) :
    ∑ a ∈ Ico 1 (p / 2).succ, a * q / p + ∑ a ∈ Ico 1 (q / 2).succ, a * p / q =
    p / 2 * (q / 2) 
goal: ∑ a ∈ Finset.Ico 1 (p / 2).succ, a * q / p + ∑ a ∈ Finset.Ico 1 (q / 2).succ, a * p / q = p / 2 * (q / 2)

full_name: ZMod.eisenstein_lemma
code: /-- **Eisenstein's lemma** -/
theorem eisenstein_lemma {p : ℕ} [Fact p.Prime] (hp : p ≠ 2) {a : ℕ} (ha1 : a % 2 = 1)
    (ha0 : (a : ZMod p) ≠ 0) : legendreSym p a = (-1) ^ ∑ x ∈ Ico 1 (p / 2).succ, x * a / p 
goal: legendreSym p ↑a = (-1) ^ ∑ x ∈ Finset.Ico 1 (p / 2).succ, x * a / p