具有复数的 C++ FFTW(快速傅里叶变换)

C++ FFTW (fast fourier transforms) with complex numbers

我正在尝试在 C++ 中对复数使用 FFT。问题是当使用 fftw_complex 数字时,我无法生成内积或具有共同语法的复杂向量的总和。

这里是一个简化的简单程序:

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


int main(void){

int n=1024;
    fftw_complex *in, *out;
    fftw_plan p;

    in = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * n);
    out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * n);
//  out = 1*in;   /!\
//  out = in+0;  / ! \

    p = fftw_plan_dft_1d(n, in, out, FFTW_FORWARD, FFTW_ESTIMATE);

    fftw_execute(p); /* repeat as needed */

    fftw_destroy_plan(p);
    fftw_free(in); fftw_free(out);

    return 0;
}

注释的两行不起作用:

i) 第一个在编译时给出:

test.cpp:13:10: error: invalid operands of types ‘int’ and ‘fftw_complex* {aka __complex__ double*}’ to binary ‘operator*’

ii) 第二个在执行期间给出:

*** glibc detected *** ./prog: corrupted double-linked list: 0x09350030 ***

根据 fftw.org [link] 的文档,应该接受用于操作 fftw_complex 的标准语法。为什么不使用 fftw_complex 的向量?

例如,我想计算:

r = i*gamma_p*w/w0*m*exp(-l*z);

其中i是虚数; gamma_p、w0、z为实数; w、m 和 l 是复数向量。

我试过了:

    fftw_complex* i_NUMBER = (fftw_complex*) fftw_malloc(1*sizeof(fftw_complex));
memset(i_NUMBER, 0, n*sizeof(fftw_complex));
    i_NUMBER[0][0]=0;
    i_NUMBER[0][1]=1;   //#real(i_NUMBER)=0; imag(i_NUMBER)=1; i.e. i_NUMBER=i;
fftw_complex* r = (fftw_complex*) fftw_malloc(n*sizeof(fftw_complex));

for (int i=0; i<n; i++){
    r[i] = i_NUMBER[0]*gamma_p*w[i]/w0*m[i]*pow(e_NUMBER, -l[i]*z);
}

但是编译器给出了关于操作数和操作类型的错误。

gnlse.h:58:22: error: invalid operands of types ‘fftw_complex {aka double [2]}’ and ‘double’ to binary ‘operator*’
gnlse.h:58:61: error: wrong type argument to unary minus

欢迎任何帮助,谢谢!

您必须编写显式循环才能使用向量。

out = in+0;会产生两个指向同一位置的指针。当你释放它两次时,你会得到损坏的堆

更新

我想我知道可能是什么问题。默认 FFTW 模式是 C89。使用复数的自动计算几乎需要 C99 模式或使用 <complex> header 的 C++。我猜你选择了一些例子,修改了它并想知道为什么它不起作用。

在 C89 模式下 fftw_complex 只是一个双精度 [2]。因此,C89 模式下的任何表达式都需要对实部和虚部进行大量手动处理,这正是我所建议的。不能混入表达式 coerced-to-pointer 复杂和双精度、函数并期望自动处理。

在 C99 模式下,您可以获得原生复合体,这使得在表达式中使用它们成为 C89 的真正享受。

C++ 本机复合体应该也能正常工作。

有关详细说明,请参阅 http://www.fftw.org/doc/Complex-numbers.html

我猜您现在实际上处于 C89 模式。您必须使用 C99 编译示例(通常在 linux /usr/bin/c99 上),或者移动到 C++ 并沿线使用 C++ 原生复杂

#include <complex>

...

std::complex<double>* in  = new std::complex<double>[n];
std::complex<double>* out = new std::complex<double>[n];
...
p = fftw_plan_dft_1d(n,
                     reinterpret_cast<fftw_complex*>(in),
                     reinterpret_cast<fftw_complex*>(out),
                     FFTW_FORWARD, FFTW_ESTIMATE);
...