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

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


The `apply()` function has a different "Derived" type, which is why it fails.  MatrixBase<Matrix...> and MatrixBase<Block...> are two different types.

If you want a single manipulator like this that can take either a Matrix or a Block, you need to use an Eigen::Ref<Matrix...> (passed by value).  See https://eigen.tuxfamily.org/dox/TopicFunctionTakingEigenTypes.html.
https://godbolt.org/z/ecxTxY1K5



On Fri, Feb 3, 2023 at 4:54 AM Peter <list@xxxxxxxxxxxxxxxxx> wrote:
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/