d@0: d@0:
d@0:d@0: d@0: d@0: Next: More DFTs of Real Data, d@0: Previous: One-Dimensional DFTs of Real Data, d@0: Up: Tutorial d@0:
Multi-dimensional DFTs of real data use the following planner routines: d@0: d@0:
fftw_plan fftw_plan_dft_r2c_2d(int n0, int n1, d@0: double *in, fftw_complex *out, d@0: unsigned flags); d@0: fftw_plan fftw_plan_dft_r2c_3d(int n0, int n1, int n2, d@0: double *in, fftw_complex *out, d@0: unsigned flags); d@0: fftw_plan fftw_plan_dft_r2c(int rank, const int *n, d@0: double *in, fftw_complex *out, d@0: unsigned flags); d@0:d@0:
d@0: as well as the corresponding c2r
routines with the input/output
d@0: types swapped. These routines work similarly to their complex
d@0: analogues, except for the fact that here the complex output array is cut
d@0: roughly in half and the real array requires padding for in-place
d@0: transforms (as in 1d, above).
d@0:
d@0:
As before, n
is the logical size of the array, and the
d@0: consequences of this on the the format of the complex arrays deserve
d@0: careful attention.
d@0: Suppose that the real data has dimensions n0 × n1 × n2 × … × nd-1 (in row-major order).
d@0: Then, after an r2c transform, the output is an n0 × n1 × n2 × … × (nd-1/2 + 1) array of
d@0: fftw_complex
values in row-major order, corresponding to slightly
d@0: over half of the output of the corresponding complex DFT. (The division
d@0: is rounded down.) The ordering of the data is otherwise exactly the
d@0: same as in the complex-DFT case.
d@0:
d@0:
Since the complex data is slightly larger than the real data, some
d@0: complications arise for in-place transforms. In this case, the final
d@0: dimension of the real data must be padded with extra values to
d@0: accommodate the size of the complex data—two values if the last
d@0: dimension is even and one if it is odd.
d@0: That is, the last dimension of the real data must physically contain
d@0: 2 * (nd-1/2+1)double
values (exactly enough to hold the complex data).
d@0: This physical array size does not, however, change the logical
d@0: array size—only
d@0: nd-1values are actually stored in the last dimension, and
d@0: nd-1is the last dimension passed to the plan-creation routine.
d@0:
d@0:
For example, consider the transform of a two-dimensional real array of
d@0: size n0
by n1
. The output of the r2c transform is a
d@0: two-dimensional complex array of size n0
by n1/2+1
, where
d@0: the y
dimension has been cut nearly in half because of
d@0: redundancies in the output. Because fftw_complex
is twice the
d@0: size of double
, the output array is slightly bigger than the
d@0: input array. Thus, if we want to compute the transform in place, we
d@0: must pad the input array so that it is of size n0
by
d@0: 2*(n1/2+1)
. If n1
is even, then there are two padding
d@0: elements at the end of each row (which need not be initialized, as they
d@0: are only used for output).
d@0:
d@0:
The following illustration depicts the input and output arrays just d@0: described, for both the out-of-place and in-place transforms (with the d@0: arrows indicating consecutive memory locations): d@0: d@0:
These transforms are unnormalized, so an r2c followed by a c2r
d@0: transform (or vice versa) will result in the original data scaled by
d@0: the number of real data elements—that is, the product of the
d@0: (logical) dimensions of the real data.
d@0:
d@0: (Because the last dimension is treated specially, if it is equal to
d@0: 1
the transform is not equivalent to a lower-dimensional
d@0: r2c/c2r transform. In that case, the last complex dimension also has
d@0: size 1
(=1/2+1
), and no advantage is gained over the
d@0: complex transforms.)
d@0:
d@0:
d@0:
d@0: