diff --git a/fft-notes.bib b/fft-notes.bib new file mode 100644 index 0000000..daa1b11 --- /dev/null +++ b/fft-notes.bib @@ -0,0 +1,20 @@ +@misc{gstrang, + title = {Linear Algebra and Its Applications, by Gilbert Strang (chapter 3.5)}, + howpublished = "\url{https://archive.org/details/linearalgebrait00stra}", +} +@misc{tpornin, + title = {{Thomas Pornin} mathoverflow answer}, + howpublished = "\url{https://crypto.stackexchange.com/a/63616}", +} +@misc{rfateman, + title = {notes by {Prof. R. Fateman}}, + howpublished = "\url{https://www.csee.umbc.edu/~phatak/691a/fft-lnotes/fftnotes.pdf}", +} +@misc{fftrs, + title = {fft-rs}, + howpublished = "\url{https://github.com/arnaucube/fft-rs}", +} +@misc{fftsage, + title = {fft-sage}, + howpublished = "\url{https://github.com/arnaucube/math/blob/master/fft.sage}", +} diff --git a/fft-notes.pdf b/fft-notes.pdf new file mode 100644 index 0000000..cdc0eff Binary files /dev/null and b/fft-notes.pdf differ diff --git a/fft-notes.tex b/fft-notes.tex new file mode 100644 index 0000000..6cddbc5 --- /dev/null +++ b/fft-notes.tex @@ -0,0 +1,200 @@ +\documentclass{article} +\usepackage[utf8]{inputenc} +\usepackage{amsfonts} +\usepackage{amsthm} +\usepackage{amsmath} +\usepackage{amssymb} +\usepackage{enumerate} +\usepackage{hyperref} +\hypersetup{ + colorlinks, + citecolor=black, + filecolor=black, + linkcolor=black, + urlcolor=blue +} + +\theoremstyle{definition} +\newtheorem{definition}{Def}[section] +\newtheorem{theorem}[definition]{Thm} +\newtheorem{innersolution}{} +\newenvironment{solution}[1] +{\renewcommand\theinnersolution{#1}\innersolution} +{\endinnersolution} + + +\title{FFT: Fast Fourier Transform} +\author{arnaucube} +\date{August 2022} + +\begin{document} + +\maketitle + +\begin{abstract} + Usually while reading papers and books I take handwritten notes, this document contains some of them re-written to $LaTeX$. + + The notes are not complete, don't include all the steps neither all the proofs. I use these notes to revisit the concepts after some time of reading the topic. + + This document are notes done while reading about the topic from \cite{gstrang}, \cite{tpornin}, \cite{rfateman}. +\end{abstract} + +\tableofcontents + +\section{Discrete \& Fast Fourier Transform} + +\subsection{Discrete Fourier Transform (DFT)} + +Continuous: + +$$ +x(f) = \int_{-\infty}^{\infty} x(t) e^{-2 \pi f t} dt +$$ + +Discrete: +The $k^{th}$ frequency, evaluating at $n$ of $N$ samples. +$$ +\hat{f_k} = \sum_{n=0}^{n-1} f_n e^{\frac{-j \pi kn}{N}} +$$ + +where we can group under $b_n = \frac{\pi kn}{N}$. The previous expression can be expanded into: +$$ +x_k = x_0 e^{-b_0 j} + x_1 e^{-b_1 j} + ... + x_n e^{-b_n j} +$$ + +By the \emph{Euler's formula} we have $e^{jx} = cos(x) + j\cdot sin(x)$, and using it in the previous $x_k$, we obtain + +$$ +x_k = x_0 [cos(-b_0) + j \cdot sin(-b_0)] + \ldots +$$ + +Using $\hat{f_k}$ we obtained +$$ +\{f_0, f_1, \ldots, f_N\} \xrightarrow{DFT} \{ \hat{f_0}, \hat{f_1}, \ldots, \hat{f_N} \} +$$ + +To reverse the $\hat{f_k}$ back to $f_k$: +$$ +f_k = \left( \sum_{n=0}^{n-1} \hat{f_n} e^{\frac{-j \pi kn}{N}} \right) \cdot \frac{1}{N} +$$ + + +$$ +DFT = +\begin{pmatrix} +\hat{f_0}\\ +\hat{f_1}\\ +\hat{f_2}\\ +\vdots\\ +\hat{f_n}\\ +\end{pmatrix}= +\begin{pmatrix} +1 & 1 & 1 & \ldots & 1 \\ +1 & w_n & w_n^2 & \ldots & w_n^{N-1} \\ +1 & w_n^2 & w_n^4 & \ldots & w_n^{2(N-1)} \\ +\vdots & \vdots & \vdots & & \vdots\\ +1 & w_n^{n-1} & w_n^{2(n-1)} & \ldots & w_n^{(N-1)^2} \\ +\end{pmatrix} +\begin{pmatrix} +f_0 \\ f_1 \\ f_2 \\ \vdots \\ f_n +\end{pmatrix} +$$ + +\subsection{Fast Fourier Transform (FFT)} +While DFT is $O(n)$, FFT is $O(n \space log(n))$ + +Here you can find a simple implementation of the these concepts in Rust: \href{https://github.com/arnaucube/fft-rs}{arnaucube/fft-rs} \cite{fftrs} + + +\section{FFT over finite fields, roots of unity, and polynomial multiplication} + +FFT is very useful when working with polynomials. [TODO poly multiplication] + +An implementation of the FFT over finite fields using the Vandermonde matrix approach can be found at \cite{fftsage}. + +\subsection{Intro} +Let $A(x)$ be a polynomial of degree $n-1$, + +$$ +A(x) = a_0 + a_1 \cdot x + a_2 \cdot x^2 + \cdots + a_{n-1} \cdot x^{n-1} = \sum_{i=0}^{n-1} a_i \cdot x^i +$$ + +We can represent $A(x)$ in its evaluation form, + +$$ +(x_0, A(x_0)), (x_1, A(x_1)), \cdots, (x_{n-1}, A(x_{n-1})) = (x_i, A(x_i)) +$$ + + +We can evaluate A(x) at n given points $(x_0, x_1, ..., x_{n-1}$): + +$$ +\begin{pmatrix} +A(x_0)\\ A(x_1)\\ A(x_2)\\ \vdots\\ A(x_{n-1}) +\end{pmatrix}= +\begin{pmatrix} +x_0^0 & x_0^1 & x_0^2 & \ldots & x_0^{n-1} \\ +x_1^0 & x_1^1 & x_1^2 & \ldots & x_1^{n-1} \\ +x_2^0 & x_2^1 & x_2^2 & \ldots & x_2^{n-1} \\ +\vdots & \vdots & \vdots & & \vdots\\ +x_{n-1}^0 & x_{n-1}^1 & x_{n-1}^2 & \ldots & x_{n-1}^{n-1} \\ +\end{pmatrix} +\begin{pmatrix} +a_0 \\ a_1 \\ a_2 \\ \vdots \\ a_{n-1} +\end{pmatrix} +$$ + +This is known by the Vandermonde matrix. + +But this will not be too efficient. Instead of random $x_i$ values, we use \emph{roots of unity}, where $\omega_n^n = 1$. We denote $\omega$ as a primitive $n^{th}$ root of unity: + +$$ +\begin{pmatrix} +A(1)\\ A(\omega)\\ A(\omega^2)\\ \vdots\\ A(\omega^{n-1}) +\end{pmatrix}= +\begin{pmatrix} +1 & 1 & 1 & \ldots & 1 \\ +1 & \omega & \omega^2 & \ldots & \omega^{n-1} \\ +1 & \omega^2 & \omega^4 & \ldots & \omega^{2(n-1)} \\ +\vdots & \vdots & \vdots & & \vdots\\ +1 & \omega^{n-1} & \omega^{2(n-1)} & \ldots & \omega^{(n-1)^2} \\ +\end{pmatrix} +\begin{pmatrix} +a_0 \\ a_1 \\ a_2 \\ \vdots \\ a_{n-1} +\end{pmatrix} +$$ + +Which we can see as + +$$ +\hat{A} = F_n \cdot A +$$ + +This matches our system of equations: + +\begin{itemize} + \item at $x=0$, $a_0 + a_1 + \cdots + a_{n-1} = A_0 = A(1)$ + \item at $x=1$, $a_0 \cdot 1 + a_1 \cdot \omega + a_2 \cdot \omega^2 + \cdots + a_{n-1} \cdot \omega^{n-1} = A_1 = A(\omega)$ + \item at $x=2$, $a_0 \cdot 1 + a_1 \cdot \omega^2 + a_2 \cdot \omega^4 + \cdots + a_{n-1} \cdot \omega^{2(n-1)} = A_2 = A(\omega^2)$ + \item $\cdots$ + \item at $x=n-1$, $a_0 \cdot 1 + a_1 \cdot \omega^{n-1} + a_2 \cdot \omega^{2(n-1)} + \cdots + a_{n-1} \cdot \omega^{(n-1)(n-1)} = A_2 = A(\omega^{n-1})$ +\end{itemize} + +We denote the $F_n$ as the Fourier matrix, with $j$ rows and $k$ columns, where each entry can be expressed as $F_{jk} = \omega^{jk}$. + +To find the $a_i$ values, we use the inverted $F_n = F_n^{-1}$ + +\subsection{Roots of unity} +todo + +\subsection{FFT over finite fields} +todo + +\subsection{Polynomial multiplication with FFT} +todo + + +\bibliography{fft-notes.bib} +\bibliographystyle{unsrt} + +\end{document}