Eigen: vector or matrix componentwise to power?

倾然丶 夕夏残阳落幕 提交于 2019-12-23 22:34:33

问题


Given a vector of reals c and a vector of integers rw, I want to create a vector z with elements z_i=c_i^rw_i. I tried to do this using the component-wise function pow, but I get a compiler error.

#include <Eigen/Core>

typedef Eigen::VectorXd RealVector;
typedef Eigen::VectorXi IntVector; // dynamically-sized vector of integers
RealVector c; c << 2, 3, 4, 5;
IntVector rw; rw << 6, 7, 8, 9;
RealVector z = c.pow(rw);    **compile error**

The compiler error is

error C2664: 'const Eigen::MatrixComplexPowerReturnValue<Derived> Eigen::MatrixBase<Derived>::pow(const std::complex<double> &) const': cannot convert argument 1 from 'IntVector' to 'const double &'
      with
      [
          Derived=Eigen::Matrix<double,-1,1,0,-1,1>
      ]
c:\auc\sedanal\LammSolve.h(117): note: Reason: cannot convert from 'IntVector' to 'const double'
c:\auc\sedanal\LammSolve.h(117): note: No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called

What is wrong with this code? And, assuming it can be fixed, how would I do the same operation when c is a real matrix instead of a vector, to compute c_ij^b_i for all elements of c?

Compiler is Visual Studio 2015, running under 64-bit Windows 7.


回答1:


First of all, MatrixBase::pow is a function that computes the matrix power of a square matrix (if the matrix has an eigenvalue decomposition, it is the same matrix, but with the eigenvalues raised to the given power).

What you want is an element-wise power, which since there is no cwisePow function in MatrixBase, requires switching to the Array-domain. Furthermore, there is no integer-specialization for the powers (this could be efficient, but only up to a certain threshold -- and checking for that threshold for every element would waste computation time), so you need to cast the exponents to the type of your matrix.

To also answer your bonus-question:

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

int main(int argc, char **argv) {
    Eigen::MatrixXd A; A.setRandom(3,4);
    Eigen::VectorXi b = (Eigen::VectorXd::Random(3)*16).cast<int>();

    Eigen::MatrixXd C = A.array() // go to array domain
        .pow(                 // element-wise power
             b.cast<double>() // cast exponents to double
            .replicate(1, A.cols()).array() // repeat exponents to match size of A
        );

    std::cout << A << '\n' << b << '\n' << C << '\n';
}

Essentially, this will call C(i,j) = std::pow(A(i,j), b(i)) for each i, j. If all your exponents are small, you might actually be faster than that with a simple nested loop that calls a specialized pow(double, int) implementation (like gcc's __builtin_powi), but you should benchmark that with actual data.



来源:https://stackoverflow.com/questions/44268968/eigen-vector-or-matrix-componentwise-to-power

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!