scfft2d(3S)
SCFFT2D, DZFFT2D, CSFFT2D, ZDFFT2D - Applies a two-dimensional real-to- complex or complex-to-real Fast Fourier Transform (FFT)
Showing IRIX 6.5.30 (default release). Added in IRIX 6.5.15.
NAME SCFFT2D, DZFFT2D, CSFFT2D, ZDFFT2D - Applies a two-dimensional real-to- complex or complex-to-real Fast Fourier Transform (FFT) SYNOPSIS Single precision -> Single precision complex Fortran: CALL SCFFT2D (isign, n1, n2, scale, x, ldx, y, ldy, table, work, isys) C/C++: #include <scsl_fft.h> int scfft2d (int isign, int n1, int n2, float scale, float *x, int ldx, scsl_complex *y, int ldy, float *table, float *work, int *isys); C++ STL: #include <complex.h> #include <scsl_fft.h> int scfft2d (int isign, int n1, int n2, float scale, float *x, int ldx, complex<float> *y, int ldy, float *table, float *work, int *isys); Double precision -> Double precision complex Fortran: CALL DZFFT2D (isign, n1, n2, scale, x, ldx, y, ldy, table, work, isys) C/C++: #include <scsl_fft.h> int dzfft2d (int isign, int n1, int n2, double scale, double *x, int ldx, scsl_zomplex *y, int ldy, double *table, double *work, int *isys); C++ STL: #include <complex.h> #include <scsl_fft.h> int dzfft2d (int isign, int n1, int n2, double scale, double *x, int ldx, complex<double> *y, int ldy, double *table, double *work, int *isys); Single precision complex -> Single precision Fortran: CALL CSFFT2D (isign, n1, n2, scale, x, ldx, y, ldy, table, work, isys) C/C++: #include <scsl_fft.h> int csfft2d (int isign, int n1, int n2, float scale, scsl_complex *x, int ldx, float *y, int ldy, float *table, float *work, int *isys); C++ STL: #include <complex.h> #include <scsl_fft.h> int csfft2d (int isign, int n1, int n2, float scale, complex<float> *x, int ldx, float *y, int ldy, float *table, float *work, int *isys); Double precision complex -> Double precision Fortran: CALL ZDFFT2D (isign, n1, n2, scale, x, ldx, y, ldy, table, work, isys) C/C++: #include <scsl_fft.h> int zdfft2d (int isign, int n1, int n2, double scale, scsl_zomplex *x, int ldx, double *y, int ldy, double *table, double *work, int *isys); C++ STL: #include <complex.h> #include <scsl_fft.h> int zzfft2d (int isign, int n1, int n2, double scale, complex<double> *x, int ldx, double *y, int ldy, double *table, double *work, int *isys); IMPLEMENTATION These routines are part of the SCSL Scientific Library and can be loaded using either the -lscs or the -lscs_mp option. The -lscs_mp option directs the linker to use the multi-processor version of the library. When linking to SCSL with -lscs or -lscs_mp, the default integer size is 4 bytes (32 bits). Another version of SCSL is available in which integers are 8 bytes (64 bits). This version allows the user access to larger memory sizes and helps when porting legacy Cray codes. It can be loaded by using the -lscs_i8 option or the -lscs_i8_mp option. A program may use only one of the two versions; 4-byte integer and 8-byte integer library calls cannot be mixed. The C and C++ prototypes shown above are appropriate for the 4-byte integer version of SCSL. When using the 8-byte integer version, the variables of type int become long long and the <scsl_fft_i8.h> header file should be included. DESCRIPTION SCFFT2D/DZFFT2D computes the two-dimensional Fast Fourier Transform (FFT) of the real matrix X, and it stores the results in the complex matrix Y. CSFFT2D/ZDFFT2D computes the corresponding inverse transform. In FFT applications, it is customary to use zero-based subscripts; the formulas are simpler that way. First the function of SCFFT2D is described. Suppose the arrays are declared as follows: Fortran: REAL X(0:ldx-1, 0:n2-1) COMPLEX Y(0:ldy-1, 0:n2-1) C/C++: float x[n2][ldx]; scsl_complex y[n2][ldy]; C++ STL: float x[n2][ldx]; complex<float> y[n2][ldy]; where ldx >= n1, ldy >= (n1/2) + 1. SCFFT2D computes the formula: n2-1 n1-1 Y(k1, k2) = scale * Sum Sum [ X(j1, j2)*w1**(j1*k1)*w2**(j2*k2) ] j2=0 j1=0 for k1 = 0, ..., n1/2 + 1 k2 = 0, ..., n2-1 where: w1 = exp(isign*2*pi*i/n1) w2 = exp(isign*2*pi*i/n2) i = + sqrt(-1) pi = 3.14159..., isign = +1 or -1 Different authors use different conventions for which of the transforms, isign = +1 or isign = -1, is the forward or inverse transform, and what the scale factor should be in either case. You can make these routines compute any of the various possible definitions, however, by choosing the appropriate values for isign and scale. The relevant fact from FFT theory is this: If you take the FFT with any particular values of isign and scale, the mathematical inverse function is computed by taking the FFT with -isign and 1/(n1 * n2 * scale). In particular, if you use isign = +1 and scale = 1.0 for the forward FFT, you can compute the inverse FFT by using isign = -1 and scale = 1.0/(n1 * n2). SCFFT2D is very similar in function to CCFFT2D, but it takes the real- to-complex transform in the first dimension, followed by the complex-to-complex transform in the second dimension. CSFFT2D does the reverse. It takes the complex-to-complex FFT in the second dimension, followed by the complex-to-real FFT in the first dimension. See the INTRO_FFT(3S) man page for more information about real-to-complex and complex-to-real FFTs. The two-dimensional analog of the conjugate formula is as follows: Yk1, k2 = conjg Y n1 - k1, n2 - k2 for n1/2 < k1 <= n1 - 1 0 <= k2 <= n2 - 1 where the notation conjg(z) represents the complex conjugate of z. Thus, you have to compute only (slightly more than) half of the output values, namely: Yk1, k2 for 0 <= k1 <= n1/2 0 <= k2 <= n2 - 1 See the NOTES section of this man page for information about the interpretation of the data types described in the following arguments. These routines have the following arguments: isign Integer. (input) Specifies whether to initialize the table array or to do the forward or inverse Fourier transform, as follows: If isign = 0, the routine initializes the table array and returns. In this case, the only arguments used or checked are isign, n1, n2, and table. If isign = +1 or -1, the value of isign is the sign of the exponent used in the FFT formula. n1 Integer. (input) Transform size in the first dimension. If n1 is not positive, the routine returns without calculating a transform. n2 Integer. (input) Transform size in the second dimension. If n2 is not positive, the routine returns without calculating a transform. scale Scale factor. (input) SCFFT2D: Single precision. DZFFT2D: Double precision. CSFFT2D: Single precision. ZDFFT2D: Double precision. Each element of the output array is multiplied by scale factor after taking the Fourier transform, as defined previously. x Array of dimensions (ldx, n2). (input) SCFFT2D: Single precision array. DZFFT2D: Double precision array. CSFFT2D: Single precision complex array. ZDFFT2D: Double precision complex array. Array of values to be transformed. ldx Integer. (input) The number of rows in the x array, as it was declared in the calling program. That is, the leading dimension of x. SCFFT2D, DZFFT2D: ldx >= MAX(n1, 1). CSFFT2D, ZDFFT2D: ldx >= MAX(n1/2 + 1, 1). y Array of dimension (ldy, n2). (output) SCFFT2D: Single precision complex array. DZFFT2D: Double precision complex array. CSFFT2D: Single precision array. ZDFFT2D: Double precision array. Output array of transformed values. The output array can be the same as the input array, in which case, the transform is done in place and the input array is overwritten with the transformed values. In this case, it is necessary that the following equalities hold: SCFFT2D, DZFFT2D: ldx = 2 * ldy. CSFFT2D, ZDFFT2D: ldy = 2 * ldx. ldy Integer. (input) The number of rows in the y array, as it was declared in the calling program (the leading dimension of y). SCFFT2D, DZFFT2D: ldy >= MAX(n1/2 + 1, 1). CSFFT2D, ZDFFT2D: ldy >= MAX(n1 + 2, 1). In the complex-to-real routine, two extra elements are in the first dimension (ldy >= n1 + 2, rather than just ldy >= n1). These elements are needed for intermediate storage during the computation. On exit, their value is undefined. table Array of dimension (n1 + NFR) + (2 * n2 + NF) (input or output) SCFFT2D, CSFFT2D: Single precision array DZFFT2D, ZDFFT2D: Double precision array Table of factors and roots of unity. See the description of the isys argument for the value of NF and NFR. If isign = 0, the routine initializes table (table is output only). If isign = +1 or -1, the values in table are assumed to be initialized already by a prior call with isign = 0 (table is input only). work Array of dimension n1 + 4 * n2 SCFFT2D, CSFFT2D: Single precision array DZFFT2D, ZDFFT2D: Double precision array Work array. This is a scratch array used for intermediate calculations. Its address space must be different from that of the input and output arrays. isys Integer array dimensioned 0..isys(0). An array that gives implementation-specific information. All features and functions of the FFT routines specific to any particular implementation are confined to this isys array. In the Origin series implementation, isys(0)=0 and isys(0)=1 are supported. In SCSL versions prior to 1.3, only isys(0)=0 was allowed. For isys(0)=0, NF=30 and NFR=15, and for isys(0)=1, NF=NFR=256. The NF(R) words of storage in the table array contain a factorization of the length of the transform. The smaller value of NF and NFR for isys(0)=0 is historical. They are too small to store all the required factors for the highest performing FFT, so when isys(0)=0, extra space is allocated when the table array is initialized. To avoid memory leaks, this extra space must be deallocated when the table array is no longer needed. The SCFFT2DF routine is used to release this memory. Due to the potential for memory leaks, the use of isys(0)=0 should be avoided. For isys(0)=1, the value of NF and NFR are large enough so that no extra memory needs to be allocated, and there is no need to call SCFFT2DF to release memory. If called, it does nothing. NOTE: isys(0)=1 means that isys is an integer array with two elements. The second element, isys(1), will not be accessed. NOTES The following data types are described in this documentation: Term Used Data type Fortran: Array dimensioned 0..n-1 x(0:n-1) Array of dimensions (m,n) x(m,n) Array of dimensions (m,n,p) x(m,n,p) Integer INTEGER (INTEGER*8 for -lscs_i8[_mp]) Single precision REAL Double precision DOUBLE PRECISION Single precision complex COMPLEX Double precision complex DOUBLE COMPLEX C/C++: Array dimensioned 0..n-1 x[n] Array of dimensions (m,n) x[m*n] or x[n][m] Array of dimensions (m,n,p) x[m*n*p] or x[p][n][m] Integer int (long long for -lscs_i8[_mp]) Single precision float Double precision double Single precision complex scsl_complex Double precision complex scsl_zomplex C++ STL: Array dimensioned 0..n-1 x[n] Array of dimensions (m,n) x[m*n] or x[n][m] Array of dimensions (m,n,p) x[m*n*p] or x[p][n][m] Integer int (long long for -lscs_i8[_mp]) Single precision float Double precision double Single precision complex complex<float> Double precision complex complex<double> CAUTIONS Transform sizes with a prime factor exceeding 232-1 are not supported for the 8-byte integer version of the library. In addition to the work array, the FFT routines also dynamically allocate scratch space from the stack. The amount of space allocated can be slightly bigger than the size of the largest processor cache. For single processor runs, the default stack size is large enough that these allocations generally cause no problems. But for parallel runs, you need to ensure that the stack size of slave threads is big enough to hold this scratch space. Failure to reserve sufficient stack space will cause programs to dump core due to stack overflows. The stack size of MP library slave threads is controlled via the MP_SLAVE_STACKSIZE environment variable or the mp_set_slave_stacksize() library routine. See the mp(3C), mp(3F) and pe_environ(5) reference pages for more information on controlling the slave stack size. For pthreads applications, the thread's stack size is specified as one of many creation attributes provided in the pthread_attr_t argument to pthread_create(3P). The stacksize attribute should be set explicitly to a non-default value using the pthread_attr_setstacksize(3P) call, described in the pthread_attr_init(3P) man page. Care must be exercised if copies of the table array are used: even though a copy exists, the original must persist. As an example, the following code will not work: #include <scsl_fft.h> float x[256][129]; scsl_complex y[256][65]; float table[(128 + 256) + (2*256 + 256)]; float work[128 + 4*256]; int isys[2]; isys[0] = 1; { float table_orig[(128 + 256) + (2*256 + 256)]; scfft2d(0, 128, 256, 1.0f, (float *) x, 129, (scsl_complex *) y, 65, table_orig, work, isys); bcopy(table_orig, table, ((128+256)+(2*256+256))*sizeof(float)); } scfft2d(1, 128, 256, 1.0f, (float *) x, 129, (scsl_complex *) y, 65, table, work, isys); In this example, because table_orig is a stack variable that does not persist outside of the code block delimited by the braces, the data in the copy, table, are not guaranteed to be valid. However, the following code will work because table_orig is persistent: #include <scsl_fft.h> float x[256][129]; scsl_complex y[256][65]; float table_orig[(128 + 256) + (2*256 + 256)]; float table[(128 + 256) + (2*256 + 256)]; float work[128 + 4*256]; int isys[2]; isys[0] = 1; scfft2d(0, 128, 256, 1.0f, (float *) x, 129, (scsl_complex *) y, 65, table_orig, work, isys); bcopy(table_orig, table, ((128+256)+(2*256+256))*sizeof(float)); scfft2d(1, 128, 256, 1.0f, (float *) x, 129, (scsl_complex *) y, 65, table, work, isys); EXAMPLES The following examples are for Origin series only. Example 1: Initialize the TABLE array in preparation for doing a two- dimensional FFT of size 128 by 256. In this case, only the isign, n1, n2, and table arguments are used; you can use dummy arguments or zeros for other arguments. Fortran: REAL TABLE ((128 + 256) + (2*256 + 256)) INTEGER ISYS(0:1) ISYS(0) = 1 CALL SCFFT2D (0, 128, 256, 0.0, DUMMY, 1, DUMMY, 1, & TABLE, DUMMY, ISYS) Example 2: X is an array dimensioned (0...128, 0...255), and Y is a complex array dimensioned (0...64, 0...255). The first 128 elements of each column of X contain data; for performance reasons, the extra element forces the leading dimension to be an odd number. Take the two-dimensional FFT of X and store it in Y. Initialize the TABLE array, as in example 1. Fortran: REAL X(0:128, 0:255) COMPLEX Y(0:64, 0:255) REAL TABLE ((128 + 256) + (2*256 + 256)) REAL WORK(128 + 4*256) INTEGER ISYS(0:1) ISYS(0) = 1 CALL SCFFT2D(0, 128, 256, 1.0, X, 129, Y, 65, TABLE, WORK, ISYS) CALL SCFFT2D(1, 128, 256, 1.0, X, 129, Y, 65, TABLE, WORK, ISYS) C/C++: #include <scsl_fft.h> float x[256][129]; scsl_complex y[256][65]; float table[(128 + 256) + (2*256 + 256)]; float work[128 + 4*256]; int isys[2]; isys[0] = 1; scfft2d(0, 128, 256, 1.0f, (float *) x, 129, (scsl_complex *) y, 65, table, work, isys); scfft2d(1, 128, 256, 1.0f, (float *) x, 129, (scsl_complex *) y, 65, table, work, isys); C++ STL: #include <complex.h> #include <scsl_fft.h> float x[256][129]; complex<float> y[256][65]; float table[(128 + 256) + (2*256 + 256)]; float work[128 + 4*256]; int isys[2]; isys[0] = 1; scfft2d(0, 128, 256, 1.0f, (float *) x, 129, (complex<float> *) y, 65, table, work, isys); scfft2d(1, 128, 256, 1.0f, (float *) x, 129, (complex<float> *) y, 65, table, work, isys); Example 3: Take the inverse FFT of Y and store it back in X. Note that the leading dimension of X must be increased to 2 * ldy. The scale factor 1.0/(128.0*256.0) is used. Fortran: REAL X(0:129, 0:255) COMPLEX Y(0:64, 0:255) ... CALL CSFFT2D(-1, 128, 256, 1.0/(128.0*256.0), Y, 65, & X, 130, TABLE, WORK, ISYS) C/C++: float x[256][129]; scsl_complex y[256][65]; csfft2d(-1, 128, 256, 1.0f/(128.0f*256.0f), (scsl_complex *) y, 65, (float *) x, 130, table, work, isys); C++ STL: float x[256][129]; complex<float> y[256][65]; csfft2d(-1, 128, 256, 1.0f/(128.0f*256.0f), (complex<float> *) y, 65, (float *) x, 130, table, work, isys); Example 4: Perform the same computation as in example 2, but equivalence the input and output arrays to save storage space. In this case, a row must be added to X, because it is equivalenced to a complex array. Use the 8-byte integer version of SCSL. Fortran: REAL X(0:129, 0:255) COMPLEX Y(0:64, 0:255) EQUIVALENCE ( X(0, 0), Y(0, 0) ) REAL TABLE ((128 + 256) + (2*256 + 256)) REAL WORK(128 + 4*256) INTEGER*8 ISYS(0:1) ISYS(0) = 1_8 CALL SCFFT2D(0_8, 128_8, 256_8, 1.0, X, 130_8, & Y, 65_8, TABLE, WORK, ISYS) CALL SCFFT2D(1_8, 128_8, 256_8, 1.0, X, 130_8, & Y, 65_8, TABLE, WORK, ISYS) C/C++: #include <scsl_fft_i8.h> float *x; scsl_complex y[256][65]; float table[(128 + 256) + (2*256 + 256)]; float work[128 + 4*256]; long long isys[2]; isys[0] = 1LL; x = (float *) &y[0][0]; scfft2d(0LL, 128LL, 256LL, 1.0f, x, 130LL, (scsl_complex *) y, 65LL, table, work, isys); scfft2d(1LL, 128LL, 256LL, 1.0f, x, 130LL, (scsl_complex *) y, 65LL, table, work, isys); C++ STL: #include <complex.h> #include <scsl_fft.h> float *x; complex<float> y[256][65]; float table[(128 + 256) + (2*256 + 256)]; float work[128 + 4*256]; long long isys[2]; isys[0] = 1LL; x = (float *) &y[0][0]; scfft2d(0LL, 128LL, 256LL, 1.0f, x, 130LL, (complex<float> *) y, 65LL, table, work, isys); scfft2d(1LL, 128LL, 256LL, 1.0f, x, 130LL, (complex<float> *) y, 65LL, table, work, isys); Example 5: Perform the same computation as in example 2, but assume that the lower bound of each Fortran array is 1, rather than 0. No change is needed in the subroutine calls. Fortran: REAL X(129, 256) COMPLEX Y(65, 256) CALL SCFFT2D(0, 128, 256, 1.0, X, 129, Y, 65, TABLE, WORK, ISYS) CALL SCFFT2D(1, 128, 256, 1.0, X, 129, Y, 65, TABLE, WORK, ISYS) SEE ALSO INTRO_FFT(3S), INTRO_SCSL(3S), CCFFT(3S), CCFFT2D(3S), CCFFT3D(3S), CCFFTM(3S), SCFFT(3S), SCFFT3D(3S), SCFFTM(3S)