Writing data into Eigen::Matrix row - c++

I would like to write the (row-major ordered) data into a row of an Eigen::Matrix. I found a way, but to me it looks inefficient. Is there a faster/more concise way?
// 24 x 16 D Matrix
Eigen::Matrix<double, JOINT_NUM, 16> Mat;
// 4 x 4 D Matrix, stored in row major order to paste data correctly
Eigen::Matrix<double, 4, 4, Eigen::RowMajor> row0_rowMajor = row0;
// copy data from row major Matrix into first row of Mat
Mat.row(0) = Eigen::Map<Eigen::RowVectorXd>(row0_rowMajor.data(), row0_rowMajor.size());
Thanks!
Edit:
Here is a minimal working example, you can compile it with g++ -I/usr/include/eigen3 file.cpp and run with ./a.out:
#include <Eigen/Core>
#include <iostream>
int main(int argc, const char* argv[]) {
// 24 x 16 D Matrix
Eigen::Matrix<double, 2, 16> Mat_rowMajor;
Eigen::Matrix<double, 2, 16> Mat;
Mat.setZero();
Mat_rowMajor.setZero();
Eigen::Matrix4d row0;
row0 << 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15;
// 4 x 4 D Matrix, stored in row major order to paste data correctly
Eigen::Matrix<double, 4, 4, Eigen::RowMajor> row0_rowMajor = row0;
// copy data from row major Matrix into first row of Mat
Mat.row(0) = Eigen::Map<Eigen::RowVectorXd>(row0.data(), row0.size());
Mat_rowMajor.row(0) = Eigen::Map<Eigen::RowVectorXd>(row0_rowMajor.data(), row0_rowMajor.size());
std::cout << "row0:\n" << row0 << std::endl;
std::cout << "Matrix:\n" << Mat << std::endl;
std::cout << "Matrix Row-Major:\n" << Mat_rowMajor << std::endl;
return 1;
}
My aim is to get rid of the copying into the Eigen::Matrix<double, 4, 4, Eigen::RowMajor>, and work directly with row0, and remove the Eigen::Map... by just a simple copy if possible. It just makes the code much more readable, concise, and less prone to errors. Also, the copying is slow for larger matrices, which I'd like to avoid.

Eigen doesn't come with a vector-like view of a matrix, as far as I know. So the approach of using a Map is already pretty good. However, it is also very brittle.
Since your ultimate goal is to store into a row of a column-major matrix, vectorization is out of the question. That's why I don't think you can improve performance by doing something fancy. So you can go for something simple instead. Like this:
Eigen::Matrix<double, JOINT_NUM, 16> Mat;
const Eigen::Matrix4d row0 = ...;
auto out_row = Mat.row(0);
for(Eigen::Index i = 0; i < row0.rows(); ++i)
out_row.segment(i * row0.cols(), row0.cols()) = row0.row(i);
At least this makes it clear what is going on.
Side note: The reason why Eigen doesn't have a convenient view is likely that this keeps you stuck between a rock and a hard place when you want to support the general case:
Practically all methods should work on both block expressions and full matrices. In a block expression, the Map approach doesn't work because there is a gap between consecutive columns (in a column-major matrix).
So instead you would need a custom view type to translate indices. However, now you are translating from a 1D index to a 2D index, which requires a costly division on every access.
Other linear algebra packages like Numpy have the same issue. However, Numpy for example is more liberal in its memory allocations and would create a copy if it needs to. The only Eigen type that does copies if required, is Eigen::Ref and that comes with its own set of problems.

With Eigen 3.4 you can simply use the reshaped<>() mechanism:
Mat.row(0) = row0.reshaped<Eigen::RowMajor>();
Prior to Eigen 3.4, you can manually create a map (onto the data of Mat.row(0)), but you need to manually calculate some strides. E.g., if Mat is a column-major matrix, the index difference between two columns would be Mat.rows() (which would correspond to the "outer stride"), the difference between two rows would be 4*Mat.rows() (corresponding to the "inner stride"):
Eigen::Matrix4d::Map(Mat.row(0).data(), // address of first element
Eigen::Stride<Eigen::Dynamic,Eigen::Dynamic> // stride object
(Mat.rows(), // column-stride/"outer stride"
4*Mat.rows()) // row-stride/"inner stride"
) = row0; // end of `Map()` and assignment of a 4x4 matrix `row0`
Alternatively, you could create a Map from a row-major 4x4 matrix, which would switch the meaning of inner and outer stride.
Overall, if you intend to store matrices in rows of Mat you should also consider making Mat itself row-major. In that case, each row of Mat would be stored in 16 consecutive bytes making the Map easier to create (and having memory locality is often advantageous anyway).

Related

How to access multiple elements in c++ Eigen array?

I want to retrieve certain elements in an Eigen array and return them as a vector. I use the following code:
Eigen::ArrayXXi test;
test.resize(5,5);
test.setRandom();
Eigen::Matrix<int, 2, 3> inds;
inds<<0, 2, 3, 2, 3, 1;
auto res = test(inds.row(0), inds.row(1));
std::cout<<"test: \n"<<test <<std::endl;
std::cout<<"inds: \n"<<inds <<std::endl;
std::cout<<"res: \n"<<res <<std::endl;
The output is:
test:
730547559 -649503489 -48539462 893772102 -1038736613
-226810938 -353856438 276748203 291438716 -552146456
607950953 576018668 -290373134 466641602 -779039257
640895091 -477225175 28778235 -769652652 653214605
884005969 115899597 971155939 229713912 -737276042
inds:
0 2 3
2 3 1
res:
-48539462 893772102 -649503489
-290373134 466641602 576018668
28778235 -769652652 -477225175
The result is a matrix. I note that the diagonal of the matrix is the result I want. I could use res.diagonal() to retrieve the vector. However, I am still wondering if I can do the same thing in a more efficient way.
You can reshape the test Array to a column and then use the single-index access operator:
auto res = test.reshaped()(inds.row(0) + test.rows() * inds.row(1));
Generally, be careful when using auto with Eigen expressions (this case is fine, as long as test and inds are still valid when res is used).

Vectorize a Symmetric Matrix

I would like to write a function with the following signature
VectorXd vectorize (const MatrixXd&);
which returns the contents of a symmetric matrix in VectorXd form, without repeated elements. For example,
int n = 3; // n may be much larger in practice.
MatrixXd sym(n, n);
sym << 9, 2, 3,
2, 8, 4,
3, 4, 7;
std::cout << vectorize(sym) << std::endl;
should return:
9
2
3
8
4
7
The order of elements within vec is not important, provided it is systematic. What is important for my purposes is to return the data of sym without the repeated elements, because sym is always assumed to be symmetric. That is, I want to return the elements of the upper or lower triangular "view" of sym in VectorXd form.
I have naively implemented vectorize with nested for loops, but this function may be called very often within my program (over 1 million times). My question is thus: what is the most computationally efficient way to write vectorize? I was hoping to use Eigen's triangularView, but I do not see how.
Thank you in advance.
Regarding efficiency, you could write a single for loop with column-wise (and thus vectorized) copies:
VectorXd res(mat.rows()*(mat.cols()+1)/2);
Index size = mat.rows();
Index offset = 0;
for(Index j=0; j<mat.cols(); ++j) {
res.segment(offset,size) = mat.col(j).tail(size);
offset += size;
size--;
}
In practice, I expect that the compiler already fully vectorized your nested loop, and thus speed should be roughly the same.

Map two-dimensional array to Eigen::Matrix

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.
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;
}
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);

pointer to sub-row of Eigen MatrixXd that behaves like a VectorXd

I have an Eigen MatrixXd and need a pointer to some subsequent entries of some row. I would like to be able to use this pointer. I have something like this:
Eigen::MatrixXd* matrix = new MatrixXd(3, 3);
(*matrix) << 1, 2, 3,
4, 5, 6,
7, 8, 9;
Block<MatrixXd, 1, Dynamic, false, true> full_row = (*matrix).row(1);
// this gives me the full row. I am interested only in the row containing 5 6.
Block<MatrixXd> part_row = (*matrix).block(1, 1, 1, 2);
// this gives me the partial row that I want, but now i need two indices to
// access an element.
part_row(0, 1) = 3; // works
part_row(1) = 3; // gives compiler error
I would like to be able to directly access the partial row, without having to copy the values. This is really important, since it has to be done often and I cannot afford to copy vectors back and forth. (I believe I cannot expect the compiler to optimize out the copying, since the sizes of the matrices are generally unknown). Any help is greatly appreciated. Cheers!
You need to specify that your submatrix is a vector:
Block<MatrixXd,1,Dynamic> part_row(*matrix, 1, 1, 1, 2);

get # of rows and # of columns of a square matrix from vector c++

I have a vector of size lets say 4:
vector <double> example;
example.push_back(3.0);
example.push_back(10.1);
example.push_back(33.1);
example.push_back(23.3);
so I have [3 10.1 33.1 23.3];
If I know I have a square matrix (i.e. sizes can only be 4, 9, 16, 25, 36, 49...)
How do I know the # of rows which is the same as the number of columns in c++??
so I am doing
int size, col, row;
size = example.size();
row = col = sqrt(size);
Is there other a faster way??
A two-dimensional array allocated as contiguous locations will be faster than a vector of vectors or an array of vectors. A vector has a slight disadvantage in that functions must be called to access the vector (although the compiler may optimize these out).
For example:
enum {MATRIX_SIZE = 4};
// Define a square matrix of integers
int matrix[MATRIX_SIZE * MATRIX_SIZE];
// Set value at row: 3, column 2 to 64:
unsigned int row = 3;
unsigned int column = 2;
matrix[row * MATRIX_SIZE + column] = 64;
Using vectors has a slight overhead.
The question to answer is whether the difference in performance between arrays and vectors is worthwhile. The person hours in maintenance and development may outweigh the benefit in performance (i.e. a slower but correct and released applications may be worth more than a faster application that is released much later to the market place or consumers).