Yes, by default `Eigen::Ref` assumes the inner stride is 1 for efficiency.
This is documented here
<https://eigen.tuxfamily.org/dox/classEigen_1_1Ref.html>.  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 <[email protected]> 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;
> }
>
>
>

Reply via email to