THE FAST FOURIER TRANSFORM

Given a sequence of complex numbers (the coefficients on the successive terms of a complex polynomial, perhaps), its length a power of 2, compute its discrete Fourier transform. For a detailed explanation of the background to the algorithm, consult Introduction to algorithms, by Thomas H. Cormen, Charles E. Leiserson, and Ronald L. Rivest (Cambridge, Massachusetts: MIT Press, 1990), chapter 32.

The idea of the algorithm is to use recursive calls to fft to compute the Fourier transforms of the ``unshuffled'' halves of the sequence. One then obtains the first (respectively, second) len/2 components of the solution by multiplying each component of the Fourier transform of the ``odd'' half by the corresponding len-th complex root of unity, then adding it to (respectively, subtracting it from) the corresponding component of the Fourier transform of the ``even'' half.

The internal unshuffle procedure separates the elements of a given sequence into two shorter sequences, the first containing the elements in the even-numbered positions of the given sequence, the second containing those in the odd-numbered positions. It returns a pair of which the first shorter sequence is the car and the second the cdr. (This version of unshuffle presupposes that the sequence it is given is always of even length.)

(define fft
  (let ((pi 3.14159265358979323846)

        (unshuffle
         (lambda (seq)
           (let loop ((rest seq)
                      (evens '())
                      (odds '()))
             (if (null? rest)
                 (cons (reverse evens) (reverse odds))
                 (loop (cddr rest)
                       (cons (car rest) evens)
                       (cons (cadr rest) odds)))))))

    (lambda (sequence)
      (let ((len (length sequence)))
        (if (= len 1)
            sequence
            (let ((nth-root (make-polar 1 (/ (* 2 pi) len)))
                            ; principal len-th root of unity
                  (half-len (quotient len 2))
                  (packs (unshuffle sequence)))
              (let loop ((step 0)
                         (root 1)
                         (evens (fft (car packs)))
                         (odds (fft (cdr packs)))
                         (front '())
                         (rear '()))
                (if (= step half-len)
                    (append (reverse front) (reverse rear))
                    (loop (+ step 1)
                          (* root nth-root)
                          (cdr evens)
                          (cdr odds)
                          (cons (+ (car evens) (* root (car odds)))
                                front)
                          (cons (- (car evens) (* root (car odds)))
                                rear))))))))))


This document is available on the World Wide Web as

http://www.math.grin.edu/~stone/events/scheme-workshop/fft.html


created July 11, 1995
last revised June 24, 1996

John David Stone (stone@math.grin.edu)