В поисках лучшего способа инициализации матрицы Eigen3

У меня есть ситуация, когда я получаю матрицу Eigen3 со сложными элементами из матрицы с двойными элементами. Сейчас я просто перебираю строки и столбцы и заполняю записи по одной. Мне было интересно, если кто-нибудь знает какой-либо подход по линии:

 complexMatrix = doubleMatrix.unaryExpr(transform)

0

Решение

В Eigen есть оператор, который называется бросать. Объявление выглядит страшно из-за шаблона, но его использование довольно просто.

Я думаю, что это должно работать

complexMatrix = doubleMatrix.cast< std::complex<double> >();

Отредактируйте, ну, ладно … есть способ сделать это. В документации есть пример: http://eigen.tuxfamily.org/dox/classEigen_1_1MatrixBase.html#a23fc4bf97168dee2516f85edcfd4cfe7

Однако я считаю, что для получения правильного типа нужно сочетать cast и функтор.

complexMatrix = doubleMatrix.cast< std::complex<double> >().unaryExpr( FUNCTOR );

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

Примечание: может быть возможно пропустить cast при использовании класса functor, который принимает double и возвращает complex, но мне не удалось сделать это с нуля. Это было бы сложно. Я также не думаю, что это необходимо, потому что cast вероятно, не вводит никаких реальных накладных расходов.

Изменить: Рабочий пример.

Это вносит немного накладных расходов от преобразования x от double в complex назад и вперед 2 раза, но я ожидаю, что это будет незначительно по сравнению с фактическим телом функтора.

#include <Eigen/Core>
#include <iostream>
using namespace Eigen;
using namespace std;

std::complex<double> functor(double x){
//complicated stuff
return std::complex<double> (x, -2*x) ;
}

std::complex<double> wrapper(std::complex<double> x)
{
//nothing is lost here, as we expect x to have only real part
//from being upcasted from the original matrix
double xReal = x.real();
return functor(xReal);
}

int main(int, char**)
{
Matrix4d m1 = Matrix4d::Random();
cout << m1 << endl << "becomes: " << endl
<< m1.cast< std::complex<double> >().unaryExpr(ptr_fun(wrapper)) << endl;
return 0;
}
1

Другие решения

unaryExpr может определить тип возвращаемого значения из функтора, поэтому можно сделать следующее:

#include <Eigen/Core>
std::complex<double> functor(double x){
return std::complex<double> (-x, x) ;
}
int main(int, char**)
{
Eigen::Matrix3d m1 = Eigen::Matrix3d::Random();
Eigen::Matrix3cd m2 = m1.unaryExpr(std::ptr_fun(functor));
}

и с классом функторов:

#include <Eigen/Core>
struct Functor {
typedef std::complex<double> result_type;
std::complex<double> operator()(double x) const {
return std::complex<double> (-x, x) ;
}
};
int main(int, char**)
{
Eigen::Matrix3d m1 = Eigen::Matrix3d::Random();
Eigen::Matrix3cd m2 = m1.unaryExpr(Functor());
}
1

По вопросам рекламы [email protected]