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

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


Yes, by default `Eigen::Ref` assumes the inner stride is 1 for efficiency.  This is documented here.  You can specify a dynamic stride via

// Ref with dynamic stride.
template<typename Derived>
using StridedRef = Eigen::Ref<Derived, 0, Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>>;
https://godbolt.org/z/nWa9xbsa7

Though you may be better off copying the column to a vector with unit stride.

On Sat, Feb 4, 2023 at 1:24 AM Peter <list@xxxxxxxxxxxxxxxxx> wrote:
Dear Antonio,

Am 03.02.23 um 17:54 schrieb Antonio Sanchez:
> 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://eigen.tuxfamily.org/dox/TopicFunctionTakingEigenTypes.html>.
> https://godbolt.org/z/ecxTxY1K5 <https://godbolt.org/z/ecxTxY1K5>


thanks for your advice and example. I had actually tried Eigen::Ref before and failed.
So I took another look at it, and found that there is actually one edge case,
that is failing, and I happened to test the on: <https://godbolt.org/z/5xW8Y1sbE>
i.e. col() for RowMajor and a row() for a ColumnMajor Matrix fails for me.

Now this is not a show stopper for my project, but I guess that's not intended behaviour.
However the failure has some advantages, namely ruling out inefficient code,
so this could be intended.

Best regards
Peter


/// Here's the Ref version that fails with -DFAIL

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

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

/// Ref-Value call
template <typename Derived>
void mulValue_ref(Eigen::Ref<Derived> r, const double s)
{
     r *= 1.0 / s;
};

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

         void set_manipulator_ref(std::function<void(Eigen::Ref<Derived>,  const double)> mulValue_ref_)
         {
             fr = mulValue_ref_;
         };

         void apply_ref(Eigen::Ref<Derived> r, const double s)
         {
             fr(r, s);
         };

     private:
         std::function<void(Eigen::Ref<Derived>, const double)>  fr;
};

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

     // ----------------
     // the Ref version
     // ----------------

     Manipulator<Matrix> m;
     m.set_manipulator_ref(mulValue_ref<Matrix>);
     m.apply_ref(testMatrix, 2.0);
     m.apply_ref(B, 5.0);
     m.apply_ref(testMatrix.block(0, 0, 2, 2), 2.0);
     m.apply_ref(testMatrix.row(0), 0.1);
#ifdef FAIL
     m.apply_ref(testMatrix.col(0), 0.2);
#endif
     std::cout << "testMatrix after Refs:\n" << testMatrix << std::endl << std::endl;
     return 0;
}




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