# Documentation

Mathlib.RingTheory.RootsOfUnity.Basic

# Roots of unity and primitive roots of unity #

We define roots of unity in the context of an arbitrary commutative monoid, as a subgroup of the group of units. We also define a predicate IsPrimitiveRoot on commutative monoids, expressing that an element is a primitive root of unity.

## Main definitions #

• rootsOfUnity n M, for n : ℕ+ is the subgroup of the units of a commutative monoid M consisting of elements x that satisfy x ^ n = 1.
• IsPrimitiveRoot ζ k: an element ζ is a primitive k-th root of unity if ζ ^ k = 1, and if l satisfies ζ ^ l = 1 then k ∣ l.
• primitiveRoots k R: the finset of primitive k-th roots of unity in an integral domain R.
• IsPrimitiveRoot.autToPow: the monoid hom that takes an automorphism of a ring to the power it sends that specific primitive root, as a member of (ZMod n)ˣ.

## Main results #

• rootsOfUnity.isCyclic: the roots of unity in an integral domain form a cyclic group.
• IsPrimitiveRoot.zmodEquivZpowers: ZMod k is equivalent to the subgroup generated by a primitive k-th root of unity.
• IsPrimitiveRoot.zpowers_eq: in an integral domain, the subgroup generated by a primitive k-th root of unity is equal to the k-th roots of unity.
• IsPrimitiveRoot.card_primitiveRoots: if an integral domain has a primitive k-th root of unity, then it has φ k of them.

## Implementation details #

It is desirable that rootsOfUnity is a subgroup, and it will mainly be applied to rings (e.g. the ring of integers in a number field) and fields. We therefore implement it as a subgroup of the units of a commutative monoid.

We have chosen to define rootsOfUnity n for n : ℕ+, instead of n : ℕ, because almost all lemmas need the positivity assumption, and in particular the type class instances for Fintype and IsCyclic.

On the other hand, for primitive roots of unity, it is desirable to have a predicate not just on units, but directly on elements of the ring/field. For example, we want to say that exp (2 * pi * I / n) is a primitive n-th root of unity in the complex numbers, without having to turn that number into a unit first.

This creates a little bit of friction, but lemmas like IsPrimitiveRoot.isUnit and IsPrimitiveRoot.coe_units_iff should provide the necessary glue.

def rootsOfUnity (k : ℕ+) (M : Type u_7) [] :

rootsOfUnity k M is the subgroup of elements m : Mˣ that satisfy m ^ k = 1.

Instances For
@[simp]
theorem mem_rootsOfUnity {M : Type u_1} [] (k : ℕ+) (ζ : Mˣ) :
ζ ζ ^ k = 1
theorem mem_rootsOfUnity' {M : Type u_1} [] (k : ℕ+) (ζ : Mˣ) :
ζ ζ ^ k = 1
theorem rootsOfUnity.coe_injective {M : Type u_1} [] {n : ℕ+} :
Function.Injective fun x => x
@[simp]
theorem rootsOfUnity.val_mkOfPowEq_coe {M : Type u_1} [] (ζ : M) {n : ℕ+} (h : ζ ^ n = 1) :
↑() = ζ
def rootsOfUnity.mkOfPowEq {M : Type u_1} [] (ζ : M) {n : ℕ+} (h : ζ ^ n = 1) :
{ x // x }

Make an element of rootsOfUnity from a member of the base ring, and a proof that it has a positive power equal to one.

Instances For
@[simp]
theorem rootsOfUnity.coe_mkOfPowEq {M : Type u_1} [] {ζ : M} {n : ℕ+} (h : ζ ^ n = 1) :
↑() = ζ
theorem rootsOfUnity_le_of_dvd {M : Type u_1} [] {k : ℕ+} {l : ℕ+} (h : k l) :
theorem map_rootsOfUnity {M : Type u_1} {N : Type u_2} [] [] (f : Mˣ →* Nˣ) (k : ℕ+) :
theorem rootsOfUnity.coe_pow {R : Type u_4} {k : ℕ+} [] (ζ : { x // x }) (m : ) :
↑(ζ ^ m) = ζ ^ m
def restrictRootsOfUnity {R : Type u_4} {S : Type u_5} {F : Type u_6} [] [] [RingHomClass F R S] (σ : F) (n : ℕ+) :
{ x // x } →* { x // x }

Restrict a ring homomorphism to the nth roots of unity.

Instances For
@[simp]
theorem restrictRootsOfUnity_coe_apply {R : Type u_4} {S : Type u_5} {F : Type u_6} {k : ℕ+} [] [] [RingHomClass F R S] (σ : F) (ζ : { x // x }) :
↑(↑() ζ) = σ ζ
def RingEquiv.restrictRootsOfUnity {R : Type u_4} {S : Type u_5} [] [] (σ : R ≃+* S) (n : ℕ+) :
{ x // x } ≃* { x // x }

Restrict a ring isomorphism to the nth roots of unity.

Instances For
@[simp]
theorem RingEquiv.restrictRootsOfUnity_coe_apply {R : Type u_4} {S : Type u_5} {k : ℕ+} [] [] (σ : R ≃+* S) (ζ : { x // x }) :
↑(↑() ζ) = σ ζ
@[simp]
theorem RingEquiv.restrictRootsOfUnity_symm {R : Type u_4} {S : Type u_5} {k : ℕ+} [] [] (σ : R ≃+* S) :
theorem mem_rootsOfUnity_iff_mem_nthRoots {R : Type u_4} {k : ℕ+} [] [] {ζ : Rˣ} :
ζ ζ Polynomial.nthRoots (k) 1
def rootsOfUnityEquivNthRoots (R : Type u_4) (k : ℕ+) [] [] :
{ x // x } { x // x Polynomial.nthRoots (k) 1 }

Equivalence between the k-th roots of unity in R and the k-th roots of 1.

This is implemented as equivalence of subtypes, because rootsOfUnity is a subgroup of the group of units, whereas nthRoots is a multiset.

Instances For
@[simp]
theorem rootsOfUnityEquivNthRoots_apply {R : Type u_4} {k : ℕ+} [] [] (x : { x // x }) :
↑(↑() x) = x
@[simp]
theorem rootsOfUnityEquivNthRoots_symm_apply {R : Type u_4} {k : ℕ+} [] [] (x : { x // x Polynomial.nthRoots (k) 1 }) :
↑(().symm x) = x
instance rootsOfUnity.fintype (R : Type u_4) (k : ℕ+) [] [] :
Fintype { x // x }
instance rootsOfUnity.isCyclic (R : Type u_4) (k : ℕ+) [] [] :
IsCyclic { x // x }
theorem card_rootsOfUnity (R : Type u_4) (k : ℕ+) [] [] :
Fintype.card { x // x } k
theorem map_rootsOfUnity_eq_pow_self {R : Type u_4} {F : Type u_6} {k : ℕ+} [] [] [RingHomClass F R R] (σ : F) (ζ : { x // x }) :
m, σ ζ = ζ ^ m
theorem mem_rootsOfUnity_prime_pow_mul_iff (R : Type u_4) [] [] (p : ) (k : ) (m : ℕ+) [hp : Fact ()] [CharP R p] {ζ : Rˣ} :
ζ rootsOfUnity ({ val := p, property := (_ : 0 < p) } ^ k * m) R ζ
@[simp]
theorem mem_rootsOfUnity_prime_pow_mul_iff' (R : Type u_4) [] [] (p : ) (k : ) (m : ℕ+) [hp : Fact ()] [CharP R p] {ζ : Rˣ} :
ζ ^ (p ^ k * m) = 1 ζ
theorem IsPrimitiveRoot.iff_def {M : Type u_1} [] (ζ : M) (k : ) :
ζ ^ k = 1 ∀ (l : ), ζ ^ l = 1k l
structure IsPrimitiveRoot {M : Type u_1} [] (ζ : M) (k : ) :
• pow_eq_one : ζ ^ k = 1
• dvd_of_pow_eq_one : ∀ (l : ), ζ ^ l = 1k l

An element ζ is a primitive k-th root of unity if ζ ^ k = 1, and if l satisfies ζ ^ l = 1 then k ∣ l.

Instances For
@[simp]
theorem IsPrimitiveRoot.val_inv_toRootsOfUnity_coe {M : Type u_1} [] {μ : M} {n : ℕ+} (h : ) :
= μ ^ (n - 1)
@[simp]
theorem IsPrimitiveRoot.val_toRootsOfUnity_coe {M : Type u_1} [] {μ : M} {n : ℕ+} (h : ) :
def IsPrimitiveRoot.toRootsOfUnity {M : Type u_1} [] {μ : M} {n : ℕ+} (h : ) :
{ x // x }

Turn a primitive root μ into a member of the rootsOfUnity subgroup.

Instances For
def primitiveRoots (k : ) (R : Type u_7) [] [] :

primitiveRoots k R is the finset of primitive k-th roots of unity in the integral domain R.

Instances For
@[simp]
theorem mem_primitiveRoots {R : Type u_4} {k : } [] [] {ζ : R} (h0 : 0 < k) :
ζ
@[simp]
theorem primitiveRoots_zero {R : Type u_4} [] [] :
theorem isPrimitiveRoot_of_mem_primitiveRoots {R : Type u_4} {k : } [] [] {ζ : R} (h : ζ ) :
theorem IsPrimitiveRoot.mk_of_lt {M : Type u_1} [] {k : } (ζ : M) (hk : 0 < k) (h1 : ζ ^ k = 1) (h : ∀ (l : ), 0 < ll < kζ ^ l 1) :
theorem IsPrimitiveRoot.of_subsingleton {M : Type u_1} [] [] (x : M) :
theorem IsPrimitiveRoot.pow_eq_one_iff_dvd {M : Type u_1} [] {k : } {ζ : M} (h : ) (l : ) :
ζ ^ l = 1 k l
theorem IsPrimitiveRoot.isUnit {M : Type u_1} [] {k : } {ζ : M} (h : ) (h0 : 0 < k) :
theorem IsPrimitiveRoot.pow_ne_one_of_pos_of_lt {M : Type u_1} [] {k : } {l : } {ζ : M} (h : ) (h0 : 0 < l) (hl : l < k) :
ζ ^ l 1
theorem IsPrimitiveRoot.ne_one {M : Type u_1} [] {k : } {ζ : M} (h : ) (hk : 1 < k) :
ζ 1
theorem IsPrimitiveRoot.pow_inj {M : Type u_1} [] {k : } {ζ : M} (h : ) ⦃i : ⦃j : (hi : i < k) (hj : j < k) (H : ζ ^ i = ζ ^ j) :
i = j
theorem IsPrimitiveRoot.one {M : Type u_1} [] :
@[simp]
theorem IsPrimitiveRoot.one_right_iff {M : Type u_1} [] {ζ : M} :
ζ = 1
@[simp]
theorem IsPrimitiveRoot.coe_submonoidClass_iff {k : } {M : Type u_7} {B : Type u_8} [] [SetLike B M] [] {N : B} {ζ : { x // x N }} :
IsPrimitiveRoot (ζ) k
@[simp]
theorem IsPrimitiveRoot.coe_units_iff {M : Type u_1} [] {k : } {ζ : Mˣ} :
IsPrimitiveRoot (ζ) k
theorem IsPrimitiveRoot.pow_of_coprime {M : Type u_1} [] {k : } {ζ : M} (h : ) (i : ) (hi : ) :
theorem IsPrimitiveRoot.pow_of_prime {M : Type u_1} [] {k : } {ζ : M} (h : ) {p : } (hprime : ) (hdiv : ¬p k) :
theorem IsPrimitiveRoot.pow_iff_coprime {M : Type u_1} [] {k : } {ζ : M} (h : ) (h0 : 0 < k) (i : ) :
theorem IsPrimitiveRoot.orderOf {M : Type u_1} [] (ζ : M) :
theorem IsPrimitiveRoot.unique {M : Type u_1} [] {k : } {l : } {ζ : M} (hk : ) (hl : ) :
k = l
theorem IsPrimitiveRoot.eq_orderOf {M : Type u_1} [] {k : } {ζ : M} (h : ) :
k =
theorem IsPrimitiveRoot.iff {M : Type u_1} [] {k : } {ζ : M} (hk : 0 < k) :
ζ ^ k = 1 ∀ (l : ), 0 < ll < kζ ^ l 1
theorem IsPrimitiveRoot.not_iff {M : Type u_1} [] {k : } {ζ : M} :
theorem IsPrimitiveRoot.pow_of_dvd {M : Type u_1} [] {k : } {ζ : M} (h : ) {p : } (hp : p 0) (hdiv : p k) :
IsPrimitiveRoot (ζ ^ p) (k / p)
theorem IsPrimitiveRoot.mem_rootsOfUnity {M : Type u_1} [] {ζ : Mˣ} {n : ℕ+} (h : ) :
ζ
theorem IsPrimitiveRoot.pow {M : Type u_1} [] {ζ : M} {n : } {a : } {b : } (hn : 0 < n) (h : ) (hprod : n = a * b) :

If there is an n-th primitive root of unity in R and b divides n, then there is a b-th primitive root of unity in R.

theorem IsPrimitiveRoot.map_of_injective {M : Type u_1} {N : Type u_2} {F : Type u_6} [] [] {k : } {ζ : M} {f : F} [] (h : ) (hf : ) :
IsPrimitiveRoot (f ζ) k
theorem IsPrimitiveRoot.of_map_of_injective {M : Type u_1} {N : Type u_2} {F : Type u_6} [] [] {k : } {ζ : M} {f : F} [] (h : IsPrimitiveRoot (f ζ) k) (hf : ) :
theorem IsPrimitiveRoot.map_iff_of_injective {M : Type u_1} {N : Type u_2} {F : Type u_6} [] [] {k : } {ζ : M} {f : F} [] (hf : ) :
IsPrimitiveRoot (f ζ) k
theorem IsPrimitiveRoot.zero {M₀ : Type u_7} [] [] :
theorem IsPrimitiveRoot.ne_zero {k : } {M₀ : Type u_7} [] [] {ζ : M₀} (h : ) :
k 0ζ 0
theorem IsPrimitiveRoot.zpow_eq_one {G : Type u_3} {k : } {ζ : G} (h : ) :
ζ ^ k = 1
theorem IsPrimitiveRoot.zpow_eq_one_iff_dvd {G : Type u_3} {k : } {ζ : G} (h : ) (l : ) :
ζ ^ l = 1 k l
theorem IsPrimitiveRoot.inv {G : Type u_3} {k : } {ζ : G} (h : ) :
@[simp]
theorem IsPrimitiveRoot.inv_iff {G : Type u_3} {k : } {ζ : G} :
theorem IsPrimitiveRoot.zpow_of_gcd_eq_one {G : Type u_3} {k : } {ζ : G} (h : ) (i : ) (hi : Int.gcd i k = 1) :
@[simp]
theorem IsPrimitiveRoot.primitiveRoots_one {R : Type u_4} [] [] :
= {1}
theorem IsPrimitiveRoot.neZero' {R : Type u_4} {ζ : R} [] [] {n : ℕ+} (hζ : ) :
NeZero n
theorem IsPrimitiveRoot.mem_nthRootsFinset {R : Type u_4} {k : } {ζ : R} [] [] (hζ : ) (hk : 0 < k) :
theorem IsPrimitiveRoot.eq_neg_one_of_two_right {R : Type u_4} [] [] {ζ : R} (h : ) :
ζ = -1
theorem IsPrimitiveRoot.neg_one {R : Type u_4} [] (p : ) [] [h : CharP R p] (hp : p 2) :
theorem IsPrimitiveRoot.geom_sum_eq_zero {R : Type u_4} {k : } [] [] {ζ : R} (hζ : ) (hk : 1 < k) :
(Finset.sum () fun i => ζ ^ i) = 0

If 1 < k then (∑ i in range k, ζ ^ i) = 0.

theorem IsPrimitiveRoot.pow_sub_one_eq {R : Type u_4} {k : } [] [] {ζ : R} (hζ : ) (hk : 1 < k) :
ζ ^ = -Finset.sum () fun i => ζ ^ i

If 1 < k, then ζ ^ k.pred = -(∑ i in range k.pred, ζ ^ i).

def IsPrimitiveRoot.zmodEquivZpowers {R : Type u_4} {k : } [] {ζ : Rˣ} (h : ) :
ZMod k ≃+ Additive { x // }

The (additive) monoid equivalence between ZMod k and the powers of a primitive root of unity ζ.

Instances For
@[simp]
theorem IsPrimitiveRoot.zmodEquivZpowers_apply_coe_int {R : Type u_4} {k : } [] {ζ : Rˣ} (h : ) (i : ) :
= Additive.ofMul { val := ζ ^ i, property := (_ : y, (fun x x_1 => x ^ x_1) ζ y = ζ ^ i) }
@[simp]
theorem IsPrimitiveRoot.zmodEquivZpowers_apply_coe_nat {R : Type u_4} {k : } [] {ζ : Rˣ} (h : ) (i : ) :
= Additive.ofMul { val := ζ ^ i, property := (_ : y, (fun x x_1 => x ^ x_1) ζ y = ζ ^ i) }
@[simp]
theorem IsPrimitiveRoot.zmodEquivZpowers_symm_apply_zpow {R : Type u_4} {k : } [] {ζ : Rˣ} (h : ) (i : ) :
↑() (Additive.ofMul { val := ζ ^ i, property := (_ : y, (fun x x_1 => x ^ x_1) ζ y = ζ ^ i) }) = i
@[simp]
theorem IsPrimitiveRoot.zmodEquivZpowers_symm_apply_zpow' {R : Type u_4} {k : } [] {ζ : Rˣ} (h : ) (i : ) :
↑() { val := ζ ^ i, property := (_ : y, (fun x x_1 => x ^ x_1) ζ y = ζ ^ i) } = i
@[simp]
theorem IsPrimitiveRoot.zmodEquivZpowers_symm_apply_pow {R : Type u_4} {k : } [] {ζ : Rˣ} (h : ) (i : ) :
↑() (Additive.ofMul { val := ζ ^ i, property := (_ : y, (fun x x_1 => x ^ x_1) ζ y = ζ ^ i) }) = i
@[simp]
theorem IsPrimitiveRoot.zmodEquivZpowers_symm_apply_pow' {R : Type u_4} {k : } [] {ζ : Rˣ} (h : ) (i : ) :
↑() { val := ζ ^ i, property := (_ : y, (fun x x_1 => x ^ x_1) ζ y = ζ ^ i) } = i
theorem IsPrimitiveRoot.zpowers_eq {R : Type u_4} [] [] {k : ℕ+} {ζ : Rˣ} (h : ) :
theorem IsPrimitiveRoot.eq_pow_of_mem_rootsOfUnity {R : Type u_4} [] [] {k : ℕ+} {ζ : Rˣ} {ξ : Rˣ} (h : ) (hξ : ξ ) :
i, i < k ζ ^ i = ξ
theorem IsPrimitiveRoot.eq_pow_of_pow_eq_one {R : Type u_4} [] [] {k : } {ζ : R} {ξ : R} (h : ) (hξ : ξ ^ k = 1) (h0 : 0 < k) :
i, i < k ζ ^ i = ξ
theorem IsPrimitiveRoot.isPrimitiveRoot_iff' {R : Type u_4} [] [] {k : ℕ+} {ζ : Rˣ} {ξ : Rˣ} (h : ) :
i, i < k Nat.Coprime i k ζ ^ i = ξ
theorem IsPrimitiveRoot.isPrimitiveRoot_iff {R : Type u_4} [] [] {k : } {ζ : R} {ξ : R} (h : ) (h0 : 0 < k) :
i, i < k ζ ^ i = ξ
theorem IsPrimitiveRoot.card_rootsOfUnity' {R : Type u_4} [] {ζ : Rˣ} [] {n : ℕ+} (h : ) :
Fintype.card { x // x } = n
theorem IsPrimitiveRoot.card_rootsOfUnity {R : Type u_4} [] [] {ζ : R} {n : ℕ+} (h : ) :
Fintype.card { x // x } = n
theorem IsPrimitiveRoot.card_nthRoots {R : Type u_4} [] [] {ζ : R} {n : } (h : ) :
Multiset.card () = n

The cardinality of the multiset nthRoots ↑n (1 : R) is n if there is a primitive root of unity in R.

theorem IsPrimitiveRoot.nthRoots_nodup {R : Type u_4} [] [] {ζ : R} {n : } (h : ) :

The multiset nthRoots ↑n (1 : R) has no repeated elements if there is a primitive root of unity in R.

@[simp]
theorem IsPrimitiveRoot.card_nthRootsFinset {R : Type u_4} [] [] {ζ : R} {n : } (h : ) :
theorem IsPrimitiveRoot.card_primitiveRoots {R : Type u_4} [] [] {ζ : R} {k : } (h : ) :

If an integral domain has a primitive k-th root of unity, then it has φ k of them.

theorem IsPrimitiveRoot.disjoint {R : Type u_4} [] [] {k : } {l : } (h : k l) :
Disjoint () ()

The sets primitiveRoots k R are pairwise disjoint.

theorem IsPrimitiveRoot.nthRoots_one_eq_biUnion_primitiveRoots' {R : Type u_4} [] [] {ζ : R} {n : ℕ+} (h : ) :
= Finset.biUnion () fun i =>

nthRoots n as a Finset is equal to the union of primitiveRoots i R for i ∣ n if there is a primitive root of unity in R. This holds for any Nat, not just PNat, see nthRoots_one_eq_bUnion_primitive_roots.

theorem IsPrimitiveRoot.nthRoots_one_eq_biUnion_primitiveRoots {R : Type u_4} [] [] {ζ : R} {n : } (h : ) :
= Finset.biUnion () fun i =>

nthRoots n as a Finset is equal to the union of primitiveRoots i R for i ∣ n if there is a primitive root of unity in R.

noncomputable def IsPrimitiveRoot.autToPow (R : Type u_4) {S : Type u_5} [] [] {μ : S} {n : ℕ+} (hμ : ) [] [Algebra R S] :
(S ≃ₐ[R] S) →* (ZMod n)ˣ

The MonoidHom that takes an automorphism to the power of μ that μ gets mapped to under it.

Instances For
theorem IsPrimitiveRoot.coe_autToPow_apply (R : Type u_4) {S : Type u_5} [] [] {μ : S} {n : ℕ+} (hμ : ) [] [Algebra R S] (f : S ≃ₐ[R] S) :
↑(↑() f) = ↑(Exists.choose (_ : m, f = ^ m))
@[simp]
theorem IsPrimitiveRoot.autToPow_spec (R : Type u_4) {S : Type u_5} [] [] {μ : S} {n : ℕ+} (hμ : ) [] [Algebra R S] (f : S ≃ₐ[R] S) :
μ ^ ZMod.val ↑(↑() f) = f μ