What I ask is a generalization of this question . In particular, I would like to create a C ++ Eigen wrapper around the old C and Fortran library, which uses a 2D data structure:
[ x[0,0] ... x[0,w-1] ] [ u[0,0] ... u[0,w-1] ] [ ... ] [ x[c-1,0] ... x[c-1,w-1] ] [ u[c-1,0] ... u[c-1,w-1] ]
where each of the entries x[i,j] and u[i,j] are the very columns of vectors of size ( nx1 ) and ( mx1 ) respectively. This leads to some complicated (and error prone) pointer arithmetic, as well as some very unreadable code.
Therefore, I want to write an Eigen class whose sole purpose is to simplify the extraction of records of this matrix as much as possible. In C ++ 14, this looks like data_getter.h :
#ifndef DATA_GETTER_HEADER
and here is a test program demonstrating how this works:
#include <iostream> #include <vector> #include "Eigen/Dense" #include "data_getter.h" using namespace std; using namespace Eigen; template<typename T> void printSize(MatrixBase<T> &mat) { cout << T::RowsAtCompileTime << " x " << T::ColsAtCompileTime; } int main() { using T = double; const int n = 2; const int m = 3; const int c = 2; const int w = 5; const int size = w * (c * (n + m)); std::vector<T> vec; for (int i = 0; i < size; ++i) vec.push_back(i); /* Define the interface that we will use a lot */ using Data = DataGetter<T, n, m, c, w>; /* Now let map that pointer to some submatrices */ Ref<Matrix<T, (n + m) * c, w>> allData = Data::asMatrix(vec.data()); Ref<Matrix<T, n, w>> x1 = Data::X(vec.data(), 1); Ref<Matrix<T, n, c>> xc2 = Data::Xc(vec.data(), 2); Ref<Matrix<T, n + m, c>> xuc2 = Data::C(vec.data(), 2); Ref<Matrix<T, n, 1>> x12 = Data::X(vec.data(), 1, 2); cout << "Data::asMatrix( T* ): "; printSize(allData); cout << endl << endl << allData << endl << endl; cout << "Data::X( T*, 1 ) : "; printSize(x1); cout << endl << endl << x1 << endl << endl; cout << "Data::Xc( T*, 2 ) : "; printSize(xc2); cout << endl << endl << xc2 << endl << endl; cout << "Data::C( T*, 2 ) : "; printSize(xuc2); cout << endl << endl << xuc2 << endl << endl; cout << "Data::X( T*, 1, 2 ) : "; printSize(x12); cout << endl << endl << x12 << endl << endl; /* Now changes to x12 should be reflected in the other variables */ x12.setZero(); cout << "-----" << endl << endl << "x12.setZero() " << endl << endl << "-----" << endl; cout << "allData" << endl << endl << allData << endl << endl; cout << "x1" << endl << endl << x1 << endl << endl; cout << "xc2" << endl << endl << xc2 << endl << endl; cout << "xuc2" << endl << endl << xuc2 << endl << endl; cout << "x12" << endl << endl << x12 << endl << endl; return 0; }
In particular, it produces the following output (as expected):
Data::asMatrix( T* ): 10 x 5 0 10 20 30 40 1 11 21 31 41 2 12 22 32 42 3 13 23 33 43 4 14 24 34 44 5 15 25 35 45 6 16 26 36 46 7 17 27 37 47 8 18 28 38 48 9 19 29 39 49 Data::X( T*, 1 ) : 2 x 5 5 15 25 35 45 6 16 26 36 46 Data::Xc( T*, 2 ) : 2 x 2 20 25 21 26 Data::C( T*, 2 ) : 5 x 2 20 25 21 26 22 27 23 28 24 29 Data::X( T*, 1, 2 ) : 2 x 1 25 26 ----- x12.setZero() ----- allData 0 10 20 30 40 1 11 21 31 41 2 12 22 32 42 3 13 23 33 43 4 14 24 34 44 5 15 0 35 45 6 16 0 36 46 7 17 27 37 47 8 18 28 38 48 9 19 29 39 49 x1 5 15 0 35 45 6 16 0 36 46 xc2 20 0 21 0 xuc2 20 0 21 0 22 27 23 28 24 29 x12 0 0
The problem is that compile-time runtime checks on dimensions do not work. In data_getter.h you can notice that I have imposed a bunch of static_assert on the dimensions. This may seem a little redundant, but I wanted to make sure that the expressions actually do compilation operations so that we can get the size checks. If they were dynamic expressions, then the dimensions would be -1.
However, although the entire static_assert pass passes, link references are not checked. For example, if we change the following line in a test program
Ref<Matrix<T, (n + m) * c, w>> allData = Data::asMatrix(vec.data());
in
Ref<Matrix<T, (n + m) * c + 1, w>> allData = Data::asMatrix(vec.data());
The code compiles, but crashes at runtime. This seems to indicate that Ref discarding sizes. So how should I define these variables?
One idea that may come to mind is to define these return values โโas auto . However, this is clearly discouraged by the Eigen docs , because if we end up using output in a loop, it can cause the expression to evaluate again and again. It is for this reason that I use Ref s. Also, it just seems like I want to clearly indicate the size, since we know it at compile time ...
So is this a bug in Ref? and what type should I use for variables that spit out with all my access methods?