# Discrete Fast Fourier Transform Available code files: * [fft2.sage](https://github.com/darkrenaissance/darkfi/blob/master/script/research/zk/fft/fft2.sage): implementation using vandermonde matrices illustrating the theory section below. * [fft3.sage](https://github.com/darkrenaissance/darkfi/blob/master/script/research/zk/fft/fft3.sage): simple example with $n = 4$ showing 3 steps of the algorithm. * [fft4.sage](https://github.com/darkrenaissance/darkfi/blob/master/script/research/zk/fft/fft4.sage): illustrates the full working algorithm. ## Theory $$ f(x)g(x) ∈ š”½_{<2n}[x] $$ $$ fg = \sum_{i + j < 2n - 2} a_i b_j x^{i + j} $$ Complexity: $O(n^2)$ Suppose $ω ∈ š”½$ is an nth root of unity. Recall: if $š”½ = š”½_{p^k}$ then $∃N : š”½_{p^N}$ contains all nth roots of unity. $$ \DFT_ω : š”½^n → š”½^n $$ $$ \DFT_ω(f) = (f(ω^0), f(ω^1), …, f(ω^{n - 1})) $$ $$ V_ω = \begin{pmatrix} 1 & 1 & 1 & \cdots & 1 \\ 1 & ω^1 & ω^2 & \cdots & ω^{n - 1} \\ 1 & ω^2 & ω^4 & \cdots & ω^{2(n - 1)} \\ \vdots \\ 1 & ω^{n - 1} & ω^{2(n - 1)} & \cdots & ω^{(n - 1)^2} \\ \end{pmatrix} $$ $$ \DFT_ω(f) = V_ω Ā· f^T $$ since vandermonde multiplication is simply evaluation of a polynomial. ### Lemma: $V_ω^{-1} = \frac{1}{n} V_{ω^{-1}}$ Use $1 + ω + ⋯ + ω^{n - 1}$ and compute $V_ω V_{ω^{-1}}$ Corollary: $\DFT_ω$ is invertible. ### Definitions 1. Convolution $f * g = fg \mod (x^n - 1)$ 2. Pointwise product $$(a_0, …, a_{n - 1})Ā·(b_0, …, b_{n - 1}) = (a_0 b_0, …, a_{n - 1} b_{n - 1}) ∈ š”½^n → š”½_{ **if** $n = 1$ **then**
**return** $f(X)$
**end**
Write $f(X)$ as the sum of two polynomials with equal degree
$f(X) = g(X) + X^{n/2} h(X)$
Let $\mathbf{g}, \mathbf{h}$ be the vector representations of $g(X), h(X)$

$\mathbf{r} = \mathbf{g} + \mathbf{h}$
$\mathbf{s} = (\mathbf{g} - \mathbf{h})Ā·(ω^0, …, ω^{n/2 - 1})$
Let $r(X), s(X)$ be the polynomials represented by the vectors $\mathbf{r}, \mathbf{s}$

Compute $(r(ω^0), …, r(ω^{n/2})) = \textrm{DFT}_{ω^2}(n/2, r(X))$
Compute $(s(ω^0), …, s(ω^{n/2})) = \textrm{DFT}_{ω^2}(n/2, s(X))$

**return** $(r(ω^0), s(ω^0), r(ω^2), s(ω^2), …, r(ω^{n/2}), s(ω^{n/2}))$
end Sage code: ```python def calc_dft(ω_powers, f): m = len(f) if m == 1: return f g, h = vector(f[:m/2]), vector(f[m/2:]) r = g + h s = dot(g - h, ω_powers) ω_powers = vector(ω_i for ω_i in ω_powers[::2]) rT = calc_dft(ω_powers, r) sT = calc_dft(ω_powers, s) return list(alternate(rT, sT)) ``` ### Even Values $$ \begin{align} r(X) &= g(X) + h(X) \\ \\ f(ω^{2i}) &= g(ω^{2i}) + (ω^{2i})^{n/2} h(ω^{2i}) \\ &= g(ω^{2i}) + h(ω^{2i}) \\ &= (g + h)(ω^{2i}) \\ \end{align} $$ So then we can now compute $DFT_ω(f)_{k=2i} = DFT_{ω^2}(r)$ for the even powers of $f(ω^{2i})$. ### Odd Values For odd values $k = 2i + 1$ $$ \begin{align} s(X) &= (g(X) - h(X))Ā·(ω^0, …, ω^{n/2 - 1}) \\ \\ f(X) &= a_0 + a_1 X + a_2 X^2 + ⋯ + a_{n - 1} X^{n - 1} \\ &= g(X) + X^{n/2} h(X) \\ f(ω^{2i + 1}) &= g(ω^{2i + 1}) + (ω^{2i + 1})^{n/2} h(ω^{2i + 1}) \\ \end{align} $$ But observe that for any $n$th root of unity $ω^n = 1$ and $ω^{n/2} = -1$ $$ (ω^{2i + 1})^{n/2} = ω^{in} ω^{n/2} = ω^{n/2} = -1 $$ $$ \begin{align} ⇒ f(ω^{2i + 1}) &= g(ω^{2i + 1}) - h(ω^{2i + 1}) \\ &= (g - h)(ω^{2i + 1}) \end{align} $$ Let $\mathbf{s} = (\mathbf{g} - \mathbf{h})Ā·(ω^0, …, ω^{n/2 - 1})$ be the representation for $s(X)$. Then we can see that $s(ω^{2i}) = (g - h)(ω^{2i + 1})$ as desired. So then we can now compute $DFT_ω(f)_{k=2i + 1} = DFT_{ω^2}(s)$ for the odd powers of $f(ω^{2i + 1})$. ## Example Let $n = 8$ $$ \begin{align} f(X) &= (a_0 + a_1 X + a_2 X^2 + a_3 X^3) + (a_4 X^4 + a_5 X^5 + a_6 X^6 + a_7 X^7) \\ &= (a_0 + a_1 X + a_2 X^2 + a_3 X^3) + X^4 (a_4 + a_5 X + a_6 X^2 + a_7 X^3) \\ &= g(X) + X^{n/2} h(X) \\ g(X) &= a_0 + a_1 X + a_2 X^2 + a_3 X^3 \\ h(X) &= a_4 + a_5 X + a_6 X^2 + a_7 X^3 \\ \end{align} $$ Now vectorize $g(X), h(X)$ $$ \begin{align} \mathbf{g} &= (a_0, a_1, a_2, a_3) \\ \mathbf{h} &= (a_4, a_5, a_6, a_7) \\ \end{align} $$ Compute reduced polynomials in vector form $$ \begin{align} \mathbf{r} &= \mathbf{g} + \mathbf{h} \\ &= (a_0 + a_4, a_1 + a_5, a_2 + a_6, a_3 + a_7) \\ \mathbf{s} &= (\mathbf{g} - \mathbf{h})Ā·(1, ω, ω^2, ω^3) \\ &= (a_0 - a_4, a_1 - a_5, a_2 - a_6, a_3 - a_7)Ā·(1, ω, ω^2, ω^3) \\ &= (a_0 - a_4, ω (a_1 - a_5), ω^2 (a_2 - a_6), ω^3 (a_3 - a_7)) \\ \end{align} $$ Convert them to polynomials from the vectors. We also expand them out below for completeness. $$ \begin{align} r(X) &= r_0 + r_1 X + r_2 X^2 + r_3 X^3 \\ &= (a_0 + a_4) + (a_1 + a_5) X + (a_2 + a_6) X^2 + (a_3 + a_7) X^3 \\ s(X) &= s_0 + s_1 X + s_2 X^2 + s_3 X^3 \\ &= (a_0 - a_4) + ω (a_1 - a_5) X + ω^2 (a_2 - a_6) X^2 + ω^3 (a_3 - a_7) X^3 \\ \end{align} $$ Compute $$ \textrm{DFT}_{ω^2}(4, r(X)), \textrm{DFT}_{ω^2}(4, s(X)) $$ The values returned will be $$ (r(1), s(1), r(ω^2), s(ω^2), r(ω^4), s(ω^4), r(ω^6), s(ω^6)) = (f(1), f(ω), f(ω^2), f(ω^3), f(ω^4), f(ω^5), f(ω^6), f(ω^7)) $$ Which is the output we return. ### Comparing Evaluations for $f(X)$ and $r(X), s(X)$ We can see the evaluations are correct by substituting in $ω^i$. We expect that $s(X)$ on the domain $(1, ω^2, ω^4, ω^6)$ produces the values $(f(1), f(ω^2), f(ω^4), f(ω^6))$, while $r(X)$ on the same domain produces $(f(ω), f(ω^3), f(ω^5), f(ω^7))$. #### Even Values Let $k = 2i$, be an even number. Then note that $k$ is a multiple of 2, so $4k$ is a multiple of $n ⇒ ω^{4k} = 1$, $$ \begin{align} r(X) &= (a_0 + a_4) + (a_1 + a_5) X + (a_2 + a_6) X^2 + (a_3 + a_7) X^3 \\ r(ω^{2i}) &= (a_0 + a_4) + (a_1 + a_5) ω^{2i} + (a_2 + a_6) ω^{4i} + (a_3 + a_7) ω^{6i} \\ f(ω^k) &= (a_0 + a_1 ω^k + a_2 ω^{2k} + a_3 ω^{3k}) + ω^{4k} (a_4 + a_5 ω^k + a_6 ω^{2k} + a_7 ω^{3k}) \\ &= (a_0 + a_1 ω^k + a_2 ω^{2k} + a_3 ω^{3k}) + (a_4 + a_5 ω^k + a_6 ω^{2k} + a_7 ω^{3k}) \\ &= (a_0 + a_4) + (a_1 + a_5) ω^k + (a_2 + a_6) ω^{2k} + (a_3 + a_7) ω^{3k} \\ &= f(ω^{2i}) \\ &= (a_0 + a_4) + (a_1 + a_5) ω^{2i} + (a_2 + a_6) ω^{4i} + (a_3 + a_7) ω^{6i} \\ &= r(ω^{2i}) \end{align} $$ #### Odd Values For $k = 2i + 1$ odd, we have a similar relation where $4k = 8i + 4$, so $ω^{4k} = ω^4$. But observe that $ω^4 = -1$. $$ \begin{align} s(X) &= (a_0 - a_4) + ω (a_1 - a_5) X + ω^2 (a_2 - a_6) X^2 + ω^3 (a_3 - a_7) X^3 \\ s(ω^{2i}) &= (a_0 - a_4) + (a_1 - a_5) ω^{2i + 1} + (a_2 - a_6) ω^{4i + 2} + (a_3 - a_7) ω^{6i + 3} \\ f(ω^k) &= (a_0 + a_1 ω^k + a_2 ω^{2k} + a_3 ω^{3k}) + ω^{4k} (a_4 + a_5 ω^k + a_6 ω^{2k} + a_7 ω^{3k}) \\ &= (a_0 + a_1 ω^k + a_2 ω^{2k} + a_3 ω^{3k}) - (a_4 + a_5 ω^k + a_6 ω^{2k} + a_7 ω^{3k}) \\ &= f(ω^{2i + 1}) \\ &= (a_0 + a_1 ω^{2i + 1} + a_2 ω^{4i + 2} + a_3 ω^{6i + 3}) - (a_4 + a_5 ω^{2i + 1} + a_6 ω^{4i + 2} + a_7 ω^{6i + 3}) \\ &= (a_0 - a_4) + (a_1 - a_5) ω^{2i + 1} + (a_2 - a_6) ω^{4i + 2} + (a_3 - a_7) ω^{6i + 3} \\ &= s(ω^{2i}) \end{align} $$