cdeterman
cdeterman

Reputation: 19960

Mapping Eigen Matrix Ref objects not consistent with blocks

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

Answers (1)

Avi Ginsburg
Avi Ginsburg

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

Related Questions