#### 4.4.1 Advanced Complex DFTs ¶

    fftw_plan fftw_plan_many_dft(int rank, const int *n, int howmany,
                                 fftw_complex *in, const int *inembed,
                                 int istride, int idist,
                                 fftw_complex *out, const int *onembed,
                                 int ostride, int odist,
                                 int sign, unsigned flags);

This routine plans multiple multidimensional complex DFTs, and it extends the `fftw_plan_dft` routine (see Complex DFTs) to compute `howmany` transforms, each having rank `rank` and size `n`. In addition, the transform data need not be contiguous, but it may be laid out in memory with an arbitrary stride. To account for these possibilities, `fftw_plan_many_dft` adds the new parameters `howmany`, {`i`,`o`}`nembed`, {`i`,`o`}`stride`, and {`i`,`o`}`dist`. The FFTW basic interface (see Complex DFTs) provides routines specialized for ranks 1, 2, and 3, but the advanced interface handles only the general-rank case.

`howmany` is the (nonnegative) number of transforms to compute. The resulting plan computes `howmany` transforms, where the input of the `k`-th transform is at location `in+k*idist` (in C pointer arithmetic), and its output is at location `out+k*odist`. Plans obtained in this way can often be faster than calling FFTW multiple times for the individual transforms. The basic `fftw_plan_dft` interface corresponds to `howmany=1` (in which case the `dist` parameters are ignored).

Each of the `howmany` transforms has rank `rank` and size `n`, as in the basic interface. In addition, the advanced interface allows the input and output arrays of each transform to be row-major subarrays of larger rank-`rank` arrays, described by `inembed` and `onembed` parameters, respectively. {`i`,`o`}`nembed` must be arrays of length `rank`, and `n` should be elementwise less than or equal to {`i`,`o`}`nembed`. Passing `NULL` for an `nembed` parameter is equivalent to passing `n` (i.e. same physical and logical dimensions, as in the basic interface).

The `stride` parameters indicate that the `j`-th element of the input or output arrays is located at `j*istride` or `j*ostride`, respectively. (For a multi-dimensional array, `j` is the ordinary row-major index.) When combined with the `k`-th transform in a `howmany` loop, from above, this means that the (`j`,`k`)-th element is at `j*stride+k*dist`. (The basic `fftw_plan_dft` interface corresponds to a stride of 1.)

For in-place transforms, the input and output `stride` and `dist` parameters should be the same; otherwise, the planner may return `NULL`.

Arrays `n`, `inembed`, and `onembed` are not used after this function returns. You can safely free or reuse them.

Examples: One transform of one 5 by 6 array contiguous in memory:

       int rank = 2;
       int n[] = {5, 6};
       int howmany = 1;
       int idist = odist = 0; /* unused because howmany = 1 */
       int istride = ostride = 1; /* array is contiguous in memory */
       int *inembed = n, *onembed = n;

Transform of three 5 by 6 arrays, each contiguous in memory, stored in memory one after another:

       int rank = 2;
       int n[] = {5, 6};
       int howmany = 3;
       int idist = odist = n[0]*n[1]; /* = 30, the distance in memory
                                         between the first element
                                         of the first array and the
                                         first element of the second array */
       int istride = ostride = 1; /* array is contiguous in memory */
       int *inembed = n, *onembed = n;

Transform each column of a 2d array with 10 rows and 3 columns:

       int rank = 1; /* not 2: we are computing 1d transforms */
       int n[] = {10}; /* 1d transforms of length 10 */
       int howmany = 3;
       int idist = odist = 1;
       int istride = ostride = 3; /* distance between two elements in
                                     the same column */
       int *inembed = n, *onembed = n;