# Fast Fourier Transforms (draft).
A polynomial of degree $k$ can be described in two different ways:
1. the sequence of its coefficients $f = (a_0, a_1\dots , a_{k})$
2. a list of $k+1$ evaluations $f = (f(x_0), \dots, f(x_k))$ for a fixed set $(x_0, x_1,\cdots, x_k)$.
Fourier transforms are ways to switch back and forth between such representations.
#### Why would you care?
1. Easy polynomial multiplication. For example if $\deg(f) =m$ and $deg(g)= n$ then computing $f\cdot g$ will cost $O(mn)$ operations. If we do this via FFT, you can do it in $O((m+n)\log (m+n))$.
2. Erasure codes. Recall that if you encode your data as a polynomial of degree $2^{k-1} < n < 2^k$ then you can produce an erasure code $$ C= \{ f(\omega^i) | i = 1 \dots 2^{k+1}-1 \}.$$
Knowing any $2^k$ of these $2^{k+1}$ elements will allow you to reconstruct the polynomial. FFT will allow this in $O(n\log n)$. This is very useful for sharding.
## Mutiplicative FFT
### Theoretical point:
Suppose that $p$ is a prime so that $2^k | p-1$ and $F$ is the field of "reminders modulo $p$".
In this case $F$ admits $2^k$ roots of 1, that is there exist elements $a \in F$ with $a^{2^k} = 1 \pmod p$.
Let $\omega$ be a `primitive` $2^k$ root of one, that is $\omega^{2^k} =1 \pmod p$ in $F$ and $\omega^{2^{k-1}} \ne 1 \pmod p$. (such an element exists).
$f$ is a polynomial of degree n and $2^{k-1} < n < 2^k$. Consider the correspondence
$$ f \rightarrow S =\{ f(\omega^i) | i = 1 \dots 2^k-1 \}.$$
Clearly knowing $f$ determines the set $S$ and, by Lagrange interpolation, the set $S$ uniquely determines $f$.
#### Problems you want to solve:
1. **Evaluation**: Given $f$, compute $S$. Naively this will cost $O(n^2)$ which is unacceptable. FFT will allow for $O(n\log n)$
2. **Interpolation**: Given the set $S$ of element of $f$ determine $f$ as above. Again Lagrange interpolation costs $O(n^2)$. Again FFT will allow for $O(n\log n)$
### Algorithms
#### Evaluation:
The main point here is that, if $\omega$ is a (primitive) $n$ root of 1 (n even) then $\omega^{\frac n 2}= -1$ so and $x= \omega^i$, $y = \omega ^{i+\frac n 2}$ then $x = -y$ and $x^2=y^2$ is a $\frac n 2$ root of 1. Moreover $\omega^2$ will be a primitive $\frac n 2$ root of 1.
Consider the decomposition of the polynomial:
$$f (x) = a_0 + a_1 x \cdots a_{n}x^{n} = (a_0 + a_2 x^2 + \cdots) + x (a_1 + a_3x^2 \cdots) = f_0(x^2) + x f_1(x^2)$$
If follows that $f(\omega^i) = f_0(\omega^{2i}) + \omega^if_1(\omega^{2i})$. In particular, the evaluation problem for $f$ of degree $n$ reduces to evaluating the two polynomials $f_0$ and $f_1$ which have degree (at most) $\frac n 2$ at all $\frac n 2$ roots of 1. Inductively one can show that you will need $O(n\log n)$ operations. The algorithm then is as follows:
`input:` $f = (a_0, ..., a_n)$
`output` $(z_0, ..., z_{2^k-1}) = (f(\omega^0), f(\omega^1), \cdots , f(\omega^{2^k-1}))$
1. Let $(b_0, \cdots , b_{\frac n 2}) = (a_0, a_2, \cdots, a_n)$ and $(c_0, \cdots , b_{\frac n 2 -1}) = (a_1, a_3, \cdots, a_{n-1})$.
2. Recursively solve the problem for $(b_0, \cdots , b_{\frac n 2})$ and $(c_0, \cdots , b_{\frac n 2 -1})$ replacing $\omega$ by $\omega^2$ to obtain $(x_0, ..., x_{2^{k-1}-1})$ respectively $(y_0, ..., y_{2^{k-1}-1})$.
3. Reasemble the output as $z_i = x_i + \omega^iy_i$ if $i\le 2^{k-1}-1$ and $z_i = x_{i-2^{k-1}} + \omega^iy_{i-2^{k-1}}$ otherwise.
#### Interpolation.
Suppose that you know the set $S = \{z_i | i = 1 \cdots n-1\}$ and you want to compute apolynomial of degree $< n$ so that $f(\omega^i) = z_i$. You first note that the respective polynomial will have the decomposition $f_0(x^2) + x f_1(x^2)$ as above and that
$$f(\omega^i)= f_0(\omega^{2i}) + \omega^i f_1(\omega^{2i})$$
$$f(\omega^{i+ \frac n 2})/2 = y_i + y_{i+\frac n 2})/2= f_0(\omega^{2i}) - \omega^i f_1(\omega^{2i})$$
We can compute $$f_0(\omega^{2i})= \frac{f(\omega^i)+f(\omega^{i+ \frac n 2})} 2 = \frac {z_i + z_{i+\frac n 2}} 2$$
$$f_1(\omega^{2i})= \frac{f(\omega^i)-f(\omega^{i+ \frac n 2})} {2\omega^i} = \frac {z_i - z_{i+\frac n 2}} {2 \omega^i}$$
Therefore the interpolation problem for the set $S=\{y_i | i = 1 \cdots n-1\}$ is equivalent to two interpolation problems $S_0 =\{ \frac {y_i + y_{i+\frac n 2}} 2 | i =0 \cdots \frac n 2 - 1\}$ respectively $S_1 = \{\frac {y_i - y_{i+\frac n 2}}{2 \omega^i} i =0 \cdots \frac n 2 - 1\}$. Inductively this shows that the interpolation will be computed in $O(n\log n)$.
The algorithm then is as follows:
`input:` $(z_0, ..., z_{2^k-1}) = (f(\omega^0), f(\omega^1), \cdots , f(\omega^{2^k-1}))$
`output` $f = (a_0, ..., a_n)$
1. Let $x_i = \frac {y_i + y_{i+\frac n 2}} 2$ and $y_i = \frac {z_i - z_{i+\frac n 2}} {2 \omega^i}$ for all $i = 0, \cdots 2^{k-1}-1$.
2. Recursively solve the problem for $(x_0, \cdots , x_{2^{k-1}-1})$ and $(y_0, \cdots , y_{2^{k-1}-1})$ replacing $\omega$ by $\omega^2$ to obtain $(b_0, ..., b_{\frac n 2})$ respectively $(c_0, ..., c_{\frac n 2 -1})$.
3. Reasemble the output as $(a_0, ..., a_n) = (b_0, b_1, a_1, b_2, \cdots , a_{\frac n 2})$.
## Applications:
1. polynomial multiplication:
Suppose $f,g$ are two polinomials of degrees $\le n$. It means thet $f\cdot g$ is a poly of degree $\le 2n$. To compute that, compute $f(\omega^i)\cdot g(\omega^i)$ for $0\le i \le 2n$ and $omega$ a $2n$ root of 1 (recall $n$ is a power of two) this takes $O(n\log n)$. Now interpolate the polinomial $g$ of degree less than $2n$ so that $g(\omega^i)=f(\omega^i)\cdot g(\omega^i)$. This again takes $O(n\log n)$. Standard poly multiplication is $n^2$.
- Given $a,b$ two vectors with nonegative integer coefficients write an algorithm that finds all possible sums $(a[i]+ b[j])$ and the number of times each appears.
2. General interpolation:
Suppose you want to find a polynomial $P$ of degree $\le n$ so that $P(x_i) = y_i$ for $i = 1,\cdots n$. and so that $x_i$ are in the set $\{\omega^k | k = 0,\cdots 2n\}$This is useful for example in erasure codes.
You want to use lagrange interpolation, that is to compute
$$P(x)= \sum_{i=1}^n y_i\prod_{j\ne i}\frac{x-x_j}{x_i-x_j} =\sum_{i=1}^n y_i\frac{Q_i(x)}{Q_i(x_i)} $$
where $Q_i=\prod_{j\ne i}(x-x_j)$. Note that $Q_i(x_j)=0$ if $i\ne j$.
Note that doing this is unreasonably expensive. To do that you compute $Z=(x-x_1)\cdots (x-x_n)$.
We then have
$$P(x)= \sum_{i=1}^n \frac{Q_i(x)}{Q_i(x_i)} = Z(x)\sum_{i=1}^n \frac{y_i}{Q_i(x_i)(x-x_i)}$$
Note that $Z'(x) = \sum_i Q_i(x)$ and so $Q_i(x_i)=Z'(x_i)$. We can therfore evaluate the $n_i= \frac{y_i}{Q_i(x_i)}$ in $O(n\log n)$. Next we need to compute $Z(x)\sum_{i=1}^n \frac{n_i}{(x-x_i)}$.
We use Taylor series to expand $\sum_{i=1}^n \frac{n_i}{(x-x_i)}$ and truncate at $x^n$. The useing polynomial multiplication we can obtain $P$ in $O(n\log n)$.
## Problem:
Very often a field $F$ does not contain enough roots of 1.
* if $F$ is a field of characteristic 2 then there are no $2^k$ roots of one aside from 1 itself.
* in the BLS12-381 library, the field size is `52435875175126190479447740508185965837690552500527637822603658699938581184513` while the largest $2^k$ root of one is of order $2^32=4294967296$.
In the literarure we have found two approaches for this:
1. Elliptic curves FFT (see a brief description in [here](https://hackmd.io/@corneliuhoffman/ECFFT))
2. Additive FFT. There are a number of algorithms for this, see [Todd Mateer's thesis](https://tigerprints.clemson.edu/cgi/viewcontent.cgi?article=1231&context=all_dissertations) for an overview of the state of the art in the late 2000's. To my knowledge the 2014 paper described below is the best existing algorithm
## Additive FFT (based on [Lin & all.](https://www.semanticscholar.org/paper/Novel-Polynomial-Basis-and-Its-Application-to-Codes-Lin-Chung/46ab62acbba389bbaa08d5350dea04ad477ed75d))
### Finite Fields of characteristic 2:
A finite field of characteristic 2 (or binary finite field) is a generalization of mod two arithmetic. It is a finite set $F$ together with operations $+, \cdot$ and elements $0_F, 1_F \in F$so that:
* $\forall a, b,c \in F,$
$$a +b = b+a,$$
$$a\cdot b = b\cdot a ,$$
$$a\cdot (b+c) = a\cdot b + a\cdot c $$
$$a+0=a$$
$$a\cdot 1 = a$$
* $\forall a \in F, a+a =0$
* $\forall a \in F\setminus\{0_F\}, \exists b \in F, a\cdot b =1$. We denote that $b$ by $a^{-1}$.
#### Properties:
1. The size of a finite field of characteristic 2 is $2^k$ for some $k$ an, for each $k$ there is a "unique" field of that size. It is usually denoted by $\mathbb{F}_{2^k}$ or $GF(2^k)$. We will use the latter notation. In particular the field $GF(2)$ is just the mod 2 arithmetic
2.The field $F =GF(2^k)$ a "copy" inside a field $G =GF(2^l)$ if and only if $k | l$. In that case you can view $G$ as a $F$ vector space and all methods of linear algebra work.
3. $\forall a, b \in F,$ if $a \cdot b = 0$ then $a = 0$ or $b =0$.
4. $\forall a, b \in F, (a +b)^2 = a^2+b^2$.
5. If $F =GF(2^k)$ then $\forall a \in F, a^{2^k} =a$.
6. If $F =GF(2^k)$ then there exists $\omega \in F$ so that $F = \{0, \omega, \omega^2 \cdots \omega^{2^k-1}\}$.
7. If $f(x) = a_0 + a_1x + a_{k-1}x^{k-1} + x^k$ is a polynomial of degree $k$ with coefficients in $F$ then there are at most $k$ elements of $a \in F$ with $f(a)$. Moreover synthetic division of polynomials works as usual.
7. If $F =GF(2^k)$ and $Z_2$ is the field of order 2 then there exists a polynomial $f = a_0 + a_1x + a_{k-1}x^{k-1} + x^k$ of degree $k$ with coefficients in $Z_2$ so that $K =GF(2)[X]/f. That means that $F = \{\sum_{i=0}^{k-1} b_i x^i | b_i \in Z_2\}$ where addition is usual (coefficient XOR) and mutiplication is done modulo the identity $x^k = a_0 + a_1x + a_{k-1}x^{k-1} + x^k$.
For example the field with 4 elements can be constructed using the polynomial $x^2+x+1$ so $F = \{0,1,x,x+1\}$ and teh tables for addition and multiplication are:
| + | 0 | 1 | x | x+1 |
| - | - | - | - | -|
| 0 | 0 | 1 | x | x+1|
| 1 | 1 | 0 | x+1 | x|
| x | x | x+1 | 0 | 1|
| x+1 | x+1 | x | 1 | 0|
| $\cdot$ | 0 | 1 | x | x+1 |
| - | - | - | - | -|
| 0 | 0 | 0 | 0 | 0|
| 1 | 0 | 1 | x | x+1|
| x | 0 | x | x+1 | 1|
| x+1 | 0 | x+1 | 1 | x|
### Subspace polynomials:
Recall that if $F =GF(2^k)$ $F$ is a $GF(2)$ vector space. Suppose that $V$ is a subspace of $F$. We can define the polynomial
$$W(x) = \prod_{a \in V} (x+a) $$
This polynomial has the following properties:
1. $\forall w \in V, W(w) = 0$
2. $\forall a, b \in F, W(a+b) = W(a) + W(b)$.
3. $W(x) = a_1x + a_2 x^2 + a_4 x^4 + \cdots + x^{2^k}$ where $V$ is a vector space of dimension $k$.
4. $\forall x \in F, w \in V, W(a+w) = W(a)$.
### Lin and all. construction.
Let $F = GF(2^k$) and fix $\{v_0, v_1, \cdots v_{r-1}\}$ a bsis of F$ as a vector space. That means that every element of $F$ can be written uniquely asa sumof some of the $v_i$. Fix an order on $F$ as follows:
If $$i = i_0 + i_1\cdot 2 + i_2 \cdot 2^2 +\dots + i_{k-1}2^{k-1}$$ is the binary representation of $i$ then we will denote
$$ w_i =i_0 + i_1v_1+ i_2 \cdot v_2 +\dots + i_{k-1}v_{k-1}.$$
We also define $W_i$ to be the subspace polynomial for the space $V_i = \{w_j| j= 0\dots 2^i-1\}$ that is
$$W_i =\prod_{i=0}^{2^i-1} (x+w_i).$$
**Notes:**
- the degree of $W_i$ is $2^i$.
- One can recursivelly compmpute $W_i$ using:
$$W_{i+1}(x) = W_i^2(x) + W_i(w_{2^i})W_i(x)$$
- if $i\le j$ then $W_i | W_j$.
Finally define (with the above binary representation of $i$)
$$X_i(x) =\prod_{i=0}^{k-1} \left(\frac{W_j(x)}{W_j(w_{2^j})}\right)^{i_j}$$
It is not to hard to convince yourself that the degree of $X_i$ is i.
**Notes:**
- the powers $i_j$ are just 0 or 1. In particular $X_0=1$
- if $i_j = 0$ then $\left(\frac{W_j(x)}{W_j(w_{2^j})}\right)^{i_j}=1$
- If $2^{j}\le i < 2^{j+1}$ (that is $j = log_2(i)$) then $\forall w \in V_j, X_i(w) = 0$.
- if $i < 2^j$ then $X_i | X_{2^j-1}$.
Remarcably $X_i$ forms a basis for the vector space of polynomials with coefficients in $F$ and so they will "play the role" of $x^i$ in the standard FFT. In particular a polynomial of degree $k-1$ can be written as
$D_h = (h_0, \cdots, h_{k-1})$ where the polynomial is (notation as in Op.cit.)
$$[D_k](x) = \sum_{i=1}^{k-1} d_iX_i(x).$$
Conversely we can have an "evaluation" transformation
$$\Psi_k^l([D_k]) = ([D_k](w_0+w_l), [D_k](w_1+w_l), \cdots [D_k](w_{k-1}+w_l))$$
Which admits an "interpolation" inverse that will be described below. For simplicity we will denote
$$\bar{W}_j(x)=\frac{W_j(x)}{W_j(w_{2^j})}$$