具有for_each的特征矩阵向量乘法

时间:2015-11-23 05:49:41

标签: c++ templates vector foreach eigen3

我想用for_each循环来处理矩阵向量乘法的序列。

所以我做了这样的代码。

template <typename EigenMat, typename EigenVec>
struct MatVecMult{
    MatVecMult(const EigenMat& m){
        mat = m;
    }

    void operator()(EigenVec& v)
    {
        v = mat*v;
    }

    EigenMat mat;
};

//this is main loop.
Eigen::Matrix2d mat;
vector<Eigen::Vector2d> v_array; //very huge vector, i.e 1000000. 

MatVecMult<Eigen::Matrix2d, Eigen::Vector2d> functor(mat);
std::for_each(v_array.begin(), v_array.end(), functor);

现在问题是上面的代码要求我指定MatVecMul仿函数的模板参数。

但不是这样,我想让代码看起来更像下面的内容。

Eigen::Matrix2d mat1;
vector<Eigen::Vector2d> v_array1;
Eigen::Matrix4d mat2;
vector<Eigen::Vector4d> v_array2;

std::for_each(v_array1.begin(), v_array1.end(), MatVecMult(mat1));
std::for_each(v_array2.begin(), v_array2.end(), MatVecMult(mat2));

此代码适用于任何类型的Eigen::MatrixEigen::Vector。 这可能吗?

2 个答案:

答案 0 :(得分:0)

首先,您可以改进MatVecMulti类,使operator()成为模板方法:

template <typename EigenMat>
struct MatVecMult {
    MatVecMult(const EigenMat& m){
        mat = m;
    }

    template <typename T>
    void operator()(T& v)
    {
        v = mat*v;
    }

    EigenMat mat;
};

// So now it can be used as

Eigen::Matrix2d mat;
vector<Eigen::Vector2d> v_array;

MatVecMult<Eigen::Matrix2d> functor(mat);
std::for_each(v_array.begin(), v_array.end(), functor);

可以删除MatVecMulti的最后一个模板参数吗?这取决于。

由于乘数数据存储在MatVecMulti中,因此在使用之前需要使用乘数类型。这就是你MatVecMult<Eigen::Matrix2d> functor(mat);

的原因
  

但不是这样,我想让代码看起来更像   以下。

Eigen::Matrix2d mat1; 
vector<Eigen::Vector2d> v_array1;   
Eigen::Matrix4d mat2; 
vector<Eigen::Vector4d> v_array2;

std::for_each(v_array1.begin(), v_array1.end(), MatVecMult(mat1)); 
std::for_each(v_array2.begin(), v_array2.end(), MatVecMult(mat2));

如果Eigen::Matrix2dEigen::Matrix4d共享一个公共基类,例如Eigen::MyFakeBaseMatrix,您可以通过多态存储/使用乘数,并将构造函数转换为模板方法:

struct MatVecMult {
    template <typename prod_t>
    MatVecMult(const prod_t& m){
        mat = unique_ptr<MyFakeBaseMatrix>(new prod_t(m));
    }

    template <typename T>
    void operator()(T& v)
    {
        v = (*mat)*v;
    }

    std::unique_ptr<MyFakeBaseMatrix> mat;
};

答案 1 :(得分:0)

您可以使用EigenMat的模板参数来推导EigenVec的矢量类型。以下用g ++编译,但不是VS2013。我没有针对运行时问题对其进行测试。

#include <iostream>
#include <algorithm>
#include <vector>
#include <Eigen/Core>
#include <Eigen/StdVector>

using std::vector;

template <typename EigenMat>
struct MatVecMult{
    typedef typename EigenMat::Scalar Scalar;
    typedef Eigen::Matrix<Scalar, EigenMat::ColsAtCompileTime, 1> EigenVec;
    MatVecMult(const EigenMat& m){
        mat = m;
    }

    void operator()(EigenVec& v)
    {
        v = mat*v;
    }

    EigenMat mat;
};

EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Eigen::Vector4d);
EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Eigen::Vector2d);

int main()
{
    Eigen::Matrix2d mat1;
    vector<Eigen::Vector2d> v_array1;
    Eigen::Matrix4d mat2;
    vector<Eigen::Vector4d> v_array2;

    std::for_each(v_array1.begin(), v_array1.end(), MatVecMult<Eigen::Matrix2d>(mat1));
    std::for_each(v_array2.begin(), v_array2.end(), MatVecMult<Eigen::Matrix4d>(mat2));

    return 0;
}

请勿忘记使用std::vector处理与Eigen静态大小类型的对齐问题。