# Finding Roots Of Unity *Thanks [Matan](https://sites.google.com/view/matanprasmashomepage/publications) for teaching the topic!* ![idk](https://hackmd.io/_uploads/Skh03cRFJg.jpg) Roots of unity are the elements in a [field](https://en.wikipedia.org/wiki/Field_(mathematics)) that satisfy the equation $$ x^n = 1 $$ In cryptography, you might come across having to use the [Discrete Fourier Transform](https://en.wikipedia.org/wiki/Discrete_Fourier_transform) (DFT) to optimize polynomial multiplications or [dealing with commitment schemes](https://hackmd.io/@brech1/fk). Roots of unity are a key structure for the DFT, in this post I'll review the steps to find a [generator](https://crypto.stanford.edu/pbc/notes/numbertheory/gen.html) for a group of $n$-th [roots of unity](https://crypto.stanford.edu/pbc/notes/numbertheory/rootsunity.html). ## Prime Field A prime field is a [finite field](https://en.wikipedia.org/wiki/Finite_field) with a prime number of elements. It is usually denoted by $\mathbb{F}_p$ where $p$ is prime. In prime fields, every nonzero element has a multiplicative inverse, and there are no zero divisors. This guarantees that the [multiplicative group](https://en.wikipedia.org/wiki/Multiplicative_group) $\mathbb{F}_p^*$ is cyclic (has a generator). The [cyclic](https://crypto.stanford.edu/pbc/notes/numbertheory/cyclic.html) nature of $\mathbb{F}_p^*$ means that any [subgroup](https://math.libretexts.org/Bookshelves/Abstract_and_Geometric_Algebra/First-Semester_Abstract_Algebra%3A_A_Structural_Approach_(Sklar)/04%3A_Subgroups/4.01%3A_Introduction_to_Subgroups), such as the group of $n$-th roots of unity, is also cyclic. ## Roots Of Unity An element $\omega$ of a field is an $n$-th root of unity if $$ \omega^n = 1 $$ For example, in the complex numbers the $n$-th roots of unity are given by $$ \omega_k = e^{\frac{2\pi i k}{n}} \quad \text{for } k = 0, 1, 2, \dots, n-1 $$ ## Lagrange's Theorem [Lagrange's Theorem](https://en.wikipedia.org/wiki/Lagrange%27s_theorem_(group_theory)) states that for any finite group $G$ and subgroup $H$, the order (number of elements) of $H$ divides the order of $G$: $$ |H| \mid |G| $$ When applied to the multiplicative group of a finite field, such as $\mathbb{F}_{p}^*$, we know that this group is cyclic and has order $p$. Therefore, any subgroup of $\mathbb{F}_{p}^*$ must have an order that divides $p$. ## Extending The Field Now, let's assume we need $n$ roots of unity for our operation. We have to work with a finite field with a sufficiently large multiplicative group ($>n$). To get a larger field, we consider an [extension field](https://mathworld.wolfram.com/ExtensionField.html), typically denoted by $\mathbb{F}_{p^N}$. This notation indicates that each element of $\mathbb{F}_{p^N}$ can be uniquely written as a linear combination of $N$ basis elements. Since there are $p$ choices for each coefficient, the total number of elements in $\mathbb{F}_{p^N}$ is $p^N$. Since the multiplicative group excludes the zero element, the group $\mathbb{F}_{p^N}^*$ is of order $$ p^N - 1 $$ By Lagrange, we can define our condition as: $$ n \mid (p^N - 1) $$ To find the minimal extension degree we can perform this check for every element: ```python def minimal_extension_degree(p, n): N = 1 while (p**N - 1) % n != 0: N += 1 return N ``` ## Finding $w$ Now that we have extended our field, we can find a generator for the subgroup of $n$-th roots of unity. To verify whether a candidate element $g$ is a generator, we must check that raising it to the power $\frac{n}{p}$ does not yield the [identity element](https://en.wikipedia.org/wiki/Identity_element). So: $$ g^{n/p} \neq 1 $$ If any of these powers equals $1$, the element's order is a proper divisor of $n$, and it cannot be a generator. The naive implementation looks like this: ```python def is_generator(g, group_order): # Factor the group order for p, e in factor(group_order): if g^(group_order // p) == 1: return False return True ``` Sage, however, provides a more efficient method for this, which you can view [here](https://github.com/sagemath/sage/blob/develop/src/sage/rings/finite_rings/finite_field_base.pyx#L830). Since the multiplicative group $\mathbb{F}_{p^N}^*$ is cyclic, every element can be written as a power of a generator $g$. We want to find a primitive $n$-th root of unity $\omega$ that satisfies $$ \omega^n = 1 $$ Assume that $\omega$ can be written as a power of $g$: $$ w = g^k $$ Then we have $$ w^n = (g^k)^n = g^{kn} $$ Because $g$ is a generator of $\mathbb{F}_{p^N}^*$ we know that $$ g^{|F^*|} = g^{p^N - 1} = 1. $$ In a cyclic group, the equation $g^m = 1$ holds if and only if $|F^*|$ divides $m$. Therefore, for $$ g^{kn} = 1, $$ it is necessary and sufficient that $|F^*|$ divides $kn$. To ensure that $\omega$ is a primitive \(n\)-th root of unity, we choose the smallest $k$ such that this condition is met. The minimal choice is $$ k = \frac{|F^*|}{n} = \frac{p^N - 1}{n} $$ Resulting in $$ \omega = g^{\frac{p^N - 1}{n}} $$ Once we have our primitive $n$-th root of unity $\omega$, we can generate the complete set of $n$-th roots of unity by taking its successive powers: $$ \mu_n = \{ \omega^0, \omega^1, \omega^2, \dots, \omega^{n-1} \} $$ ## Mersenne Prime *Not related to the main topic, but I'll use this in the implementation example.* A Mersenne number is a number of the form $$ M_n = 2^n - 1 $$ When a Mersenne number is prime, it is called a Mersenne prime. > 💡 The present [largest known prime](https://www.mersenne.org/primes/?press=M136279841) is a Mersenne prime. An interesting one for us is $M_{31}$ $$ M_{31} = 2^{31} - 1 $$ Since $M_{31}$ is a 32-bit prime, every element in the field $\mathbb{F}_{M_{31}}$ can be stored in a single computer word. This leads to very efficient arithmetic operations. ## Full steps Below are the steps to find the generator for: - $n = 8$ - $p = M_{31}$ ```sage # Declare n and p n = 8 p = 2**31 - 1 # Get N (degree of field extension) N = minimal_extension_degree(p, n) # Define the Prime Field of order p^N F = FiniteField(p**N) # Get the generator of F_p* with Sage's method gen_mul_subg = F.multiplicative_generator() # Get roots of unity generator w = gen_mul_subg ** ((F.cardinality() - 1) // n) ``` After computing this we get: - $\omega$ = `1816824951*z2 + 1438809788` - $\mu_n$ = {`1`, `1816824951*z2 + 1438809788`, `209180821*z2 + 2126293891`, ` 1816824951*z2 + 1438744252`, `2147483646`,`330658696*z2 + 708673859`, `1938302826*z2 + 21189756`, `330658696*z2 + 708739395`} We can verify the obtained roots: ```sage roots = [w**k for k in range(n)] for k, r in enumerate(roots): if r**n != F(1): print("Verification Failed for root", k) break else: print("All roots verified") ``` ## References - [Circle STARKs: notes from a seminar in Stateless Consensus EF (2024)](https://sites.google.com/view/matanprasmashomepage/publications) - [Roots of Unity](https://crypto.stanford.edu/pbc/notes/numbertheory/rootsunity.html) - [Plonky3](https://github.com/Plonky3/Plonky3/blob/main/mersenne-31/src/mersenne_31.rs) - [Why I’m Excited By Circle Stark And Stwo](https://starkware.co/integrity-matters-blog/why-im-excited-by-circle-stark-and-stwo/) - [Sage](https://www.sagemath.org/)