Notes

This paper talks about reducing the time complexity of the discrete fourier transformation from to .

The DFT has the formula:

def dft(x):
    """
    Naive DFT in O(n^2) time.
    """
    N = len(x)
    result = []
    for k in range(N):
        s = 0j
        for n in range(N):
            angle = -2j * math.pi * k * n / N
            s += x[n] * cmath.exp(angle)
        result.append(s)
    return result

The paper reduces this to operations when is composite, so it can be written as . So, the indices can be re-expressed in factored form, and then turned into a sum that relies of fewer indices, and continue recursively. This divides and conquers the algorithm into .

The Radix-2 FFT:

def fft(x):
    """
    Radix-2 FFT. O(n log n) time complexity if n is a power of 2.
    """
    N = len(x)
    if N <= 1:
        return x
    if N & (N - 1) != 0:
        raise ValueError("Length of input must be a power of 2 for this FFT implementation")
 
    # Recursive FFT on even and odd indices
    even = fft(x[0::2])
    odd = fft(x[1::2])
 
    result = [0j] * N
    for k in range(N // 2):
        twiddle = cmath.exp(-2j * math.pi * k / N) * odd[k]
        result[k] = even[k] + twiddle
        result[k + N // 2] = even[k] - twiddle
    return result