2010-11-18 8 views
12

Il manuale FFTW says che il suo tipo fftw_complex è bit compatibile con la classe std::complex<double> in AWL. Ma questo non funziona per me:Problema di colata Complesso STL <double> a fftw_complex

#include <complex> 
#include <fftw3.h> 
int main() 
{ 
    std::complex<double> x(1,0); 
    fftw_complex fx; 
    fx = reinterpret_cast<fftw_complex>(x); 
} 

Questo mi dà un errore:

error: invalid cast from type ‘std::complex<double>’ to type ‘double [2]’ 

Che cosa sto facendo di sbagliato?

risposta

8

Ri-scrivere il codice come segue:

#include <complex> 
#include <fftw3.h> 
int main() 
{ 
    std::complex<double> x(1,0); 
    fftw_complex fx; 
    memcpy(&fx, &x, sizeof(fftw_complex)); 
} 

Ogni compilatore che ho usato ottimizzerà il memcpy perché sta copiando un fisso, vale a dire al momento della compilazione, quantità di dati.

Ciò evita pointer aliasing issues.

Edit: È anche possibile evitare severi problemi di aliasing utilizzando un'unione come segue:

#include <complex> 
#include <fftw3.h> 
int main() 
{ 
    union stdfftw 
    { 
     std::complex<double> stdc; 
     fftw_complex   fftw; 
    }; 
    std::complex<double> x(1,0); 
    stdfftw u; 
    u.stdc = x; 
    fftw_complex fx = u.fftw; 
} 

Anche se strettamente queste regole C99 (non è sicuro su C++) sono rotti come la lettura da un diverso membro di un sindacato a quello scritto anche non è definito. Funziona sulla maggior parte dei compilatori però. Personalmente preferisco il mio metodo originale.

+0

Ok, questo funziona per me! 3 anni non codifica in pura C :) Grazie mille. – galadog

+0

@galadog La memcpy è necessaria? Perché non potresti farlo: 'std :: complex x (1,0); fftw_complex * fx = & x' –

+0

@Andre Boos: Perché questo infrange le rigide regole di aliasing ... – Goz

4

reinterpret_cast funziona solo per puntatori e riferimenti. Quindi dovreste fare questo:

#include <complex> 
#include <fftw3.h> 
int main() 
{ 
    std::complex<double> x(1,0); 
    fftw_complex fx(*reinterpret_cast<fftw_complex*>(&x)); 
} 

Questo presuppone che fftw_complex ha un costruttore di copia. Per evitare problemi con aliasing rigoroso, è preferibile lo Goz's solution.

+1

Quello che fai sopra rompe rigide regole di aliasing e dovrebbe essere evitato. GCC ti avviserà per averlo fatto e si interromperà potenzialmente se hai attivato un aliasing rigoroso. – Goz

+0

@ Goz: hai ragione. Ho aggiunto un avvertimento e ho fatto riferimento alla tua risposta. –

+2

Funziona anche per i riferimenti: 'fftw_complex fx (reinterpret_cast (x));' – MSalters

18

L'idea alla base della compatibilità dei bit dei tipi complessi fftw_complex e C99 e C++ non è che possano essere facilmente creati l'uno dall'altro, ma tutte le funzioni in FFTW che portano i puntatori a fftw_complex possono anche puntare a C++ std :: complesso. Pertanto l'approccio migliore è probabilmente quello di usare std :: complesso <> tutto il programma e convertire solo puntatori a questi valori quando si chiamano le funzioni FFTW:

std::vector<std::complex<double> > a1, a2; 
.... 
.... 
fftw_plan_dft(N, reinterpret_cast<fftw_complex*>(&a1[0]), 
       reinterpret_cast<fftw_complex*>(&a2[0]), 
       FFTW_FORWARD, FFTW_ESTIMATE); 
.... 
+0

Di gran lunga il modo migliore per andare. – Mike

Problemi correlati