summaryrefslogtreecommitdiff
path: root/gsl-1.9/doc/fft.texi
diff options
context:
space:
mode:
Diffstat (limited to 'gsl-1.9/doc/fft.texi')
-rw-r--r--gsl-1.9/doc/fft.texi1001
1 files changed, 1001 insertions, 0 deletions
diff --git a/gsl-1.9/doc/fft.texi b/gsl-1.9/doc/fft.texi
new file mode 100644
index 0000000..16cc5a9
--- /dev/null
+++ b/gsl-1.9/doc/fft.texi
@@ -0,0 +1,1001 @@
+@cindex FFT
+@cindex Fast Fourier Transforms, see FFT
+@cindex Fourier Transforms, see FFT
+@cindex Discrete Fourier Transforms, see FFT
+@cindex DFTs, see FFT
+
+This chapter describes functions for performing Fast Fourier Transforms
+(FFTs). The library includes radix-2 routines (for lengths which are a
+power of two) and mixed-radix routines (which work for any length). For
+efficiency there are separate versions of the routines for real data and
+for complex data. The mixed-radix routines are a reimplementation of the
+@sc{fftpack} library of Paul Swarztrauber. Fortran code for @sc{fftpack} is
+available on Netlib (@sc{fftpack} also includes some routines for sine and
+cosine transforms but these are currently not available in GSL). For
+details and derivations of the underlying algorithms consult the
+document @cite{GSL FFT Algorithms} (@pxref{FFT References and Further Reading})
+
+@menu
+* Mathematical Definitions::
+* Overview of complex data FFTs::
+* Radix-2 FFT routines for complex data::
+* Mixed-radix FFT routines for complex data::
+* Overview of real data FFTs::
+* Radix-2 FFT routines for real data::
+* Mixed-radix FFT routines for real data::
+* FFT References and Further Reading::
+@end menu
+
+@node Mathematical Definitions
+@section Mathematical Definitions
+@cindex FFT mathematical definition
+
+Fast Fourier Transforms are efficient algorithms for
+calculating the discrete fourier transform (DFT),
+@tex
+\beforedisplay
+$$
+x_j = \sum_{k=0}^{N-1} z_k \exp(-2\pi i j k / N)
+$$
+\afterdisplay
+@end tex
+@ifinfo
+
+@example
+x_j = \sum_@{k=0@}^@{N-1@} z_k \exp(-2\pi i j k / N)
+@end example
+@end ifinfo
+
+The DFT usually arises as an approximation to the continuous fourier
+transform when functions are sampled at discrete intervals in space or
+time. The naive evaluation of the discrete fourier transform is a
+matrix-vector multiplication
+@c{$W\vec{z}$}
+@math{W\vec@{z@}}. A general matrix-vector multiplication takes
+@math{O(N^2)} operations for @math{N} data-points. Fast fourier
+transform algorithms use a divide-and-conquer strategy to factorize the
+matrix @math{W} into smaller sub-matrices, corresponding to the integer
+factors of the length @math{N}. If @math{N} can be factorized into a
+product of integers
+@c{$f_1 f_2 \ldots f_n$}
+@math{f_1 f_2 ... f_n} then the DFT can be computed in @math{O(N \sum
+f_i)} operations. For a radix-2 FFT this gives an operation count of
+@math{O(N \log_2 N)}.
+
+All the FFT functions offer three types of transform: forwards, inverse
+and backwards, based on the same mathematical definitions. The
+definition of the @dfn{forward fourier transform},
+@c{$x = \hbox{FFT}(z)$}
+@math{x = FFT(z)}, is,
+@tex
+\beforedisplay
+$$
+x_j = \sum_{k=0}^{N-1} z_k \exp(-2\pi i j k / N)
+$$
+\afterdisplay
+@end tex
+@ifinfo
+
+@example
+x_j = \sum_@{k=0@}^@{N-1@} z_k \exp(-2\pi i j k / N)
+@end example
+
+@end ifinfo
+@noindent
+and the definition of the @dfn{inverse fourier transform},
+@c{$x = \hbox{IFFT}(z)$}
+@math{x = IFFT(z)}, is,
+@tex
+\beforedisplay
+$$
+z_j = {1 \over N} \sum_{k=0}^{N-1} x_k \exp(2\pi i j k / N).
+$$
+\afterdisplay
+@end tex
+@ifinfo
+
+@example
+z_j = @{1 \over N@} \sum_@{k=0@}^@{N-1@} x_k \exp(2\pi i j k / N).
+@end example
+
+@end ifinfo
+@noindent
+The factor of @math{1/N} makes this a true inverse. For example, a call
+to @code{gsl_fft_complex_forward} followed by a call to
+@code{gsl_fft_complex_inverse} should return the original data (within
+numerical errors).
+
+In general there are two possible choices for the sign of the
+exponential in the transform/ inverse-transform pair. GSL follows the
+same convention as @sc{fftpack}, using a negative exponential for the forward
+transform. The advantage of this convention is that the inverse
+transform recreates the original function with simple fourier
+synthesis. Numerical Recipes uses the opposite convention, a positive
+exponential in the forward transform.
+
+The @dfn{backwards FFT} is simply our terminology for an unscaled
+version of the inverse FFT,
+@tex
+\beforedisplay
+$$
+z^{backwards}_j = \sum_{k=0}^{N-1} x_k \exp(2\pi i j k / N).
+$$
+\afterdisplay
+@end tex
+@ifinfo
+
+@example
+z^@{backwards@}_j = \sum_@{k=0@}^@{N-1@} x_k \exp(2\pi i j k / N).
+@end example
+
+@end ifinfo
+@noindent
+When the overall scale of the result is unimportant it is often
+convenient to use the backwards FFT instead of the inverse to save
+unnecessary divisions.
+
+@node Overview of complex data FFTs
+@section Overview of complex data FFTs
+@cindex FFT, complex data
+
+The inputs and outputs for the complex FFT routines are @dfn{packed
+arrays} of floating point numbers. In a packed array the real and
+imaginary parts of each complex number are placed in alternate
+neighboring elements. For example, the following definition of a packed
+array of length 6,
+
+@example
+double x[3*2];
+gsl_complex_packed_array data = x;
+@end example
+
+@noindent
+can be used to hold an array of three complex numbers, @code{z[3]}, in
+the following way,
+
+@example
+data[0] = Re(z[0])
+data[1] = Im(z[0])
+data[2] = Re(z[1])
+data[3] = Im(z[1])
+data[4] = Re(z[2])
+data[5] = Im(z[2])
+@end example
+
+@noindent
+The array indices for the data have the same ordering as those
+in the definition of the DFT---i.e. there are no index transformations
+or permutations of the data.
+
+A @dfn{stride} parameter allows the user to perform transforms on the
+elements @code{z[stride*i]} instead of @code{z[i]}. A stride greater
+than 1 can be used to take an in-place FFT of the column of a matrix. A
+stride of 1 accesses the array without any additional spacing between
+elements.
+
+To perform an FFT on a vector argument, such as @code{gsl_vector_complex
+* v}, use the following definitions (or their equivalents) when calling
+the functions described in this chapter:
+
+@example
+gsl_complex_packed_array data = v->data;
+size_t stride = v->stride;
+size_t n = v->size;
+@end example
+
+For physical applications it is important to remember that the index
+appearing in the DFT does not correspond directly to a physical
+frequency. If the time-step of the DFT is @math{\Delta} then the
+frequency-domain includes both positive and negative frequencies,
+ranging from @math{-1/(2\Delta)} through 0 to @math{+1/(2\Delta)}. The
+positive frequencies are stored from the beginning of the array up to
+the middle, and the negative frequencies are stored backwards from the
+end of the array.
+
+Here is a table which shows the layout of the array @var{data}, and the
+correspondence between the time-domain data @math{z}, and the
+frequency-domain data @math{x}.
+
+@example
+index z x = FFT(z)
+
+0 z(t = 0) x(f = 0)
+1 z(t = 1) x(f = 1/(N Delta))
+2 z(t = 2) x(f = 2/(N Delta))
+. ........ ..................
+N/2 z(t = N/2) x(f = +1/(2 Delta),
+ -1/(2 Delta))
+. ........ ..................
+N-3 z(t = N-3) x(f = -3/(N Delta))
+N-2 z(t = N-2) x(f = -2/(N Delta))
+N-1 z(t = N-1) x(f = -1/(N Delta))
+@end example
+
+@noindent
+When @math{N} is even the location @math{N/2} contains the most positive
+and negative frequencies (@math{+1/(2 \Delta)}, @math{-1/(2 \Delta)})
+which are equivalent. If @math{N} is odd then general structure of the
+table above still applies, but @math{N/2} does not appear.
+
+
+@node Radix-2 FFT routines for complex data
+@section Radix-2 FFT routines for complex data
+@cindex FFT of complex data, radix-2 algorithm
+@cindex Radix-2 FFT, complex data
+
+The radix-2 algorithms described in this section are simple and compact,
+although not necessarily the most efficient. They use the Cooley-Tukey
+algorithm to compute in-place complex FFTs for lengths which are a power
+of 2---no additional storage is required. The corresponding
+self-sorting mixed-radix routines offer better performance at the
+expense of requiring additional working space.
+
+All the functions described in this section are declared in the header file @file{gsl_fft_complex.h}.
+
+@deftypefun int gsl_fft_complex_radix2_forward (gsl_complex_packed_array @var{data}, size_t @var{stride}, size_t @var{n})
+
+@deftypefunx int gsl_fft_complex_radix2_transform (gsl_complex_packed_array @var{data}, size_t @var{stride}, size_t @var{n}, gsl_fft_direction @var{sign})
+
+@deftypefunx int gsl_fft_complex_radix2_backward (gsl_complex_packed_array @var{data}, size_t @var{stride}, size_t @var{n})
+
+@deftypefunx int gsl_fft_complex_radix2_inverse (gsl_complex_packed_array @var{data}, size_t @var{stride}, size_t @var{n})
+
+These functions compute forward, backward and inverse FFTs of length
+@var{n} with stride @var{stride}, on the packed complex array @var{data}
+using an in-place radix-2 decimation-in-time algorithm. The length of
+the transform @var{n} is restricted to powers of two. For the
+@code{transform} version of the function the @var{sign} argument can be
+either @code{forward} (@math{-1}) or @code{backward} (@math{+1}).
+
+The functions return a value of @code{GSL_SUCCESS} if no errors were
+detected, or @code{GSL_EDOM} if the length of the data @var{n} is not a
+power of two.
+@end deftypefun
+
+@deftypefun int gsl_fft_complex_radix2_dif_forward (gsl_complex_packed_array @var{data}, size_t @var{stride}, size_t @var{n})
+
+@deftypefunx int gsl_fft_complex_radix2_dif_transform (gsl_complex_packed_array @var{data}, size_t @var{stride}, size_t @var{n}, gsl_fft_direction @var{sign})
+
+@deftypefunx int gsl_fft_complex_radix2_dif_backward (gsl_complex_packed_array @var{data}, size_t @var{stride}, size_t @var{n})
+
+@deftypefunx int gsl_fft_complex_radix2_dif_inverse (gsl_complex_packed_array @var{data}, size_t @var{stride}, size_t @var{n})
+
+These are decimation-in-frequency versions of the radix-2 FFT functions.
+
+@end deftypefun
+
+
+@comment @node Example of using radix-2 FFT routines for complex data
+@comment @subsection Example of using radix-2 FFT routines for complex data
+
+Here is an example program which computes the FFT of a short pulse in a
+sample of length 128. To make the resulting fourier transform real the
+pulse is defined for equal positive and negative times (@math{-10}
+@dots{} @math{10}), where the negative times wrap around the end of the
+array.
+
+@example
+@verbatiminclude examples/fft.c
+@end example
+
+@noindent
+Note that we have assumed that the program is using the default error
+handler (which calls @code{abort} for any errors). If you are not using
+a safe error handler you would need to check the return status of
+@code{gsl_fft_complex_radix2_forward}.
+
+The transformed data is rescaled by @math{1/\sqrt N} so that it fits on
+the same plot as the input. Only the real part is shown, by the choice
+of the input data the imaginary part is zero. Allowing for the
+wrap-around of negative times at @math{t=128}, and working in units of
+@math{k/N}, the DFT approximates the continuum fourier transform, giving
+a modulated sine function.
+@iftex
+@tex
+\beforedisplay
+$$
+\int_{-a}^{+a} e^{-2 \pi i k x} dx = {\sin(2\pi k a) \over\pi k}
+$$
+\afterdisplay
+@end tex
+
+@sp 1
+@center @image{fft-complex-radix2-t,2.8in}
+@center @image{fft-complex-radix2-f,2.8in}
+@quotation
+A pulse and its discrete fourier transform, output from
+the example program.
+@end quotation
+@end iftex
+
+@node Mixed-radix FFT routines for complex data
+@section Mixed-radix FFT routines for complex data
+@cindex FFT of complex data, mixed-radix algorithm
+@cindex Mixed-radix FFT, complex data
+
+This section describes mixed-radix FFT algorithms for complex data. The
+mixed-radix functions work for FFTs of any length. They are a
+reimplementation of Paul Swarztrauber's Fortran @sc{fftpack} library.
+The theory is explained in the review article @cite{Self-sorting
+Mixed-radix FFTs} by Clive Temperton. The routines here use the same
+indexing scheme and basic algorithms as @sc{fftpack}.
+
+The mixed-radix algorithm is based on sub-transform modules---highly
+optimized small length FFTs which are combined to create larger FFTs.
+There are efficient modules for factors of 2, 3, 4, 5, 6 and 7. The
+modules for the composite factors of 4 and 6 are faster than combining
+the modules for @math{2*2} and @math{2*3}.
+
+For factors which are not implemented as modules there is a fall-back to
+a general length-@math{n} module which uses Singleton's method for
+efficiently computing a DFT. This module is @math{O(n^2)}, and slower
+than a dedicated module would be but works for any length @math{n}. Of
+course, lengths which use the general length-@math{n} module will still
+be factorized as much as possible. For example, a length of 143 will be
+factorized into @math{11*13}. Large prime factors are the worst case
+scenario, e.g. as found in @math{n=2*3*99991}, and should be avoided
+because their @math{O(n^2)} scaling will dominate the run-time (consult
+the document @cite{GSL FFT Algorithms} included in the GSL distribution
+if you encounter this problem).
+
+The mixed-radix initialization function @code{gsl_fft_complex_wavetable_alloc}
+returns the list of factors chosen by the library for a given length
+@math{N}. It can be used to check how well the length has been
+factorized, and estimate the run-time. To a first approximation the
+run-time scales as @math{N \sum f_i}, where the @math{f_i} are the
+factors of @math{N}. For programs under user control you may wish to
+issue a warning that the transform will be slow when the length is
+poorly factorized. If you frequently encounter data lengths which
+cannot be factorized using the existing small-prime modules consult
+@cite{GSL FFT Algorithms} for details on adding support for other
+factors.
+
+@comment First, the space for the trigonometric lookup tables and scratch area is
+@comment allocated by a call to one of the @code{alloc} functions. We
+@comment call the combination of factorization, scratch space and trigonometric
+@comment lookup arrays a @dfn{wavetable}. It contains the sine and cosine
+@comment waveforms for the all the frequencies that will be used in the FFT.
+
+@comment The wavetable is initialized by a call to the corresponding @code{init}
+@comment function. It factorizes the data length, using the implemented
+@comment subtransforms as preferred factors wherever possible. The trigonometric
+@comment lookup table for the chosen factorization is also computed.
+
+@comment An FFT is computed by a call to one of the @code{forward},
+@comment @code{backward} or @code{inverse} functions, with the data, length and
+@comment wavetable as arguments.
+
+All the functions described in this section are declared in the header
+file @file{gsl_fft_complex.h}.
+
+@deftypefun {gsl_fft_complex_wavetable *} gsl_fft_complex_wavetable_alloc (size_t @var{n})
+This function prepares a trigonometric lookup table for a complex FFT of
+length @var{n}. The function returns a pointer to the newly allocated
+@code{gsl_fft_complex_wavetable} if no errors were detected, and a null
+pointer in the case of error. The length @var{n} is factorized into a
+product of subtransforms, and the factors and their trigonometric
+coefficients are stored in the wavetable. The trigonometric coefficients
+are computed using direct calls to @code{sin} and @code{cos}, for
+accuracy. Recursion relations could be used to compute the lookup table
+faster, but if an application performs many FFTs of the same length then
+this computation is a one-off overhead which does not affect the final
+throughput.
+
+The wavetable structure can be used repeatedly for any transform of the
+same length. The table is not modified by calls to any of the other FFT
+functions. The same wavetable can be used for both forward and backward
+(or inverse) transforms of a given length.
+@end deftypefun
+
+@deftypefun void gsl_fft_complex_wavetable_free (gsl_fft_complex_wavetable * @var{wavetable})
+This function frees the memory associated with the wavetable
+@var{wavetable}. The wavetable can be freed if no further FFTs of the
+same length will be needed.
+@end deftypefun
+
+@noindent
+These functions operate on a @code{gsl_fft_complex_wavetable} structure
+which contains internal parameters for the FFT. It is not necessary to
+set any of the components directly but it can sometimes be useful to
+examine them. For example, the chosen factorization of the FFT length
+is given and can be used to provide an estimate of the run-time or
+numerical error. The wavetable structure is declared in the header file
+@file{gsl_fft_complex.h}.
+
+@deftp {Data Type} gsl_fft_complex_wavetable
+This is a structure that holds the factorization and trigonometric
+lookup tables for the mixed radix fft algorithm. It has the following
+components:
+
+@table @code
+@item size_t n
+This is the number of complex data points
+
+@item size_t nf
+This is the number of factors that the length @code{n} was decomposed into.
+
+@item size_t factor[64]
+This is the array of factors. Only the first @code{nf} elements are
+used.
+
+@comment (FIXME: This is a fixed length array and therefore probably in
+@comment violation of the GNU Coding Standards).
+
+@item gsl_complex * trig
+This is a pointer to a preallocated trigonometric lookup table of
+@code{n} complex elements.
+
+@item gsl_complex * twiddle[64]
+This is an array of pointers into @code{trig}, giving the twiddle
+factors for each pass.
+@end table
+@end deftp
+
+@noindent
+The mixed radix algorithms require additional working space to hold
+the intermediate steps of the transform.
+
+@deftypefun {gsl_fft_complex_workspace *} gsl_fft_complex_workspace_alloc (size_t @var{n})
+This function allocates a workspace for a complex transform of length
+@var{n}.
+@end deftypefun
+
+@deftypefun void gsl_fft_complex_workspace_free (gsl_fft_complex_workspace * @var{workspace})
+This function frees the memory associated with the workspace
+@var{workspace}. The workspace can be freed if no further FFTs of the
+same length will be needed.
+@end deftypefun
+
+@comment @deftp {Data Type} gsl_fft_complex_workspace
+@comment This is a structure that holds the workspace for the mixed radix fft
+@comment algorithm. It has the following components:
+@comment
+@comment @table @code
+@comment @item gsl_complex * scratch
+@comment This is a pointer to a workspace of @code{n} complex elements,
+@comment capable of holding intermediate copies of the original data set.
+@comment @end table
+@comment @end deftp
+
+@noindent
+The following functions compute the transform,
+
+@deftypefun int gsl_fft_complex_forward (gsl_complex_packed_array @var{data}, size_t @var{stride}, size_t @var{n}, const gsl_fft_complex_wavetable * @var{wavetable}, gsl_fft_complex_workspace * @var{work})
+@deftypefunx int gsl_fft_complex_transform (gsl_complex_packed_array @var{data}, size_t @var{stride}, size_t @var{n}, const gsl_fft_complex_wavetable * @var{wavetable}, gsl_fft_complex_workspace * @var{work}, gsl_fft_direction @var{sign})
+@deftypefunx int gsl_fft_complex_backward (gsl_complex_packed_array @var{data}, size_t @var{stride}, size_t @var{n}, const gsl_fft_complex_wavetable * @var{wavetable}, gsl_fft_complex_workspace * @var{work})
+@deftypefunx int gsl_fft_complex_inverse (gsl_complex_packed_array @var{data}, size_t @var{stride}, size_t @var{n}, const gsl_fft_complex_wavetable * @var{wavetable}, gsl_fft_complex_workspace * @var{work})
+
+These functions compute forward, backward and inverse FFTs of length
+@var{n} with stride @var{stride}, on the packed complex array
+@var{data}, using a mixed radix decimation-in-frequency algorithm.
+There is no restriction on the length @var{n}. Efficient modules are
+provided for subtransforms of length 2, 3, 4, 5, 6 and 7. Any remaining
+factors are computed with a slow, @math{O(n^2)}, general-@math{n}
+module. The caller must supply a @var{wavetable} containing the
+trigonometric lookup tables and a workspace @var{work}. For the
+@code{transform} version of the function the @var{sign} argument can be
+either @code{forward} (@math{-1}) or @code{backward} (@math{+1}).
+
+The functions return a value of @code{0} if no errors were detected. The
+following @code{gsl_errno} conditions are defined for these functions:
+
+@table @code
+@item GSL_EDOM
+The length of the data @var{n} is not a positive integer (i.e. @var{n}
+is zero).
+
+@item GSL_EINVAL
+The length of the data @var{n} and the length used to compute the given
+@var{wavetable} do not match.
+@end table
+@end deftypefun
+
+@comment @node Example of using mixed-radix FFT routines for complex data
+@comment @subsection Example of using mixed-radix FFT routines for complex data
+
+Here is an example program which computes the FFT of a short pulse in a
+sample of length 630 (@math{=2*3*3*5*7}) using the mixed-radix
+algorithm.
+
+@example
+@verbatiminclude examples/fftmr.c
+@end example
+
+@noindent
+Note that we have assumed that the program is using the default
+@code{gsl} error handler (which calls @code{abort} for any errors). If
+you are not using a safe error handler you would need to check the
+return status of all the @code{gsl} routines.
+
+@node Overview of real data FFTs
+@section Overview of real data FFTs
+@cindex FFT of real data
+The functions for real data are similar to those for complex data.
+However, there is an important difference between forward and inverse
+transforms. The fourier transform of a real sequence is not real. It is
+a complex sequence with a special symmetry:
+@tex
+\beforedisplay
+$$
+z_k = z_{N-k}^*
+$$
+\afterdisplay
+@end tex
+@ifinfo
+
+@example
+z_k = z_@{N-k@}^*
+@end example
+
+@end ifinfo
+@noindent
+A sequence with this symmetry is called @dfn{conjugate-complex} or
+@dfn{half-complex}. This different structure requires different
+storage layouts for the forward transform (from real to half-complex)
+and inverse transform (from half-complex back to real). As a
+consequence the routines are divided into two sets: functions in
+@code{gsl_fft_real} which operate on real sequences and functions in
+@code{gsl_fft_halfcomplex} which operate on half-complex sequences.
+
+Functions in @code{gsl_fft_real} compute the frequency coefficients of a
+real sequence. The half-complex coefficients @math{c} of a real sequence
+@math{x} are given by fourier analysis,
+@tex
+\beforedisplay
+$$
+c_k = \sum_{j=0}^{N-1} x_j \exp(-2 \pi i j k /N)
+$$
+\afterdisplay
+@end tex
+@ifinfo
+
+@example
+c_k = \sum_@{j=0@}^@{N-1@} x_j \exp(-2 \pi i j k /N)
+@end example
+
+@end ifinfo
+@noindent
+Functions in @code{gsl_fft_halfcomplex} compute inverse or backwards
+transforms. They reconstruct real sequences by fourier synthesis from
+their half-complex frequency coefficients, @math{c},
+@tex
+\beforedisplay
+$$
+x_j = {1 \over N} \sum_{k=0}^{N-1} c_k \exp(2 \pi i j k /N)
+$$
+\afterdisplay
+@end tex
+@ifinfo
+
+@example
+x_j = @{1 \over N@} \sum_@{k=0@}^@{N-1@} c_k \exp(2 \pi i j k /N)
+@end example
+
+@end ifinfo
+@noindent
+The symmetry of the half-complex sequence implies that only half of the
+complex numbers in the output need to be stored. The remaining half can
+be reconstructed using the half-complex symmetry condition. This works
+for all lengths, even and odd---when the length is even the middle value
+where @math{k=N/2} is also real. Thus only @var{N} real numbers are
+required to store the half-complex sequence, and the transform of a real
+sequence can be stored in the same size array as the original data.
+
+The precise storage arrangements depend on the algorithm, and are
+different for radix-2 and mixed-radix routines. The radix-2 function
+operates in-place, which constrains the locations where each element can
+be stored. The restriction forces real and imaginary parts to be stored
+far apart. The mixed-radix algorithm does not have this restriction, and
+it stores the real and imaginary parts of a given term in neighboring
+locations (which is desirable for better locality of memory accesses).
+
+@node Radix-2 FFT routines for real data
+@section Radix-2 FFT routines for real data
+@cindex FFT of real data, radix-2 algorithm
+@cindex Radix-2 FFT for real data
+
+This section describes radix-2 FFT algorithms for real data. They use
+the Cooley-Tukey algorithm to compute in-place FFTs for lengths which
+are a power of 2.
+
+The radix-2 FFT functions for real data are declared in the header files
+@file{gsl_fft_real.h}
+
+@deftypefun int gsl_fft_real_radix2_transform (double @var{data}[], size_t @var{stride}, size_t @var{n})
+
+This function computes an in-place radix-2 FFT of length @var{n} and
+stride @var{stride} on the real array @var{data}. The output is a
+half-complex sequence, which is stored in-place. The arrangement of the
+half-complex terms uses the following scheme: for @math{k < N/2} the
+real part of the @math{k}-th term is stored in location @math{k}, and
+the corresponding imaginary part is stored in location @math{N-k}. Terms
+with @math{k > N/2} can be reconstructed using the symmetry
+@c{$z_k = z^*_{N-k}$}
+@math{z_k = z^*_@{N-k@}}.
+The terms for @math{k=0} and @math{k=N/2} are both purely
+real, and count as a special case. Their real parts are stored in
+locations @math{0} and @math{N/2} respectively, while their imaginary
+parts which are zero are not stored.
+
+The following table shows the correspondence between the output
+@var{data} and the equivalent results obtained by considering the input
+data as a complex sequence with zero imaginary part,
+
+@example
+complex[0].real = data[0]
+complex[0].imag = 0
+complex[1].real = data[1]
+complex[1].imag = data[N-1]
+............... ................
+complex[k].real = data[k]
+complex[k].imag = data[N-k]
+............... ................
+complex[N/2].real = data[N/2]
+complex[N/2].imag = 0
+............... ................
+complex[k'].real = data[k] k' = N - k
+complex[k'].imag = -data[N-k]
+............... ................
+complex[N-1].real = data[1]
+complex[N-1].imag = -data[N-1]
+@end example
+@noindent
+Note that the output data can be converted into the full complex
+sequence using the function @code{gsl_fft_halfcomplex_unpack}
+described in the next section.
+
+@end deftypefun
+The radix-2 FFT functions for halfcomplex data are declared in the
+header file @file{gsl_fft_halfcomplex.h}.
+
+@deftypefun int gsl_fft_halfcomplex_radix2_inverse (double @var{data}[], size_t @var{stride}, size_t @var{n})
+@deftypefunx int gsl_fft_halfcomplex_radix2_backward (double @var{data}[], size_t @var{stride}, size_t @var{n})
+
+These functions compute the inverse or backwards in-place radix-2 FFT of
+length @var{n} and stride @var{stride} on the half-complex sequence
+@var{data} stored according the output scheme used by
+@code{gsl_fft_real_radix2}. The result is a real array stored in natural
+order.
+
+@end deftypefun
+
+
+
+@node Mixed-radix FFT routines for real data
+@section Mixed-radix FFT routines for real data
+@cindex FFT of real data, mixed-radix algorithm
+@cindex Mixed-radix FFT, real data
+
+This section describes mixed-radix FFT algorithms for real data. The
+mixed-radix functions work for FFTs of any length. They are a
+reimplementation of the real-FFT routines in the Fortran @sc{fftpack} library
+by Paul Swarztrauber. The theory behind the algorithm is explained in
+the article @cite{Fast Mixed-Radix Real Fourier Transforms} by Clive
+Temperton. The routines here use the same indexing scheme and basic
+algorithms as @sc{fftpack}.
+
+The functions use the @sc{fftpack} storage convention for half-complex
+sequences. In this convention the half-complex transform of a real
+sequence is stored with frequencies in increasing order, starting at
+zero, with the real and imaginary parts of each frequency in neighboring
+locations. When a value is known to be real the imaginary part is not
+stored. The imaginary part of the zero-frequency component is never
+stored. It is known to be zero (since the zero frequency component is
+simply the sum of the input data (all real)). For a sequence of even
+length the imaginary part of the frequency @math{n/2} is not stored
+either, since the symmetry
+@c{$z_k = z_{N-k}^*$}
+@math{z_k = z_@{N-k@}^*} implies that this is
+purely real too.
+
+The storage scheme is best shown by some examples. The table below
+shows the output for an odd-length sequence, @math{n=5}. The two columns
+give the correspondence between the 5 values in the half-complex
+sequence returned by @code{gsl_fft_real_transform}, @var{halfcomplex}[] and the
+values @var{complex}[] that would be returned if the same real input
+sequence were passed to @code{gsl_fft_complex_backward} as a complex
+sequence (with imaginary parts set to @code{0}),
+
+@example
+complex[0].real = halfcomplex[0]
+complex[0].imag = 0
+complex[1].real = halfcomplex[1]
+complex[1].imag = halfcomplex[2]
+complex[2].real = halfcomplex[3]
+complex[2].imag = halfcomplex[4]
+complex[3].real = halfcomplex[3]
+complex[3].imag = -halfcomplex[4]
+complex[4].real = halfcomplex[1]
+complex[4].imag = -halfcomplex[2]
+@end example
+
+@noindent
+The upper elements of the @var{complex} array, @code{complex[3]} and
+@code{complex[4]} are filled in using the symmetry condition. The
+imaginary part of the zero-frequency term @code{complex[0].imag} is
+known to be zero by the symmetry.
+
+The next table shows the output for an even-length sequence, @math{n=6}
+In the even case there are two values which are purely real,
+
+@example
+complex[0].real = halfcomplex[0]
+complex[0].imag = 0
+complex[1].real = halfcomplex[1]
+complex[1].imag = halfcomplex[2]
+complex[2].real = halfcomplex[3]
+complex[2].imag = halfcomplex[4]
+complex[3].real = halfcomplex[5]
+complex[3].imag = 0
+complex[4].real = halfcomplex[3]
+complex[4].imag = -halfcomplex[4]
+complex[5].real = halfcomplex[1]
+complex[5].imag = -halfcomplex[2]
+@end example
+
+@noindent
+The upper elements of the @var{complex} array, @code{complex[4]} and
+@code{complex[5]} are filled in using the symmetry condition. Both
+@code{complex[0].imag} and @code{complex[3].imag} are known to be zero.
+
+All these functions are declared in the header files
+@file{gsl_fft_real.h} and @file{gsl_fft_halfcomplex.h}.
+
+@deftypefun {gsl_fft_real_wavetable *} gsl_fft_real_wavetable_alloc (size_t @var{n})
+@deftypefunx {gsl_fft_halfcomplex_wavetable *} gsl_fft_halfcomplex_wavetable_alloc (size_t @var{n})
+These functions prepare trigonometric lookup tables for an FFT of size
+@math{n} real elements. The functions return a pointer to the newly
+allocated struct if no errors were detected, and a null pointer in the
+case of error. The length @var{n} is factorized into a product of
+subtransforms, and the factors and their trigonometric coefficients are
+stored in the wavetable. The trigonometric coefficients are computed
+using direct calls to @code{sin} and @code{cos}, for accuracy.
+Recursion relations could be used to compute the lookup table faster,
+but if an application performs many FFTs of the same length then
+computing the wavetable is a one-off overhead which does not affect the
+final throughput.
+
+The wavetable structure can be used repeatedly for any transform of the
+same length. The table is not modified by calls to any of the other FFT
+functions. The appropriate type of wavetable must be used for forward
+real or inverse half-complex transforms.
+@end deftypefun
+
+@deftypefun void gsl_fft_real_wavetable_free (gsl_fft_real_wavetable * @var{wavetable})
+@deftypefunx void gsl_fft_halfcomplex_wavetable_free (gsl_fft_halfcomplex_wavetable * @var{wavetable})
+These functions free the memory associated with the wavetable
+@var{wavetable}. The wavetable can be freed if no further FFTs of the
+same length will be needed.
+@end deftypefun
+
+@noindent
+The mixed radix algorithms require additional working space to hold
+the intermediate steps of the transform,
+
+@deftypefun {gsl_fft_real_workspace *} gsl_fft_real_workspace_alloc (size_t @var{n})
+This function allocates a workspace for a real transform of length
+@var{n}. The same workspace can be used for both forward real and inverse
+halfcomplex transforms.
+@end deftypefun
+
+@deftypefun void gsl_fft_real_workspace_free (gsl_fft_real_workspace * @var{workspace})
+This function frees the memory associated with the workspace
+@var{workspace}. The workspace can be freed if no further FFTs of the
+same length will be needed.
+@end deftypefun
+
+@noindent
+The following functions compute the transforms of real and half-complex
+data,
+
+@deftypefun int gsl_fft_real_transform (double @var{data}[], size_t @var{stride}, size_t @var{n}, const gsl_fft_real_wavetable * @var{wavetable}, gsl_fft_real_workspace * @var{work})
+@deftypefunx int gsl_fft_halfcomplex_transform (double @var{data}[], size_t @var{stride}, size_t @var{n}, const gsl_fft_halfcomplex_wavetable * @var{wavetable}, gsl_fft_real_workspace * @var{work})
+These functions compute the FFT of @var{data}, a real or half-complex
+array of length @var{n}, using a mixed radix decimation-in-frequency
+algorithm. For @code{gsl_fft_real_transform} @var{data} is an array of
+time-ordered real data. For @code{gsl_fft_halfcomplex_transform}
+@var{data} contains fourier coefficients in the half-complex ordering
+described above. There is no restriction on the length @var{n}.
+Efficient modules are provided for subtransforms of length 2, 3, 4 and
+5. Any remaining factors are computed with a slow, @math{O(n^2)},
+general-n module. The caller must supply a @var{wavetable} containing
+trigonometric lookup tables and a workspace @var{work}.
+@end deftypefun
+
+@deftypefun int gsl_fft_real_unpack (const double @var{real_coefficient}[], gsl_complex_packed_array @var{complex_coefficient}, size_t @var{stride}, size_t @var{n})
+
+This function converts a single real array, @var{real_coefficient} into
+an equivalent complex array, @var{complex_coefficient}, (with imaginary
+part set to zero), suitable for @code{gsl_fft_complex} routines. The
+algorithm for the conversion is simply,
+
+@example
+for (i = 0; i < n; i++)
+ @{
+ complex_coefficient[i].real
+ = real_coefficient[i];
+ complex_coefficient[i].imag
+ = 0.0;
+ @}
+@end example
+@end deftypefun
+
+@deftypefun int gsl_fft_halfcomplex_unpack (const double @var{halfcomplex_coefficient}[], gsl_complex_packed_array @var{complex_coefficient}, size_t @var{stride}, size_t @var{n})
+
+This function converts @var{halfcomplex_coefficient}, an array of
+half-complex coefficients as returned by @code{gsl_fft_real_transform}, into an
+ordinary complex array, @var{complex_coefficient}. It fills in the
+complex array using the symmetry
+@c{$z_k = z_{N-k}^*$}
+@math{z_k = z_@{N-k@}^*}
+to reconstruct the redundant elements. The algorithm for the conversion
+is,
+
+@example
+complex_coefficient[0].real
+ = halfcomplex_coefficient[0];
+complex_coefficient[0].imag
+ = 0.0;
+
+for (i = 1; i < n - i; i++)
+ @{
+ double hc_real
+ = halfcomplex_coefficient[2 * i - 1];
+ double hc_imag
+ = halfcomplex_coefficient[2 * i];
+ complex_coefficient[i].real = hc_real;
+ complex_coefficient[i].imag = hc_imag;
+ complex_coefficient[n - i].real = hc_real;
+ complex_coefficient[n - i].imag = -hc_imag;
+ @}
+
+if (i == n - i)
+ @{
+ complex_coefficient[i].real
+ = halfcomplex_coefficient[n - 1];
+ complex_coefficient[i].imag
+ = 0.0;
+ @}
+@end example
+@end deftypefun
+
+@comment @node Example of using mixed-radix FFT routines for real data
+@comment @subsection Example of using mixed-radix FFT routines for real data
+
+Here is an example program using @code{gsl_fft_real_transform} and
+@code{gsl_fft_halfcomplex_inverse}. It generates a real signal in the
+shape of a square pulse. The pulse is fourier transformed to frequency
+space, and all but the lowest ten frequency components are removed from
+the array of fourier coefficients returned by
+@code{gsl_fft_real_transform}.
+
+The remaining fourier coefficients are transformed back to the
+time-domain, to give a filtered version of the square pulse. Since
+fourier coefficients are stored using the half-complex symmetry both
+positive and negative frequencies are removed and the final filtered
+signal is also real.
+
+@example
+@verbatiminclude examples/fftreal.c
+@end example
+
+@iftex
+@sp 1
+@center @image{fft-real-mixedradix,3.4in}
+
+@center Low-pass filtered version of a real pulse,
+@center output from the example program.
+@end iftex
+
+@node FFT References and Further Reading
+@section References and Further Reading
+
+A good starting point for learning more about the FFT is the review
+article @cite{Fast Fourier Transforms: A Tutorial Review and A State of
+the Art} by Duhamel and Vetterli,
+
+@itemize @asis
+@item
+P. Duhamel and M. Vetterli.
+Fast fourier transforms: A tutorial review and a state of the art.
+@cite{Signal Processing}, 19:259--299, 1990.
+@end itemize
+
+@noindent
+To find out about the algorithms used in the GSL routines you may want
+to consult the document @cite{GSL FFT Algorithms} (it is included
+in GSL, as @file{doc/fftalgorithms.tex}). This has general information
+on FFTs and explicit derivations of the implementation for each
+routine. There are also references to the relevant literature. For
+convenience some of the more important references are reproduced below.
+
+@noindent
+There are several introductory books on the FFT with example programs,
+such as @cite{The Fast Fourier Transform} by Brigham and @cite{DFT/FFT
+and Convolution Algorithms} by Burrus and Parks,
+
+@itemize @asis
+@item
+E. Oran Brigham.
+@cite{The Fast Fourier Transform}.
+Prentice Hall, 1974.
+
+@item
+C. S. Burrus and T. W. Parks.
+@cite{DFT/FFT and Convolution Algorithms}.
+Wiley, 1984.
+@end itemize
+
+@noindent
+Both these introductory books cover the radix-2 FFT in some detail.
+The mixed-radix algorithm at the heart of the @sc{fftpack} routines is
+reviewed in Clive Temperton's paper,
+
+@itemize @asis
+@item
+Clive Temperton.
+Self-sorting mixed-radix fast fourier transforms.
+@cite{Journal of Computational Physics}, 52(1):1--23, 1983.
+@end itemize
+
+@noindent
+The derivation of FFTs for real-valued data is explained in the
+following two articles,
+
+@itemize @asis
+@item
+Henrik V. Sorenson, Douglas L. Jones, Michael T. Heideman, and C. Sidney
+Burrus.
+Real-valued fast fourier transform algorithms.
+@cite{IEEE Transactions on Acoustics, Speech, and Signal Processing},
+ASSP-35(6):849--863, 1987.
+
+@item
+Clive Temperton.
+Fast mixed-radix real fourier transforms.
+@cite{Journal of Computational Physics}, 52:340--350, 1983.
+@end itemize
+
+@noindent
+In 1979 the IEEE published a compendium of carefully-reviewed Fortran
+FFT programs in @cite{Programs for Digital Signal Processing}. It is a
+useful reference for implementations of many different FFT
+algorithms,
+
+@itemize @asis
+@item
+Digital Signal Processing Committee and IEEE Acoustics, Speech, and Signal
+Processing Committee, editors.
+@cite{Programs for Digital Signal Processing}.
+IEEE Press, 1979.
+@end itemize
+@comment @noindent
+@comment There is also an annotated bibliography of papers on the FFT and related
+@comment topics by Burrus,
+
+@comment @itemize @asis
+@comment @item C. S. Burrus. Notes on the FFT.
+@comment @end itemize
+@comment @noindent
+@comment The notes are available from @url{http://www-dsp.rice.edu/res/fft/fftnote.asc}.
+
+@noindent
+For large-scale FFT work we recommend the use of the dedicated FFTW library
+by Frigo and Johnson. The FFTW library is self-optimizing---it
+automatically tunes itself for each hardware platform in order to
+achieve maximum performance. It is available under the GNU GPL.
+
+@itemize @asis
+@item
+FFTW Website, @uref{http://www.fftw.org/}
+@end itemize
+
+@noindent
+The source code for @sc{fftpack} is available from Netlib,
+
+@itemize @asis
+@item
+FFTPACK, @uref{http://www.netlib.org/fftpack/}
+@end itemize
+
+