1/*
2 * memory_conf.hpp
3 *
4 * Created on: Aug 28, 2014
5 * Author: Pietro Incardona
6 */
7
8#ifndef MEMORY_CONF_HPP_
9#define MEMORY_CONF_HPP_
10
11#include "util/variadic_to_vmpl.hpp"
12#include "t_to_memory_c.hpp"
13#include "Vector/vect_isel.hpp"
14#include "Vector/util.hpp"
15
16constexpr int SOA_layout_IA = 2;
17constexpr int SOA_layout = 1;
18constexpr int AOS_layout = 0;
19
20/*! \brief This class convert a boost::mpl::fusion/vector to a boost::mpl::fusion/vector with memory_c interleaved
21 *
22 * This class convert a boost::mpl::fusion/vector to a boost::mpl::fusion/vector with memory_c interleaved
23 *
24 * Example:
25 *
26 * typedef boost::mpl::vector<float,float,float[3][3], ... > A
27 *
28 * inter_memc<A>
29 *
30 * produce
31 *
32 * boost::fusion::vector<memory_c<float>,memory_c<float>, memory_c<multi_array<boost::mpl::vector<float,3,3>, ...... >
33 *
34 * \param Seq Is suppose to be an boost::mpl::vector/fusion
35 *
36 */
37template<typename Seq>
38struct inter_memc
39{
40 typedef typename v_transform<t_to_memory_c,Seq>::type type;
41};
42
43/*! \brief This class convert a boost::mpl::fusion/vector to a boost::mpl::fusion/vector with memory_c<.....,MEMORY_C_REDUCED> interleaved
44 *
45 * This class convert a boost::mpl::fusion/vector to a boost::mpl::fusion/vector with memory_c<.....,MEMORY_C_REDUCED> interleaved
46 *
47 * Example:
48 *
49 * typedef boost::mpl::vector<float,float,float[3][3], ... > A
50 *
51 * inter_memc<A>
52 *
53 * produce
54 *
55 * boost::fusion::vector<memory_c<float>,memory_c<float>, memory_c<multi_array<boost::mpl::vector<float,3,3>, ...... >
56 *
57 * \param Seq Is suppose to be an boost::mpl::vector/fusion
58 *
59 */
60template<typename Seq>
61struct inter_memc_red
62{
63 typedef typename v_transform<t_to_memory_c_red,Seq>::type type;
64};
65
66/*! \brief Transform the boost::fusion::vector into memory specification (memory_traits)
67 *
68 * Transform the boost::fusion::vector into memory_traits.
69 * In this implementation we interleave each property of the base type with memory_c
70 *
71 * We basically create a buffer for each property
72 *
73 * \see see inter_mem_c for detail
74 *
75 * \param T base type (T::type must define a boost::fusion::vector )
76 *
77 *
78 */
79template<typename T>
80struct memory_traits_inte
81{
82 //! for each element in the vector interleave memory_c
83 typedef typename inter_memc<typename T::type>::type type;
84
85 //! indicate that it change the memory layout from the original
86 typedef int yes_is_inte;
87
88 typedef boost::mpl::int_<SOA_layout_IA> type_value;
89
90 /*! \brief Return a reference to the selected element
91 *
92 * \param data object from where to take the element
93 * \param g1 grid information
94 * \param v1 element id
95 *
96 * \return a reference to the object selected
97 *
98 */
99 template<unsigned int p, typename data_type, typename g1_type, typename key_type>
100 __host__ __device__ static inline auto get(data_type & data_, const g1_type & g1, const key_type & v1) -> decltype(boost::fusion::at_c<p>(data_).mem_r.operator[](g1.LinId(v1)))
101 {
102 return boost::fusion::at_c<p>(data_).mem_r.operator[](g1.LinId(v1));
103 }
104
105 /*! \brief Return a reference to the selected element
106 *
107 * \param data object from where to take the element
108 * \param g1 grid information
109 * \param v1 element id
110 *
111 * \return a reference to the object selected
112 *
113 */
114 template<unsigned int p, typename data_type, typename g1_type>
115 __host__ __device__ static inline auto get_lin(data_type & data_, const g1_type & g1, size_t lin_id) -> decltype(boost::fusion::at_c<p>(data_).mem_r.operator[](lin_id))
116 {
117 return boost::fusion::at_c<p>(data_).mem_r.operator[](lin_id);
118 }
119
120 /*! \brief Return a reference to the selected element
121 *
122 * \param data object from where to take the element
123 * \param g1 grid information
124 * \param v1 element id
125 *
126 * \return a const reference to the object selected
127 *
128 */
129 template<unsigned int p, typename data_type, typename g1_type, typename key_type>
130 __host__ __device__ static inline auto get_c(const data_type & data_, const g1_type & g1, const key_type & v1) -> decltype(boost::fusion::at_c<p>(data_).mem_r.operator[](g1.LinId(v1)))
131 {
132 return boost::fusion::at_c<p>(data_).mem_r.operator[](g1.LinId(v1));
133 }
134
135 /*! \brief Return a reference to the selected element
136 *
137 * \param data object from where to take the element
138 * \param g1 grid information
139 * \param v1 element id
140 *
141 * \return a const reference to the object selected
142 *
143 */
144 template<unsigned int p, typename data_type, typename g1_type>
145 __host__ __device__ static inline auto get_lin_c(const data_type & data_, const g1_type & g1, size_t lin_id) -> decltype(boost::fusion::at_c<p>(data_).mem_r.operator[](lin_id))
146 {
147 return boost::fusion::at_c<p>(data_).mem_r.operator[](lin_id);
148 }
149};
150
151/*! \brief Transform the boost::fusion::vector into memory specification (memory_traits)
152 *
153 * Transform the boost::fusion::vector into memory_traits.
154 * In this implementation we interleave each property of the base type with memory_c
155 *
156 * We basically create a buffer for each property
157 *
158 * \see see inter_mem_c for detail
159 *
160 * \param T base type (T::type must define a boost::fusion::vector )
161 *
162 *
163 */
164/*template<typename T>
165struct memory_traits_inte_red
166{
167 //! for each element in the vector interleave memory_c
168 typedef typename inter_memc_red<typename T::type>::type type;
169
170 //! indicate that it change the memory layout from the original
171 typedef int yes_is_inte;
172};*/
173
174/*! \brief small meta-function to get the type of the memory
175 *
176 *
177 */
178template<typename T, bool is_agg>
179struct memory_traits_lin_type
180{
181 typedef memory_c<typename T::type> type;
182};
183
184/*! \brief small meta-function to get the type of the memory
185 *
186 *
187 */
188template<typename T>
189struct memory_traits_lin_type<T,false>
190{
191 typedef void type;
192};
193
194/*! \brief Transform the boost::fusion::vector into memory specification (memory_traits)
195 *
196 * Transform the boost::fusion::vector into memory specification (memory_traits).
197 * In this implementation we create a buffer of base type with memory_c
198 *
199 * We basically create a buffer for each property
200 *
201 * \param T base type (T::type must define a boost::fusion::vector )
202 *
203 *
204 */
205
206template<typename T>
207struct memory_traits_lin
208{
209 //! for each element in the vector interleave memory_c
210 typedef typename memory_traits_lin_type<T,openfpm::vect_isel<T>::value == OPENFPM_NATIVE>::type type;
211
212 typedef int yes_is_tlin;
213
214 typedef boost::mpl::int_<AOS_layout> type_value;
215
216 /*! \brief Return a reference to the selected element
217 *
218 * \param data object from where to take the element
219 * \param g1 grid information
220 * \param v1 element id
221 *
222 * \return a reference to the object selected
223 *
224 */
225 template<unsigned int p, typename data_type, typename g1_type, typename key_type>
226 __host__ __device__ static inline auto get(data_type & data_, const g1_type & g1, const key_type & v1) -> decltype(boost::fusion::at_c<p>(data_.mem_r.operator[](g1.LinId(v1)))) &
227 {
228 return boost::fusion::at_c<p>(data_.mem_r.operator[](g1.LinId(v1)));
229 }
230
231 /*! \brief Return a reference to the selected element
232 *
233 * \param data object from where to take the element
234 * \param g1 grid information
235 * \param v1 element id
236 *
237 * \return a reference to the object selected
238 *
239 */
240 template<unsigned int p, typename data_type, typename g1_type>
241 __host__ __device__ static inline auto get_lin(data_type & data_, const g1_type & g1, const size_t lin_id) -> decltype(boost::fusion::at_c<p>(data_.mem_r.operator[](lin_id))) &
242 {
243 return boost::fusion::at_c<p>(data_.mem_r.operator[](lin_id));
244 }
245
246 /*! \brief Return a reference to the selected element
247 *
248 * \param data object from where to take the element
249 * \param g1 grid information
250 * \param v1 element id
251 *
252 * \return a reference to the object selected
253 *
254 */
255 template<unsigned int p, typename data_type, typename g1_type, typename key_type>
256 __host__ __device__ static inline auto get_c(const data_type & data_, const g1_type & g1, const key_type & v1) -> decltype(boost::fusion::at_c<p>(data_.mem_r.operator[](g1.LinId(v1)))) &
257 {
258 return boost::fusion::at_c<p>(data_.mem_r.operator[](g1.LinId(v1)));
259 }
260
261 /*! \brief Return a reference to the selected element
262 *
263 * \param data object from where to take the element
264 * \param g1 grid information
265 * \param v1 element id
266 *
267 * \return a reference to the object selected
268 *
269 */
270 template<unsigned int p, typename data_type, typename g1_type>
271 __host__ __device__ static inline auto get_lin_c(const data_type & data_, const g1_type & g1, const size_t lin_id) -> decltype(boost::fusion::at_c<p>(data_.mem_r.operator[](lin_id))) &
272 {
273 return boost::fusion::at_c<p>(data_.mem_r.operator[](lin_id));
274 }
275};
276
277
278//////////////////////////////////////////////////////////////
279
280template<typename T, typename Sfinae = void>
281struct is_layout_mlin: std::false_type {};
282
283
284/*! \brief is_layout_mlin
285 *
286 * ### Example
287 *
288 * \snippet util.hpp Check if the memory layout is memory_traits_lin
289 *
290 * return true if T is a memory_traits_lin
291 *
292 */
293template<typename T>
294struct is_layout_mlin<T, typename Void< typename T::yes_is_tlin>::type> : std::true_type
295{};
296
297
298template<typename T, typename Sfinae = void>
299struct is_layout_inte: std::false_type {};
300
301
302/*! \brief is_layout_inte
303 *
304 * ### Example
305 *
306 * \snippet util.hpp Check if the memory layout is memory_traits_inte
307 *
308 * return true if T is a memory_traits_inte
309 *
310 */
311template<typename T>
312struct is_layout_inte<T, typename Void< typename T::yes_is_inte>::type> : std::true_type
313{};
314
315/*! \brief is_multiple_buffer_each_prp
316 *
317 * return if each property is splitted on a separate buffer. This class make sense to be used if T is
318 * a vector in case it is not it always return 0
319 *
320 * ### Example
321 *
322 * \snippet util_test.hpp Check if the vector has multiple buffers for each vector
323 *
324 *
325 */
326template<typename T, unsigned int impl = is_vector<T>::value >
327struct is_multiple_buffer_each_prp: std::false_type
328{};
329
330template<typename T>
331struct is_multiple_buffer_each_prp<T,true>: is_layout_inte<typename T::layout_base_>
332{};
333
334#endif
335