

   FFaasstt DDiissccrreettee FFoouurriieerr TTrraannssffoorrmm

        fft(z, inverse = FALSE)
        mvfft(z, inverse = FALSE)

   AArrgguummeennttss::

          z: a real or complex array containing the values to
             be transformed

    inverse: if `TRUE', the unnormalized inverse transform is
             computed (the inverse has a `+' in the exponent of
             e, but here, we do not divide by `1/length(x)').

   VVaalluuee::

        When `z' is a vector, the value computed and returned
        by `fft' is the unnormalized univariate Fourier trans-
        form of the sequence of values in `z'.  When `z' con-
        tains an array, `fft' computes and returns the multi-
        variate (spatial) transform.  If `inverse' is `TRUE',
        the (unnormalized) inverse Fourier transform is
        returned, i.e., if `y <- fft(z)', then `z' is `fft(y,
        inv=TRUE) / length(y)'.

        By contrast, `mvfft' takes a real or complex matrix as
        argument, and returns a similar shaped matrix, but with
        each column replaced by its discrete Fourier transform.
        This is useful for analyzing vector-valued series.

        The FFT is fastest when the length of of the series
        being transformed is highly composite (i.e. has many
        factors).  If this is not the case, the transform may
        take a long time to compute and will use a large amount
        of memory.

   RReeffeerreenncceess::

        Singleton, R. C. (1979).  Mixed Radix Fast Fourier
        Transforms, in Programs for Digital Signal Processing,
        IEEE Digital Signal Processing Committee eds.  IEEE
        Press.

   SSeeee AAllssoo::

        `convolve', `nextn'.

   EExxaammpplleess::

        x <- 1:4
        fft(x)
        all(fft(fft(x), inverse = TRUE)/(x*length(x)) == 1+0i)
        eps <- 1e-11 ## In general, not exactly, but still:
        for(N in 1:130) {
            cat("N=",formatC(N,wid=3),": ")
            x <- rnorm(N)
            if(N %% 5 == 0) {
                m5 <- matrix(x,ncol=5)
                cat("mvfft:",all(apply(m5,2,fft) == mvfft(m5)),"")
            }
            dd <- Mod(1 - (f2 <- fft(fft(x), inverse=TRUE)/(x*length(x))))
            cat(if(all(dd < eps))paste(" all < ", formatC(eps)) else
                    paste("NO: range=",paste(formatC(range(dd)),collapse=",")),"\n")
        }

        plot(fft(c(9:0,0:13, numeric(301))), type = "l")
        periodogram <- function(x, mean.x = mean(x)) { # simple periodogram
          n <- length(x)
          x <- unclass(x) - mean.x
          Mod(fft(x))[1:(n%/%2 + 1)]^2 / (2*pi*n)
        }
        data(sunspots)
        plot(10*log10(periodogram(sunspots)), type = "b", col = "blue")

