2016-01-12 2 views
0

J'essaie d'utiliser FFT avec des nombres complexes en C++. Le problème est que je ne peux pas faire des produits internes, ou des sommes de vecteurs complexes avec un sintax commun, en utilisant des nombres fftw_complex.C++ FFTW (transformées de Fourier rapides) avec des nombres complexes

Voici un programme simple réduit:

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

Les deux lignes qui sont commentées ne fonctionnent pas:

i) la 1ère donne, lors de la compilation:

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

ii) le 2e donne, au cours de l'exécution:

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

Conformément à la documentation de fftw.org [link], sintax standard pour la manipulation de fftw_complex devrait être accepté. Pourquoi pas avec les vecteurs de fftw_complex?

Par exemple, je veux calculer:

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

où i est le nombre imaginaire; gamma_p, w0 et z sont des nombres réels; w, m et l sont des vecteurs de nombres complexes.

J'ai essayé:

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

mais le compilateur donne des erreurs sur les types d'opérandes et des opérations.

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 

Toute aide est la bienvenue, merci!

+0

les lignes: \t * out = (* dans) +1; \t * out = (* in) +0; résoudre le 1er problème. –

+0

qu'en est-il du 2e script? –

+0

C n'est pas C++ n'est pas C. Ne pas ajouter de balises non liées. – Olaf

Répondre

0

Vous devez écrire des boucles explicites pour travailler avec des vecteurs.

La ligne out = in+0; produira deux pointeurs pointant vers le même emplacement. Lorsque vous DEALLOCATION deux fois, vous obtiendrez tas corrompu

MISE À JOUR

Je pense que je sais ce problème pourrait être. Le mode FFTW par défaut est C89. Les calculs automatiques avec des nombres complexes nécessitent à peu près le mode C99 ou C++ en utilisant l'en-tête <complex>. Je suppose que vous avez choisi un exemple, l'avez modifié et vous vous demandez pourquoi cela ne fonctionne pas.

En mode C89, fftw_complex est juste un double [2]. Donc, toute expression en mode C89 nécessite une manipulation manuelle de la partie réelle et imag, juste ce que j'ai proposé. Ne peut pas mélanger dans le complexe d'expression coerced-to-pointer et double, fonctionne et attend une gestion automatique.

En mode C99, vous pouvez obtenir un complexe natif qui rend le travail avec eux dans l'expression un vrai traitement par C89.

Le complexe natif C++ devrait également fonctionner.

Voir http://www.fftw.org/doc/Complex-numbers.html pour une description détaillée.

Je suppose que vous êtes maintenant en mode C89.Vous devez compiler l'exemple soit avec C99 (généralement sous linux/usr/bin/C99), ou passer à C++ et utiliser C++ complexe natif le long de la ligne

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

même avec une boucle, certaines opérations provoquent des erreurs - cela peut être vu dans la dernière partie de mon message ... –

+0

@sissi_luaty Je crois que vous devez écrire un code séparé pour real (indexé par 0) et imag (indexé par 1) les pièces. Dans le 'i_NUMBER [0] * gamma_p' le premier argument est 2d double array, qui est contraint au pointeur, et second argument est juste un double nombre. Le compilateur ne peut pas déduire comment multiplier le pointeur par le double –

+0

J'essaie r [i] [0] = real (...); r [i] [1] = imag (...); mais le compilateur ne peut pas faire les maths –