Eigen library: return a matrix block in a function as lvalue
Asked Answered
E

2

7

I am trying to return a block of a matrix as an lvalue of a function. Let's say my function looks like this:

Block<Derived> getBlock(MatrixXd & m, int i, int j, int row, int column)
{
    return m.block(i,j,row,column);
}

As it turns out, it seems that C++ compiler understands that block() operator gives only temporary value and so returning it as an lvalue is prohibited by the compiler. However, in Eigen documentation there is some example that we can use Eigen as an lvalue (http://eigen.tuxfamily.org/dox/TutorialBlockOperations.html#TutorialBlockOperationsUsing) so I am wondering how we couldn't do the same with function return.

a.block(0,0,2,3) = a.block(2,1,2,3);

Thank you!

Entrenchment answered 25/11, 2012 at 4:23 Comment(0)
E
9

I want to put what I found myself so it might be helpful to someone else:

My basic solution is to know what derived type you want the block to be. In this case:

Block<MatrixXd> getBlock(MatrixXd & m, int i, int j, int row, int column)
{
    return m.block(i,j,row,column);
}

It is interesting to me to notice that this method will return the reference to the content of matrix m by default. So if we do:

MatrixXd m = MatrixXd::Zero(10,10);
Block<MatrixXd> myBlock = getBlock(m, 1, 1, 3, 3);
myBlock << 1, 0, 0, 
           0, 1, 0, 
           0, 0, 1;

The content in matrix m will be modified as well. Note that, however,

MatrixXd m = MatrixXd::Zero(10,10);
MatrixXd myBlock = getBlock(m, 1, 1, 3, 3);
myBlock << 1, 0, 0, 
           0, 1, 0, 
           0, 0, 1;

will not work. My understanding is that once we convert the block to another type Eigen makes a copy of the data before conversion.

Entrenchment answered 6/12, 2012 at 8:7 Comment(3)
thanks to expression templates, block() does not actually return a copy the block, instead it just returns an expressionCaptivity
@user3183610 so how to force a block (an expression) to evaluate. I mean as a valid lvalue.Surfboarding
@Surfboarding Either by calling eval() or by assigning it to an Array or Matrix type (read something that's not an expression). That's why the second example doesn't change the original matrix. The Block is an expression pointing to the elements in the original matrix but when you assign the block to another MatrixXd variable, the expression is evaluated and the result stored in the variable. That variable now obviously has its own memory as with any MatrixXd mat = other_mat assignment.Domineca
S
0

I was trying something like this, specifically returning the last 3 elements of a 4 element vector and I couldn't get this to work.

Solution turned out kind of nice, although maybe a little confusing if you're not familiar with trailing return types:

struct foo{

  Eigen::Vector4d e_;

  // const version
  auto get_tail() const -> const auto { return e_.tail<3>(); };

  // non-const version
  auto get_tail() -> auto { return e_.tail<3>(); };

};
Serrell answered 7/1, 2022 at 22:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.