An executable search for a primitive root of unity modulo p #
Mathlib proves that ZMod p contains a primitive k-th root of unity when p is prime and
k ∣ p - 1, but the witness comes from the cyclicity of the unit group and cannot be evaluated.
An algorithm that works modulo p with a root of unity needs one it can compute. This file supplies
TauCeti.ZMod.primitiveRoot?, which tests the residues 0, 1, …, p - 1 in turn and returns the
first one that is a primitive k-th root of unity, together with the proof that it is one.
The test is the finite criterion of IsPrimitiveRoot.mk_of_lt: 0 < k, ζ ^ k = 1 and
ζ ^ l ≠ 1 for 0 < l < k. It is decidable in ZMod p, so the search runs, and since every
residue is tested, for p ≠ 0 and k ≠ 0 the search fails only when there is nothing to find
(TauCeti.ZMod.isSome_primitiveRoot?_iff). The criterion deliberately excludes order zero, so the
search always fails for k = 0, even though 0 : ZMod p is a primitive 0-th root of unity when
p ≠ 1.
Main definitions #
TauCeti.ZMod.primitiveRoot?: forp ≠ 0andk ≠ 0, the least residue modulopthat is a primitivek-th root of unity, if there is one; alwaysnonewhenk = 0.
Main results #
TauCeti.ZMod.isSome_primitiveRoot?_iff: the search succeeds exactly whenZMod phas a primitivek-th root of unity, forpandknonzero.TauCeti.ZMod.map_val_primitiveRoot?_eq_some_iff: the search returns the least residue passing the criterion, a decidable description of its value.
An executable search for a primitive k-th root of unity in ZMod p. The residues
0, 1, …, p - 1 are tested in increasing order against the criterion ζ ^ k = 1 and ζ ^ l ≠ 1
for 0 < l < k, and the first one that passes is returned with the proof that it is a primitive
root. The result is none when no residue passes, in particular when k = 0.
Equations
Instances For
The search finds a primitive root whenever there is one. For p and k nonzero, the
search over all residues modulo p succeeds exactly when ZMod p contains a primitive k-th
root of unity.
Which root the search returns. The search returns ζ exactly when ζ passes the
criterion ζ ^ k = 1 and ζ ^ l ≠ 1 for 0 < l < k and no smaller residue does; the condition
ζ.val < p only fails for p = 0, where there are no residues to test. Every condition is
decidable, so a concrete value of the search can be checked without unfolding it.