2

Is it possible to append an Eigen vector to an another matrix without copying any data? Given matrix m and vector b I would like to modify matrix m such that m = [m, b] without copying data. Is that possible at all?

An example is:

#include <Eigen/Core>
using namespace Eigen;
int main()
{
    MatrixXd m(2,2);
    m << 0, 1, 2, 3;
    VectorXd b(2);
    b << 4, 5;
    return 0;
}

I tried to work with ggael's wonderful reply to a related question . This questions asks how to create a new matrix without copying data, whilst I would like to modify an existing matrix. I could use conservativeResize to append column b to m but only at the expense of allocating new memory. Does somebody kindly have any ideas how to proceed?

fabian
  • 1,413
  • 1
  • 13
  • 24
  • 4
    Are you asking how to append a vector onto a matrix column without copying? If so, ( and I say this as someone who is often acused of premature optimisation, but this feels like premature optimisation ). Id consider profiling to find where cost is actually coming from. The best you can do atm with sacrificing readability is preallocate all the memory you need for your matrix. – George May 08 '19 at 07:27
  • 3
    No, this is straight up impossible. How would you even imagine the memory layout for that? Or do you mean not concatenating into a full Matrix but an expression template and only copy once you access/evaluate it? – PeterT May 08 '19 at 07:51
  • @PeterT Thanks for your comment! I profiled ggael answer to the post I linked with `valgrind massif`. I think the lines `auto example1 = horizcat(mat,2*mat); std::cout << example << std::endl;` do not allocate any new memory. However, I can use `example1` as any other matrix and calculate reductions (for example) without any memory costs. I would like to do the same but instead of using the new object `example1` redefine the existing matrix `m` as mentioned above. Do you think that's not possible? – fabian May 08 '19 at 08:10
  • 3
    @fabian no that's not possible. `m` already has a type and `horizcat` only works by using expression template types. As soon as you convert the expression template to a matrix it will copy (or move in some cases, not this one though). – PeterT May 08 '19 at 08:21

1 Answers1

1

The only solution I can think of, is to store m and b in the same matrix from the beginning:

Eigen::MatrixXd mb(2,2+1);
Eigen::Ref<Eigen::MatrixXd> m = mb.leftCols(2);
Eigen::Ref<Eigen::VectorXd> b = mb.col(2);

After these lines m and b are read/writable references to blocks of the bigger mb matrix and they stay valid as long as mb is not resized (or destructed). However, you can't easily resize m (you could with a placement-new, but I doubt you really need this).

If you already have data allocated for m and b and want to have their actual data next to each other, you will need to copy something (unless the data was next to each other already).

chtz
  • 17,329
  • 4
  • 26
  • 56