Problema de lanzar complejo STL a FFTW_COMPLEX
-
26-09-2019 - |
Pregunta
El manual FFTW dice que es fftw_complex
El tipo es bit compatible para std::complex<double>
clase en stl. Pero eso no funciona para mí:
#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?
Solución
Reescribe tu 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 MEMCPY porque está copiando una cantidad fija, es decir, en el momento de la compilación.
Esto evita Problemas de alias de puntero.
Editar: También puede evitar problemas estrictos de alias utilizando un sindicato 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 de C99 (no estoy segura de C ++) se rompen como la lectura de un miembro diferente de un sindicato a la escrita también está indefinida. Sin embargo, funciona en la mayoría de los compiladores. Personalmente prefiero mi método original.
Otros consejos
La idea detrás de la compatibilidad de bit de los tipos complejos FFTW_COMPLEX y C99 y C ++ no es que puedan crearse fácilmente entre sí, sino que todas las funciones en FFTW que llevan punteros a FFTW_COMPLEX también pueden llevar punteros a C ++ Std :: Complex. Por lo tanto, el mejor enfoque es probablemente usar STD :: Complex <> a lo largo de su programa y solo convertir punteros a estos valores al llamar a las 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);
....
reinterpret_cast
Solo funciona para punteros y referencias. Entonces tendrías 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 supone que fftw_complex
tiene un constructor de copias. Para evitar problemas con alias estricto, La solución de Goz debe ser preferido.