Assume that mat
below is of type Eigen::MatrixXd
and already contains some data. In an attempt to avoid duplicating memory, I tried to instantiate a flann::Matrix<double>
object from the pointer to the raw memory chunk allocated by Eigen3:
flann::Matrix<double> input(const_cast<double *>(mat.data(), mat.rows(), mat.cols())
However, my algorithm outputs garbage, but is just fine with the ugly:
flann::Matrix<double> input(new double[mat.rows()*mat.cols()], mat.rows(), mat.cols());
for (int i = 0; i < mat.rows(); i++) {
for (int j = 0; j < mat.cols(); j++) {
input[i][j] = mat(i, j);
}
}
I investigated the option to subclass the base Matrix_
type from flann to create an adaptor to Eigen3 matrices. The problem though is that Matrix_
relies on the implementation of the []
operator in its interace. It makes me feel that I might encounter the same memory issue than in the simple (but broken) solution shown above.
What do you think could explain such behaviour ?
Eigen::Map
is sweet, but not what I'm looking for. It would suck to re-write my code to use stl::vector<std::vector<double> >
as base types and Eigen::Map
them to Eigen::MatrixXd
Resizing. The current size of a matrix can be retrieved by rows(), cols() and size(). These methods return the number of rows, the number of columns and the number of coefficients, respectively. Resizing a dynamic-size matrix is done by the resize() method.
The default in Eigen is column-major. Naturally, most of the development and testing of the Eigen library is thus done with column-major matrices. This means that, even though we aim to support column-major and row-major storage orders transparently, the Eigen library may well work best with column-major matrices.
The next line of the main function introduces a new type: VectorXd . This represents a (column) vector of arbitrary size. Here, the vector v is created to contain 3 coefficients which are left uninitialized.
I also got confirmation from Marius Muja, the author of libflann, that flann::Matrix
stores in row-major order whereas Eigen uses column-major by default. Here's the answer that he gave me by email:
The problem is most likely the fact that Eigen stores matrices in column-major order > while FLANN requires them in row-major order.
A solution would be to use
Matrix<double, Dynamic, Dynamic, RowMajor>
instead ofMatrixXd
, then FLANN and Eigen matrices can share the same memory, otherwise a copy will be needed. Marius Muja
Eigen::Matrix store data continously, so you shouldn't get stride problems. Alignment may be the problem if you are trying to construct an Eigen::Matrix on it (but I can't imagine how this is possible). By default Eigen::Matrix is column-major, this may be your problem. I don't know how flann treat matrices, if they are row-major, then that's it. The following example work with Eigen::Matrix< double, -1, -1, Eigen::RowMajor > for mat and fails with Eigen::MatrixXd.
int k = 0;
for (int i = 0; i<mat.rows(); ++i)
{
for (int j = 0; j<mat.cols(); ++j, ++k) {
mat(i, j) = k;
}
}
double* mptr = mat.data();
for (int i = 0; i<mat.rows() * mat.cols(); ++i) {
assert(mptr[i] == i);
}
I haven't got your complain about Eigen::Map. It is the nicest way to treat some data as eigen matrix (note that it will still be column-major by default), subclassing from matrix, or implementing custom eigen expression may be painfull.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With