Search code examples
c++11eigen

How to use element wise integer power with Eigen


I would like to take the element wise power of an array of double with and array of int using Eigen power function.

Here is a sample code that reproduce the issue using Eigen v3.3.4 and v3.3.7:

#include <Eigen/Dense>

int main() {
  Eigen::ArrayXd x(10);
  Eigen::ArrayXd res(10);
  Eigen::ArrayXi exponents(10);
  x = Eigen::ArrayXd::Random(10);
  exponents = Eigen::ArrayXi::LinSpaced(10, 0, 9);
  res = Eigen::pow(x, exponents);

  return (0);
}

The error message is quite long but in essence I get

YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY

which does not seem appropriate to me in this context, along with

Eigen3/Eigen/src/Core/functors/BinaryFunctors.h:294:84: error: no type named ‘ReturnType’ in ‘struct Eigen::ScalarBinaryOpTraits<double, int, Eigen::internal::scalar_pow_op<double, int> >’
   typedef typename ScalarBinaryOpTraits<Scalar,Exponent,scalar_pow_op>::ReturnType result_type;

Solution

  • As the error message indicated, you can't mix scalar types implicitly. You have to explicitly cast so that the types match:

    res = Eigen::pow(x, exponents.cast<double>());
    

    As for a specialization for integer types, the template of the power function (as a functor) is:

    template<typename ScalarX,typename ScalarY, bool IsInteger = 
                                     NumTraits<ScalarX>::IsInteger&&NumTraits<ScalarY>::IsInteger>
    

    and calls a simple pow(x,y) unless both types are integers (IsInteger), in which case there is a different specialization.

    There is also an overload for an array to the power of a constant, which doesn't seem to be what you are looking for. In that case (unless ggael corrects me), you can definitely implement your own CustomBinaryOp