l3lab/ntp-mathlib huggingface dataset:
/-- If `p` is a prime natural number and `x` is an integer number, then there exist natural numbers
`a ≤ p / 2` and `b ≤ p / 2` such that `a ^ 2 + b ^ 2 ≡ x [ZMOD p]`. This is a version of
`ZMod.sq_add_sq` with estimates on `a` and `b`. -/
theorem Nat.sq_add_sq_zmodEq (p : ℕ) [Fact p.Prime] (x : ℤ) :
    ∃ a b : ℕ, a ≤ p / 2 ∧ b ≤ p / 2 ∧ (a : ℤ) ^ 2 + (b : ℤ) ^ 2 ≡ x [ZMOD p] := by
  rcases ZMod.sq_add_sq p x with ⟨a, b, hx⟩
  refine ⟨a.valMinAbs.natAbs, b.valMinAbs.natAbs, ZMod.natAbs_valMinAbs_le _,
    ZMod.natAbs_valMinAbs_le _, ?_⟩
  

Proof state:
case intro.intro
K : Type u_1
R : Type u_2
p : ℕ
inst✝ : Fact (Prime p)
x : ℤ
a b : ZMod p
hx : a ^ 2 + b ^ 2 = ↑x
⊢ ↑(Int.natAbs (ZMod.valMinAbs a)) ^ 2 + ↑(Int.natAbs (ZMod.valMinAbs b)) ^ 2 ≡ x [ZMOD ↑p]

Next tactic:
rw [← a.coe_valMinAbs, ← b.coe_valMinAbs] at hx
/-- If `p` is a prime natural number and `x` is an integer number, then there exist natural numbers
`a ≤ p / 2` and `b ≤ p / 2` such that `a ^ 2 + b ^ 2 ≡ x [ZMOD p]`. This is a version of
`ZMod.sq_add_sq` with estimates on `a` and `b`. -/
theorem Nat.sq_add_sq_zmodEq (p : ℕ) [Fact p.Prime] (x : ℤ) :
    ∃ a b : ℕ, a ≤ p / 2 ∧ b ≤ p / 2 ∧ (a : ℤ) ^ 2 + (b : ℤ) ^ 2 ≡ x [ZMOD p] := by
  rcases ZMod.sq_add_sq p x with ⟨a, b, hx⟩
  refine ⟨a.valMinAbs.natAbs, b.valMinAbs.natAbs, ZMod.natAbs_valMinAbs_le _,
    ZMod.natAbs_valMinAbs_le _, ?_⟩
  rw [← a.coe_valMinAbs, ← b.coe_valMinAbs] at hx
  

Proof state:
case intro.intro
K : Type u_1
R : Type u_2
p : ℕ
inst✝ : Fact (Prime p)
x : ℤ
a b : ZMod p
hx : ↑(ZMod.valMinAbs a) ^ 2 + ↑(ZMod.valMinAbs b) ^ 2 = ↑x
⊢ ↑(Int.natAbs (ZMod.valMinAbs a)) ^ 2 + ↑(Int.natAbs (ZMod.valMinAbs b)) ^ 2 ≡ x [ZMOD ↑p]

Next tactic:
push_cast
/-- If `p` is a prime natural number and `x` is an integer number, then there exist natural numbers
`a ≤ p / 2` and `b ≤ p / 2` such that `a ^ 2 + b ^ 2 ≡ x [ZMOD p]`. This is a version of
`ZMod.sq_add_sq` with estimates on `a` and `b`. -/
theorem Nat.sq_add_sq_zmodEq (p : ℕ) [Fact p.Prime] (x : ℤ) :
    ∃ a b : ℕ, a ≤ p / 2 ∧ b ≤ p / 2 ∧ (a : ℤ) ^ 2 + (b : ℤ) ^ 2 ≡ x [ZMOD p] := by
  rcases ZMod.sq_add_sq p x with ⟨a, b, hx⟩
  refine ⟨a.valMinAbs.natAbs, b.valMinAbs.natAbs, ZMod.natAbs_valMinAbs_le _,
    ZMod.natAbs_valMinAbs_le _, ?_⟩
  rw [← a.coe_valMinAbs, ← b.coe_valMinAbs] at hx
  push_cast
  

Proof state:
case intro.intro
K : Type u_1
R : Type u_2
p : ℕ
inst✝ : Fact (Prime p)
x : ℤ
a b : ZMod p
hx : ↑(ZMod.valMinAbs a) ^ 2 + ↑(ZMod.valMinAbs b) ^ 2 = ↑x
⊢ |ZMod.valMinAbs a| ^ 2 + |ZMod.valMinAbs b| ^ 2 ≡ x [ZMOD ↑p]

Next tactic:
rw [sq_abs, sq_abs, ← ZMod.int_cast_eq_int_cast_iff]
/-- If `p` is a prime natural number and `x` is an integer number, then there exist natural numbers
`a ≤ p / 2` and `b ≤ p / 2` such that `a ^ 2 + b ^ 2 ≡ x [ZMOD p]`. This is a version of
`ZMod.sq_add_sq` with estimates on `a` and `b`. -/
theorem Nat.sq_add_sq_zmodEq (p : ℕ) [Fact p.Prime] (x : ℤ) :
    ∃ a b : ℕ, a ≤ p / 2 ∧ b ≤ p / 2 ∧ (a : ℤ) ^ 2 + (b : ℤ) ^ 2 ≡ x [ZMOD p] := by
  rcases ZMod.sq_add_sq p x with ⟨a, b, hx⟩
  refine ⟨a.valMinAbs.natAbs, b.valMinAbs.natAbs, ZMod.natAbs_valMinAbs_le _,
    ZMod.natAbs_valMinAbs_le _, ?_⟩
  rw [← a.coe_valMinAbs, ← b.coe_valMinAbs] at hx
  push_cast
  rw [sq_abs, sq_abs, ← ZMod.int_cast_eq_int_cast_iff]
  

Proof state:
case intro.intro
K : Type u_1
R : Type u_2
p : ℕ
inst✝ : Fact (Prime p)
x : ℤ
a b : ZMod p
hx : ↑(ZMod.valMinAbs a) ^ 2 + ↑(ZMod.valMinAbs b) ^ 2 = ↑x
⊢ ↑(ZMod.valMinAbs a ^ 2 + ZMod.valMinAbs b ^ 2) = ↑x

Next tactic:
exact mod_cast hx
/-- If `p` is a prime natural number and `x` is a natural number, then there exist natural numbers
`a ≤ p / 2` and `b ≤ p / 2` such that `a ^ 2 + b ^ 2 ≡ x [MOD p]`. This is a version of
`ZMod.sq_add_sq` with estimates on `a` and `b`. -/
theorem Nat.sq_add_sq_modEq (p : ℕ) [Fact p.Prime] (x : ℕ) :
    ∃ a b : ℕ, a ≤ p / 2 ∧ b ≤ p / 2 ∧ a ^ 2 + b ^ 2 ≡ x [MOD p] := by
  

Proof state:
K : Type u_1
R : Type u_2
p : ℕ
inst✝ : Fact (Prime p)
x : ℕ
⊢ ∃ a b, a ≤ p / 2 ∧ b ≤ p / 2 ∧ a ^ 2 + b ^ 2 ≡ x [MOD p]

Next tactic:
simpa only [← Int.coe_nat_modEq_iff] using Nat.sq_add_sq_zmodEq p x
theorem sq_add_sq (R : Type*) [CommRing R] [IsDomain R] (p : ℕ) [NeZero p] [CharP R p] (x : ℤ) :
    ∃ a b : ℕ, ((a : R) ^ 2 + (b : R) ^ 2) = x := by
  

Proof state:
K : Type u_1
R✝ : Type u_2
R : Type u_3
inst✝³ : CommRing R
inst✝² : IsDomain R
p : ℕ
inst✝¹ : NeZero p
inst✝ : CharP R p
x : ℤ
⊢ ∃ a b, ↑a ^ 2 + ↑b ^ 2 = ↑x

Next tactic:
haveI := char_is_prime_of_pos R p
theorem sq_add_sq (R : Type*) [CommRing R] [IsDomain R] (p : ℕ) [NeZero p] [CharP R p] (x : ℤ) :
    ∃ a b : ℕ, ((a : R) ^ 2 + (b : R) ^ 2) = x := by
  haveI := char_is_prime_of_pos R p
  

Proof state:
K : Type u_1
R✝ : Type u_2
R : Type u_3
inst✝³ : CommRing R
inst✝² : IsDomain R
p : ℕ
inst✝¹ : NeZero p
inst✝ : CharP R p
x : ℤ
this : Fact (Nat.Prime p)
⊢ ∃ a b, ↑a ^ 2 + ↑b ^ 2 = ↑x

Next tactic:
obtain ⟨a, b, hab⟩ := ZMod.sq_add_sq p x
theorem sq_add_sq (R : Type*) [CommRing R] [IsDomain R] (p : ℕ) [NeZero p] [CharP R p] (x : ℤ) :
    ∃ a b : ℕ, ((a : R) ^ 2 + (b : R) ^ 2) = x := by
  haveI := char_is_prime_of_pos R p
  obtain ⟨a, b, hab⟩ := ZMod.sq_add_sq p x
  

Proof state:
case intro.intro
K : Type u_1
R✝ : Type u_2
R : Type u_3
inst✝³ : CommRing R
inst✝² : IsDomain R
p : ℕ
inst✝¹ : NeZero p
inst✝ : CharP R p
x : ℤ
this : Fact (Nat.Prime p)
a b : ZMod p
hab : a ^ 2 + b ^ 2 = ↑x
⊢ ∃ a b, ↑a ^ 2 + ↑b ^ 2 = ↑x

Next tactic:
refine' ⟨a.val, b.val, _⟩
theorem sq_add_sq (R : Type*) [CommRing R] [IsDomain R] (p : ℕ) [NeZero p] [CharP R p] (x : ℤ) :
    ∃ a b : ℕ, ((a : R) ^ 2 + (b : R) ^ 2) = x := by
  haveI := char_is_prime_of_pos R p
  obtain ⟨a, b, hab⟩ := ZMod.sq_add_sq p x
  refine' ⟨a.val, b.val, _⟩
  

Proof state:
case intro.intro
K : Type u_1
R✝ : Type u_2
R : Type u_3
inst✝³ : CommRing R
inst✝² : IsDomain R
p : ℕ
inst✝¹ : NeZero p
inst✝ : CharP R p
x : ℤ
this : Fact (Nat.Prime p)
a b : ZMod p
hab : a ^ 2 + b ^ 2 = ↑x
⊢ ↑(ZMod.val a) ^ 2 + ↑(ZMod.val b) ^ 2 = ↑x

Next tactic:
simpa using congr_arg (ZMod.castHom dvd_rfl R) hab
/-- The **Fermat-Euler totient theorem**. `Nat.ModEq.pow_totient` is an alternative statement
  of the same theorem. -/
@[simp]
theorem ZMod.pow_totient {n : ℕ} (x : (ZMod n)ˣ) : x ^ φ n = 1 := by
  

Proof state:
K : Type u_1
R : Type u_2
n : ℕ
x : (ZMod n)ˣ
⊢ x ^ φ n = 1

Next tactic:
cases n
/-- The **Fermat-Euler totient theorem**. `Nat.ModEq.pow_totient` is an alternative statement
  of the same theorem. -/
@[simp]
theorem ZMod.pow_totient {n : ℕ} (x : (ZMod n)ˣ) : x ^ φ n = 1 := by
  cases n
  · 

Proof state:
case zero
K : Type u_1
R : Type u_2
x : (ZMod Nat.zero)ˣ
⊢ x ^ φ Nat.zero = 1

Next tactic:
rw [Nat.totient_zero, pow_zero]
/-- The **Fermat-Euler totient theorem**. `Nat.ModEq.pow_totient` is an alternative statement
  of the same theorem. -/
@[simp]
theorem ZMod.pow_totient {n : ℕ} (x : (ZMod n)ˣ) : x ^ φ n = 1 := by
  cases n
  · rw [Nat.totient_zero, pow_zero]
  · 

Proof state:
case succ
K : Type u_1
R : Type u_2
n✝ : ℕ
x : (ZMod (Nat.succ n✝))ˣ
⊢ x ^ φ (Nat.succ n✝) = 1

Next tactic:
rw [← card_units_eq_totient, pow_card_eq_one]
/-- The **Fermat-Euler totient theorem**. `ZMod.pow_totient` is an alternative statement
  of the same theorem. -/
theorem Nat.ModEq.pow_totient {x n : ℕ} (h : Nat.Coprime x n) : x ^ φ n ≡ 1 [MOD n] := by
  

Proof state:
K : Type u_1
R : Type u_2
x n : ℕ
h : Coprime x n
⊢ x ^ φ n ≡ 1 [MOD n]

Next tactic:
rw [← ZMod.eq_iff_modEq_nat]
/-- The **Fermat-Euler totient theorem**. `ZMod.pow_totient` is an alternative statement
  of the same theorem. -/
theorem Nat.ModEq.pow_totient {x n : ℕ} (h : Nat.Coprime x n) : x ^ φ n ≡ 1 [MOD n] := by
  rw [← ZMod.eq_iff_modEq_nat]
  

Proof state:
K : Type u_1
R : Type u_2
x n : ℕ
h : Coprime x n
⊢ ↑(x ^ φ n) = ↑1

Next tactic:
let x' : Units (ZMod n) := ZMod.unitOfCoprime _ h
/-- The **Fermat-Euler totient theorem**. `ZMod.pow_totient` is an alternative statement
  of the same theorem. -/
theorem Nat.ModEq.pow_totient {x n : ℕ} (h : Nat.Coprime x n) : x ^ φ n ≡ 1 [MOD n] := by
  rw [← ZMod.eq_iff_modEq_nat]
  let x' : Units (ZMod n) := ZMod.unitOfCoprime _ h
  

Proof state:
K : Type u_1
R : Type u_2
x n : ℕ
h : Coprime x n
x' : (ZMod n)ˣ := unitOfCoprime x h
⊢ ↑(x ^ φ n) = ↑1

Next tactic:
have := ZMod.pow_totient x'
/-- The **Fermat-Euler totient theorem**. `ZMod.pow_totient` is an alternative statement
  of the same theorem. -/
theorem Nat.ModEq.pow_totient {x n : ℕ} (h : Nat.Coprime x n) : x ^ φ n ≡ 1 [MOD n] := by
  rw [← ZMod.eq_iff_modEq_nat]
  let x' : Units (ZMod n) := ZMod.unitOfCoprime _ h
  have := ZMod.pow_totient x'
  

Proof state:
K : Type u_1
R : Type u_2
x n : ℕ
h : Coprime x n
x' : (ZMod n)ˣ := unitOfCoprime x h
this : x' ^ φ n = 1
⊢ ↑(x ^ φ n) = ↑1

Next tactic:
apply_fun ((fun (x : Units (ZMod n)) => (x : ZMod n)) : Units (ZMod n) → ZMod n) at this
/-- The **Fermat-Euler totient theorem**. `ZMod.pow_totient` is an alternative statement
  of the same theorem. -/
theorem Nat.ModEq.pow_totient {x n : ℕ} (h : Nat.Coprime x n) : x ^ φ n ≡ 1 [MOD n] := by
  rw [← ZMod.eq_iff_modEq_nat]
  let x' : Units (ZMod n) := ZMod.unitOfCoprime _ h
  have := ZMod.pow_totient x'
  apply_fun ((fun (x : Units (ZMod n)) => (x : ZMod n)) : Units (ZMod n) → ZMod n) at this
  

Proof state:
K : Type u_1
R : Type u_2
x n : ℕ
h : Coprime x n
x' : (ZMod n)ˣ := unitOfCoprime x h
this : ↑(x' ^ φ n) = ↑1
⊢ ↑(x ^ φ n) = ↑1

Next tactic:
simpa only [Nat.succ_eq_add_one, Nat.cast_pow, Units.val_one, Nat.cast_one,
    coe_unitOfCoprime, Units.val_pow_eq_pow_val]
theorem card_eq_pow_finrank [Fintype V] : Fintype.card V = q ^ FiniteDimensional.finrank K V := by
  

Proof state:
K : Type u_1
R : Type u_2
V : Type u_3
inst✝⁴ : Fintype K
inst✝³ : DivisionRing K
inst✝² : AddCommGroup V
inst✝¹ : Module K V
inst✝ : Fintype V
⊢ Fintype.card V = q ^ FiniteDimensional.finrank K V

Next tactic:
let b := IsNoetherian.finsetBasis K V
theorem card_eq_pow_finrank [Fintype V] : Fintype.card V = q ^ FiniteDimensional.finrank K V := by
  let b := IsNoetherian.finsetBasis K V
  

Proof state:
K : Type u_1
R : Type u_2
V : Type u_3
inst✝⁴ : Fintype K
inst✝³ : DivisionRing K
inst✝² : AddCommGroup V
inst✝¹ : Module K V
inst✝ : Fintype V
b : Basis { x // x ∈ IsNoetherian.finsetBasisIndex K V } K V := IsNoetherian.finsetBasis K V
⊢ Fintype.card V = q ^ FiniteDimensional.finrank K V

Next tactic:
rw [Module.card_fintype b, ← FiniteDimensional.finrank_eq_card_basis b]
/-- A variation on Fermat's little theorem. See `ZMod.pow_card_sub_one_eq_one` -/
@[simp]
theorem pow_card {p : ℕ} [Fact p.Prime] (x : ZMod p) : x ^ p = x := by
  

Proof state:
K : Type u_1
R : Type u_2
p : ℕ
inst✝ : Fact (Nat.Prime p)
x : ZMod p
⊢ x ^ p = x

Next tactic:
have h := FiniteField.pow_card x
/-- A variation on Fermat's little theorem. See `ZMod.pow_card_sub_one_eq_one` -/
@[simp]
theorem pow_card {p : ℕ} [Fact p.Prime] (x : ZMod p) : x ^ p = x := by
  have h := FiniteField.pow_card x; 

Proof state:
K : Type u_1
R : Type u_2
p : ℕ
inst✝ : Fact (Nat.Prime p)
x : ZMod p
h : x ^ Fintype.card (ZMod p) = x
⊢ x ^ p = x

Next tactic:
rwa [ZMod.card p] at h
@[simp]
theorem pow_card_pow {n p : ℕ} [Fact p.Prime] (x : ZMod p) : x ^ p ^ n = x := by
  

Proof state:
K : Type u_1
R : Type u_2
n p : ℕ
inst✝ : Fact (Nat.Prime p)
x : ZMod p
⊢ x ^ p ^ n = x

Next tactic:
induction' n with n ih
@[simp]
theorem pow_card_pow {n p : ℕ} [Fact p.Prime] (x : ZMod p) : x ^ p ^ n = x := by
  induction' n with n ih
  · 

Proof state:
case zero
K : Type u_1
R : Type u_2
p : ℕ
inst✝ : Fact (Nat.Prime p)
x : ZMod p
⊢ x ^ p ^ Nat.zero = x

Next tactic:
simp
@[simp]
theorem pow_card_pow {n p : ℕ} [Fact p.Prime] (x : ZMod p) : x ^ p ^ n = x := by
  induction' n with n ih
  · simp
  · 

Proof state:
case succ
K : Type u_1
R : Type u_2
p : ℕ
inst✝ : Fact (Nat.Prime p)
x : ZMod p
n : ℕ
ih : x ^ p ^ n = x
⊢ x ^ p ^ Nat.succ n = x

Next tactic:
simp [pow_succ, pow_mul, ih, pow_card]
@[simp]
theorem frobenius_zmod (p : ℕ) [Fact p.Prime] : frobenius (ZMod p) p = RingHom.id _ := by
  

Proof state:
K : Type u_1
R : Type u_2
p : ℕ
inst✝ : Fact (Nat.Prime p)
⊢ frobenius (ZMod p) p = RingHom.id (ZMod p)

Next tactic:
ext a
@[simp]
theorem frobenius_zmod (p : ℕ) [Fact p.Prime] : frobenius (ZMod p) p = RingHom.id _ := by
  ext a
  

Proof state:
case a
K : Type u_1
R : Type u_2
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ZMod p
⊢ (frobenius (ZMod p) p) a = (RingHom.id (ZMod p)) a

Next tactic:
rw [frobenius_def, ZMod.pow_card, RingHom.id_apply]
theorem card_units (p : ℕ) [Fact p.Prime] : Fintype.card (ZMod p)ˣ = p - 1 := by
  

Proof state:
K : Type u_1
R : Type u_2
p : ℕ
inst✝ : Fact (Nat.Prime p)
⊢ Fintype.card (ZMod p)ˣ = p - 1

Next tactic:
rw [Fintype.card_units, card]
/-- **Fermat's Little Theorem**: for every unit `a` of `ZMod p`, we have `a ^ (p - 1) = 1`. -/
theorem units_pow_card_sub_one_eq_one (p : ℕ) [Fact p.Prime] (a : (ZMod p)ˣ) : a ^ (p - 1) = 1 := by
  

Proof state:
K : Type u_1
R : Type u_2
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : (ZMod p)ˣ
⊢ a ^ (p - 1) = 1

Next tactic:
rw [← card_units p, pow_card_eq_one]
/-- **Fermat's Little Theorem**: for all nonzero `a : ZMod p`, we have `a ^ (p - 1) = 1`. -/
theorem pow_card_sub_one_eq_one {p : ℕ} [Fact p.Prime] {a : ZMod p} (ha : a ≠ 0) :
    a ^ (p - 1) = 1 := by
    

Proof state:
K : Type u_1
R : Type u_2
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ZMod p
ha : a ≠ 0
⊢ a ^ (p - 1) = 1

Next tactic:
have h := FiniteField.pow_card_sub_one_eq_one a ha
/-- **Fermat's Little Theorem**: for all nonzero `a : ZMod p`, we have `a ^ (p - 1) = 1`. -/
theorem pow_card_sub_one_eq_one {p : ℕ} [Fact p.Prime] {a : ZMod p} (ha : a ≠ 0) :
    a ^ (p - 1) = 1 := by
    have h := FiniteField.pow_card_sub_one_eq_one a ha
    

Proof state:
K : Type u_1
R : Type u_2
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ZMod p
ha : a ≠ 0
h : a ^ (Fintype.card (ZMod p) - 1) = 1
⊢ a ^ (p - 1) = 1

Next tactic:
rwa [ZMod.card p] at h
theorem expand_card {p : ℕ} [Fact p.Prime] (f : Polynomial (ZMod p)) :
    expand (ZMod p) p f = f ^ p := by 

Proof state:
K : Type u_1
R : Type u_2
p : ℕ
inst✝ : Fact (Nat.Prime p)
f : (ZMod p)[X]
⊢ (expand (ZMod p) p) f = f ^ p

Next tactic:
have h := FiniteField.expand_card f
theorem expand_card {p : ℕ} [Fact p.Prime] (f : Polynomial (ZMod p)) :
    expand (ZMod p) p f = f ^ p := by have h := FiniteField.expand_card f; 

Proof state:
K : Type u_1
R : Type u_2
p : ℕ
inst✝ : Fact (Nat.Prime p)
f : (ZMod p)[X]
h : (expand (ZMod p) (Fintype.card (ZMod p))) f = f ^ Fintype.card (ZMod p)
⊢ (expand (ZMod p) p) f = f ^ p

Next tactic:
rwa [ZMod.card p] at h
/-- **Fermat's Little Theorem**: for all `a : ℤ` coprime to `p`, we have
`a ^ (p - 1) ≡ 1 [ZMOD p]`. -/
theorem Int.ModEq.pow_card_sub_one_eq_one {p : ℕ} (hp : Nat.Prime p) {n : ℤ} (hpn : IsCoprime n p) :
    n ^ (p - 1) ≡ 1 [ZMOD p] := by
  

Proof state:
K : Type u_1
R : Type u_2
p : ℕ
hp : Nat.Prime p
n : ℤ
hpn : IsCoprime n ↑p
⊢ n ^ (p - 1) ≡ 1 [ZMOD ↑p]

Next tactic:
haveI : Fact p.Prime := ⟨hp⟩
/-- **Fermat's Little Theorem**: for all `a : ℤ` coprime to `p`, we have
`a ^ (p - 1) ≡ 1 [ZMOD p]`. -/
theorem Int.ModEq.pow_card_sub_one_eq_one {p : ℕ} (hp : Nat.Prime p) {n : ℤ} (hpn : IsCoprime n p) :
    n ^ (p - 1) ≡ 1 [ZMOD p] := by
  haveI : Fact p.Prime := ⟨hp⟩
  

Proof state:
K : Type u_1
R : Type u_2
p : ℕ
hp : Nat.Prime p
n : ℤ
hpn : IsCoprime n ↑p
this : Fact (Nat.Prime p)
⊢ n ^ (p - 1) ≡ 1 [ZMOD ↑p]

Next tactic:
have : ¬(n : ZMod p) = 0 := by
    rw [CharP.int_cast_eq_zero_iff _ p, ← (Nat.prime_iff_prime_int.mp hp).coprime_iff_not_dvd]
    · exact hpn.symm
/-- **Fermat's Little Theorem**: for all `a : ℤ` coprime to `p`, we have
`a ^ (p - 1) ≡ 1 [ZMOD p]`. -/
theorem Int.ModEq.pow_card_sub_one_eq_one {p : ℕ} (hp : Nat.Prime p) {n : ℤ} (hpn : IsCoprime n p) :
    n ^ (p - 1) ≡ 1 [ZMOD p] := by
  haveI : Fact p.Prime := ⟨hp⟩
  have : ¬(n : ZMod p) = 0 := by
    

Proof state:
K : Type u_1
R : Type u_2
p : ℕ
hp : Nat.Prime p
n : ℤ
hpn : IsCoprime n ↑p
this : Fact (Nat.Prime p)
⊢ ¬↑n = 0

Next tactic:
rw [CharP.int_cast_eq_zero_iff _ p, ← (Nat.prime_iff_prime_int.mp hp).coprime_iff_not_dvd]
/-- **Fermat's Little Theorem**: for all `a : ℤ` coprime to `p`, we have
`a ^ (p - 1) ≡ 1 [ZMOD p]`. -/
theorem Int.ModEq.pow_card_sub_one_eq_one {p : ℕ} (hp : Nat.Prime p) {n : ℤ} (hpn : IsCoprime n p) :
    n ^ (p - 1) ≡ 1 [ZMOD p] := by
  haveI : Fact p.Prime := ⟨hp⟩
  have : ¬(n : ZMod p) = 0 := by
    rw [CharP.int_cast_eq_zero_iff _ p, ← (Nat.prime_iff_prime_int.mp hp).coprime_iff_not_dvd]
    · 

Proof state:
K : Type u_1
R : Type u_2
p : ℕ
hp : Nat.Prime p
n : ℤ
hpn : IsCoprime n ↑p
this : Fact (Nat.Prime p)
⊢ IsCoprime (↑p) n

Next tactic:
exact hpn.symm
/-- **Fermat's Little Theorem**: for all `a : ℤ` coprime to `p`, we have
`a ^ (p - 1) ≡ 1 [ZMOD p]`. -/
theorem Int.ModEq.pow_card_sub_one_eq_one {p : ℕ} (hp : Nat.Prime p) {n : ℤ} (hpn : IsCoprime n p) :
    n ^ (p - 1) ≡ 1 [ZMOD p] := by
  haveI : Fact p.Prime := ⟨hp⟩
  have : ¬(n : ZMod p) = 0 := by
    rw [CharP.int_cast_eq_zero_iff _ p, ← (Nat.prime_iff_prime_int.mp hp).coprime_iff_not_dvd]
    · exact hpn.symm
  

Proof state:
K : Type u_1
R : Type u_2
p : ℕ
hp : Nat.Prime p
n : ℤ
hpn : IsCoprime n ↑p
this✝ : Fact (Nat.Prime p)
this : ¬↑n = 0
⊢ n ^ (p - 1) ≡ 1 [ZMOD ↑p]

Next tactic:
simpa [← ZMod.int_cast_eq_int_cast_iff] using ZMod.pow_card_sub_one_eq_one this
/-- In a finite field of odd characteristic, not every element is a square. -/
theorem exists_nonsquare (hF : ringChar F ≠ 2) : ∃ a : F, ¬IsSquare a := by
  -- Idea: the squaring map on `F` is not injective, hence not surjective
  

Proof state:
K : Type u_1
R : Type u_2
F : Type u_3
inst✝¹ : Field F
inst✝ : Finite F
hF : ringChar F ≠ 2
⊢ ∃ a, ¬IsSquare a

Next tactic:
let sq : F → F := fun x => x ^ 2
/-- In a finite field of odd characteristic, not every element is a square. -/
theorem exists_nonsquare (hF : ringChar F ≠ 2) : ∃ a : F, ¬IsSquare a := by
  -- Idea: the squaring map on `F` is not injective, hence not surjective
  let sq : F → F := fun x => x ^ 2
  

Proof state:
K : Type u_1
R : Type u_2
F : Type u_3
inst✝¹ : Field F
inst✝ : Finite F
hF : ringChar F ≠ 2
sq : F → F := fun x => x ^ 2
⊢ ∃ a, ¬IsSquare a

Next tactic:
have h : ¬Function.Injective sq := by
    simp only [Function.Injective, not_forall, exists_prop]
    refine' ⟨-1, 1, _, Ring.neg_one_ne_one_of_char_ne_two hF⟩
    simp only [one_pow, neg_one_sq]
/-- In a finite field of odd characteristic, not every element is a square. -/
theorem exists_nonsquare (hF : ringChar F ≠ 2) : ∃ a : F, ¬IsSquare a := by
  -- Idea: the squaring map on `F` is not injective, hence not surjective
  let sq : F → F := fun x => x ^ 2
  have h : ¬Function.Injective sq := by
    

Proof state:
K : Type u_1
R : Type u_2
F : Type u_3
inst✝¹ : Field F
inst✝ : Finite F
hF : ringChar F ≠ 2
sq : F → F := fun x => x ^ 2
⊢ ¬Function.Injective sq

Next tactic:
simp only [Function.Injective, not_forall, exists_prop]
/-- In a finite field of odd characteristic, not every element is a square. -/
theorem exists_nonsquare (hF : ringChar F ≠ 2) : ∃ a : F, ¬IsSquare a := by
  -- Idea: the squaring map on `F` is not injective, hence not surjective
  let sq : F → F := fun x => x ^ 2
  have h : ¬Function.Injective sq := by
    simp only [Function.Injective, not_forall, exists_prop]
    

Proof state:
K : Type u_1
R : Type u_2
F : Type u_3
inst✝¹ : Field F
inst✝ : Finite F
hF : ringChar F ≠ 2
sq : F → F := fun x => x ^ 2
⊢ ∃ x x_1, x ^ 2 = x_1 ^ 2 ∧ ¬x = x_1

Next tactic:
refine' ⟨-1, 1, _, Ring.neg_one_ne_one_of_char_ne_two hF⟩
/-- In a finite field of odd characteristic, not every element is a square. -/
theorem exists_nonsquare (hF : ringChar F ≠ 2) : ∃ a : F, ¬IsSquare a := by
  -- Idea: the squaring map on `F` is not injective, hence not surjective
  let sq : F → F := fun x => x ^ 2
  have h : ¬Function.Injective sq := by
    simp only [Function.Injective, not_forall, exists_prop]
    refine' ⟨-1, 1, _, Ring.neg_one_ne_one_of_char_ne_two hF⟩
    

Proof state:
K : Type u_1
R : Type u_2
F : Type u_3
inst✝¹ : Field F
inst✝ : Finite F
hF : ringChar F ≠ 2
sq : F → F := fun x => x ^ 2
⊢ (-1) ^ 2 = 1 ^ 2

Next tactic:
simp only [one_pow, neg_one_sq]
/-- In a finite field of odd characteristic, not every element is a square. -/
theorem exists_nonsquare (hF : ringChar F ≠ 2) : ∃ a : F, ¬IsSquare a := by
  -- Idea: the squaring map on `F` is not injective, hence not surjective
  let sq : F → F := fun x => x ^ 2
  have h : ¬Function.Injective sq := by
    simp only [Function.Injective, not_forall, exists_prop]
    refine' ⟨-1, 1, _, Ring.neg_one_ne_one_of_char_ne_two hF⟩
    simp only [one_pow, neg_one_sq]
  

Proof state:
K : Type u_1
R : Type u_2
F : Type u_3
inst✝¹ : Field F
inst✝ : Finite F
hF : ringChar F ≠ 2
sq : F → F := fun x => x ^ 2
h : ¬Function.Injective sq
⊢ ∃ a, ¬IsSquare a

Next tactic:
rw [Finite.injective_iff_surjective] at h
/-- In a finite field of odd characteristic, not every element is a square. -/
theorem exists_nonsquare (hF : ringChar F ≠ 2) : ∃ a : F, ¬IsSquare a := by
  -- Idea: the squaring map on `F` is not injective, hence not surjective
  let sq : F → F := fun x => x ^ 2
  have h : ¬Function.Injective sq := by
    simp only [Function.Injective, not_forall, exists_prop]
    refine' ⟨-1, 1, _, Ring.neg_one_ne_one_of_char_ne_two hF⟩
    simp only [one_pow, neg_one_sq]
  rw [Finite.injective_iff_surjective] at h
  -- sq not surjective
  

Proof state:
K : Type u_1
R : Type u_2
F : Type u_3
inst✝¹ : Field F
inst✝ : Finite F
hF : ringChar F ≠ 2
sq : F → F := fun x => x ^ 2
h : ¬Function.Surjective sq
⊢ ∃ a, ¬IsSquare a

Next tactic:
simp_rw [IsSquare, ← pow_two, @eq_comm _ _ (_ ^ 2)]
/-- In a finite field of odd characteristic, not every element is a square. -/
theorem exists_nonsquare (hF : ringChar F ≠ 2) : ∃ a : F, ¬IsSquare a := by
  -- Idea: the squaring map on `F` is not injective, hence not surjective
  let sq : F → F := fun x => x ^ 2
  have h : ¬Function.Injective sq := by
    simp only [Function.Injective, not_forall, exists_prop]
    refine' ⟨-1, 1, _, Ring.neg_one_ne_one_of_char_ne_two hF⟩
    simp only [one_pow, neg_one_sq]
  rw [Finite.injective_iff_surjective] at h
  -- sq not surjective
  simp_rw [IsSquare, ← pow_two, @eq_comm _ _ (_ ^ 2)]
  

Proof state:
K : Type u_1
R : Type u_2
F : Type u_3
inst✝¹ : Field F
inst✝ : Finite F
hF : ringChar F ≠ 2
sq : F → F := fun x => x ^ 2
h : ¬Function.Surjective sq
⊢ ∃ a, ¬∃ r, r ^ 2 = a

Next tactic:
unfold Function.Surjective at h
/-- In a finite field of odd characteristic, not every element is a square. -/
theorem exists_nonsquare (hF : ringChar F ≠ 2) : ∃ a : F, ¬IsSquare a := by
  -- Idea: the squaring map on `F` is not injective, hence not surjective
  let sq : F → F := fun x => x ^ 2
  have h : ¬Function.Injective sq := by
    simp only [Function.Injective, not_forall, exists_prop]
    refine' ⟨-1, 1, _, Ring.neg_one_ne_one_of_char_ne_two hF⟩
    simp only [one_pow, neg_one_sq]
  rw [Finite.injective_iff_surjective] at h
  -- sq not surjective
  simp_rw [IsSquare, ← pow_two, @eq_comm _ _ (_ ^ 2)]
  unfold Function.Surjective at h
  

Proof state:
K : Type u_1
R : Type u_2
F : Type u_3
inst✝¹ : Field F
inst✝ : Finite F
hF : ringChar F ≠ 2
sq : F → F := fun x => x ^ 2
h : ¬∀ (b : F), ∃ a, sq a = b
⊢ ∃ a, ¬∃ r, r ^ 2 = a

Next tactic:
push_neg at h ⊢
/-- In a finite field of odd characteristic, not every element is a square. -/
theorem exists_nonsquare (hF : ringChar F ≠ 2) : ∃ a : F, ¬IsSquare a := by
  -- Idea: the squaring map on `F` is not injective, hence not surjective
  let sq : F → F := fun x => x ^ 2
  have h : ¬Function.Injective sq := by
    simp only [Function.Injective, not_forall, exists_prop]
    refine' ⟨-1, 1, _, Ring.neg_one_ne_one_of_char_ne_two hF⟩
    simp only [one_pow, neg_one_sq]
  rw [Finite.injective_iff_surjective] at h
  -- sq not surjective
  simp_rw [IsSquare, ← pow_two, @eq_comm _ _ (_ ^ 2)]
  unfold Function.Surjective at h
  push_neg at h ⊢
  

Proof state:
K : Type u_1
R : Type u_2
F : Type u_3
inst✝¹ : Field F
inst✝ : Finite F
hF : ringChar F ≠ 2
sq : F → F := fun x => x ^ 2
h : ∃ b, ∀ (a : F), sq a ≠ b
⊢ ∃ a, ∀ (r : F), r ^ 2 ≠ a

Next tactic:
exact h