具有复杂数组的指针数学

时间:2017-10-25 17:33:33

标签: c arrays fftw

我有一些代码片段带有一些指针数学,我无法理解:

#include <stdlib.h>
#include <complex.h>
#include <fftw3.h>

int main(void)
{
    int i, j, k;
    int N, N2;
    fftwf_complex *box;
    fftwf_plan plan;
    float *smoothed_box;

    // Allocate memory for arrays (Ns are set elsewhere and properly,
    // I've just left it out for clarity)
    box = (fftwf_complex *)fftwf_malloc(N * sizeof(fftwf_complex));
    smoothed_box = (float *)malloc(N2 * sizeof(float));

    // Create complex data and fill box with it. Do FFT. Box has the
    // Hermitian symmetry that complex data has when doing FFTs with 
    // real data
    plan = fftwf_plan_dft_c2r_3d(N,N,N,box,(float *)box,
         FFTW_ESTIMATE);
    ...

    // end fft

    // Now do the loop I don't understand
    for(i = 0; i < N2; i++)
    {
        for(j = 0; j < N2; j++)
        {
            for(k = 0; k < N2; k++)
            {
                smoothed_box[R_INDEX(i,j,k)] = *((float *)box + 
                    R_FFT_INDEX(i*f + 0.5, j*f + 0.5, k*f +0.5))/V;
            }
        }
    }

    // Do other stuff
    ...

    return 0;
}

其中f和V只是在代码中其他地方设置的一些数字,对于这个特定问题无关紧要。此外,函数R_FFT_INDEX和R_INDEX也无关紧要。重要的是,对于第一次循环迭代,当i = j = k = 0时,R_INDEX = 0且R_FFT_INDEX = 45。 smoothed_box有8个元素,box有320个。

所以,在gdb中,当我在循环后打印smoothed_box [0]时,我得到了smoothed_box [0] =某个数字。现在,我理解,对于一个普通类型的数组,比如浮点数,数组+整数将给出数组[整数],假设整数在数组的范围内。

但是,fftwf_complex被定义为typedef float fftw_complex [2],因为你需要同时保存复数的实部和虚部。它也被从fftwf_complex *转换为float *,鉴于typedef,我不确定这是做什么的。

我所知道的是,当我在gdb中打印框[45]时,我得到框[45] =某个复数不是smoothed_box [0] * V.即使我打印*((float *)框+ 45)/ V,我得到的数字与smoothed_box [0]不同。

所以,我只是想知道是否有人能向我解释上述循环中正在进行的指针数学运算?谢谢,我感谢你的时间!

1 个答案:

答案 0 :(得分:1)

box被分配为N fftwf_complex的数组。然后在N,N,N上执行使用box的后向3D c2r fftw变换,需要N*N*(N/2+1) fftwf_complex。请参阅http://www.fftw.org/fftw3_doc/Real_002ddata-DFT-Array-Format.html#Real_002ddata-DFT-Array-Format因此,此代码可能会在到达指针算术之前触发未定义的行为,例如分段错误......

box转换回float数组是切实可行的,因为DFT是在适当的位置执行的。实际上,在创建fftwf_plan时使用box两次。 box既是复数的输入数组又是真实的输出数组:

plan = fftwf_plan_dft_c2r_3d(N,N,N,box,(float *)box,
     FFTW_ESTIMATE);

调用fftwf_execute(plan);后,box最好被视为真实数组。然而,该阵列的大小为N*N*2*(N/2+1),其中位于位置i,j,k的项目,其中k> N-1是无意义的。见FFTW's Real-data DFT Array Format

  

对于就地变换,由于复杂数据略大于实际数据,因此会出现一些复杂情况。在这种情况下,实际数据的最终维度必须用额外的值填充以适应复杂数据的大小 - 如果最后一个维度是偶数则为两个额外值,如果是奇数则为一个。也就是说,实际数据的最后一个维度必须在物理上包含2 *(nd-1/2 + 1)个双精度值(足以保存复杂数据)。但是,此物理数组大小不会更改逻辑数组大小 - 仅nd-1值实际存储在最后一个维度中,而nd-1是传递给计划程序的最后一个维度。

这就是为什么引入了真实数组smoothed_box的原因,尽管期望有一个N*N*N数组。如果smoothed_box是一个大小为N*N*N的数组,则可以执行以下转换:

for(i=0;i<N;i++){
  for(j=0;j<N;j++){
    for(k=0;k<N;k++){
     smoothed_box[(i*N+j)*N+k]=((float *)box)[(i*N+j)*(2*(N/2+1))+k]
    }
  }
}