This forum has been archived. All content is frozen. Please use KDE Discuss instead.

Setting M.diagonal() vs M.rowwise().reverse().diagonal()

Tags: None
(comma "," separated)
rmeyer
Registered Member
Posts
3
Karma
0
Hi all,

I'm a new Eigen user, but have been enjoying playing around with it. It seems like it will definitely make my life easier and code cleaner. Anyway, right now I'm trying to find the most succinct way to modify both diagonals (topLeft --> bottomRight, and bottomLeft --> topRight) within a function in which I've used a Ref<T> so that the original matrix or block is writable. These are the relevant bits:

Code: Select all
void fitLineToLMR( Ref<VectorXf> D );          // just modifies D.
//VectorXf fitLineToLMR(const Ref<const VectorXf>& D) ;         // alternate form

void step( Ref<MatrixXf> M ){
    ....
    VectorXf diag_TB( M.diagonal() );   
    fitLineToLMR( diag_TB );
    M.diagonal() << diag_TB;              // This works...

    VectorXf diag_BT( M.rowwise().reverse().diagonal() );
    fitLineToLMR( diag_BT );
    M.rowwise().reverse().diagonal() << diag_BT;          // This doesn't work...
    ....
}


I have tried inserting eval() calls at various places, changing << to =, as well as giving fitLineToLMR() a VectorXf return type and putting it directly on the RHS. I seem to get a similar error message in each case, which I interpret as telling me that "M.rowwise().reverse().diagonal()" doesn't have the proper type for the operator<< or operator= methods (at least with another matrix ref. on the RHS). Probably because it's const? I broke it up a bit so it's more readable:
Code: Select all
passing ‘Eigen::MatrixBase<Eigen::Reverse<Eigen::Ref<Eigen::Matrix<float, -1, -1> >, 1> >::ConstDiagonalReturnType
{aka const Eigen::Diagonal<const Eigen::Reverse<Eigen::Ref<Eigen::Matrix<float, -1, -1> >, 1>, 0>}’

as ‘this’ argument of

‘Eigen::CommaInitializer<Derived> Eigen::DenseBase<Derived>::operator<<(const Eigen::DenseBase<OtherDerived>&)
[with OtherDerived = Eigen::Matrix<float, -1, 1>;
 Derived = Eigen::Diagonal<const Eigen::Reverse<Eigen::Ref<Eigen::Matrix<float, -1, -1> >, 1>, 0>]’ 

discards qualifiers [-fpermissive]

M.rowwise().reverse().diagonal() << fitLineToLMR(diag_BT);


I understand what -fpermissive is, but I certainly don't know enough to think I should disable it, and I don't know how to go about working around it from here. In the Documentation for reverse(), there is an example where mat.reverse()(i , j) is assigned a value which then propagates back to the original matrix, which makes me wonder if there's some easy way I can get the above code to work as intended. Obviously, I could write a loop to accomplish the task, but in the interest of learning, I'm hoping someone can explain to me exactly why it doesn't work as written, or why the diagonal() call is automatically const, and/or point me towards a possible fix.

Thanks!
rmeyer
Registered Member
Posts
3
Karma
0
Ok, well I'm still not sure exactly when and why methods have to return const objects, so if anyone wants to shed some light on that, I would still appreciate it. With that said, I did come up with a solution to my particular problem by doing the rowwise().reverse() call on an identity matrix and then using applyOnTheLeft() to flip the matrix M vertically. Here's how the relevant parts look now:
Code: Select all
VectorXf fitLineToLMR(const Ref<const VectorXf>& D );

void step( Ref<MatrixXf> M ){
    ....
    VectorXf diag_TB( M.diagonal() );   
    M.diagonal() << fitLineToLMR( diag_TB );
   
    MatrixXf T = MatrixXf::Identity(M.rows(), M.cols());          // note: M is square
    T = T.rowwise().reverse().eval();

    M.applyOnTheLeft(T);                    // flip vertically
    VectorXf diag_BT( M.diagonal() );
    M.diagonal() << fitLineToLMR( diag_BT );          //  Works now!
    M.applyOnTheLeft(T);                    // recover original orientation
    ....
}

}
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS
This is because there is a shortcoming in the VectorwiseOp class where a non-const overload of reverse() is missing. You can workaround by bypassing VectorwiseOp with something like:

Reverse<Ref<MatrixXf>,Vertical>(M).diagonal() = ...;


Bookmarks



Who is online

Registered users: Bing [Bot], Google [Bot], Yahoo [Bot]