Purpose: The recursive divide-and-conquer scheme that computes a Discrete Fourier Transform in . When people say βthe FFTβ, they almost always mean radix-2 Cooley-Tukey.
The Decimation
Split the input by index parity:
Since is a primitive -th root of unity, both sums are DFTs of half the size. Writing and for them:
That pair is the butterfly, and it is why one DFT of size costs two of size plus :
Iterative implementation
The recursion permutes the input into bit-reversed order. Doing that permutation up front turns the algorithm into three tidy loops with no recursion:
using cd = complex<double>;
void fft(vector<cd>& a, bool invert) {
int n = a.size();
for (int i = 1, j = 0; i < n; i++) { // bit-reversal permutation
int bit = n >> 1;
for (; j & bit; bit >>= 1) j ^= bit;
j ^= bit;
if (i < j) swap(a[i], a[j]);
}
for (int len = 2; len <= n; len <<= 1) { // butterfly levels
double ang = 2 * M_PI / len * (invert ? -1 : 1);
cd wlen(cos(ang), sin(ang));
for (int i = 0; i < n; i += len) {
cd w(1);
for (int j = 0; j < len / 2; j++) {
cd u = a[i + j], v = a[i + j + len / 2] * w;
a[i + j] = u + v;
a[i + j + len / 2] = u - v;
w *= wlen;
}
}
}
if (invert) for (cd& x : a) x /= n;
}Complexity
- Time: , with butterflies
- Space: , fully in place after the bit-reversal
Radix and variants
| Variant | Idea |
|---|---|
| Radix-2 DIT | split by index parity (the code above) |
| Radix-2 DIF | split by output parity; no bit-reversal on input, but on output |
| Radix-4 / split-radix | fewer multiplications; ~20% faster |
| Good-Thomas | with ; no twiddle factors at all |
| Rader | prime , via a convolution over the multiplicative group |
| Bluestein | arbitrary , via a chirp-z convolution |
Precision
Doubles give roughly bits of error growth. For products of integers up to with , plain complex FFT will lose the low bits. Use NTT over a prime modulus, or split each coefficient into two 15-bit halves and do four transforms.
Variants / Use Cases
- FFT and NTT β the topic page with the full contest toolkit
- Fast Fourier Transform β the overview page
- NTT β exact integer version, no precision loss
- Convolution β the reason you want an FFT at all
- Karatsuba / Toom-Cook β the sub-quadratic methods used below the FFT crossover