Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 45

DIT FFT: Algorithm and Complexity Analysis

Recommended resources

Hello! Welcome back to our course on signal processing.

In our last lesson, we put together a powerful, practical algorithm: "fast convolution." We saw how to compute linear convolution by using the DFT, with the crucial step of zero-padding our signals to a length of at least . We've repeatedly justified this roundabout method by citing the incredible efficiency of the "Fast Fourier Transform," or FFT.

Today, we will finally uncover the magic behind that efficiency. This lesson is dedicated to understanding what the FFT truly is: not a new transform, but a brilliant algorithm for computing the DFT. Our goal is to derive the decimation-in-time (DIT) FFT algorithm and analyze its computational complexity compared to the direct DFT. This is a cornerstone concept in digital signal processing, a development that, as you'll see, transformed the field from theoretical to practical for many applications.

1. The Computational Cost of the Direct DFT

Before we can appreciate the "fast" in FFT, we must first understand the "slow" in DFT. The DFT is defined by the analysis equation:

Let's analyze the number of calculations needed to compute this directly.

  • For a single DFT coefficient , we need to perform complex multiplications (each by its corresponding complex exponential) and complex additions to sum the results.
  • Since we need to do this for all values of (from 0 to ), the total number of operations is on the order of .

We say the direct DFT has a computational complexity of . This might not seem so bad for small , but as grows, the computational cost becomes prohibitive very quickly.

To get a feel for the numbers and the historical context behind the FFT's development, please watch the beginning of the following video.

The Fast Fourier Transform Algorithm

This video, from Barry Van Veen's channel, provides a clear and concise introduction to the FFT. The first part explains the computational problem with the direct DFT and demonstrates the dramatic impact of the FFT's efficiency.

Please watch from the beginning to 03:45. Focus on: The calculation of the direct DFT's complexity as O(N^2). The comparison table and the example that shows a calculation taking 31 years with the direct DFT could take just 30 seconds with the FFT.

The difference between and the FFT's is not just an incremental improvement; it's a revolutionary leap that made real-time spectral analysis and complex digital filtering feasible.


2. The Core Idea: Divide and Conquer

The key to the FFT algorithm, first published in its modern form by James Cooley and John Tukey in 1965 (though rediscovered from the work of Gauss), is a "divide and conquer" strategy. We break a large problem into smaller, easier-to-solve subproblems and then combine their results.

The most common variant of this is the radix-2 decimation-in-time (DIT) algorithm, which we'll derive now. It works on signals where the length is a power of 2 (e.g., 1024, 4096).

The derivation starts by splitting the DFT summation into two smaller sums: one over the even-indexed samples of and one over the odd-indexed samples.

This derivation is the heart of the lesson. The following video segment walks through it step-by-step. As you watch, I will provide the key mathematical expressions here for your reference.

The Fast Fourier Transform Algorithm

This segment of the same video explains the core mathematical trick of the DIT-FFT. It shows how to split the N-point DFT sum into two N/2-point DFTs.

Please watch from 03:45 to 09:22. Pay close attention to the algebraic manipulation. Notice the introduction of the 'twiddle factor' notation, W_N, and how the main sum is rearranged.

Derivation Summary

Let's formalize the steps shown in the video.

  1. Define the Twiddle Factor: To simplify notation, we define . The DFT is then .

  2. Split the Sum: We separate the sum over into even and odd indices. Let for the even terms and for the odd terms. Both sums now go from to .

  3. Factor and Simplify: We can factor out terms that don't depend on .

  4. Recognize the Smaller DFTs: The key insight is that . Substituting this in, we see two familiar forms emerge:

    Let's call the DFT of the even part and the DFT of the odd part . The equation is now:

This is a remarkable result! We have expressed an -point DFT in terms of two -point DFTs. This equation computes the first half of the output, for .

But what about the second half? For , we can substitute for :

Using the periodicity properties , , and , we get:

These two equations define the fundamental DIT butterfly computation:

For :

butterfly_diagram

Caption: A diagram of the radix-2 DIT butterfly operation. The inputs on the left (g_2(0) and g_2(4) in this example, corresponding to our X_e[k] and X_o[k]) are combined using a twiddle factor (W_8^a) to produce two outputs on the right (X[k] and X[k+N/2]). This structure is the basic building block of the FFT.


3. Complexity Analysis: From to

The "divide and conquer" step reduced the problem, but how much does that save us? And how do we turn this into a full algorithm?

The key is to apply the decomposition recursively. The two -point DFTs can each be broken down into two -point DFTs, and so on, until we are left with trivial 1-point DFTs (where the DFT of a single point is just the point itself).

Let's see how this recursive splitting leads to the complexity.

The Fast Fourier Transform Algorithm

This final segment from the Van Veen video explains the recursive nature of the FFT and derives its overall complexity.

Watch from 12:49 to 14:59. The video explains how the splitting process continues, and a simple analysis shows that at each of the \log_2 N stages, the number of operations is proportional to N.

To summarize the analysis:

  • We have stages of decomposition. (e.g., for N=8, we have 8 -> 4 -> 2 -> 1, which is 3 stages, and ).
  • At each stage, we perform butterfly computations to combine the results from the previous stage.
  • Each butterfly involves one complex multiplication and two complex additions.
  • Therefore, each of the stages requires operations.
  • The total complexity is the number of stages times the work per stage: .
Test your understanding!

Let's compare the number of complex multiplications for a direct DFT versus a DIT-FFT for a 1024-point transform ().

  1. How many complex multiplications does the direct DFT require (approximately)?
  2. How many complex multiplications does the FFT require (approximately)? Remember, there are multiplications per stage, and stages.
Show answer
  1. Direct DFT: The number of multiplications is approximately .
  2. FFT: The number of stages is . The approximate number of multiplications is .

The reduction is staggering: from over a million multiplications to just over five thousand!


4. The Algorithm in Practice: Signal Flow and Bit Reversal

When we implement this recursive algorithm, an interesting pattern emerges in the ordering of the input data. To perform the computations efficiently "in-place" (i.e., overwriting the input buffer with intermediate results to save memory), the input data must be reordered first.

This reordering is called bit reversal. If you take the index of a sample, write it in binary, and then reverse the bits, you get its new position in the input array for the DIT-FFT.

The entire process is visualized using a signal flow graph, which shows the butterfly computations at each stage.

The Fast Fourier Transform Algorithm

To make this concrete, let's look at the full signal flow graph for an 8-point FFT.

Watch from 14:59 to 18:20. Observe the three stages of butterflies for N=8. Notice the input order on the left (x[0], x[4], x[2], x[6]...) and how it corresponds to the bit-reversal of the natural order (0, 1, 2, 3...).

The canonical DIT-FFT algorithm can be summarized in pseudocode:

// N is a power of 2
// x is an array of N complex numbers

procedure dit_fft(x, N):
    // 1. Reorder the input array by bit-reversal
    bit_reverse_copy(x)

    // 2. Perform log2(N) stages of butterfly computations
    for stage from 1 to log2(N):
        M = 2^stage  // Size of DFTs being combined
        W_m = exp(-2*pi*j / M)
        for k from 0 to M/2 - 1:
            twiddle = (W_m)^k
            for j from 0 to N-1 by M:
                // Perform butterfly
                t = twiddle * x[j + k + M/2]
                u = x[j + k]
                x[j + k] = u + t
                x[j + k + M/2] = u - t

This iterative, in-place structure is how most high-performance FFT libraries are implemented.


5. A Deeper Perspective: Why Does This Work?

We have successfully derived the algorithm and analyzed its complexity. For your interest, given your preference for deeper mathematical insights, there is a beautiful alternative perspective from computer science and algebra that explains why a fast algorithm like this is even possible.

The key is to view the DFT as the evaluation of a polynomial, whose coefficients are the signal values , at specific points on the complex plane—the -th roots of unity. The DIT-FFT algorithm is a manifestation of a fast polynomial evaluation algorithm. The "divide and conquer" strategy works because the set of -th roots of unity has a special "collapsing" property: if you square all of them, you get the -th roots of unity, repeated twice. This allows the problem size to shrink at each stage of the recursion.

This is a more abstract but powerful way to understand the FFT. If you're curious, the MIT OpenCourseWare lecture "Divide & Conquer: FFT" provides a fantastic explanation of this viewpoint.


Conclusion

In this lesson, we demystified the Fast Fourier Transform. You now understand that it is not a different transform, but a remarkably efficient algorithm for computing the DFT.

Key Takeaways:

  • Direct computation of the DFT has a complexity of , which is too slow for large .
  • The FFT is a divide-and-conquer algorithm that reduces this complexity to .
  • The radix-2 Decimation-In-Time (DIT) algorithm works by recursively splitting an -point signal into its even and odd indexed samples, computing their -point DFTs, and combining them.
  • The core computation is the butterfly, which combines results from smaller DFTs using "twiddle factors" ().
  • An efficient, in-place implementation of the DIT-FFT algorithm involves an initial bit-reversal of the input data, followed by stages of butterfly computations.

This understanding of the FFT's mechanics completes our deep dive into the fundamental tools of discrete-time signal analysis.

Preview of the Next Module:

We now possess a comprehensive toolkit for analyzing and manipulating signals in the frequency domain. Our next major topic is to use these tools for a practical purpose: designing digital filters. In the first lesson of the next module, we will explore the historical context of digital filter design, examining how engineers first ingeniously adapted decades of analog filter theory to the digital domain before developing the direct digital design methods we use today. This will set the stage for designing our own IIR and FIR filters to meet specific frequency-response requirements.