简体   繁体   中英

Looking for a better way to initialize an Eigen3 Matrix

I've got a situation where I derive an Eigen3 matrix with complex elements from one with double elements. At the moment I just loop over the rows and columns and fill in the entries one by one. I was wondering if anyone knew of any approach along the lines of:

 complexMatrix = doubleMatrix.unaryExpr(transform)

There is an operator in Eigen for that called cast . The declaration looks scary because of the template stuff, but usage is pretty simple.

I think this should work

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

Edit, umm ok... there is a way to do this. There is an example in the documentation: http://eigen.tuxfamily.org/dox/classEigen_1_1MatrixBase.html#a23fc4bf97168dee2516f85edcfd4cfe7

However I believe, that to get proper type you need to combine cast and functor.

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

Of course functor is expected to be designed to work with complex Scalar type. You can also use fnc_ptr wrapper with a plain function as shown in the example.

Note: It might be possible to skip cast when using functor class that accepts double and returns complex, but I didn't manage to do it off the bat. It would be tricky. I also don't think it is necessary becasue cast probably does not introduce any real overhead.

Edit: Working example.

It does introduce a little bit of overhead from converting x from double to complex back and forth 2 times, but i expect it to be negligible compared to the actual functor body.

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

unaryExpr can deduce the return type from the functor, so one can do:

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

and with a functor class:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM