Search code examples
c++eigeneigen3

Using Eigen::Map with array of structs


Given an array of structs, how can I use Eigen to, for example, calculate the mean of all Foo.b?

struct Foo {
        int a;
        double b;
        char c;
}

std::vector<Foo> foos;
// push_back some Foos

From the documentation, I think I should be able to do this using an Eigen::Map and setting the stride appropriately, I just can't seem to figure out exactly what it needs to be. I think it should be something like:

using namespace Eigen;
double* bPtr = foos.data() + offsetof(struct Foo, b); // casts omitted for brevity
Map<ArrayXd, Unaligned, InnerStride<sizeof(Foo)>> bMap(bPtr, foos.size());
double mean = bMap.mean();

Relevant documentation here: https://eigen.tuxfamily.org/dox/classEigen_1_1Map.html


Solution

  • The strides in Eigen are always considered as multiple of the size of the Scalar, i.e., you need to write:

    using namespace Eigen;
    Map<ArrayXd, Unaligned, InnerStride<sizeof(Foo)/sizeof(double)> >
       bMap(&foos[0].b, foos.size());
    double mean = bMap.mean();
    

    (Make sure foos is not empty before doing &foos[0].b)

    This happens to work, since double (usually) has an alignment of 8 bytes, i.e., Foo will have padding bytes before b and after c so that sizeof(Foo) is guaranteed to be a multiple of sizeof(double). Add a static assertion, if you want to be sure.

    Usage demo: https://godbolt.org/z/aM-veN

    Warning: This won't work for std::complex<double> unless you somehow make sure that the size of your struct is a multiple of 16 (or a multiple of 8 for std::complex<float>)