Eigen :: Ref用于连接矩阵

use*_*195 3 c++ eigen

如果我想连接两个矩阵AB,我会做

using Eigen::MatrixXd;
const MatrixXd A(n, p);
const MatrixXd B(n, q);
MatrixXd X(n, p+q);
X << A, B;
Run Code Online (Sandbox Code Playgroud)

现在,如果n,p,q是大的,定义X这样将意味着创建的副本AB.是否可以定义XEigen::Ref<MatrixXd>替代?

谢谢.

gga*_*ael 6

不,Ref不是为此设计的.我们/您需要为其定义一个可以调用的新表达式Cat.如果你只需要水平连接两个矩阵,在Eigen 3.3中,这可以用不到十几行代码作为一个nullary表达式来实现,参见那里的一些例子.

编辑:这是一个自包含的示例,显示可以混合矩阵和表达式:

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

using namespace Eigen;

template<typename Arg1, typename Arg2>
struct horizcat_helper {
  typedef Matrix<typename Arg1::Scalar,
    Arg1::RowsAtCompileTime,
    Arg1::ColsAtCompileTime==Dynamic || Arg2::ColsAtCompileTime==Dynamic
    ? Dynamic : Arg1::ColsAtCompileTime+Arg2::ColsAtCompileTime,
    ColMajor,
    Arg1::MaxRowsAtCompileTime,
    Arg1::MaxColsAtCompileTime==Dynamic || Arg2::MaxColsAtCompileTime==Dynamic
    ? Dynamic : Arg1::MaxColsAtCompileTime+Arg2::MaxColsAtCompileTime> MatrixType;
};

template<typename Arg1, typename Arg2>
class horizcat_functor
{
  const typename Arg1::Nested m_mat1;
  const typename Arg2::Nested m_mat2;

public:
  horizcat_functor(const Arg1& arg1, const Arg2& arg2)
    : m_mat1(arg1), m_mat2(arg2)
  {}

  const typename Arg1::Scalar operator() (Index row, Index col) const {
    if (col < m_mat1.cols())
      return m_mat1(row,col);
    return m_mat2(row, col - m_mat1.cols());
  }
};

template <typename Arg1, typename Arg2>
CwiseNullaryOp<horizcat_functor<Arg1,Arg2>, typename horizcat_helper<Arg1,Arg2>::MatrixType>
horizcat(const Eigen::MatrixBase<Arg1>& arg1, const Eigen::MatrixBase<Arg2>& arg2)
{
  typedef typename horizcat_helper<Arg1,Arg2>::MatrixType MatrixType;
  return MatrixType::NullaryExpr(arg1.rows(), arg1.cols()+arg2.cols(),
                                horizcat_functor<Arg1,Arg2>(arg1.derived(),arg2.derived()));
}

int main()
{
  MatrixXd mat(3, 3);
  mat << 0, 1, 2, 3, 4, 5, 6, 7, 8;

  auto example1 = horizcat(mat,2*mat);
  std::cout << example1 << std::endl;

  auto example2 = horizcat(VectorXd::Ones(3),mat);
  std::cout << example2 << std::endl;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)