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 <[email protected]> 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
>
>
>
>

Reply via email to