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

Expression return type for custom method

Tags: None
(comma "," separated)
jle
Registered Member
Posts
3
Karma
0
Hello.
I have developed the following method as an Eigen plugin to perform a multiple dot product between corresponding column vectors in two matrices:
Code: Select all
/**
 * @brief Performs the dot product between each corresponding column vector in this and
 *        that matrices. If either matrix is a column vector, the operation is performed
 *        between the vector against each row in the other matrix.
 * @param v the second matrix (or column vector)
 * @return a row vector containing the dot product results
 */
template <typename OtherDerived>
Matrix<RealScalar, 1, Dynamic> colwiseDot(const MatrixBase<OtherDerived> & that) const {
    assert(this->rows() == that.rows());
    if (that.cols() == 1) {
        return that.transpose() * *this;
    }
    if (this->cols() == 1) {
        return this->transpose() * that;
    }
    assert(this->cols() == that.cols());
    return (this->array() * that.array()).colwise().sum();
}

This works well according to my tests BUT id like this method to return an expression type instead of a calculated vector, so that I can take advantage of lazy evaluation. I've tried a number of approaches but I must confess I'm getting lost in the template forest.

Any help will be appreciated.
JLE
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS
I don't get it, what your function is doing is just computing the diagonal of a matrix-matrix product:

(A.transpose() * B).diagonal()

This is already optimized to compute only the diagonal coefficient in a lazy way.
jle
Registered Member
Posts
3
Karma
0
Ok, I should clarify this.

I understand that returning a Matrix<RealScalar, 1, Dynamic> forces the expression to be evaluated as a vector.
As long as I'm using this method within other expressions, I'd prefer to return an expression type instead of a regular vector.
I'd like to know if this is possible.

Thanks,
JLE
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS
What I'm saying is that there is no need for writing a custom member for that. If you still want it, then you must remove the branches and always returns the same expression, for instance: (derived().transpose() * other.derived()).diagonal() which type should be :

Diagonal<const CoeffBasedProduct<const Transpose<const Derived>, const OtherDerived, 0>, 0>
jle
Registered Member
Posts
3
Karma
0
The following works for a multiple dot product between two (mxn) matrices:
Code: Select all
template <typename OtherDerived>
const Diagonal<const CoeffBasedProduct<const Transpose<const Derived>, const OtherDerived, 0>, 0> colwiseDot(const MatrixBase<OtherDerived> & other) const {
    return (derived().transpose() * other.derived()).diagonal();
}


However, that method doesn't address the cases when one of the operands is a column vector. I understand I should write specific methods for those cases.

The reason why I want a method like the first colwiseDot I wrote is to maintain some readability of code like this:
Code: Select all
aMatrix.colwiseDot( bMatrix.colwise() - bVector ).array() /
aMatrix.colwiseDot( aVector ).array();


Thank you for illuminating my way from Matlab to Eigen.
JLE


Bookmarks



Who is online

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