---
# System prepended metadata

title: Fast Fourier Transform
tags: [Summer Project, FFT]

---

# Fast Fourier Transform
###### tags: `Summer Project` `FFT`

[TOC]

## Discrete Fourier Transform
The DFT sequence $X_0,X_2,\ldots,X_{N-1}$ of sequence $x_0,x_1,\ldots,x_{N-1}\in\mathbb{C}$ is defined by
$$
X_k=\sum_{n=0}^{N-1}x_ne^{-i2\pi k\frac{n}{N}},\quad k=0,1,\ldots,N-1
$$
Let $w=e^{-i\frac{2\pi}{N}}$, then
$$
X=\begin{pmatrix}
X_0\\X_1\\\vdots\\X_{N-1}
\end{pmatrix}=
\begin{pmatrix}
1&1&\dots&1\\
1&w&\dots&w^{N-1}\\
\vdots&\vdots&\ddots&\vdots\\
1&w^{N-1}&\dots&w^{(N-1)(N-1)}
\end{pmatrix}
\begin{pmatrix}
x_0\\x_1\\\vdots\\x_{N-1}
\end{pmatrix}
=Wx=\mathcal F_N(x)
$$
where $W$ is called DFT matrix, $\mathcal F_N$ is called $N$-points Fourier transform.

### Inverse Discrete Fourier Transform
$$
x_n=\frac{1}{N}\sum_{k=0}^{N-1}X_ke^{i2\pi k\frac{n}{N}},\quad n=0,1,\ldots,N-1
$$

Remark that $W$ is invertible and $W^{-1}=\frac{1}{N}W^\star$, thus $x=\frac{1}{N}W^\star X$.

### Two Dimension and More
Let $x=\{x_{ij}\mid 0\leq i<N,0\leq j<M\}$ then the DFT of $x$ is defined by
$$
X_{uv}=\sum_{n=0}^{N-1}\sum_{m=0}^{M-1}x_{nm}e^{-i2\pi\left(u\frac{n}{N}+v\frac{m}{M}\right)},\quad 0\leq u<N,0\leq v<M
$$
and IDFT
$$
x_{nm}=\frac{1}{NM}\sum_{u=0}^{N-1}\sum_{v=0}^{M-1}X_{uv}e^{i2\pi\left(n\frac{u}{N}+m\frac{v}{M}\right)},\quad 0\leq n<N,0\leq m<M
$$
For higher dimension, let $I=\{(n_1,n_2,\ldots,n_M)\mid0\leq n_i<N_i\}$, we define
$$
X_{k}=\sum_{n\in I}x_ne^{-i2\pi k\cdot\frac{n}{N}},\quad k\in I
$$

### Example
- Let $x_n=c$ for $n=0,1,\ldots,N-1$, then 
$$
X_k=
\begin{cases}
cN&,k=0\\
0&,k\neq 0
\end{cases}
$$
- Let $y_n=cx_n+dz_n$ for $n=0,1,\ldots,N-1$, then
$$
\begin{split}
Y_k=&\sum_{n=0}^{N-1}y_nW_N^{kn}\\
=&\sum_{n=0}^{N-1}(cx_n+dz_n)W_N^{kn}\\
=&cX_k+dZ_k
\end{split}
$$
- Let $y_n=x_{n-c}$ for $n=0,1,\ldots,N-1$ and $c\in\mathbb N$, then
$$
\begin{split}
Y_k=&\sum_{n=0}^{N-1}y_nW_N^{kn}=\sum_{n=0}^{N-1}x_{n-c}W_N^{kn}=\sum_{n=-c}^{N-c-1}x_nW_N^{k(n+c)}\\
=&W_N^{kc}\sum_{n=0}^{N-1}x_nW_N^{kn}=W_N^{kc}X_k
\end{split}
$$


## Time-Frequency Perspective
Given a function $x_c:\mathbb R\to\mathbb C$, the *sampling* of $x_c$ is 
$$
x_n=x_c(nT),\quad n=0,1,\ldots,L-1
$$
where
- $T$ is called the *sampling period*
    - $F_s=\frac{1}{T}$ is called *sampling rate*
    - $\Omega_s=\frac{2\pi}{T}$ is called *sampling frequency*
- $L$ is called the *length* of signal

### Example
Let $x_c(t)=\cos(2\pi ft)$, which is periodic with period $\frac{1}{f}$, then the DFT of $x_n$ is
$$
\begin{split}
X_k=&\sum_{n=0}^{L-1}x_ne^{-i2\pi k\frac{n}{L}}\\
=&\sum_{n=0}^{L-1}\cos(2\pi fnT)e^{-i2\pi fTn}\quad\mbox{when}\quad k=fTL=\frac{f}{F_s}L\\
=&\sum_{n=0}^{L-1}\frac{e^{i2\pi fnT}+e^{-i2\pi fnT}}{2}e^{-i2\pi fTn}\\
=&\frac{L}{2}+\frac{1}{2}\sum_{n=0}^{L-1}(e^{ir})^n\quad\mbox{where}\quad r=-4\pi fT\\
=&\frac{L}{2}+\frac{1}{2}\left(\frac{1-e^{irL}}{1-e^{ir}}\right)
\end{split}
$$
which is a peak on real line intuitively when $k\approx\frac{f}{F_s}L$. Suppose it is not a peak, that means
$$
-L=\frac{1-e^{irL}}{1-e^{ir}}\\
-L+L\cos(r)+iL\sin(r)=L-Le^{ir}=1-e^{irL}=1-\cos(rL)-i\sin(rL)
$$
thus
$$
L\cos(r)+\cos(rL)=L+1,\quad \cos(r)=\cos(rL)=1
$$
only when
$$
-4\pi fT=r=2\pi n,\quad n\in\mathbb Z\\2\frac{f}{F_s}=2fT=-n
$$
Hence, we need sampling rate $F_s> 2f$ to avoid this, which is called *reconstruction* condition.

Notice that when $k=(1-\frac{f}{F_s})L$,
$$
\begin{split}
X_k=&\sum_{n=0}^{L-1}\cos(2\pi fnT)e^{-i2\pi (1-fT)n}\\
=&\sum_{n=0}^{L-1}\frac{e^{i2\pi fnT}+e^{-i2\pi fnT}}{2}e^{i2\pi fTn}\\
=&\frac{L}{2}+\frac{1}{2}\sum_{n=0}^{L-1}e^{irn}\quad\mbox{where}\quad r=4\pi fT\\
=&\frac{L}{2}+\frac{1}{2}\left(\frac{1-e^{irL}}{1-e^{ir}}\right)
\end{split}
$$
which implies $X_k$ is symmetrical and it is called *double-sided amplitude spectrum*. If we change
$$
Y_k=\begin{cases}
X_k,&\quad k=0\vee k=L/2+1\\
2X_k,&\quad k=1,2,\ldots,\lfloor L/2\rfloor
\end{cases}
$$
then $Y_k$ is called *single-sided amplitude spectrum*.

```matlab
Fs = 1000;
T = 1/Fs;  
L = 300;
t = (0:L-1)*T;
xc = @(x) 0.7*sin(2*pi*50*x) + sin(2*pi*120*x) + rand(size(x));
X = xc(t);
plot(1000*t,X)
xlabel('t (milliseconds)')
ylabel('X(t)')
```
![](https://i.imgur.com/YqGwp7e.png)
```matlab
Y = fft(X);
P2 = abs(Y/L);
f = Fs*(0:L-1)/L; % k=f/Fs*L, f=Fs*f/L
plot(f,P2) 
xlabel('f (Hz)')
ylabel('|P2(f)|')
```
![](https://i.imgur.com/vOf7hCY.png)
```matlab
P1 = P2(1:L/2+1); % L is even
P1(2:end-1) = 2*P1(2:end-1); % L is even
f = Fs*(0:(L/2))/L;
plot(f,P1) 
xlabel('f (Hz)')
ylabel('|P1(f)|')
```
![](https://i.imgur.com/8t3V9bw.png)

### Zero Padding
Given sequence $x'_n$ with length $N$, padding zero with length $M$ is
$$
x_n=
\begin{cases}
x'_n,&0\leq n<N\\
0,&N\leq n<N+M
\end{cases}
$$
then the DFT is
$$
X_k=\sum_{n=0}^{N+M-1}x_nW_{N+M}^{kn}=\sum_{n=0}^{N-1}x_nW_{N+M}^{kn}
$$
Similar to above, the peak appears at $k=fT(N+M)$ and $k=(1-fT)(N+M)$. This will

- increase the resolution of frequency
- extend the length so that it performs FFT fast

| |Original | Padding | 
|-|-------- | -------- | 
|$x_n$ |![](https://i.imgur.com/mMoh9V8.png)| ![](https://i.imgur.com/Vmi77Xh.png)| 
| $\mid P_1(f)\mid$ |![](https://i.imgur.com/w1IaYE3.png)|![](https://i.imgur.com/ATRldKL.png)|

## Fast Fourier Transform
Assume $N=2^k,k\in\mathbb N\cup\{0\}$. Let $W_N=e^{-i\frac{2\pi}{N}}$
$$
\begin{split}
X_k=&\sum_{n=0}^{N-1}x_nW_N^{kn}=\sum_{n=0}^{N/2-1}x_{2n}W_N^{2nk}+\sum_{n=0}^{N/2-1}x_{2n+1}W_N^{(2n+1)k}\\
=&\sum_{n=0}^{N/2-1}x_{2n}W_N^{2nk}+W_N^k\sum_{n=0}^{N/2-1}x_{2n+1}W_N^{2nk}\\
=&\sum_{n=0}^{N/2-1}x_{2n}W_{N/2}^{nk}+W_N^k\sum_{n=0}^{N/2-1}x_{2n+1}W_{N/2}^{nk}
\end{split}
$$
which is calculated by the DFT of sequence $x_0,x_2,\ldots,x_{N-2}$ and $x_1,x_3,\ldots,x_N-1$ with length $N/2$. Thus we do *Divide and Conquer*.

Note that if $N/2\leq k<N$, it is not defined in sequence of length $N/2$, then with

- $W_{N/2}^{n(k+N/2)}=(e^{-i\frac{2\pi}{N/2}})^{n(k+N/2)}=(e^{-i\frac{2\pi}{N/2}})^{nk}e^{-i2\pi n}=(e^{-i\frac{2\pi}{N/2}})^{nk}=W_{N/2}^{nk}$
- $W_N^{k+N/2}=(e^{-i\frac{2\pi}{N}})^{k+N/2}=e^{-i\frac{2\pi}{N}k}e^{-i\pi}=-e^{-i\frac{2\pi}{N}k}=-W_N^k$

thus

$$
\begin{split}
X_{k+N/2}=&\sum_{n=0}^{N/2-1}x_{2n}W_{N/2}^{n(k+N/2)}+W_N^{k+N/2}\sum_{n=0}^{N/2-1}x_{2n+1}W_{N/2}^{n(k+N/2)}\\
=&\sum_{n=0}^{N/2-1}x_{2n}W_{N/2}^{nk}-W_N^{k}\sum_{n=0}^{N/2-1}x_{2n+1}W_{N/2}^{nk}
\end{split}
$$

this method is called *radix-2 DIT Cooley–Tukey Algorithm*

### Pseudo Code
```matlab
funtion fft(N, x = x[0],x[1],...,x[N-1]): // N=2^k
    if N == 1:
        return x
    Xe = fft(N/2, (x[0],x[2],...,x[N-2])
    Xo = fft(N/2, (x[1],x[3],...,x[N-1])
    w = exp(-2i * pi / N)
    for k from 0 to N/2 - 1:
        X[k] = Xe[k] + w^k * Xo[k]
        X[k + N/2] = Xe[k] - w^k * Xo[k]
    return X
```

and to perform IFFT, it remains to change `w=exp(2i*pi/N)` and lastly to be divided by `N`.

### Time Complexity
$$
O(\mathcal F_1)=O(1)\\
\begin{split}
O(\mathcal F_N)=&O(\mathcal F_{\frac{N}{2}}+\mathcal F_{\frac{N}{2}}+N)=O(2\mathcal F_{\frac{N}{2}}+N)\\
=&O(2(2\mathcal F_{\frac{N}{4}}+\frac{N}{2})+N)=O(4\mathcal F_{\frac{N}{4}}+2N)\\
&\vdots\\
=&O(2^k\mathcal F_1+kN)=O(N+N\log_2N)\\
=&O(N\log N)
\end{split}
$$

### Matlab Implementation
```matlab
function y = yafft(x)
    N = length(x);
    if N == 1
        y = x;
        return
    end
    
    xe = zeros(1, N/2);
    xo = zeros(1, N/2);
    for k = 1:N/2
        xe(k) = x(2*k-1);
        xo(k) = x(2*k);
    end
    
    ye = yafft(xe);
    yo = yafft(xo);
    w = exp(-2i*pi/N);
    
    y = zeros(1, N);
    for k = 1:N/2
        y(k) = ye(k) + w^(k-1) * yo(k);
        y(k+N/2) = ye(k) - w^(k-1) * yo(k);
    end
end
```

## General Cooley–Tukey Algorithm
Let $N=M\cdot L$ where $M\neq 1\neq L$, then
$$
\begin{split}
X_k=&\sum_{n=0}^{N-1}x_nW_N^{kn}
=\sum_{l=0}^{L-1}\sum_{m=0}^{M-1}x_{mL+l}W_N^{k(mL+l)}\\
=&\sum_{l=0}^{L-1}W_N^{kl}\sum_{m=0}^{M-1}x_{mL+l}W_N^{kmL}=\sum_{l=0}^{L-1}W_N^{kl}\sum_{m=0}^{M-1}x_{mL+l}W_M^{km}
\end{split}
$$
which splits the original problem into $L$ FFT problems of length $M$. Similarly, if $k\geq M$, we have

- $W_M^{(aM+k)m}=W_M^{aMm}W^{km}=e^{-i2\pi lm\frac{M}{M}}W_M^{km}=W_M^{km}$

thus
$$
\begin{split}
X_{aM+k}=&\sum_{l=0}^{L-1}W_N^{(aM+k)l}\sum_{m=0}^{M-1}x_{mL+l}W_M^{(aM+k)m}\\
=&\sum_{l=0}^{L-1}W_N^{(aM+k)l}\sum_{m=0}^{M-1}x_{mL+l}W_M^{km}
\end{split}
$$

### Pseudo Code
```matlab
function fft(N, x = x[0],x[1],...,x[N-1]): \\ N=M*L
    for l from 0 to L-1:
        for m from 0 to M-1:
            z[l][m] = x[m*L+l]
    for l from 0 to L-1:
        Z[l] = fft(M, z[l][:])
    w = exp(-2i*pi/N)
    for a from 0 to L-1:
        for k from 0 to M-1:
            X[a*M+k] = 0
            for l from 0 to L-1:
                X[a*M+k] += w^((a*M+k)*l) * Z[l][k]
    return X
```

### Time Complexity
$$
O(\mathcal F_N)=O(LM+L\mathcal F_M+L^2M)=O(NL+L\mathcal F_{\frac{N}{L}})
$$

## Rader's Algorithm
Let $N>2$ be a prime, then $\mathbb Z_N^\times$ is a cyclic group, and there exists primitive root $g$. That is, $f_g:\mathbb Z_{N-1}\to\mathbb Z_{N}\setminus\{0\}$ by
$$
f_g(n)=g^n\pmod N
$$
is a bijection. Recall we have
$$
X_0=\sum_{n=0}^{N-1}x_n\\
X_k=x_0+\sum_{n=1}^{N-1}x_nW_N^{kn},\quad k=1,2,\ldots,N-1
$$
and we change the order
$$
X_k=x_0+\sum_{q=0}^{N-2}x_{g^q}W_N^{kg^q},\quad k=1,2,\ldots,N-1\\
X_{g^{-p}}=x_0+\sum_{q=0}^{N-2}x_{g^q}W_N^{g^{q-p}},\quad p=0,1,\ldots,N-2
$$
Now let $a_k=x_{g^{k}},b_k=W_N^{g^{-k}}$, then
$$
X_{g^{-p}}-x_0=\sum_{q=0}^{N-2}a_{q}b_{p-q},\quad p=0,1,\ldots,N-2
$$
is called the *cyclic convolution* $b\star a$ of $a$ and $b$.

### Cyclic Convolution
Calculating the cyclic convolution of two sequence $a_k$ and $b_k$ is another problem that can be solved by FFT.

:::info
**Property.**
Let $a=(a_0,\ldots,a_{N-1}),b=(b_0,\ldots,b_{N-1})$, then
$$
\mathcal F_N(a\star b)=\mathcal F_N(a)\cdot\mathcal F_N(b)
$$
**Proof.**
Let $c=(c_0,\ldots,c_{N-1})$ where $c_n=\sum_{k=0}^{N-1}b_ka_{n-k}$ and $A=\mathcal F_N(a),B=\mathcal F_N(b)$, then
$$
\begin{split}
c_n=&\sum_{k=0}^{N-1}b_ka_{n-k}\\
=&\sum_{k=0}^{N-1}b_k\left(\frac{1}{N}\sum_{m=0}^{N-1}A_{m}W_N^{-m(n-k)}\right)\\
=&\frac{1}{N}\sum_{k=0}^{N-1}b_k\left(\sum_{m=0}^{N-1}A_{m}W_N^{-mn}\right)W_N^{mk}\\
=&\frac{1}{N}\sum_{m=0}^{N-1}A_{m}\left(\sum_{k=0}^{N-1}b_kW_N^{mk}\right)W_N^{-mn}\\
=&\frac{1}{N}\sum_{m=0}^{N-1}A_{m}B_mW_N^{-mn}
\end{split}
$$
:::
Also, with proper way of extending the length, we can have the same convolution result.
:::info
**Property.**
Let $a,b\in\mathbb {C}^N$,, $a',b',c'\in\mathbb{C}^M$ where $M\geq 2N-1$ and

- $a'_k=\begin{cases}a_k,&\quad k=0,1,\ldots,N-1\\0,&\quad k=N,\ldots,M-1\end{cases}$
- $b'_k=\begin{cases}b_k,&\quad k=0,1,\ldots,N-1\\ 0,&\quad k=N,\ldots,M-N\\b_{k+N-M},&\quad k=M-N+1,\ldots,M-1\end{cases}$

namely,

$$
(a'\star b')^T=
\begin{pmatrix}
\begin{matrix}
a_0&0&\dots&0\\
a_1&a_0&\dots&0\\
\vdots&\vdots&\ddots&\vdots\\
a_{N-1}&a_{N-2}&\dots&a_0
\end{matrix}&\dots&
\begin{matrix}
a_{N-1}&a_{N-2}&\dots&a_1\\
0&a_{N-1}&\dots&a_2\\
\vdots&\vdots&\ddots&\vdots\\
0&0&\dots&a_{N-1}
\end{matrix}\\
\vdots&&\vdots
\end{pmatrix}
\begin{pmatrix}
b_0\\b_1\\\vdots\\b_{N-1}\\0\\\vdots\\0\\b_1\\\vdots\\b_{N-1}
\end{pmatrix}
$$

Then
$$
a\star b=a'\star b'\mid_{n=0,1,\ldots,N-1}
$$
namely, the first $N$ items of $a'\star b'$.

**Proof.**
Let $c=a\star b$, $c'=a'\star b'$, then for $0\leq k< N$,
$$
\begin{split}
c'_k=&\sum_{n=0}^{M-1}b'_na'_{k-n}\\
=&\sum_{n=0}^{k}b'_na'_{k-n}+\sum_{n=k+1}^{M-N+k}b'_na'_{k-n}+\sum_{n=M-N+k+1}^{M-1}b'_na'_{k-n}\\
=&\sum_{n=0}^{k}b_na_{k-n}+\sum_{n=M-N+k+1}^{M-1}b'_na'_{k-n}\\
=&\sum_{n=0}^{k}b_na_{k-n}+\sum_{n=k+1}^{N-1}b'_{M-N+n}a'_{M-N+k-n}\\
=&\sum_{n=0}^{k}b_na_{k-n}+\sum_{n=k+1}^{N-1}b_na_{k-n}=\sum_{n=0}^{N-1}b_na_{k-n}=c_k
\end{split}
$$
:::

```matlab
function cyclic_convolution(N, a, b):
    M = minimum 2-power at least 2N-1
    for k from 0 to N-1:
        A[k] = a[k], B[k] = b[k]
    for k from N to M-N:
        A[k] = 0, B[k] = 0
    for k from M-N+1 to M-1:
        A[k] = 0, B[k] = b[k+N-M]
    A2 = fft(M, A)
    B2 = fft(M, B)
    return ifft(N, A2.*B2)[0:N-1]
```

and the time complexity of cyclic convolution is
$$
O(M+3M\log M)=O(N\log N)
$$

### Pseudo Code
The naive way to find the primitive root is by checking all $g$ and all powers, but it can be speed up due to the proterty.
:::info
**Property.**
Let $N$ be prime, $p_1,p_2,\ldots,p_k$ be prime factors of $N-1$ then $g$ is primitive root of $N$ if and only if
$$
g^\frac{N-1}{p_i}\neq 1\pmod N,\quad i=1,2,\ldots,k
$$

**Proof.**
Assume $g$ is not a primitive root, then $g^p=1\pmod N$ for some smallest $0<p<N-1$. Since $g^{N-1}=1\pmod N$, we have $p\mid N-1$. And thus $p_i\mid \frac{N-1}{p}$ for some $p_i$, and 
$$
g^{\frac{N-1}{p_i}}=g^{p(N-1)/(pp_i)}=(g^p)^{(N-1)/pp_i}=1\pmod N
$$
:::

```matlab
function primitive_root(N): // N is prime
    S = prime factors of N-1
    n = length(S)
    for g from 2 to n-1:
        for k in S:
            if g^((n-1)/k) mod N == 1:
                break
        else:
            return g
```

```matlab
function fft(N, x = x[0],x[1],...,x[N-1]): // N is prime
    X[0] = sum(x)
    g = primitive_root(N)
    w = exp(-2i * pi / N)
    for k from 0 to N-2:
        a[k] = x[g^k]
        b[k] = w^(g^{-k})
    c = cyclic_convolution(N-1, a, b)
    for p from 0 to N-2:
        X[g^(-p)] = x[0] + c[p]
    return X
```

## Bluestein's algorithm
Note that
$$
nk=\frac{-(k-n)^2}{2}+\frac{k^2}{2}+\frac{n^2}{2}
$$
thus
$$
\begin{split}
X_k=&\sum_{n=0}^{N-1}x_nW_N^{kn}\\
=&\sum_{n=0}^{N-1}x_nW_N^{-(k-n)^2/2}W_N^{k^2/2}W_N^{n^2/2}\\
=&W_N^{k^2/2}\sum_{n=0}^{N-1}\left(x_nW_N^{n^2/2}\right)W_N^{-(k-n)^2/2}\\
=&W_N^{k^2/2}\sum_{n=0}^{N-1}a_nb_{k-n}\quad\mbox{where}\quad a_k=x_kW_N^{k^2/2},b_k=W_N^{-k^2/2}
\end{split}
$$

```matlab
function fft(N, x): // for all N
    w = exp(-2i*pi/N)
    for k from 0 to N-1:
        a[k] = x[k] * w^(k^2/2)
        b[k] = w^(-k^2/2)
    c = cyclic_convolution(N, a, b)
    for k from 0 to N-1:
        X[k] = w^(k^2/2) * c[k]
    return X
```
and the time complexity is
$$
O(\mathcal F_N)=O(N+N\log N+N)=O(N\log N)
$$

## Application

### Multiplication of Polynomial
Let $p(x)=a_0+a_1x+\ldots+a_nx^n,q(x)=b_0+b_1x+\ldots+b_mx^m$, $a_n\neq0\neq b_m$. By interpolation, we find 

$$
(W_{n+m+1}^k,p(W_{n+m+1}^k))\quad\mbox{and}\quad (W_{n+m+1}^k,q(W_{n+m}^k)),\quad k=0,1,\ldots,n+m
$$

then $r(x)$ has points 
$$
(W_{n+m}^k,p(W_{n+m}^k)q(W_{n+m}^k)),\quad k=0,1,\dots,n+m
$$

```matlab
function padding(a, N, v):
    return [a [v]*(N-length(a))]

function mul(a, b): 
    n = length(a), m = length(b)
    A = fft(n+m+1, padding(a, n + m + 1, 0))
    B = fft(n+m+1, padding(b, n + m + 1, 0))
    return ifft(n+m+1, A.*B)
```

### Solution of Circulant matrix
Let $A=(a_{ij})\in\mathbb{M}_{n\times n}(\mathbb{C})$, $A$ is called *circulant* if 
$$
a_{i,j}=a_{i+1,j+1},\quad i,j\in\mathbb{Z}_n
$$
namely, in the form
$$
\begin{pmatrix}
a_0&a_{n-1}&\dots&a_2&a_{1}\\
a_1&a_0&\dots&a_3&a_2\\
\vdots&\vdots&\ddots&\vdots&\vdots\\
a_{n-2}&a_{n-3}&\dots&a_0&a_{n-1}\\
a_{n-1}&a_{n-2}&\dots&a_1&a_0
\end{pmatrix}
$$
To solve linear system 
$$
Ax=b
$$
where $A$ is circulant, by the fact that it is equivalent to solve $a\star x=b$ where $a=(a_0,a_1,\ldots,a_{n-1})$ and $\star$ is the cyclic convolution. Thus
$$
\mathcal F_n(a\star x)=\mathcal F_n(a)\cdot\mathcal F_n(x)=\mathcal F_n(b)
$$
and hence
$$
\mathcal F_n(x)=\frac{\mathcal F_n(b)}{\mathcal F_n(a)},\quad x=\mathcal F_n^{-1}(\frac{\mathcal F_n(b)}{\mathcal F_n(a)})
$$

```matlab
function solve(a, b):
    n = length(a)
    A = fft(n, a)
    B = fft(n, b)
    return ifft(n, A./B)
```

### aplusb
[Kattis](https://open.kattis.com/problems/aplusb)
Given $N$ integers $a_0,a_1,\ldots,a_{N-1}$ in the range $[-S,S]$, find the number of tuple $(i,j,k)$ such that 

- $a_i+a_j=a_k$
- $i,j,k$ are distinct

with some limitations

- $1\leq N\leq 2\times10^5$
- $S=5\times10^4$

First, shift $b_i=a_i+S$ so that they are non-negtive. Let $M=2S$ and
$$
p(x)=c_0+c_1x+\ldots+c_{M}x^{M}
$$ where $c_i$ is the number of $i$ in $\{b_i\}$. Now define
$$
q(x)=p^2(x)=d_0+d_1x+\ldots+d_{2M}x^{2M}
$$
then observe that
$$
\begin{split}
d_{b_k+S}=&|\{(i,j)\mid b_i+b_j=b_k+S\}|\\
=&|\{(i,j)\mid a_i+a_j=a_k\}|
\end{split}
$$
and thus the solution is $\sum_{i=0}^{N-1}d_{b_i+S}$ excluding

1. $a_i+a_j=a_k$, but $a_i=0$ and $j=k$
2. $a_i+a_j=a_k$, but $a_j=0$ and $i=k$
3. $a_i+a_j=a_k$, but $i=j$

```matlab
function solve(N, a):
    S = 5*10^4, M = 2*S, Z = 0
    for i from 0 to N-1:
        if a[i] == 0:
            Z++
        a[i] += S
        b[a[i]]++
    
    B = fft(2*M, padding(b, 2*M, 0))
    C = ifft(2*M, B.*B)
    
    for i from 0 to N-1:
        C[2*b[i]]--
    
    ans = 0
    for i from 0 to N-1:
        ans += C[b[i]+S]
    return ans-2*Z*(n-1)
```