📄 fft.texi
字号:
@cindex FFT@cindex Fast Fourier Transforms, see FFT@cindex Fourier Transforms, see FFT@cindex Discrete Fourier Transforms, see FFT@cindex DFTs, see FFTThis chapter describes functions for performing Fast Fourier Transforms(FFTs). The library includes radix-2 routines (for lengths which are apower of two) and mixed-radix routines (which work for any length). Forefficiency there are separate versions of the routines for real data andfor complex data. The mixed-radix routines are a reimplementation of the@sc{fftpack} library by Paul Swarztrauber. Fortran code for @sc{fftpack} isavailable on Netlib (@sc{fftpack} also includes some routines for sine andcosine transforms but these are currently not available in GSL). Fordetails and derivations of the underlying algorithms consult thedocument @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 definitionFast Fourier Transforms are efficient algorithms forcalculating 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@examplex_j = \sum_@{k=0@}^@{N-1@} z_k \exp(-2\pi i j k / N) @end example@end ifinfoThe DFT usually arises as an approximation to the continuous fouriertransform when functions are sampled at discrete intervals in space ortime. The naive evaluation of the discrete fourier transform is amatrix-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 fouriertransform algorithms use a divide-and-conquer strategy to factorize thematrix @math{W} into smaller sub-matrices, corresponding to the integerfactors of the length @math{N}. If @math{N} can be factorized into aproduct 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 \sumf_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, inverseand backwards, based on the same mathematical definitions. Thedefinition 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@examplex_j = \sum_@{k=0@}^@{N-1@} z_k \exp(-2\pi i j k / N) @end example@end ifinfo@noindentand 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@examplez_j = @{1 \over N@} \sum_@{k=0@}^@{N-1@} x_k \exp(2\pi i j k / N).@end example@end ifinfo@noindentThe factor of @math{1/N} makes this a true inverse. For example, a callto @code{gsl_fft_complex_forward} followed by a call to@code{gsl_fft_complex_inverse} should return the original data (withinnumerical errors).In general there are two possible choices for the sign of theexponential in the transform/ inverse-transform pair. GSL follows thesame convention as @sc{fftpack}, using a negative exponential for the forwardtransform. The advantage of this convention is that the inversetransform recreates the original function with simple fouriersynthesis. Numerical Recipes uses the opposite convention, a positiveexponential in the forward transform.The @dfn{backwards FFT} is simply our terminology for an unscaledversion 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@examplez^@{backwards@}_j = \sum_@{k=0@}^@{N-1@} x_k \exp(2\pi i j k / N).@end example@end ifinfo@noindentWhen the overall scale of the result is unimportant it is oftenconvenient to use the backwards FFT instead of the inverse to saveunnecessary divisions.@node Overview of complex data FFTs@section Overview of complex data FFTs@cindex FFT, complex dataThe inputs and outputs for the complex FFT routines are @dfn{packedarrays} of floating point numbers. In a packed array the real andimaginary parts of each complex number are placed in alternateneighboring elements. For example, the following definition of a packedarray of length 6,@examplegsl_complex_packed_array data[6];@end example@noindentcan be used to hold an array of three complex numbers, @code{z[3]}, inthe following way,@exampledata[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@noindentA @dfn{stride} parameter allows the user to perform transforms on theelements @code{z[stride*i]} instead of @code{z[i]}. A stride greaterthan 1 can be used to take an in-place FFT of the column of a matrix. Astride of 1 accesses the array without any additional spacing betweenelements.The array indices have the same ordering as those in the definition ofthe DFT --- i.e. there are no index transformations or permutations ofthe data.For physical applications it is important to remember that the indexappearing in the DFT does not correspond directly to a physicalfrequency. If the time-step of the DFT is @math{\Delta} then thefrequency-domain includes both positive and negative frequencies,ranging from @math{-1/(2\Delta)} through 0 to @math{+1/(2\Delta)}. Thepositive frequencies are stored from the beginning of the array up tothe middle, and the negative frequencies are stored backwards from theend of the array.Here is a table which shows the layout of the array @var{data}, and thecorrespondence between the time-domain data @math{z}, and thefrequency-domain data @math{x}.@exampleindex 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@noindentWhen @math{N} is even the location @math{N/2} contains the most positiveand negative frequencies @math{+1/(2 \Delta)}, @math{-1/(2 \Delta)})which are equivalent. If @math{N} is odd then general structure of thetable 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 dataThe radix-2 algorithms described in this section are simple and compact,although not necessarily the most efficient. They use the Cooley-Tukeyalgorithm to compute in-place complex FFTs for lengths which are a powerof 2 --- no additional storage is required. The correspondingself-sorting mixed-radix routines offer better performance at theexpense of requiring additional working space.All these functions 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})@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 ofthe transform @var{n} is restricted to powers of two.The functions return a value of @code{GSL_SUCCESS} if no errors weredetected, or @code{GSL_EDOM} if the length of the data @var{n} is not apower 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})@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 dataHere is an example program which computes the FFT of a short pulse in asample of length 128. To make the resulting fourier transform real thepulse is defined for equal positive and negative times (@math{-10}@dots{} @math{10}), where the negative times wrap around the end of thearray.@example#include <stdio.h>#include <math.h>#include <gsl/gsl_errno.h>#include <gsl/gsl_fft_complex.h>#define REAL(z,i) ((z)[2*(i)])#define IMAG(z,i) ((z)[2*(i)+1])intmain (void)@{ int i; double data[2*128]; for (i = 0; i < 128; i++) @{ REAL(data,i) = 0.0; IMAG(data,i) = 0.0; @} REAL(data,0) = 1.0; for (i = 1; i <= 10; i++) @{ REAL(data,i) = REAL(data,128-i) = 1.0; @} for (i = 0; i < 128; i++) @{ printf ("%d %e %e\n", i, REAL(data,i), IMAG(data,i)); @} printf ("\n"); gsl_fft_complex_radix2_forward (data, 1, 128); for (i = 0; i < 128; i++) @{ printf ("%d %e %e\n", i, REAL(data,i)/sqrt(128), IMAG(data,i)/sqrt(128)); @} return 0;@}@end example@noindentNote that we have assumed that the program is using the default errorhandler (which calls @code{abort} for any errors). If you are not usinga 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 onthe same plot as the input. Only the real part is shown, by the choiceof the input data the imaginary part is zero. Allowing for thewrap-around of negative times at @math{t=128}, and working in units of@math{k/N}, the DFT approximates the continuum fourier transform, givinga modulated @math{\sin} 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,3.4in} @center @image{fft-complex-radix2-f,3.4in}@displayA pulse and its discrete fourier transform, output fromthe example program.@end display@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 dataThis section describes mixed-radix FFT algorithms for complex data. Themixed-radix functions work for FFTs of any length. They are areimplementation of the Fortran @sc{fftpack} library by PaulSwarztrauber. The theory is explained in the review article@cite{Self-sorting Mixed-radix FFTs} by Clive Temperton. The routineshere use the same indexing scheme and basic algorithms as @sc{fftpack}.The mixed-radix algorithm is based on sub-transform modules -- highlyoptimized small length FFTs which are combined to create larger FFTs.There are efficient modules for factors of 2, 3, 4, 5, 6 and 7. Themodules for the composite factors of 4 and 6 are faster than combiningthe modules for @math{2*2} and @math{2*3}.For factors which are not implemented as modules there is a fall-back toa general length-@math{n} module which uses Singleton's method forefficiently computing a DFT. This module is @math{O(n^2)}, and slowerthan a dedicated module would be but works for any length @math{n}. Ofcourse, lengths which use the general length-@math{n} module will stillbe factorized as much as possible. For example, a length of 143 will befactorized into @math{11*13}. Large prime factors are the worst casescenario, e.g. as found in @math{n=2*3*99991}, and should be avoidedbecause their @math{O(n^2)} scaling will dominate the run-time (consultthe document @cite{GSL FFT Algorithms} included in the GSL distributionif 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 beenfactorized, and estimate the run-time. To a first approximation therun-time scales as @math{N \sum f_i}, where the @math{f_i} are thefactors of @math{N}. For programs under user control you may wish to
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -