复数数组的FFT

时间:2015-01-01 22:32:14

标签: c complex-numbers fftw

使用FFTW,我想执行复数数组的IFFT,从文件" numbers.txt"中读取数据。 (它们以a + b * I的格式存储,每行一个复数)。我尝试了以下内容,但它不起作用:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <math.h>
#include <complex.h>
#include <fftw3.h>

int main(void)
{
fftw_complex *in;
fftw_complex *out;
float re,im;
int size;

printf("Insert size");
scanf("%d", &size);

FILE *file = fopen("numbers.txt", "r");

int i=0;

while(fscanf(file, "%f+%fi", &re, &im) > 0) {
in[i]=re+im*I;
i++;
}
fclose(file);

 fftw_complex *out_cpx;

 fftw_plan ifft;
 out_cpx = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*size);
 out = (double *) malloc(size*sizeof(double));

 ifft = fftw_plan_dft_c2r_1d(size, out_cpx, out, FFTW_ESTIMATE);   //Setup fftw plan 

 fftw_execute(ifft);

 printf("Input:    \tOutput:\n");
 for(i=0;i<size;i++)
 {
 printf("%f\t%f\n",(in[i]),out[i]);
 }

 fftw_destroy_plan(ifft);
 fftw_free(out_cpx);
 free(out);


 return 0;
 }

样本输入是(每行一个数字):

0+0*I
0.01198+-0.0825632*I
1.32139e-05+1.94777e-05*I 
-1.18289e-11+7.30045e-12*I 
2.71773e-20+0*I 
-1.18289e-11+-7.30045e-12*I 
1.32139e-05+-1.94777e-05*I 
0.01198+0.0825632*I

特别是,我在从文件中读取数据时遇到了问题。有人有什么建议吗?提前致谢

编辑:

经过一些改进之后,我现在正在使用这个经过修改的代码:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <math.h>
#include <complex.h>
#include <fftw3.h>


 int main(void)
{
fftw_complex *in;
fftw_complex *out;
double re,im;
int size;
int i=0;
FILE *file;
fftw_plan ifft;

printf("Insert size");
if (scanf("%d", &size) != 1 || size < 1)
    return 1;

in = fftw_malloc(sizeof(*in)*size);
out = fftw_malloc(sizeof(*out)*size);

file = fopen("numbers.txt", "r");

for (i = 0; i < size && fscanf(file, "%lf+%lf*I\n", &re, &im) == 2; i++)
{
    in[i]= re+im*I;
}

fclose(file);
// Error if i != size?


ifft = fftw_plan_dft_1d(size, in, out, FFTW_BACKWARD, FFTW_ESTIMATE);

fftw_execute(ifft);

printf("Input:    \tOutput:\n");
for(i=0; i<size; i++)
{
printf("%lf+%lfI\t%lf+%lfI\n", creal(in[i]), cimag(in[i]), creal(out[i]), cimag(out[i]));
}

fftw_destroy_plan(ifft);
fftw_free(in);
fftw_free(out);
//free(out);

return 0;
}

现在的问题是我总是得到一个实值变换的数组。我该如何解决?

3 个答案:

答案 0 :(得分:3)

你有几个问题。 fftw_plan_dft_c2r_1d的调用顺序如下:

  

逆变换将复杂输入(存储逻辑Hermitian数组的非冗余半部分)转换为实际输出,由下式给出:

 fftw_plan fftw_plan_dft_c2r_1d(int n0,
                                fftw_complex *in, double *out,
                                unsigned flags);

因此,您有以下问题:

  1. 您永远不会分配fftw_complex *in数组。它应该是

    in = fftw_malloc(sizeof(*in)*size);
    // And later
    fftw_free(in);
    
  2. 不需要in_cpx,因为in很复杂。

  3. 建议fftw_malloc使用out

  4. fftw_complex具有双精度,因此reim也应如此。

  5. 您的printf will not work for C99 complex numbers

  6. 检查scanf和fscanf的返回值。

  7. 更新如上面的chux所述,当i&gt; = size时突破循环。另外,检查以确保循环完成时i == size。

  8. 我没有c99可用,因此我无法访问新的built-in complex type,但修复可能看起来像(未经过测试):

    int main(void)
    {
        fftw_complex *in;
        double *out;
        double re,im;
        int size;
        int i=0;
        FILE *file;
        fftw_plan ifft;
    
        printf("Insert size");
        if (scanf("%d", &size) != 1 || size < 1)
            return 1;
    
        in = fftw_malloc(sizeof(*in)*size);
        out = fftw_malloc(sizeof(*out)*size);
    
        file = fopen("numbers.txt", "r");
    
        for (i = 0; i < size && fscanf(file, "%lf+%lf*I\n", &re, &im) == 2; i++)
        {
            in[i]= re + im*I;
        }
    
        fclose(file);
        // Error if i != size?
    
        ifft = fftw_plan_dft_c2r_1d(size, in, out, FFTW_ESTIMATE);   //Setup fftw plan 
    
        fftw_execute(ifft);
    
        printf("Input:    \tOutput:\n");
        for(i=0; i<size; i++)
        {
            printf("%lf+i%lf\t%lf\n", creal(in[i]), cimag(in[i]), out[i]);
        }
    
        fftw_destroy_plan(ifft);
        fftw_free(in);
        fftw_free(out);
    
        return 0;
    }
    

答案 1 :(得分:1)

printf("%f\t%f\n",(in[i]),out[i]);

必须是

printf("%f + %f j\t%f + %f j\n", in[i][0], in[i][1], out[i][0], out[i][1]);

因为fftw_complex只是

typedef double fftw_complex[2];

答案 2 :(得分:1)

  1. 代码没有为输入分配内存(这是主要问题)

    fftw_complex *in;
    ...
    in = malloc(size * sizeof *in); 
    // or
    in = calloc(size, sizeof *in);
    ...
    in[i]=re+im*I;
    ...
    free(in);
    
  2. while循环应检查== 2而不是> 0。还添加了空格以允许复数的间距。如果不起作用,建议OP提供样本输入。

    // while(fscanf(file, "%f+%fi", &re, &im) > 0) {
    while(fscanf(file, "%f +%f i", &re, &im) == 2) { 
    
  3. 代码不会在循环i == size之后检查。

  4. 建议更轻松地编码和维护malloc()样式:

    // out_cpx = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*size);
    out_cpx = fftw_malloc(size * sizeof *out_cpx);
    
    // out = (double *) malloc(size*sizeof(double));
    out = malloc(size * sizeof *out);
    
  5. 替代格式可能提供更多信息

    // printf("%f\t%f\n",(in[i]),out[i]);
    printf("%e\t%e\n",(in[i]),out[i]);
    
  6. 强大的代码会检查scanf("%d", &size);malloc()的返回值。

  7. 重新格式化代码会使其更容易理解。