Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
307 views
in Technique[技术] by (71.8m points)

c++ - Eigen::Ref for concatenating matrices

If I want to concatenate two matrices A and B, I would do

using Eigen::MatrixXd;
const MatrixXd A(n, p);
const MatrixXd B(n, q);
MatrixXd X(n, p+q);
X << A, B;

Now if n, p, q are large, defining X in this way would mean creating copies of A and B. Is it possible to define X as an Eigen::Ref<MatrixXd> instead?

Thanks.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

No, Ref is not designed for that. We/You would need to define a new expression for that, that could be called Cat. If you only need to concatenate two matrices horizontally, in Eigen 3.3, this can be implemented in less than a dozen of lines of code as a nullary expression, see some exemple there.

Edit: here is a self-contained example showing that one can mix matrices and expressions:

#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;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...