l3lab/ntp-mathlib huggingface dataset:
/-- If `1 < k` then `(∑ i in range k, ζ ^ i) = 0`. -/
theorem geom_sum_eq_zero [IsDomain R] {ζ : R} (hζ : IsPrimitiveRoot ζ k) (hk : 1 < k) :
    ∑ i in range k, ζ ^ i = 0 := by
  refine' eq_zero_of_ne_zero_of_mul_left_eq_zero (sub_ne_zero_of_ne (hζ.ne_one hk).symm) _
  

Proof state:
M : Type u_1
N : Type u_2
G : Type u_3
R : Type u_4
S : Type u_5
F : Type u_6
inst✝⁴ : CommMonoid M
inst✝³ : CommMonoid N
inst✝² : DivisionCommMonoid G
k l : ℕ
inst✝¹ : CommRing R
ζ✝ : Rˣ
h : IsPrimitiveRoot ζ✝ k
inst✝ : IsDomain R
ζ : R
hζ : IsPrimitiveRoot ζ k
hk : 1 < k
⊢ (1 - ζ) * ∑ i in range k, ζ ^ i = 0

Next tactic:
rw [mul_neg_geom_sum, hζ.pow_eq_one, sub_self]
/-- If `1 < k`, then `ζ ^ k.pred = -(∑ i in range k.pred, ζ ^ i)`. -/
theorem pow_sub_one_eq [IsDomain R] {ζ : R} (hζ : IsPrimitiveRoot ζ k) (hk : 1 < k) :
    ζ ^ k.pred = -∑ i in range k.pred, ζ ^ i := by
  

Proof state:
M : Type u_1
N : Type u_2
G : Type u_3
R : Type u_4
S : Type u_5
F : Type u_6
inst✝⁴ : CommMonoid M
inst✝³ : CommMonoid N
inst✝² : DivisionCommMonoid G
k l : ℕ
inst✝¹ : CommRing R
ζ✝ : Rˣ
h : IsPrimitiveRoot ζ✝ k
inst✝ : IsDomain R
ζ : R
hζ : IsPrimitiveRoot ζ k
hk : 1 < k
⊢ ζ ^ Nat.pred k = -∑ i in range (Nat.pred k), ζ ^ i

Next tactic:
rw [eq_neg_iff_add_eq_zero, add_comm, ← sum_range_succ, ← Nat.succ_eq_add_one,
    Nat.succ_pred_eq_of_pos (pos_of_gt hk), hζ.geom_sum_eq_zero hk]
/-- The (additive) monoid equivalence between `ZMod k`
and the powers of a primitive root of unity `ζ`. -/
def zmodEquivZPowers (h : IsPrimitiveRoot ζ k) : ZMod k ≃+ Additive (Subgroup.zpowers ζ) :=
  AddEquiv.ofBijective
    (AddMonoidHom.liftOfRightInverse (Int.castAddHom <| ZMod k) _ ZMod.int_cast_rightInverse
      ⟨{  toFun := fun i => Additive.ofMul (⟨_, i, rfl⟩ : Subgroup.zpowers ζ)
          map_zero' := by 

Proof state:
M : Type u_1
N : Type u_2
G : Type u_3
R : Type u_4
S : Type u_5
F : Type u_6
inst✝³ : CommMonoid M
inst✝² : CommMonoid N
inst✝¹ : DivisionCommMonoid G
k l : ℕ
inst✝ : CommRing R
ζ : Rˣ
h✝ h : IsPrimitiveRoot ζ k
⊢ (fun i =>
        Additive.ofMul { val := (fun x => ζ ^ x) i, property := (_ : ∃ y, (fun x => ζ ^ x) y = (fun x => ζ ^ x) i) })
      0 =
    0

Next tactic:
simp only [zpow_zero]
/-- The (additive) monoid equivalence between `ZMod k`
and the powers of a primitive root of unity `ζ`. -/
def zmodEquivZPowers (h : IsPrimitiveRoot ζ k) : ZMod k ≃+ Additive (Subgroup.zpowers ζ) :=
  AddEquiv.ofBijective
    (AddMonoidHom.liftOfRightInverse (Int.castAddHom <| ZMod k) _ ZMod.int_cast_rightInverse
      ⟨{  toFun := fun i => Additive.ofMul (⟨_, i, rfl⟩ : Subgroup.zpowers ζ)
          map_zero' := by simp only [zpow_zero]; 

Proof state:
M : Type u_1
N : Type u_2
G : Type u_3
R : Type u_4
S : Type u_5
F : Type u_6
inst✝³ : CommMonoid M
inst✝² : CommMonoid N
inst✝¹ : DivisionCommMonoid G
k l : ℕ
inst✝ : CommRing R
ζ : Rˣ
h✝ h : IsPrimitiveRoot ζ k
⊢ Additive.ofMul { val := 1, property := (_ : (fun x => x ∈ Subgroup.zpowers ζ) 1) } = 0

Next tactic:
rfl
/-- The (additive) monoid equivalence between `ZMod k`
and the powers of a primitive root of unity `ζ`. -/
def zmodEquivZPowers (h : IsPrimitiveRoot ζ k) : ZMod k ≃+ Additive (Subgroup.zpowers ζ) :=
  AddEquiv.ofBijective
    (AddMonoidHom.liftOfRightInverse (Int.castAddHom <| ZMod k) _ ZMod.int_cast_rightInverse
      ⟨{  toFun := fun i => Additive.ofMul (⟨_, i, rfl⟩ : Subgroup.zpowers ζ)
          map_zero' := by simp only [zpow_zero]; rfl
          map_add' := by 

Proof state:
M : Type u_1
N : Type u_2
G : Type u_3
R : Type u_4
S : Type u_5
F : Type u_6
inst✝³ : CommMonoid M
inst✝² : CommMonoid N
inst✝¹ : DivisionCommMonoid G
k l : ℕ
inst✝ : CommRing R
ζ : Rˣ
h✝ h : IsPrimitiveRoot ζ k
⊢ ∀ (x y : ℤ),
    ZeroHom.toFun
        {
          toFun := fun i =>
            Additive.ofMul
              { val := (fun x => ζ ^ x) i, property := (_ : ∃ y, (fun x => ζ ^ x) y = (fun x => ζ ^ x) i) },
          map_zero' :=
            (_ :
              (fun i =>
                    Additive.ofMul
                      { val := (fun x => ζ ^ x) i, property := (_ : ∃ y, (fun x => ζ ^ x) y = (fun x => ζ ^ x) i) })
                  0 =
                0) }
        (x + y) =
      ZeroHom.toFun
          {
            toFun := fun i =>
              Additive.ofMul
                { val := (fun x => ζ ^ x) i, property := (_ : ∃ y, (fun x => ζ ^ x) y = (fun x => ζ ^ x) i) },
            map_zero' :=
              (_ :
                (fun i =>
                      Additive.ofMul
                        { val := (fun x => ζ ^ x) i, property := (_ : ∃ y, (fun x => ζ ^ x) y = (fun x => ζ ^ x) i) })
                    0 =
                  0) }
          x +
        ZeroHom.toFun
          {
            toFun := fun i =>
              Additive.ofMul
                { val := (fun x => ζ ^ x) i, property := (_ : ∃ y, (fun x => ζ ^ x) y = (fun x => ζ ^ x) i) },
            map_zero' :=
              (_ :
                (fun i =>
                      Additive.ofMul
                        { val := (fun x => ζ ^ x) i, property := (_ : ∃ y, (fun x => ζ ^ x) y = (fun x => ζ ^ x) i) })
                    0 =
                  0) }
          y

Next tactic:
intro i j
/-- The (additive) monoid equivalence between `ZMod k`
and the powers of a primitive root of unity `ζ`. -/
def zmodEquivZPowers (h : IsPrimitiveRoot ζ k) : ZMod k ≃+ Additive (Subgroup.zpowers ζ) :=
  AddEquiv.ofBijective
    (AddMonoidHom.liftOfRightInverse (Int.castAddHom <| ZMod k) _ ZMod.int_cast_rightInverse
      ⟨{  toFun := fun i => Additive.ofMul (⟨_, i, rfl⟩ : Subgroup.zpowers ζ)
          map_zero' := by simp only [zpow_zero]; rfl
          map_add' := by intro i j; 

Proof state:
M : Type u_1
N : Type u_2
G : Type u_3
R : Type u_4
S : Type u_5
F : Type u_6
inst✝³ : CommMonoid M
inst✝² : CommMonoid N
inst✝¹ : DivisionCommMonoid G
k l : ℕ
inst✝ : CommRing R
ζ : Rˣ
h✝ h : IsPrimitiveRoot ζ k
i j : ℤ
⊢ ZeroHom.toFun
      {
        toFun := fun i =>
          Additive.ofMul { val := (fun x => ζ ^ x) i, property := (_ : ∃ y, (fun x => ζ ^ x) y = (fun x => ζ ^ x) i) },
        map_zero' :=
          (_ :
            (fun i =>
                  Additive.ofMul
                    { val := (fun x => ζ ^ x) i, property := (_ : ∃ y, (fun x => ζ ^ x) y = (fun x => ζ ^ x) i) })
                0 =
              0) }
      (i + j) =
    ZeroHom.toFun
        {
          toFun := fun i =>
            Additive.ofMul
              { val := (fun x => ζ ^ x) i, property := (_ : ∃ y, (fun x => ζ ^ x) y = (fun x => ζ ^ x) i) },
          map_zero' :=
            (_ :
              (fun i =>
                    Additive.ofMul
                      { val := (fun x => ζ ^ x) i, property := (_ : ∃ y, (fun x => ζ ^ x) y = (fun x => ζ ^ x) i) })
                  0 =
                0) }
        i +
      ZeroHom.toFun
        {
          toFun := fun i =>
            Additive.ofMul
              { val := (fun x => ζ ^ x) i, property := (_ : ∃ y, (fun x => ζ ^ x) y = (fun x => ζ ^ x) i) },
          map_zero' :=
            (_ :
              (fun i =>
                    Additive.ofMul
                      { val := (fun x => ζ ^ x) i, property := (_ : ∃ y, (fun x => ζ ^ x) y = (fun x => ζ ^ x) i) })
                  0 =
                0) }
        j

Next tactic:
simp only [zpow_add]
/-- The (additive) monoid equivalence between `ZMod k`
and the powers of a primitive root of unity `ζ`. -/
def zmodEquivZPowers (h : IsPrimitiveRoot ζ k) : ZMod k ≃+ Additive (Subgroup.zpowers ζ) :=
  AddEquiv.ofBijective
    (AddMonoidHom.liftOfRightInverse (Int.castAddHom <| ZMod k) _ ZMod.int_cast_rightInverse
      ⟨{  toFun := fun i => Additive.ofMul (⟨_, i, rfl⟩ : Subgroup.zpowers ζ)
          map_zero' := by simp only [zpow_zero]; rfl
          map_add' := by intro i j; simp only [zpow_add]; 

Proof state:
M : Type u_1
N : Type u_2
G : Type u_3
R : Type u_4
S : Type u_5
F : Type u_6
inst✝³ : CommMonoid M
inst✝² : CommMonoid N
inst✝¹ : DivisionCommMonoid G
k l : ℕ
inst✝ : CommRing R
ζ : Rˣ
h✝ h : IsPrimitiveRoot ζ k
i j : ℤ
⊢ Additive.ofMul { val := ζ ^ i * ζ ^ j, property := (_ : (fun x => x ∈ Subgroup.zpowers ζ) (ζ ^ i * ζ ^ j)) } =
    Additive.ofMul { val := ζ ^ i, property := (_ : ∃ y, (fun x => ζ ^ x) y = (fun x => ζ ^ x) i) } +
      Additive.ofMul { val := ζ ^ j, property := (_ : ∃ y, (fun x => ζ ^ x) y = (fun x => ζ ^ x) j) }

Next tactic:
rfl
/-- The (additive) monoid equivalence between `ZMod k`
and the powers of a primitive root of unity `ζ`. -/
def zmodEquivZPowers (h : IsPrimitiveRoot ζ k) : ZMod k ≃+ Additive (Subgroup.zpowers ζ) :=
  AddEquiv.ofBijective
    (AddMonoidHom.liftOfRightInverse (Int.castAddHom <| ZMod k) _ ZMod.int_cast_rightInverse
      ⟨{  toFun := fun i => Additive.ofMul (⟨_, i, rfl⟩ : Subgroup.zpowers ζ)
          map_zero' := by simp only [zpow_zero]; rfl
          map_add' := by intro i j; simp only [zpow_add]; rfl }, fun i hi => by
        simp only [AddMonoidHom.mem_ker, CharP.int_cast_eq_zero_iff (ZMod k) k, AddMonoidHom.coe_mk,
          Int.coe_castAddHom] at hi ⊢
        

Proof state:
M : Type u_1
N : Type u_2
G : Type u_3
R : Type u_4
S : Type u_5
F : Type u_6
inst✝³ : CommMonoid M
inst✝² : CommMonoid N
inst✝¹ : DivisionCommMonoid G
k l : ℕ
inst✝ : CommRing R
ζ : Rˣ
h✝ h : IsPrimitiveRoot ζ k
i : ℤ
hi : ↑k ∣ i
⊢ { toFun := fun i => Additive.ofMul { val := ζ ^ i, property := (_ : ∃ y, (fun x => ζ ^ x) y = (fun x => ζ ^ x) i) },
        map_zero' :=
          (_ :
            (fun i =>
                  Additive.ofMul
                    { val := (fun x => ζ ^ x) i, property := (_ : ∃ y, (fun x => ζ ^ x) y = (fun x => ζ ^ x) i) })
                0 =
              0) }
      i =
    0

Next tactic:
obtain ⟨i, rfl⟩ := hi
/-- The (additive) monoid equivalence between `ZMod k`
and the powers of a primitive root of unity `ζ`. -/
def zmodEquivZPowers (h : IsPrimitiveRoot ζ k) : ZMod k ≃+ Additive (Subgroup.zpowers ζ) :=
  AddEquiv.ofBijective
    (AddMonoidHom.liftOfRightInverse (Int.castAddHom <| ZMod k) _ ZMod.int_cast_rightInverse
      ⟨{  toFun := fun i => Additive.ofMul (⟨_, i, rfl⟩ : Subgroup.zpowers ζ)
          map_zero' := by simp only [zpow_zero]; rfl
          map_add' := by intro i j; simp only [zpow_add]; rfl }, fun i hi => by
        simp only [AddMonoidHom.mem_ker, CharP.int_cast_eq_zero_iff (ZMod k) k, AddMonoidHom.coe_mk,
          Int.coe_castAddHom] at hi ⊢
        obtain ⟨i, rfl⟩ := hi
        

Proof state:
case intro
M : Type u_1
N : Type u_2
G : Type u_3
R : Type u_4
S : Type u_5
F : Type u_6
inst✝³ : CommMonoid M
inst✝² : CommMonoid N
inst✝¹ : DivisionCommMonoid G
k l : ℕ
inst✝ : CommRing R
ζ : Rˣ
h✝ h : IsPrimitiveRoot ζ k
i : ℤ
⊢ { toFun := fun i => Additive.ofMul { val := ζ ^ i, property := (_ : ∃ y, (fun x => ζ ^ x) y = (fun x => ζ ^ x) i) },
        map_zero' :=
          (_ :
            (fun i =>
                  Additive.ofMul
                    { val := (fun x => ζ ^ x) i, property := (_ : ∃ y, (fun x => ζ ^ x) y = (fun x => ζ ^ x) i) })
                0 =
              0) }
      (↑k * i) =
    0

Next tactic:
simp [zpow_mul, h.pow_eq_one, one_zpow, zpow_ofNat]
@[simp]
theorem zmodEquivZPowers_apply_coe_int (i : ℤ) :
    h.zmodEquivZPowers i = Additive.ofMul (⟨ζ ^ i, i, rfl⟩ : Subgroup.zpowers ζ) := by
  

Proof state:
M : Type u_1
N : Type u_2
G : Type u_3
R : Type u_4
S : Type u_5
F : Type u_6
inst✝³ : CommMonoid M
inst✝² : CommMonoid N
inst✝¹ : DivisionCommMonoid G
k l : ℕ
inst✝ : CommRing R
ζ : Rˣ
h : IsPrimitiveRoot ζ k
i : ℤ
⊢ (zmodEquivZPowers h) ↑i = Additive.ofMul { val := ζ ^ i, property := (_ : ∃ y, (fun x => ζ ^ x) y = ζ ^ i) }

Next tactic:
rw [zmodEquivZPowers, AddEquiv.ofBijective_apply]
@[simp]
theorem zmodEquivZPowers_apply_coe_nat (i : ℕ) :
    h.zmodEquivZPowers i = Additive.ofMul (⟨ζ ^ i, i, rfl⟩ : Subgroup.zpowers ζ) := by
  

Proof state:
M : Type u_1
N : Type u_2
G : Type u_3
R : Type u_4
S : Type u_5
F : Type u_6
inst✝³ : CommMonoid M
inst✝² : CommMonoid N
inst✝¹ : DivisionCommMonoid G
k l : ℕ
inst✝ : CommRing R
ζ : Rˣ
h : IsPrimitiveRoot ζ k
i : ℕ
⊢ (zmodEquivZPowers h) ↑i = Additive.ofMul { val := ζ ^ i, property := (_ : ∃ y, (fun x => ζ ^ x) y = ζ ^ i) }

Next tactic:
have : (i : ZMod k) = (i : ℤ) := by norm_cast
@[simp]
theorem zmodEquivZPowers_apply_coe_nat (i : ℕ) :
    h.zmodEquivZPowers i = Additive.ofMul (⟨ζ ^ i, i, rfl⟩ : Subgroup.zpowers ζ) := by
  have : (i : ZMod k) = (i : ℤ) := by 

Proof state:
M : Type u_1
N : Type u_2
G : Type u_3
R : Type u_4
S : Type u_5
F : Type u_6
inst✝³ : CommMonoid M
inst✝² : CommMonoid N
inst✝¹ : DivisionCommMonoid G
k l : ℕ
inst✝ : CommRing R
ζ : Rˣ
h : IsPrimitiveRoot ζ k
i : ℕ
⊢ ↑i = ↑↑i

Next tactic:
norm_cast
@[simp]
theorem zmodEquivZPowers_apply_coe_nat (i : ℕ) :
    h.zmodEquivZPowers i = Additive.ofMul (⟨ζ ^ i, i, rfl⟩ : Subgroup.zpowers ζ) := by
  have : (i : ZMod k) = (i : ℤ) := by norm_cast
  

Proof state:
M : Type u_1
N : Type u_2
G : Type u_3
R : Type u_4
S : Type u_5
F : Type u_6
inst✝³ : CommMonoid M
inst✝² : CommMonoid N
inst✝¹ : DivisionCommMonoid G
k l : ℕ
inst✝ : CommRing R
ζ : Rˣ
h : IsPrimitiveRoot ζ k
i : ℕ
this : ↑i = ↑↑i
⊢ (zmodEquivZPowers h) ↑i = Additive.ofMul { val := ζ ^ i, property := (_ : ∃ y, (fun x => ζ ^ x) y = ζ ^ i) }

Next tactic:
simp only [this, zmodEquivZPowers_apply_coe_int, zpow_ofNat]
@[simp]
theorem zmodEquivZPowers_symm_apply_zpow (i : ℤ) :
    h.zmodEquivZPowers.symm (Additive.ofMul (⟨ζ ^ i, i, rfl⟩ : Subgroup.zpowers ζ)) = i := by
  

Proof state:
M : Type u_1
N : Type u_2
G : Type u_3
R : Type u_4
S : Type u_5
F : Type u_6
inst✝³ : CommMonoid M
inst✝² : CommMonoid N
inst✝¹ : DivisionCommMonoid G
k l : ℕ
inst✝ : CommRing R
ζ : Rˣ
h : IsPrimitiveRoot ζ k
i : ℤ
⊢ (AddEquiv.symm (zmodEquivZPowers h))
      (Additive.ofMul { val := ζ ^ i, property := (_ : ∃ y, (fun x => ζ ^ x) y = ζ ^ i) }) =
    ↑i

Next tactic:
rw [← h.zmodEquivZPowers.symm_apply_apply i, zmodEquivZPowers_apply_coe_int]
@[simp]
theorem zmodEquivZPowers_symm_apply_pow (i : ℕ) :
    h.zmodEquivZPowers.symm (Additive.ofMul (⟨ζ ^ i, i, rfl⟩ : Subgroup.zpowers ζ)) = i := by
  

Proof state:
M : Type u_1
N : Type u_2
G : Type u_3
R : Type u_4
S : Type u_5
F : Type u_6
inst✝³ : CommMonoid M
inst✝² : CommMonoid N
inst✝¹ : DivisionCommMonoid G
k l : ℕ
inst✝ : CommRing R
ζ : Rˣ
h : IsPrimitiveRoot ζ k
i : ℕ
⊢ (AddEquiv.symm (zmodEquivZPowers h))
      (Additive.ofMul { val := ζ ^ i, property := (_ : ∃ y, (fun x => ζ ^ x) y = ζ ^ i) }) =
    ↑i

Next tactic:
rw [← h.zmodEquivZPowers.symm_apply_apply i, zmodEquivZPowers_apply_coe_nat]
theorem zpowers_eq {k : ℕ+} {ζ : Rˣ} (h : IsPrimitiveRoot ζ k) :
    Subgroup.zpowers ζ = rootsOfUnity k R := by
  

Proof state:
M : Type u_1
N : Type u_2
G : Type u_3
R : Type u_4
S : Type u_5
F : Type u_6
inst✝⁴ : CommMonoid M
inst✝³ : CommMonoid N
inst✝² : DivisionCommMonoid G
k✝ l : ℕ
inst✝¹ : CommRing R
ζ✝ : Rˣ
h✝ : IsPrimitiveRoot ζ✝ k✝
inst✝ : IsDomain R
k : ℕ+
ζ : Rˣ
h : IsPrimitiveRoot ζ ↑k
⊢ Subgroup.zpowers ζ = rootsOfUnity k R

Next tactic:
apply SetLike.coe_injective
theorem zpowers_eq {k : ℕ+} {ζ : Rˣ} (h : IsPrimitiveRoot ζ k) :
    Subgroup.zpowers ζ = rootsOfUnity k R := by
  apply SetLike.coe_injective
  

Proof state:
case a
M : Type u_1
N : Type u_2
G : Type u_3
R : Type u_4
S : Type u_5
F : Type u_6
inst✝⁴ : CommMonoid M
inst✝³ : CommMonoid N
inst✝² : DivisionCommMonoid G
k✝ l : ℕ
inst✝¹ : CommRing R
ζ✝ : Rˣ
h✝ : IsPrimitiveRoot ζ✝ k✝
inst✝ : IsDomain R
k : ℕ+
ζ : Rˣ
h : IsPrimitiveRoot ζ ↑k
⊢ ↑(Subgroup.zpowers ζ) = ↑(rootsOfUnity k R)

Next tactic:
haveI F : Fintype (Subgroup.zpowers ζ) := Fintype.ofEquiv _ h.zmodEquivZPowers.toEquiv
theorem zpowers_eq {k : ℕ+} {ζ : Rˣ} (h : IsPrimitiveRoot ζ k) :
    Subgroup.zpowers ζ = rootsOfUnity k R := by
  apply SetLike.coe_injective
  haveI F : Fintype (Subgroup.zpowers ζ) := Fintype.ofEquiv _ h.zmodEquivZPowers.toEquiv
  

Proof state:
case a
M : Type u_1
N : Type u_2
G : Type u_3
R : Type u_4
S : Type u_5
F✝ : Type u_6
inst✝⁴ : CommMonoid M
inst✝³ : CommMonoid N
inst✝² : DivisionCommMonoid G
k✝ l : ℕ
inst✝¹ : CommRing R
ζ✝ : Rˣ
h✝ : IsPrimitiveRoot ζ✝ k✝
inst✝ : IsDomain R
k : ℕ+
ζ : Rˣ
h : IsPrimitiveRoot ζ ↑k
F : Fintype ↥(Subgroup.zpowers ζ)
⊢ ↑(Subgroup.zpowers ζ) = ↑(rootsOfUnity k R)

Next tactic:
refine'
    @Set.eq_of_subset_of_card_le Rˣ (Subgroup.zpowers ζ) (rootsOfUnity k R) F
      (rootsOfUnity.fintype R k)
      (Subgroup.zpowers_le_of_mem <| show ζ ∈ rootsOfUnity k R from h.pow_eq_one) _
theorem zpowers_eq {k : ℕ+} {ζ : Rˣ} (h : IsPrimitiveRoot ζ k) :
    Subgroup.zpowers ζ = rootsOfUnity k R := by
  apply SetLike.coe_injective
  haveI F : Fintype (Subgroup.zpowers ζ) := Fintype.ofEquiv _ h.zmodEquivZPowers.toEquiv
  refine'
    @Set.eq_of_subset_of_card_le Rˣ (Subgroup.zpowers ζ) (rootsOfUnity k R) F
      (rootsOfUnity.fintype R k)
      (Subgroup.zpowers_le_of_mem <| show ζ ∈ rootsOfUnity k R from h.pow_eq_one) _
  

Proof state:
case a
M : Type u_1
N : Type u_2
G : Type u_3
R : Type u_4
S : Type u_5
F✝ : Type u_6
inst✝⁴ : CommMonoid M
inst✝³ : CommMonoid N
inst✝² : DivisionCommMonoid G
k✝ l : ℕ
inst✝¹ : CommRing R
ζ✝ : Rˣ
h✝ : IsPrimitiveRoot ζ✝ k✝
inst✝ : IsDomain R
k : ℕ+
ζ : Rˣ
h : IsPrimitiveRoot ζ ↑k
F : Fintype ↥(Subgroup.zpowers ζ)
⊢ Fintype.card ↑↑(rootsOfUnity k R) ≤ Fintype.card ↑↑(Subgroup.zpowers ζ)

Next tactic:
calc
    Fintype.card (rootsOfUnity k R) ≤ k := card_rootsOfUnity R k
    _ = Fintype.card (ZMod k) := (ZMod.card k).symm
    _ = Fintype.card (Subgroup.zpowers ζ) := Fintype.card_congr h.zmodEquivZPowers.toEquiv
theorem eq_pow_of_mem_rootsOfUnity {k : ℕ+} {ζ ξ : Rˣ} (h : IsPrimitiveRoot ζ k)
    (hξ : ξ ∈ rootsOfUnity k R) : ∃ (i : ℕ), i < k ∧ ζ ^ i = ξ := by
  

Proof state:
M : Type u_1
N : Type u_2
G : Type u_3
R : Type u_4
S : Type u_5
F : Type u_6
inst✝⁴ : CommMonoid M
inst✝³ : CommMonoid N
inst✝² : DivisionCommMonoid G
k✝ l : ℕ
inst✝¹ : CommRing R
ζ✝ : Rˣ
h✝ : IsPrimitiveRoot ζ✝ k✝
inst✝ : IsDomain R
k : ℕ+
ζ ξ : Rˣ
h : IsPrimitiveRoot ζ ↑k
hξ : ξ ∈ rootsOfUnity k R
⊢ ∃ i < ↑k, ζ ^ i = ξ

Next tactic:
obtain ⟨n, rfl⟩ : ∃ n : ℤ, ζ ^ n = ξ := by rwa [← h.zpowers_eq] at hξ
theorem eq_pow_of_mem_rootsOfUnity {k : ℕ+} {ζ ξ : Rˣ} (h : IsPrimitiveRoot ζ k)
    (hξ : ξ ∈ rootsOfUnity k R) : ∃ (i : ℕ), i < k ∧ ζ ^ i = ξ := by
  obtain ⟨n, rfl⟩ : ∃ n : ℤ, ζ ^ n = ξ := by 

Proof state:
M : Type u_1
N : Type u_2
G : Type u_3
R : Type u_4
S : Type u_5
F : Type u_6
inst✝⁴ : CommMonoid M
inst✝³ : CommMonoid N
inst✝² : DivisionCommMonoid G
k✝ l : ℕ
inst✝¹ : CommRing R
ζ✝ : Rˣ
h✝ : IsPrimitiveRoot ζ✝ k✝
inst✝ : IsDomain R
k : ℕ+
ζ ξ : Rˣ
h : IsPrimitiveRoot ζ ↑k
hξ : ξ ∈ rootsOfUnity k R
⊢ ∃ n, ζ ^ n = ξ

Next tactic:
rwa [← h.zpowers_eq] at hξ
theorem eq_pow_of_mem_rootsOfUnity {k : ℕ+} {ζ ξ : Rˣ} (h : IsPrimitiveRoot ζ k)
    (hξ : ξ ∈ rootsOfUnity k R) : ∃ (i : ℕ), i < k ∧ ζ ^ i = ξ := by
  obtain ⟨n, rfl⟩ : ∃ n : ℤ, ζ ^ n = ξ := by rwa [← h.zpowers_eq] at hξ
  

Proof state:
case intro
M : Type u_1
N : Type u_2
G : Type u_3
R : Type u_4
S : Type u_5
F : Type u_6
inst✝⁴ : CommMonoid M
inst✝³ : CommMonoid N
inst✝² : DivisionCommMonoid G
k✝ l : ℕ
inst✝¹ : CommRing R
ζ✝ : Rˣ
h✝ : IsPrimitiveRoot ζ✝ k✝
inst✝ : IsDomain R
k : ℕ+
ζ : Rˣ
h : IsPrimitiveRoot ζ ↑k
n : ℤ
hξ : ζ ^ n ∈ rootsOfUnity k R
⊢ ∃ i < ↑k, ζ ^ i = ζ ^ n

Next tactic:
have hk0 : (0 : ℤ) < k := mod_cast k.pos
theorem eq_pow_of_mem_rootsOfUnity {k : ℕ+} {ζ ξ : Rˣ} (h : IsPrimitiveRoot ζ k)
    (hξ : ξ ∈ rootsOfUnity k R) : ∃ (i : ℕ), i < k ∧ ζ ^ i = ξ := by
  obtain ⟨n, rfl⟩ : ∃ n : ℤ, ζ ^ n = ξ := by rwa [← h.zpowers_eq] at hξ
  have hk0 : (0 : ℤ) < k := mod_cast k.pos
  

Proof state:
case intro
M : Type u_1
N : Type u_2
G : Type u_3
R : Type u_4
S : Type u_5
F : Type u_6
inst✝⁴ : CommMonoid M
inst✝³ : CommMonoid N
inst✝² : DivisionCommMonoid G
k✝ l : ℕ
inst✝¹ : CommRing R
ζ✝ : Rˣ
h✝ : IsPrimitiveRoot ζ✝ k✝
inst✝ : IsDomain R
k : ℕ+
ζ : Rˣ
h : IsPrimitiveRoot ζ ↑k
n : ℤ
hξ : ζ ^ n ∈ rootsOfUnity k R
hk0 : 0 < ↑↑k
⊢ ∃ i < ↑k, ζ ^ i = ζ ^ n

Next tactic:
let i := n % k
theorem eq_pow_of_mem_rootsOfUnity {k : ℕ+} {ζ ξ : Rˣ} (h : IsPrimitiveRoot ζ k)
    (hξ : ξ ∈ rootsOfUnity k R) : ∃ (i : ℕ), i < k ∧ ζ ^ i = ξ := by
  obtain ⟨n, rfl⟩ : ∃ n : ℤ, ζ ^ n = ξ := by rwa [← h.zpowers_eq] at hξ
  have hk0 : (0 : ℤ) < k := mod_cast k.pos
  let i := n % k
  

Proof state:
case intro
M : Type u_1
N : Type u_2
G : Type u_3
R : Type u_4
S : Type u_5
F : Type u_6
inst✝⁴ : CommMonoid M
inst✝³ : CommMonoid N
inst✝² : DivisionCommMonoid G
k✝ l : ℕ
inst✝¹ : CommRing R
ζ✝ : Rˣ
h✝ : IsPrimitiveRoot ζ✝ k✝
inst✝ : IsDomain R
k : ℕ+
ζ : Rˣ
h : IsPrimitiveRoot ζ ↑k
n : ℤ
hξ : ζ ^ n ∈ rootsOfUnity k R
hk0 : 0 < ↑↑k
i : ℤ := n % ↑↑k
⊢ ∃ i < ↑k, ζ ^ i = ζ ^ n

Next tactic:
have hi0 : 0 ≤ i := Int.emod_nonneg _ (ne_of_gt hk0)
theorem eq_pow_of_mem_rootsOfUnity {k : ℕ+} {ζ ξ : Rˣ} (h : IsPrimitiveRoot ζ k)
    (hξ : ξ ∈ rootsOfUnity k R) : ∃ (i : ℕ), i < k ∧ ζ ^ i = ξ := by
  obtain ⟨n, rfl⟩ : ∃ n : ℤ, ζ ^ n = ξ := by rwa [← h.zpowers_eq] at hξ
  have hk0 : (0 : ℤ) < k := mod_cast k.pos
  let i := n % k
  have hi0 : 0 ≤ i := Int.emod_nonneg _ (ne_of_gt hk0)
  

Proof state:
case intro
M : Type u_1
N : Type u_2
G : Type u_3
R : Type u_4
S : Type u_5
F : Type u_6
inst✝⁴ : CommMonoid M
inst✝³ : CommMonoid N
inst✝² : DivisionCommMonoid G
k✝ l : ℕ
inst✝¹ : CommRing R
ζ✝ : Rˣ
h✝ : IsPrimitiveRoot ζ✝ k✝
inst✝ : IsDomain R
k : ℕ+
ζ : Rˣ
h : IsPrimitiveRoot ζ ↑k
n : ℤ
hξ : ζ ^ n ∈ rootsOfUnity k R
hk0 : 0 < ↑↑k
i : ℤ := n % ↑↑k
hi0 : 0 ≤ i
⊢ ∃ i < ↑k, ζ ^ i = ζ ^ n

Next tactic:
lift i to ℕ using hi0 with i₀ hi₀
theorem eq_pow_of_mem_rootsOfUnity {k : ℕ+} {ζ ξ : Rˣ} (h : IsPrimitiveRoot ζ k)
    (hξ : ξ ∈ rootsOfUnity k R) : ∃ (i : ℕ), i < k ∧ ζ ^ i = ξ := by
  obtain ⟨n, rfl⟩ : ∃ n : ℤ, ζ ^ n = ξ := by rwa [← h.zpowers_eq] at hξ
  have hk0 : (0 : ℤ) < k := mod_cast k.pos
  let i := n % k
  have hi0 : 0 ≤ i := Int.emod_nonneg _ (ne_of_gt hk0)
  lift i to ℕ using hi0 with i₀ hi₀
  

Proof state:
case intro.intro
M : Type u_1
N : Type u_2
G : Type u_3
R : Type u_4
S : Type u_5
F : Type u_6
inst✝⁴ : CommMonoid M
inst✝³ : CommMonoid N
inst✝² : DivisionCommMonoid G
k✝ l : ℕ
inst✝¹ : CommRing R
ζ✝ : Rˣ
h✝ : IsPrimitiveRoot ζ✝ k✝
inst✝ : IsDomain R
k : ℕ+
ζ : Rˣ
h : IsPrimitiveRoot ζ ↑k
n : ℤ
hξ : ζ ^ n ∈ rootsOfUnity k R
hk0 : 0 < ↑↑k
i : ℤ := n % ↑↑k
i₀ : ℕ
hi₀ : ↑i₀ = i
⊢ ∃ i < ↑k, ζ ^ i = ζ ^ n

Next tactic:
refine' ⟨i₀, _, _⟩
theorem eq_pow_of_mem_rootsOfUnity {k : ℕ+} {ζ ξ : Rˣ} (h : IsPrimitiveRoot ζ k)
    (hξ : ξ ∈ rootsOfUnity k R) : ∃ (i : ℕ), i < k ∧ ζ ^ i = ξ := by
  obtain ⟨n, rfl⟩ : ∃ n : ℤ, ζ ^ n = ξ := by rwa [← h.zpowers_eq] at hξ
  have hk0 : (0 : ℤ) < k := mod_cast k.pos
  let i := n % k
  have hi0 : 0 ≤ i := Int.emod_nonneg _ (ne_of_gt hk0)
  lift i to ℕ using hi0 with i₀ hi₀
  refine' ⟨i₀, _, _⟩
  · 

Proof state:
case intro.intro.refine'_1
M : Type u_1
N : Type u_2
G : Type u_3
R : Type u_4
S : Type u_5
F : Type u_6
inst✝⁴ : CommMonoid M
inst✝³ : CommMonoid N
inst✝² : DivisionCommMonoid G
k✝ l : ℕ
inst✝¹ : CommRing R
ζ✝ : Rˣ
h✝ : IsPrimitiveRoot ζ✝ k✝
inst✝ : IsDomain R
k : ℕ+
ζ : Rˣ
h : IsPrimitiveRoot ζ ↑k
n : ℤ
hξ : ζ ^ n ∈ rootsOfUnity k R
hk0 : 0 < ↑↑k
i : ℤ := n % ↑↑k
i₀ : ℕ
hi₀ : ↑i₀ = i
⊢ i₀ < ↑k

Next tactic:
zify
theorem eq_pow_of_mem_rootsOfUnity {k : ℕ+} {ζ ξ : Rˣ} (h : IsPrimitiveRoot ζ k)
    (hξ : ξ ∈ rootsOfUnity k R) : ∃ (i : ℕ), i < k ∧ ζ ^ i = ξ := by
  obtain ⟨n, rfl⟩ : ∃ n : ℤ, ζ ^ n = ξ := by rwa [← h.zpowers_eq] at hξ
  have hk0 : (0 : ℤ) < k := mod_cast k.pos
  let i := n % k
  have hi0 : 0 ≤ i := Int.emod_nonneg _ (ne_of_gt hk0)
  lift i to ℕ using hi0 with i₀ hi₀
  refine' ⟨i₀, _, _⟩
  · zify; 

Proof state:
case intro.intro.refine'_1
M : Type u_1
N : Type u_2
G : Type u_3
R : Type u_4
S : Type u_5
F : Type u_6
inst✝⁴ : CommMonoid M
inst✝³ : CommMonoid N
inst✝² : DivisionCommMonoid G
k✝ l : ℕ
inst✝¹ : CommRing R
ζ✝ : Rˣ
h✝ : IsPrimitiveRoot ζ✝ k✝
inst✝ : IsDomain R
k : ℕ+
ζ : Rˣ
h : IsPrimitiveRoot ζ ↑k
n : ℤ
hξ : ζ ^ n ∈ rootsOfUnity k R
hk0 : 0 < ↑↑k
i : ℤ := n % ↑↑k
i₀ : ℕ
hi₀ : ↑i₀ = i
⊢ ↑i₀ < ↑↑k

Next tactic:
rw [hi₀]