Reputation: 19960
Quick context, I am working with another C++ library that has functions that expect either a regular or mapped Eigen matrix. I would like to use the mapped version to avoid the memory overhead of copying.
That said, I am trying to work with blocks of matrices. I know these can be easily accessed with the block
method returning either an Eigen::Block
or Eigen::Ref
object. Below I am trying to work with the Ref
object. I would like to Map
the Eigen::MatrixXd
block. However, it appears that I cannot map across columns but only contiguous elements in columns (which I assume is a consequence of the column oriented data). You can see the difference in outputs below.
Is there any way for me to Map
a block of an Eigen::MatrixXd
?
#include <iostream>
#include <Eigen/Core>
int main()
{
Eigen::MatrixXd A(3,3);
A(0,0) = 1.0;
A(0,1) = 2.0;
A(0,2) = 3.0;
A(1,0) = 4.0;
A(1,1) = 5.0;
A(1,2) = 6.0;
A(2,0) = 7.0;
A(2,1) = 8.0;
A(2,2) = 9.0;
std::cout << "source" << std::endl;
std::cout << A << std::endl;
Eigen::Ref<Eigen::MatrixXd> block = A.block(1,1,1,2);
std::cout << "block" << std::endl;
std::cout << block << std::endl;
Eigen::Map<Eigen::MatrixXd> map(block.data(), block.rows(), block.cols());
std::cout << "map" << std::endl;
std::cout << map << std::endl;
}
Output:
source
1 2 3
4 5 6
7 8 9
block
5 6
map
5 8
Upvotes: 4
Views: 952
Reputation: 10596
The Eigen::Map
assumes a unit stride unless specified otherwise. The problem with the Ref
object is that the stride is not 1. You can specify the stride (outer in this case) as follows:
Eigen::Map<Eigen::MatrixXd, 0, Eigen::OuterStride<> >
map2(block.data(), block.rows(), block.cols(), Eigen::OuterStride<>(3));
std::cout << "map2" << std::endl;
std::cout << map2 << std::endl;
Better yet, you can use the outer stride of the Ref
object to specify it for the map:
Eigen::Map<Eigen::MatrixXd, 0, Eigen::OuterStride<> >
map2(block.data(), block.rows(), block.cols(), Eigen::OuterStride<>(block.outerStride()));
Upvotes: 2