24

It's quite a simple task, but I was not able to find an answer to it:

Using the Eigen library, suppose I have Matrix2Xd mat and Vector2d vec, where

mat = 1 1 1
      1 1 1
vec = 2 2

Now I need something like mat.addCol(vec) such that afterwards

mat = 1 1 1 2
      1 1 1 2

What is the best (simplest) way to accomplish this?

Please note, that this is not a duplicate of How do you make a matrix out of vectors in eigen?. I don't want to initialy construct the matrix but append to an existing one. Or is there maybe a trick, how to use the comma initialization in this case? The following code will fail:

Matrix2Xd mat(2,3);
Vector2d vec;
mat << 1, 1, 1, 1, 1, 1;
vec << 2, 2;

cout << mat << endl;
mat << vec;             // <-- crashes here
cout << mat << endl;

Edit: The following works, but I don't like the need of a temporary variable for such a basic task. Is there a better way?

Matrix2Xd tmp(2, mat.cols()+1);
tmp << mat, vec;
mat = tmp;
Community
  • 1
  • 1
luator
  • 4,769
  • 3
  • 30
  • 51
  • 1
    You did read the first answer in the dupe: "The matrix m mus have been properly resized first."? An Eigen Matrix has a [`resize`](http://eigen.tuxfamily.org/dox/classEigen_1_1PlainObjectBase.html#afbbb33d14fe7fb9683019a39ce1c659d) member function... Documentation can be googled, or read, at the least. – rubenvb Dec 10 '14 at 15:43
  • 1
    @rubenvb `resize` does not keep the content of the matrix. If I do `mat.resize(2, mat.cols()+1);`, the matrix is filled with some random values afterwards. – luator Dec 10 '14 at 15:49
  • Then you'll need to either create a temporary or initialize it to the correct size. – rubenvb Dec 10 '14 at 15:51
  • @rubenvb The size is not known in the beginning, so this is not possible. I hoped there is a better solution than copying all the data to a temporary :/ – luator Dec 10 '14 at 15:57
  • There is no data structure (that is contiguous in memory, as would be wanted for a numerical matrix) that fullfills your needs. What sizes are we talking about? – rubenvb Dec 10 '14 at 16:10
  • @rubenvb Well, for example the matrix class of the Armadillo library has `insert_cols()` and `insert_rows()`, so I hoped there is something similar in Eigen. But I'm happy with ggaels answer, so I think we can end this discussion. – luator Dec 11 '14 at 08:19
  • 1
    just so you know, those functions might well reallocate the memory, you're just "hiding" that fact from plain view. See e.g. [this question](http://stackoverflow.com/q/24186398/256138) for some more info. – rubenvb Dec 11 '14 at 08:39

1 Answers1

39

You can use conservativeResize for that purpose:

mat.conservativeResize(mat.rows(), mat.cols()+1);
mat.col(mat.cols()-1) = vec;
ggael
  • 28,425
  • 2
  • 65
  • 71
  • 14
    Thanks, this is working. I figured out that it is even possible to write `mat.conservativeResize(NoChange, mat.cols()+1);` which lets the number of rows unchanged. – luator Dec 11 '14 at 08:00
  • Is this approach recommended from a performance perspective? As I understand, conservativeResize() will allocate memory again and copy old data to the new location. Suppose we need to append multiple vectors to the matrix, does this method suffer from performance loss significantly? – Bo Tian Jan 31 '23 at 15:43