Reputation: 539
This question is concerned with C++ and Eigen.
I have a function that computes some vector as Eigen::VectorXd
and stores them into the vector passed as an argument. The return value of the function is the number of iterations done in the function. Below is the pseudocode of the function:
size_t integrate(Eigen::VectorXd& v) {
size_t numIterations = 0;
// do some iterative calculations and increment numIterations
// vNew is generated from the new calculations
v = vNew;
return numIterations;
}
The way I'd like to use this function is as below:
Eigen::MatrixXd q = Eigen::MatrixXd::Zero(numRows, numCols);
for(size_t i = 0; i < numSteps; i++) {
integrate(q.row(i));
}
However this won't compile in Visual Studio. I'm getting a C++ initial value of reference to non-const must be an lvalue
compiler error. My intention is to avoid unnecessary copies and just place the calculation result (a vector) into the matrix in every iteration of the for loop. I understand that row()
does not return a VectorXd
. I've tried a few other things but none worked. What would be an efficient way of filling the rows of a preallocated MatrixXd
in Eigen?
Note: I am aware that I could've just passed the matrix to the function by ref along with the current value of i
and do q.row(i) = vNew;
in integrate()
. However it looks ugly and unnecessary to me. integrate()
really doesn't have to know anything about a MatrixXd
.
Thank you.
Upvotes: 1
Views: 858
Reputation: 18827
You can pass writable references to blocks of matrices using an Eigen::Ref
object. In your case, since rows of (column major) matrices will have an inner stride, you need to explicitly allow that:
size_t integrate(Eigen::Ref<Eigen::VectorXd, 0, Eigen::InnerStride<> > v) {
v.setRandom(); // use `v` as if it was a VectorXd
return 0;
}
For better performance, you should consider either storing q
in row major form, or passing individual columns to integrate
:
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> q; q.setZero(numRows, numCols);
// ...
integrate(q.row(i));
Or:
Eigen::MatrixXd q; q.setZero(numRows, numCols); // you'll need to switch how many rows and cols are to be allocated
// ...
integrate(q.col(i));
In either that case, integrate
could take a simple Eigen::Ref<Eigen::VectorXd>
(aka Eigen::Ref<Eigen::VectorXd, 0, Eigen::InnerStride<1> >
):
size_t integrate(Eigen::Ref<Eigen::VectorXd> v) {
// ...
Upvotes: 2