2
我想计算3D FFT
使用Intel MKL
的数组,其具有约300×200×200
元素。这种3D数组存储为double
类型的纵列方式一维数组:使用带有零填充的英特尔MKL的3D FFT
for(int k = 0; k < nk; k++) // Loop through the height.
for(int j = 0; j < nj; j++) // Loop through the rows.
for(int i = 0; i < ni; i++) // Loop through the columns.
{
ijk = i + ni * j + ni * nj * k;
my3Darray[ ijk ] = 1.0;
}
我要输入阵列上执行not-in-place
FFT和防止屏幕修改(我需要在我的代码后使用它)然后进行反向计算in-place
。我也想要零填充。
我的问题是:
- 我怎么能执行零填充?
- 在计算中包含零填充时,我应该如何处理
FFT
函数使用的数组大小? - 如何取出零填充结果并获得实际结果?
这里是我对这个问题的尝试,我会绝对感谢的任何评论,建议或提示。
#include <stdio.h>
#include "mkl.h"
int max(int a, int b, int c)
{
int m = a;
(m < b) && (m = b);
(m < c) && (m = c);
return m;
}
void FFT3D_R2C(// Real to Complex 3D FFT.
double *in, int nRowsIn , int nColsIn , int nHeightsIn ,
double *out)
{
int n = max(nRowsIn , nColsIn , nHeightsIn );
// Round up to the next highest power of 2.
unsigned int N = (unsigned int) n; // compute the next highest power of 2 of 32-bit n.
N--;
N |= N >> 1;
N |= N >> 2;
N |= N >> 4;
N |= N >> 8;
N |= N >> 16;
N++;
/* Strides describe data layout in real and conjugate-even domain. */
MKL_LONG rs[4], cs[4];
// DFTI descriptor.
DFTI_DESCRIPTOR_HANDLE fft_desc = 0;
// Variables needed for out-of-place computations.
MKL_Complex16 *in_fft = new MKL_Complex16 [ N*N*N ];
MKL_Complex16 *out_fft = new MKL_Complex16 [ N*N*N ];
double *out_ZeroPadded = new double [ N*N*N ];
/* Compute strides */
rs[3] = 1; cs[3] = 1;
rs[2] = (N/2+1)*2; cs[2] = (N/2+1);
rs[1] = N*(N/2+1)*2; cs[1] = N*(N/2+1);
rs[0] = 0; cs[0] = 0;
// Create DFTI descriptor.
MKL_LONG sizes[] = { N, N, N };
DftiCreateDescriptor(&fft_desc, DFTI_DOUBLE, DFTI_REAL, 3, sizes);
// Configure DFTI descriptor.
DftiSetValue(fft_desc, DFTI_CONJUGATE_EVEN_STORAGE, DFTI_COMPLEX_COMPLEX);
DftiSetValue(fft_desc, DFTI_PLACEMENT, DFTI_NOT_INPLACE ); // Out-of-place transformation.
DftiSetValue(fft_desc, DFTI_INPUT_STRIDES , rs );
DftiSetValue(fft_desc, DFTI_OUTPUT_STRIDES , cs );
DftiCommitDescriptor(fft_desc);
DftiComputeForward (fft_desc, in , in_fft );
// Change strides to compute backward transform.
DftiSetValue (fft_desc, DFTI_INPUT_STRIDES , cs);
DftiSetValue (fft_desc, DFTI_OUTPUT_STRIDES, rs);
DftiCommitDescriptor(fft_desc);
DftiComputeBackward (fft_desc, out_fft, out_ZeroPadded);
// Printing the zero padded 3D FFT result.
for(long long i = 0; i < (long long)N*N*N; i++)
printf("%f\n", out_ZeroPadded[i]);
/* I don't know how to take out the zero padded results and
save the actual result in the variable named "out" */
DftiFreeDescriptor (&fft_desc);
delete[] in_fft;
delete[] out_ZeroPadded ;
}
int main()
{
int n = 10;
double *a = new double [n*n*n]; // This array is real.
double *afft = new double [n*n*n];
// Fill the array with some 'real' numbers.
for(int i = 0; i < n*n*n; i++)
a[ i ] = 1.0;
// Calculate FFT.
FFT3D_R2C(a, n, n, n, afft);
printf("FFT results:\n");
for(int i = 0; i < n*n*n; i++)
printf("%15.8f\n", afft[i]);
delete[] a;
delete[] afft;
return 0;
}