Eigen how to concatenate matrix along a specific dimension?
You can use the comma initializer syntax for that.
Horizontally:
MatrixXd C(A.rows(), A.cols()+B.cols());
C << A, B;
Vertically:
// eigen uses provided dimensions in declaration to determine
// concatenation direction
MatrixXd D(A.rows()+B.rows(), A.cols()); // <-- D(A.rows() + B.rows(), ...)
D << A, B; // <-- syntax is the same for vertical and horizontal concatenation
For readability, one might format vertical concatenations with whitespace:
D << A,
B; // <-- But this is for readability only.
how to concatenate Vectors in Eigen?
Like so, assuming you have vec1
and vec2
already:
VectorXd vec_joined(vec1.size() + vec2.size());
vec_joined << vec1, vec2;
(Note that the vector types are simply typedefs of matrix types constrained to have only one column.)
Further reading: Advanced initialization
Eigen::Ref for concatenating matrices
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;
}
C++ Eigen: How to concatenate matrices dynamically (pointer issue?)
What do you mean you don't know the size? You can use the member functions cols()/rows()
to get the size. Also, I assume by concatenation you mean direct sum? In that case, you can do something like
#include <iostream>
#include <Eigen/Dense>
int main()
{
Eigen::MatrixXd *A = new Eigen::MatrixXd(2, 2);
Eigen::MatrixXd *B = new Eigen::MatrixXd(3, 3);
*A << 1, 2, 3, 4;
*B << 5, 6, 7, 8, 9, 10, 11, 12, 13;
Eigen::MatrixXd *result = new Eigen::MatrixXd(A->rows() + B->rows(), A->cols() + B->cols());
result->Zero(A->rows() + B->rows(), A->cols() + B->cols());
result->block(0, 0, A->rows(), A->cols()) = *A;
result->block(A->rows(), A->cols(), B->rows(), B->cols()) = *B;
std::cout << *result << std::endl;
delete A;
delete B;
delete result;
}
So first make sure it works for 2 matrices, test it, then extend it to N
.
Eigen vertical stacking rows into Matrix
TLDR: Write something like this:
CoefficientMatrix A(2*N, 9);
for (int i = 0; i < N; i++) {
CoefficientRow ax;
CoefficientRow ay;
// fill in ax and ay
A.row(2*i) = ax;
A.row(2*i+1) = ay;
}
The reason of your error is (as Avi explained) that the operator<<
is intended to fill an entire matrix at once. In fact, calling operator<<(Array &A, Array const &b)
assigns b
to the top-left corner of A
and returns a proxy-object which holds a reference to A
and keeps track of how much entries of A
already got assigned to (stored in m_row
, m_currentBlockRows
, m_col
) and overloads operator,
which assigns the next expression to the corresponding position of a
and increases the position accordingly. Finally, when that proxy object gets destructed (which usually happens "at the ;
") the destructor checks if all entries of A
have been filled (and raises a failed assertion, if not).
If you prefer to use the << ,
syntax you could also write:
A.middleRows<2>(2*i) << ax, ay;
With optimizations enabled that should generate the same code as the simple implementation above (so choose whichever is easier to read for you).
N.B.: You could technically (ab)use the CommaInitializer
in a loop, by constructing it outside the loop, assigning it to a variable and then only use the ,
operator inside the loop. I'll intentionally won't give more details on how to do that ...
Eigen: Concatenating matrices and vectors
Does this count as elegant enough?
#include <Eigen/Sparse>
#include <iostream>
using namespace Eigen;
using std::cout;
using std::endl;
int main(int argc, char *argv[])
{
Matrix4f m = Matrix4f::Random();
Matrix3f A = Matrix3f::Constant(0.1);
Vector4f b = Vector4f::Constant(0.2), c = Vector4f::Constant(0.3);
cout << m << endl << endl;
cout << A << endl << endl;
cout << b << endl << endl;
cout << c << endl << endl;
m.block(0, 0, 3, 3) = A;
m.col(3) = b;
m.row(3) = c;
cout << m << endl << endl;
return 0;
}
Note that your question is kinda ambiguous, as the (3,3) position will be determined by the order of assignment between b
and c
.
Append column to matrix, using Eigen library
You can use conservativeResize
for that purpose:
mat.conservativeResize(mat.rows(), mat.cols()+1);
mat.col(mat.cols()-1) = vec;
How replicate eigen::matrix dynamically
The correct way to achieve the same effect as the python's numpy version in C++ would be:
B.replicate<1, 100>();
The above will do the replication as you want.
Or you can use:
B.replicate(1, A.rows());
Related Topics
Const Unsigned Char * to Std::String
Converting a Vector<Int> to String
Understand Op Registration and Kernel Linking in Tensorflow
In C++ I Cannot Grasp Pointers and Classes
Are There Any Issues with Allocating Memory Within Constructor Initialization Lists
How to Write a Variadic Template Recursive Function
Is It Valid for a Lambda To, Essentially, Close Over Itself
What's the Point of Std::Unique_Ptr::Get
C++11 Compiler: Closest to the Standard and How Close
Zero Initialization and Static Initialization of Local Scope Static Variable
How to Perform a Pairwise Binary Operation Between the Elements of Two Containers
Does C++11, 14, 17 or 20 Introduce a Standard Constant for Pi
How to Asynchronously Copy Memory from the Host to the Device Using Thrust and Cuda Streams