Подтвердить что ты не робот

Проблема литья комплекса STL <double> to fftw_complex

Руководство FFTW сообщает, что его тип fftw_complex бит совместим с классом std::complex<double> в STL. Но это не работает для меня:

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

Это дает мне ошибку:

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

Что я делаю неправильно?

4b9b3361

Ответ 1

Перепишите код следующим образом:

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

Каждый компилятор, который я использовал, будет оптимизировать memcpy, потому что он копирует фиксированный, то есть во время компиляции, количество данных.

Это позволяет избежать проблем с псевдонимом указателя.

Изменить: Вы также можете избежать строгих проблем с псевдонимом с помощью объединения следующим образом:

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

Хотя строго эти правила C99 (не уверены в С++) нарушаются, так как чтение из другого члена объединения в одно написанное тоже есть undefined. Однако он работает на большинстве компиляторов. Лично я предпочитаю свой оригинальный метод.

Ответ 2

Идея бит-совместимости сложных типов fftw_complex и C99 и С++ заключается не в том, что они могут быть легко созданы друг от друга, но что все функции в FFTW, которые принимают указатели на fftw_complex, также могут принимать указатели на С++ std:: complex, Поэтому наилучшим подходом, вероятно, является использование std:: complex < > во всей вашей программе и только преобразование указателей на эти значения при вызове функций 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);
....

Ответ 3

reinterpret_cast работает только для указателей и ссылок. Поэтому вам нужно будет сделать это:

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

Это предполагает, что fftw_complex имеет конструктор копирования. Чтобы избежать проблем со строгим псевдонимом, рекомендуется Goz solution.