After a long talk with Evgeny Panasyuk, I ended up doing something a bit different. Since I wanted to be able to do some simple arithmetic operations on the data structures, I decided to use Eigen::Map
rather than Boost::multi_array
since it offers a wide range of operators as well as a clear documentation.
Thus, the higher-level loop is handled by boost::fusion::for_each
and the lower-level loops are handled by Eigen. The arrays are mapped linearly to Eigen vectors. The sizes are passed in data_eigen
's constructor.
#include <iostream>
#include <boost/fusion/adapted/struct/adapt_struct.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <boost/bind.hpp>
#include <Eigen/Core>
namespace demo
{
template<typename T, int SIZE1, int SIZE2>
struct data
{
T ar1[SIZE1][SIZE2];
T ar2[SIZE1][SIZE2];
};
template<typename T>
struct EigenMap
{
typedef Eigen::Map<Eigen::Matrix<T, Eigen::Dynamic, 1> > type;
};
template<typename T>
struct data_eigen
{
template <int SIZE1, int SIZE2>
data_eigen(data<T,SIZE1,SIZE2>& src)
: ar1(typename EigenMap<T>::type(&src.ar1[0][0], SIZE1*SIZE2)),
ar2(typename EigenMap<T>::type(&src.ar2[0][0], SIZE1*SIZE2))
{
}
typename EigenMap<T>::type ar1;
typename EigenMap<T>::type ar2;
};
struct print
{
template<typename T>
void operator()(const Eigen::Map<Eigen::Matrix<T, Eigen::Dynamic, 1> >& t) const
{
std::cout << t.transpose() << std::endl;
}
};
struct scalarMult
{
template<typename T, typename U>
void operator()(T& t, U& u) const
{
t *= u;
}
};
}
BOOST_FUSION_ADAPT_TPL_STRUCT
(
(T),
(demo::data_eigen) (T),
(typename demo::EigenMap<T>::type, ar1)
(typename demo::EigenMap<T>::type, ar2)
)
int main()
{
typedef float REALTYPE;
const int SIZE1 = 2;
const int SIZE2 = 2;
// Basic data structure with multidimensional arrays
demo::data<REALTYPE, SIZE1, SIZE2> d;
for (unsigned int i = 0; i < SIZE1; ++i)
for (unsigned int j = 0; j < SIZE2; ++j)
{
d.ar1[i][j] = (i+1)*(j+1);
d.ar2[i][j] = i + j;
}
// Eigen::Map + BOOST_FUSION_ADAPT_TPL_STRUCT
demo::data_eigen<REALTYPE> eig_d(d);
std::cout << "d:" << std::endl;
boost::fusion::for_each(eig_d, demo::print());
std::cout << std::endl;
boost::fusion::for_each(eig_d, boost::bind<void>(demo::scalarMult(), _1, 2.0));
std::cout << "2 * d:" << std::endl;
boost::fusion::for_each(eig_d, demo::print());
std::cout << std::endl;
}