Search code examples
c++eigen

Eigen binaryExpr with eigen type output


I'm having a problem while trying to use binaryExpr. It is the first use I'm making of it so I have been following the Eigen documentation

For my use I need a functor with Eigen type inputs and outputs but this does not want to compile and I do not understand why. I've looked up the explanation in the code but I didn't think this would apply here because I use floats and an array of floats

// We require Lhs and Rhs to have "compatible" scalar types.
// It is tempting to always allow mixing different types but remember that this is often impossible in the vectorized paths.
// So allowing mixing different types gives very unexpected errors when enabling vectorization, when the user tries to
// add together a float matrix and a double matrix.

Here is a short example of the use I would need that gets me the same compilation error:

#include <eigen3/Eigen/Dense>

using namespace std;
using namespace Eigen;

struct myBinaryFunctor {
  EIGEN_EMPTY_STRUCT_CTOR(myBinaryFunctor)
  typedef Vector2f result_type;
  Vector2f operator()(const Matrix<float,9,1>& a,const float& f) const
  {
      float x = a.head(4).sum()*f;
      float y = a.tail(5).sum()/f;
      return Vector2f(x,y);
  }
};

int main()
{
    constexpr int n = 3;
    Matrix<Matrix<float,9,1>,n,n> Ma;
    Matrix<float,n,n> F;
    Matrix<Vector2f,n,n> R;

    for(size_t i = 0, sizeMa = Ma.size(); i<sizeMa; i++)
    {
        Ma(i).setOnes();
    }

    F.setConstant(n,n,2);

    R = Ma.binaryExpr(F,myBinaryFunctor());

    return 0;
}

The compilation output is :

/usr/local/include/eigen3/Eigen/src/Core/CwiseBinaryOp.h:107: erreur : static assertion failed: YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY
       EIGEN_CHECK_BINARY_COMPATIBILIY(BinaryOp,typename Lhs::Scalar,typename Rhs::Scalar);
       ^

If you have a solution that could make this work this would be a huge help for me :) If not I would still enjoy an explanation to understand what is happening. Thanks a lot.


Solution

  • Adding:

    namespace Eigen {
    template<>
    struct ScalarBinaryOpTraits<Matrix<float,9,1>,float,myBinaryFunctor> {
      typedef Vector2f ReturnType;
    };
    }
    

    will do the job. This is because implicit scalar conversion are explicitly disallowed within Eigen, so you must explicit say that two different scalar types are compatible. For instance adding a VectorXd to a VectorXf is disallowed.

    Nonetheless, it seems to me that your abusing Eigen's features here.