Last active
February 25, 2018 13:00
-
-
Save mlund/0b74c6951d92897042e8c1225e75fb75 to your computer and use it in GitHub Desktop.
Eigen facade or view for structured data in STL vector/array (Eigen3 and C++14 required)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <vector> | |
#include <iostream> | |
#include <type_traits> | |
#include <Eigen/Eigen> | |
/** | |
* @brief Eigen::Map facade to access data members in STL vectors/arrays | |
* | |
* No data is copied and modifications of the Eigen object | |
* modifies the original container and vice versa. | |
* | |
* Example: | |
* | |
* struct Particle { | |
* double mass=2.0; | |
* Eigen::Vector3d velocity; | |
* int type; | |
* }; | |
* | |
* std::vector<Particle> v(10); | |
* auto m1 = asEigenVector(v.begin, v.end(), &Particle::velocity); --> 3x10 maxtix view | |
* auto m2 = asEigenMatrix(v.begin, v.end(), &Particle::mass); --> 1x10 vector view | |
* | |
* @warning Be careful that objects are properly aligned and divisible with `sizeof<double>` | |
*/ | |
template<typename matrix=Eigen::MatrixXd, typename dbl=typename matrix::Scalar, class iter, class memberptr> | |
auto asEigenMatrix(iter begin, iter end, memberptr m) { | |
typedef typename std::iterator_traits<iter>::value_type T; | |
static_assert( sizeof(T) % sizeof(dbl) == 0, "value_type size must multiples of double"); | |
const size_t s = sizeof(T) / sizeof(dbl); | |
const size_t cols = sizeof(((T *) 0)->*m) / sizeof(dbl); | |
return Eigen::Map<matrix, 0, Eigen::Stride<1,s>>((dbl*)&(*begin.*m), end-begin, cols).array(); | |
} | |
template<typename matrix=Eigen::MatrixXd, typename dbl=typename matrix::Scalar, class iter, class memberptr> | |
auto asEigenVector(iter begin, iter end, memberptr m) { | |
typedef typename std::iterator_traits<iter>::value_type T; | |
static_assert( std::is_same<dbl&, decltype(((T *) 0)->*m)>::value, "member must be a scalar"); | |
return asEigenMatrix<matrix>(begin, end, m).col(0); | |
} | |
struct Particle { | |
double mass=2.0; | |
Eigen::Vector3d velocity; | |
int type; | |
}; | |
int main() { | |
std::vector<Particle> d(5); | |
auto m = asEigenVector( d.begin(), d.end(), &Particle::mass); // 1x5 vector | |
auto v = asEigenMatrix( d.begin(), d.end(), &Particle::velocity);// 3x5 matrix | |
d[1].mass = 0; // Map points to original data | |
v = v.setRandom(); // random positions | |
auto p = v.colwise() * m; // momenta, p=mv | |
std::cout << "masses:\n\n" << m << "\n\n"; | |
std::cout << "velocities:\n\n" << v << "\n\n"; | |
std::cout << "momenta:\n\n" << p << "\n"; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment