home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-08-02 | 45.8 KB | 1,347 lines |
- #############################################################################
- # #
- # LIBFFT Version 2.3 - Jan 12, 1992 - #
- # #
- # libfft by Jean-Pierre Panziera #
- # Silicon Graphics Inc. #
- # jpp@sgi.com #
- # #
- # libfft includes one, two and three dimensional FFTs #
- # complex <---> complex #
- # real <---> complex #
- # single and double precision, #
- # 2D and 3D are parallel #
- # #
- # libfft uses a "row-column" algorithm, and it is based on 1D FFTs #
- # from FFTPACK #
- # #
- # FFTPACK is a 1D FFTs package written by Paul N Swarztrauber #
- # at National Center for Atmospheric Research Boulder,CO #
- # #
- #############################################################################
- # #
- # Version 2.3 fixes a bug with SFFT2DU and DFFT2DU. #
- # Also the default value for FFT_MAXMEM is now set to 10000000 #
- # #
- #############################################################################
- # #
- # The version 2.2 is equivalent to version 2.0 in terms of #
- # performances. However it adds a new family of function/routines #
- # for ( Real <---> Complex ) 1, 2 and 3 D FFTs. #
- # These new modules are identified by the letter U (e.g. SFFT2DU) #
- # They provide the same functionnality as the modules of version 2.0 #
- # However, the storage scheme of the Fourier Transforms is much #
- # more simpler, for the same performance ... #
- # #
- #############################################################################
-
- All routines come with both Fortran and C interfaces.
- In C two types "complex" and "zomplex" have been defined as structures of
- two floating point variables ( re, im) ... see "fft.h". They are equivalent
- to the "complex" and "double complex" Fortran types.
-
-
- #############################################################################
-
- WARNING:
-
- The library FFTs are NOT normalized. The following successive double call :
- call _fft_d( +1, ...)
- call _fft_d( -1, ...)
- will scale the input by N for 1D FFT, ( N1 x N2 for 2D FFT, and
- N1 x N2 x N3 for 3D FFT).
-
- ############################################################################
-
- The functions/routines names are:
-
- _________________________________________________________________________
- | | | | |
- | | 1 Dimension | 2 Dimensions | 3 Dimensions |
- |_______________|__________________|__________________|__________________|
- | | | | |
- | REAL | sfft1di SFFT1DUI | sfft2di SFFT2DUI | sfft3di SFFT3DUI |
- | <---> | sfft1d SFFT1DU | sfft2d SFFT2DU | sfft3d SFFT3DU |
- | COMPLEX | csfft1d | | |
- | | sprod1d SPROD1DU | sprod2d SPROD2DU | sprod3d SPROD3DU |
- | Single | sscal1d | sscal2d | sscal3d |
- | Precision | csscal1d | | |
- |_______________|__________________|__________________|__________________|
- | | | | |
- | REAL | dfft1di DFFT1DUI | dfft2di DFFT2DUI | dfft3di DFFT3DUI |
- | <---> | dfft1d DFFT1DU | dfft2d DFFT2DU | dfft3d DFFT3DU |
- | COMPLEX | zdfft1d | | |
- | | dprod1d DPROD1DU | dprod2d DPROD2DU | dprod3d DPROD3DU |
- | Double | dscal1d | dscal2d | dscal3d |
- | Precision | zdscal1d | | |
- |_______________|__________________|__________________|__________________|
- | | | | |
- | COMPLEX | cfft1di | cfft2di | cfft3di |
- | <---> | cfft1d | cfft2d | cfft3d |
- | COMPLEX | cprod1d | cprod2d | cprod3d |
- | | cscal1d | cscal2d | cscal3d |
- | Single | | | |
- |_______________|__________________|__________________|__________________|
- | | | | |
- | COMPLEX | zfft1di | zfft2di | zfft3di |
- | <---> | zfft1d | zfft2d | zfft3d |
- | COMPLEX | zprod1d | zprod2d | zprod3d |
- | | zscal1d | zscal2d | zscal3d |
- | Double | | | |
- |_______________|__________________|__________________|__________________|
-
- Note: The new modules are written "upper-case" in the list above, It is
- advisable to use them instead of the "packed" versions (e.g. "SFFT2DU"
- should be used instead of "sfft2d").
-
- |------------------|
- | Overview |
- |------------------|
-
- The first Letter of the Function/Subroutine depends on the type:
-
- c____ : Single Precision Complex
- z____ : Double Precision Complex
- s____ : Single Precision REAL
- d____ : Double Precision REAL
-
- "_fft_di", "fft_dui" functions/routines :
-
- Initialize the workspace array
-
-
-
- "_fft_d", "_fft_du" functions/routines :
-
- Fast Fourier Transformation.
-
- The library routines do the transforms IN PLACE.
- They work optimally if each of the dimension number
- n1, n2 or n3 is a multiple of 2, 3, 4 and 5.
-
- But they will always give you the right answer independent of
- the value of N.
-
-
-
- "_prod_d", "_prod_du" functions/routines :
-
- Performs the product of Fourier Transform of SAME sizes.
-
- The Array is multiplied term by term by those of a Filter.
- This operation in the Fourier Domain is equivalent to a
- Convolution in the time/space domain.
-
- "_scal_d" functions/routines :
-
- Scale a Sequence by a "real" value.
-
- This functions/routines need to be used when going back and forth
- between domains, since a direct FFT followed by an inverse FFT
- scale the original array by a factor of N (1D), N1*N2 (2D) or
- N1*N2*N3 (3D).
-
-
- PARALLEL routines:
- Only the 2D and the 3D routines have been parallelized.
-
- MEMORY allocation:
- LIBFFT gives you a control on the amount of scratch arrays
- allocated to a maximum value that can be adjusted at runtime
- through an environment variable (FFT_MAXMEM). The following command:
- % setenv FFT_MAXMEM 16777216
- will increase this Maximum size to 16 MegaBytes. This may be usefull
- to increase performances when running large FFTs like 250x300x256.
- The default value for FFT_MAXMEM is 10^6 Bytes.
-
-
- ---------------------------
- | COMPLEX <---> COMPLEX |
- ---------------------------
-
- 1 DIMENSION :
- =============
-
- C :
- complex *cfft1di( int n, complex *workspace);
-
- zomplex *zfft1di( int n, zomplex *workspace);
-
- int cfft1d ( int job, int n, complex *sequence,
- int inc, complex *workspace);
-
- int zfft1d ( int job, int n, zomplex *sequence,
- int inc, zomplex *workspace);
-
- Fortran:
- subroutine CFFT1DI( n, workspace)
- integer n
- complex workspace(*)
-
- subroutine ZFFT1DI( n, workspace)
- integer n
- double complex workspace(*)
-
- subroutine CFFT1D( job, n, sequence, inc, workspace)
- integer job, n, inc
- complex sequence(*), workspace(*)
-
- subroutine ZFFT1D( job, n, sequence, inc, workspace)
- integer job, n, inc
- double complex sequence(*), workspace(*)
-
-
- "cfft1di", "zfft1di" IMPORTANT:
-
- The "workspace" array must be at least (N + 15) elements long.
- This array requires N elements for the Sines and Cosines
- + 15 elements for the factor decomposition of N.
-
- "cfft1d", "zfft1d"
-
- job = -1 or 1 for forward or backward Fast Fourier Transform
- n = number of elements in the 1 D FFT
- sequence = array containing the elements for the FFT
- inc = increment between two consecutive elements of the sequence
- workspace = Array containing the Sines/Cosines and factorization of N
- workspace needs to be initialized by a call to _fft1di
-
-
- ---------------------------
- | COMPLEX <---> COMPLEX |
- ---------------------------
-
- 2 DIMENSIONS :
- ==============
-
- C :
- complex *cfft2di( int n1, int n2, complex *workspace)
-
- zomplex *zfft2di( int n1, int n2, zomplex *workspace)
-
- int cfft2d( int job, int n1, int n2, complex *sequence,
- int lda, complex *workspace)
-
- int zfft2d( int job, int n1, int n2, zomplex *sequence,
- int lda, zomplex *workspace)
-
- Fortran:
- subroutine CFFT2DI( n1, n2, workspace)
- integer n1, n2
- complex workspace(*)
-
- subroutine ZFFT2DI( n1, n2, workspace)
- integer n1, n2
- complex workspace(*)
-
- subroutine CFFT2D( job, n1, n2, sequence, lda, workspace)
- integer job, n1, n2, lda
- complex sequence(lda,*), workspace(*)
-
- subroutine ZFFT2D( job, n1, n2, sequence, lda, workspace)
- integer job, n1, n2, lda
- double complex sequence(lda,*), workspace(*)
-
-
- "cfft2di", "zfft2di" IMPORTANT:
-
- the "workspace" array must be at least
- (N1 + 15 + N2 + 15) elements long for Zfft2di and Cfft2di
- this array needs N1+N2 elements for the Sines and Cosines
- + 2 x 15 elements for the factorization of N1 and N2
-
-
- "cfft2d", "zfft2d" :
-
- job = -1 or 1 for forward or backward Fast Fourier Transform
- n1 = number of elements in the First Dimension of the Sequence
- n2 = number of elements in the Second Dimension of the Sequence
- sequence = Array containing the (lda*n2) elements for the FFT
- lda = Leading dimension for the Array, (lda >= n1)
- workspace = Array containing the Sin/Cos and factorization of N1 and N2
- workspace needs to be initialized by a call to _fft2di
-
- ---------------------------
- | COMPLEX <---> COMPLEX |
- ---------------------------
-
- 3 DIMENSIONS :
- ==============
-
-
- C :
- complex *cfft3di( int n1, int n2, int n3, complex *workspace);
-
- zomplex *zfft3di( int n1, int n2, int n3, zomplex *workspace);
-
- int cfft3d( int job, int n1, int n2, int n3, complex *sequence,
- int ld1, int ld2, complex *workspace)
-
- int zfft3d( int job, int n1, int n2, int n3, zomplex *sequence,
- int ld1, int ld2, zomplex *workspace)
-
- Fortran:
-
- subroutine CFFT3DI( n1, n2, n3, workspace)
- integer n1, n2, n3
- complex workspace(*)
-
- subroutine ZFFT3DI( n1, n2, n3, workspace)
- integer n1, n2, n3
- double complex workspace(*)
-
- subroutine CFFT3D( job, n1, n2, n3, sequence, ld1, ld2, workspace)
- integer job, n1, n2, ld1, ld2
- complex sequence(ld1,ld2,*), workspace(*)
-
- subroutine ZFFT3D( job, n1, n2, n3, sequence, ld1, ld2, workspace)
- integer job, n1, n2, ld1, ld2
- double complex sequence(ld1,ld2,*), workspace(*)
-
-
- "cfft3di", "zfft3di" IMPORTANT:
-
- the "workspace" array must be at least
- (N1 + 15 + N2 + 15 + N3 + 15 ) elements long for Zfft3di and Cfft3di
- this array needs N1+N2+N3 elements for the Sines and Cosines
- + 3 x 15 elements for the factorization of N1,N2 and N3.
-
-
- "cfft3d", "zfft3d" :
-
- job = -1 or 1 for forward or backward Fast Fourier Transform
- n1,n2,n3 = number of elements in the First, Second and Third
- Dimension of the Sequence
- sequence = Array containing the (ld1*ld2*n3) elements for the FFT
- ld1, ld2 = Leading dimensions for the Array, (ld1 >= n1 and ld2 >= n2)
- workspace = Array containing the Sin/Cos and factorization of N1, N2, N3
- workspace needs to be initialized by a call to _fft3di
-
- ---------------------------
- | COMPLEX <---> COMPLEX |
- ---------------------------
-
- 1 DIMENSION :
- ==============
-
- Fortran:
-
- C
- C the N elements of sequence(j) for j = 1, ..., n
- C are the SUM for k = 1, ..., n of
- C sequence(k) * exp( job*iz*(j-1)*(k-1)*2*PI/N)
- C where iz = sqrt(-1)
- C
-
- C language:
- /*
- the N elements sequence[j] for j = 0, ..., (n-1)
- are the SUM for k = 0, ..., (n-1) of
- sequence[k] * exp( job*iz*j*k*2*PI / n)
- where iz = sqrt( -1)
- */
-
- 2 DIMENSIONS :
- ==============
-
- Fortran:
- C the N1xN2 elements of sequence(j,k) for j=1,...,n1 and k=1,...,n2
- C are the SUM for l = 1, ..., n1 and m = 1, ..., n2 of
- C sequence(l,m) * exp( job*2*iz*PI*((j-1)*(l-1)/N1 + (k-1)*(m-1)/N2))
- C where iz = sqrt(-1)
-
- C language:
- /*
- the N1xN2 elements sequence[j+k*lda] for j=0,..,(n1-1) and k=0,..,(n2-1)
- are the SUM for l = 0,..,(n1-1) and m = 0,..,(n2-1) of
- sequence[l+m*lda] * exp( job*2*iz*PI*(j*l/N1 + k*m/N2))
- where iz = sqrt( -1)
- */
- 3 DIMENSIONS :
- ==============
- Fortran:
-
- C the N1xN2xN3 elements of sequence (j1,j2,j3)
- C for j1 = 1, ..., n1, for j2 = 1, ..., n2 and j3 = 1, ..., n3
- C are the SUM for k1, k2 and k3 of:
- C sequence(k1,k2,k3) * exp( job*2*iz*PI*
- C ((j1-1)*(k1-1)/N1 + (j2-1)*(k2-1)/N2 + (j3-1)*(k3-1)/N3))
- C where iz = sqrt(-1)
-
- C language:
- /*
- the N1xN2xN3 elements "sequence[j0+j1*ld1+j2*ld2]"
- are the SUM of
- sequence[k0+k1*ld1+k2*ld2]
- * exp( job*2*iz*PI*(j1*k1/N1 + j2*k2/N2 + j3*k3/N3))
- where iz = sqrt( -1)
- */
-
-
- ---------------------------
- | REAL <---> COMPLEX |
- ---------------------------
-
- 1 DIMENSION :
- =============
-
- C :
- float *sfft1dui( int n, float *workspace);
-
- double *dfft1dui( int n, double *workspace);
-
- int sfft1d ( int job, int n, float *sequence,
- int inc, float *workspace);
-
- int dfft1d ( int job, int n, double *sequence,
- int inc, double *workspace);
-
- Fortran:
- subroutine SFFT1DUI( n, workspace)
- integer n
- real workspace(*)
-
- subroutine DFFT1DUI( n, workspace)
- integer n
- double precision workspace(*)
-
- subroutine SFFT1DU( job, n, sequence, inc, workspace)
- integer job, n, inc
- real sequence(*), workspace(*)
-
- subroutine DFFT1DU( job, n, sequence, inc, workspace)
- integer job, n, inc
- double precision sequence(*), workspace(*)
-
-
- "sfft1dui", "dfft1dui" IMPORTANT:
-
- The "workspace" array must be at least (N + 15) elements long.
- This array requires N elements for the Sines and Cosines
- + 15 elements for the factor decomposition of N.
-
- "sfft1du", "dfft1du"
-
- job = -1 or 1 for forward or backward Fast Fourier Transform
- n = number of elements in the 1 D FFT
- sequence = array containing the elements for the FFT
- inc = increment between two consecutive elements of the sequence
- workspace = Array containing the Sines/Cosines and factorization of N
- workspace needs to be initialized by a call to _fft1di
-
- NOTA BENE : After the direct FFT, the sequence is 2*((n+2)/2) elements long.
- The Fourier Transform is 1 or 2 elements LONGER than the
- original sequence.
- PLEASE, pad your input array, so that no useful data is over
- written.
-
- ---------------------------
- | REAL <---> COMPLEX |
- ---------------------------
-
- 2 DIMENSIONS :
- ==============
-
- C :
- float *sfft2dui( int n1, int n2, float *workspace)
-
- double *dfft2dui( int n1, int n2, double *workspace)
-
- int sfft2du( int job, int n1, int n2, float *sequence,
- int lda, float *workspace)
-
- int dfft2du( int job, int n1, int n2, double *sequence,
- int lda, double *workspace)
-
- Fortran:
- subroutine SFFT2DUI( n1, n2, workspace)
- integer n1, n2
- real workspace(*)
-
- subroutine DFFT2DUI( n1, n2, workspace)
- integer n1, n2
- double precision workspace(*)
-
- subroutine SFFT2DU( job, n1, n2, sequence, lda, workspace)
- integer job, n1, n2, lda
- real sequence(lda,*), workspace(*)
-
- subroutine DFFT2DU( job, n1, n2, sequence, lda, workspace)
- integer job, n1, n2, lda
- double precision sequence(lda,*), workspace(*)
-
-
- "sfft2dui", "dfft2dui" IMPORTANT:
-
- the "workspace" array must be at least
- (N1 + 15 + 2*N2 + 15 ) elements long for Zfft2di and Cfft2di
- N1 elements are needed for the Sines and Cosines of the first dim.
- But we need the (2 * N2 ) for the second dimension ( COMPLEX ).
- + 2 x 15 elements for the factorization of N1 and N2
-
-
- "sfft2du", "dfft2du" :
-
- job = -1 or 1 for forward or backward Fast Fourier Transform
- n1 = number of elements in the First Dimension of the Sequence
- n2 = number of elements in the Second Dimension of the Sequence
- sequence = Array containing the (lda*n2) elements for the FFT
- lda = Leading dimension for the Array, (lda >= 2*((n1+2)/2) )
- workspace = Array containing the Sin/Cos and factorization of N1 and N2
- workspace needs to be initialized by a call to _fft2di
-
- NOTA BENE : During the direct FFT, after the FFT along the First dimension,
- the sequences are 2*((n1+2)/2) elements long.
- PLEASE, make sure that lda >= 2*((n1+2)/2)
-
- ---------------------------
- | REAL <---> COMPLEX |
- ---------------------------
-
- 3 DIMENSIONS :
- ==============
-
-
- C :
- float *sfft3dui( int n1, int n2, int n3, float *workspace);
-
- double *dfft3dui( int n1, int n2, int n3, double *workspace);
-
- int sfft3du( int job, int n1, int n2, int n3, float *sequence,
- int ld1, int ld2, float *workspace)
-
- int dfft3du( int job, int n1, int n2, int n3, double *sequence,
- int ld1, int ld2, double *workspace)
-
- Fortran:
-
- subroutine SFFT3DUI( n1, n2, n3, workspace)
- integer n1, n2, n3
- real workspace(*)
-
- subroutine DFFT3DUI( n1, n2, n3, workspace)
- integer n1, n2, n3
- double precision workspace(*)
-
- subroutine SFFT3DU( job, n1, n2, n3, sequence, ld1, ld2, workspace)
- integer job, n1, n2, ld1, ld2
- real sequence(ld1,ld2,*), workspace(*)
-
- subroutine DFFT3DU( job, n1, n2, n3, sequence, ld1, ld2, workspace)
- integer job, n1, n2, ld1, ld2
- double precision sequence(ld1,ld2,*), workspace(*)
-
-
- "sfft3dui", "dfft3dui" IMPORTANT:
-
- the "workspace" array must be at least
- (N1 + 15 + 2*N2 + 15 + 2*N3 + 15 ) elements long for Zfft3di and Cfft3di
- this array needs N1+2*N2+2*N3 elements for the Sines and Cosines
- + 3 x 15 elements for the factorization of N1, N2 and N3.
-
-
- "sfft3du", "dfft3du" :
-
- job = -1 or 1 for forward or backward Fast Fourier Transform
- n1,n2,n3 = number of elements in the First, Second and Third
- Dimension of the Sequence
- sequence = Array containing the (ld1*ld2*n3) elements for the FFT
- ld1, ld2 = Leading dimensions for the Array,
- (ld1 >= 2*((n1+2)/2) and ld2 >= n2)
- workspace = Array containing the Sin/Cos and factorization of N1, N2, N3
- workspace needs to be initialized by a call to _fft3di
-
- NOTA BENE : During the direct FFT, after the FFT along the First dimension,
- the sequences are 2*((n1+2)/2) elements long.
- PLEASE, make sure that ld1 >= 2*((n1+2)/2)
-
- ---------------------------
- | REAL <---> COMPLEX |
- ---------------------------
-
- 1 DIMENSION :
- ==============
-
- Given a sequence a(j), j = 0, ..., n-1 of N real samples,
- and B(I) its (complex) FFT.
-
- Only the first half of the FFT need to be computed, the second half can be
- deduced by symmetry : B(I) = Conjugate { B(N-I) }.
-
- example n = 5 :
- ---------------
- a0 a1 a2 a3 a4
- B0r,B0i B1r,B1i B2r,B2i B3r,B3i B4r,B4i
-
- B0i = 0 <--- Frequence 0
- B4r = B1r, B4i = - B1i
- B3r = B2r, B3i = - B2i
-
- the output from SFFT1DU or DFFT1DU will be:
-
- B0r,0.0 B1r,B1i B2r,B2i
-
- example n = 4 :
- ---------------
- a0 a1 a2 a3
- B0r,B0i B1r,B1i B2r,B2i B3r,B3i
-
- B0i = 0 <--- Frequence 0
- B2i = 0 <--- Nyquist's Frequence (N/2)
- B3r = B1r, B3i = - B1i <--- Symmetry due to real input
-
- the output from SFFT1DU or DFFT1DU will be:
-
- B0r,0.0 B1r,B1i B2r,0.0
-
- *****
- In "sfft1du" and "dfft1du" (contrary to "sfft1d" and "dfft1d" ) no
- attempt is made to pack the result (we explicitly keep the zeroes).
- The Fourier transform is therefore much simpler to interpret as a
- sequence of COMPLEX numbers.
- Formally, the definition "sfft1du" is the SAME as for "cfft1d".
-
- 2 and 3 DIMENSIONS :
- ====================
- For a 2D the direct Fourier transform we compute :
- first the N2 ( REAL--->COMPLEX ) 1D FFTs of size N1,
- then (N1+2)/2 ( COMPLEX--->COMPLEX ) FFTs of size N2.
-
- For a 3D the direct Fourier transform we compute :
- first the N2xN3 ( REAL --->COMPLEX ) 1D FFTs of size N1,
- then ((N1+2)/2)xN3 ( COMPLEX--->COMPLEX ) 1D FFTs of size N2,
- and finally ((N1+2)/2)xN2 ( COMPLEX--->COMPLEX ) 1D FFTs of size N3.
-
- The computations are performed in the reverse order for the inverse FFTs.
-
- -----------------------------------------
- | REAL <---> COMPLEX |
- -----------------------------------------
-
- 2 DIMENSIONS :
- ==============
-
- Original Real Array(lda,5) --- N1 = 4 and N2 = 5:
- |--------|--------|--------|--------|--------|
- | f(1,1) | f(1,2) | f(1,3) | f(1,4) | f(1,5) |
- |--------|--------|--------|--------|--------|
- | f(2,1) | f(2,2) | f(2,3) | f(2,4) | f(2,5) |
- |--------|--------|--------|--------|--------|
- | f(3,1) | f(3,2) | f(3,3) | f(3,4) | f(3,5) |
- |--------|--------|--------|--------|--------|
- | f(4,1) | f(4,2) | f(4,3) | f(4,4) | f(4,5) |
- |--------|--------|--------|--------|--------|
-
- After First Dimension Real FFT:
- |--------|--------|--------|--------|--------|
- | Re1(1) | Re1(2) | Re1(3) | Re1(4) | Re1(5) |
- | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
- |--------|--------|--------|--------|--------|
- | Re2(1) | Re2(2) | Re2(3) | Re2(4) | Re2(5) |
- | Im2(1) | Im2(2) | Im2(3) | Im2(4) | Im2(5) |
- |--------|--------|--------|--------|--------|
- | Re3(1) | Re3(2) | Re3(3) | Re3(4) | Re3(5) |
- | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
- |--------|--------|--------|--------|--------|
-
- After Second Dimension FFT:
- |--------|--------|--------|--------|--------|
- |Fr(1,1) |Fr(1,2) |Fr(1,3) |Fr(1,4) |Fr(1,5) |
- | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
- |--------|--------|--------|--------|--------|
- |Fr(2,1) |Fr(2,2) |Fr(2,3) |Fr(2,4) |Fr(2,5) |
- |Fi(2,1) |Fi(2,2) |Fi(2,3) |Fi(2,4) |Fi(2,5) |
- |--------|--------|--------|--------|--------|
- |Fr(3,1) |Fr(3,2) |Fr(3,3) |Fr(3,4) |Fr(3,5) |
- | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
- |--------|--------|--------|--------|--------|
-
- The Real ---> Complex FFTs store only the first half of the Fourier
- transform.
- For simplicity, the values corresponding to Frequency 0,and Nyquist
- (N/2 when is N is an even number), are treated as Complex numbers
- even though their imaginary part is ZERO.
- When processing the Lines of the matrix for the FFTs along the second
- dimension, all lines are then considered as Complex arrays.
-
- NOTE: when using a matrix MxN, depending on M (odd or even) the result
- is and (M+1)xN or (M+2)xN matrix.
-
- ---------------------------------
- | Fourier Transforms PRODUCT |
- ---------------------------------
-
- It is well known that the convolution of two sequences in the space domain
- is equivalent to the product of their Fourier transforms.
- For convenience, the following modules perform a "product" of 2 Fourier
- Transforms, one called "y", the second "filter".
-
-
- C :
-
- void cprod1d( int n, complex *y, int incy, complex *filter, int incx);
-
- void zprod1d( int n, complex *y, int incy, complex *filter, int incx);
-
- void sprod1du( int n, complex *y, int incy, complex *filter, int incx);
-
- void dprod1du( int n, complex *y, int incy, complex *filter, int incx);
-
- void cprod2d( int n1, int n2, complex *y,int ldy,
- complex *filter,int ldx);
-
- void zprod2d( int n1, int n2, zomplex *y,int ldy,
- zomplex *filter,int ldx);
-
- void sprod2du( int n1, int n2, float *y, int ldy,
- float *filter, int ldx);
-
- void dprod2du( int n1, int n2, double *y, int ldy,
- double *filter,int ldx);
-
- void cprod3d( int n1, int n2, int n3, complex *y, int ldy1, int ldy2,
- complex *filter, int ldx1, int ldx2);
-
- void zprod3d( int n1, int n2, int n3, complex *y, int ldy1, int ldy2,
- complex *filter, int ldx1, int ldx2);
-
- void sprod3du( int n1, int n2, int n3, complex *y, int ldy1, int ldy2,
- complex *filter, int ldx1, int ldx2);
-
- void dprod3du( int n1, int n2, int n3, complex *y, int ldy1, int ldy2,
- complex *filter, int ldx1, int ldx2);
-
-
- ---------------------------------
- | Fourier Transforms PRODUCT |
- ---------------------------------
-
- Fortran:
-
-
- subroutine CPROD1D( n, y, inca, filter, incf)
- integer n, inca, incf
- complex y(*), filter(*)
-
- subroutine ZPROD1D( n, y, inca, filter, incf)
- integer n, inca, incf
- double complex y(*), filter(*)
-
- subroutine SPROD1DU( n, y, inca, filter, incf)
- integer n, inca, incf
- real y(*), filter(*)
-
- subroutine DPROD1DU( n, y, inca, filter, incf)
- integer n, inca, incf
- double precision y(*), filter(*)
-
-
- subroutine CPROD2D( n1, n2, y, lda, filter, ldf)
- integer n1, n2, lda, ldf
- complex y(lda,*), filter(ldf,*)
-
- subroutine ZPROD2D( n1, n2, y, lda, filter, ldf)
- integer n1, n2, lda, ldf
- double complex y(lda,*), filter(ldf,*)
-
- subroutine SPROD2DU( n1, n2, y, lda, filter, ldf)
- integer n1, n2, lda, ldf
- real y(lda,*), filter(ldf,*)
-
- subroutine DPROD2DU( n1, n2, y, lda, filter, ldf)
- integer n1, n2, lda, ldf
- double precision y(lda,*), filter(ldf,*)
-
-
- subroutine CPROD3D( n1, n2, n3, y, ld1, ld2, filter, ldf1,ldf2)
- integer n1, n2, n3, ld1, ld2, ldf1, ldf2
- complex y(ld1,ld2,*), filter(ldf1,ldf2,*)
-
- subroutine ZPROD3D( n1, n2, n3, y, ld1, ld2, filter, ldf1,ldf2)
- integer n1, n2, n3, ld1, ld2, ldf1, ldf2
- double complex y(ld1,ld2,*), filter(ldf1,ldf2,*)
-
- subroutine SPROD3DU( n1, n2, n3, y, ld1,ld2, filter, ldf1,ldf2)
- integer n1, n2, n3, ld1, ld2, ldf1, ldf2
- real y(ld1,ld2,*), filter(ldf1,ldf2,*)
-
- subroutine DPROD3DU( n1, n2, n3, y, ld1,ld2, filter, ldf1,ldf2)
- integer n1, n2, n3, ld1, ld2, ldf1, ldf2
- double precision y(ld1,ld2,*), filter(ldf1,ldf2,*)
-
-
- -----------------------------------------
- | Fourier Transforms SCALING |
- -----------------------------------------
-
- The Fourier transforms of this library are not normalized, therefore after a
- double call ( direct_transform, inverse_transform), the original sequence
- is scaled by the total number of samples.
- To get absolute values, you need to scale back the result by
- alpha = 1/n_total
- Where
- n_total = N ... for 1D FFTs,
- n_total = N1 x N2 ... for 2D FFTs,
- n_total = N1 x N2 x N3 ... for 3D FFTs.
-
- C:
-
- void cscal1d( int n, float alpha, complex y, int inc);
- void zscal1d( int n, double alpha, zomplex y, int inc);
- void sscal1d( int n, float alpha, float y, int inc);
- void dscal1d( int n, double alpha, double y, int inc);
-
- void cscal2d( int nx, int ny, float alpha, complex y, int ld);
- void zscal2d( int nx, int ny, double alpha, zomplex y, int ld);
- void sscal2d( int nx, int ny, float alpha, float y, int ld);
- void dscal2d( int nx, int ny, double alpha, double y, int ld);
-
- void cscal3d( int nx, int ny, int nz, float alpha,
- complex y, int ld1,int ld2);
- void zscal3d( int nx, int ny, int nz, double alpha,
- zomplex y,int ld1,int ld2);
- void sscal3d( int nx, int ny, int nz, float alpha,
- float y, int ld1,int ld2);
- void dscal3d( int nx, int ny, int nz, double alpha,
- double y, int ld1,int ld2);
-
-
-
- Fortran:
-
- subroutine CSCAL1D( n, alpha, sequence, inc)
- integer n, inc
- complex sequence(*)
- real alpha
-
- subroutine ZSCAL1D( n, alpha, sequence, inc)
- integer n, inc
- double complex sequence(*)
- double precision alpha
-
- subroutine SSCAL1D( n, alpha, sequence, inc)
- integer n, inc
- real sequence(*), alpha
-
- subroutine DSCAL1D( n, alpha, sequence, inc)
- integer n, inc
- double precision sequence(*), alpha
-
-
- subroutine CSCAL2D( nx, ny, alpha, array, ld)
- integer nx ,ny, ld
- complex array(ld,*)
- real alpha
-
- subroutine ZSCAL2D( nx, ny, alpha, array, ld)
- integer nx ,ny, ld
- double complex array(ld,*)
- double precision alpha
-
- subroutine SSCAL2D( nx, ny, alpha, array, ld)
- integer nx ,ny, ld
- real array(ld,*), alpha
-
- subroutine DSCAL2D( nx, ny, alpha, array, ld)
- integer nx ,ny, ld
- double precision array(ld,*), alpha
-
-
- subroutine CSCAL3D( nx, ny, nz, alpha, array, ld1, ld2)
- integer nx ,ny, nz, ld1, ld2
- complex array(ld1,ld2,*)
- real alpha
-
- subroutine ZSCAL3D( nx, ny, nz, alpha, array, ld1, ld2)
- integer nx ,ny, nz, ld1, ld2
- double complex array(ld1,ld2,*)
- double precision alpha
-
- subroutine SSCAL3D( nx, ny, nz, alpha, array, ld1, ld2)
- integer nx ,ny, nz, ld1, ld2
- real array(ld1,ld2,*), alpha
-
- subroutine DSCAL3D( nx, ny, nz, alpha, array, ld1, ld2)
- integer nx ,ny, nz, ld1, ld2
- double precision array(ld1,ld2,*), alpha
-
- -----------------------------------------
- | REAL <---> COMPLEX *** PACKED |
- -----------------------------------------
-
-
-
- The modules described in the following pages, the PACKED FFTs, are
- kept for compatibility with the previous release.
-
- Various users experience proved these modules to be difficult to use,
-
- the "not_so_packed" modules described above are to be prefered !
- Both versions "packed" and "not_so_packed" have equivalent performances.
-
-
-
- OLD "packed" versions NEWER, SIMPLER, BETTER versions
-
- SFFT1DI, SFFT1D ---> SFFT1DUI, SFFT1DU
- DFFT1DI, DFFT1D ---> DFFT1DUI, DFFT1DU
-
- SFFT2DI, SFFT2D ---> SFFT2DUI, SFFT2DU
- DFFT2DI, DFFT2D ---> DFFT2DUI, DFFT2DU
-
- SFFT3DI, SFFT3D ---> SFFT3DUI, SFFT3DU
- DFFT3DI, DFFT3D ---> DFFT3DUI, DFFT3DU
-
-
-
- -----------------------------------------
- | REAL <---> COMPLEX *** PACKED |
- -----------------------------------------
-
- 1 DIMENSION :
- =============
-
- C :
- float *sfft1di( int n, float *workspace);
-
- double *dfft1di( int n, double *workspace);
-
- int sfft1d ( int job, int n, float *sequence,
- int inc, float *workspace);
-
- int dfft1d ( int job, int n, double *sequence,
- int inc, double *workspace);
-
- Fortran:
- subroutine SFFT1DI( n, workspace)
- integer n
- real workspace(*)
-
- subroutine DFFT1DI( n, workspace)
- integer n
- double precision workspace(*)
-
- subroutine SFFT1D( job, n, sequence, inc, workspace)
- integer job, n, inc
- real sequence(*), workspace(*)
-
- subroutine DFFT1D( job, n, sequence, inc, workspace)
- integer job, n, inc
- double precision sequence(*), workspace(*)
-
-
- "sfft1di", "dfft1di" IMPORTANT:
-
- The "workspace" array must be at least (N + 15) elements long.
- This array requires N elements for the Sines and Cosines
- + 15 elements for the factor decomposition of N.
-
- "sfft1d", "dfft1d"
-
- job = -1 or 1 for forward or backward Fast Fourier Transform
- n = number of elements in the 1 D FFT
- sequence = array containing the elements for the FFT
- inc = increment between two consecutive elements of the sequence
- workspace = Array containing the Sines/Cosines and factorization of N
- workspace needs to be initialized by a call to _fft1di
-
- NOTA BENE : The packed FFTs are done "in place"
-
- -----------------------------------------
- | REAL <---> COMPLEX *** PACKED |
- -----------------------------------------
-
- 1 DIMENSION :
- =============
-
- "csfft1d" or "zdfft1d":
-
- C:
- int csfft1d( int job,int n,float *sequence,
- int iof,int inc,float *workspace)
-
- int zdfft1d( int job,int n,double *sequence,
- int iof,int inc,double *workspace)
-
-
- Fortran:
- subroutine csfft1d( job, n, sequence, iof, inc, workspace)
- integer job, n, iof, inc
- complex sequence(*), workspace(*)
-
- subroutine zdfft1d( job, n, sequence, iof, inc, workspace)
- integer job, n, iof, inc
- double complex sequence(*), workspace(*)
-
-
- job = -1 or 1 for forward or backward Fast Fourier Transform
- n = number of complex elements of the 1 D FFT
- sequence = array containing the REAL values of a complex sequence
- iof = offset between the Imaginary and the Real value
- of a complex number
- inc = increment between two consecutive Real values of a sequence
- workspace = Array containing the Sines/Cosines and factorization of N
- workspace needs to be initialized by a call to _fft1di
-
- IMPORTANT: Theses routines must be used when the Imaginary part of a
- complex number does not follow immediately its Real part. They are
- more general than CFFT1D and ZFFT1D.
- call cfft1d( job, n, sequence, inc, workspace)
- is equivalent to:
- call csfft1d(( job, n, sequence, 1, 2*inc, workspace)
-
- CSFFT1D's workspace needs to be initialized by SFFT1DI.
- ZDFFT1D's workspace needs to be initialized by ZFFT1DI.
-
-
- -----------------------------------------
- | REAL <---> COMPLEX *** PACKED |
- -----------------------------------------
-
- 2 DIMENSIONS :
- ==============
-
- C :
- float *sfft2di( int n1, int n2, float *workspace)
-
- double *dfft2di( int n1, int n2, double *workspace)
-
- int sfft2d( int job, int n1, int n2, float *sequence,
- int lda, float *workspace)
-
- int dfft2d( int job, int n1, int n2, double *sequence,
- int lda, double *workspace)
-
- Fortran:
- subroutine SFFT2DI( n1, n2, workspace)
- integer n1, n2
- real workspace(*)
-
- subroutine DFFT2DI( n1, n2, workspace)
- integer n1, n2
- double precision workspace(*)
-
- subroutine SFFT2D( job, n1, n2, sequence, lda, workspace)
- integer job, n1, n2, lda
- real sequence(lda,*), workspace(*)
-
- subroutine DFFT2D( job, n1, n2, sequence, lda, workspace)
- integer job, n1, n2, lda
- double precision sequence(lda,*), workspace(*)
-
-
- "sfft2di", "dfft2di" IMPORTANT:
-
- the "workspace" array must be at least
- (N1 + 15 + 3 * (N2 + 15) ) elements long for Zfft2di and Cfft2di
- N1 elements are needed for the Sines and Cosines of the first dim.
- But we need the (2 * N2) for the second dimension ( COMPLEX ),
- and (1 * N2) for the second dimension ( REAL ),
- + 4 x 15 elements for the factorization of N1 and N2
-
-
- "sfft2d", "dfft2d" :
-
- job = -1 or 1 for forward or backward Fast Fourier Transform
- n1 = number of elements in the First Dimension of the Sequence
- n2 = number of elements in the Second Dimension of the Sequence
- sequence = Array containing the (lda*n2) elements for the FFT
- lda = Leading dimension for the Array, (lda >= n1 )
- workspace = Array containing the Sin/Cos and factorization of N1 and N2
- workspace needs to be initialized by a call to _fft2di
-
- NOTA BENE : The packed FFTs are done "in place"
-
- -----------------------------------------
- | REAL <---> COMPLEX *** PACKED |
- -----------------------------------------
-
- 3 DIMENSIONS :
- ==============
-
-
- C :
- float *sfft3di( int n1, int n2, int n3, float *workspace);
-
- double *dfft3di( int n1, int n2, int n3, double *workspace);
-
- int sfft3d( int job, int n1, int n2, int n3, float *sequence,
- int ld1, int ld2, float *workspace)
-
- int dfft3d( int job, int n1, int n2, int n3, double *sequence,
- int ld1, int ld2, double *workspace)
-
- Fortran:
-
- subroutine SFFT3DI( n1, n2, n3, workspace)
- integer n1, n2, n3
- real workspace(*)
-
- subroutine DFFT3DI( n1, n2, n3, workspace)
- integer n1, n2, n3
- double precision workspace(*)
-
- subroutine SFFT3D( job, n1, n2, n3, sequence, ld1, ld2, workspace)
- integer job, n1, n2, ld1, ld2
- real sequence(ld1,ld2,*), workspace(*)
-
- subroutine DFFT3D( job, n1, n2, n3, sequence, ld1, ld2, workspace)
- integer job, n1, n2, ld1, ld2
- double precision sequence(ld1,ld2,*), workspace(*)
-
-
- "sfft3di", "dfft3di" IMPORTANT:
-
- the "workspace" array must be at least
- (N1 + 15 + 3 * (N2 + 15) + 3*(N3 + 15) ) elements long for Zfft3di
- and Cfft3di this array needs
- N1+N2+N3 elements for the Sines and Cosines (REAL)
- 2*N2 + 2*N3 for the sines (COMPLEX)
- + 7 x 15 elements for the factorization of N1, N2 and N3.
-
-
- "sfft3d", "dfft3d" :
-
- job = -1 or 1 for forward or backward Fast Fourier Transform
- n1,n2,n3 = number of elements in the First, Second and Third
- Dimension of the Sequence
- sequence = Array containing the (ld1*ld2*n3) elements for the FFT
- ld1, ld2 = Leading dimensions for the Array,
- (ld1 >= 2*((n1+2)/2) and ld2 >= n2)
- workspace = Array containing the Sin/Cos and factorization of N1, N2, N3
- workspace needs to be initialized by a call to _fft3di
-
- NOTA BENE : The packed FFTs are done "in place"
-
-
- -----------------------------------------
- | REAL <---> COMPLEX *** PACKED |
- -----------------------------------------
-
- 1 DIMENSION :
- ==============
-
- Given a sequence a(j), j = 0, ..., n-1 of N real samples,
- and B(I) its (complex) FFT.
-
- Only the first half of the FFT need to be computed, the second half can be
- deduced by symmetry : B(I) = Conjugate { B(N-I) }.
-
- example n = 5 :
- ---------------
- a0 a1 a2 a3 a4
- B0r,B0i B1r,B1i B2r,B2i B3r,B3i B4r,B4i
-
- B0i = 0 <--- Frequence 0
- B4r = B1r, B4i = - B1i
- B3r = B2r, B3i = - B2i
-
- the output from SFFT1D or DFFT1D will be:
-
- B0r, B1r,B1i, B2r,B2i
-
- example n = 4 :
- ---------------
- a0 a1 a2 a3
- B0r,B0i B1r,B1i B2r,B2i B3r,B3i
-
- B0i = 0 <--- Frequence 0
- B2i = 0 <--- Nyquist's Frequence (N/2)
- B3r = B1r, B3i = - B1i
-
- Once PACKED, the output from SFFT1D or DFFT1D will be:
-
- B0r, B1r,B1i, B2r
-
- *****
- PLEASE note that the first value (and the last when N is even )is real,
- while the others are complex numbers.
-
- -----------------------------------------
- | REAL <---> COMPLEX *** PACKED |
- -----------------------------------------
-
- 2 DIMENSIONS :
- ==============
-
- Original Real Array(lda,5) --- N1 = 4 and N2 = 5:
- |--------|--------|--------|--------|--------|
- | f(1,1) | f(1,2) | f(1,3) | f(1,4) | f(1,5) |
- |--------|--------|--------|--------|--------|
- | f(2,1) | f(2,2) | f(2,3) | f(2,4) | f(2,5) |
- |--------|--------|--------|--------|--------|
- | f(3,1) | f(3,2) | f(3,3) | f(3,4) | f(3,5) |
- |--------|--------|--------|--------|--------|
- | f(4,1) | f(4,2) | f(4,3) | f(4,4) | f(4,5) |
- |--------|--------|--------|--------|--------|
-
- After First Dimension Real FFT:
- |--------|--------|--------|--------|--------|
- | Re1(1) | Re1(2) | Re1(3) | Re1(4) | Re1(5) |
- |--------|--------|--------|--------|--------|
- | Re2(1) | Re2(2) | Re2(3) | Re2(4) | Re2(5) |
- | Im2(1) | Im2(2) | Im2(3) | Im2(4) | Im2(5) |
- |--------|--------|--------|--------|--------|
- | Re3(1) | Re3(2) | Re3(3) | Re3(4) | Re3(5) |
- |--------|--------|--------|--------|--------|
-
- After Second Dimension FFT:
- |--------|-----------------|-----------------|
- | F(1,1) | F(1,2) F(1,3) | F(1,4) F(1,5) |
- |--------|--------|--------|--------|--------|
- | F(2,1) | F(2,2) | F(2,3) | F(2,4) | F(2,5) |
- | F(3,1) | F(3,2) | F(3,3) | F(3,4) | F(3,5) |
- |--------|-----------------|-----------------|
- | F(4,1) | F(4,2) F(4,3) | F(4,4) F(4,5) |
- |--------|--------|--------|--------|--------|
-
- The FIRST and LAST line FFT is a REAl FFT (SFFT1D) --- N=5 and INC=lda.
- Note that F(1,2) and F(1,3) are respectively the real and imaginary part of
- the same complex number.
- call SFFT1D( -1, 5, array(1,1), lda, workspace)
- call SFFT1D( -1, 5, array(4,1), lda, workspace)
-
- Lines 2 and 3 use a Complex FFT (CSFFT1D) --- N=5 , IOF=1, INC=lda.
- In this case CSFFT1D has to be called since lda may not be an even number.
- call CSFFT1D( -1, 5, array(2,1), 1, lda, workspace)
-
- -----------------------------------------
- | REAL <---> COMPLEX *** PACKED |
- -----------------------------------------
-
- 2 DIMENSIONS :
- ==============
-
- Real(8x8) <--> Complex FFT OUTPUT:
-
- Let's start with a real Array F(0:7,0:7):
-
- |-----------------------------------------------------------------------|
- | F(0,0) | F(0,1) | F(0,2) | F(0,3) | F(0,4) | F(0,5) | F(0,6) | F(0,7) |
- |________|________|________|________|________|________|________|________|
- | F(1,0) | F(1,1) | F(1,2) | F(1,3) | F(1,4) | F(1,5) | F(1,6) | F(1,7) |
- |________|________|________|________|________|________|________|________|
- | F(2,0) | F(2,1) | F(2,2) | F(2,3) | F(2,4) | F(2,5) | F(2,6) | F(2,7) |
- |________|________|________|________|________|________|________|________|
- | F(3,0) | F(3,1) | F(3,2) | F(3,3) | F(3,4) | F(3,5) | F(3,6) | F(3,7) |
- |________|________|________|________|________|________|________|________|
- | F(4,0) | F(4,1) | F(4,2) | F(4,3) | F(4,4) | F(4,5) | F(4,6) | F(4,7) |
- |________|________|________|________|________|________|________|________|
- | F(5,0) | F(5,1) | F(5,2) | F(5,3) | F(5,4) | F(5,5) | F(5,6) | F(5,7) |
- |________|________|________|________|________|________|________|________|
- | F(6,0) | F(6,1) | F(6,2) | F(6,3) | F(6,4) | F(6,5) | F(6,6) | F(6,7) |
- |________|________|________|________|________|________|________|________|
- | F(7,0) | F(7,1) | F(7,2) | F(7,3) | F(7,4) | F(7,5) | F(7,6) | F(7,7) |
- |________|________|________|________|________|________|________|________|
-
- Now After the First FFT (along columns) ...
-
- |-----------------------------------------------------------------------|
- | R(0,0) | R(0,1) | R(0,2) | R(0,3) | R(0,4) | R(0,5) | R(0,6) | R(0,7) |
- |________|________|________|________|________|________|________|________|
- | R(1,0) | R(1,1) | R(1,2) | R(1,3) | R(1,4) | R(1,5) | R(1,6) | R(1,7) |
- |________|________|________|________|________|________|________|________|
- | I(1,0) | I(1,1) | I(1,2) | I(1,3) | I(1,4) | I(1,5) | I(1,6) | I(1,7) |
- |________|________|________|________|________|________|________|________|
- | R(2,0) | R(2,1) | R(2,2) | R(2,3) | R(2,4) | R(2,5) | R(2,6) | R(2,7) |
- |________|________|________|________|________|________|________|________|
- | I(2,0) | I(2,1) | I(2,2) | I(2,3) | I(2,4) | I(2,5) | I(2,6) | I(2,7) |
- |________|________|________|________|________|________|________|________|
- | R(3,0) | R(3,1) | R(3,2) | R(3,3) | R(3,4) | R(3,5) | R(3,6) | R(3,7) |
- |________|________|________|________|________|________|________|________|
- | I(3,0) | I(3,1) | I(3,2) | I(3,3) | I(3,4) | I(3,5) | I(3,6) | I(3,7) |
- |________|________|________|________|________|________|________|________|
- | R(4,0) | R(4,1) | R(4,2) | R(4,3) | R(4,4) | R(4,5) | R(4,6) | R(4,7) |
- |________|________|________|________|________|________|________|________|
-
- Where R(i,j) represents the Real part of the 1D FFTs, and I(i,j) the
- imaginary part.
-
- After the second Direction FFTs (along lines) the final result is:
-
- |-----------------------------------------------------------------------|
- | R(0,0) | R(0,1) | I(0,1) | R(0,2) | I(0,2) | R(0,3) | I(0,3) | R(0,4) |
- |________|________|________|________|________|________|________|________|
- | R(1,0) | R(1,1) | R(1,2) | R(1,3) | R(1,4) | R(1,5) | R(1,6) | R(1,7) |
- |________|________|________|________|________|________|________|________|
- | I(1,0) | I(1,1) | I(1,2) | I(1,3) | I(1,4) | I(1,5) | I(1,6) | I(1,7) |
- |________|________|________|________|________|________|________|________|
- | R(2,0) | R(2,1) | R(2,2) | R(2,3) | R(2,4) | R(2,5) | R(2,6) | R(2,7) |
- |________|________|________|________|________|________|________|________|
- | I(2,0) | I(2,1) | I(2,2) | I(2,3) | I(2,4) | I(2,5) | I(2,6) | I(2,7) |
- |________|________|________|________|________|________|________|________|
- | R(3,0) | R(3,1) | R(3,2) | R(3,3) | R(3,4) | R(3,5) | R(3,6) | R(3,7) |
- |________|________|________|________|________|________|________|________|
- | I(3,0) | I(3,1) | I(3,2) | I(3,3) | I(3,4) | I(3,5) | I(3,6) | I(3,7) |
- |________|________|________|________|________|________|________|________|
- | R(4,0) | R(4,1) | I(4,1) | R(4,2) | I(4,2) | R(4,3) | I(4,3) | R(4,4) |
- |________|________|________|________|________|________|________|________|
-
- Suppose You want to UNPACK this result in (5x8) Complex Matrix to get a
- result equivalent to SPROD2D , you would fill it up like this:
-
- |-----------------------------------------------------------------------|
- | R(0,0) | R(0,1) | R(0,2) | R(0,3) | R(0,4) | r(0,3) | r(0,2) | r(0,1) |
- | 0. | I(0,1) | I(0,2) | I(0,3) | 0. |-i(0,3) |-i(0,2) |-i(0,1) |
- |________|________|________|________|________|________|________|________|
- | R(1,0) | R(1,1) | R(1,2) | R(1,3) | R(1,4) | R(1,5) | R(1,6) | R(1,7) |
- | I(1,0) | I(1,1) | I(1,2) | I(1,3) | I(1,4) | I(1,5) | I(1,6) | I(1,7) |
- |________|________|________|________|________|________|________|________|
- | R(2,0) | R(2,1) | R(2,2) | R(2,3) | R(2,4) | R(2,5) | R(2,6) | R(2,7) |
- | I(2,0) | I(2,1) | I(2,2) | I(2,3) | I(2,4) | I(2,5) | I(2,6) | I(2,7) |
- |________|________|________|________|________|________|________|________|
- | R(3,0) | R(3,1) | R(3,2) | R(3,3) | R(3,4) | R(3,5) | R(3,6) | R(3,7) |
- | I(3,0) | I(3,1) | I(3,2) | I(3,3) | I(3,4) | I(3,5) | I(3,6) | I(3,7) |
- |________|________|________|________|________|________|________|________|
- | R(4,0) | R(4,1) | R(4,2) | R(4,3) | R(4,4) | r(4,3) | r(4,2) | r(4,1) |
- | 0. | I(4,1) | I(4,2) | I(4,3) | 0. |-i(4,3) |-i(4,2) |-i(4,1) |
- |________|________|________|________|________|________|________|________|
-
- The UPPER case (R & I) represent original values, while the lower case (r & i)
- represent redundant data that can be deduced from symmetries.
-
- |------------------|
- | 3 Dimensions |
- |------------------|
-
- Complex <--> Complex FFT OUTPUT:
-
- Real <--> Complex FFT OUTPUT:
-
- 1)- 2 D FFTs are first performed along the First and Second direction
- ( see above the Real <---> Complex FFT OUTPUT in the 2 D case) for
- each XY slice.
- 2)- The third dimension FFT is then performed.
-
- There is no real problem for the Complex YZ slices. However the First
- (and Last if N1 is even) YZ slices need to be carefully explained.
-
- Suppose a N1x5x4 FFT, the first XY slice, indexes (1,j,k) will look like
- the following after the First 2 Dimensions FFTs:
- |----------|---------------------|---------------------|
- | F(1,1,1) | F(1,2,1) F(1,3,1) | F(1,4,1) F(1,5,1) |
- |----------|---------------------|---------------------|
- | F(1,1,2) | F(1,2,2) F(1,3,2) | F(1,4,2) F(1,5,2) |
- |----------|---------------------|---------------------|
- | F(1,1,3) | F(1,2,3) F(1,3,3) | F(1,4,3) F(1,5,3) |
- |----------|---------------------|---------------------|
- | F(1,1,4) | F(1,2,4) F(1,3,4) | F(1,4,4) F(1,5,4) |
- |----------|---------------------|---------------------|
-
- after the third Dimension FFT, the array wil finally be:
- |----------|---------------------|---------------------|
- | G(1,1,1) | G(1,2,1) G(1,3,1) | G(1,4,1) G(1,5,1) |
- |----------|---------------------|---------------------|
- | G(1,1,2) | G(1,2,2) G(1,3,2) | G(1,4,2) G(1,5,2) |
- | |---------------------|---------------------|
- | G(1,1,3) | G(1,2,3) G(1,3,3) | G(1,4,3) G(1,5,3) |
- |----------|---------------------|---------------------|
- | G(1,1,4) | G(1,2,4) G(1,3,4) | G(1,4,4) G(1,5,4) |
- |----------|---------------------|---------------------|
-
- This is actually achieved through 1 call to SFFT1D and 2 Calls to CSFFT1D:
-
- call SFFT1D( -1, n3, F(1,1,1), ld1*ld2, workspace)
- call CSFFT1D( -1, n3, F(1,2,1), ld1, ld1*ld2, workspace)
- call CSFFT1D( -1, n3, F(1,4,1), ld1, ld1*ld2, workspace)
-