[GOAL]
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 k : ℕ+
M : Type u_7
inst✝ : CommMonoid M
a✝ b✝ : Mˣ
x✝¹ : a✝ ∈ {ζ | ζ ^ ↑k = 1}
x✝ : b✝ ∈ {ζ | ζ ^ ↑k = 1}
⊢ a✝ * b✝ ∈ {ζ | ζ ^ ↑k = 1}
[PROOFSTEP]
simp_all only [Set.mem_setOf_eq, mul_pow, one_mul]
[GOAL]
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 k : ℕ+
M : Type u_7
inst✝ : CommMonoid M
x✝¹ : Mˣ
x✝ :
  x✝¹ ∈
    {
          toSubsemigroup :=
            { carrier := {ζ | ζ ^ ↑k = 1},
              mul_mem' := (_ : ∀ {a b : Mˣ}, a ∈ {ζ | ζ ^ ↑k = 1} → b ∈ {ζ | ζ ^ ↑k = 1} → (a * b) ^ ↑k = 1) },
          one_mem' := (_ : 1 ^ ↑k = 1) }.toSubsemigroup.carrier
⊢ x✝¹⁻¹ ∈
    {
          toSubsemigroup :=
            { carrier := {ζ | ζ ^ ↑k = 1},
              mul_mem' := (_ : ∀ {a b : Mˣ}, a ∈ {ζ | ζ ^ ↑k = 1} → b ∈ {ζ | ζ ^ ↑k = 1} → (a * b) ^ ↑k = 1) },
          one_mem' := (_ : 1 ^ ↑k = 1) }.toSubsemigroup.carrier
[PROOFSTEP]
simp_all only [Set.mem_setOf_eq, inv_pow, inv_one]
[GOAL]
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 k : ℕ+
ζ : Mˣ
⊢ ζ ∈ rootsOfUnity k M ↔ ↑ζ ^ ↑k = 1
[PROOFSTEP]
rw [mem_rootsOfUnity]
[GOAL]
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 k : ℕ+
ζ : Mˣ
⊢ ζ ^ ↑k = 1 ↔ ↑ζ ^ ↑k = 1
[PROOFSTEP]
norm_cast
[GOAL]
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 : ℕ+
h : k ∣ l
⊢ rootsOfUnity k M ≤ rootsOfUnity l M
[PROOFSTEP]
obtain ⟨d, rfl⟩ := h
[GOAL]
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 d : ℕ+
⊢ rootsOfUnity k M ≤ rootsOfUnity (k * d) M
[PROOFSTEP]
intro ζ h
[GOAL]
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 d : ℕ+
ζ : Mˣ
h : ζ ∈ rootsOfUnity k M
⊢ ζ ∈ rootsOfUnity (k * d) M
[PROOFSTEP]
simp_all only [mem_rootsOfUnity, PNat.mul_coe, pow_mul, one_pow]
[GOAL]
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 : ℕ+
f : Mˣ →* Nˣ
k : ℕ+
⊢ Subgroup.map f (rootsOfUnity k M) ≤ rootsOfUnity k N
[PROOFSTEP]
rintro _ ⟨ζ, h, rfl⟩
[GOAL]
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 : ℕ+
f : Mˣ →* Nˣ
k : ℕ+
ζ : Mˣ
h : ζ ∈ ↑(rootsOfUnity k M)
⊢ ↑f ζ ∈ rootsOfUnity k N
[PROOFSTEP]
simp_all only [← map_pow, mem_rootsOfUnity, SetLike.mem_coe, MonoidHom.map_one]
[GOAL]
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✝ : CommMonoid R
ζ : { x // x ∈ rootsOfUnity k R }
m : ℕ
⊢ ↑↑(ζ ^ m) = ↑↑ζ ^ m
[PROOFSTEP]
rw [Subgroup.coe_pow, Units.val_pow_eq_pow_val]
[GOAL]
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✝² : CommSemiring R
inst✝¹ : CommSemiring S
inst✝ : RingHomClass F R S
σ : F
n : ℕ+
ξ : { x // x ∈ rootsOfUnity n R }
⊢ ↑σ ↑↑ξ ^ ↑n = 1
[PROOFSTEP]
rw [← map_pow, ← Units.val_pow_eq_pow_val, show (ξ : Rˣ) ^ (n : ℕ) = 1 from ξ.2, Units.val_one, map_one σ]
[GOAL]
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✝² : CommSemiring R
inst✝¹ : CommSemiring S
inst✝ : RingHomClass F R S
σ : F
n : ℕ+
h : ∀ (ξ : { x // x ∈ rootsOfUnity n R }), ↑σ ↑↑ξ ^ ↑n = 1 :=
  fun ξ =>
    Eq.mpr (id (Eq.symm (map_pow σ ↑↑ξ ↑n) ▸ Eq.refl (↑σ ↑↑ξ ^ ↑n = 1)))
      (Eq.mpr (id (Eq.symm (Units.val_pow_eq_pow_val ↑ξ ↑n) ▸ Eq.refl (↑σ (↑↑ξ ^ ↑n) = 1)))
        (Eq.mpr
          (id
            ((let_fun this := ξ.property;
              this) ▸
              Eq.refl (↑σ ↑(↑ξ ^ ↑n) = 1)))
          (Eq.mpr (id (Units.val_one ▸ Eq.refl (↑σ ↑1 = 1)))
            (Eq.mpr (id (map_one σ ▸ Eq.refl (↑σ 1 = 1))) (Eq.refl 1)))))
ξ : { x // x ∈ rootsOfUnity n R }
⊢ unitOfInvertible (↑σ ↑↑ξ) ∈ rootsOfUnity n S
[PROOFSTEP]
ext
[GOAL]
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✝² : CommSemiring R
inst✝¹ : CommSemiring S
inst✝ : RingHomClass F R S
σ : F
n : ℕ+
h : ∀ (ξ : { x // x ∈ rootsOfUnity n R }), ↑σ ↑↑ξ ^ ↑n = 1 :=
  fun ξ =>
    Eq.mpr (id (Eq.symm (map_pow σ ↑↑ξ ↑n) ▸ Eq.refl (↑σ ↑↑ξ ^ ↑n = 1)))
      (Eq.mpr (id (Eq.symm (Units.val_pow_eq_pow_val ↑ξ ↑n) ▸ Eq.refl (↑σ (↑↑ξ ^ ↑n) = 1)))
        (Eq.mpr
          (id
            ((let_fun this := ξ.property;
              this) ▸
              Eq.refl (↑σ ↑(↑ξ ^ ↑n) = 1)))
          (Eq.mpr (id (Units.val_one ▸ Eq.refl (↑σ ↑1 = 1)))
            (Eq.mpr (id (map_one σ ▸ Eq.refl (↑σ 1 = 1))) (Eq.refl 1)))))
ξ : { x // x ∈ rootsOfUnity n R }
⊢ ↑(unitOfInvertible (↑σ ↑↑ξ) ^ ↑n) = ↑1
[PROOFSTEP]
rw [Units.val_pow_eq_pow_val]
[GOAL]
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✝² : CommSemiring R
inst✝¹ : CommSemiring S
inst✝ : RingHomClass F R S
σ : F
n : ℕ+
h : ∀ (ξ : { x // x ∈ rootsOfUnity n R }), ↑σ ↑↑ξ ^ ↑n = 1 :=
  fun ξ =>
    Eq.mpr (id (Eq.symm (map_pow σ ↑↑ξ ↑n) ▸ Eq.refl (↑σ ↑↑ξ ^ ↑n = 1)))
      (Eq.mpr (id (Eq.symm (Units.val_pow_eq_pow_val ↑ξ ↑n) ▸ Eq.refl (↑σ (↑↑ξ ^ ↑n) = 1)))
        (Eq.mpr
          (id
            ((let_fun this := ξ.property;
              this) ▸
              Eq.refl (↑σ ↑(↑ξ ^ ↑n) = 1)))
          (Eq.mpr (id (Units.val_one ▸ Eq.refl (↑σ ↑1 = 1)))
            (Eq.mpr (id (map_one σ ▸ Eq.refl (↑σ 1 = 1))) (Eq.refl 1)))))
ξ : { x // x ∈ rootsOfUnity n R }
⊢ ↑(unitOfInvertible (↑σ ↑↑ξ)) ^ ↑n = ↑1
[PROOFSTEP]
exact h ξ
[GOAL]
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✝² : CommSemiring R
inst✝¹ : CommSemiring S
inst✝ : RingHomClass F R S
σ : F
n : ℕ+
h : ∀ (ξ : { x // x ∈ rootsOfUnity n R }), ↑σ ↑↑ξ ^ ↑n = 1 :=
  fun ξ =>
    Eq.mpr (id (Eq.symm (map_pow σ ↑↑ξ ↑n) ▸ Eq.refl (↑σ ↑↑ξ ^ ↑n = 1)))
      (Eq.mpr (id (Eq.symm (Units.val_pow_eq_pow_val ↑ξ ↑n) ▸ Eq.refl (↑σ (↑↑ξ ^ ↑n) = 1)))
        (Eq.mpr
          (id
            ((let_fun this := ξ.property;
              this) ▸
              Eq.refl (↑σ ↑(↑ξ ^ ↑n) = 1)))
          (Eq.mpr (id (Units.val_one ▸ Eq.refl (↑σ ↑1 = 1)))
            (Eq.mpr (id (map_one σ ▸ Eq.refl (↑σ 1 = 1))) (Eq.refl 1)))))
⊢ (fun ξ => { val := unitOfInvertible (↑σ ↑↑ξ), property := (_ : unitOfInvertible (↑σ ↑↑ξ) ^ ↑n = 1) }) 1 = 1
[PROOFSTEP]
ext
[GOAL]
case a.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✝² : CommSemiring R
inst✝¹ : CommSemiring S
inst✝ : RingHomClass F R S
σ : F
n : ℕ+
h : ∀ (ξ : { x // x ∈ rootsOfUnity n R }), ↑σ ↑↑ξ ^ ↑n = 1 :=
  fun ξ =>
    Eq.mpr (id (Eq.symm (map_pow σ ↑↑ξ ↑n) ▸ Eq.refl (↑σ ↑↑ξ ^ ↑n = 1)))
      (Eq.mpr (id (Eq.symm (Units.val_pow_eq_pow_val ↑ξ ↑n) ▸ Eq.refl (↑σ (↑↑ξ ^ ↑n) = 1)))
        (Eq.mpr
          (id
            ((let_fun this := ξ.property;
              this) ▸
              Eq.refl (↑σ ↑(↑ξ ^ ↑n) = 1)))
          (Eq.mpr (id (Units.val_one ▸ Eq.refl (↑σ ↑1 = 1)))
            (Eq.mpr (id (map_one σ ▸ Eq.refl (↑σ 1 = 1))) (Eq.refl 1)))))
⊢ ↑↑((fun ξ => { val := unitOfInvertible (↑σ ↑↑ξ), property := (_ : unitOfInvertible (↑σ ↑↑ξ) ^ ↑n = 1) }) 1) = ↑↑1
[PROOFSTEP]
exact map_one σ
[GOAL]
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✝² : CommSemiring R
inst✝¹ : CommSemiring S
inst✝ : RingHomClass F R S
σ : F
n : ℕ+
h : ∀ (ξ : { x // x ∈ rootsOfUnity n R }), ↑σ ↑↑ξ ^ ↑n = 1 :=
  fun ξ =>
    Eq.mpr (id (Eq.symm (map_pow σ ↑↑ξ ↑n) ▸ Eq.refl (↑σ ↑↑ξ ^ ↑n = 1)))
      (Eq.mpr (id (Eq.symm (Units.val_pow_eq_pow_val ↑ξ ↑n) ▸ Eq.refl (↑σ (↑↑ξ ^ ↑n) = 1)))
        (Eq.mpr
          (id
            ((let_fun this := ξ.property;
              this) ▸
              Eq.refl (↑σ ↑(↑ξ ^ ↑n) = 1)))
          (Eq.mpr (id (Units.val_one ▸ Eq.refl (↑σ ↑1 = 1)))
            (Eq.mpr (id (map_one σ ▸ Eq.refl (↑σ 1 = 1))) (Eq.refl 1)))))
ξ₁ ξ₂ : { x // x ∈ rootsOfUnity n R }
⊢ OneHom.toFun
      { toFun := fun ξ => { val := unitOfInvertible (↑σ ↑↑ξ), property := (_ : unitOfInvertible (↑σ ↑↑ξ) ^ ↑n = 1) },
        map_one' :=
          (_ :
            (fun ξ => { val := unitOfInvertible (↑σ ↑↑ξ), property := (_ : unitOfInvertible (↑σ ↑↑ξ) ^ ↑n = 1) }) 1 =
              1) }
      (ξ₁ * ξ₂) =
    OneHom.toFun
        { toFun := fun ξ => { val := unitOfInvertible (↑σ ↑↑ξ), property := (_ : unitOfInvertible (↑σ ↑↑ξ) ^ ↑n = 1) },
          map_one' :=
            (_ :
              (fun ξ => { val := unitOfInvertible (↑σ ↑↑ξ), property := (_ : unitOfInvertible (↑σ ↑↑ξ) ^ ↑n = 1) }) 1 =
                1) }
        ξ₁ *
      OneHom.toFun
        { toFun := fun ξ => { val := unitOfInvertible (↑σ ↑↑ξ), property := (_ : unitOfInvertible (↑σ ↑↑ξ) ^ ↑n = 1) },
          map_one' :=
            (_ :
              (fun ξ => { val := unitOfInvertible (↑σ ↑↑ξ), property := (_ : unitOfInvertible (↑σ ↑↑ξ) ^ ↑n = 1) }) 1 =
                1) }
        ξ₂
[PROOFSTEP]
ext
[GOAL]
case a.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✝² : CommSemiring R
inst✝¹ : CommSemiring S
inst✝ : RingHomClass F R S
σ : F
n : ℕ+
h : ∀ (ξ : { x // x ∈ rootsOfUnity n R }), ↑σ ↑↑ξ ^ ↑n = 1 :=
  fun ξ =>
    Eq.mpr (id (Eq.symm (map_pow σ ↑↑ξ ↑n) ▸ Eq.refl (↑σ ↑↑ξ ^ ↑n = 1)))
      (Eq.mpr (id (Eq.symm (Units.val_pow_eq_pow_val ↑ξ ↑n) ▸ Eq.refl (↑σ (↑↑ξ ^ ↑n) = 1)))
        (Eq.mpr
          (id
            ((let_fun this := ξ.property;
              this) ▸
              Eq.refl (↑σ ↑(↑ξ ^ ↑n) = 1)))
          (Eq.mpr (id (Units.val_one ▸ Eq.refl (↑σ ↑1 = 1)))
            (Eq.mpr (id (map_one σ ▸ Eq.refl (↑σ 1 = 1))) (Eq.refl 1)))))
ξ₁ ξ₂ : { x // x ∈ rootsOfUnity n R }
⊢ ↑↑(OneHom.toFun
          {
            toFun := fun ξ =>
              { val := unitOfInvertible (↑σ ↑↑ξ), property := (_ : unitOfInvertible (↑σ ↑↑ξ) ^ ↑n = 1) },
            map_one' :=
              (_ :
                (fun ξ => { val := unitOfInvertible (↑σ ↑↑ξ), property := (_ : unitOfInvertible (↑σ ↑↑ξ) ^ ↑n = 1) })
                    1 =
                  1) }
          (ξ₁ * ξ₂)) =
    ↑↑(OneHom.toFun
            {
              toFun := fun ξ =>
                { val := unitOfInvertible (↑σ ↑↑ξ), property := (_ : unitOfInvertible (↑σ ↑↑ξ) ^ ↑n = 1) },
              map_one' :=
                (_ :
                  (fun ξ => { val := unitOfInvertible (↑σ ↑↑ξ), property := (_ : unitOfInvertible (↑σ ↑↑ξ) ^ ↑n = 1) })
                      1 =
                    1) }
            ξ₁ *
          OneHom.toFun
            {
              toFun := fun ξ =>
                { val := unitOfInvertible (↑σ ↑↑ξ), property := (_ : unitOfInvertible (↑σ ↑↑ξ) ^ ↑n = 1) },
              map_one' :=
                (_ :
                  (fun ξ => { val := unitOfInvertible (↑σ ↑↑ξ), property := (_ : unitOfInvertible (↑σ ↑↑ξ) ^ ↑n = 1) })
                      1 =
                    1) }
            ξ₂)
[PROOFSTEP]
rw [Subgroup.coe_mul, Units.val_mul]
[GOAL]
case a.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✝² : CommSemiring R
inst✝¹ : CommSemiring S
inst✝ : RingHomClass F R S
σ : F
n : ℕ+
h : ∀ (ξ : { x // x ∈ rootsOfUnity n R }), ↑σ ↑↑ξ ^ ↑n = 1 :=
  fun ξ =>
    Eq.mpr (id (Eq.symm (map_pow σ ↑↑ξ ↑n) ▸ Eq.refl (↑σ ↑↑ξ ^ ↑n = 1)))
      (Eq.mpr (id (Eq.symm (Units.val_pow_eq_pow_val ↑ξ ↑n) ▸ Eq.refl (↑σ (↑↑ξ ^ ↑n) = 1)))
        (Eq.mpr
          (id
            ((let_fun this := ξ.property;
              this) ▸
              Eq.refl (↑σ ↑(↑ξ ^ ↑n) = 1)))
          (Eq.mpr (id (Units.val_one ▸ Eq.refl (↑σ ↑1 = 1)))
            (Eq.mpr (id (map_one σ ▸ Eq.refl (↑σ 1 = 1))) (Eq.refl 1)))))
ξ₁ ξ₂ : { x // x ∈ rootsOfUnity n R }
⊢ ↑↑(OneHom.toFun
          {
            toFun := fun ξ =>
              { val := unitOfInvertible (↑σ ↑↑ξ), property := (_ : unitOfInvertible (↑σ ↑↑ξ) ^ ↑n = 1) },
            map_one' :=
              (_ :
                (fun ξ => { val := unitOfInvertible (↑σ ↑↑ξ), property := (_ : unitOfInvertible (↑σ ↑↑ξ) ^ ↑n = 1) })
                    1 =
                  1) }
          (ξ₁ * ξ₂)) =
    ↑↑(OneHom.toFun
            {
              toFun := fun ξ =>
                { val := unitOfInvertible (↑σ ↑↑ξ), property := (_ : unitOfInvertible (↑σ ↑↑ξ) ^ ↑n = 1) },
              map_one' :=
                (_ :
                  (fun ξ => { val := unitOfInvertible (↑σ ↑↑ξ), property := (_ : unitOfInvertible (↑σ ↑↑ξ) ^ ↑n = 1) })
                      1 =
                    1) }
            ξ₁) *
      ↑↑(OneHom.toFun
            {
              toFun := fun ξ =>
                { val := unitOfInvertible (↑σ ↑↑ξ), property := (_ : unitOfInvertible (↑σ ↑↑ξ) ^ ↑n = 1) },
              map_one' :=
                (_ :
                  (fun ξ => { val := unitOfInvertible (↑σ ↑↑ξ), property := (_ : unitOfInvertible (↑σ ↑↑ξ) ^ ↑n = 1) })
                      1 =
                    1) }
            ξ₂)
[PROOFSTEP]
exact map_mul σ _ _
[GOAL]
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✝¹ : CommSemiring R
inst✝ : CommSemiring S
σ : R ≃+* S
n : ℕ+
ξ : { x // x ∈ rootsOfUnity n R }
⊢ ↑(_root_.restrictRootsOfUnity (toRingHom (RingEquiv.symm σ)) n) (↑(_root_.restrictRootsOfUnity (toRingHom σ) n) ξ) = ξ
[PROOFSTEP]
ext
[GOAL]
case a.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✝¹ : CommSemiring R
inst✝ : CommSemiring S
σ : R ≃+* S
n : ℕ+
ξ : { x // x ∈ rootsOfUnity n R }
⊢ ↑↑(↑(_root_.restrictRootsOfUnity (toRingHom (RingEquiv.symm σ)) n)
          (↑(_root_.restrictRootsOfUnity (toRingHom σ) n) ξ)) =
    ↑↑ξ
[PROOFSTEP]
exact σ.symm_apply_apply (ξ : Rˣ)
[GOAL]
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✝¹ : CommSemiring R
inst✝ : CommSemiring S
σ : R ≃+* S
n : ℕ+
ξ : { x // x ∈ rootsOfUnity n S }
⊢ ↑(_root_.restrictRootsOfUnity (toRingHom σ) n) (↑(_root_.restrictRootsOfUnity (toRingHom (RingEquiv.symm σ)) n) ξ) = ξ
[PROOFSTEP]
ext
[GOAL]
case a.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✝¹ : CommSemiring R
inst✝ : CommSemiring S
σ : R ≃+* S
n : ℕ+
ξ : { x // x ∈ rootsOfUnity n S }
⊢ ↑↑(↑(_root_.restrictRootsOfUnity (toRingHom σ) n)
          (↑(_root_.restrictRootsOfUnity (toRingHom (RingEquiv.symm σ)) n) ξ)) =
    ↑↑ξ
[PROOFSTEP]
exact σ.apply_symm_apply (ξ : Sˣ)
[GOAL]
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
inst✝ : IsDomain R
ζ : Rˣ
⊢ ζ ∈ rootsOfUnity k R ↔ ↑ζ ∈ nthRoots (↑k) 1
[PROOFSTEP]
simp only [mem_rootsOfUnity, mem_nthRoots k.pos, Units.ext_iff, Units.val_one, Units.val_pow_eq_pow_val]
[GOAL]
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
inst✝ : IsDomain R
⊢ { x // x ∈ rootsOfUnity k R } ≃ { x // x ∈ nthRoots (↑k) 1 }
[PROOFSTEP]
refine'
  { toFun := fun x => ⟨(x : Rˣ), mem_rootsOfUnity_iff_mem_nthRoots.mp x.2⟩
    invFun := fun x => ⟨⟨x, ↑x ^ (k - 1 : ℕ), _, _⟩, _⟩
    left_inv := _
    right_inv := _ }
[GOAL]
case 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
inst✝ : IsDomain R
x : { x // x ∈ nthRoots (↑k) 1 }
⊢ ↑x * ↑x ^ (↑k - 1) = 1
case refine'_2
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
inst✝ : IsDomain R
x : { x // x ∈ nthRoots (↑k) 1 }
⊢ ↑x ^ (↑k - 1) * ↑x = 1
case refine'_3
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
inst✝ : IsDomain R
x : { x // x ∈ nthRoots (↑k) 1 }
⊢ { val := ↑x, inv := ↑x ^ (↑k - 1), val_inv := ?refine'_1, inv_val := ?refine'_2 } ∈ rootsOfUnity k R
case refine'_4
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
inst✝ : IsDomain R
⊢ Function.LeftInverse
    (fun x =>
      {
        val :=
          { val := ↑x, inv := ↑x ^ (↑k - 1), val_inv := (_ : ↑x * ?m.1200034 x ^ (↑k - 1) = 1),
            inv_val := (_ : ?m.1200036 x ^ (↑k - 1) * ↑x = 1) },
        property :=
          (_ :
            { val := ↑x, inv := ?m.1200038 x ^ (↑k - 1), val_inv := (_ : ↑x * ?m.1200039 x ^ (↑k - 1) = 1),
                inv_val := (_ : ?m.1200041 x ^ (↑k - 1) * ↑x = 1) } ∈
              rootsOfUnity k R) })
    fun x => { val := ↑↑x, property := (_ : ↑↑x ∈ nthRoots (↑k) 1) }
case refine'_5
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
inst✝ : IsDomain R
⊢ Function.RightInverse
    (fun x =>
      {
        val :=
          { val := ↑x, inv := ↑x ^ (↑k - 1), val_inv := (_ : ↑x * ?m.1200034 x ^ (↑k - 1) = 1),
            inv_val := (_ : ?m.1200036 x ^ (↑k - 1) * ↑x = 1) },
        property :=
          (_ :
            { val := ↑x, inv := ?m.1200038 x ^ (↑k - 1), val_inv := (_ : ↑x * ?m.1200039 x ^ (↑k - 1) = 1),
                inv_val := (_ : ?m.1200041 x ^ (↑k - 1) * ↑x = 1) } ∈
              rootsOfUnity k R) })
    fun x => { val := ↑↑x, property := (_ : ↑↑x ∈ nthRoots (↑k) 1) }
[PROOFSTEP]
pick_goal 4
[GOAL]
case refine'_4
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
inst✝ : IsDomain R
⊢ Function.LeftInverse
    (fun x =>
      {
        val :=
          { val := ↑x, inv := ↑x ^ (↑k - 1), val_inv := (_ : ↑x * ?m.1200034 x ^ (↑k - 1) = 1),
            inv_val := (_ : ?m.1200036 x ^ (↑k - 1) * ↑x = 1) },
        property :=
          (_ :
            { val := ↑x, inv := ?m.1200038 x ^ (↑k - 1), val_inv := (_ : ↑x * ?m.1200039 x ^ (↑k - 1) = 1),
                inv_val := (_ : ?m.1200041 x ^ (↑k - 1) * ↑x = 1) } ∈
              rootsOfUnity k R) })
    fun x => { val := ↑↑x, property := (_ : ↑↑x ∈ nthRoots (↑k) 1) }
[PROOFSTEP]
rintro ⟨x, hx⟩
[GOAL]
case refine'_4.mk
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
inst✝ : IsDomain R
x : Rˣ
hx : x ∈ rootsOfUnity k R
⊢ (fun x =>
        {
          val :=
            { val := ↑x, inv := ↑x ^ (↑k - 1), val_inv := (_ : ↑x * ?m.1200034 x ^ (↑k - 1) = 1),
              inv_val := (_ : ?m.1200036 x ^ (↑k - 1) * ↑x = 1) },
          property :=
            (_ :
              { val := ↑x, inv := ?m.1200038 x ^ (↑k - 1), val_inv := (_ : ↑x * ?m.1200039 x ^ (↑k - 1) = 1),
                  inv_val := (_ : ?m.1200041 x ^ (↑k - 1) * ↑x = 1) } ∈
                rootsOfUnity k R) })
      ((fun x => { val := ↑↑x, property := (_ : ↑↑x ∈ nthRoots (↑k) 1) }) { val := x, property := hx }) =
    { val := x, property := hx }
[PROOFSTEP]
ext
[GOAL]
case refine'_4.mk.a.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
inst✝ : IsDomain R
x : Rˣ
hx : x ∈ rootsOfUnity k R
⊢ ↑↑((fun x =>
            {
              val :=
                { val := ↑x, inv := ↑x ^ (↑k - 1), val_inv := (_ : ↑x * ?m.1200034 x ^ (↑k - 1) = 1),
                  inv_val := (_ : ?m.1200036 x ^ (↑k - 1) * ↑x = 1) },
              property :=
                (_ :
                  { val := ↑x, inv := ?m.1200038 x ^ (↑k - 1), val_inv := (_ : ↑x * ?m.1200039 x ^ (↑k - 1) = 1),
                      inv_val := (_ : ?m.1200041 x ^ (↑k - 1) * ↑x = 1) } ∈
                    rootsOfUnity k R) })
          ((fun x => { val := ↑↑x, property := (_ : ↑↑x ∈ nthRoots (↑k) 1) }) { val := x, property := hx })) =
    ↑↑{ val := x, property := hx }
[PROOFSTEP]
rfl
[GOAL]
case 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
inst✝ : IsDomain R
x : { x // x ∈ nthRoots (↑k) 1 }
⊢ ↑x * ↑x ^ (↑k - 1) = 1
case refine'_2
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
inst✝ : IsDomain R
x : { x // x ∈ nthRoots (↑k) 1 }
⊢ ↑x ^ (↑k - 1) * ↑x = 1
case refine'_3
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
inst✝ : IsDomain R
x : { x // x ∈ nthRoots (↑k) 1 }
⊢ { val := ↑x, inv := ↑x ^ (↑k - 1), val_inv := ?refine'_1, inv_val := ?refine'_2 } ∈ rootsOfUnity k R
case refine'_5
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
inst✝ : IsDomain R
⊢ Function.RightInverse
    (fun x =>
      {
        val :=
          { val := ↑x, inv := ↑x ^ (↑k - 1), val_inv := (_ : ↑x * ?m.1200034 x ^ (↑k - 1) = 1),
            inv_val := (_ : ?m.1200036 x ^ (↑k - 1) * ↑x = 1) },
        property :=
          (_ :
            { val := ↑x, inv := ?m.1200038 x ^ (↑k - 1), val_inv := (_ : ↑x * ?m.1200039 x ^ (↑k - 1) = 1),
                inv_val := (_ : ?m.1200041 x ^ (↑k - 1) * ↑x = 1) } ∈
              rootsOfUnity k R) })
    fun x => { val := ↑↑x, property := (_ : ↑↑x ∈ nthRoots (↑k) 1) }
[PROOFSTEP]
pick_goal 4
[GOAL]
case refine'_5
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
inst✝ : IsDomain R
⊢ Function.RightInverse
    (fun x =>
      {
        val :=
          { val := ↑x, inv := ↑x ^ (↑k - 1), val_inv := (_ : ↑x * ?m.1200034 x ^ (↑k - 1) = 1),
            inv_val := (_ : ?m.1200036 x ^ (↑k - 1) * ↑x = 1) },
        property :=
          (_ :
            { val := ↑x, inv := ?m.1200038 x ^ (↑k - 1), val_inv := (_ : ↑x * ?m.1200039 x ^ (↑k - 1) = 1),
                inv_val := (_ : ?m.1200041 x ^ (↑k - 1) * ↑x = 1) } ∈
              rootsOfUnity k R) })
    fun x => { val := ↑↑x, property := (_ : ↑↑x ∈ nthRoots (↑k) 1) }
[PROOFSTEP]
rintro ⟨x, hx⟩
[GOAL]
case refine'_5.mk
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
inst✝ : IsDomain R
x : R
hx : x ∈ nthRoots (↑k) 1
⊢ (fun x => { val := ↑↑x, property := (_ : ↑↑x ∈ nthRoots (↑k) 1) })
      ((fun x =>
          {
            val :=
              { val := ↑x, inv := ↑x ^ (↑k - 1), val_inv := (_ : ↑x * ?m.1200034 x ^ (↑k - 1) = 1),
                inv_val := (_ : ?m.1200036 x ^ (↑k - 1) * ↑x = 1) },
            property :=
              (_ :
                { val := ↑x, inv := ?m.1200038 x ^ (↑k - 1), val_inv := (_ : ↑x * ?m.1200039 x ^ (↑k - 1) = 1),
                    inv_val := (_ : ?m.1200041 x ^ (↑k - 1) * ↑x = 1) } ∈
                  rootsOfUnity k R) })
        { val := x, property := hx }) =
    { val := x, property := hx }
[PROOFSTEP]
ext
[GOAL]
case refine'_5.mk.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
inst✝ : IsDomain R
x : R
hx : x ∈ nthRoots (↑k) 1
⊢ ↑((fun x => { val := ↑↑x, property := (_ : ↑↑x ∈ nthRoots (↑k) 1) })
        ((fun x =>
            {
              val :=
                { val := ↑x, inv := ↑x ^ (↑k - 1), val_inv := (_ : ↑x * ?m.1200034 x ^ (↑k - 1) = 1),
                  inv_val := (_ : ?m.1200036 x ^ (↑k - 1) * ↑x = 1) },
              property :=
                (_ :
                  { val := ↑x, inv := ?m.1200038 x ^ (↑k - 1), val_inv := (_ : ↑x * ?m.1200039 x ^ (↑k - 1) = 1),
                      inv_val := (_ : ?m.1200041 x ^ (↑k - 1) * ↑x = 1) } ∈
                    rootsOfUnity k R) })
          { val := x, property := hx })) =
    ↑{ val := x, property := hx }
[PROOFSTEP]
rfl
[GOAL]
case 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
inst✝ : IsDomain R
x : { x // x ∈ nthRoots (↑k) 1 }
⊢ ↑x * ↑x ^ (↑k - 1) = 1
case refine'_2
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
inst✝ : IsDomain R
x : { x // x ∈ nthRoots (↑k) 1 }
⊢ ↑x ^ (↑k - 1) * ↑x = 1
case refine'_3
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
inst✝ : IsDomain R
x : { x // x ∈ nthRoots (↑k) 1 }
⊢ { val := ↑x, inv := ↑x ^ (↑k - 1), val_inv := ?refine'_1, inv_val := ?refine'_2 } ∈ rootsOfUnity k R
[PROOFSTEP]
all_goals
  rcases x with ⟨x, hx⟩; rw [mem_nthRoots k.pos] at hx 
  simp only [Subtype.coe_mk, ← pow_succ, ← pow_succ', hx, tsub_add_cancel_of_le (show 1 ≤ (k : ℕ) from k.one_le)]
[GOAL]
case 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
inst✝ : IsDomain R
x : { x // x ∈ nthRoots (↑k) 1 }
⊢ ↑x * ↑x ^ (↑k - 1) = 1
[PROOFSTEP]
rcases x with ⟨x, hx⟩
[GOAL]
case refine'_1.mk
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
inst✝ : IsDomain R
x : R
hx : x ∈ nthRoots (↑k) 1
⊢ ↑{ val := x, property := hx } * ↑{ val := x, property := hx } ^ (↑k - 1) = 1
[PROOFSTEP]
rw [mem_nthRoots k.pos] at hx 
[GOAL]
case refine'_1.mk
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
inst✝ : IsDomain R
x : R
hx✝ : x ∈ nthRoots (↑k) 1
hx : x ^ ↑k = 1
⊢ ↑{ val := x, property := hx✝ } * ↑{ val := x, property := hx✝ } ^ (↑k - 1) = 1
[PROOFSTEP]
simp only [Subtype.coe_mk, ← pow_succ, ← pow_succ', hx, tsub_add_cancel_of_le (show 1 ≤ (k : ℕ) from k.one_le)]
[GOAL]
case refine'_2
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
inst✝ : IsDomain R
x : { x // x ∈ nthRoots (↑k) 1 }
⊢ ↑x ^ (↑k - 1) * ↑x = 1
[PROOFSTEP]
rcases x with ⟨x, hx⟩
[GOAL]
case refine'_2.mk
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
inst✝ : IsDomain R
x : R
hx : x ∈ nthRoots (↑k) 1
⊢ ↑{ val := x, property := hx } ^ (↑k - 1) * ↑{ val := x, property := hx } = 1
[PROOFSTEP]
rw [mem_nthRoots k.pos] at hx 
[GOAL]
case refine'_2.mk
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
inst✝ : IsDomain R
x : R
hx✝ : x ∈ nthRoots (↑k) 1
hx : x ^ ↑k = 1
⊢ ↑{ val := x, property := hx✝ } ^ (↑k - 1) * ↑{ val := x, property := hx✝ } = 1
[PROOFSTEP]
simp only [Subtype.coe_mk, ← pow_succ, ← pow_succ', hx, tsub_add_cancel_of_le (show 1 ≤ (k : ℕ) from k.one_le)]
[GOAL]
case refine'_3
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
inst✝ : IsDomain R
x : { x // x ∈ nthRoots (↑k) 1 }
⊢ { val := ↑x, inv := ↑x ^ (↑k - 1), val_inv := (_ : ↑x * ↑x ^ (↑k - 1) = 1),
      inv_val := (_ : ↑x ^ (↑k - 1) * ↑x = 1) } ∈
    rootsOfUnity k R
[PROOFSTEP]
rcases x with ⟨x, hx⟩
[GOAL]
case refine'_3.mk
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
inst✝ : IsDomain R
x : R
hx : x ∈ nthRoots (↑k) 1
⊢ { val := ↑{ val := x, property := hx }, inv := ↑{ val := x, property := hx } ^ (↑k - 1),
      val_inv := (_ : ↑{ val := x, property := hx } * ↑{ val := x, property := hx } ^ (↑k - 1) = 1),
      inv_val := (_ : ↑{ val := x, property := hx } ^ (↑k - 1) * ↑{ val := x, property := hx } = 1) } ∈
    rootsOfUnity k R
[PROOFSTEP]
rw [mem_nthRoots k.pos] at hx 
[GOAL]
case refine'_3.mk
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
inst✝ : IsDomain R
x : R
hx✝ : x ∈ nthRoots (↑k) 1
hx : x ^ ↑k = 1
⊢ { val := ↑{ val := x, property := hx✝ }, inv := ↑{ val := x, property := hx✝ } ^ (↑k - 1),
      val_inv := (_ : ↑{ val := x, property := hx✝ } * ↑{ val := x, property := hx✝ } ^ (↑k - 1) = 1),
      inv_val := (_ : ↑{ val := x, property := hx✝ } ^ (↑k - 1) * ↑{ val := x, property := hx✝ } = 1) } ∈
    rootsOfUnity k R
[PROOFSTEP]
simp only [Subtype.coe_mk, ← pow_succ, ← pow_succ', hx, tsub_add_cancel_of_le (show 1 ≤ (k : ℕ) from k.one_le)]
[GOAL]
case refine'_3.mk
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
inst✝ : IsDomain R
x : R
hx✝ : x ∈ nthRoots (↑k) 1
hx : x ^ ↑k = 1
⊢ { val := x, inv := x ^ (↑k - 1),
      val_inv := (_ : ↑{ val := x, property := hx✝ } * ↑{ val := x, property := hx✝ } ^ (↑k - 1) = 1),
      inv_val := (_ : ↑{ val := x, property := hx✝ } ^ (↑k - 1) * ↑{ val := x, property := hx✝ } = 1) } ∈
    rootsOfUnity k R
[PROOFSTEP]
show (_ : Rˣ) ^ (k : ℕ) = 1
[GOAL]
case refine'_3.mk
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
inst✝ : IsDomain R
x : R
hx✝ : x ∈ nthRoots (↑k) 1
hx : x ^ ↑k = 1
⊢ { val := x, inv := x ^ (↑k - 1),
        val_inv := (_ : ↑{ val := x, property := hx✝ } * ↑{ val := x, property := hx✝ } ^ (↑k - 1) = 1),
        inv_val := (_ : ↑{ val := x, property := hx✝ } ^ (↑k - 1) * ↑{ val := x, property := hx✝ } = 1) } ^
      ↑k =
    1
[PROOFSTEP]
simp only [Units.ext_iff, hx, Units.val_mk, Units.val_one, Subtype.coe_mk, Units.val_pow_eq_pow_val]
[GOAL]
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
inst✝¹ : IsDomain R
inst✝ : RingHomClass F R R
σ : F
ζ : { x // x ∈ rootsOfUnity k R }
⊢ ∃ m, ↑σ ↑↑ζ = ↑↑ζ ^ m
[PROOFSTEP]
obtain ⟨m, hm⟩ := MonoidHom.map_cyclic (restrictRootsOfUnity σ k)
[GOAL]
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
inst✝¹ : IsDomain R
inst✝ : RingHomClass F R R
σ : F
ζ : { x // x ∈ rootsOfUnity k R }
m : ℤ
hm : ∀ (g : { x // x ∈ rootsOfUnity k R }), ↑(restrictRootsOfUnity σ k) g = g ^ m
⊢ ∃ m, ↑σ ↑↑ζ = ↑↑ζ ^ m
[PROOFSTEP]
rw [← restrictRootsOfUnity_coe_apply, hm, zpow_eq_mod_orderOf, ←
  Int.toNat_of_nonneg (m.emod_nonneg (Int.coe_nat_ne_zero.mpr (pos_iff_ne_zero.mp (orderOf_pos ζ)))), zpow_ofNat,
  rootsOfUnity.coe_pow]
[GOAL]
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
inst✝¹ : IsDomain R
inst✝ : RingHomClass F R R
σ : F
ζ : { x // x ∈ rootsOfUnity k R }
m : ℤ
hm : ∀ (g : { x // x ∈ rootsOfUnity k R }), ↑(restrictRootsOfUnity σ k) g = g ^ m
⊢ ∃ m_1, ↑↑ζ ^ Int.toNat (m % ↑(orderOf ζ)) = ↑↑ζ ^ m_1
[PROOFSTEP]
exact ⟨(m % orderOf ζ).toNat, rfl⟩
[GOAL]
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
inst✝¹ : IsReduced R
p k : ℕ
m : ℕ+
hp : Fact (Nat.Prime p)
inst✝ : CharP R p
ζ : Rˣ
⊢ ζ ∈ rootsOfUnity ({ val := p, property := (_ : 0 < p) } ^ k * m) R ↔ ζ ∈ rootsOfUnity m R
[PROOFSTEP]
simp only [mem_rootsOfUnity', PNat.mul_coe, PNat.pow_coe, PNat.mk_coe, CharP.pow_prime_pow_mul_eq_one_iff]
[GOAL]
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
inst✝¹ : IsReduced R
p k : ℕ
m : ℕ+
hp : Fact (Nat.Prime p)
inst✝ : CharP R p
ζ : Rˣ
⊢ ζ ^ (p ^ k * ↑m) = 1 ↔ ζ ∈ rootsOfUnity m R
[PROOFSTEP]
rw [← PNat.mk_coe p hp.1.pos, ← PNat.pow_coe, ← PNat.mul_coe, ← mem_rootsOfUnity, mem_rootsOfUnity_prime_pow_mul_iff]
[GOAL]
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 : ℕ
inst✝¹ : CommRing R
inst✝ : IsDomain R
ζ : R
h0 : 0 < k
⊢ ζ ∈ primitiveRoots k R ↔ IsPrimitiveRoot ζ k
[PROOFSTEP]
rw [primitiveRoots, mem_filter, Multiset.mem_toFinset, mem_nthRoots h0, and_iff_right_iff_imp]
[GOAL]
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 : ℕ
inst✝¹ : CommRing R
inst✝ : IsDomain R
ζ : R
h0 : 0 < k
⊢ IsPrimitiveRoot ζ k → ζ ^ k = 1
[PROOFSTEP]
exact IsPrimitiveRoot.pow_eq_one
[GOAL]
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 : ℕ
inst✝¹ : CommRing R
inst✝ : IsDomain R
⊢ primitiveRoots 0 R = ∅
[PROOFSTEP]
rw [primitiveRoots, nthRoots_zero, Multiset.toFinset_zero, Finset.filter_empty]
[GOAL]
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 : ℕ
inst✝¹ : CommRing R
inst✝ : IsDomain R
ζ : R
h : ζ ∈ primitiveRoots k R
hk : k = 0
⊢ IsPrimitiveRoot ζ k
[PROOFSTEP]
simp [hk] at h 
[GOAL]
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 : ℕ
ζ : M
hk : 0 < k
h1 : ζ ^ k = 1
h : ∀ (l : ℕ), 0 < l → l < k → ζ ^ l ≠ 1
⊢ IsPrimitiveRoot ζ k
[PROOFSTEP]
refine' ⟨h1, fun l hl => _⟩
[GOAL]
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✝ : ℕ
ζ : M
hk : 0 < k
h1 : ζ ^ k = 1
h : ∀ (l : ℕ), 0 < l → l < k → ζ ^ l ≠ 1
l : ℕ
hl : ζ ^ l = 1
⊢ k ∣ l
[PROOFSTEP]
suffices k.gcd l = k by exact this ▸ k.gcd_dvd_right l
[GOAL]
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✝ : ℕ
ζ : M
hk : 0 < k
h1 : ζ ^ k = 1
h : ∀ (l : ℕ), 0 < l → l < k → ζ ^ l ≠ 1
l : ℕ
hl : ζ ^ l = 1
this : Nat.gcd k l = k
⊢ k ∣ l
[PROOFSTEP]
exact this ▸ k.gcd_dvd_right l
[GOAL]
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✝ : ℕ
ζ : M
hk : 0 < k
h1 : ζ ^ k = 1
h : ∀ (l : ℕ), 0 < l → l < k → ζ ^ l ≠ 1
l : ℕ
hl : ζ ^ l = 1
⊢ Nat.gcd k l = k
[PROOFSTEP]
rw [eq_iff_le_not_lt]
[GOAL]
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✝ : ℕ
ζ : M
hk : 0 < k
h1 : ζ ^ k = 1
h : ∀ (l : ℕ), 0 < l → l < k → ζ ^ l ≠ 1
l : ℕ
hl : ζ ^ l = 1
⊢ Nat.gcd k l ≤ k ∧ ¬Nat.gcd k l < k
[PROOFSTEP]
refine' ⟨Nat.le_of_dvd hk (k.gcd_dvd_left l), _⟩
[GOAL]
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✝ : ℕ
ζ : M
hk : 0 < k
h1 : ζ ^ k = 1
h : ∀ (l : ℕ), 0 < l → l < k → ζ ^ l ≠ 1
l : ℕ
hl : ζ ^ l = 1
⊢ ¬Nat.gcd k l < k
[PROOFSTEP]
intro h'
[GOAL]
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✝ : ℕ
ζ : M
hk : 0 < k
h1 : ζ ^ k = 1
h : ∀ (l : ℕ), 0 < l → l < k → ζ ^ l ≠ 1
l : ℕ
hl : ζ ^ l = 1
h' : Nat.gcd k l < k
⊢ False
[PROOFSTEP]
apply h _ (Nat.gcd_pos_of_pos_left _ hk) h'
[GOAL]
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✝ : ℕ
ζ : M
hk : 0 < k
h1 : ζ ^ k = 1
h : ∀ (l : ℕ), 0 < l → l < k → ζ ^ l ≠ 1
l : ℕ
hl : ζ ^ l = 1
h' : Nat.gcd k l < k
⊢ ζ ^ Nat.gcd k l = 1
[PROOFSTEP]
exact pow_gcd_eq_one _ h1 hl
[GOAL]
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✝ : ℕ
ζ : M
f : F
h : IsPrimitiveRoot ζ k
l : ℕ
⊢ k ∣ l → ζ ^ l = 1
[PROOFSTEP]
rintro ⟨i, rfl⟩
[GOAL]
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 : ℕ
ζ : M
f : F
h : IsPrimitiveRoot ζ k
i : ℕ
⊢ ζ ^ (k * i) = 1
[PROOFSTEP]
simp only [pow_mul, h.pow_eq_one, one_pow, PNat.mul_coe]
[GOAL]
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 : ℕ
ζ : M
f : F
h✝ h : IsPrimitiveRoot ζ k
h0 : 0 < k
⊢ IsUnit ζ
[PROOFSTEP]
apply isUnit_of_mul_eq_one ζ (ζ ^ (k - 1))
[GOAL]
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 : ℕ
ζ : M
f : F
h✝ h : IsPrimitiveRoot ζ k
h0 : 0 < k
⊢ ζ * ζ ^ (k - 1) = 1
[PROOFSTEP]
rw [← pow_succ, tsub_add_cancel_of_le h0.nat_succ_le, h.pow_eq_one]
[GOAL]
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 : ℕ
ζ : M
f : F
h✝ h : IsPrimitiveRoot ζ k
i j : ℕ
hi : i < k
hj : j < k
H : ζ ^ i = ζ ^ j
⊢ i = j
[PROOFSTEP]
wlog hij : i ≤ j generalizing i j
[GOAL]
case inr
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 : ℕ
ζ : M
f : F
h✝ h : IsPrimitiveRoot ζ k
i j : ℕ
hi : i < k
hj : j < k
H : ζ ^ i = ζ ^ j
this : ∀ ⦃i j : ℕ⦄, i < k → j < k → ζ ^ i = ζ ^ j → i ≤ j → i = j
hij : ¬i ≤ j
⊢ i = j
[PROOFSTEP]
exact (this hj hi H.symm (le_of_not_le hij)).symm
[GOAL]
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 : ℕ
ζ : M
f : F
h✝ h : IsPrimitiveRoot ζ k
i j : ℕ
hi : i < k
hj : j < k
H : ζ ^ i = ζ ^ j
hij : i ≤ j
⊢ i = j
[PROOFSTEP]
apply le_antisymm hij
[GOAL]
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 : ℕ
ζ : M
f : F
h✝ h : IsPrimitiveRoot ζ k
i j : ℕ
hi : i < k
hj : j < k
H : ζ ^ i = ζ ^ j
hij : i ≤ j
⊢ j ≤ i
[PROOFSTEP]
rw [← tsub_eq_zero_iff_le]
[GOAL]
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 : ℕ
ζ : M
f : F
h✝ h : IsPrimitiveRoot ζ k
i j : ℕ
hi : i < k
hj : j < k
H : ζ ^ i = ζ ^ j
hij : i ≤ j
⊢ j - i = 0
[PROOFSTEP]
apply Nat.eq_zero_of_dvd_of_lt _ (lt_of_le_of_lt tsub_le_self hj)
[GOAL]
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 : ℕ
ζ : M
f : F
h✝ h : IsPrimitiveRoot ζ k
i j : ℕ
hi : i < k
hj : j < k
H : ζ ^ i = ζ ^ j
hij : i ≤ j
⊢ k ∣ j - i
[PROOFSTEP]
apply h.dvd_of_pow_eq_one
[GOAL]
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 : ℕ
ζ : M
f : F
h✝ h : IsPrimitiveRoot ζ k
i j : ℕ
hi : i < k
hj : j < k
H : ζ ^ i = ζ ^ j
hij : i ≤ j
⊢ ζ ^ (j - i) = 1
[PROOFSTEP]
rw [← ((h.isUnit (lt_of_le_of_lt (Nat.zero_le _) hi)).pow i).mul_left_inj, ← pow_add, tsub_add_cancel_of_le hij, H,
  one_mul]
[GOAL]
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 : ℕ
ζ : M
f : F
h : IsPrimitiveRoot ζ k
⊢ IsPrimitiveRoot ζ 1 ↔ ζ = 1
[PROOFSTEP]
clear h
[GOAL]
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 : ℕ
ζ : M
f : F
⊢ IsPrimitiveRoot ζ 1 ↔ ζ = 1
[PROOFSTEP]
constructor
[GOAL]
case mp
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 : ℕ
ζ : M
f : F
⊢ IsPrimitiveRoot ζ 1 → ζ = 1
[PROOFSTEP]
intro h
[GOAL]
case mp
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 : ℕ
ζ : M
f : F
h : IsPrimitiveRoot ζ 1
⊢ ζ = 1
[PROOFSTEP]
rw [← pow_one ζ, h.pow_eq_one]
[GOAL]
case mpr
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 : ℕ
ζ : M
f : F
⊢ ζ = 1 → IsPrimitiveRoot ζ 1
[PROOFSTEP]
rintro rfl
[GOAL]
case mpr
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 : ℕ
f : F
⊢ IsPrimitiveRoot 1 1
[PROOFSTEP]
exact one
[GOAL]
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 : ℕ
ζ✝ : M✝
f : F
h : IsPrimitiveRoot ζ✝ k
M : Type u_7
B : Type u_8
inst✝² : CommMonoid M
inst✝¹ : SetLike B M
inst✝ : SubmonoidClass B M
N : B
ζ : { x // x ∈ N }
⊢ IsPrimitiveRoot (↑ζ) k ↔ IsPrimitiveRoot ζ k
[PROOFSTEP]
simp_rw [iff_def]
[GOAL]
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 : ℕ
ζ✝ : M✝
f : F
h : IsPrimitiveRoot ζ✝ k
M : Type u_7
B : Type u_8
inst✝² : CommMonoid M
inst✝¹ : SetLike B M
inst✝ : SubmonoidClass B M
N : B
ζ : { x // x ∈ N }
⊢ (↑ζ ^ k = 1 ∧ ∀ (l : ℕ), ↑ζ ^ l = 1 → k ∣ l) ↔ ζ ^ k = 1 ∧ ∀ (l : ℕ), ζ ^ l = 1 → k ∣ l
[PROOFSTEP]
norm_cast
[GOAL]
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 : ℕ
ζ✝ : M
f : F
h : IsPrimitiveRoot ζ✝ k
ζ : Mˣ
⊢ IsPrimitiveRoot (↑ζ) k ↔ IsPrimitiveRoot ζ k
[PROOFSTEP]
simp only [iff_def, Units.ext_iff, Units.val_pow_eq_pow_val, Units.val_one]
[GOAL]
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 : ℕ
ζ : M
f : F
h : IsPrimitiveRoot ζ k
i : ℕ
hi : Nat.coprime i k
⊢ IsPrimitiveRoot (ζ ^ i) k
[PROOFSTEP]
by_cases h0 : k = 0
[GOAL]
case pos
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 : ℕ
ζ : M
f : F
h : IsPrimitiveRoot ζ k
i : ℕ
hi : Nat.coprime i k
h0 : k = 0
⊢ IsPrimitiveRoot (ζ ^ i) k
[PROOFSTEP]
subst k
[GOAL]
case pos
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
l : ℕ
ζ : M
f : F
i : ℕ
h : IsPrimitiveRoot ζ 0
hi : Nat.coprime i 0
⊢ IsPrimitiveRoot (ζ ^ i) 0
[PROOFSTEP]
simp_all only [pow_one, Nat.coprime_zero_right]
[GOAL]
case neg
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 : ℕ
ζ : M
f : F
h : IsPrimitiveRoot ζ k
i : ℕ
hi : Nat.coprime i k
h0 : ¬k = 0
⊢ IsPrimitiveRoot (ζ ^ i) k
[PROOFSTEP]
rcases h.isUnit (Nat.pos_of_ne_zero h0) with ⟨ζ, rfl⟩
[GOAL]
case neg.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 : ℕ
f : F
i : ℕ
hi : Nat.coprime i k
h0 : ¬k = 0
ζ : Mˣ
h : IsPrimitiveRoot (↑ζ) k
⊢ IsPrimitiveRoot (↑ζ ^ i) k
[PROOFSTEP]
rw [← Units.val_pow_eq_pow_val]
[GOAL]
case neg.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 : ℕ
f : F
i : ℕ
hi : Nat.coprime i k
h0 : ¬k = 0
ζ : Mˣ
h : IsPrimitiveRoot (↑ζ) k
⊢ IsPrimitiveRoot (↑(ζ ^ i)) k
[PROOFSTEP]
rw [coe_units_iff] at h ⊢
[GOAL]
case neg.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 : ℕ
f : F
i : ℕ
hi : Nat.coprime i k
h0 : ¬k = 0
ζ : Mˣ
h : IsPrimitiveRoot ζ k
⊢ IsPrimitiveRoot (ζ ^ i) k
[PROOFSTEP]
refine'
  { pow_eq_one := by rw [← pow_mul', pow_mul, h.pow_eq_one, one_pow]
    dvd_of_pow_eq_one := _ }
[GOAL]
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 : ℕ
f : F
i : ℕ
hi : Nat.coprime i k
h0 : ¬k = 0
ζ : Mˣ
h : IsPrimitiveRoot ζ k
⊢ (ζ ^ i) ^ k = 1
[PROOFSTEP]
rw [← pow_mul', pow_mul, h.pow_eq_one, one_pow]
[GOAL]
case neg.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 : ℕ
f : F
i : ℕ
hi : Nat.coprime i k
h0 : ¬k = 0
ζ : Mˣ
h : IsPrimitiveRoot ζ k
⊢ ∀ (l : ℕ), (ζ ^ i) ^ l = 1 → k ∣ l
[PROOFSTEP]
intro l hl
[GOAL]
case neg.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✝ : ℕ
f : F
i : ℕ
hi : Nat.coprime i k
h0 : ¬k = 0
ζ : Mˣ
h : IsPrimitiveRoot ζ k
l : ℕ
hl : (ζ ^ i) ^ l = 1
⊢ k ∣ l
[PROOFSTEP]
apply h.dvd_of_pow_eq_one
[GOAL]
case neg.intro.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✝ : ℕ
f : F
i : ℕ
hi : Nat.coprime i k
h0 : ¬k = 0
ζ : Mˣ
h : IsPrimitiveRoot ζ k
l : ℕ
hl : (ζ ^ i) ^ l = 1
⊢ ζ ^ l = 1
[PROOFSTEP]
rw [← pow_one ζ, ← zpow_ofNat ζ, ← hi.gcd_eq_one, Nat.gcd_eq_gcd_ab, zpow_add, mul_pow, ← zpow_ofNat, ← zpow_mul,
  mul_right_comm]
[GOAL]
case neg.intro.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✝ : ℕ
f : F
i : ℕ
hi : Nat.coprime i k
h0 : ¬k = 0
ζ : Mˣ
h : IsPrimitiveRoot ζ k
l : ℕ
hl : (ζ ^ i) ^ l = 1
⊢ ζ ^ (↑i * ↑l * Nat.gcdA i k) * (ζ ^ (↑k * Nat.gcdB i k)) ^ l = 1
[PROOFSTEP]
simp only [zpow_mul, hl, h.pow_eq_one, one_zpow, one_pow, one_mul, zpow_ofNat]
[GOAL]
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 : ℕ
ζ : M
f : F
h✝ h : IsPrimitiveRoot ζ k
h0 : 0 < k
i : ℕ
⊢ IsPrimitiveRoot (ζ ^ i) k ↔ Nat.coprime i k
[PROOFSTEP]
refine' ⟨_, h.pow_of_coprime i⟩
[GOAL]
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 : ℕ
ζ : M
f : F
h✝ h : IsPrimitiveRoot ζ k
h0 : 0 < k
i : ℕ
⊢ IsPrimitiveRoot (ζ ^ i) k → Nat.coprime i k
[PROOFSTEP]
intro hi
[GOAL]
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 : ℕ
ζ : M
f : F
h✝ h : IsPrimitiveRoot ζ k
h0 : 0 < k
i : ℕ
hi : IsPrimitiveRoot (ζ ^ i) k
⊢ Nat.coprime i k
[PROOFSTEP]
obtain ⟨a, ha⟩ := i.gcd_dvd_left k
[GOAL]
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 : ℕ
ζ : M
f : F
h✝ h : IsPrimitiveRoot ζ k
h0 : 0 < k
i : ℕ
hi : IsPrimitiveRoot (ζ ^ i) k
a : ℕ
ha : i = Nat.gcd i k * a
⊢ Nat.coprime i k
[PROOFSTEP]
obtain ⟨b, hb⟩ := i.gcd_dvd_right k
[GOAL]
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 : ℕ
ζ : M
f : F
h✝ h : IsPrimitiveRoot ζ k
h0 : 0 < k
i : ℕ
hi : IsPrimitiveRoot (ζ ^ i) k
a : ℕ
ha : i = Nat.gcd i k * a
b : ℕ
hb : k = Nat.gcd i k * b
⊢ Nat.coprime i k
[PROOFSTEP]
suffices b = k by
  -- Porting note: was `rwa [this, ← one_mul k, mul_left_inj' h0.ne', eq_comm] at hb`
  rw [this, eq_comm, Nat.mul_left_eq_self_iff h0] at hb 
  rwa [Nat.coprime]
[GOAL]
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 : ℕ
ζ : M
f : F
h✝ h : IsPrimitiveRoot ζ k
h0 : 0 < k
i : ℕ
hi : IsPrimitiveRoot (ζ ^ i) k
a : ℕ
ha : i = Nat.gcd i k * a
b : ℕ
hb : k = Nat.gcd i k * b
this : b = k
⊢ Nat.coprime i k
[PROOFSTEP]
rw [this, eq_comm, Nat.mul_left_eq_self_iff h0] at hb 
[GOAL]
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 : ℕ
ζ : M
f : F
h✝ h : IsPrimitiveRoot ζ k
h0 : 0 < k
i : ℕ
hi : IsPrimitiveRoot (ζ ^ i) k
a : ℕ
ha : i = Nat.gcd i k * a
b : ℕ
hb : Nat.gcd i k = 1
this : b = k
⊢ Nat.coprime i k
[PROOFSTEP]
rwa [Nat.coprime]
[GOAL]
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 : ℕ
ζ : M
f : F
h✝ h : IsPrimitiveRoot ζ k
h0 : 0 < k
i : ℕ
hi : IsPrimitiveRoot (ζ ^ i) k
a : ℕ
ha : i = Nat.gcd i k * a
b : ℕ
hb : k = Nat.gcd i k * b
⊢ b = k
[PROOFSTEP]
rw [ha] at hi 
[GOAL]
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 : ℕ
ζ : M
f : F
h✝ h : IsPrimitiveRoot ζ k
h0 : 0 < k
i a : ℕ
hi : IsPrimitiveRoot (ζ ^ (Nat.gcd i k * a)) k
ha : i = Nat.gcd i k * a
b : ℕ
hb : k = Nat.gcd i k * b
⊢ b = k
[PROOFSTEP]
rw [mul_comm] at hb 
[GOAL]
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 : ℕ
ζ : M
f : F
h✝ h : IsPrimitiveRoot ζ k
h0 : 0 < k
i a : ℕ
hi : IsPrimitiveRoot (ζ ^ (Nat.gcd i k * a)) k
ha : i = Nat.gcd i k * a
b : ℕ
hb : k = b * Nat.gcd i k
⊢ b = k
[PROOFSTEP]
apply Nat.dvd_antisymm ⟨i.gcd k, hb⟩ (hi.dvd_of_pow_eq_one b _)
[GOAL]
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 : ℕ
ζ : M
f : F
h✝ h : IsPrimitiveRoot ζ k
h0 : 0 < k
i a : ℕ
hi : IsPrimitiveRoot (ζ ^ (Nat.gcd i k * a)) k
ha : i = Nat.gcd i k * a
b : ℕ
hb : k = b * Nat.gcd i k
⊢ (ζ ^ (Nat.gcd i k * a)) ^ b = 1
[PROOFSTEP]
rw [← pow_mul', ← mul_assoc, ← hb, pow_mul, h.pow_eq_one, one_pow]
[GOAL]
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 : ℕ
ζ : M
f : F
h : IsPrimitiveRoot ζ k
hk : 0 < k
⊢ IsPrimitiveRoot ζ k ↔ ζ ^ k = 1 ∧ ∀ (l : ℕ), 0 < l → l < k → ζ ^ l ≠ 1
[PROOFSTEP]
refine' ⟨fun h => ⟨h.pow_eq_one, fun l hl' hl => _⟩, fun ⟨hζ, hl⟩ => IsPrimitiveRoot.mk_of_lt ζ hk hζ hl⟩
[GOAL]
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✝ : ℕ
ζ : M
f : F
h✝ : IsPrimitiveRoot ζ k
hk : 0 < k
h : IsPrimitiveRoot ζ k
l : ℕ
hl' : 0 < l
hl : l < k
⊢ ζ ^ l ≠ 1
[PROOFSTEP]
rw [h.eq_orderOf] at hl 
[GOAL]
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✝ : ℕ
ζ : M
f : F
h✝ : IsPrimitiveRoot ζ k
hk : 0 < k
h : IsPrimitiveRoot ζ k
l : ℕ
hl' : 0 < l
hl : l < orderOf ζ
⊢ ζ ^ l ≠ 1
[PROOFSTEP]
exact pow_ne_one_of_lt_orderOf' hl'.ne' hl
[GOAL]
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 : ℕ
ζ : M
f : F
h✝ h : IsPrimitiveRoot ζ k
p : ℕ
hp : p ≠ 0
hdiv : p ∣ k
⊢ IsPrimitiveRoot (ζ ^ p) (k / p)
[PROOFSTEP]
suffices orderOf (ζ ^ p) = k / p by exact this ▸ IsPrimitiveRoot.orderOf (ζ ^ p)
[GOAL]
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 : ℕ
ζ : M
f : F
h✝ h : IsPrimitiveRoot ζ k
p : ℕ
hp : p ≠ 0
hdiv : p ∣ k
this : orderOf (ζ ^ p) = k / p
⊢ IsPrimitiveRoot (ζ ^ p) (k / p)
[PROOFSTEP]
exact this ▸ IsPrimitiveRoot.orderOf (ζ ^ p)
[GOAL]
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 : ℕ
ζ : M
f : F
h✝ h : IsPrimitiveRoot ζ k
p : ℕ
hp : p ≠ 0
hdiv : p ∣ k
⊢ orderOf (ζ ^ p) = k / p
[PROOFSTEP]
rw [orderOf_pow' _ hp, ← eq_orderOf h, Nat.gcd_eq_right hdiv]
[GOAL]
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 : ℕ
ζ : M
f : F
h✝ : IsPrimitiveRoot ζ k
n a b : ℕ
hn : 0 < n
h : IsPrimitiveRoot ζ n
hprod : n = a * b
⊢ IsPrimitiveRoot (ζ ^ a) b
[PROOFSTEP]
subst n
[GOAL]
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 : ℕ
ζ : M
f : F
h✝ : IsPrimitiveRoot ζ k
a b : ℕ
hn : 0 < a * b
h : IsPrimitiveRoot ζ (a * b)
⊢ IsPrimitiveRoot (ζ ^ a) b
[PROOFSTEP]
simp only [iff_def, ← pow_mul, h.pow_eq_one, eq_self_iff_true, true_and_iff]
[GOAL]
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 : ℕ
ζ : M
f : F
h✝ : IsPrimitiveRoot ζ k
a b : ℕ
hn : 0 < a * b
h : IsPrimitiveRoot ζ (a * b)
⊢ ∀ (l : ℕ), ζ ^ (a * l) = 1 → b ∣ l
[PROOFSTEP]
intro l hl
[GOAL]
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✝ : ℕ
ζ : M
f : F
h✝ : IsPrimitiveRoot ζ k
a b : ℕ
hn : 0 < a * b
h : IsPrimitiveRoot ζ (a * b)
l : ℕ
hl : ζ ^ (a * l) = 1
⊢ b ∣ l
[PROOFSTEP]
have ha0 : a ≠ 0 := left_ne_zero_of_mul hn.ne'
[GOAL]
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✝ : ℕ
ζ : M
f : F
h✝ : IsPrimitiveRoot ζ k
a b : ℕ
hn : 0 < a * b
h : IsPrimitiveRoot ζ (a * b)
l : ℕ
hl : ζ ^ (a * l) = 1
ha0 : a ≠ 0
⊢ b ∣ l
[PROOFSTEP]
rw [← mul_dvd_mul_iff_left ha0]
[GOAL]
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✝ : ℕ
ζ : M
f : F
h✝ : IsPrimitiveRoot ζ k
a b : ℕ
hn : 0 < a * b
h : IsPrimitiveRoot ζ (a * b)
l : ℕ
hl : ζ ^ (a * l) = 1
ha0 : a ≠ 0
⊢ a * b ∣ a * l
[PROOFSTEP]
exact h.dvd_of_pow_eq_one _ hl
[GOAL]
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 : ℕ
ζ : M
f : F
h✝ : IsPrimitiveRoot ζ k
inst✝ : MonoidHomClass F M N
h : IsPrimitiveRoot ζ k
hf : Injective ↑f
⊢ ↑f ζ ^ k = 1
[PROOFSTEP]
rw [← map_pow, h.pow_eq_one, _root_.map_one]
[GOAL]
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 : ℕ
ζ : M
f : F
h✝ : IsPrimitiveRoot ζ k
inst✝ : MonoidHomClass F M N
h : IsPrimitiveRoot ζ k
hf : Injective ↑f
⊢ ∀ (l : ℕ), ↑f ζ ^ l = 1 → k ∣ l
[PROOFSTEP]
rw [h.eq_orderOf]
[GOAL]
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 : ℕ
ζ : M
f : F
h✝ : IsPrimitiveRoot ζ k
inst✝ : MonoidHomClass F M N
h : IsPrimitiveRoot ζ k
hf : Injective ↑f
⊢ ∀ (l : ℕ), ↑f ζ ^ l = 1 → orderOf ζ ∣ l
[PROOFSTEP]
intro l hl
[GOAL]
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✝ : ℕ
ζ : M
f : F
h✝ : IsPrimitiveRoot ζ k
inst✝ : MonoidHomClass F M N
h : IsPrimitiveRoot ζ k
hf : Injective ↑f
l : ℕ
hl : ↑f ζ ^ l = 1
⊢ orderOf ζ ∣ l
[PROOFSTEP]
rw [← map_pow, ← map_one f] at hl 
[GOAL]
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✝ : ℕ
ζ : M
f : F
h✝ : IsPrimitiveRoot ζ k
inst✝ : MonoidHomClass F M N
h : IsPrimitiveRoot ζ k
hf : Injective ↑f
l : ℕ
hl : ↑f (ζ ^ l) = ↑f 1
⊢ orderOf ζ ∣ l
[PROOFSTEP]
exact orderOf_dvd_of_pow_eq_one (hf hl)
[GOAL]
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 : ℕ
ζ : M
f : F
h✝ : IsPrimitiveRoot ζ k
inst✝ : MonoidHomClass F M N
h : IsPrimitiveRoot (↑f ζ) k
hf : Injective ↑f
⊢ ζ ^ k = 1
[PROOFSTEP]
apply_fun f
[GOAL]
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 : ℕ
ζ : M
f : F
h✝ : IsPrimitiveRoot ζ k
inst✝ : MonoidHomClass F M N
h : IsPrimitiveRoot (↑f ζ) k
hf : Injective ↑f
⊢ ↑f (ζ ^ k) = ↑f 1
[PROOFSTEP]
rw [map_pow, _root_.map_one, h.pow_eq_one]
[GOAL]
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 : ℕ
ζ : M
f : F
h✝ : IsPrimitiveRoot ζ k
inst✝ : MonoidHomClass F M N
h : IsPrimitiveRoot (↑f ζ) k
hf : Injective ↑f
⊢ ∀ (l : ℕ), ζ ^ l = 1 → k ∣ l
[PROOFSTEP]
rw [h.eq_orderOf]
[GOAL]
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 : ℕ
ζ : M
f : F
h✝ : IsPrimitiveRoot ζ k
inst✝ : MonoidHomClass F M N
h : IsPrimitiveRoot (↑f ζ) k
hf : Injective ↑f
⊢ ∀ (l : ℕ), ζ ^ l = 1 → orderOf (↑f ζ) ∣ l
[PROOFSTEP]
intro l hl
[GOAL]
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✝ : ℕ
ζ : M
f : F
h✝ : IsPrimitiveRoot ζ k
inst✝ : MonoidHomClass F M N
h : IsPrimitiveRoot (↑f ζ) k
hf : Injective ↑f
l : ℕ
hl : ζ ^ l = 1
⊢ orderOf (↑f ζ) ∣ l
[PROOFSTEP]
apply_fun f at hl 
[GOAL]
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✝ : ℕ
ζ : M
f : F
h✝ : IsPrimitiveRoot ζ k
inst✝ : MonoidHomClass F M N
h : IsPrimitiveRoot (↑f ζ) k
hf : Injective ↑f
l : ℕ
hl : ↑f (ζ ^ l) = ↑f 1
⊢ orderOf (↑f ζ) ∣ l
[PROOFSTEP]
rw [map_pow, _root_.map_one] at hl 
[GOAL]
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✝ : ℕ
ζ : M
f : F
h✝ : IsPrimitiveRoot ζ k
inst✝ : MonoidHomClass F M N
h : IsPrimitiveRoot (↑f ζ) k
hf : Injective ↑f
l : ℕ
hl : ↑f ζ ^ l = 1
⊢ orderOf (↑f ζ) ∣ l
[PROOFSTEP]
exact orderOf_dvd_of_pow_eq_one hl
[GOAL]
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✝ : ℕ
M₀ : Type u_7
inst✝¹ : CommMonoidWithZero M₀
inst✝ : Nontrivial M₀
l : ℕ
hl : 0 ^ l = 1
⊢ 0 ∣ l
[PROOFSTEP]
simpa [zero_pow_eq, show ∀ p, ¬p → False ↔ p from @Classical.not_not] using hl
[GOAL]
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 : ℕ
ζ : G
h : IsPrimitiveRoot ζ k
⊢ ζ ^ ↑k = 1
[PROOFSTEP]
rw [zpow_ofNat]
[GOAL]
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 : ℕ
ζ : G
h : IsPrimitiveRoot ζ k
⊢ ζ ^ k = 1
[PROOFSTEP]
exact h.pow_eq_one
[GOAL]
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✝ : ℕ
ζ : G
h : IsPrimitiveRoot ζ k
l : ℤ
⊢ ζ ^ l = 1 ↔ ↑k ∣ l
[PROOFSTEP]
by_cases h0 : 0 ≤ l
[GOAL]
case pos
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✝ : ℕ
ζ : G
h : IsPrimitiveRoot ζ k
l : ℤ
h0 : 0 ≤ l
⊢ ζ ^ l = 1 ↔ ↑k ∣ l
[PROOFSTEP]
lift l to ℕ using h0
[GOAL]
case pos.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✝ : ℕ
ζ : G
h : IsPrimitiveRoot ζ k
l : ℕ
⊢ ζ ^ ↑l = 1 ↔ ↑k ∣ ↑l
[PROOFSTEP]
rw [zpow_ofNat]
[GOAL]
case pos.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✝ : ℕ
ζ : G
h : IsPrimitiveRoot ζ k
l : ℕ
⊢ ζ ^ l = 1 ↔ ↑k ∣ ↑l
[PROOFSTEP]
norm_cast
[GOAL]
case pos.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✝ : ℕ
ζ : G
h : IsPrimitiveRoot ζ k
l : ℕ
⊢ ζ ^ l = 1 ↔ k ∣ l
[PROOFSTEP]
exact h.pow_eq_one_iff_dvd l
[GOAL]
case neg
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✝ : ℕ
ζ : G
h : IsPrimitiveRoot ζ k
l : ℤ
h0 : ¬0 ≤ l
⊢ ζ ^ l = 1 ↔ ↑k ∣ l
[PROOFSTEP]
have : 0 ≤ -l := by simp only [not_le, neg_nonneg] at h0 ⊢; exact le_of_lt h0
[GOAL]
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✝ : ℕ
ζ : G
h : IsPrimitiveRoot ζ k
l : ℤ
h0 : ¬0 ≤ l
⊢ 0 ≤ -l
[PROOFSTEP]
simp only [not_le, neg_nonneg] at h0 ⊢
[GOAL]
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✝ : ℕ
ζ : G
h : IsPrimitiveRoot ζ k
l : ℤ
h0 : l < 0
⊢ l ≤ 0
[PROOFSTEP]
exact le_of_lt h0
[GOAL]
case neg
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✝ : ℕ
ζ : G
h : IsPrimitiveRoot ζ k
l : ℤ
h0 : ¬0 ≤ l
this : 0 ≤ -l
⊢ ζ ^ l = 1 ↔ ↑k ∣ l
[PROOFSTEP]
lift -l to ℕ using this with l' hl'
[GOAL]
case neg.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✝ : ℕ
ζ : G
h : IsPrimitiveRoot ζ k
l : ℤ
h0 : ¬0 ≤ l
l' : ℕ
hl' : ↑l' = -l
⊢ ζ ^ l = 1 ↔ ↑k ∣ l
[PROOFSTEP]
rw [← dvd_neg, ← hl']
[GOAL]
case neg.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✝ : ℕ
ζ : G
h : IsPrimitiveRoot ζ k
l : ℤ
h0 : ¬0 ≤ l
l' : ℕ
hl' : ↑l' = -l
⊢ ζ ^ l = 1 ↔ ↑k ∣ ↑l'
[PROOFSTEP]
norm_cast
[GOAL]
case neg.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✝ : ℕ
ζ : G
h : IsPrimitiveRoot ζ k
l : ℤ
h0 : ¬0 ≤ l
l' : ℕ
hl' : ↑l' = -l
⊢ ζ ^ l = 1 ↔ k ∣ l'
[PROOFSTEP]
rw [← h.pow_eq_one_iff_dvd, ← inv_inj, ← zpow_neg, ← hl', zpow_ofNat, inv_one]
[GOAL]
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 : ℕ
ζ : G
h : IsPrimitiveRoot ζ k
⊢ ζ⁻¹ ^ k = 1
[PROOFSTEP]
simp only [h.pow_eq_one, inv_one, eq_self_iff_true, inv_pow]
[GOAL]
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 : ℕ
ζ : G
h : IsPrimitiveRoot ζ k
⊢ ∀ (l : ℕ), ζ⁻¹ ^ l = 1 → k ∣ l
[PROOFSTEP]
intro l hl
[GOAL]
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✝ : ℕ
ζ : G
h : IsPrimitiveRoot ζ k
l : ℕ
hl : ζ⁻¹ ^ l = 1
⊢ k ∣ l
[PROOFSTEP]
apply h.dvd_of_pow_eq_one l
[GOAL]
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✝ : ℕ
ζ : G
h : IsPrimitiveRoot ζ k
l : ℕ
hl : ζ⁻¹ ^ l = 1
⊢ ζ ^ l = 1
[PROOFSTEP]
rw [← inv_inj, ← inv_pow, hl, inv_one]
[GOAL]
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 : ℕ
ζ : G
⊢ IsPrimitiveRoot ζ⁻¹ k ↔ IsPrimitiveRoot ζ k
[PROOFSTEP]
refine' ⟨_, fun h => inv h⟩
[GOAL]
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 : ℕ
ζ : G
⊢ IsPrimitiveRoot ζ⁻¹ k → IsPrimitiveRoot ζ k
[PROOFSTEP]
intro h
[GOAL]
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 : ℕ
ζ : G
h : IsPrimitiveRoot ζ⁻¹ k
⊢ IsPrimitiveRoot ζ k
[PROOFSTEP]
rw [← inv_inv ζ]
[GOAL]
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 : ℕ
ζ : G
h : IsPrimitiveRoot ζ⁻¹ k
⊢ IsPrimitiveRoot ζ⁻¹⁻¹ k
[PROOFSTEP]
exact inv h
[GOAL]
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 : ℕ
ζ : G
h : IsPrimitiveRoot ζ k
i : ℤ
hi : Int.gcd i ↑k = 1
⊢ IsPrimitiveRoot (ζ ^ i) k
[PROOFSTEP]
by_cases h0 : 0 ≤ i
[GOAL]
case pos
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 : ℕ
ζ : G
h : IsPrimitiveRoot ζ k
i : ℤ
hi : Int.gcd i ↑k = 1
h0 : 0 ≤ i
⊢ IsPrimitiveRoot (ζ ^ i) k
[PROOFSTEP]
lift i to ℕ using h0
[GOAL]
case pos.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 : ℕ
ζ : G
h : IsPrimitiveRoot ζ k
i : ℕ
hi : Int.gcd ↑i ↑k = 1
⊢ IsPrimitiveRoot (ζ ^ ↑i) k
[PROOFSTEP]
rw [zpow_ofNat]
[GOAL]
case pos.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 : ℕ
ζ : G
h : IsPrimitiveRoot ζ k
i : ℕ
hi : Int.gcd ↑i ↑k = 1
⊢ IsPrimitiveRoot (ζ ^ i) k
[PROOFSTEP]
exact h.pow_of_coprime i hi
[GOAL]
case neg
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 : ℕ
ζ : G
h : IsPrimitiveRoot ζ k
i : ℤ
hi : Int.gcd i ↑k = 1
h0 : ¬0 ≤ i
⊢ IsPrimitiveRoot (ζ ^ i) k
[PROOFSTEP]
have : 0 ≤ -i := by simp only [not_le, neg_nonneg] at h0 ⊢; exact le_of_lt h0
[GOAL]
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 : ℕ
ζ : G
h : IsPrimitiveRoot ζ k
i : ℤ
hi : Int.gcd i ↑k = 1
h0 : ¬0 ≤ i
⊢ 0 ≤ -i
[PROOFSTEP]
simp only [not_le, neg_nonneg] at h0 ⊢
[GOAL]
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 : ℕ
ζ : G
h : IsPrimitiveRoot ζ k
i : ℤ
hi : Int.gcd i ↑k = 1
h0 : i < 0
⊢ i ≤ 0
[PROOFSTEP]
exact le_of_lt h0
[GOAL]
case neg
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 : ℕ
ζ : G
h : IsPrimitiveRoot ζ k
i : ℤ
hi : Int.gcd i ↑k = 1
h0 : ¬0 ≤ i
this : 0 ≤ -i
⊢ IsPrimitiveRoot (ζ ^ i) k
[PROOFSTEP]
lift -i to ℕ using this with i' hi'
[GOAL]
case neg.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 : ℕ
ζ : G
h : IsPrimitiveRoot ζ k
i : ℤ
hi : Int.gcd i ↑k = 1
h0 : ¬0 ≤ i
i' : ℕ
hi' : ↑i' = -i
⊢ IsPrimitiveRoot (ζ ^ i) k
[PROOFSTEP]
rw [← inv_iff, ← zpow_neg, ← hi', zpow_ofNat]
[GOAL]
case neg.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 : ℕ
ζ : G
h : IsPrimitiveRoot ζ k
i : ℤ
hi : Int.gcd i ↑k = 1
h0 : ¬0 ≤ i
i' : ℕ
hi' : ↑i' = -i
⊢ IsPrimitiveRoot (ζ ^ i') k
[PROOFSTEP]
apply h.pow_of_coprime
[GOAL]
case neg.intro.hi
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 : ℕ
ζ : G
h : IsPrimitiveRoot ζ k
i : ℤ
hi : Int.gcd i ↑k = 1
h0 : ¬0 ≤ i
i' : ℕ
hi' : ↑i' = -i
⊢ Nat.coprime i' k
[PROOFSTEP]
rw [Int.gcd, ← Int.natAbs_neg, ← hi'] at hi 
[GOAL]
case neg.intro.hi
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 : ℕ
ζ : G
h : IsPrimitiveRoot ζ k
i : ℤ
h0 : ¬0 ≤ i
i' : ℕ
hi : Nat.gcd (Int.natAbs ↑i') (Int.natAbs ↑k) = 1
hi' : ↑i' = -i
⊢ Nat.coprime i' k
[PROOFSTEP]
exact hi
[GOAL]
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 : ℕ
ζ : R
inst✝¹ : CommRing R
inst✝ : IsDomain R
⊢ primitiveRoots 1 R = {1}
[PROOFSTEP]
apply Finset.eq_singleton_iff_unique_mem.2
[GOAL]
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 : ℕ
ζ : R
inst✝¹ : CommRing R
inst✝ : IsDomain R
⊢ 1 ∈ primitiveRoots 1 R ∧ ∀ (x : R), x ∈ primitiveRoots 1 R → x = 1
[PROOFSTEP]
constructor
[GOAL]
case left
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 : ℕ
ζ : R
inst✝¹ : CommRing R
inst✝ : IsDomain R
⊢ 1 ∈ primitiveRoots 1 R
[PROOFSTEP]
simp only [IsPrimitiveRoot.one_right_iff, mem_primitiveRoots zero_lt_one]
[GOAL]
case right
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 : ℕ
ζ : R
inst✝¹ : CommRing R
inst✝ : IsDomain R
⊢ ∀ (x : R), x ∈ primitiveRoots 1 R → x = 1
[PROOFSTEP]
intro x hx
[GOAL]
case right
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 : ℕ
ζ : R
inst✝¹ : CommRing R
inst✝ : IsDomain R
x : R
hx : x ∈ primitiveRoots 1 R
⊢ x = 1
[PROOFSTEP]
rw [mem_primitiveRoots zero_lt_one, IsPrimitiveRoot.one_right_iff] at hx 
[GOAL]
case right
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 : ℕ
ζ : R
inst✝¹ : CommRing R
inst✝ : IsDomain R
x : R
hx : x = 1
⊢ x = 1
[PROOFSTEP]
exact hx
[GOAL]
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 : ℕ
ζ : R
inst✝¹ : CommRing R
inst✝ : IsDomain R
n : ℕ+
hζ : IsPrimitiveRoot ζ ↑n
⊢ NeZero ↑↑n
[PROOFSTEP]
let p := ringChar R
[GOAL]
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 : ℕ
ζ : R
inst✝¹ : CommRing R
inst✝ : IsDomain R
n : ℕ+
hζ : IsPrimitiveRoot ζ ↑n
p : ℕ := ringChar R
⊢ NeZero ↑↑n
[PROOFSTEP]
have hfin := multiplicity.finite_nat_iff.2 ⟨CharP.char_ne_one R p, n.pos⟩
[GOAL]
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 : ℕ
ζ : R
inst✝¹ : CommRing R
inst✝ : IsDomain R
n : ℕ+
hζ : IsPrimitiveRoot ζ ↑n
p : ℕ := ringChar R
hfin : multiplicity.Finite p ↑n
⊢ NeZero ↑↑n
[PROOFSTEP]
obtain ⟨m, hm⟩ := multiplicity.exists_eq_pow_mul_and_not_dvd hfin
[GOAL]
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 : ℕ
ζ : R
inst✝¹ : CommRing R
inst✝ : IsDomain R
n : ℕ+
hζ : IsPrimitiveRoot ζ ↑n
p : ℕ := ringChar R
hfin : multiplicity.Finite p ↑n
m : ℕ
hm : ↑n = p ^ Part.get (multiplicity p ↑n) hfin * m ∧ ¬p ∣ m
⊢ NeZero ↑↑n
[PROOFSTEP]
by_cases hp : p ∣ n
[GOAL]
case pos
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 : ℕ
ζ : R
inst✝¹ : CommRing R
inst✝ : IsDomain R
n : ℕ+
hζ : IsPrimitiveRoot ζ ↑n
p : ℕ := ringChar R
hfin : multiplicity.Finite p ↑n
m : ℕ
hm : ↑n = p ^ Part.get (multiplicity p ↑n) hfin * m ∧ ¬p ∣ m
hp : p ∣ ↑n
⊢ NeZero ↑↑n
[PROOFSTEP]
obtain ⟨k, hk⟩ := Nat.exists_eq_succ_of_ne_zero (multiplicity.pos_of_dvd hfin hp).ne'
[GOAL]
case pos.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 : ℕ
ζ : R
inst✝¹ : CommRing R
inst✝ : IsDomain R
n : ℕ+
hζ : IsPrimitiveRoot ζ ↑n
p : ℕ := ringChar R
hfin : multiplicity.Finite p ↑n
m : ℕ
hm : ↑n = p ^ Part.get (multiplicity p ↑n) hfin * m ∧ ¬p ∣ m
hp : p ∣ ↑n
k : ℕ
hk : Part.get (multiplicity p ↑n) hfin = Nat.succ k
⊢ NeZero ↑↑n
[PROOFSTEP]
haveI : NeZero p := NeZero.of_pos (Nat.pos_of_dvd_of_pos hp n.pos)
[GOAL]
case pos.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 : ℕ
ζ : R
inst✝¹ : CommRing R
inst✝ : IsDomain R
n : ℕ+
hζ : IsPrimitiveRoot ζ ↑n
p : ℕ := ringChar R
hfin : multiplicity.Finite p ↑n
m : ℕ
hm : ↑n = p ^ Part.get (multiplicity p ↑n) hfin * m ∧ ¬p ∣ m
hp : p ∣ ↑n
k : ℕ
hk : Part.get (multiplicity p ↑n) hfin = Nat.succ k
this : NeZero p
⊢ NeZero ↑↑n
[PROOFSTEP]
haveI hpri : Fact p.Prime := CharP.char_is_prime_of_pos R p
[GOAL]
case pos.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 : ℕ
ζ : R
inst✝¹ : CommRing R
inst✝ : IsDomain R
n : ℕ+
hζ : IsPrimitiveRoot ζ ↑n
p : ℕ := ringChar R
hfin : multiplicity.Finite p ↑n
m : ℕ
hm : ↑n = p ^ Part.get (multiplicity p ↑n) hfin * m ∧ ¬p ∣ m
hp : p ∣ ↑n
k : ℕ
hk : Part.get (multiplicity p ↑n) hfin = Nat.succ k
this : NeZero p
hpri : Fact (Nat.Prime p)
⊢ NeZero ↑↑n
[PROOFSTEP]
have := hζ.pow_eq_one
[GOAL]
case pos.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 : ℕ
ζ : R
inst✝¹ : CommRing R
inst✝ : IsDomain R
n : ℕ+
hζ : IsPrimitiveRoot ζ ↑n
p : ℕ := ringChar R
hfin : multiplicity.Finite p ↑n
m : ℕ
hm : ↑n = p ^ Part.get (multiplicity p ↑n) hfin * m ∧ ¬p ∣ m
hp : p ∣ ↑n
k : ℕ
hk : Part.get (multiplicity p ↑n) hfin = Nat.succ k
this✝ : NeZero p
hpri : Fact (Nat.Prime p)
this : ζ ^ ↑n = 1
⊢ NeZero ↑↑n
[PROOFSTEP]
rw [hm.1, hk, pow_succ, mul_assoc, pow_mul', ← frobenius_def, ← frobenius_one p] at this 
[GOAL]
case pos.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 : ℕ
ζ : R
inst✝¹ : CommRing R
inst✝ : IsDomain R
n : ℕ+
hζ : IsPrimitiveRoot ζ ↑n
p : ℕ := ringChar R
hfin : multiplicity.Finite p ↑n
m : ℕ
hm : ↑n = p ^ Part.get (multiplicity p ↑n) hfin * m ∧ ¬p ∣ m
hp : p ∣ ↑n
k : ℕ
hk : Part.get (multiplicity p ↑n) hfin = Nat.succ k
this✝¹ : NeZero p
hpri : Fact (Nat.Prime p)
this✝ : ↑(frobenius R p) (ζ ^ (p ^ k * m)) = 1
this : ↑(frobenius R p) (ζ ^ (p ^ k * m)) = ↑(frobenius R p) 1
⊢ NeZero ↑↑n
[PROOFSTEP]
exfalso
[GOAL]
case pos.intro.h
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 : ℕ
ζ : R
inst✝¹ : CommRing R
inst✝ : IsDomain R
n : ℕ+
hζ : IsPrimitiveRoot ζ ↑n
p : ℕ := ringChar R
hfin : multiplicity.Finite p ↑n
m : ℕ
hm : ↑n = p ^ Part.get (multiplicity p ↑n) hfin * m ∧ ¬p ∣ m
hp : p ∣ ↑n
k : ℕ
hk : Part.get (multiplicity p ↑n) hfin = Nat.succ k
this✝¹ : NeZero p
hpri : Fact (Nat.Prime p)
this✝ : ↑(frobenius R p) (ζ ^ (p ^ k * m)) = 1
this : ↑(frobenius R p) (ζ ^ (p ^ k * m)) = ↑(frobenius R p) 1
⊢ False
[PROOFSTEP]
have hpos : 0 < p ^ k * m :=
  by
  refine' mul_pos (pow_pos hpri.1.pos _) (Nat.pos_of_ne_zero fun h => _)
  have H := hm.1
  rw [h] at H 
  simp at H 
[GOAL]
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 : ℕ
ζ : R
inst✝¹ : CommRing R
inst✝ : IsDomain R
n : ℕ+
hζ : IsPrimitiveRoot ζ ↑n
p : ℕ := ringChar R
hfin : multiplicity.Finite p ↑n
m : ℕ
hm : ↑n = p ^ Part.get (multiplicity p ↑n) hfin * m ∧ ¬p ∣ m
hp : p ∣ ↑n
k : ℕ
hk : Part.get (multiplicity p ↑n) hfin = Nat.succ k
this✝¹ : NeZero p
hpri : Fact (Nat.Prime p)
this✝ : ↑(frobenius R p) (ζ ^ (p ^ k * m)) = 1
this : ↑(frobenius R p) (ζ ^ (p ^ k * m)) = ↑(frobenius R p) 1
⊢ 0 < p ^ k * m
[PROOFSTEP]
refine' mul_pos (pow_pos hpri.1.pos _) (Nat.pos_of_ne_zero fun h => _)
[GOAL]
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 : ℕ
ζ : R
inst✝¹ : CommRing R
inst✝ : IsDomain R
n : ℕ+
hζ : IsPrimitiveRoot ζ ↑n
p : ℕ := ringChar R
hfin : multiplicity.Finite p ↑n
m : ℕ
hm : ↑n = p ^ Part.get (multiplicity p ↑n) hfin * m ∧ ¬p ∣ m
hp : p ∣ ↑n
k : ℕ
hk : Part.get (multiplicity p ↑n) hfin = Nat.succ k
this✝¹ : NeZero p
hpri : Fact (Nat.Prime p)
this✝ : ↑(frobenius R p) (ζ ^ (p ^ k * m)) = 1
this : ↑(frobenius R p) (ζ ^ (p ^ k * m)) = ↑(frobenius R p) 1
h : m = 0
⊢ False
[PROOFSTEP]
have H := hm.1
[GOAL]
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 : ℕ
ζ : R
inst✝¹ : CommRing R
inst✝ : IsDomain R
n : ℕ+
hζ : IsPrimitiveRoot ζ ↑n
p : ℕ := ringChar R
hfin : multiplicity.Finite p ↑n
m : ℕ
hm : ↑n = p ^ Part.get (multiplicity p ↑n) hfin * m ∧ ¬p ∣ m
hp : p ∣ ↑n
k : ℕ
hk : Part.get (multiplicity p ↑n) hfin = Nat.succ k
this✝¹ : NeZero p
hpri : Fact (Nat.Prime p)
this✝ : ↑(frobenius R p) (ζ ^ (p ^ k * m)) = 1
this : ↑(frobenius R p) (ζ ^ (p ^ k * m)) = ↑(frobenius R p) 1
h : m = 0
H : ↑n = p ^ Part.get (multiplicity p ↑n) hfin * m
⊢ False
[PROOFSTEP]
rw [h] at H 
[GOAL]
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 : ℕ
ζ : R
inst✝¹ : CommRing R
inst✝ : IsDomain R
n : ℕ+
hζ : IsPrimitiveRoot ζ ↑n
p : ℕ := ringChar R
hfin : multiplicity.Finite p ↑n
m : ℕ
hm : ↑n = p ^ Part.get (multiplicity p ↑n) hfin * m ∧ ¬p ∣ m
hp : p ∣ ↑n
k : ℕ
hk : Part.get (multiplicity p ↑n) hfin = Nat.succ k
this✝¹ : NeZero p
hpri : Fact (Nat.Prime p)
this✝ : ↑(frobenius R p) (ζ ^ (p ^ k * m)) = 1
this : ↑(frobenius R p) (ζ ^ (p ^ k * m)) = ↑(frobenius R p) 1
h : m = 0
H : ↑n = p ^ Part.get (multiplicity p ↑n) hfin * 0
⊢ False
[PROOFSTEP]
simp at H 
[GOAL]
case pos.intro.h
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 : ℕ
ζ : R
inst✝¹ : CommRing R
inst✝ : IsDomain R
n : ℕ+
hζ : IsPrimitiveRoot ζ ↑n
p : ℕ := ringChar R
hfin : multiplicity.Finite p ↑n
m : ℕ
hm : ↑n = p ^ Part.get (multiplicity p ↑n) hfin * m ∧ ¬p ∣ m
hp : p ∣ ↑n
k : ℕ
hk : Part.get (multiplicity p ↑n) hfin = Nat.succ k
this✝¹ : NeZero p
hpri : Fact (Nat.Prime p)
this✝ : ↑(frobenius R p) (ζ ^ (p ^ k * m)) = 1
this : ↑(frobenius R p) (ζ ^ (p ^ k * m)) = ↑(frobenius R p) 1
hpos : 0 < p ^ k * m
⊢ False
[PROOFSTEP]
refine' hζ.pow_ne_one_of_pos_of_lt hpos _ (frobenius_inj R p this)
[GOAL]
case pos.intro.h
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 : ℕ
ζ : R
inst✝¹ : CommRing R
inst✝ : IsDomain R
n : ℕ+
hζ : IsPrimitiveRoot ζ ↑n
p : ℕ := ringChar R
hfin : multiplicity.Finite p ↑n
m : ℕ
hm : ↑n = p ^ Part.get (multiplicity p ↑n) hfin * m ∧ ¬p ∣ m
hp : p ∣ ↑n
k : ℕ
hk : Part.get (multiplicity p ↑n) hfin = Nat.succ k
this✝¹ : NeZero p
hpri : Fact (Nat.Prime p)
this✝ : ↑(frobenius R p) (ζ ^ (p ^ k * m)) = 1
this : ↑(frobenius R p) (ζ ^ (p ^ k * m)) = ↑(frobenius R p) 1
hpos : 0 < p ^ k * m
⊢ p ^ k * m < ↑n
[PROOFSTEP]
rw [hm.1, hk, pow_succ, mul_assoc, mul_comm p]
[GOAL]
case pos.intro.h
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 : ℕ
ζ : R
inst✝¹ : CommRing R
inst✝ : IsDomain R
n : ℕ+
hζ : IsPrimitiveRoot ζ ↑n
p : ℕ := ringChar R
hfin : multiplicity.Finite p ↑n
m : ℕ
hm : ↑n = p ^ Part.get (multiplicity p ↑n) hfin * m ∧ ¬p ∣ m
hp : p ∣ ↑n
k : ℕ
hk : Part.get (multiplicity p ↑n) hfin = Nat.succ k
this✝¹ : NeZero p
hpri : Fact (Nat.Prime p)
this✝ : ↑(frobenius R p) (ζ ^ (p ^ k * m)) = 1
this : ↑(frobenius R p) (ζ ^ (p ^ k * m)) = ↑(frobenius R p) 1
hpos : 0 < p ^ k * m
⊢ p ^ k * m < p ^ k * m * p
[PROOFSTEP]
exact lt_mul_of_one_lt_right hpos hpri.1.one_lt
[GOAL]
case neg
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 : ℕ
ζ : R
inst✝¹ : CommRing R
inst✝ : IsDomain R
n : ℕ+
hζ : IsPrimitiveRoot ζ ↑n
p : ℕ := ringChar R
hfin : multiplicity.Finite p ↑n
m : ℕ
hm : ↑n = p ^ Part.get (multiplicity p ↑n) hfin * m ∧ ¬p ∣ m
hp : ¬p ∣ ↑n
⊢ NeZero ↑↑n
[PROOFSTEP]
exact NeZero.of_not_dvd R hp
[GOAL]
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✝ : NoZeroDivisors R
ζ : R
h : IsPrimitiveRoot ζ 2
⊢ ζ = -1
[PROOFSTEP]
apply (eq_or_eq_neg_of_sq_eq_sq ζ 1 _).resolve_left
[GOAL]
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✝ : NoZeroDivisors R
ζ : R
h : IsPrimitiveRoot ζ 2
⊢ ¬ζ = 1
[PROOFSTEP]
rw [← pow_one ζ]
[GOAL]
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✝ : NoZeroDivisors R
ζ : R
h : IsPrimitiveRoot ζ 2
⊢ ¬ζ ^ 1 = 1
[PROOFSTEP]
apply h.pow_ne_one_of_pos_of_lt
[GOAL]
case h0
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✝ : NoZeroDivisors R
ζ : R
h : IsPrimitiveRoot ζ 2
⊢ 0 < 1
[PROOFSTEP]
decide
[GOAL]
case hl
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✝ : NoZeroDivisors R
ζ : R
h : IsPrimitiveRoot ζ 2
⊢ 1 < 2
[PROOFSTEP]
decide
[GOAL]
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✝ : NoZeroDivisors R
ζ : R
h : IsPrimitiveRoot ζ 2
⊢ ζ ^ 2 = 1 ^ 2
[PROOFSTEP]
simp only [h.pow_eq_one, one_pow]
[GOAL]
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
p : ℕ
inst✝ : Nontrivial R
h : CharP R p
hp : p ≠ 2
⊢ IsPrimitiveRoot (-1) 2
[PROOFSTEP]
convert IsPrimitiveRoot.orderOf (-1 : R)
[GOAL]
case h.e'_4
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
p : ℕ
inst✝ : Nontrivial R
h : CharP R p
hp : p ≠ 2
⊢ 2 = orderOf (-1)
[PROOFSTEP]
rw [orderOf_neg_one, if_neg]
[GOAL]
case h.e'_4.hnc
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
p : ℕ
inst✝ : Nontrivial R
h : CharP R p
hp : p ≠ 2
⊢ ¬ringChar R = 2
[PROOFSTEP]
rwa [ringChar.eq_iff.mpr h]
[GOAL]
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
⊢ ∑ i in range k, ζ ^ i = 0
[PROOFSTEP]
refine' eq_zero_of_ne_zero_of_mul_left_eq_zero (sub_ne_zero_of_ne (hζ.ne_one hk).symm) _
[GOAL]
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
[PROOFSTEP]
rw [mul_neg_geom_sum, hζ.pow_eq_one, sub_self]
[GOAL]
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
[PROOFSTEP]
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]
[GOAL]
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_1 => x ^ x_1) ζ i,
            property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
      0 =
    0
[PROOFSTEP]
simp only [zpow_zero]
[GOAL]
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
[PROOFSTEP]
rfl
[GOAL]
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_1 => x ^ x_1) ζ i,
                property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
          map_zero' :=
            (_ :
              (fun i =>
                    ↑Additive.ofMul
                      { val := (fun x x_1 => x ^ x_1) ζ i,
                        property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                  0 =
                0) }
        (x + y) =
      ZeroHom.toFun
          {
            toFun := fun i =>
              ↑Additive.ofMul
                { val := (fun x x_1 => x ^ x_1) ζ i,
                  property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
            map_zero' :=
              (_ :
                (fun i =>
                      ↑Additive.ofMul
                        { val := (fun x x_1 => x ^ x_1) ζ i,
                          property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                    0 =
                  0) }
          x +
        ZeroHom.toFun
          {
            toFun := fun i =>
              ↑Additive.ofMul
                { val := (fun x x_1 => x ^ x_1) ζ i,
                  property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
            map_zero' :=
              (_ :
                (fun i =>
                      ↑Additive.ofMul
                        { val := (fun x x_1 => x ^ x_1) ζ i,
                          property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                    0 =
                  0) }
          y
[PROOFSTEP]
intro i j
[GOAL]
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_1 => x ^ x_1) ζ i,
              property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
        map_zero' :=
          (_ :
            (fun i =>
                  ↑Additive.ofMul
                    { val := (fun x x_1 => x ^ x_1) ζ i,
                      property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                0 =
              0) }
      (i + j) =
    ZeroHom.toFun
        {
          toFun := fun i =>
            ↑Additive.ofMul
              { val := (fun x x_1 => x ^ x_1) ζ i,
                property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
          map_zero' :=
            (_ :
              (fun i =>
                    ↑Additive.ofMul
                      { val := (fun x x_1 => x ^ x_1) ζ i,
                        property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                  0 =
                0) }
        i +
      ZeroHom.toFun
        {
          toFun := fun i =>
            ↑Additive.ofMul
              { val := (fun x x_1 => x ^ x_1) ζ i,
                property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
          map_zero' :=
            (_ :
              (fun i =>
                    ↑Additive.ofMul
                      { val := (fun x x_1 => x ^ x_1) ζ i,
                        property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                  0 =
                0) }
        j
[PROOFSTEP]
simp only [zpow_add]
[GOAL]
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_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) } +
      ↑Additive.ofMul { val := ζ ^ j, property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ j) }
[PROOFSTEP]
rfl
[GOAL]
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 : i ∈ AddMonoidHom.ker (Int.castAddHom (ZMod k))
⊢ i ∈
    AddMonoidHom.ker
      {
        toZeroHom :=
          {
            toFun := fun i =>
              ↑Additive.ofMul
                { val := (fun x x_1 => x ^ x_1) ζ i,
                  property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
            map_zero' :=
              (_ :
                (fun i =>
                      ↑Additive.ofMul
                        { val := (fun x x_1 => x ^ x_1) ζ i,
                          property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                    0 =
                  0) },
        map_add' :=
          (_ :
            ∀ (i j : ℤ),
              ZeroHom.toFun
                  {
                    toFun := fun i =>
                      ↑Additive.ofMul
                        { val := (fun x x_1 => x ^ x_1) ζ i,
                          property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                    map_zero' :=
                      (_ :
                        (fun i =>
                              ↑Additive.ofMul
                                { val := (fun x x_1 => x ^ x_1) ζ i,
                                  property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                            0 =
                          0) }
                  (i + j) =
                ZeroHom.toFun
                    {
                      toFun := fun i =>
                        ↑Additive.ofMul
                          { val := (fun x x_1 => x ^ x_1) ζ i,
                            property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                      map_zero' :=
                        (_ :
                          (fun i =>
                                ↑Additive.ofMul
                                  { val := (fun x x_1 => x ^ x_1) ζ i,
                                    property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                              0 =
                            0) }
                    i +
                  ZeroHom.toFun
                    {
                      toFun := fun i =>
                        ↑Additive.ofMul
                          { val := (fun x x_1 => x ^ x_1) ζ i,
                            property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                      map_zero' :=
                        (_ :
                          (fun i =>
                                ↑Additive.ofMul
                                  { val := (fun x x_1 => x ^ x_1) ζ i,
                                    property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                              0 =
                            0) }
                    j) }
[PROOFSTEP]
simp only [AddMonoidHom.mem_ker, CharP.int_cast_eq_zero_iff (ZMod k) k, AddMonoidHom.coe_mk, Int.coe_castAddHom] at hi ⊢
[GOAL]
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_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
          map_zero' :=
            (_ :
              (fun i =>
                    ↑Additive.ofMul
                      { val := (fun x x_1 => x ^ x_1) ζ i,
                        property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                  0 =
                0) }
      i =
    0
[PROOFSTEP]
obtain ⟨i, rfl⟩ := hi
[GOAL]
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_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
          map_zero' :=
            (_ :
              (fun i =>
                    ↑Additive.ofMul
                      { val := (fun x x_1 => x ^ x_1) ζ i,
                        property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                  0 =
                0) }
      (↑k * i) =
    0
[PROOFSTEP]
simp [zpow_mul, h.pow_eq_one, one_zpow, zpow_ofNat]
[GOAL]
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
⊢ Function.Bijective
    ↑(↑(AddMonoidHom.liftOfRightInverse (Int.castAddHom (ZMod k)) ZMod.cast
            (_ : Function.RightInverse ZMod.cast Int.cast))
        {
          val :=
            {
              toZeroHom :=
                {
                  toFun := fun i =>
                    ↑Additive.ofMul
                      { val := (fun x x_1 => x ^ x_1) ζ i,
                        property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                  map_zero' :=
                    (_ :
                      (fun i =>
                            ↑Additive.ofMul
                              { val := (fun x x_1 => x ^ x_1) ζ i,
                                property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                          0 =
                        0) },
              map_add' :=
                (_ :
                  ∀ (i j : ℤ),
                    ZeroHom.toFun
                        {
                          toFun := fun i =>
                            ↑Additive.ofMul
                              { val := (fun x x_1 => x ^ x_1) ζ i,
                                property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                          map_zero' :=
                            (_ :
                              (fun i =>
                                    ↑Additive.ofMul
                                      { val := (fun x x_1 => x ^ x_1) ζ i,
                                        property :=
                                          (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                  0 =
                                0) }
                        (i + j) =
                      ZeroHom.toFun
                          {
                            toFun := fun i =>
                              ↑Additive.ofMul
                                { val := (fun x x_1 => x ^ x_1) ζ i,
                                  property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                            map_zero' :=
                              (_ :
                                (fun i =>
                                      ↑Additive.ofMul
                                        { val := (fun x x_1 => x ^ x_1) ζ i,
                                          property :=
                                            (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                    0 =
                                  0) }
                          i +
                        ZeroHom.toFun
                          {
                            toFun := fun i =>
                              ↑Additive.ofMul
                                { val := (fun x x_1 => x ^ x_1) ζ i,
                                  property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                            map_zero' :=
                              (_ :
                                (fun i =>
                                      ↑Additive.ofMul
                                        { val := (fun x x_1 => x ^ x_1) ζ i,
                                          property :=
                                            (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                    0 =
                                  0) }
                          j) },
          property :=
            (_ :
              ∀ (i : ℤ),
                i ∈ AddMonoidHom.ker (Int.castAddHom (ZMod k)) →
                  i ∈
                    AddMonoidHom.ker
                      {
                        toZeroHom :=
                          {
                            toFun := fun i =>
                              ↑Additive.ofMul
                                { val := (fun x x_1 => x ^ x_1) ζ i,
                                  property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                            map_zero' :=
                              (_ :
                                (fun i =>
                                      ↑Additive.ofMul
                                        { val := (fun x x_1 => x ^ x_1) ζ i,
                                          property :=
                                            (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                    0 =
                                  0) },
                        map_add' :=
                          (_ :
                            ∀ (i j : ℤ),
                              ZeroHom.toFun
                                  {
                                    toFun := fun i =>
                                      ↑Additive.ofMul
                                        { val := (fun x x_1 => x ^ x_1) ζ i,
                                          property :=
                                            (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                    map_zero' :=
                                      (_ :
                                        (fun i =>
                                              ↑Additive.ofMul
                                                { val := (fun x x_1 => x ^ x_1) ζ i,
                                                  property :=
                                                    (_ :
                                                      ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                            0 =
                                          0) }
                                  (i + j) =
                                ZeroHom.toFun
                                    {
                                      toFun := fun i =>
                                        ↑Additive.ofMul
                                          { val := (fun x x_1 => x ^ x_1) ζ i,
                                            property :=
                                              (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                      map_zero' :=
                                        (_ :
                                          (fun i =>
                                                ↑Additive.ofMul
                                                  { val := (fun x x_1 => x ^ x_1) ζ i,
                                                    property :=
                                                      (_ :
                                                        ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                              0 =
                                            0) }
                                    i +
                                  ZeroHom.toFun
                                    {
                                      toFun := fun i =>
                                        ↑Additive.ofMul
                                          { val := (fun x x_1 => x ^ x_1) ζ i,
                                            property :=
                                              (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                      map_zero' :=
                                        (_ :
                                          (fun i =>
                                                ↑Additive.ofMul
                                                  { val := (fun x x_1 => x ^ x_1) ζ i,
                                                    property :=
                                                      (_ :
                                                        ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                              0 =
                                            0) }
                                    j) }) })
[PROOFSTEP]
constructor
[GOAL]
case left
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
⊢ Function.Injective
    ↑(↑(AddMonoidHom.liftOfRightInverse (Int.castAddHom (ZMod k)) ZMod.cast
            (_ : Function.RightInverse ZMod.cast Int.cast))
        {
          val :=
            {
              toZeroHom :=
                {
                  toFun := fun i =>
                    ↑Additive.ofMul
                      { val := (fun x x_1 => x ^ x_1) ζ i,
                        property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                  map_zero' :=
                    (_ :
                      (fun i =>
                            ↑Additive.ofMul
                              { val := (fun x x_1 => x ^ x_1) ζ i,
                                property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                          0 =
                        0) },
              map_add' :=
                (_ :
                  ∀ (i j : ℤ),
                    ZeroHom.toFun
                        {
                          toFun := fun i =>
                            ↑Additive.ofMul
                              { val := (fun x x_1 => x ^ x_1) ζ i,
                                property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                          map_zero' :=
                            (_ :
                              (fun i =>
                                    ↑Additive.ofMul
                                      { val := (fun x x_1 => x ^ x_1) ζ i,
                                        property :=
                                          (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                  0 =
                                0) }
                        (i + j) =
                      ZeroHom.toFun
                          {
                            toFun := fun i =>
                              ↑Additive.ofMul
                                { val := (fun x x_1 => x ^ x_1) ζ i,
                                  property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                            map_zero' :=
                              (_ :
                                (fun i =>
                                      ↑Additive.ofMul
                                        { val := (fun x x_1 => x ^ x_1) ζ i,
                                          property :=
                                            (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                    0 =
                                  0) }
                          i +
                        ZeroHom.toFun
                          {
                            toFun := fun i =>
                              ↑Additive.ofMul
                                { val := (fun x x_1 => x ^ x_1) ζ i,
                                  property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                            map_zero' :=
                              (_ :
                                (fun i =>
                                      ↑Additive.ofMul
                                        { val := (fun x x_1 => x ^ x_1) ζ i,
                                          property :=
                                            (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                    0 =
                                  0) }
                          j) },
          property :=
            (_ :
              ∀ (i : ℤ),
                i ∈ AddMonoidHom.ker (Int.castAddHom (ZMod k)) →
                  i ∈
                    AddMonoidHom.ker
                      {
                        toZeroHom :=
                          {
                            toFun := fun i =>
                              ↑Additive.ofMul
                                { val := (fun x x_1 => x ^ x_1) ζ i,
                                  property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                            map_zero' :=
                              (_ :
                                (fun i =>
                                      ↑Additive.ofMul
                                        { val := (fun x x_1 => x ^ x_1) ζ i,
                                          property :=
                                            (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                    0 =
                                  0) },
                        map_add' :=
                          (_ :
                            ∀ (i j : ℤ),
                              ZeroHom.toFun
                                  {
                                    toFun := fun i =>
                                      ↑Additive.ofMul
                                        { val := (fun x x_1 => x ^ x_1) ζ i,
                                          property :=
                                            (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                    map_zero' :=
                                      (_ :
                                        (fun i =>
                                              ↑Additive.ofMul
                                                { val := (fun x x_1 => x ^ x_1) ζ i,
                                                  property :=
                                                    (_ :
                                                      ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                            0 =
                                          0) }
                                  (i + j) =
                                ZeroHom.toFun
                                    {
                                      toFun := fun i =>
                                        ↑Additive.ofMul
                                          { val := (fun x x_1 => x ^ x_1) ζ i,
                                            property :=
                                              (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                      map_zero' :=
                                        (_ :
                                          (fun i =>
                                                ↑Additive.ofMul
                                                  { val := (fun x x_1 => x ^ x_1) ζ i,
                                                    property :=
                                                      (_ :
                                                        ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                              0 =
                                            0) }
                                    i +
                                  ZeroHom.toFun
                                    {
                                      toFun := fun i =>
                                        ↑Additive.ofMul
                                          { val := (fun x x_1 => x ^ x_1) ζ i,
                                            property :=
                                              (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                      map_zero' :=
                                        (_ :
                                          (fun i =>
                                                ↑Additive.ofMul
                                                  { val := (fun x x_1 => x ^ x_1) ζ i,
                                                    property :=
                                                      (_ :
                                                        ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                              0 =
                                            0) }
                                    j) }) })
[PROOFSTEP]
rw [injective_iff_map_eq_zero]
[GOAL]
case left
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
⊢ ∀ (a : ZMod k),
    ↑(↑(AddMonoidHom.liftOfRightInverse (Int.castAddHom (ZMod k)) ZMod.cast
                  (_ : Function.RightInverse ZMod.cast Int.cast))
              {
                val :=
                  {
                    toZeroHom :=
                      {
                        toFun := fun i =>
                          ↑Additive.ofMul
                            { val := (fun x x_1 => x ^ x_1) ζ i,
                              property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                        map_zero' :=
                          (_ :
                            (fun i =>
                                  ↑Additive.ofMul
                                    { val := (fun x x_1 => x ^ x_1) ζ i,
                                      property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                0 =
                              0) },
                    map_add' :=
                      (_ :
                        ∀ (i j : ℤ),
                          ZeroHom.toFun
                              {
                                toFun := fun i =>
                                  ↑Additive.ofMul
                                    { val := (fun x x_1 => x ^ x_1) ζ i,
                                      property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                map_zero' :=
                                  (_ :
                                    (fun i =>
                                          ↑Additive.ofMul
                                            { val := (fun x x_1 => x ^ x_1) ζ i,
                                              property :=
                                                (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                        0 =
                                      0) }
                              (i + j) =
                            ZeroHom.toFun
                                {
                                  toFun := fun i =>
                                    ↑Additive.ofMul
                                      { val := (fun x x_1 => x ^ x_1) ζ i,
                                        property :=
                                          (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                  map_zero' :=
                                    (_ :
                                      (fun i =>
                                            ↑Additive.ofMul
                                              { val := (fun x x_1 => x ^ x_1) ζ i,
                                                property :=
                                                  (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                          0 =
                                        0) }
                                i +
                              ZeroHom.toFun
                                {
                                  toFun := fun i =>
                                    ↑Additive.ofMul
                                      { val := (fun x x_1 => x ^ x_1) ζ i,
                                        property :=
                                          (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                  map_zero' :=
                                    (_ :
                                      (fun i =>
                                            ↑Additive.ofMul
                                              { val := (fun x x_1 => x ^ x_1) ζ i,
                                                property :=
                                                  (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                          0 =
                                        0) }
                                j) },
                property :=
                  (_ :
                    ∀ (i : ℤ),
                      i ∈ AddMonoidHom.ker (Int.castAddHom (ZMod k)) →
                        i ∈
                          AddMonoidHom.ker
                            {
                              toZeroHom :=
                                {
                                  toFun := fun i =>
                                    ↑Additive.ofMul
                                      { val := (fun x x_1 => x ^ x_1) ζ i,
                                        property :=
                                          (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                  map_zero' :=
                                    (_ :
                                      (fun i =>
                                            ↑Additive.ofMul
                                              { val := (fun x x_1 => x ^ x_1) ζ i,
                                                property :=
                                                  (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                          0 =
                                        0) },
                              map_add' :=
                                (_ :
                                  ∀ (i j : ℤ),
                                    ZeroHom.toFun
                                        {
                                          toFun := fun i =>
                                            ↑Additive.ofMul
                                              { val := (fun x x_1 => x ^ x_1) ζ i,
                                                property :=
                                                  (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                          map_zero' :=
                                            (_ :
                                              (fun i =>
                                                    ↑Additive.ofMul
                                                      { val := (fun x x_1 => x ^ x_1) ζ i,
                                                        property :=
                                                          (_ :
                                                            ∃ y,
                                                              (fun x x_1 => x ^ x_1) ζ y =
                                                                (fun x x_1 => x ^ x_1) ζ i) })
                                                  0 =
                                                0) }
                                        (i + j) =
                                      ZeroHom.toFun
                                          {
                                            toFun := fun i =>
                                              ↑Additive.ofMul
                                                { val := (fun x x_1 => x ^ x_1) ζ i,
                                                  property :=
                                                    (_ :
                                                      ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                            map_zero' :=
                                              (_ :
                                                (fun i =>
                                                      ↑Additive.ofMul
                                                        { val := (fun x x_1 => x ^ x_1) ζ i,
                                                          property :=
                                                            (_ :
                                                              ∃ y,
                                                                (fun x x_1 => x ^ x_1) ζ y =
                                                                  (fun x x_1 => x ^ x_1) ζ i) })
                                                    0 =
                                                  0) }
                                          i +
                                        ZeroHom.toFun
                                          {
                                            toFun := fun i =>
                                              ↑Additive.ofMul
                                                { val := (fun x x_1 => x ^ x_1) ζ i,
                                                  property :=
                                                    (_ :
                                                      ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                            map_zero' :=
                                              (_ :
                                                (fun i =>
                                                      ↑Additive.ofMul
                                                        { val := (fun x x_1 => x ^ x_1) ζ i,
                                                          property :=
                                                            (_ :
                                                              ∃ y,
                                                                (fun x x_1 => x ^ x_1) ζ y =
                                                                  (fun x x_1 => x ^ x_1) ζ i) })
                                                    0 =
                                                  0) }
                                          j) }) })
          a =
        0 →
      a = 0
[PROOFSTEP]
intro i hi
[GOAL]
case left
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 : ZMod k
hi :
  ↑(↑(AddMonoidHom.liftOfRightInverse (Int.castAddHom (ZMod k)) ZMod.cast
              (_ : Function.RightInverse ZMod.cast Int.cast))
          {
            val :=
              {
                toZeroHom :=
                  {
                    toFun := fun i =>
                      ↑Additive.ofMul
                        { val := (fun x x_1 => x ^ x_1) ζ i,
                          property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                    map_zero' :=
                      (_ :
                        (fun i =>
                              ↑Additive.ofMul
                                { val := (fun x x_1 => x ^ x_1) ζ i,
                                  property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                            0 =
                          0) },
                map_add' :=
                  (_ :
                    ∀ (i j : ℤ),
                      ZeroHom.toFun
                          {
                            toFun := fun i =>
                              ↑Additive.ofMul
                                { val := (fun x x_1 => x ^ x_1) ζ i,
                                  property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                            map_zero' :=
                              (_ :
                                (fun i =>
                                      ↑Additive.ofMul
                                        { val := (fun x x_1 => x ^ x_1) ζ i,
                                          property :=
                                            (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                    0 =
                                  0) }
                          (i + j) =
                        ZeroHom.toFun
                            {
                              toFun := fun i =>
                                ↑Additive.ofMul
                                  { val := (fun x x_1 => x ^ x_1) ζ i,
                                    property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                              map_zero' :=
                                (_ :
                                  (fun i =>
                                        ↑Additive.ofMul
                                          { val := (fun x x_1 => x ^ x_1) ζ i,
                                            property :=
                                              (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                      0 =
                                    0) }
                            i +
                          ZeroHom.toFun
                            {
                              toFun := fun i =>
                                ↑Additive.ofMul
                                  { val := (fun x x_1 => x ^ x_1) ζ i,
                                    property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                              map_zero' :=
                                (_ :
                                  (fun i =>
                                        ↑Additive.ofMul
                                          { val := (fun x x_1 => x ^ x_1) ζ i,
                                            property :=
                                              (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                      0 =
                                    0) }
                            j) },
            property :=
              (_ :
                ∀ (i : ℤ),
                  i ∈ AddMonoidHom.ker (Int.castAddHom (ZMod k)) →
                    i ∈
                      AddMonoidHom.ker
                        {
                          toZeroHom :=
                            {
                              toFun := fun i =>
                                ↑Additive.ofMul
                                  { val := (fun x x_1 => x ^ x_1) ζ i,
                                    property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                              map_zero' :=
                                (_ :
                                  (fun i =>
                                        ↑Additive.ofMul
                                          { val := (fun x x_1 => x ^ x_1) ζ i,
                                            property :=
                                              (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                      0 =
                                    0) },
                          map_add' :=
                            (_ :
                              ∀ (i j : ℤ),
                                ZeroHom.toFun
                                    {
                                      toFun := fun i =>
                                        ↑Additive.ofMul
                                          { val := (fun x x_1 => x ^ x_1) ζ i,
                                            property :=
                                              (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                      map_zero' :=
                                        (_ :
                                          (fun i =>
                                                ↑Additive.ofMul
                                                  { val := (fun x x_1 => x ^ x_1) ζ i,
                                                    property :=
                                                      (_ :
                                                        ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                              0 =
                                            0) }
                                    (i + j) =
                                  ZeroHom.toFun
                                      {
                                        toFun := fun i =>
                                          ↑Additive.ofMul
                                            { val := (fun x x_1 => x ^ x_1) ζ i,
                                              property :=
                                                (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                        map_zero' :=
                                          (_ :
                                            (fun i =>
                                                  ↑Additive.ofMul
                                                    { val := (fun x x_1 => x ^ x_1) ζ i,
                                                      property :=
                                                        (_ :
                                                          ∃ y,
                                                            (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                                0 =
                                              0) }
                                      i +
                                    ZeroHom.toFun
                                      {
                                        toFun := fun i =>
                                          ↑Additive.ofMul
                                            { val := (fun x x_1 => x ^ x_1) ζ i,
                                              property :=
                                                (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                        map_zero' :=
                                          (_ :
                                            (fun i =>
                                                  ↑Additive.ofMul
                                                    { val := (fun x x_1 => x ^ x_1) ζ i,
                                                      property :=
                                                        (_ :
                                                          ∃ y,
                                                            (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                                0 =
                                              0) }
                                      j) }) })
      i =
    0
⊢ i = 0
[PROOFSTEP]
rw [Subtype.ext_iff] at hi 
[GOAL]
case left
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 : ZMod k
hi :
  ↑(↑(↑(AddMonoidHom.liftOfRightInverse (Int.castAddHom (ZMod k)) ZMod.cast
                (_ : Function.RightInverse ZMod.cast Int.cast))
            {
              val :=
                {
                  toZeroHom :=
                    {
                      toFun := fun i =>
                        ↑Additive.ofMul
                          { val := (fun x x_1 => x ^ x_1) ζ i,
                            property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                      map_zero' :=
                        (_ :
                          (fun i =>
                                ↑Additive.ofMul
                                  { val := (fun x x_1 => x ^ x_1) ζ i,
                                    property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                              0 =
                            0) },
                  map_add' :=
                    (_ :
                      ∀ (i j : ℤ),
                        ZeroHom.toFun
                            {
                              toFun := fun i =>
                                ↑Additive.ofMul
                                  { val := (fun x x_1 => x ^ x_1) ζ i,
                                    property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                              map_zero' :=
                                (_ :
                                  (fun i =>
                                        ↑Additive.ofMul
                                          { val := (fun x x_1 => x ^ x_1) ζ i,
                                            property :=
                                              (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                      0 =
                                    0) }
                            (i + j) =
                          ZeroHom.toFun
                              {
                                toFun := fun i =>
                                  ↑Additive.ofMul
                                    { val := (fun x x_1 => x ^ x_1) ζ i,
                                      property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                map_zero' :=
                                  (_ :
                                    (fun i =>
                                          ↑Additive.ofMul
                                            { val := (fun x x_1 => x ^ x_1) ζ i,
                                              property :=
                                                (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                        0 =
                                      0) }
                              i +
                            ZeroHom.toFun
                              {
                                toFun := fun i =>
                                  ↑Additive.ofMul
                                    { val := (fun x x_1 => x ^ x_1) ζ i,
                                      property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                map_zero' :=
                                  (_ :
                                    (fun i =>
                                          ↑Additive.ofMul
                                            { val := (fun x x_1 => x ^ x_1) ζ i,
                                              property :=
                                                (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                        0 =
                                      0) }
                              j) },
              property :=
                (_ :
                  ∀ (i : ℤ),
                    i ∈ AddMonoidHom.ker (Int.castAddHom (ZMod k)) →
                      i ∈
                        AddMonoidHom.ker
                          {
                            toZeroHom :=
                              {
                                toFun := fun i =>
                                  ↑Additive.ofMul
                                    { val := (fun x x_1 => x ^ x_1) ζ i,
                                      property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                map_zero' :=
                                  (_ :
                                    (fun i =>
                                          ↑Additive.ofMul
                                            { val := (fun x x_1 => x ^ x_1) ζ i,
                                              property :=
                                                (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                        0 =
                                      0) },
                            map_add' :=
                              (_ :
                                ∀ (i j : ℤ),
                                  ZeroHom.toFun
                                      {
                                        toFun := fun i =>
                                          ↑Additive.ofMul
                                            { val := (fun x x_1 => x ^ x_1) ζ i,
                                              property :=
                                                (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                        map_zero' :=
                                          (_ :
                                            (fun i =>
                                                  ↑Additive.ofMul
                                                    { val := (fun x x_1 => x ^ x_1) ζ i,
                                                      property :=
                                                        (_ :
                                                          ∃ y,
                                                            (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                                0 =
                                              0) }
                                      (i + j) =
                                    ZeroHom.toFun
                                        {
                                          toFun := fun i =>
                                            ↑Additive.ofMul
                                              { val := (fun x x_1 => x ^ x_1) ζ i,
                                                property :=
                                                  (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                          map_zero' :=
                                            (_ :
                                              (fun i =>
                                                    ↑Additive.ofMul
                                                      { val := (fun x x_1 => x ^ x_1) ζ i,
                                                        property :=
                                                          (_ :
                                                            ∃ y,
                                                              (fun x x_1 => x ^ x_1) ζ y =
                                                                (fun x x_1 => x ^ x_1) ζ i) })
                                                  0 =
                                                0) }
                                        i +
                                      ZeroHom.toFun
                                        {
                                          toFun := fun i =>
                                            ↑Additive.ofMul
                                              { val := (fun x x_1 => x ^ x_1) ζ i,
                                                property :=
                                                  (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                          map_zero' :=
                                            (_ :
                                              (fun i =>
                                                    ↑Additive.ofMul
                                                      { val := (fun x x_1 => x ^ x_1) ζ i,
                                                        property :=
                                                          (_ :
                                                            ∃ y,
                                                              (fun x x_1 => x ^ x_1) ζ y =
                                                                (fun x x_1 => x ^ x_1) ζ i) })
                                                  0 =
                                                0) }
                                        j) }) })
        i) =
    ↑0
⊢ i = 0
[PROOFSTEP]
have := (h.zpow_eq_one_iff_dvd _).mp hi
[GOAL]
case left
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 : ZMod k
hi :
  ↑(↑(↑(AddMonoidHom.liftOfRightInverse (Int.castAddHom (ZMod k)) ZMod.cast
                (_ : Function.RightInverse ZMod.cast Int.cast))
            {
              val :=
                {
                  toZeroHom :=
                    {
                      toFun := fun i =>
                        ↑Additive.ofMul
                          { val := (fun x x_1 => x ^ x_1) ζ i,
                            property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                      map_zero' :=
                        (_ :
                          (fun i =>
                                ↑Additive.ofMul
                                  { val := (fun x x_1 => x ^ x_1) ζ i,
                                    property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                              0 =
                            0) },
                  map_add' :=
                    (_ :
                      ∀ (i j : ℤ),
                        ZeroHom.toFun
                            {
                              toFun := fun i =>
                                ↑Additive.ofMul
                                  { val := (fun x x_1 => x ^ x_1) ζ i,
                                    property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                              map_zero' :=
                                (_ :
                                  (fun i =>
                                        ↑Additive.ofMul
                                          { val := (fun x x_1 => x ^ x_1) ζ i,
                                            property :=
                                              (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                      0 =
                                    0) }
                            (i + j) =
                          ZeroHom.toFun
                              {
                                toFun := fun i =>
                                  ↑Additive.ofMul
                                    { val := (fun x x_1 => x ^ x_1) ζ i,
                                      property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                map_zero' :=
                                  (_ :
                                    (fun i =>
                                          ↑Additive.ofMul
                                            { val := (fun x x_1 => x ^ x_1) ζ i,
                                              property :=
                                                (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                        0 =
                                      0) }
                              i +
                            ZeroHom.toFun
                              {
                                toFun := fun i =>
                                  ↑Additive.ofMul
                                    { val := (fun x x_1 => x ^ x_1) ζ i,
                                      property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                map_zero' :=
                                  (_ :
                                    (fun i =>
                                          ↑Additive.ofMul
                                            { val := (fun x x_1 => x ^ x_1) ζ i,
                                              property :=
                                                (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                        0 =
                                      0) }
                              j) },
              property :=
                (_ :
                  ∀ (i : ℤ),
                    i ∈ AddMonoidHom.ker (Int.castAddHom (ZMod k)) →
                      i ∈
                        AddMonoidHom.ker
                          {
                            toZeroHom :=
                              {
                                toFun := fun i =>
                                  ↑Additive.ofMul
                                    { val := (fun x x_1 => x ^ x_1) ζ i,
                                      property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                map_zero' :=
                                  (_ :
                                    (fun i =>
                                          ↑Additive.ofMul
                                            { val := (fun x x_1 => x ^ x_1) ζ i,
                                              property :=
                                                (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                        0 =
                                      0) },
                            map_add' :=
                              (_ :
                                ∀ (i j : ℤ),
                                  ZeroHom.toFun
                                      {
                                        toFun := fun i =>
                                          ↑Additive.ofMul
                                            { val := (fun x x_1 => x ^ x_1) ζ i,
                                              property :=
                                                (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                        map_zero' :=
                                          (_ :
                                            (fun i =>
                                                  ↑Additive.ofMul
                                                    { val := (fun x x_1 => x ^ x_1) ζ i,
                                                      property :=
                                                        (_ :
                                                          ∃ y,
                                                            (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                                0 =
                                              0) }
                                      (i + j) =
                                    ZeroHom.toFun
                                        {
                                          toFun := fun i =>
                                            ↑Additive.ofMul
                                              { val := (fun x x_1 => x ^ x_1) ζ i,
                                                property :=
                                                  (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                          map_zero' :=
                                            (_ :
                                              (fun i =>
                                                    ↑Additive.ofMul
                                                      { val := (fun x x_1 => x ^ x_1) ζ i,
                                                        property :=
                                                          (_ :
                                                            ∃ y,
                                                              (fun x x_1 => x ^ x_1) ζ y =
                                                                (fun x x_1 => x ^ x_1) ζ i) })
                                                  0 =
                                                0) }
                                        i +
                                      ZeroHom.toFun
                                        {
                                          toFun := fun i =>
                                            ↑Additive.ofMul
                                              { val := (fun x x_1 => x ^ x_1) ζ i,
                                                property :=
                                                  (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                          map_zero' :=
                                            (_ :
                                              (fun i =>
                                                    ↑Additive.ofMul
                                                      { val := (fun x x_1 => x ^ x_1) ζ i,
                                                        property :=
                                                          (_ :
                                                            ∃ y,
                                                              (fun x x_1 => x ^ x_1) ζ y =
                                                                (fun x x_1 => x ^ x_1) ζ i) })
                                                  0 =
                                                0) }
                                        j) }) })
        i) =
    ↑0
this : ↑k ∣ ↑i
⊢ i = 0
[PROOFSTEP]
rw [← (CharP.int_cast_eq_zero_iff (ZMod k) k _).mpr this, eq_comm]
[GOAL]
case left
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 : ZMod k
hi :
  ↑(↑(↑(AddMonoidHom.liftOfRightInverse (Int.castAddHom (ZMod k)) ZMod.cast
                (_ : Function.RightInverse ZMod.cast Int.cast))
            {
              val :=
                {
                  toZeroHom :=
                    {
                      toFun := fun i =>
                        ↑Additive.ofMul
                          { val := (fun x x_1 => x ^ x_1) ζ i,
                            property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                      map_zero' :=
                        (_ :
                          (fun i =>
                                ↑Additive.ofMul
                                  { val := (fun x x_1 => x ^ x_1) ζ i,
                                    property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                              0 =
                            0) },
                  map_add' :=
                    (_ :
                      ∀ (i j : ℤ),
                        ZeroHom.toFun
                            {
                              toFun := fun i =>
                                ↑Additive.ofMul
                                  { val := (fun x x_1 => x ^ x_1) ζ i,
                                    property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                              map_zero' :=
                                (_ :
                                  (fun i =>
                                        ↑Additive.ofMul
                                          { val := (fun x x_1 => x ^ x_1) ζ i,
                                            property :=
                                              (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                      0 =
                                    0) }
                            (i + j) =
                          ZeroHom.toFun
                              {
                                toFun := fun i =>
                                  ↑Additive.ofMul
                                    { val := (fun x x_1 => x ^ x_1) ζ i,
                                      property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                map_zero' :=
                                  (_ :
                                    (fun i =>
                                          ↑Additive.ofMul
                                            { val := (fun x x_1 => x ^ x_1) ζ i,
                                              property :=
                                                (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                        0 =
                                      0) }
                              i +
                            ZeroHom.toFun
                              {
                                toFun := fun i =>
                                  ↑Additive.ofMul
                                    { val := (fun x x_1 => x ^ x_1) ζ i,
                                      property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                map_zero' :=
                                  (_ :
                                    (fun i =>
                                          ↑Additive.ofMul
                                            { val := (fun x x_1 => x ^ x_1) ζ i,
                                              property :=
                                                (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                        0 =
                                      0) }
                              j) },
              property :=
                (_ :
                  ∀ (i : ℤ),
                    i ∈ AddMonoidHom.ker (Int.castAddHom (ZMod k)) →
                      i ∈
                        AddMonoidHom.ker
                          {
                            toZeroHom :=
                              {
                                toFun := fun i =>
                                  ↑Additive.ofMul
                                    { val := (fun x x_1 => x ^ x_1) ζ i,
                                      property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                map_zero' :=
                                  (_ :
                                    (fun i =>
                                          ↑Additive.ofMul
                                            { val := (fun x x_1 => x ^ x_1) ζ i,
                                              property :=
                                                (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                        0 =
                                      0) },
                            map_add' :=
                              (_ :
                                ∀ (i j : ℤ),
                                  ZeroHom.toFun
                                      {
                                        toFun := fun i =>
                                          ↑Additive.ofMul
                                            { val := (fun x x_1 => x ^ x_1) ζ i,
                                              property :=
                                                (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                        map_zero' :=
                                          (_ :
                                            (fun i =>
                                                  ↑Additive.ofMul
                                                    { val := (fun x x_1 => x ^ x_1) ζ i,
                                                      property :=
                                                        (_ :
                                                          ∃ y,
                                                            (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                                0 =
                                              0) }
                                      (i + j) =
                                    ZeroHom.toFun
                                        {
                                          toFun := fun i =>
                                            ↑Additive.ofMul
                                              { val := (fun x x_1 => x ^ x_1) ζ i,
                                                property :=
                                                  (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                          map_zero' :=
                                            (_ :
                                              (fun i =>
                                                    ↑Additive.ofMul
                                                      { val := (fun x x_1 => x ^ x_1) ζ i,
                                                        property :=
                                                          (_ :
                                                            ∃ y,
                                                              (fun x x_1 => x ^ x_1) ζ y =
                                                                (fun x x_1 => x ^ x_1) ζ i) })
                                                  0 =
                                                0) }
                                        i +
                                      ZeroHom.toFun
                                        {
                                          toFun := fun i =>
                                            ↑Additive.ofMul
                                              { val := (fun x x_1 => x ^ x_1) ζ i,
                                                property :=
                                                  (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                          map_zero' :=
                                            (_ :
                                              (fun i =>
                                                    ↑Additive.ofMul
                                                      { val := (fun x x_1 => x ^ x_1) ζ i,
                                                        property :=
                                                          (_ :
                                                            ∃ y,
                                                              (fun x x_1 => x ^ x_1) ζ y =
                                                                (fun x x_1 => x ^ x_1) ζ i) })
                                                  0 =
                                                0) }
                                        j) }) })
        i) =
    ↑0
this : ↑k ∣ ↑i
⊢ ↑↑i = i
[PROOFSTEP]
exact ZMod.int_cast_rightInverse i
[GOAL]
case right
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
⊢ Function.Surjective
    ↑(↑(AddMonoidHom.liftOfRightInverse (Int.castAddHom (ZMod k)) ZMod.cast
            (_ : Function.RightInverse ZMod.cast Int.cast))
        {
          val :=
            {
              toZeroHom :=
                {
                  toFun := fun i =>
                    ↑Additive.ofMul
                      { val := (fun x x_1 => x ^ x_1) ζ i,
                        property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                  map_zero' :=
                    (_ :
                      (fun i =>
                            ↑Additive.ofMul
                              { val := (fun x x_1 => x ^ x_1) ζ i,
                                property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                          0 =
                        0) },
              map_add' :=
                (_ :
                  ∀ (i j : ℤ),
                    ZeroHom.toFun
                        {
                          toFun := fun i =>
                            ↑Additive.ofMul
                              { val := (fun x x_1 => x ^ x_1) ζ i,
                                property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                          map_zero' :=
                            (_ :
                              (fun i =>
                                    ↑Additive.ofMul
                                      { val := (fun x x_1 => x ^ x_1) ζ i,
                                        property :=
                                          (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                  0 =
                                0) }
                        (i + j) =
                      ZeroHom.toFun
                          {
                            toFun := fun i =>
                              ↑Additive.ofMul
                                { val := (fun x x_1 => x ^ x_1) ζ i,
                                  property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                            map_zero' :=
                              (_ :
                                (fun i =>
                                      ↑Additive.ofMul
                                        { val := (fun x x_1 => x ^ x_1) ζ i,
                                          property :=
                                            (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                    0 =
                                  0) }
                          i +
                        ZeroHom.toFun
                          {
                            toFun := fun i =>
                              ↑Additive.ofMul
                                { val := (fun x x_1 => x ^ x_1) ζ i,
                                  property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                            map_zero' :=
                              (_ :
                                (fun i =>
                                      ↑Additive.ofMul
                                        { val := (fun x x_1 => x ^ x_1) ζ i,
                                          property :=
                                            (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                    0 =
                                  0) }
                          j) },
          property :=
            (_ :
              ∀ (i : ℤ),
                i ∈ AddMonoidHom.ker (Int.castAddHom (ZMod k)) →
                  i ∈
                    AddMonoidHom.ker
                      {
                        toZeroHom :=
                          {
                            toFun := fun i =>
                              ↑Additive.ofMul
                                { val := (fun x x_1 => x ^ x_1) ζ i,
                                  property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                            map_zero' :=
                              (_ :
                                (fun i =>
                                      ↑Additive.ofMul
                                        { val := (fun x x_1 => x ^ x_1) ζ i,
                                          property :=
                                            (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                    0 =
                                  0) },
                        map_add' :=
                          (_ :
                            ∀ (i j : ℤ),
                              ZeroHom.toFun
                                  {
                                    toFun := fun i =>
                                      ↑Additive.ofMul
                                        { val := (fun x x_1 => x ^ x_1) ζ i,
                                          property :=
                                            (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                    map_zero' :=
                                      (_ :
                                        (fun i =>
                                              ↑Additive.ofMul
                                                { val := (fun x x_1 => x ^ x_1) ζ i,
                                                  property :=
                                                    (_ :
                                                      ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                            0 =
                                          0) }
                                  (i + j) =
                                ZeroHom.toFun
                                    {
                                      toFun := fun i =>
                                        ↑Additive.ofMul
                                          { val := (fun x x_1 => x ^ x_1) ζ i,
                                            property :=
                                              (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                      map_zero' :=
                                        (_ :
                                          (fun i =>
                                                ↑Additive.ofMul
                                                  { val := (fun x x_1 => x ^ x_1) ζ i,
                                                    property :=
                                                      (_ :
                                                        ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                              0 =
                                            0) }
                                    i +
                                  ZeroHom.toFun
                                    {
                                      toFun := fun i =>
                                        ↑Additive.ofMul
                                          { val := (fun x x_1 => x ^ x_1) ζ i,
                                            property :=
                                              (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                      map_zero' :=
                                        (_ :
                                          (fun i =>
                                                ↑Additive.ofMul
                                                  { val := (fun x x_1 => x ^ x_1) ζ i,
                                                    property :=
                                                      (_ :
                                                        ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                              0 =
                                            0) }
                                    j) }) })
[PROOFSTEP]
rintro ⟨ξ, i, rfl⟩
[GOAL]
case right.mk.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 : ℤ
⊢ ∃ a,
    ↑(↑(AddMonoidHom.liftOfRightInverse (Int.castAddHom (ZMod k)) ZMod.cast
                (_ : Function.RightInverse ZMod.cast Int.cast))
            {
              val :=
                {
                  toZeroHom :=
                    {
                      toFun := fun i =>
                        ↑Additive.ofMul
                          { val := (fun x x_1 => x ^ x_1) ζ i,
                            property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                      map_zero' :=
                        (_ :
                          (fun i =>
                                ↑Additive.ofMul
                                  { val := (fun x x_1 => x ^ x_1) ζ i,
                                    property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                              0 =
                            0) },
                  map_add' :=
                    (_ :
                      ∀ (i j : ℤ),
                        ZeroHom.toFun
                            {
                              toFun := fun i =>
                                ↑Additive.ofMul
                                  { val := (fun x x_1 => x ^ x_1) ζ i,
                                    property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                              map_zero' :=
                                (_ :
                                  (fun i =>
                                        ↑Additive.ofMul
                                          { val := (fun x x_1 => x ^ x_1) ζ i,
                                            property :=
                                              (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                      0 =
                                    0) }
                            (i + j) =
                          ZeroHom.toFun
                              {
                                toFun := fun i =>
                                  ↑Additive.ofMul
                                    { val := (fun x x_1 => x ^ x_1) ζ i,
                                      property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                map_zero' :=
                                  (_ :
                                    (fun i =>
                                          ↑Additive.ofMul
                                            { val := (fun x x_1 => x ^ x_1) ζ i,
                                              property :=
                                                (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                        0 =
                                      0) }
                              i +
                            ZeroHom.toFun
                              {
                                toFun := fun i =>
                                  ↑Additive.ofMul
                                    { val := (fun x x_1 => x ^ x_1) ζ i,
                                      property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                map_zero' :=
                                  (_ :
                                    (fun i =>
                                          ↑Additive.ofMul
                                            { val := (fun x x_1 => x ^ x_1) ζ i,
                                              property :=
                                                (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                        0 =
                                      0) }
                              j) },
              property :=
                (_ :
                  ∀ (i : ℤ),
                    i ∈ AddMonoidHom.ker (Int.castAddHom (ZMod k)) →
                      i ∈
                        AddMonoidHom.ker
                          {
                            toZeroHom :=
                              {
                                toFun := fun i =>
                                  ↑Additive.ofMul
                                    { val := (fun x x_1 => x ^ x_1) ζ i,
                                      property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                map_zero' :=
                                  (_ :
                                    (fun i =>
                                          ↑Additive.ofMul
                                            { val := (fun x x_1 => x ^ x_1) ζ i,
                                              property :=
                                                (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                        0 =
                                      0) },
                            map_add' :=
                              (_ :
                                ∀ (i j : ℤ),
                                  ZeroHom.toFun
                                      {
                                        toFun := fun i =>
                                          ↑Additive.ofMul
                                            { val := (fun x x_1 => x ^ x_1) ζ i,
                                              property :=
                                                (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                        map_zero' :=
                                          (_ :
                                            (fun i =>
                                                  ↑Additive.ofMul
                                                    { val := (fun x x_1 => x ^ x_1) ζ i,
                                                      property :=
                                                        (_ :
                                                          ∃ y,
                                                            (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                                0 =
                                              0) }
                                      (i + j) =
                                    ZeroHom.toFun
                                        {
                                          toFun := fun i =>
                                            ↑Additive.ofMul
                                              { val := (fun x x_1 => x ^ x_1) ζ i,
                                                property :=
                                                  (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                          map_zero' :=
                                            (_ :
                                              (fun i =>
                                                    ↑Additive.ofMul
                                                      { val := (fun x x_1 => x ^ x_1) ζ i,
                                                        property :=
                                                          (_ :
                                                            ∃ y,
                                                              (fun x x_1 => x ^ x_1) ζ y =
                                                                (fun x x_1 => x ^ x_1) ζ i) })
                                                  0 =
                                                0) }
                                        i +
                                      ZeroHom.toFun
                                        {
                                          toFun := fun i =>
                                            ↑Additive.ofMul
                                              { val := (fun x x_1 => x ^ x_1) ζ i,
                                                property :=
                                                  (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                          map_zero' :=
                                            (_ :
                                              (fun i =>
                                                    ↑Additive.ofMul
                                                      { val := (fun x x_1 => x ^ x_1) ζ i,
                                                        property :=
                                                          (_ :
                                                            ∃ y,
                                                              (fun x x_1 => x ^ x_1) ζ y =
                                                                (fun x x_1 => x ^ x_1) ζ i) })
                                                  0 =
                                                0) }
                                        j) }) })
        a =
      { val := (fun x x_1 => x ^ x_1) ζ i,
        property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) }
[PROOFSTEP]
refine' ⟨Int.castAddHom (ZMod k) i, _⟩
[GOAL]
case right.mk.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 : ℤ
⊢ ↑(↑(AddMonoidHom.liftOfRightInverse (Int.castAddHom (ZMod k)) ZMod.cast
              (_ : Function.RightInverse ZMod.cast Int.cast))
          {
            val :=
              {
                toZeroHom :=
                  {
                    toFun := fun i =>
                      ↑Additive.ofMul
                        { val := (fun x x_1 => x ^ x_1) ζ i,
                          property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                    map_zero' :=
                      (_ :
                        (fun i =>
                              ↑Additive.ofMul
                                { val := (fun x x_1 => x ^ x_1) ζ i,
                                  property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                            0 =
                          0) },
                map_add' :=
                  (_ :
                    ∀ (i j : ℤ),
                      ZeroHom.toFun
                          {
                            toFun := fun i =>
                              ↑Additive.ofMul
                                { val := (fun x x_1 => x ^ x_1) ζ i,
                                  property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                            map_zero' :=
                              (_ :
                                (fun i =>
                                      ↑Additive.ofMul
                                        { val := (fun x x_1 => x ^ x_1) ζ i,
                                          property :=
                                            (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                    0 =
                                  0) }
                          (i + j) =
                        ZeroHom.toFun
                            {
                              toFun := fun i =>
                                ↑Additive.ofMul
                                  { val := (fun x x_1 => x ^ x_1) ζ i,
                                    property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                              map_zero' :=
                                (_ :
                                  (fun i =>
                                        ↑Additive.ofMul
                                          { val := (fun x x_1 => x ^ x_1) ζ i,
                                            property :=
                                              (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                      0 =
                                    0) }
                            i +
                          ZeroHom.toFun
                            {
                              toFun := fun i =>
                                ↑Additive.ofMul
                                  { val := (fun x x_1 => x ^ x_1) ζ i,
                                    property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                              map_zero' :=
                                (_ :
                                  (fun i =>
                                        ↑Additive.ofMul
                                          { val := (fun x x_1 => x ^ x_1) ζ i,
                                            property :=
                                              (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                      0 =
                                    0) }
                            j) },
            property :=
              (_ :
                ∀ (i : ℤ),
                  i ∈ AddMonoidHom.ker (Int.castAddHom (ZMod k)) →
                    i ∈
                      AddMonoidHom.ker
                        {
                          toZeroHom :=
                            {
                              toFun := fun i =>
                                ↑Additive.ofMul
                                  { val := (fun x x_1 => x ^ x_1) ζ i,
                                    property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                              map_zero' :=
                                (_ :
                                  (fun i =>
                                        ↑Additive.ofMul
                                          { val := (fun x x_1 => x ^ x_1) ζ i,
                                            property :=
                                              (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                      0 =
                                    0) },
                          map_add' :=
                            (_ :
                              ∀ (i j : ℤ),
                                ZeroHom.toFun
                                    {
                                      toFun := fun i =>
                                        ↑Additive.ofMul
                                          { val := (fun x x_1 => x ^ x_1) ζ i,
                                            property :=
                                              (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                      map_zero' :=
                                        (_ :
                                          (fun i =>
                                                ↑Additive.ofMul
                                                  { val := (fun x x_1 => x ^ x_1) ζ i,
                                                    property :=
                                                      (_ :
                                                        ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                              0 =
                                            0) }
                                    (i + j) =
                                  ZeroHom.toFun
                                      {
                                        toFun := fun i =>
                                          ↑Additive.ofMul
                                            { val := (fun x x_1 => x ^ x_1) ζ i,
                                              property :=
                                                (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                        map_zero' :=
                                          (_ :
                                            (fun i =>
                                                  ↑Additive.ofMul
                                                    { val := (fun x x_1 => x ^ x_1) ζ i,
                                                      property :=
                                                        (_ :
                                                          ∃ y,
                                                            (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                                0 =
                                              0) }
                                      i +
                                    ZeroHom.toFun
                                      {
                                        toFun := fun i =>
                                          ↑Additive.ofMul
                                            { val := (fun x x_1 => x ^ x_1) ζ i,
                                              property :=
                                                (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                        map_zero' :=
                                          (_ :
                                            (fun i =>
                                                  ↑Additive.ofMul
                                                    { val := (fun x x_1 => x ^ x_1) ζ i,
                                                      property :=
                                                        (_ :
                                                          ∃ y,
                                                            (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                                0 =
                                              0) }
                                      j) }) })
      (↑(Int.castAddHom (ZMod k)) i) =
    { val := (fun x x_1 => x ^ x_1) ζ i,
      property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) }
[PROOFSTEP]
rw [AddMonoidHom.liftOfRightInverse_comp_apply]
[GOAL]
case right.mk.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 : ℤ
⊢ ↑↑{
            val :=
              {
                toZeroHom :=
                  {
                    toFun := fun i =>
                      ↑Additive.ofMul
                        { val := (fun x x_1 => x ^ x_1) ζ i,
                          property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                    map_zero' :=
                      (_ :
                        (fun i =>
                              ↑Additive.ofMul
                                { val := (fun x x_1 => x ^ x_1) ζ i,
                                  property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                            0 =
                          0) },
                map_add' :=
                  (_ :
                    ∀ (i j : ℤ),
                      ZeroHom.toFun
                          {
                            toFun := fun i =>
                              ↑Additive.ofMul
                                { val := (fun x x_1 => x ^ x_1) ζ i,
                                  property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                            map_zero' :=
                              (_ :
                                (fun i =>
                                      ↑Additive.ofMul
                                        { val := (fun x x_1 => x ^ x_1) ζ i,
                                          property :=
                                            (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                    0 =
                                  0) }
                          (i + j) =
                        ZeroHom.toFun
                            {
                              toFun := fun i =>
                                ↑Additive.ofMul
                                  { val := (fun x x_1 => x ^ x_1) ζ i,
                                    property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                              map_zero' :=
                                (_ :
                                  (fun i =>
                                        ↑Additive.ofMul
                                          { val := (fun x x_1 => x ^ x_1) ζ i,
                                            property :=
                                              (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                      0 =
                                    0) }
                            i +
                          ZeroHom.toFun
                            {
                              toFun := fun i =>
                                ↑Additive.ofMul
                                  { val := (fun x x_1 => x ^ x_1) ζ i,
                                    property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                              map_zero' :=
                                (_ :
                                  (fun i =>
                                        ↑Additive.ofMul
                                          { val := (fun x x_1 => x ^ x_1) ζ i,
                                            property :=
                                              (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                      0 =
                                    0) }
                            j) },
            property :=
              (_ :
                ∀ (i : ℤ),
                  i ∈ AddMonoidHom.ker (Int.castAddHom (ZMod k)) →
                    i ∈
                      AddMonoidHom.ker
                        {
                          toZeroHom :=
                            {
                              toFun := fun i =>
                                ↑Additive.ofMul
                                  { val := (fun x x_1 => x ^ x_1) ζ i,
                                    property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                              map_zero' :=
                                (_ :
                                  (fun i =>
                                        ↑Additive.ofMul
                                          { val := (fun x x_1 => x ^ x_1) ζ i,
                                            property :=
                                              (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                      0 =
                                    0) },
                          map_add' :=
                            (_ :
                              ∀ (i j : ℤ),
                                ZeroHom.toFun
                                    {
                                      toFun := fun i =>
                                        ↑Additive.ofMul
                                          { val := (fun x x_1 => x ^ x_1) ζ i,
                                            property :=
                                              (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                      map_zero' :=
                                        (_ :
                                          (fun i =>
                                                ↑Additive.ofMul
                                                  { val := (fun x x_1 => x ^ x_1) ζ i,
                                                    property :=
                                                      (_ :
                                                        ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                              0 =
                                            0) }
                                    (i + j) =
                                  ZeroHom.toFun
                                      {
                                        toFun := fun i =>
                                          ↑Additive.ofMul
                                            { val := (fun x x_1 => x ^ x_1) ζ i,
                                              property :=
                                                (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                        map_zero' :=
                                          (_ :
                                            (fun i =>
                                                  ↑Additive.ofMul
                                                    { val := (fun x x_1 => x ^ x_1) ζ i,
                                                      property :=
                                                        (_ :
                                                          ∃ y,
                                                            (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                                0 =
                                              0) }
                                      i +
                                    ZeroHom.toFun
                                      {
                                        toFun := fun i =>
                                          ↑Additive.ofMul
                                            { val := (fun x x_1 => x ^ x_1) ζ i,
                                              property :=
                                                (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                        map_zero' :=
                                          (_ :
                                            (fun i =>
                                                  ↑Additive.ofMul
                                                    { val := (fun x x_1 => x ^ x_1) ζ i,
                                                      property :=
                                                        (_ :
                                                          ∃ y,
                                                            (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                                0 =
                                              0) }
                                      j) }) }
      i =
    { val := (fun x x_1 => x ^ x_1) ζ i,
      property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) }
[PROOFSTEP]
rfl
[GOAL]
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_1 => x ^ x_1) ζ y = ζ ^ i) }
[PROOFSTEP]
rw [zmodEquivZpowers, AddEquiv.ofBijective_apply]
  -- Porting note: Original proof didn't have `rw`
[GOAL]
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 : ℤ
⊢ ↑(↑(AddMonoidHom.liftOfRightInverse (Int.castAddHom (ZMod k)) ZMod.cast
              (_ : Function.RightInverse ZMod.cast Int.cast))
          {
            val :=
              {
                toZeroHom :=
                  {
                    toFun := fun i =>
                      ↑Additive.ofMul
                        { val := (fun x x_1 => x ^ x_1) ζ i,
                          property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                    map_zero' :=
                      (_ :
                        (fun i =>
                              ↑Additive.ofMul
                                { val := (fun x x_1 => x ^ x_1) ζ i,
                                  property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                            0 =
                          0) },
                map_add' :=
                  (_ :
                    ∀ (i j : ℤ),
                      ZeroHom.toFun
                          {
                            toFun := fun i =>
                              ↑Additive.ofMul
                                { val := (fun x x_1 => x ^ x_1) ζ i,
                                  property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                            map_zero' :=
                              (_ :
                                (fun i =>
                                      ↑Additive.ofMul
                                        { val := (fun x x_1 => x ^ x_1) ζ i,
                                          property :=
                                            (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                    0 =
                                  0) }
                          (i + j) =
                        ZeroHom.toFun
                            {
                              toFun := fun i =>
                                ↑Additive.ofMul
                                  { val := (fun x x_1 => x ^ x_1) ζ i,
                                    property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                              map_zero' :=
                                (_ :
                                  (fun i =>
                                        ↑Additive.ofMul
                                          { val := (fun x x_1 => x ^ x_1) ζ i,
                                            property :=
                                              (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                      0 =
                                    0) }
                            i +
                          ZeroHom.toFun
                            {
                              toFun := fun i =>
                                ↑Additive.ofMul
                                  { val := (fun x x_1 => x ^ x_1) ζ i,
                                    property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                              map_zero' :=
                                (_ :
                                  (fun i =>
                                        ↑Additive.ofMul
                                          { val := (fun x x_1 => x ^ x_1) ζ i,
                                            property :=
                                              (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                      0 =
                                    0) }
                            j) },
            property :=
              (_ :
                ∀ (i : ℤ),
                  i ∈ AddMonoidHom.ker (Int.castAddHom (ZMod k)) →
                    i ∈
                      AddMonoidHom.ker
                        {
                          toZeroHom :=
                            {
                              toFun := fun i =>
                                ↑Additive.ofMul
                                  { val := (fun x x_1 => x ^ x_1) ζ i,
                                    property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                              map_zero' :=
                                (_ :
                                  (fun i =>
                                        ↑Additive.ofMul
                                          { val := (fun x x_1 => x ^ x_1) ζ i,
                                            property :=
                                              (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                      0 =
                                    0) },
                          map_add' :=
                            (_ :
                              ∀ (i j : ℤ),
                                ZeroHom.toFun
                                    {
                                      toFun := fun i =>
                                        ↑Additive.ofMul
                                          { val := (fun x x_1 => x ^ x_1) ζ i,
                                            property :=
                                              (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                      map_zero' :=
                                        (_ :
                                          (fun i =>
                                                ↑Additive.ofMul
                                                  { val := (fun x x_1 => x ^ x_1) ζ i,
                                                    property :=
                                                      (_ :
                                                        ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                              0 =
                                            0) }
                                    (i + j) =
                                  ZeroHom.toFun
                                      {
                                        toFun := fun i =>
                                          ↑Additive.ofMul
                                            { val := (fun x x_1 => x ^ x_1) ζ i,
                                              property :=
                                                (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                        map_zero' :=
                                          (_ :
                                            (fun i =>
                                                  ↑Additive.ofMul
                                                    { val := (fun x x_1 => x ^ x_1) ζ i,
                                                      property :=
                                                        (_ :
                                                          ∃ y,
                                                            (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                                0 =
                                              0) }
                                      i +
                                    ZeroHom.toFun
                                      {
                                        toFun := fun i =>
                                          ↑Additive.ofMul
                                            { val := (fun x x_1 => x ^ x_1) ζ i,
                                              property :=
                                                (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) },
                                        map_zero' :=
                                          (_ :
                                            (fun i =>
                                                  ↑Additive.ofMul
                                                    { val := (fun x x_1 => x ^ x_1) ζ i,
                                                      property :=
                                                        (_ :
                                                          ∃ y,
                                                            (fun x x_1 => x ^ x_1) ζ y = (fun x x_1 => x ^ x_1) ζ i) })
                                                0 =
                                              0) }
                                      j) }) })
      ↑i =
    ↑Additive.ofMul { val := ζ ^ i, property := (_ : ∃ y, (fun x x_1 => x ^ x_1) ζ y = ζ ^ i) }
[PROOFSTEP]
exact AddMonoidHom.liftOfRightInverse_comp_apply _ _ ZMod.int_cast_rightInverse _ _
[GOAL]
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_1 => x ^ x_1) ζ y = ζ ^ i) }
[PROOFSTEP]
have : (i : ZMod k) = (i : ℤ) := by norm_cast
[GOAL]
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
[PROOFSTEP]
norm_cast
[GOAL]
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_1 => x ^ x_1) ζ y = ζ ^ i) }
[PROOFSTEP]
simp only [this, zmodEquivZpowers_apply_coe_int, zpow_ofNat]
[GOAL]
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_1 => x ^ x_1) ζ y = ζ ^ i) }) =
    ↑i
[PROOFSTEP]
rw [← h.zmodEquivZpowers.symm_apply_apply i, zmodEquivZpowers_apply_coe_int]
[GOAL]
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_1 => x ^ x_1) ζ y = ζ ^ i) }) =
    ↑i
[PROOFSTEP]
rw [← h.zmodEquivZpowers.symm_apply_apply i, zmodEquivZpowers_apply_coe_nat]
[GOAL]
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
[PROOFSTEP]
apply SetLike.coe_injective
[GOAL]
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)
[PROOFSTEP]
haveI F : Fintype (Subgroup.zpowers ζ) := Fintype.ofEquiv _ h.zmodEquivZpowers.toEquiv
[GOAL]
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 { x // x ∈ Subgroup.zpowers ζ }
⊢ ↑(Subgroup.zpowers ζ) = ↑(rootsOfUnity k R)
[PROOFSTEP]
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) _
[GOAL]
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 { x // x ∈ Subgroup.zpowers ζ }
⊢ Fintype.card ↑↑(rootsOfUnity k R) ≤ Fintype.card ↑↑(Subgroup.zpowers ζ)
[PROOFSTEP]
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
[GOAL]
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, i < ↑k ∧ ζ ^ i = ξ
[PROOFSTEP]
obtain ⟨n, rfl⟩ : ∃ n : ℤ, ζ ^ n = ξ := by rwa [← h.zpowers_eq] at hξ 
[GOAL]
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 = ξ
[PROOFSTEP]
rwa [← h.zpowers_eq] at hξ 
[GOAL]
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, i < ↑k ∧ ζ ^ i = ζ ^ n
[PROOFSTEP]
have hk0 : (0 : ℤ) < k := by exact_mod_cast k.pos
[GOAL]
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
⊢ 0 < ↑↑k
[PROOFSTEP]
exact_mod_cast k.pos
[GOAL]
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, i < ↑k ∧ ζ ^ i = ζ ^ n
[PROOFSTEP]
let i := n % k
[GOAL]
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, i < ↑k ∧ ζ ^ i = ζ ^ n
[PROOFSTEP]
have hi0 : 0 ≤ i := Int.emod_nonneg _ (ne_of_gt hk0)
[GOAL]
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, i < ↑k ∧ ζ ^ i = ζ ^ n
[PROOFSTEP]
lift i to ℕ using hi0 with i₀ hi₀
[GOAL]
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, i < ↑k ∧ ζ ^ i = ζ ^ n
[PROOFSTEP]
refine' ⟨i₀, _, _⟩
[GOAL]
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
[PROOFSTEP]
zify
[GOAL]
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
[PROOFSTEP]
rw [hi₀]
[GOAL]
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
[PROOFSTEP]
exact Int.emod_lt_of_pos _ hk0
[GOAL]
case intro.intro.refine'_2
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₀ = ζ ^ n
[PROOFSTEP]
rw [← zpow_ofNat, hi₀, ← Int.emod_add_ediv n k, zpow_add, zpow_mul, h.zpow_eq_one, one_zpow, mul_one]
[GOAL]
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ξ : ξ ^ k = 1
h0 : 0 < k
⊢ ∃ i, i < k ∧ ζ ^ i = ξ
[PROOFSTEP]
lift ζ to Rˣ using h.isUnit h0
[GOAL]
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ξ : ξ ^ k = 1
h0 : 0 < k
ζ : Rˣ
h : IsPrimitiveRoot (↑ζ) k
⊢ ∃ i, i < k ∧ ↑ζ ^ i = ξ
[PROOFSTEP]
lift ξ to Rˣ using isUnit_ofPowEqOne hξ h0.ne'
[GOAL]
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 : ℕ
h0 : 0 < k
ζ : Rˣ
h : IsPrimitiveRoot (↑ζ) k
ξ : Rˣ
hξ : ↑ξ ^ k = 1
⊢ ∃ i, i < k ∧ ↑ζ ^ i = ↑ξ
[PROOFSTEP]
lift k to ℕ+ using h0
[GOAL]
case intro.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
ζ ξ : Rˣ
k : ℕ+
h : IsPrimitiveRoot ↑ζ ↑k
hξ : ↑ξ ^ ↑k = 1
⊢ ∃ i, i < ↑k ∧ ↑ζ ^ i = ↑ξ
[PROOFSTEP]
simp only [← Units.val_pow_eq_pow_val, ← Units.ext_iff]
[GOAL]
case intro.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
ζ ξ : Rˣ
k : ℕ+
h : IsPrimitiveRoot ↑ζ ↑k
hξ : ↑ξ ^ ↑k = 1
⊢ ∃ i, i < ↑k ∧ ζ ^ i = ξ
[PROOFSTEP]
rw [coe_units_iff] at h 
[GOAL]
case intro.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
ζ ξ : Rˣ
k : ℕ+
h : IsPrimitiveRoot ζ ↑k
hξ : ↑ξ ^ ↑k = 1
⊢ ∃ i, i < ↑k ∧ ζ ^ i = ξ
[PROOFSTEP]
apply h.eq_pow_of_mem_rootsOfUnity
[GOAL]
case intro.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
ζ ξ : Rˣ
k : ℕ+
h : IsPrimitiveRoot ζ ↑k
hξ : ↑ξ ^ ↑k = 1
⊢ ξ ∈ rootsOfUnity k R
[PROOFSTEP]
rw [mem_rootsOfUnity, Units.ext_iff, Units.val_pow_eq_pow_val, hξ, Units.val_one]
[GOAL]
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
⊢ IsPrimitiveRoot ξ ↑k ↔ ∃ i, i < ↑k ∧ Nat.coprime i ↑k ∧ ζ ^ i = ξ
[PROOFSTEP]
constructor
[GOAL]
case mp
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
⊢ IsPrimitiveRoot ξ ↑k → ∃ i, i < ↑k ∧ Nat.coprime i ↑k ∧ ζ ^ i = ξ
[PROOFSTEP]
intro hξ
[GOAL]
case mp
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ξ : IsPrimitiveRoot ξ ↑k
⊢ ∃ i, i < ↑k ∧ Nat.coprime i ↑k ∧ ζ ^ i = ξ
[PROOFSTEP]
obtain ⟨i, hik, rfl⟩ := h.eq_pow_of_mem_rootsOfUnity hξ.pow_eq_one
[GOAL]
case mp.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
i : ℕ
hik : i < ↑k
hξ : IsPrimitiveRoot (ζ ^ i) ↑k
⊢ ∃ i_1, i_1 < ↑k ∧ Nat.coprime i_1 ↑k ∧ ζ ^ i_1 = ζ ^ i
[PROOFSTEP]
rw [h.pow_iff_coprime k.pos] at hξ 
[GOAL]
case mp.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
i : ℕ
hik : i < ↑k
hξ : Nat.coprime i ↑k
⊢ ∃ i_1, i_1 < ↑k ∧ Nat.coprime i_1 ↑k ∧ ζ ^ i_1 = ζ ^ i
[PROOFSTEP]
exact ⟨i, hik, hξ, rfl⟩
[GOAL]
case mpr
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
⊢ (∃ i, i < ↑k ∧ Nat.coprime i ↑k ∧ ζ ^ i = ξ) → IsPrimitiveRoot ξ ↑k
[PROOFSTEP]
rintro ⟨i, -, hi, rfl⟩
[GOAL]
case mpr.intro.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
i : ℕ
hi : Nat.coprime i ↑k
⊢ IsPrimitiveRoot (ζ ^ i) ↑k
[PROOFSTEP]
exact h.pow_of_coprime i hi
[GOAL]
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
h0 : 0 < k
⊢ IsPrimitiveRoot ξ k ↔ ∃ i, i < k ∧ Nat.coprime i k ∧ ζ ^ i = ξ
[PROOFSTEP]
constructor
[GOAL]
case mp
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
h0 : 0 < k
⊢ IsPrimitiveRoot ξ k → ∃ i, i < k ∧ Nat.coprime i k ∧ ζ ^ i = ξ
[PROOFSTEP]
intro hξ
[GOAL]
case mp
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
h0 : 0 < k
hξ : IsPrimitiveRoot ξ k
⊢ ∃ i, i < k ∧ Nat.coprime i k ∧ ζ ^ i = ξ
[PROOFSTEP]
obtain ⟨i, hik, rfl⟩ := h.eq_pow_of_pow_eq_one hξ.pow_eq_one h0
[GOAL]
case mp.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
h0 : 0 < k
i : ℕ
hik : i < k
hξ : IsPrimitiveRoot (ζ ^ i) k
⊢ ∃ i_1, i_1 < k ∧ Nat.coprime i_1 k ∧ ζ ^ i_1 = ζ ^ i
[PROOFSTEP]
rw [h.pow_iff_coprime h0] at hξ 
[GOAL]
case mp.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
h0 : 0 < k
i : ℕ
hik : i < k
hξ : Nat.coprime i k
⊢ ∃ i_1, i_1 < k ∧ Nat.coprime i_1 k ∧ ζ ^ i_1 = ζ ^ i
[PROOFSTEP]
exact ⟨i, hik, hξ, rfl⟩
[GOAL]
case mpr
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
h0 : 0 < k
⊢ (∃ i, i < k ∧ Nat.coprime i k ∧ ζ ^ i = ξ) → IsPrimitiveRoot ξ k
[PROOFSTEP]
rintro ⟨i, -, hi, rfl⟩
[GOAL]
case mpr.intro.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
h0 : 0 < k
i : ℕ
hi : Nat.coprime i k
⊢ IsPrimitiveRoot (ζ ^ i) k
[PROOFSTEP]
exact h.pow_of_coprime i hi
[GOAL]
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
n : ℕ+
h : IsPrimitiveRoot ζ ↑n
⊢ Fintype.card { x // x ∈ rootsOfUnity n R } = ↑n
[PROOFSTEP]
let e := h.zmodEquivZpowers
[GOAL]
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
n : ℕ+
h : IsPrimitiveRoot ζ ↑n
e : ZMod ↑n ≃+ Additive { x // x ∈ Subgroup.zpowers ζ } := zmodEquivZpowers h
⊢ Fintype.card { x // x ∈ rootsOfUnity n R } = ↑n
[PROOFSTEP]
haveI F : Fintype (Subgroup.zpowers ζ) := Fintype.ofEquiv _ e.toEquiv
[GOAL]
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
n : ℕ+
h : IsPrimitiveRoot ζ ↑n
e : ZMod ↑n ≃+ Additive { x // x ∈ Subgroup.zpowers ζ } := zmodEquivZpowers h
F : Fintype { x // x ∈ Subgroup.zpowers ζ }
⊢ Fintype.card { x // x ∈ rootsOfUnity n R } = ↑n
[PROOFSTEP]
calc
  Fintype.card (rootsOfUnity n R) = Fintype.card (Subgroup.zpowers ζ) := Fintype.card_congr <| by rw [h.zpowers_eq]
  _ = Fintype.card (ZMod n) := (Fintype.card_congr e.toEquiv.symm)
  _ = n := ZMod.card n
[GOAL]
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
n : ℕ+
h : IsPrimitiveRoot ζ ↑n
e : ZMod ↑n ≃+ Additive { x // x ∈ Subgroup.zpowers ζ } := zmodEquivZpowers h
F : Fintype { x // x ∈ Subgroup.zpowers ζ }
⊢ { x // x ∈ rootsOfUnity n R } ≃ { x // x ∈ Subgroup.zpowers ζ }
[PROOFSTEP]
rw [h.zpowers_eq]
[GOAL]
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
n : ℕ+
h : IsPrimitiveRoot ζ ↑n
⊢ Fintype.card { x // x ∈ rootsOfUnity n R } = ↑n
[PROOFSTEP]
obtain ⟨ζ, hζ⟩ := h.isUnit n.pos
[GOAL]
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
ζ✝ : R
n : ℕ+
h : IsPrimitiveRoot ζ✝ ↑n
ζ : Rˣ
hζ : ↑ζ = ζ✝
⊢ Fintype.card { x // x ∈ rootsOfUnity n R } = ↑n
[PROOFSTEP]
rw [← hζ, IsPrimitiveRoot.coe_units_iff] at h 
[GOAL]
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
ζ✝ : R
n : ℕ+
ζ : Rˣ
h : IsPrimitiveRoot ζ ↑n
hζ : ↑ζ = ζ✝
⊢ Fintype.card { x // x ∈ rootsOfUnity n R } = ↑n
[PROOFSTEP]
exact h.card_rootsOfUnity'
[GOAL]
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
n : ℕ
h : IsPrimitiveRoot ζ n
⊢ ↑Multiset.card (nthRoots n 1) = n
[PROOFSTEP]
cases' Nat.eq_zero_or_pos n with hzero hpos
[GOAL]
case inl
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
n : ℕ
h : IsPrimitiveRoot ζ n
hzero : n = 0
⊢ ↑Multiset.card (nthRoots n 1) = n
[PROOFSTEP]
simp only [hzero, Multiset.card_zero, nthRoots_zero]
[GOAL]
case inr
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
n : ℕ
h : IsPrimitiveRoot ζ n
hpos : n > 0
⊢ ↑Multiset.card (nthRoots n 1) = n
[PROOFSTEP]
rw [eq_iff_le_not_lt]
[GOAL]
case inr
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
n : ℕ
h : IsPrimitiveRoot ζ n
hpos : n > 0
⊢ ↑Multiset.card (nthRoots n 1) ≤ n ∧ ¬↑Multiset.card (nthRoots n 1) < n
[PROOFSTEP]
use card_nthRoots n 1
[GOAL]
case right
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
n : ℕ
h : IsPrimitiveRoot ζ n
hpos : n > 0
⊢ ¬↑Multiset.card (nthRoots n 1) < n
[PROOFSTEP]
rw [not_lt]
[GOAL]
case right
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
n : ℕ
h : IsPrimitiveRoot ζ n
hpos : n > 0
⊢ n ≤ ↑Multiset.card (nthRoots n 1)
[PROOFSTEP]
have hcard : Fintype.card { x // x ∈ nthRoots n (1 : R) } ≤ Multiset.card (nthRoots n (1 : R)).attach :=
  Multiset.card_le_of_le (Multiset.dedup_le _)
[GOAL]
case right
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
n : ℕ
h : IsPrimitiveRoot ζ n
hpos : n > 0
hcard : Fintype.card { x // x ∈ nthRoots n 1 } ≤ ↑Multiset.card (Multiset.attach (nthRoots n 1))
⊢ n ≤ ↑Multiset.card (nthRoots n 1)
[PROOFSTEP]
rw [Multiset.card_attach] at hcard 
[GOAL]
case right
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
n : ℕ
h : IsPrimitiveRoot ζ n
hpos : n > 0
hcard : Fintype.card { x // x ∈ nthRoots n 1 } ≤ ↑Multiset.card (nthRoots n 1)
⊢ n ≤ ↑Multiset.card (nthRoots n 1)
[PROOFSTEP]
rw [← PNat.toPNat'_coe hpos] at hcard h ⊢
[GOAL]
case right
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
n : ℕ
h : IsPrimitiveRoot ζ ↑(Nat.toPNat' n)
hpos : n > 0
hcard : Fintype.card { x // x ∈ nthRoots (↑(Nat.toPNat' n)) 1 } ≤ ↑Multiset.card (nthRoots (↑(Nat.toPNat' n)) 1)
⊢ ↑(Nat.toPNat' n) ≤ ↑Multiset.card (nthRoots (↑(Nat.toPNat' n)) 1)
[PROOFSTEP]
set m := Nat.toPNat' n
[GOAL]
case right
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
n : ℕ
hpos : n > 0
m : ℕ+ := Nat.toPNat' n
h : IsPrimitiveRoot ζ ↑m
hcard : Fintype.card { x // x ∈ nthRoots (↑m) 1 } ≤ ↑Multiset.card (nthRoots (↑m) 1)
⊢ ↑m ≤ ↑Multiset.card (nthRoots (↑m) 1)
[PROOFSTEP]
rw [← Fintype.card_congr (rootsOfUnityEquivNthRoots R m), card_rootsOfUnity h] at hcard 
[GOAL]
case right
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
n : ℕ
hpos : n > 0
m : ℕ+ := Nat.toPNat' n
h : IsPrimitiveRoot ζ ↑m
hcard : ↑m ≤ ↑Multiset.card (nthRoots (↑m) 1)
⊢ ↑m ≤ ↑Multiset.card (nthRoots (↑m) 1)
[PROOFSTEP]
exact hcard
[GOAL]
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
n : ℕ
h : IsPrimitiveRoot ζ n
⊢ Multiset.Nodup (nthRoots n 1)
[PROOFSTEP]
cases' Nat.eq_zero_or_pos n with hzero hpos
[GOAL]
case inl
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
n : ℕ
h : IsPrimitiveRoot ζ n
hzero : n = 0
⊢ Multiset.Nodup (nthRoots n 1)
[PROOFSTEP]
simp only [hzero, Multiset.nodup_zero, nthRoots_zero]
[GOAL]
case inr
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
n : ℕ
h : IsPrimitiveRoot ζ n
hpos : n > 0
⊢ Multiset.Nodup (nthRoots n 1)
[PROOFSTEP]
apply (Multiset.dedup_eq_self (α := R)).1
[GOAL]
case inr
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
n : ℕ
h : IsPrimitiveRoot ζ n
hpos : n > 0
⊢ Multiset.dedup (nthRoots n 1) = nthRoots n 1
[PROOFSTEP]
rw [eq_iff_le_not_lt]
[GOAL]
case inr
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
n : ℕ
h : IsPrimitiveRoot ζ n
hpos : n > 0
⊢ Multiset.dedup (nthRoots n 1) ≤ nthRoots n 1 ∧ ¬Multiset.dedup (nthRoots n 1) < nthRoots n 1
[PROOFSTEP]
constructor
[GOAL]
case inr.left
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
n : ℕ
h : IsPrimitiveRoot ζ n
hpos : n > 0
⊢ Multiset.dedup (nthRoots n 1) ≤ nthRoots n 1
[PROOFSTEP]
exact Multiset.dedup_le (nthRoots n (1 : R))
[GOAL]
case inr.right
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
n : ℕ
h : IsPrimitiveRoot ζ n
hpos : n > 0
⊢ ¬Multiset.dedup (nthRoots n 1) < nthRoots n 1
[PROOFSTEP]
by_contra ha
[GOAL]
case inr.right
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
n : ℕ
h : IsPrimitiveRoot ζ n
hpos : n > 0
ha : Multiset.dedup (nthRoots n 1) < nthRoots n 1
⊢ False
[PROOFSTEP]
replace ha := Multiset.card_lt_of_lt ha
[GOAL]
case inr.right
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
n : ℕ
h : IsPrimitiveRoot ζ n
hpos : n > 0
ha : ↑Multiset.card (Multiset.dedup (nthRoots n 1)) < ↑Multiset.card (nthRoots n 1)
⊢ False
[PROOFSTEP]
rw [card_nthRoots h] at ha 
[GOAL]
case inr.right
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
n : ℕ
h : IsPrimitiveRoot ζ n
hpos : n > 0
ha : ↑Multiset.card (Multiset.dedup (nthRoots n 1)) < n
⊢ False
[PROOFSTEP]
have hrw : Multiset.card (nthRoots n (1 : R)).dedup = Fintype.card { x // x ∈ nthRoots n (1 : R) } :=
  by
  set fs := (⟨(nthRoots n (1 : R)).dedup, Multiset.nodup_dedup _⟩ : Finset R)
  rw [← Finset.card_mk, Fintype.card_of_subtype fs _]
  intro x
  simp only [Multiset.mem_dedup, Finset.mem_mk]
[GOAL]
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
n : ℕ
h : IsPrimitiveRoot ζ n
hpos : n > 0
ha : ↑Multiset.card (Multiset.dedup (nthRoots n 1)) < n
⊢ ↑Multiset.card (Multiset.dedup (nthRoots n 1)) = Fintype.card { x // x ∈ nthRoots n 1 }
[PROOFSTEP]
set fs := (⟨(nthRoots n (1 : R)).dedup, Multiset.nodup_dedup _⟩ : Finset R)
[GOAL]
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
n : ℕ
h : IsPrimitiveRoot ζ n
hpos : n > 0
ha : ↑Multiset.card (Multiset.dedup (nthRoots n 1)) < n
fs : Finset R := { val := Multiset.dedup (nthRoots n 1), nodup := (_ : Multiset.Nodup (Multiset.dedup (nthRoots n 1))) }
⊢ ↑Multiset.card (Multiset.dedup (nthRoots n 1)) = Fintype.card { x // x ∈ nthRoots n 1 }
[PROOFSTEP]
rw [← Finset.card_mk, Fintype.card_of_subtype fs _]
[GOAL]
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
n : ℕ
h : IsPrimitiveRoot ζ n
hpos : n > 0
ha : ↑Multiset.card (Multiset.dedup (nthRoots n 1)) < n
fs : Finset R := { val := Multiset.dedup (nthRoots n 1), nodup := (_ : Multiset.Nodup (Multiset.dedup (nthRoots n 1))) }
⊢ ∀ (x : R), x ∈ fs ↔ x ∈ nthRoots n 1
[PROOFSTEP]
intro x
[GOAL]
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
n : ℕ
h : IsPrimitiveRoot ζ n
hpos : n > 0
ha : ↑Multiset.card (Multiset.dedup (nthRoots n 1)) < n
fs : Finset R := { val := Multiset.dedup (nthRoots n 1), nodup := (_ : Multiset.Nodup (Multiset.dedup (nthRoots n 1))) }
x : R
⊢ x ∈ fs ↔ x ∈ nthRoots n 1
[PROOFSTEP]
simp only [Multiset.mem_dedup, Finset.mem_mk]
[GOAL]
case inr.right
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
n : ℕ
h : IsPrimitiveRoot ζ n
hpos : n > 0
ha : ↑Multiset.card (Multiset.dedup (nthRoots n 1)) < n
hrw : ↑Multiset.card (Multiset.dedup (nthRoots n 1)) = Fintype.card { x // x ∈ nthRoots n 1 }
⊢ False
[PROOFSTEP]
rw [← PNat.toPNat'_coe hpos] at h hrw ha 
[GOAL]
case inr.right
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
n : ℕ
h : IsPrimitiveRoot ζ ↑(Nat.toPNat' n)
hpos : n > 0
ha : ↑Multiset.card (Multiset.dedup (nthRoots (↑(Nat.toPNat' n)) 1)) < ↑(Nat.toPNat' n)
hrw :
  ↑Multiset.card (Multiset.dedup (nthRoots (↑(Nat.toPNat' n)) 1)) =
    Fintype.card { x // x ∈ nthRoots (↑(Nat.toPNat' n)) 1 }
⊢ False
[PROOFSTEP]
set m := Nat.toPNat' n
[GOAL]
case inr.right
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
n : ℕ
hpos : n > 0
m : ℕ+ := Nat.toPNat' n
h : IsPrimitiveRoot ζ ↑m
ha : ↑Multiset.card (Multiset.dedup (nthRoots (↑m) 1)) < ↑m
hrw : ↑Multiset.card (Multiset.dedup (nthRoots (↑m) 1)) = Fintype.card { x // x ∈ nthRoots (↑m) 1 }
⊢ False
[PROOFSTEP]
rw [hrw, ← Fintype.card_congr (rootsOfUnityEquivNthRoots R m), card_rootsOfUnity h] at ha 
[GOAL]
case inr.right
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
n : ℕ
hpos : n > 0
m : ℕ+ := Nat.toPNat' n
h : IsPrimitiveRoot ζ ↑m
ha : ↑m < ↑m
hrw : ↑Multiset.card (Multiset.dedup (nthRoots (↑m) 1)) = Fintype.card { x // x ∈ nthRoots (↑m) 1 }
⊢ False
[PROOFSTEP]
exact Nat.lt_asymm ha ha
[GOAL]
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
n : ℕ
h : IsPrimitiveRoot ζ n
⊢ card (nthRootsFinset n R) = n
[PROOFSTEP]
rw [nthRootsFinset, ← Multiset.toFinset_eq (nthRoots_nodup h), card_mk, h.card_nthRoots]
[GOAL]
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
k : ℕ
h : IsPrimitiveRoot ζ k
⊢ card (primitiveRoots k R) = φ k
[PROOFSTEP]
by_cases h0 : k = 0
[GOAL]
case pos
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
k : ℕ
h : IsPrimitiveRoot ζ k
h0 : k = 0
⊢ card (primitiveRoots k R) = φ k
[PROOFSTEP]
simp [h0]
[GOAL]
case neg
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
k : ℕ
h : IsPrimitiveRoot ζ k
h0 : ¬k = 0
⊢ card (primitiveRoots k R) = φ k
[PROOFSTEP]
symm
[GOAL]
case neg
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
k : ℕ
h : IsPrimitiveRoot ζ k
h0 : ¬k = 0
⊢ φ k = card (primitiveRoots k R)
[PROOFSTEP]
refine' Finset.card_congr (fun i _ => ζ ^ i) _ _ _
[GOAL]
case neg.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
ζ : R
k : ℕ
h : IsPrimitiveRoot ζ k
h0 : ¬k = 0
⊢ ∀ (a : ℕ) (ha : a ∈ filter (Nat.coprime k) (range k)), (fun i x => ζ ^ i) a ha ∈ primitiveRoots k R
[PROOFSTEP]
simp only [true_and_iff, and_imp, mem_filter, mem_range, mem_univ]
[GOAL]
case neg.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
ζ : R
k : ℕ
h : IsPrimitiveRoot ζ k
h0 : ¬k = 0
⊢ ∀ (a : ℕ), a < k → Nat.coprime k a → ζ ^ a ∈ primitiveRoots k R
[PROOFSTEP]
rintro i - hi
[GOAL]
case neg.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
ζ : R
k : ℕ
h : IsPrimitiveRoot ζ k
h0 : ¬k = 0
i : ℕ
hi : Nat.coprime k i
⊢ ζ ^ i ∈ primitiveRoots k R
[PROOFSTEP]
rw [mem_primitiveRoots (Nat.pos_of_ne_zero h0)]
[GOAL]
case neg.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
ζ : R
k : ℕ
h : IsPrimitiveRoot ζ k
h0 : ¬k = 0
i : ℕ
hi : Nat.coprime k i
⊢ IsPrimitiveRoot (ζ ^ i) k
[PROOFSTEP]
exact h.pow_of_coprime i hi.symm
[GOAL]
case neg.refine'_2
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
k : ℕ
h : IsPrimitiveRoot ζ k
h0 : ¬k = 0
⊢ ∀ (a b : ℕ) (ha : a ∈ filter (Nat.coprime k) (range k)) (hb : b ∈ filter (Nat.coprime k) (range k)),
    (fun i x => ζ ^ i) a ha = (fun i x => ζ ^ i) b hb → a = b
[PROOFSTEP]
simp only [true_and_iff, and_imp, mem_filter, mem_range, mem_univ]
[GOAL]
case neg.refine'_2
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
k : ℕ
h : IsPrimitiveRoot ζ k
h0 : ¬k = 0
⊢ ∀ (a b : ℕ), a < k → Nat.coprime k a → b < k → Nat.coprime k b → ζ ^ a = ζ ^ b → a = b
[PROOFSTEP]
rintro i j hi - hj - H
[GOAL]
case neg.refine'_2
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
k : ℕ
h : IsPrimitiveRoot ζ k
h0 : ¬k = 0
i j : ℕ
hi : i < k
hj : j < k
H : ζ ^ i = ζ ^ j
⊢ i = j
[PROOFSTEP]
exact h.pow_inj hi hj H
[GOAL]
case neg.refine'_3
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
k : ℕ
h : IsPrimitiveRoot ζ k
h0 : ¬k = 0
⊢ ∀ (b : R), b ∈ primitiveRoots k R → ∃ a ha, (fun i x => ζ ^ i) a ha = b
[PROOFSTEP]
simp only [exists_prop, true_and_iff, mem_filter, mem_range, mem_univ]
[GOAL]
case neg.refine'_3
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
k : ℕ
h : IsPrimitiveRoot ζ k
h0 : ¬k = 0
⊢ ∀ (b : R), b ∈ primitiveRoots k R → ∃ a, (a < k ∧ Nat.coprime k a) ∧ ζ ^ a = b
[PROOFSTEP]
intro ξ hξ
[GOAL]
case neg.refine'_3
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
k : ℕ
h : IsPrimitiveRoot ζ k
h0 : ¬k = 0
ξ : R
hξ : ξ ∈ primitiveRoots k R
⊢ ∃ a, (a < k ∧ Nat.coprime k a) ∧ ζ ^ a = ξ
[PROOFSTEP]
rw [mem_primitiveRoots (Nat.pos_of_ne_zero h0), h.isPrimitiveRoot_iff (Nat.pos_of_ne_zero h0)] at hξ 
[GOAL]
case neg.refine'_3
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
k : ℕ
h : IsPrimitiveRoot ζ k
h0 : ¬k = 0
ξ : R
hξ : ∃ i, i < k ∧ Nat.coprime i k ∧ ζ ^ i = ξ
⊢ ∃ a, (a < k ∧ Nat.coprime k a) ∧ ζ ^ a = ξ
[PROOFSTEP]
rcases hξ with ⟨i, hin, hi, H⟩
[GOAL]
case neg.refine'_3.intro.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
ζ : R
k : ℕ
h : IsPrimitiveRoot ζ k
h0 : ¬k = 0
ξ : R
i : ℕ
hin : i < k
hi : Nat.coprime i k
H : ζ ^ i = ξ
⊢ ∃ a, (a < k ∧ Nat.coprime k a) ∧ ζ ^ a = ξ
[PROOFSTEP]
exact ⟨i, ⟨hin, hi.symm⟩, H⟩
[GOAL]
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
n : ℕ+
h : IsPrimitiveRoot ζ ↑n
⊢ nthRootsFinset (↑n) R = Finset.biUnion (Nat.divisors ↑n) fun i => primitiveRoots i R
[PROOFSTEP]
symm
[GOAL]
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
n : ℕ+
h : IsPrimitiveRoot ζ ↑n
⊢ (Finset.biUnion (Nat.divisors ↑n) fun i => primitiveRoots i R) = nthRootsFinset (↑n) R
[PROOFSTEP]
apply Finset.eq_of_subset_of_card_le
[GOAL]
case h
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
n : ℕ+
h : IsPrimitiveRoot ζ ↑n
⊢ (Finset.biUnion (Nat.divisors ↑n) fun i => primitiveRoots i R) ⊆ nthRootsFinset (↑n) R
[PROOFSTEP]
intro x
[GOAL]
case h
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
n : ℕ+
h : IsPrimitiveRoot ζ ↑n
x : R
⊢ (x ∈ Finset.biUnion (Nat.divisors ↑n) fun i => primitiveRoots i R) → x ∈ nthRootsFinset (↑n) R
[PROOFSTEP]
simp only [nthRootsFinset, ← Multiset.toFinset_eq (nthRoots_nodup h), exists_prop, Finset.mem_biUnion,
  Finset.mem_filter, Finset.mem_range, mem_nthRoots, Finset.mem_mk, Nat.mem_divisors, and_true_iff, Ne.def,
  PNat.ne_zero, PNat.pos, not_false_iff]
[GOAL]
case h
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
n : ℕ+
h : IsPrimitiveRoot ζ ↑n
x : R
⊢ (∃ a, a ∣ ↑n ∧ x ∈ primitiveRoots a R) → x ^ ↑n = 1
[PROOFSTEP]
rintro ⟨a, ⟨d, hd⟩, ha⟩
[GOAL]
case h.intro.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
ζ : R
n : ℕ+
h : IsPrimitiveRoot ζ ↑n
x : R
a : ℕ
ha : x ∈ primitiveRoots a R
d : ℕ
hd : ↑n = a * d
⊢ x ^ ↑n = 1
[PROOFSTEP]
have hazero : 0 < a := by
  contrapose! hd with ha0
  simp_all only [nonpos_iff_eq_zero, zero_mul]
  exact n.ne_zero
[GOAL]
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
n : ℕ+
h : IsPrimitiveRoot ζ ↑n
x : R
a : ℕ
ha : x ∈ primitiveRoots a R
d : ℕ
hd : ↑n = a * d
⊢ 0 < a
[PROOFSTEP]
contrapose! hd with ha0
[GOAL]
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
n : ℕ+
h : IsPrimitiveRoot ζ ↑n
x : R
a : ℕ
ha : x ∈ primitiveRoots a R
d : ℕ
ha0 : a ≤ 0
⊢ ↑n ≠ a * d
[PROOFSTEP]
simp_all only [nonpos_iff_eq_zero, zero_mul]
[GOAL]
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
n : ℕ+
h : IsPrimitiveRoot ζ ↑n
x : R
a d : ℕ
ha : x ∈ primitiveRoots 0 R
ha0 : a = 0
⊢ ↑n ≠ 0
[PROOFSTEP]
exact n.ne_zero
[GOAL]
case h.intro.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
ζ : R
n : ℕ+
h : IsPrimitiveRoot ζ ↑n
x : R
a : ℕ
ha : x ∈ primitiveRoots a R
d : ℕ
hd : ↑n = a * d
hazero : 0 < a
⊢ x ^ ↑n = 1
[PROOFSTEP]
rw [mem_primitiveRoots hazero] at ha 
[GOAL]
case h.intro.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
ζ : R
n : ℕ+
h : IsPrimitiveRoot ζ ↑n
x : R
a : ℕ
ha : IsPrimitiveRoot x a
d : ℕ
hd : ↑n = a * d
hazero : 0 < a
⊢ x ^ ↑n = 1
[PROOFSTEP]
rw [hd, pow_mul, ha.pow_eq_one, one_pow]
[GOAL]
case h₂
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
n : ℕ+
h : IsPrimitiveRoot ζ ↑n
⊢ card (nthRootsFinset (↑n) R) ≤ card (Finset.biUnion (Nat.divisors ↑n) fun i => primitiveRoots i R)
[PROOFSTEP]
apply le_of_eq
[GOAL]
case h₂.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
ζ : R
n : ℕ+
h : IsPrimitiveRoot ζ ↑n
⊢ card (nthRootsFinset (↑n) R) = card (Finset.biUnion (Nat.divisors ↑n) fun i => primitiveRoots i R)
[PROOFSTEP]
rw [h.card_nthRootsFinset, Finset.card_biUnion]
[GOAL]
case h₂.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
ζ : R
n : ℕ+
h : IsPrimitiveRoot ζ ↑n
⊢ ↑n = ∑ u in Nat.divisors ↑n, card (primitiveRoots u R)
[PROOFSTEP]
nth_rw 1 [← Nat.sum_totient n]
[GOAL]
case h₂.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
ζ : R
n : ℕ+
h : IsPrimitiveRoot ζ ↑n
⊢ Finset.sum (Nat.divisors ↑n) φ = ∑ u in Nat.divisors ↑n, card (primitiveRoots u R)
[PROOFSTEP]
refine' sum_congr rfl _
[GOAL]
case h₂.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
ζ : R
n : ℕ+
h : IsPrimitiveRoot ζ ↑n
⊢ ∀ (x : ℕ), x ∈ Nat.divisors ↑n → φ x = card (primitiveRoots x R)
[PROOFSTEP]
simp only [Nat.mem_divisors]
[GOAL]
case h₂.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
ζ : R
n : ℕ+
h : IsPrimitiveRoot ζ ↑n
⊢ ∀ (x : ℕ), x ∣ ↑n ∧ ↑n ≠ 0 → φ x = card (primitiveRoots x R)
[PROOFSTEP]
rintro k ⟨⟨d, hd⟩, -⟩
[GOAL]
case h₂.a.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
ζ : R
n : ℕ+
h : IsPrimitiveRoot ζ ↑n
k d : ℕ
hd : ↑n = k * d
⊢ φ k = card (primitiveRoots k R)
[PROOFSTEP]
rw [mul_comm] at hd 
[GOAL]
case h₂.a.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
ζ : R
n : ℕ+
h : IsPrimitiveRoot ζ ↑n
k d : ℕ
hd : ↑n = d * k
⊢ φ k = card (primitiveRoots k R)
[PROOFSTEP]
rw [(h.pow n.pos hd).card_primitiveRoots]
[GOAL]
case h₂.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
ζ : R
n : ℕ+
h : IsPrimitiveRoot ζ ↑n
⊢ ∀ (x : ℕ),
    x ∈ Nat.divisors ↑n → ∀ (y : ℕ), y ∈ Nat.divisors ↑n → x ≠ y → Disjoint (primitiveRoots x R) (primitiveRoots y R)
[PROOFSTEP]
intro i _ j _ hdiff
[GOAL]
case h₂.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
ζ : R
n : ℕ+
h : IsPrimitiveRoot ζ ↑n
i : ℕ
a✝¹ : i ∈ Nat.divisors ↑n
j : ℕ
a✝ : j ∈ Nat.divisors ↑n
hdiff : i ≠ j
⊢ Disjoint (primitiveRoots i R) (primitiveRoots j R)
[PROOFSTEP]
exact disjoint hdiff
[GOAL]
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
n : ℕ
h : IsPrimitiveRoot ζ n
⊢ nthRootsFinset n R = Finset.biUnion (Nat.divisors n) fun i => primitiveRoots i R
[PROOFSTEP]
by_cases hn : n = 0
[GOAL]
case pos
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
n : ℕ
h : IsPrimitiveRoot ζ n
hn : n = 0
⊢ nthRootsFinset n R = Finset.biUnion (Nat.divisors n) fun i => primitiveRoots i R
[PROOFSTEP]
simp [hn]
[GOAL]
case neg
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
n : ℕ
h : IsPrimitiveRoot ζ n
hn : ¬n = 0
⊢ nthRootsFinset n R = Finset.biUnion (Nat.divisors n) fun i => primitiveRoots i R
[PROOFSTEP]
exact nthRoots_one_eq_biUnion_primitiveRoots' (n := ⟨n, Nat.pos_of_ne_zero hn⟩) h
[GOAL]
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 S
inst✝² : IsDomain S
μ : S
n : ℕ+
hμ : IsPrimitiveRoot μ ↑n
inst✝¹ : CommRing R
inst✝ : Algebra R S
μ' : { x // x ∈ rootsOfUnity n S } := toRootsOfUnity hμ
⊢ orderOf μ' = ↑n
[PROOFSTEP]
rw [hμ.eq_orderOf, ← hμ.toRootsOfUnity_coe_val, orderOf_units, orderOf_subgroup]
[GOAL]
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 S
inst✝² : IsDomain S
μ : S
n : ℕ+
hμ : IsPrimitiveRoot μ ↑n
inst✝¹ : CommRing R
inst✝ : Algebra R S
μ' : { x // x ∈ rootsOfUnity n S } := toRootsOfUnity hμ
ho : orderOf μ' = ↑n
⊢ (fun σ => ↑(Exists.choose (_ : ∃ m, ↑↑σ ↑↑μ' = ↑↑μ' ^ m))) 1 = 1
[PROOFSTEP]
dsimp only
[GOAL]
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 S
inst✝² : IsDomain S
μ : S
n : ℕ+
hμ : IsPrimitiveRoot μ ↑n
inst✝¹ : CommRing R
inst✝ : Algebra R S
μ' : { x // x ∈ rootsOfUnity n S } := toRootsOfUnity hμ
ho : orderOf μ' = ↑n
⊢ ↑(Exists.choose (_ : ∃ m, ↑↑1 ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m)) = 1
[PROOFSTEP]
generalize_proofs h1
[GOAL]
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 S
inst✝² : IsDomain S
μ : S
n : ℕ+
hμ : IsPrimitiveRoot μ ↑n
inst✝¹ : CommRing R
inst✝ : Algebra R S
μ' : { x // x ∈ rootsOfUnity n S } := toRootsOfUnity hμ
ho : orderOf μ' = ↑n
h1 : ∃ m, ↑↑1 ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
⊢ ↑(Exists.choose h1) = 1
[PROOFSTEP]
have h := h1.choose_spec
[GOAL]
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 S
inst✝² : IsDomain S
μ : S
n : ℕ+
hμ : IsPrimitiveRoot μ ↑n
inst✝¹ : CommRing R
inst✝ : Algebra R S
μ' : { x // x ∈ rootsOfUnity n S } := toRootsOfUnity hμ
ho : orderOf μ' = ↑n
h1 : ∃ m, ↑↑1 ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
h : ↑↑1 ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ Exists.choose h1
⊢ ↑(Exists.choose h1) = 1
[PROOFSTEP]
dsimp only [AlgEquiv.one_apply, AlgEquiv.toRingEquiv_eq_coe, RingEquiv.toRingHom_eq_coe, RingEquiv.coe_toRingHom,
  AlgEquiv.coe_ringEquiv] at *
[GOAL]
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 S
inst✝² : IsDomain S
μ : S
n : ℕ+
hμ : IsPrimitiveRoot μ ↑n
inst✝¹ : CommRing R
inst✝ : Algebra R S
μ' : { x // x ∈ rootsOfUnity n S } := toRootsOfUnity hμ
ho : orderOf (toRootsOfUnity hμ) = ↑n
h1 : ∃ m, ↑↑1 ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
h : ↑↑1 ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ Exists.choose h1
⊢ ↑(Exists.choose h1) = 1
[PROOFSTEP]
replace h : μ' = μ' ^ h1.choose := rootsOfUnity.coe_injective (by simpa only [rootsOfUnity.coe_pow] using h)
[GOAL]
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 S
inst✝² : IsDomain S
μ : S
n : ℕ+
hμ : IsPrimitiveRoot μ ↑n
inst✝¹ : CommRing R
inst✝ : Algebra R S
μ' : { x // x ∈ rootsOfUnity n S } := toRootsOfUnity hμ
ho : orderOf (toRootsOfUnity hμ) = ↑n
h1 : ∃ m, ↑↑1 ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
h : ↑↑1 ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ Exists.choose h1
⊢ (fun x => ↑↑x) μ' = (fun x => ↑↑x) (μ' ^ Exists.choose h1)
[PROOFSTEP]
simpa only [rootsOfUnity.coe_pow] using h
[GOAL]
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 S
inst✝² : IsDomain S
μ : S
n : ℕ+
hμ : IsPrimitiveRoot μ ↑n
inst✝¹ : CommRing R
inst✝ : Algebra R S
μ' : { x // x ∈ rootsOfUnity n S } := toRootsOfUnity hμ
ho : orderOf (toRootsOfUnity hμ) = ↑n
h1 : ∃ m, ↑↑1 ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
h : μ' = μ' ^ Exists.choose h1
⊢ ↑(Exists.choose h1) = 1
[PROOFSTEP]
nth_rw 1 [← pow_one μ'] at h 
[GOAL]
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 S
inst✝² : IsDomain S
μ : S
n : ℕ+
hμ : IsPrimitiveRoot μ ↑n
inst✝¹ : CommRing R
inst✝ : Algebra R S
μ' : { x // x ∈ rootsOfUnity n S } := toRootsOfUnity hμ
ho : orderOf (toRootsOfUnity hμ) = ↑n
h1 : ∃ m, ↑↑1 ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
h : μ' ^ 1 = μ' ^ Exists.choose h1
⊢ ↑(Exists.choose h1) = 1
[PROOFSTEP]
rw [← Nat.cast_one, ZMod.nat_cast_eq_nat_cast_iff, ← ho, ← pow_eq_pow_iff_modEq μ', h]
[GOAL]
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 S
inst✝² : IsDomain S
μ : S
n : ℕ+
hμ : IsPrimitiveRoot μ ↑n
inst✝¹ : CommRing R
inst✝ : Algebra R S
μ' : { x // x ∈ rootsOfUnity n S } := toRootsOfUnity hμ
ho : orderOf μ' = ↑n
⊢ ∀ (x y : S ≃ₐ[R] S),
    OneHom.toFun
        { toFun := fun σ => ↑(Exists.choose (_ : ∃ m, ↑↑σ ↑↑μ' = ↑↑μ' ^ m)),
          map_one' := (_ : (fun σ => ↑(Exists.choose (_ : ∃ m, ↑↑σ ↑↑μ' = ↑↑μ' ^ m))) 1 = 1) }
        (x * y) =
      OneHom.toFun
          { toFun := fun σ => ↑(Exists.choose (_ : ∃ m, ↑↑σ ↑↑μ' = ↑↑μ' ^ m)),
            map_one' := (_ : (fun σ => ↑(Exists.choose (_ : ∃ m, ↑↑σ ↑↑μ' = ↑↑μ' ^ m))) 1 = 1) }
          x *
        OneHom.toFun
          { toFun := fun σ => ↑(Exists.choose (_ : ∃ m, ↑↑σ ↑↑μ' = ↑↑μ' ^ m)),
            map_one' := (_ : (fun σ => ↑(Exists.choose (_ : ∃ m, ↑↑σ ↑↑μ' = ↑↑μ' ^ m))) 1 = 1) }
          y
[PROOFSTEP]
intro x y
[GOAL]
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 S
inst✝² : IsDomain S
μ : S
n : ℕ+
hμ : IsPrimitiveRoot μ ↑n
inst✝¹ : CommRing R
inst✝ : Algebra R S
μ' : { x // x ∈ rootsOfUnity n S } := toRootsOfUnity hμ
ho : orderOf μ' = ↑n
x y : S ≃ₐ[R] S
⊢ OneHom.toFun
      { toFun := fun σ => ↑(Exists.choose (_ : ∃ m, ↑↑σ ↑↑μ' = ↑↑μ' ^ m)),
        map_one' := (_ : (fun σ => ↑(Exists.choose (_ : ∃ m, ↑↑σ ↑↑μ' = ↑↑μ' ^ m))) 1 = 1) }
      (x * y) =
    OneHom.toFun
        { toFun := fun σ => ↑(Exists.choose (_ : ∃ m, ↑↑σ ↑↑μ' = ↑↑μ' ^ m)),
          map_one' := (_ : (fun σ => ↑(Exists.choose (_ : ∃ m, ↑↑σ ↑↑μ' = ↑↑μ' ^ m))) 1 = 1) }
        x *
      OneHom.toFun
        { toFun := fun σ => ↑(Exists.choose (_ : ∃ m, ↑↑σ ↑↑μ' = ↑↑μ' ^ m)),
          map_one' := (_ : (fun σ => ↑(Exists.choose (_ : ∃ m, ↑↑σ ↑↑μ' = ↑↑μ' ^ m))) 1 = 1) }
        y
[PROOFSTEP]
dsimp only
[GOAL]
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 S
inst✝² : IsDomain S
μ : S
n : ℕ+
hμ : IsPrimitiveRoot μ ↑n
inst✝¹ : CommRing R
inst✝ : Algebra R S
μ' : { x // x ∈ rootsOfUnity n S } := toRootsOfUnity hμ
ho : orderOf μ' = ↑n
x y : S ≃ₐ[R] S
⊢ ↑(Exists.choose (_ : ∃ m, ↑↑(x * y) ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m)) =
    ↑(Exists.choose (_ : ∃ m, ↑↑x ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m)) *
      ↑(Exists.choose (_ : ∃ m, ↑↑y ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m))
[PROOFSTEP]
generalize_proofs hxy' hx' hy'
[GOAL]
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 S
inst✝² : IsDomain S
μ : S
n : ℕ+
hμ : IsPrimitiveRoot μ ↑n
inst✝¹ : CommRing R
inst✝ : Algebra R S
μ' : { x // x ∈ rootsOfUnity n S } := toRootsOfUnity hμ
ho : orderOf μ' = ↑n
x y : S ≃ₐ[R] S
hxy' : ∃ m, ↑↑(x * y) ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
hx' : ∃ m, ↑↑x ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
hy' : ∃ m, ↑↑y ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
⊢ ↑(Exists.choose hxy') = ↑(Exists.choose hx') * ↑(Exists.choose hy')
[PROOFSTEP]
have hxy := hxy'.choose_spec
[GOAL]
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 S
inst✝² : IsDomain S
μ : S
n : ℕ+
hμ : IsPrimitiveRoot μ ↑n
inst✝¹ : CommRing R
inst✝ : Algebra R S
μ' : { x // x ∈ rootsOfUnity n S } := toRootsOfUnity hμ
ho : orderOf μ' = ↑n
x y : S ≃ₐ[R] S
hxy' : ∃ m, ↑↑(x * y) ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
hx' : ∃ m, ↑↑x ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
hy' : ∃ m, ↑↑y ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
hxy : ↑↑(x * y) ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ Exists.choose hxy'
⊢ ↑(Exists.choose hxy') = ↑(Exists.choose hx') * ↑(Exists.choose hy')
[PROOFSTEP]
have hx := hx'.choose_spec
[GOAL]
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 S
inst✝² : IsDomain S
μ : S
n : ℕ+
hμ : IsPrimitiveRoot μ ↑n
inst✝¹ : CommRing R
inst✝ : Algebra R S
μ' : { x // x ∈ rootsOfUnity n S } := toRootsOfUnity hμ
ho : orderOf μ' = ↑n
x y : S ≃ₐ[R] S
hxy' : ∃ m, ↑↑(x * y) ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
hx' : ∃ m, ↑↑x ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
hy' : ∃ m, ↑↑y ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
hxy : ↑↑(x * y) ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ Exists.choose hxy'
hx : ↑↑x ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ Exists.choose hx'
⊢ ↑(Exists.choose hxy') = ↑(Exists.choose hx') * ↑(Exists.choose hy')
[PROOFSTEP]
have hy := hy'.choose_spec
[GOAL]
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 S
inst✝² : IsDomain S
μ : S
n : ℕ+
hμ : IsPrimitiveRoot μ ↑n
inst✝¹ : CommRing R
inst✝ : Algebra R S
μ' : { x // x ∈ rootsOfUnity n S } := toRootsOfUnity hμ
ho : orderOf μ' = ↑n
x y : S ≃ₐ[R] S
hxy' : ∃ m, ↑↑(x * y) ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
hx' : ∃ m, ↑↑x ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
hy' : ∃ m, ↑↑y ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
hxy : ↑↑(x * y) ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ Exists.choose hxy'
hx : ↑↑x ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ Exists.choose hx'
hy : ↑↑y ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ Exists.choose hy'
⊢ ↑(Exists.choose hxy') = ↑(Exists.choose hx') * ↑(Exists.choose hy')
[PROOFSTEP]
dsimp only [AlgEquiv.toRingEquiv_eq_coe, RingEquiv.toRingHom_eq_coe, RingEquiv.coe_toRingHom, AlgEquiv.coe_ringEquiv,
  AlgEquiv.mul_apply] at *
[GOAL]
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 S
inst✝² : IsDomain S
μ : S
n : ℕ+
hμ : IsPrimitiveRoot μ ↑n
inst✝¹ : CommRing R
inst✝ : Algebra R S
μ' : { x // x ∈ rootsOfUnity n S } := toRootsOfUnity hμ
ho : orderOf (toRootsOfUnity hμ) = ↑n
x y : S ≃ₐ[R] S
hxy' : ∃ m, ↑↑(x * y) ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
hx' : ∃ m, ↑↑x ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
hy' : ∃ m, ↑↑y ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
hxy : ↑↑(x * y) ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ Exists.choose hxy'
hx : ↑↑x ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ Exists.choose hx'
hy : ↑↑y ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ Exists.choose hy'
⊢ ↑(Exists.choose hxy') = ↑(Exists.choose hx') * ↑(Exists.choose hy')
[PROOFSTEP]
replace hxy : x (((μ' : Sˣ) : S) ^ hy'.choose) = ((μ' : Sˣ) : S) ^ hxy'.choose := hy ▸ hxy
[GOAL]
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 S
inst✝² : IsDomain S
μ : S
n : ℕ+
hμ : IsPrimitiveRoot μ ↑n
inst✝¹ : CommRing R
inst✝ : Algebra R S
μ' : { x // x ∈ rootsOfUnity n S } := toRootsOfUnity hμ
ho : orderOf (toRootsOfUnity hμ) = ↑n
x y : S ≃ₐ[R] S
hxy' : ∃ m, ↑↑(x * y) ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
hx' : ∃ m, ↑↑x ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
hy' : ∃ m, ↑↑y ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
hx : ↑↑x ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ Exists.choose hx'
hy : ↑↑y ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ Exists.choose hy'
hxy : ↑x (↑↑μ' ^ Exists.choose hy') = ↑↑μ' ^ Exists.choose hxy'
⊢ ↑(Exists.choose hxy') = ↑(Exists.choose hx') * ↑(Exists.choose hy')
[PROOFSTEP]
rw [x.map_pow] at hxy 
[GOAL]
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 S
inst✝² : IsDomain S
μ : S
n : ℕ+
hμ : IsPrimitiveRoot μ ↑n
inst✝¹ : CommRing R
inst✝ : Algebra R S
μ' : { x // x ∈ rootsOfUnity n S } := toRootsOfUnity hμ
ho : orderOf (toRootsOfUnity hμ) = ↑n
x y : S ≃ₐ[R] S
hxy' : ∃ m, ↑↑(x * y) ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
hx' : ∃ m, ↑↑x ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
hy' : ∃ m, ↑↑y ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
hx : ↑↑x ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ Exists.choose hx'
hy : ↑↑y ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ Exists.choose hy'
hxy : ↑x ↑↑μ' ^ Exists.choose hy' = ↑↑μ' ^ Exists.choose hxy'
⊢ ↑(Exists.choose hxy') = ↑(Exists.choose hx') * ↑(Exists.choose hy')
[PROOFSTEP]
replace hxy : (((μ' : Sˣ) : S) ^ hx'.choose) ^ hy'.choose = ((μ' : Sˣ) : S) ^ hxy'.choose := hx ▸ hxy
[GOAL]
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 S
inst✝² : IsDomain S
μ : S
n : ℕ+
hμ : IsPrimitiveRoot μ ↑n
inst✝¹ : CommRing R
inst✝ : Algebra R S
μ' : { x // x ∈ rootsOfUnity n S } := toRootsOfUnity hμ
ho : orderOf (toRootsOfUnity hμ) = ↑n
x y : S ≃ₐ[R] S
hxy' : ∃ m, ↑↑(x * y) ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
hx' : ∃ m, ↑↑x ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
hy' : ∃ m, ↑↑y ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
hx : ↑↑x ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ Exists.choose hx'
hy : ↑↑y ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ Exists.choose hy'
hxy : (↑↑μ' ^ Exists.choose hx') ^ Exists.choose hy' = ↑↑μ' ^ Exists.choose hxy'
⊢ ↑(Exists.choose hxy') = ↑(Exists.choose hx') * ↑(Exists.choose hy')
[PROOFSTEP]
rw [← pow_mul] at hxy 
[GOAL]
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 S
inst✝² : IsDomain S
μ : S
n : ℕ+
hμ : IsPrimitiveRoot μ ↑n
inst✝¹ : CommRing R
inst✝ : Algebra R S
μ' : { x // x ∈ rootsOfUnity n S } := toRootsOfUnity hμ
ho : orderOf (toRootsOfUnity hμ) = ↑n
x y : S ≃ₐ[R] S
hxy' : ∃ m, ↑↑(x * y) ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
hx' : ∃ m, ↑↑x ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
hy' : ∃ m, ↑↑y ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
hx : ↑↑x ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ Exists.choose hx'
hy : ↑↑y ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ Exists.choose hy'
hxy : ↑↑μ' ^ (Exists.choose hx' * Exists.choose hy') = ↑↑μ' ^ Exists.choose hxy'
⊢ ↑(Exists.choose hxy') = ↑(Exists.choose hx') * ↑(Exists.choose hy')
[PROOFSTEP]
replace hxy : μ' ^ (hx'.choose * hy'.choose) = μ' ^ hxy'.choose :=
  rootsOfUnity.coe_injective (by simpa only [rootsOfUnity.coe_pow] using hxy)
[GOAL]
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 S
inst✝² : IsDomain S
μ : S
n : ℕ+
hμ : IsPrimitiveRoot μ ↑n
inst✝¹ : CommRing R
inst✝ : Algebra R S
μ' : { x // x ∈ rootsOfUnity n S } := toRootsOfUnity hμ
ho : orderOf (toRootsOfUnity hμ) = ↑n
x y : S ≃ₐ[R] S
hxy' : ∃ m, ↑↑(x * y) ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
hx' : ∃ m, ↑↑x ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
hy' : ∃ m, ↑↑y ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
hx : ↑↑x ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ Exists.choose hx'
hy : ↑↑y ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ Exists.choose hy'
hxy : ↑↑μ' ^ (Exists.choose hx' * Exists.choose hy') = ↑↑μ' ^ Exists.choose hxy'
⊢ (fun x => ↑↑x) (μ' ^ (Exists.choose hx' * Exists.choose hy')) = (fun x => ↑↑x) (μ' ^ Exists.choose hxy')
[PROOFSTEP]
simpa only [rootsOfUnity.coe_pow] using hxy
[GOAL]
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 S
inst✝² : IsDomain S
μ : S
n : ℕ+
hμ : IsPrimitiveRoot μ ↑n
inst✝¹ : CommRing R
inst✝ : Algebra R S
μ' : { x // x ∈ rootsOfUnity n S } := toRootsOfUnity hμ
ho : orderOf (toRootsOfUnity hμ) = ↑n
x y : S ≃ₐ[R] S
hxy' : ∃ m, ↑↑(x * y) ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
hx' : ∃ m, ↑↑x ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
hy' : ∃ m, ↑↑y ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
hx : ↑↑x ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ Exists.choose hx'
hy : ↑↑y ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ Exists.choose hy'
hxy : μ' ^ (Exists.choose hx' * Exists.choose hy') = μ' ^ Exists.choose hxy'
⊢ ↑(Exists.choose hxy') = ↑(Exists.choose hx') * ↑(Exists.choose hy')
[PROOFSTEP]
rw [← Nat.cast_mul, ZMod.nat_cast_eq_nat_cast_iff, ← ho, ← pow_eq_pow_iff_modEq μ', hxy]
[GOAL]
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 S
inst✝² : IsDomain S
μ : S
n : ℕ+
hμ : IsPrimitiveRoot μ ↑n
inst✝¹ : CommRing R
inst✝ : Algebra R S
f : S ≃ₐ[R] S
⊢ μ ^ ZMod.val ↑(↑(autToPow R hμ) f) = ↑f μ
[PROOFSTEP]
rw [IsPrimitiveRoot.coe_autToPow_apply]
[GOAL]
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 S
inst✝² : IsDomain S
μ : S
n : ℕ+
hμ : IsPrimitiveRoot μ ↑n
inst✝¹ : CommRing R
inst✝ : Algebra R S
f : S ≃ₐ[R] S
⊢ μ ^ ZMod.val ↑(Exists.choose (_ : ∃ m, ↑f ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m)) = ↑f μ
[PROOFSTEP]
generalize_proofs h
[GOAL]
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 S
inst✝² : IsDomain S
μ : S
n : ℕ+
hμ : IsPrimitiveRoot μ ↑n
inst✝¹ : CommRing R
inst✝ : Algebra R S
f : S ≃ₐ[R] S
h : ∃ m, ↑f ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
⊢ μ ^ ZMod.val ↑(Exists.choose h) = ↑f μ
[PROOFSTEP]
have := h.choose_spec
[GOAL]
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 S
inst✝² : IsDomain S
μ : S
n : ℕ+
hμ : IsPrimitiveRoot μ ↑n
inst✝¹ : CommRing R
inst✝ : Algebra R S
f : S ≃ₐ[R] S
h : ∃ m, ↑f ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
this : ↑f ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ Exists.choose h
⊢ μ ^ ZMod.val ↑(Exists.choose h) = ↑f μ
[PROOFSTEP]
dsimp only [AlgEquiv.toAlgHom_eq_coe, AlgEquiv.coe_algHom] at this 
[GOAL]
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 S
inst✝² : IsDomain S
μ : S
n : ℕ+
hμ : IsPrimitiveRoot μ ↑n
inst✝¹ : CommRing R
inst✝ : Algebra R S
f : S ≃ₐ[R] S
h : ∃ m, ↑f ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
this : ↑f ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ Exists.choose h
⊢ μ ^ ZMod.val ↑(Exists.choose h) = ↑f μ
[PROOFSTEP]
refine' (_ : ((hμ.toRootsOfUnity : Sˣ) : S) ^ _ = _).trans this.symm
[GOAL]
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 S
inst✝² : IsDomain S
μ : S
n : ℕ+
hμ : IsPrimitiveRoot μ ↑n
inst✝¹ : CommRing R
inst✝ : Algebra R S
f : S ≃ₐ[R] S
h : ∃ m, ↑f ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
this : ↑f ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ Exists.choose h
⊢ ↑↑(toRootsOfUnity hμ) ^ ZMod.val ↑(Exists.choose h) = ↑↑(toRootsOfUnity hμ) ^ Exists.choose h
[PROOFSTEP]
rw [← rootsOfUnity.coe_pow, ← rootsOfUnity.coe_pow]
[GOAL]
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 S
inst✝² : IsDomain S
μ : S
n : ℕ+
hμ : IsPrimitiveRoot μ ↑n
inst✝¹ : CommRing R
inst✝ : Algebra R S
f : S ≃ₐ[R] S
h : ∃ m, ↑f ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
this : ↑f ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ Exists.choose h
⊢ ↑↑(toRootsOfUnity hμ ^ ZMod.val ↑(Exists.choose h)) = ↑↑(toRootsOfUnity hμ ^ Exists.choose h)
[PROOFSTEP]
congr 2
[GOAL]
case e_self.e_self
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 S
inst✝² : IsDomain S
μ : S
n : ℕ+
hμ : IsPrimitiveRoot μ ↑n
inst✝¹ : CommRing R
inst✝ : Algebra R S
f : S ≃ₐ[R] S
h : ∃ m, ↑f ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
this : ↑f ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ Exists.choose h
⊢ toRootsOfUnity hμ ^ ZMod.val ↑(Exists.choose h) = toRootsOfUnity hμ ^ Exists.choose h
[PROOFSTEP]
rw [pow_eq_pow_iff_modEq, ZMod.val_nat_cast, hμ.eq_orderOf, ← orderOf_subgroup, ← orderOf_units]
[GOAL]
case e_self.e_self
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 S
inst✝² : IsDomain S
μ : S
n : ℕ+
hμ : IsPrimitiveRoot μ ↑n
inst✝¹ : CommRing R
inst✝ : Algebra R S
f : S ≃ₐ[R] S
h : ∃ m, ↑f ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ m
this : ↑f ↑↑(toRootsOfUnity hμ) = ↑↑(toRootsOfUnity hμ) ^ Exists.choose h
⊢ Exists.choose h % orderOf μ ≡ Exists.choose h [MOD orderOf ↑↑(toRootsOfUnity hμ)]
[PROOFSTEP]
exact Nat.mod_modEq _ _
