3

Sometime ago user ggael gave an answer to the problem of mapping a eigen::vectorXf to an eigen::matrixXf.

Now, i need to do something similar, but to an existing matrix, e.g i know i can:

for(int i=0;i<p;++i){
    VectorXf vec=q.col(i);
    /*q is a p**2 by n matrix*/ 
    Map<MatrixXf> qi(vec.data(),p,p);
    /*run function that uses qi to produce a scalare and store that scalar*/
}

but (it seems to me) it would be more efficient to create qi once and for all outside the loop and then use the same qi over and over again (is that right?)

Also, i wonder whether the intermediate step where i map q.col(i) to vec is really necessary...

A recent answer proposes to do:

qi=Map<MatrixXd>(vec.data(),p,p);

but doing that yields:

In function ‘Eigen::VectorXi DepType(const MatrixXf&, const MatrixXf&, const int&)’:
DeC.cpp:279:34: error: no matching function for call to ‘Eigen::Map<Eigen::Matrix<double, -0x00000000000000001, -0x00000000000000001> >::Map(Eigen::PlainObjectBase<Eigen::Matrix<float, -0x00000000000000001, 1> >::Scalar*, int&, int&)’
DeC.cpp:279:34: note: candidates are:
/eigen/Eigen/src/Core/Map.h:179:12: note: Eigen::Map<MatrixType, MapOptions, StrideType>::Map(Eigen::Map<MatrixType, MapOptions, StrideType>::PointerArgType, Eigen::Map<MatrixType, MapOptions, StrideType>::Index, Eigen::Map<MatrixType, MapOptions, StrideType>::Index, const StrideType&) [with PlainObjectType = Eigen::Matrix<double, -0x00000000000000001, -0x00000000000000001>, int MapOptions = 0, StrideType = Eigen::Stride<0, 0>, Eigen::Map<MatrixType, MapOptions, StrideType>::PointerArgType = double*, Eigen::Map<MatrixType, MapOptions, StrideType>::Index = long int]
/home/kaveh/Desktop/work/p1/geqw4/vi3/out/sp/ccode/eigen/Eigen/src/Core/Map.h:179:12: note:   no known conversion for argument 1 from ‘Eigen::PlainObjectBase<Eigen::Matrix<float, -0x00000000000000001, 1> >::Scalar* {aka float*}’ to ‘double*’
/eigen/Eigen/src/Core/Map.h:166:12: note: Eigen::Map<MatrixType, MapOptions, StrideType>::Map(Eigen::Map<MatrixType, MapOptions, StrideType>::PointerArgType, Eigen::Map<MatrixType, MapOptions, StrideType>::Index, const StrideType&) [with PlainObjectType = Eigen::Matrix<double, -0x00000000000000001, -0x00000000000000001>, int MapOptions = 0, StrideType = Eigen::Stride<0, 0>, Eigen::Map<MatrixType, MapOptions, StrideType>::PointerArgType = double*, Eigen::Map<MatrixType, MapOptions, StrideType>::Index = long int]
/eigen/Eigen/src/Core/Map.h:166:12: note:   no known conversion for argument 1 from ‘Eigen::PlainObjectBase<Eigen::Matrix<float, -0x00000000000000001, 1> >::Scalar* {aka float*}’ to ‘double*’
/eigen/Eigen/src/Core/Map.h:154:12: note: Eigen::Map<MatrixType, MapOptions, StrideType>::Map(Eigen::Map<MatrixType, MapOptions, StrideType>::PointerArgType, const StrideType&) [with PlainObjectType = Eigen::Matrix<double, -0x00000000000000001, -0x00000000000000001>, int MapOptions = 0, StrideType = Eigen::Stride<0, 0>, Eigen::Map<MatrixType, MapOptions, StrideType>::PointerArgType = double*]
/eigen/Eigen/src/Core/Map.h:154:12: note:   candidate expects 2 arguments, 3 provided
/eigen/Eigen/src/Core/Map.h:119:79: note: Eigen::Map<Eigen::Matrix<double, -0x00000000000000001, -0x00000000000000001> >::Map(const Eigen::Map<Eigen::Matrix<double, -0x00000000000000001, -0x00000000000000001> >&)
/eigen/Eigen/src/Core/Map.h:119:79: note:   candidate expects 1 argument, 3 provided

e.g. it seems Eigen thinks qi is a vector....:(

Community
  • 1
  • 1
user189035
  • 5,589
  • 13
  • 52
  • 112

1 Answers1

9

The following:

qi=Map<MatrixXd>(vec.data(),p,p);

means that you want to copy the coefficients of Map(vec.data(),p,p) into the matrix referenced by qi. However, what you actually want is to re-initialize the Map<> object. To do so you must call the constructor again using the construct new syntax of C++:

new (&qi) Map<MatrixXd>(vec.data(),p,p);

Moreover, I must say that a Map<> object is extremely lightweight: it is only one pointer and 2 integers that are statically allocated on the stack. So moving the declaration of Map<> qi outside the loop will have zero effect on the performance. On the other hand, note that you do not need to copy q.col(i) into a temporary buffer. If q is column major, you can directly do:

Map<MatrixXf> qi(q.col(i).data(),p,p);
ggael
  • 28,425
  • 2
  • 65
  • 71