1

I have an Eigen Array2Xd and I want to put each of its rows into std::vector<double>.

The spline_knots is an Array2Xd of size (2, 4) with following values:

Array2Xd spline_knots(2, 4);
spline_knots << -1, 0, 30.57, 60.83,
                 0, 0, 9.73,  15.44;

I tried the following based on this answer:

vector<double> knot_xs(spline_knots.row(0).data(), 
                           spline_knots.row(0).data() + spline_knots.row(0).size());
vector<double> knot_ys(spline_knots.row(1).data(), 
                           spline_knots.row(1).data() + spline_knots.row(1).size());

However trying to copy each row into a vector with the above code I get the following result, which is very weird (first row begins with the correct elements, then zeros; second row has only zeros and ends with the third element of first row):

kont_xs:   -1   0   0   0 
knot_ys:    0   0   0   30.57

What is wrong here, and how can I create the vector from a row of the 2D array without a loop?

zardosht
  • 3,014
  • 2
  • 24
  • 32
  • Have you tried the loop version, to see if that works? Could you show the code that lets you know that `spline_knots` actually has different values than are in the vectors. – cigien Jun 12 '20 at 18:26
  • Just use `.row(0).begin()` and `.row(0).end()` (requires the master branch of Eigen) – chtz Jun 12 '20 at 18:28
  • @cigien Yes, the loop version works. And as said, the `spline_knots` has correct values (I print it using `cout`). – zardosht Jun 12 '20 at 19:00
  • @chtz Unfortunately it seems I don't have the master branch of Eigen in my project, and I can't change it. Using `row(0).begin()` I get the error `class "Eigen::Block, 1, -1, false>" has no member "begin"`. – zardosht Jun 12 '20 at 19:01
  • Ok, could you *share* that code? It would help to know there's nothing too weird going on. – cigien Jun 12 '20 at 19:01
  • @cigien Unfortunately the code is quite work in progress. I will send the Github link as soon as it is more clean. But the question is clear: how can I copy a row of an Array2Xd into a `vector` without loop. – zardosht Jun 12 '20 at 19:28

1 Answers1

2

Figured it out. The problem is related to storage order, the way how Eigen lays out a two dimensional array in memory. There are two possible layouts: RowMajor and ColumnMajor. The default layout is ColumnMajor, which stores the 2D array elements column-wise.

Knowing this, the weird result I get makes sense. The .row(0).data() returns the pointer to the first element of the first row. The .row(0).size() is 4 and .row(0).data() + 4 takes the first 4 elements column-wise: [-1, 0, 0, 0]. Same argument for the second column which starts at (1, 0) element, and counting 4 elements column-wise leads to [0, 0, 0, 30.57].

There are two solutions:

  • Make the Array/Matrix layout row-major:
Array<double, 2, Dynamic, RowMajor> arr(2, 6);
arr << 1, 2, 3, 4
       5, 6, 7, 8;

vector<double> row1_vec(arr.row(0).data(), arr.row(0).data() + arr.cols());

// row1_vec:   1, 2, 3, 4

Array2Xd arr(2, 4);
arr << 1, 2, 3, 4, 
       5, 6, 7, 8;

vector<double> row1_vec(arr.cols());
Map<RowVectorXd>(&row1_vec[0], 1, arr.cols()) = arr.row(0);

// row1_vec:   1, 2, 3, 4
zardosht
  • 3,014
  • 2
  • 24
  • 32