Chris@19: Chris@19: Chris@19: Multi-Dimensional DFTs of Real Data - FFTW 3.3.4 Chris@19: Chris@19: Chris@19: Chris@19: Chris@19: Chris@19: Chris@19: Chris@19: Chris@19: Chris@19: Chris@19: Chris@19: Chris@19: Chris@19:
Chris@19: Chris@19: Chris@19:

Chris@19: Next: , Chris@19: Previous: One-Dimensional DFTs of Real Data, Chris@19: Up: Tutorial Chris@19:


Chris@19:
Chris@19: Chris@19:

2.4 Multi-Dimensional DFTs of Real Data

Chris@19: Chris@19:

Multi-dimensional DFTs of real data use the following planner routines: Chris@19: Chris@19:

     fftw_plan fftw_plan_dft_r2c_2d(int n0, int n1,
Chris@19:                                     double *in, fftw_complex *out,
Chris@19:                                     unsigned flags);
Chris@19:      fftw_plan fftw_plan_dft_r2c_3d(int n0, int n1, int n2,
Chris@19:                                     double *in, fftw_complex *out,
Chris@19:                                     unsigned flags);
Chris@19:      fftw_plan fftw_plan_dft_r2c(int rank, const int *n,
Chris@19:                                  double *in, fftw_complex *out,
Chris@19:                                  unsigned flags);
Chris@19: 
Chris@19:

Chris@19: as well as the corresponding c2r routines with the input/output Chris@19: types swapped. These routines work similarly to their complex Chris@19: analogues, except for the fact that here the complex output array is cut Chris@19: roughly in half and the real array requires padding for in-place Chris@19: transforms (as in 1d, above). Chris@19: Chris@19:

As before, n is the logical size of the array, and the Chris@19: consequences of this on the the format of the complex arrays deserve Chris@19: careful attention. Chris@19: Suppose that the real data has dimensions n0 × n1 × n2 × … × nd-1 (in row-major order). Chris@19: Then, after an r2c transform, the output is an n0 × n1 × n2 × … × (nd-1/2 + 1) array of Chris@19: fftw_complex values in row-major order, corresponding to slightly Chris@19: over half of the output of the corresponding complex DFT. (The division Chris@19: is rounded down.) The ordering of the data is otherwise exactly the Chris@19: same as in the complex-DFT case. Chris@19: Chris@19:

For out-of-place transforms, this is the end of the story: the real Chris@19: data is stored as a row-major array of size n0 × n1 × n2 × … × nd-1 and the complex Chris@19: data is stored as a row-major array of size n0 × n1 × n2 × … × (nd-1/2 + 1). Chris@19: Chris@19:

For in-place transforms, however, extra padding of the real-data array Chris@19: is necessary because the complex array is larger than the real array, Chris@19: and the two arrays share the same memory locations. Thus, for Chris@19: in-place transforms, the final dimension of the real-data array must Chris@19: be padded with extra values to accommodate the size of the complex Chris@19: data—two values if the last dimension is even and one if it is odd. Chris@19: That is, the last dimension of the real data must physically contain Chris@19: 2 * (nd-1/2+1)double values (exactly enough to hold the complex data). Chris@19: This physical array size does not, however, change the logical Chris@19: array size—only Chris@19: nd-1values are actually stored in the last dimension, and Chris@19: nd-1is the last dimension passed to the plan-creation routine. Chris@19: Chris@19:

For example, consider the transform of a two-dimensional real array of Chris@19: size n0 by n1. The output of the r2c transform is a Chris@19: two-dimensional complex array of size n0 by n1/2+1, where Chris@19: the y dimension has been cut nearly in half because of Chris@19: redundancies in the output. Because fftw_complex is twice the Chris@19: size of double, the output array is slightly bigger than the Chris@19: input array. Thus, if we want to compute the transform in place, we Chris@19: must pad the input array so that it is of size n0 by Chris@19: 2*(n1/2+1). If n1 is even, then there are two padding Chris@19: elements at the end of each row (which need not be initialized, as they Chris@19: are only used for output). Chris@19: Chris@19:

The following illustration depicts the input and output arrays just Chris@19: described, for both the out-of-place and in-place transforms (with the Chris@19: arrows indicating consecutive memory locations): Chris@19: rfftwnd-for-html.png Chris@19: Chris@19:

These transforms are unnormalized, so an r2c followed by a c2r Chris@19: transform (or vice versa) will result in the original data scaled by Chris@19: the number of real data elements—that is, the product of the Chris@19: (logical) dimensions of the real data. Chris@19: Chris@19: Chris@19:

(Because the last dimension is treated specially, if it is equal to Chris@19: 1 the transform is not equivalent to a lower-dimensional Chris@19: r2c/c2r transform. In that case, the last complex dimension also has Chris@19: size 1 (=1/2+1), and no advantage is gained over the Chris@19: complex transforms.) Chris@19: Chris@19: Chris@19: Chris@19: