[eigen] Eigen::Block to Eigen::MatrixBase conversion problem

[ Thread Index | Date Index | More lists.tuxfamily.org/eigen Archives ]


Dear All,

I'd like to write a class that takes a function and let this function
operate on matrices, or blocks of matrices  including columns and rows.
Think of it like scipys LinearOperator, just that we can decide
on which part of a matrix we apply it.

In trying to implement this we struggled with a conversion problem, that we do not understand.
In essence it boils down to the following examples, which compiles fine as is, while it
fails to compile when -DFAIL is set. Note  that for simplicity I only used lvalue calls, in
order to avoid lvalues vs. rvalues problems here.

In this example I define a functions `mulValue`that just multiplies the object with a given scalar.
In encapsulating it I'd like to call `mulValue`, that is expects an Eigen::MatrixBase<Eigen::Matrix>>,
with an Eigen::MatrixBase<Eigen::Block<Matrix>>, which fails to compiles.

I'm surprised by this, as I thought that this is the goal of MatrixBase, or did I misunderstand it?
In addition, is there a function declaration that allows me to do that? Possibly in a way that
allows me to set the manipulation function in python via pybind11?

#include <iostream>
#include <Eigen/Core>


typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> Matrix;

/// L-Value call
template <typename Derived>
void mulValue(Eigen::MatrixBase<Derived>& m, const double s)
{
    m *= s;
};

template <typename Derived>
class Manipulator
{
    public:
        Manipulator(){};

        void set_manipulator(std::function<void(Eigen::MatrixBase<Derived>&,  const double)> mulValue_l_)
        {
            f = mulValue_l_;
        };

        void apply(Eigen::MatrixBase<Derived>& m, const double s)   ///< line 25
        {
            f(m, s);
        };

    private:
        std::function<void(Eigen::MatrixBase<Derived>&,  const double)>  f;

};

int main()
{
    Matrix testMatrix(3, 3);
    testMatrix.setOnes();
    auto B = testMatrix.block(0, 1, 3, 2);

    /// functional approach works for matrices and blocks
    mulValue(testMatrix, 2.0);
    mulValue(B, 3.0);
    std::cout << testMatrix << std::endl << std::endl;

    /// init Maipulator with class
    Manipulator<Matrix> m;
    m.set_manipulator(mulValue<Matrix>);

    /// works fine on matrices
    std::cout << "testMatrix before m:\n" << testMatrix << std::endl << std::endl;
    m.apply(testMatrix, 3.0);
    std::cout << "testMatrix after m:\n" << testMatrix << std::endl << std::endl;

    /// works for Blocks
    Manipulator<Eigen::Block<Matrix>> mB;
    mB.set_manipulator(mulValue<Eigen::Block<Matrix>>);
    std::cout << "testMatrix before: mB\n" << testMatrix << std::endl << std::endl;
    mB.apply(B, 2.0);
    std::cout << "testMatrix aftermpl:\n" << testMatrix << std::endl << std::endl;

#ifdef FAIL
    /// fails for Blocks
    std::cout << "testMatrix before m:\n" << testMatrix << std::endl << std::endl;
    m.apply(B, 2.0);    ///< line 65
    std::cout << "testMatrix after m:\n" << testMatrix << std::endl << std::endl;
#endif

    return 0;
}

Compiling with -DFAIL leads to

block.C: In function ‘int main()’:
block.C:65:13: error: cannot convert ‘Eigen::Block<Eigen::Matrix<double, -1, -1>, -1, -1, false>’ to ‘Eigen::MatrixBase<Eigen::Matrix<double, -1, -1> >&’
   65 |     m.apply(B, 2.0);    ///< line 65
      |             ^
      |             |
      |             Eigen::Block<Eigen::Matrix<double, -1, -1>, -1, -1, false>
block.C:25:48: note:   initializing argument 1 of ‘void Manipulator<Derived>::apply(Eigen::MatrixBase<Derived>&, double) [with Derived = Eigen::Matrix<double, -1, -1>]’
   25 |         void apply(Eigen::MatrixBase<Derived>& m, const double s)
      |



Best regards,
Peter




Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/