Search code examples
c++eigeneigen3

Eigen 3.3.x: How to lamba-operate across all rows?


Suppose I have the following loop:

struct Obj {
   RowVectorXf payload;
   Obj(RowvectorXf payload) : payload(std::move(payload)) {};
}

MatrixXd data = ...

std::vector<Obj> payloads;
for (int i = 0; i < n; i++) {
  payloads.emplace_back(data.row(i)(seq(1,10,2));
}

This is a simplification of my use case, which absolutely does need to step out into the std:: space with a struct containing a slice for sanity and ease of coding. Anyhow, I have started using the unaryExpr's with abandon, and I am curious if there is something like a rowExpr that could perform this function without the for loop (and thus eliminating the visual noise).

// Goal, in pseudo code: 
data.rowExpr([](RowVectorXd row) payloads.emplace_back(row(seq(1,10,2));

Solution

  • With the development branch of Eigen (and the upcoming 3.4 version) you can access the elements of Eigen objects using std-compatible iterators. To iterate row-wise through an Eigen expression, you need to write data.rowwise().begin() and data.rowwise().end() -- (to iterate column-wise, you need to write .colwise().begin() of course). And you can directly pass these to the constructor of std::vector (if the types are compatible).

    Since in your example you also need to convert between double and float you can write something like this:

    auto const& data_ = data.cast<float>().rowwise();
    std::vector<Obj> payloads(data_.begin(), data_.end());
    

    Full working example: https://godbolt.org/z/2x2jFJ