1/*
2 * aggregate.hpp
3 *
4 * Created on: Oct 31, 2015
5 * Author: i-bird
6 */
7
8#ifndef OPENFPM_DATA_SRC_UTIL_AGGREGATE_HPP_
9#define OPENFPM_DATA_SRC_UTIL_AGGREGATE_HPP_
10
11#include <boost/fusion/container/vector.hpp>
12#include <Packer_Unpacker/has_pack_agg.hpp>
13#include "util/copy_compare/copy_compare_aggregates.hpp"
14
15/*! \brief this class is a functor for "for_each" algorithm
16 *
17 * It copy a boost::fusion::vector into another boost::fusion::vector
18 *
19 */
20template<typename bfv>
21struct copy_fusion_vector
22{
23 //! source fusion vector
24 const bfv & src;
25
26 //! destination fusion vector
27 bfv & dst;
28
29 /*! \brief constructor
30 *
31 * It define the copy parameters.
32 *
33 * \param src source fusion vector
34 * \param dst destination fusion vector
35 *
36 */
37 __device__ __host__ inline copy_fusion_vector(const bfv & src, bfv & dst)
38 :src(src),dst(dst){};
39
40#ifdef SE_CLASS1
41 /*! \brief Constructor
42 *
43 * Calling this constructor produce an error. This class store the reference of the object,
44 * this mean that the object passed must not be a temporal object
45 *
46 */
47 inline copy_fusion_vector(const bfv && src, bfv && dst)
48 :src(src),dst(dst)
49 {std::cerr << "Error: " <<__FILE__ << ":" << __LINE__ << " Passing a temporal object\n";};
50#endif
51
52 //! It call the copy function for each property
53 template<typename T>
54 __device__ __host__ inline void operator()(T& t)
55 {
56 // This is the type of the object we have to copy
57 typedef typename boost::fusion::result_of::at_c<bfv,T::value>::type copy_type;
58
59 // Remove the reference from the type to copy
60 typedef typename boost::remove_reference<copy_type>::type copy_rtype;
61
62 meta_copy<copy_rtype>::meta_copy_(boost::fusion::at_c<T::value>(src),boost::fusion::at_c<T::value>(dst));
63 }
64};
65
66#ifdef SE_CLASS3
67
68#define SE3_MAX_PROP(i) i+2
69#define SE3_ADD_PROP(i) size_t[i+1],size_t
70#define SE3_SUB_MAX_PROP -2
71
72/*! \brief An aggregate that accept a boost fusion vector as type
73 *
74 *
75 *
76 */
77template<typename T>
78struct aggregate_bfv
79{
80 //! type the object store
81 typedef T type;
82
83 //! real type the object store
84 typedef T type_real;
85
86 //! data to store
87 type data;
88
89 aggregate_bfv() {};
90
91 static const unsigned int max_prop = boost::mpl::size<type>::type::value;
92 static const unsigned int max_prop_real = boost::mpl::size<type>::type::value + SE3_SUB_MAX_PROP;
93};
94
95/*! \brief aggregate of properties, from a list of object if create a struct that follow the OPENFPM native structure
96 *
97 * see the Wiki for more information about the OPENFPM native structure format
98 *
99 * \tparam list of properties
100 *
101 */
102template<typename ... list>
103struct aggregate
104{
105 typedef boost::fusion::vector<list... , SE3_ADD_PROP(sizeof...(list))> type;
106 typedef boost::fusion::vector<list... > type_real;
107
108 typedef int yes_is_aggregate;
109
110 type data;
111
112 __device__ __host__ inline aggregate()
113 {}
114
115 __device__ __host__ inline aggregate(const aggregate<list ...> & aggr)
116 {
117 this->operator=(aggr);
118 }
119
120 /*! \brief get the properties i
121 *
122 * \return the property i
123 *
124 */
125 template<unsigned int i> typename boost::mpl::at<type,boost::mpl::int_<i>>::type & get()
126 {
127 return boost::fusion::at_c<i>(data);
128 }
129
130 /*! \brief get the properties i
131 *
132 * \return the property i
133 *
134 */
135 template<unsigned int i> const typename boost::mpl::at<type,boost::mpl::int_<i>>::type & get() const
136 {
137 return boost::fusion::at_c<i>(data);
138 }
139
140 /*! \brief it return false if this aggregate has no pointers
141 *
142 *
143 */
144 static bool noPointers()
145 {
146 return !has_pack_gen<aggregate<list ...>>::value;
147 }
148
149 aggregate<list...> & operator=(const aggregate<list...> & ag)
150 {
151 copy_fusion_vector<aggregate<list...>::type> ca(ag.data,this->data);
152
153 boost::mpl::for_each_ref< boost::mpl::range_c<int,0,sizeof...(list)> >(ca);
154
155 return *this;
156 }
157
158 static const unsigned int max_prop = boost::mpl::size<type>::type::value;
159 static const unsigned int max_prop_real = boost::mpl::size<type>::type::value + SE3_SUB_MAX_PROP;
160};
161
162
163
164#else
165
166/*! \brief An aggregate that accept a boost fusion vector as type
167 *
168 *
169 *
170 */
171template<typename T>
172struct aggregate_bfv
173{
174 //! type the object store
175 typedef T type;
176
177 //! real type the object store
178 typedef T type_real;
179
180 //! data to store
181 type data;
182
183 /*! \brief get the properties i
184 *
185 * \return the property i
186 *
187 */
188 template<unsigned int i> typename boost::mpl::at<type,boost::mpl::int_<i>>::type & get()
189 {
190 return boost::fusion::at_c<i>(data);
191 }
192
193 /*! \brief get the properties i
194 *
195 * \return the property i
196 *
197 */
198 template<unsigned int i> const typename boost::mpl::at<type,boost::mpl::int_<i>>::type & get() const
199 {
200 return boost::fusion::at_c<i>(data);
201 }
202
203 static const unsigned int max_prop = boost::mpl::size<type>::type::value;
204};
205
206/*! \brief aggregate of properties, from a list of object if create a struct that follow the OPENFPM native structure
207 *
208 * see the Wiki for more information about the OPENFPM native structure format
209 *
210 * \tparam list of properties
211 *
212 */
213template<typename ... list>
214struct aggregate
215{
216 //! internal type containing the data
217 typedef boost::fusion::vector<list...> type;
218
219 //! real internal type containing the data
220 typedef boost::fusion::vector<list...> type_real;
221
222 typedef int yes_is_aggregate;
223
224 //! the data
225 type data;
226
227 __device__ __host__ inline aggregate()
228 {}
229
230 __device__ __host__ inline aggregate(const aggregate<list ...> & aggr)
231 {
232 this->operator=(aggr);
233 }
234
235 /*! \brief get the properties i
236 *
237 * \return the property i
238 *
239 */
240 template<unsigned int i> __device__ __host__ typename boost::mpl::at<type,boost::mpl::int_<i>>::type & get()
241 {
242 return boost::fusion::at_c<i>(data);
243 }
244
245 /*! \brief it return false if this aggregate has no pointers
246 *
247 *
248 */
249 static bool noPointers()
250 {
251 return !has_pack_gen<aggregate<list ...>>::value;
252 }
253
254 /*! \brief get the properties i
255 *
256 * \return the property i
257 *
258 */
259 template<unsigned int i> __device__ __host__ const typename boost::mpl::at<type,boost::mpl::int_<i>>::type & get() const
260 {
261 return boost::fusion::at_c<i>(data);
262 }
263
264 inline aggregate<list...> & operator=(const aggregate<list...> & ag)
265 {
266 copy_fusion_vector<aggregate<list...>::type> ca(ag.data,this->data);
267
268 boost::mpl::for_each_ref< boost::mpl::range_c<int,0,sizeof...(list)> >(ca);
269
270 return *this;
271 }
272
273 static const unsigned int max_prop = boost::mpl::size<type>::type::value;
274 static const unsigned int max_prop_real = boost::mpl::size<type>::type::value;
275};
276
277#endif
278
279template<typename T, typename Sfinae = void>
280struct is_aggregate: std::false_type {};
281
282
283/*! \brief Check if a type T is an aggregate
284 *
285 * return true if T is an aggregate
286 *
287 */
288template<typename T>
289struct is_aggregate<T, typename Void< typename T::yes_is_aggregate>::type> : std::true_type
290{};
291
292namespace openfpm
293{
294 template<unsigned int p, typename aggr>
295 auto at_c(aggr & agg) -> decltype(boost::fusion::at_c<p>(agg.data))
296 {
297 return boost::fusion::at_c<p>(agg.data);
298 }
299
300 template<unsigned int p, typename aggr>
301 auto get(aggr & agg) -> decltype(boost::fusion::at_c<p>(agg.data))
302 {
303 return boost::fusion::at_c<p>(agg.data);
304 }
305}
306
307#endif /* OPENFPM_DATA_SRC_UTIL_AGGREGATE_HPP_ */
308