简体   繁体   中英

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

I am trying to use FFT with complex numbers in C++. The problem is that I cannot make inner products, or sums of complex vectors with a common sintax, when using fftw_complex numbers.

Here is a reduced simple program:

#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;
}

The two lines that are commented do not work:

i) the 1st one gives, when compiling:

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

ii) the 2nd one gives, during the execution:

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

Accordingly to the documentation of fftw.org [link] , standard sintax for manipulating fftw_complex should be accepted. Why not with vectors of fftw_complex?

For instance, I want to compute:

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

where i is the imaginary number; gamma_p, w0, and z are real numbers; w, m, and l are vectors of complex numbers.

I tried:

    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);
}

but the compiler gives errors about the types of operands and operations.

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

Any help is welcome, thanks!

You have to write explicit loops to works with vectors.

Line out = in+0; will produce two pointer pointing to the same location. When you deallocation it twice, you'll get corrupted heap

UPDATE

I think I know what problem might be. Default FFTW mode is C89. Automatic computations with complex numbers pretty much require either C99 mode or C++ using <complex> header. I would guess you picked some example, modified it and wondering why it doesn't work.

In C89 mode fftw_complex is just a double[2]. So any expression in C89 mode requires pretty much manual handling of the real and imag part, just what I proposed. Cannot mix in expression coerced-to-pointer complex and doubles, functions and expect automatic handling.

In C99 mode you could get native complex which makes working with them in expression a real treat wrt C89.

C++ native complex should work as well.

See http://www.fftw.org/doc/Complex-numbers.html for a detailed description.

My guess you're now effectively in C89 mode. You have to compile the example either with C99 (typically on linux /usr/bin/c99), or move to C++ and use C++ native complex along the line

#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);
...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM