Map two-dimensional array to Eigen::Matrix
Asked Answered
D

2

7

I can't figure out if and how it's possible to map a two-dimensional double array to an Eigen::Matrix. Is it possible to map an array double d[][] which I receive as double** p to an Eigen::Matrix?

While one-dimensinal arrays work fine, I wasn't able to map p to Eigen::Map<Eigen::Matrix<double, n, n>>. Is that possible and how could it be done? The size n is not really constant, but I could accept a hard coded size.


I tried several versions, but none worked. I thought the following should work (assume the size n would be 4).

Eigen::Map<Eigen::Matrix<double, 4, 4>> p_OUTPUT(&p[0][0]);

The code compiles and runs, but only the elements of the first column and the first element of the second column map the correct values. Using p[0] as argument yields the same result. Other versions I tried (for example without the &) did not compile.

Daphie answered 9/11, 2016 at 15:8 Comment(4)
Can you show what you tried and what you want to achieve? Is n a compile time constant? And are you sure p is a double**?Haller
@AviGinsburg Thanks for your reply, I completed my question. The size n is not a constant, but a hard coded size would be OK. And yes, I'm quite sure p is a double** because p[row][col] += ... works.Daphie
See this post.Haller
@AviGinsburg Many thanks, I upvoted your answer at the linked post! I found a very similar solution just at this moment.Daphie
D
9

For the sake of completeness, I found a solution. As mentioned here or here the storage in not contiguous memory is the problem.

The following solution worked for me.

Eigen::MatrixXd ConvertToEigenMatrix(std::vector<std::vector<double>> data)
{
    Eigen::MatrixXd eMatrix(data.size(), data[0].size());
    for (int i = 0; i < data.size(); ++i)
        eMatrix.row(i) = Eigen::VectorXd::Map(&data[i][0], data[0].size());
    return eMatrix;
}
Daphie answered 9/11, 2016 at 17:36 Comment(0)
L
2

The answer you gave yourself is kind of a clue: Eigen, by default, stores matrices in column-major format, meaning that elements from this matrix:

m(0,0)  m(0,1)  m(0,2)
m(1,0)  m(1,1)  m(1,2)
m(2,0)  m(2,1)  m(2,2)

Are stored in a big linear array as:

[m(0,0), m(1,0), m(2,0), m(0,1), m(1,1), m(2,1), m(0,2), m(1,2), m(2,2)]

Your data (judging from your answer) is in row-major format, which is why you're pulling out memory-contiguous rows from your array and assigning them into rows in your result. You can tell Map that your data is in RowMajor format, and it should read your data correctly:

Eigen::Map<Eigen::Matrix<double, 4, 4, Eigen::RowMajor>> p_OUTPUT(p);
Lugansk answered 11/11, 2016 at 18:33 Comment(2)
No, you assume that p points to a contiguous section of memory. For a double** that is not guaranteed.Haller
The original question says that it's a double[][] that is passed to the function as a double**; if it's declared as an array, then it will be contiguous in memory.Lugansk

© 2022 - 2024 — McMap. All rights reserved.