Khan
Khan

Reputation: 41

Assign a Eigen Block to an Eigen Ref compile error when Block's template arg Row equals to 1

I write a code segment:

  Eigen::Matrix<float, 5, Dynamic> m(5, 5);
  auto r = m.topRows<1>();
  Eigen::Ref<Eigen::Matrix<float, 1, Dynamic>> r2(r)

That will cause a compile error:

error: no matching function for call to ‘Eigen::Ref<Eigen::Matrix<float, 1, -1> >::Ref(Eigen::Block<Eigen::Matrix<float, 5, -1>, 1, -1, false>&)’
   46 |   Eigen::Ref<Eigen::Matrix<float, 1, Dynamic>> r2(r);

But when I changed the code to:

  Eigen::Matrix<float, 5, Dynamic> m(5, 5);
  auto r = m.topRows<2>();
  Eigen::Ref<Eigen::Matrix<float, 2, Dynamic>> r2(r)

Everything is ok.

I found the implement of block in eigen src may have a template specification when template arg row == 1

My question is:

How to walk around this case?

Upvotes: 2

Views: 38

Answers (1)

chtz
chtz

Reputation: 18827

The problem you encounter is that Eigen consider Matrices which have one dimension equal to 1 at compile time as vectors (IsVectorAtCompileTime==true). Therefore, the top row of a (column major) matrix is actually like a vector with inner stride (equal to the number of rows of the original matrix).

You can either make your matrices and Refs rowmajor,

Eigen::Matrix<float, 5, Eigen::Dynamic, Eigen::RowMajor> m(5,5);
auto r = m.topRows<1>();
Eigen::Ref<Eigen::Matrix<float, 1, Eigen::Dynamic, Eigen::RowMajor> > r2(r);

Or you need to allow Ref to have a dynamic inner stride, if it only has one row:

Eigen::Matrix<float, 5, Eigen::Dynamic> m(5,5);
auto r = m.topRows<1>();
Ref<Eigen::Matrix<float, 1, Eigen::Dynamic>, Eigen::InnerStride<> >  r2(r);

You can define yourself an alias for the latter, e.g.,

template<class Scalar, int Rows, int Cols, int Options=0>
using BlockRef = Eigen::Ref<Eigen::Matrix<Scalar, Rows, Cols>, Options,
typename Eigen::internal::conditional<Rows==1,Eigen::InnerStride<>,Eigen::OuterStride<> >::type>;

Then use it like:

BlockRef<float, 1, Eigen::Dynamic> r3(r);

Upvotes: 1

Related Questions