2010-11-18 12 views
12

El manual FFTW says que su tipo fftw_complex es poco compatible con std::complex<double> clase en STL. Pero eso no funciona para mí:Problema fundición STL complejo <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); 
} 

Esto me da un error:

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

¿Qué estoy haciendo mal?

Respuesta

8

Vuelva a escribir el código de la siguiente manera:

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

Cada compilador que he usado optimizará el establecimiento de memoria, ya que es la copia de un fijo, es decir, en tiempo de compilación, cantidad de datos.

Esto evita pointer aliasing issues.

Editar: También puede evitar problemas de aliasing estrictas a través de una unión de la siguiente manera:

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

Aunque estrictamente estas reglas C99 (no estoy seguro sobre C++) se rompen como la lectura de un miembro diferente de una unión para el escrito también no está definido. Sin embargo, funciona en la mayoría de los compiladores. Personalmente prefiero mi método original.

+0

Ok, eso funciona para mí! 3 años sin codificación en C pura :) Muchas gracias. – galadog

+0

@galadog ¿Es necesario el memcpy? ¿Por qué no podría hacer esto: 'std :: complex x (1,0); fftw_complex * fx = & x' –

+0

@Andre Boos: Porque eso rompe las estrictas reglas de alias ... – Goz

4

reinterpret_cast solo funciona para punteros y referencias. Por lo que tendría que hacer esto:

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

Esto asume que fftw_complex tiene un constructor de copia. Para evitar problemas con el aliasing estricto, se debe preferir Goz's solution.

+1

Lo que se hace encima rompe las reglas de alias estricto y debe ser evitado. GCC lo advertirá de que lo haga y potencialmente se romperá si tiene activado alias estricto. – Goz

+0

@Goz: tienes razón. Añadí una advertencia y me referí a tu respuesta. –

+2

También funciona para referencias: 'fftw_complex fx (reinterpret_cast (x));' – MSalters

18

La idea detrás de bits compatibilidad de fftw_complex y C99 y C++ tipos complejos no es que se pueden crear fácilmente una de la otra, sino que todas las funciones en FFTW que tienen punteros a fftw_complex también pueden tomar punteros a C++ std :: complejo. Por lo tanto, el mejor enfoque es probablemente usar std :: compleja <> a través de su programa y sólo convertir punteros a estos valores al llamar a funciones 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

De lejos, la mejor manera de hacerlo. – Mike

Cuestiones relacionadas