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

VariantIdea
Radix-2 DITsplit by index parity (the code above)
Radix-2 DIFsplit by output parity; no bit-reversal on input, but on output
Radix-4 / split-radixfewer multiplications; ~20% faster
Good-Thomas with ; no twiddle factors at all
Raderprime , via a convolution over the multiplicative group
Bluesteinarbitrary , 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