Reputation: 67
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
Upvotes: 0
Views: 783
Reputation: 18817
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>
)
Upvotes: 3