Search code examples
eigen3

How to create an Eigen::Ref to a fixed-sized matrix row?


I would like to write something like foo4 similar to foo3 in the Eigen::Ref doc here :

#include <Eigen/Dense>

using namespace Eigen;

void foo3(Ref<VectorXf, 0, Eigen::InnerStride<> >){};
void foo4(Ref<Vector3f, 0, Eigen::InnerStride<> >){};

int main()
{
  Eigen::Matrix3f fmat = Eigen::Matrix3f::Identity();
  Eigen::MatrixXf dmat = Eigen::Matrix3f::Identity();

  foo3(dmat.row(1)); // OK

  foo3(fmat.row(1)); // Error : YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES
  foo4(fmat.row(1)); // Error : YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES
}

I'm using Eigen version 3.3.7


Solution

  • You are getting size-mismatch errors, because you are trying to pass row-vectors where column vectors are expected.

    There are two solutions:

    1. Change the function to accept row-vectors:
    void foo3(Ref<RowVectorXf, 0, Eigen::InnerStride<> >){};
    void foo4(Ref<RowVector3f, 0, Eigen::InnerStride<> >){};
    
    1. Explicitly transpose the vector you pass to the function:
      foo3(fmat.row(1).transpose());
      foo4(fmat.row(1).transpose());
    

    Note that there are some cases where Eigen implicitly transposes row-vectors to column-vectors (like the following example). But generally, I would not rely on that and always explicitly transpose vectors to match the orientation:

    Eigen::MatrixXd A(rows,cols);
    Eigen::VectorXd v1 = A.row(0); // this works
    Eigen::VectorXd v2 = A.row(0).transpose(); // more verbose, but what actually happens