1 | /* |
2 | * Encap.hpp |
3 | * |
4 | * Created on: Feb 2, 2015 |
5 | * Author: i-bird |
6 | */ |
7 | |
8 | #ifndef ENCAP_HPP_ |
9 | #define ENCAP_HPP_ |
10 | |
11 | #include "util/for_each_ref.hpp" |
12 | #include "util/copy_compare/meta_copy.hpp" |
13 | #include "boost/mpl/range_c.hpp" |
14 | #include <boost/fusion/container/vector.hpp> |
15 | #include "util/se_util.hpp" |
16 | #include "util/copy_compare/copy_fusion_vector.hpp" |
17 | #include "util/copy_compare/compare_fusion_vector.hpp" |
18 | #include "memory_ly/memory_conf.hpp" |
19 | |
20 | |
21 | /*! \brief this class is a functor for "for_each" algorithm |
22 | * |
23 | * This class is a functor for "for_each" algorithm. For each |
24 | * element of the boost::vector the operator() is called. |
25 | * Is mainly used to copy one encap into another encap object |
26 | * |
27 | * \tparam encap source |
28 | * \tparam encap dst |
29 | * |
30 | */ |
31 | template<typename e_src, typename e_dst, unsigned int ... prp> |
32 | struct copy_cpu_encap_encap_prp |
33 | { |
34 | //! encapsulated source object |
35 | e_src & src; |
36 | //! encapsulated destination object |
37 | e_dst & dst; |
38 | |
39 | typedef typename to_boost_vmpl<prp...>::type vprp; |
40 | |
41 | /*! \brief constructor |
42 | * |
43 | * \param src source encapsulated object |
44 | * \param dst source encapsulated object |
45 | * |
46 | */ |
47 | __device__ __host__ inline copy_cpu_encap_encap_prp(e_src & src, e_dst & dst) |
48 | :src(src),dst(dst) |
49 | { |
50 | #if defined(SE_CLASS1) && !defined(__NVCC__) |
51 | // e_src and e_dst must have the same number of properties |
52 | |
53 | if (e_src::T_type::max_prop != e_dst::T_type::max_prop) |
54 | std::cerr << "Error " << __FILE__ << ":" << __LINE__ << " the number of properties between src and dst must match" ; |
55 | #endif |
56 | }; |
57 | |
58 | |
59 | #ifdef SE_CLASS1 |
60 | /*! \brief Constructor |
61 | * |
62 | * Calling this constructor produce an error. This class store the reference of the object, |
63 | * this mean that the object passed must not be a temporal object |
64 | * |
65 | */ |
66 | inline copy_cpu_encap_encap_prp(const e_src && src, const e_dst && dst) |
67 | :src(src),dst(dst) |
68 | {std::cerr << "Error: " <<__FILE__ << ":" << __LINE__ << " Passing a temporal object" ;}; |
69 | #endif |
70 | |
71 | //! It call the copy function for each property |
72 | template<typename T> |
73 | __device__ __host__ inline void operator()(T& t) const |
74 | { |
75 | typedef typename boost::mpl::at<vprp,T>::type prp_cp; |
76 | |
77 | // Remove the reference from the type to copy |
78 | typedef typename boost::remove_reference<decltype(dst.template get<prp_cp::value>())>::type copy_rtype; |
79 | |
80 | meta_copy<copy_rtype>::meta_copy_(src.template get<prp_cp::value>(),dst.template get<prp_cp::value>()); |
81 | } |
82 | }; |
83 | |
84 | |
85 | /*! \brief this class is a functor for "for_each" algorithm |
86 | * |
87 | * This class is a functor for "for_each" algorithm. For each |
88 | * element of the boost::vector the operator() is called. |
89 | * Is mainly used to copy one encap into another encap object |
90 | * |
91 | * \tparam encap source |
92 | * \tparam encap dst |
93 | * |
94 | */ |
95 | template<typename e_src, typename e_dst> |
96 | struct copy_cpu_encap_encap |
97 | { |
98 | //! encapsulated source object |
99 | const e_src & src; |
100 | //! encapsulated destination object |
101 | e_dst & dst; |
102 | |
103 | |
104 | /*! \brief constructor |
105 | * |
106 | * \param src source encapsulated object |
107 | * \param dst source encapsulated object |
108 | * |
109 | */ |
110 | __device__ __host__ inline copy_cpu_encap_encap(const e_src & src, e_dst & dst) |
111 | :src(src),dst(dst) |
112 | { |
113 | #if defined(SE_CLASS1) && !defined(__NVCC__) |
114 | // e_src and e_dst must have the same number of properties |
115 | |
116 | if (e_src::T_type::max_prop != e_dst::T_type::max_prop) |
117 | std::cerr << "Error " << __FILE__ << ":" << __LINE__ << " the number of properties between src and dst must match" ; |
118 | #endif |
119 | }; |
120 | |
121 | |
122 | #ifdef SE_CLASS1 |
123 | /*! \brief Constructor |
124 | * |
125 | * Calling this constructor produce an error. This class store the reference of the object, |
126 | * this mean that the object passed must not be a temporal object |
127 | * |
128 | */ |
129 | inline copy_cpu_encap_encap(const e_src && src, const e_dst && dst) |
130 | :src(src),dst(dst) |
131 | {std::cerr << "Error: " <<__FILE__ << ":" << __LINE__ << " Passing a temporal object" ;}; |
132 | #endif |
133 | |
134 | //! It call the copy function for each property |
135 | template<typename T> |
136 | __device__ __host__ inline void operator()(T& t) const |
137 | { |
138 | // Remove the reference from the type to copy |
139 | typedef typename boost::remove_reference<decltype(dst.template get<T::value>())>::type copy_rtype; |
140 | |
141 | meta_copy<copy_rtype>::meta_copy_(src.template get<T::value>(),dst.template get<T::value>()); |
142 | } |
143 | }; |
144 | |
145 | |
146 | /*! \brief this class is a functor for "for_each" algorithm |
147 | * |
148 | * This class is a functor for "for_each" algorithm. For each |
149 | * element of the boost::vector the operator() is called. |
150 | * Is mainly used to copy one encap into another encap object |
151 | * |
152 | * \tparam encap source |
153 | * \tparam encap dst |
154 | * |
155 | */ |
156 | template<typename e_src, typename e_dst> |
157 | struct copy_cpu_encap_encap_general |
158 | { |
159 | //! encapsulated source object |
160 | const e_src & src; |
161 | //! encapsulated destination object |
162 | e_dst & dst; |
163 | |
164 | |
165 | /*! \brief constructor |
166 | * |
167 | * \param src source encapsulated object |
168 | * \param dst source encapsulated object |
169 | * |
170 | */ |
171 | __device__ __host__ inline copy_cpu_encap_encap_general(const e_src & src, e_dst & dst) |
172 | :src(src),dst(dst) |
173 | { |
174 | #if defined(SE_CLASS1) && !defined(__NVCC__) |
175 | // e_src and e_dst must have the same number of properties |
176 | |
177 | if (e_src::T_type::max_prop != e_dst::T_type::max_prop) |
178 | std::cerr << "Error " << __FILE__ << ":" << __LINE__ << " the number of properties between src and dst must match" ; |
179 | #endif |
180 | }; |
181 | |
182 | |
183 | #ifdef SE_CLASS1 |
184 | /*! \brief Constructor |
185 | * |
186 | * Calling this constructor produce an error. This class store the reference of the object, |
187 | * this mean that the object passed must not be a temporal object |
188 | * |
189 | */ |
190 | inline copy_cpu_encap_encap_general(const e_src && src, const e_dst && dst) |
191 | :src(src),dst(dst) |
192 | {std::cerr << "Error: " <<__FILE__ << ":" << __LINE__ << " Passing a temporal object" ;}; |
193 | #endif |
194 | |
195 | //! It call the copy function for each property |
196 | template<typename T> |
197 | __device__ __host__ inline void operator()(T& t) const |
198 | { |
199 | // Remove the reference from the type to copy |
200 | typedef typename boost::remove_reference<decltype(dst.template get<T::value>())>::type copy_dtype; |
201 | |
202 | // Remove the reference from the type to copy |
203 | typedef typename boost::remove_reference<decltype(src.template get<T::value>())>::type copy_stype; |
204 | |
205 | meta_copy_d<copy_stype,copy_dtype>::meta_copy_d_(src.template get<T::value>(),dst.template get<T::value>()); |
206 | } |
207 | }; |
208 | |
209 | |
210 | /*! \brief this class is a functor for "for_each" algorithm |
211 | * |
212 | * This class is a functor for "for_each" algorithm. For each |
213 | * element of the boost::vector the operator() is called. |
214 | * Is mainly used to copy one encap into another encap object |
215 | * |
216 | * \tparam encap source |
217 | * \tparam encap dst |
218 | * |
219 | */ |
220 | template<typename e_src> |
221 | struct copy_cpu_encap_single |
222 | { |
223 | //! encapsulated source object |
224 | const e_src & src; |
225 | //! encapsulated destination object |
226 | e_src & dst; |
227 | |
228 | |
229 | /*! \brief constructor |
230 | * |
231 | * \param src source encapsulated object |
232 | * \param dst source encapsulated object |
233 | * |
234 | */ |
235 | __device__ __host__ inline copy_cpu_encap_single(const e_src & src, e_src & dst) |
236 | :src(src),dst(dst) |
237 | { |
238 | #if defined(SE_CLASS1) && !defined(__NVCC__) |
239 | // e_src and e_dst must have the same number of properties |
240 | |
241 | if (e_src::T_type::max_prop != e_src::T_type::max_prop) |
242 | std::cerr << "Error " << __FILE__ << ":" << __LINE__ << " the number of properties between src and dst must match" ; |
243 | #endif |
244 | }; |
245 | |
246 | |
247 | #ifdef SE_CLASS1 |
248 | /*! \brief Constructor |
249 | * |
250 | * Calling this constructor produce an error. This class store the reference of the object, |
251 | * this mean that the object passed must not be a temporal object |
252 | * |
253 | */ |
254 | inline copy_cpu_encap_single(const e_src && src, const e_src && dst) |
255 | :src(src),dst(dst) |
256 | {std::cerr << "Error: " <<__FILE__ << ":" << __LINE__ << " Passing a temporal object" ;}; |
257 | #endif |
258 | |
259 | //! It call the copy function for each property |
260 | template<typename T> |
261 | __device__ __host__ inline void operator()(T& t) const |
262 | { |
263 | // Remove the reference from the type to copy |
264 | typedef typename boost::remove_reference<decltype(dst.template get<T::value>())>::type copy_rtype; |
265 | |
266 | meta_copy<copy_rtype>::meta_copy_(src.template get<T::value>(),dst.template get<T::value>()); |
267 | } |
268 | }; |
269 | |
270 | |
271 | /////////////////////////////////// |
272 | |
273 | //! It copy two encap object |
274 | template<template<typename,typename> class op,typename e_src, typename e_dst, int ... prp> |
275 | struct copy_cpu_encap_encap_op_prp |
276 | { |
277 | //! encapsulated object source |
278 | const e_src & src; |
279 | //! encapsulated object destination |
280 | e_dst & dst; |
281 | |
282 | |
283 | /*! \brief constructor |
284 | * |
285 | * |
286 | * \param src source encapsulated object |
287 | * \param dst destination encapsulated object |
288 | * |
289 | */ |
290 | inline copy_cpu_encap_encap_op_prp(const e_src & src, e_dst & dst) |
291 | :src(src),dst(dst) |
292 | { |
293 | #ifdef SE_CLASS1 |
294 | // e_src and e_dst must have the same number of properties |
295 | |
296 | if (e_src::T_type::max_prop != e_dst::T_type::max_prop) |
297 | std::cerr << "Error " << __FILE__ << ":" << __LINE__ << " the number of properties between src and dst must match" ; |
298 | #endif |
299 | }; |
300 | |
301 | |
302 | #ifdef SE_CLASS1 |
303 | /*! \brief Constructor |
304 | * |
305 | * Calling this constructor produce an error. This class store the reference of the object, |
306 | * this mean that the object passed must not be a temporal object |
307 | * |
308 | */ |
309 | inline copy_cpu_encap_encap_op_prp(const e_src && src, const e_dst && dst) |
310 | :src(src),dst(dst) |
311 | {std::cerr << "Error: " <<__FILE__ << ":" << __LINE__ << " Passing a temporal object" ;}; |
312 | #endif |
313 | |
314 | //! It call the copy function for each property |
315 | template<typename T> |
316 | inline void operator()(T& t) const |
317 | { |
318 | // Convert variadic to boost::vector |
319 | typedef typename boost::mpl::vector_c<unsigned int,prp...> prpv; |
320 | |
321 | // element id to copy applying an operation |
322 | typedef typename boost::mpl::at<prpv,T>::type ele_cop; |
323 | |
324 | // Remove the reference from the type to copy |
325 | typedef typename boost::remove_reference<decltype(src.template get< ele_cop::value >())>::type copy_rtype; |
326 | |
327 | meta_copy_op<op,copy_rtype>::meta_copy_op_(src.template get< ele_cop::value >(),dst.template get< ele_cop::value >()); |
328 | } |
329 | }; |
330 | |
331 | |
332 | |
333 | /////////////////////////////// |
334 | |
335 | /*! \brief this class is a functor for "for_each" algorithm |
336 | * |
337 | * This class is a functor for "for_each" algorithm. For each |
338 | * element of the boost::vector the operator() is called. |
339 | * Is mainly used to copy one encap into another encap object |
340 | * |
341 | * \tparam encap source |
342 | * \tparam encap dst |
343 | * |
344 | */ |
345 | |
346 | template<typename e_src, typename e_dst> |
347 | struct compare_cpu_encap_encap |
348 | { |
349 | //! object 1 we have to compare |
350 | const e_src & src; |
351 | //! object 2 we have to compare |
352 | const e_dst & dst; |
353 | |
354 | |
355 | /*! \brief constructor |
356 | * |
357 | * |
358 | * \param src encapsulated object1 |
359 | * \param dst encapsulated object2 |
360 | * |
361 | */ |
362 | inline compare_cpu_encap_encap(const e_src & src, const e_dst & dst) |
363 | :src(src),dst(dst) |
364 | { |
365 | #ifdef SE_CLASS1 |
366 | // e_src and e_dst must have the same number of properties |
367 | |
368 | if (e_src::max_prop != e_dst::max_prop) |
369 | std::cerr << "Error " << __FILE__ << ":" << __LINE__ << " the number of properties between src and dst must match" ; |
370 | #endif |
371 | }; |
372 | |
373 | |
374 | #ifdef SE_CLASS1 |
375 | |
376 | /*! \brief Constructor |
377 | * |
378 | * Calling this constructor produce an error. This class store the reference of the object, |
379 | * this mean that the object passed must not be a temporal object |
380 | * |
381 | * \param e_src encapsulated object1 |
382 | * \param e_dst encapsulated object2 |
383 | * |
384 | */ |
385 | inline compare_cpu_encap_encap(const e_src && src, const e_dst && dst) |
386 | :src(src),dst(dst) |
387 | {std::cerr << "Error: " <<__FILE__ << ":" << __LINE__ << " Passing a temporal object" ;}; |
388 | #endif |
389 | |
390 | /*! \brief It call the copy function for each property |
391 | * |
392 | * \param t each member |
393 | * |
394 | */ |
395 | template<typename T> |
396 | inline void operator()(T& t) const |
397 | { |
398 | //! This is the type of the object we have to copy |
399 | typedef typename boost::fusion::result_of::at_c<typename e_src::type,T::value>::type copy_type; |
400 | |
401 | //! Remove the reference from the type to copy |
402 | typedef typename boost::remove_reference<copy_type>::type copy_rtype; |
403 | |
404 | meta_compare<copy_rtype> cp(src.template get<T::value>(),dst.template get<T::value>()); |
405 | } |
406 | }; |
407 | |
408 | /*! Stub encap |
409 | * |
410 | * \tparam dim dimension |
411 | * \tparam T object it encapsulate |
412 | * \tparam layout |
413 | * |
414 | */ |
415 | template<unsigned int dim,typename T,typename layout> |
416 | class encapc |
417 | { |
418 | |
419 | }; |
420 | |
421 | /*! \brief this structure encapsulate an object of the grid |
422 | * |
423 | * This structure encapsulate an object of the grid |
424 | * It give the possibility to select the property in a secondary moment |
425 | * |
426 | * Can be thought as a reference to an object of the grid. So every time we |
427 | * use the term encapsulated object we mean reference to object |
428 | * |
429 | * \note A vector is a 1D grid |
430 | * |
431 | * \param dim Dimensionality of the grid |
432 | * \param T type of object the grid store |
433 | * |
434 | * |
435 | */ |
436 | |
437 | template<unsigned int dim,typename T> |
438 | class encapc<dim,T,typename memory_traits_lin<T>::type > |
439 | { |
440 | public: |
441 | |
442 | //! object type the encap object encapsulate |
443 | typedef typename T::type type; |
444 | |
445 | private: |
446 | |
447 | #ifdef SE_CLASS1 |
448 | bool init = false; |
449 | #endif |
450 | |
451 | //! reference to the encapsulated object |
452 | type & data_c; |
453 | |
454 | //! layout of the encapsulated object |
455 | typedef typename memory_traits_lin<T>::type Mem; |
456 | |
457 | //! layout of the encapsulated object |
458 | typedef typename memory_traits_inte<T>::type Mem2; |
459 | |
460 | #ifdef SE_CLASS1 |
461 | __device__ __host__ void check_init() const |
462 | { |
463 | if (init == false) |
464 | { |
465 | #ifdef CUDA_ON_CPU |
466 | std::cout << __FILE__ << ":" << __LINE__ << " Error using unallocated pointer" << std::endl; |
467 | #else |
468 | assert(init == true); |
469 | #endif |
470 | } |
471 | } |
472 | #endif |
473 | |
474 | public: |
475 | |
476 | #ifdef SE_CLASS1 |
477 | __device__ __host__ ~encapc() |
478 | {init = false;} |
479 | #endif |
480 | |
481 | //! indicate the it is an encapsulated object |
482 | typedef int yes_i_am_encap; |
483 | |
484 | //! original object |
485 | typedef T T_type; |
486 | |
487 | //! number of properties |
488 | static const int max_prop = T::max_prop; |
489 | |
490 | //! constructor from a reference object |
491 | __device__ __host__ inline encapc(type & data_c) |
492 | :data_c(data_c) |
493 | { |
494 | #ifdef SE_CLASS1 |
495 | init = true; |
496 | #endif |
497 | } |
498 | |
499 | |
500 | /*! \brief Return the address of the base |
501 | * |
502 | * \return the address of the data encapsulated |
503 | * |
504 | */ |
505 | inline type * operator&() |
506 | { |
507 | #ifdef SE_CLASS1 |
508 | check_init(); |
509 | #endif |
510 | return &data_c; |
511 | } |
512 | |
513 | /*! \brief access the data |
514 | * |
515 | * \return the reference |
516 | * |
517 | */ |
518 | template <unsigned int p, typename r_type=decltype(boost::fusion::at_c<p>(data_c))> |
519 | __device__ __host__ inline r_type get() |
520 | { |
521 | #ifdef SE_CLASS1 |
522 | check_init(); |
523 | #endif |
524 | return boost::fusion::at_c<p>(data_c); |
525 | } |
526 | |
527 | /*! \brief access the data but return a constant reference |
528 | * |
529 | * \return the reference |
530 | * |
531 | */ |
532 | template <unsigned int p, typename r_type=decltype(boost::fusion::at_c<p>(data_c))> |
533 | __device__ __host__ inline const r_type get() const |
534 | { |
535 | #ifdef SE_CLASS1 |
536 | check_init(); |
537 | #endif |
538 | return boost::fusion::at_c<p>(data_c); |
539 | } |
540 | |
541 | /*! \brief Set one property of the encapsulated object |
542 | * |
543 | * \tparam p property to set |
544 | * |
545 | * \param ele value to set |
546 | * |
547 | */ |
548 | template <unsigned int p> inline |
549 | __device__ __host__ void set(decltype(boost::fusion::at_c<p>(data_c)) & ele) |
550 | { |
551 | #ifdef SE_CLASS1 |
552 | check_init(); |
553 | #endif |
554 | return boost::fusion::at_c<p>(data_c) = ele; |
555 | } |
556 | |
557 | /*! \brief Set one property of the encapsulated object |
558 | * |
559 | * \tparam dim2 dimensionality of the multy-array |
560 | * \tparam p property to set |
561 | * |
562 | * \param ec value to set as encapsulated object |
563 | * |
564 | * \return itself |
565 | * |
566 | */ |
567 | template<unsigned int dim2> |
568 | __device__ __host__ inline encapc<dim,T,Mem> & set(const encapc<dim2,T,Mem> & ec) |
569 | { |
570 | #ifdef SE_CLASS1 |
571 | check_init(); |
572 | #endif |
573 | copy_cpu_encap_encap<encapc<dim2,T,Mem>,encapc<dim,T,Mem>> cp(ec,*this); |
574 | |
575 | boost::mpl::for_each_ref< boost::mpl::range_c<int,0,T::max_prop> >(cp); |
576 | |
577 | return *this; |
578 | } |
579 | |
580 | /*! \brief Assignment |
581 | * |
582 | * \param ec object encapsulated to copy |
583 | * |
584 | * \return itself |
585 | * |
586 | */ |
587 | __device__ __host__ inline encapc<dim,T,Mem> & operator=(const encapc<dim,T,Mem> & ec) |
588 | { |
589 | #ifdef SE_CLASS1 |
590 | check_init(); |
591 | #endif |
592 | copy_cpu_encap_single<encapc<dim,T,Mem>> cp(ec,*this); |
593 | |
594 | boost::mpl::for_each_ref< boost::mpl::range_c<int,0,T::max_prop> >(cp); |
595 | |
596 | return *this; |
597 | } |
598 | |
599 | /*! \brief Assignment |
600 | * |
601 | * \param ec object encapsulated to copy |
602 | * |
603 | * \return itself |
604 | * |
605 | */ |
606 | __device__ __host__ inline encapc<dim,T,Mem> & operator=(const encapc<dim,T,Mem2> & ec) |
607 | { |
608 | #ifdef SE_CLASS1 |
609 | check_init(); |
610 | #endif |
611 | copy_cpu_encap_encap_general<encapc<dim,T,Mem2>,encapc<dim,T,Mem>> cp(ec,*this); |
612 | |
613 | boost::mpl::for_each_ref< boost::mpl::range_c<int,0,T::max_prop> >(cp); |
614 | |
615 | return *this; |
616 | } |
617 | |
618 | /*! \brief Assignment |
619 | * |
620 | * \param obj object to copy |
621 | * |
622 | * \return itself |
623 | * |
624 | */ |
625 | __device__ __host__ inline encapc<dim,T,Mem> & operator=(const T & obj) |
626 | { |
627 | #ifdef SE_CLASS1 |
628 | check_init(); |
629 | #endif |
630 | copy_fusion_vector<typename T::type> cp(obj.data,data_c); |
631 | |
632 | boost::mpl::for_each_ref< boost::mpl::range_c<int,0,T::max_prop> >(cp); |
633 | |
634 | return *this; |
635 | } |
636 | |
637 | /*! \brief Compare |
638 | * |
639 | * \param ec encapsulator |
640 | * |
641 | * \return true if the two encap store the same information |
642 | * |
643 | */ |
644 | inline bool operator==(const encapc<dim,T,Mem> & ec) const |
645 | { |
646 | #ifdef SE_CLASS1 |
647 | check_init(); |
648 | #endif |
649 | compare_fusion_vector<typename T::type> cp(ec.data_c,data_c); |
650 | |
651 | boost::mpl::for_each_ref< boost::mpl::range_c<int,0,T::max_prop> >(cp); |
652 | |
653 | return cp.result(); |
654 | } |
655 | |
656 | /*! \brief Compare |
657 | * |
658 | * \param ec encapsulator |
659 | * |
660 | * \return true if the two encap store different information |
661 | * |
662 | */ |
663 | inline bool operator!=(const encapc<dim,T,Mem> & ec) const |
664 | { |
665 | #ifdef SE_CLASS1 |
666 | check_init(); |
667 | #endif |
668 | return ! this->operator==(ec); |
669 | } |
670 | }; |
671 | |
672 | /*! \brief this structure specialize the class for a void object or null |
673 | * |
674 | * \param dim Dimensionality of the grid |
675 | * \param Mem suppose to be a boost::fusion::vector of arrays |
676 | * |
677 | */ |
678 | |
679 | template<unsigned int dim,typename Mem> |
680 | class encapc<dim,void,Mem> |
681 | { |
682 | public: |
683 | |
684 | // constructor require a key and a memory data |
685 | encapc() |
686 | {} |
687 | |
688 | //! access the data |
689 | template <unsigned int p> void get() |
690 | {} |
691 | |
692 | //! set the data |
693 | template <unsigned int p, typename S> void set(S & ele) |
694 | {} |
695 | }; |
696 | |
697 | /*! \brief this structure encapsulate an object of the grid |
698 | * |
699 | * This structure encapsulate an object of the grid |
700 | * It give the possibility to select the property in a secondary moment |
701 | * |
702 | * Can be thought as a reference to an object of the grid. So every time we |
703 | * use the term encapsulated object we mean reference to object |
704 | * |
705 | * \note A vector is a 1D grid |
706 | * |
707 | * \param dim Dimensionality of the grid |
708 | * \param T type of object the grid store |
709 | * |
710 | */ |
711 | template<unsigned int dim,typename T> |
712 | class encapc<dim,T,typename memory_traits_inte<T>::type> |
713 | { |
714 | //! type of layout |
715 | typedef typename memory_traits_inte<T>::type Mem; |
716 | |
717 | //! layout of the encapsulated object |
718 | typedef typename memory_traits_lin<T>::type Mem2; |
719 | |
720 | //! reference to the encapsulated object |
721 | Mem & data; |
722 | |
723 | //! element id |
724 | size_t k; |
725 | |
726 | #ifdef SE_CLASS1 |
727 | bool init = false; |
728 | #endif |
729 | |
730 | #ifdef SE_CLASS1 |
731 | __device__ __host__ void check_init() const |
732 | { |
733 | if (init == false) |
734 | { |
735 | #ifdef CUDA_ON_CPU |
736 | std::cout << __FILE__ << ":" << __LINE__ << " Error using unallocated pointer" << std::endl; |
737 | #else |
738 | assert(init == true); |
739 | #endif |
740 | } |
741 | } |
742 | #endif |
743 | |
744 | public: |
745 | |
746 | //! Original list if types |
747 | typedef typename T::type type; |
748 | |
749 | //! indicate it is an encapsulated object |
750 | typedef int yes_i_am_encap; |
751 | |
752 | //! original object type |
753 | typedef T T_type; |
754 | |
755 | //! number of properties |
756 | static const int max_prop = T::max_prop; |
757 | |
758 | #ifdef SE_CLASS1 |
759 | __device__ __host__ ~encapc() |
760 | {init = false;} |
761 | #endif |
762 | |
763 | //! constructor require a key and a memory data |
764 | __device__ __host__ encapc(typename memory_traits_inte<T>::type & data, size_t k) |
765 | :data(data),k(k) |
766 | { |
767 | #ifdef SE_CLASS1 |
768 | init = true; |
769 | #endif |
770 | } |
771 | |
772 | /*! \brief Access the data |
773 | * |
774 | * \tparam p property selected |
775 | * |
776 | * \return The reference of the data |
777 | * |
778 | */ |
779 | template <unsigned int p> |
780 | __device__ __host__ auto get() -> decltype(boost::fusion::at_c<p>(data).mem_r.operator[](k)) |
781 | { |
782 | #ifdef SE_CLASS1 |
783 | check_init(); |
784 | #endif |
785 | return boost::fusion::at_c<p>(data).mem_r.operator[](k); |
786 | } |
787 | |
788 | /*! \brief Access the data |
789 | * |
790 | * \tparam p property selected |
791 | * |
792 | * \return The reference of the data |
793 | * |
794 | */ |
795 | template <unsigned int p> __device__ __host__ auto get() const -> decltype(boost::fusion::at_c<p>(data).mem_r.operator[](k)) |
796 | { |
797 | #ifdef SE_CLASS1 |
798 | check_init(); |
799 | #endif |
800 | return boost::fusion::at_c<p>(data).mem_r.operator[](k); |
801 | } |
802 | |
803 | // __device__ __host__ encapc(const encapc<dim,T,Mem> & ec) = delete; |
804 | __device__ __host__ encapc(const encapc<dim,T,Mem> & ec) : data(ec.data), k(ec.k) |
805 | { |
806 | #ifdef SE_CLASS1 |
807 | init = true; |
808 | #endif |
809 | } |
810 | // __device__ __host__ inline encapc<dim,T,Mem> & operator=(const encapc<dim,T,Mem> & ec) = delete; //DEBUG |
811 | |
812 | /*! \brief Assignment |
813 | * |
814 | * \param ec encapsulator |
815 | * |
816 | * \return itself |
817 | * |
818 | */ |
819 | __device__ __host__ inline encapc<dim,T,Mem> & operator=(const encapc<dim,T,Mem> & ec) |
820 | { |
821 | #ifdef SE_CLASS1 |
822 | check_init(); |
823 | #endif |
824 | copy_cpu_encap_single<encapc<dim,T,Mem>> cp(ec,*this); |
825 | |
826 | boost::mpl::for_each_ref< boost::mpl::range_c<int,0,T::max_prop> >(cp); |
827 | |
828 | return *this; |
829 | } |
830 | |
831 | /*! \brief Assignment |
832 | * |
833 | * \param ec encapsulator |
834 | * |
835 | * \return itself |
836 | * |
837 | */ |
838 | __device__ __host__ inline encapc<dim,T,Mem> & operator=(const encapc<dim,T,Mem2> & ec) |
839 | { |
840 | #ifdef SE_CLASS1 |
841 | check_init(); |
842 | #endif |
843 | copy_cpu_encap_encap_general<encapc<dim,T,Mem2>,encapc<dim,T,Mem>> cp(ec,*this); |
844 | |
845 | boost::mpl::for_each_ref< boost::mpl::range_c<int,0,T::max_prop> >(cp); |
846 | |
847 | return *this; |
848 | } |
849 | |
850 | /*! \brief Assignment |
851 | * |
852 | * \param obj object to copy |
853 | * |
854 | * \return itself |
855 | * |
856 | */ |
857 | __device__ __host__ inline encapc<dim,T,Mem> & operator=(const T & obj) |
858 | { |
859 | #ifdef SE_CLASS1 |
860 | check_init(); |
861 | #endif |
862 | copy_fusion_vector_encap<typename T::type,decltype(*this)> cp(obj.data,*this); |
863 | |
864 | boost::mpl::for_each_ref< boost::mpl::range_c<int,0,T::max_prop> >(cp); |
865 | |
866 | return *this; |
867 | } |
868 | |
869 | __device__ __host__ inline void private_set_data_k(Mem & data_c, size_t k) |
870 | { |
871 | #ifdef SE_CLASS1 |
872 | check_init(); |
873 | #endif |
874 | this->data = data; |
875 | this->k = k; |
876 | } |
877 | |
878 | __device__ __host__ inline Mem & private_get_data() |
879 | { |
880 | #ifdef SE_CLASS1 |
881 | check_init(); |
882 | #endif |
883 | return data; |
884 | } |
885 | |
886 | __device__ __host__ inline size_t private_get_k() |
887 | { |
888 | #ifdef SE_CLASS1 |
889 | check_init(); |
890 | #endif |
891 | return k; |
892 | } |
893 | |
894 | __device__ __host__ inline size_t private_set_k(unsigned int k) |
895 | { |
896 | #ifdef SE_CLASS1 |
897 | check_init(); |
898 | #endif |
899 | return this->k = k; |
900 | } |
901 | }; |
902 | |
903 | #include "util/common.hpp" |
904 | |
905 | template<typename T, typename Sfinae = void> |
906 | struct is_encap: std::false_type {}; |
907 | |
908 | |
909 | /*! \brief is_encap check if the type is an encap type |
910 | * |
911 | * ### Example |
912 | * |
913 | * \snippet util_test.hpp Check is_encap |
914 | * |
915 | * return true if T is an encap |
916 | * |
917 | */ |
918 | template<typename T> |
919 | struct is_encap<T, typename Void< typename T::yes_i_am_encap>::type> : std::true_type |
920 | {}; |
921 | |
922 | |
923 | //! Case memory_traits_lin |
924 | template<unsigned int dim , typename T, typename layout, typename data_type, typename g1_type, typename key_type, unsigned int sel = 2*is_layout_mlin<layout>::value + is_layout_inte<layout>::value > |
925 | struct mem_geto |
926 | { |
927 | __device__ __host__ static inline encapc<dim,T,typename layout::type> get(data_type & data_, const g1_type & g1, const key_type & v1) |
928 | { |
929 | return encapc<dim,T,typename layout::type>(data_.mem_r.operator[](g1.LinId(v1))); |
930 | } |
931 | |
932 | static inline encapc<dim,T,typename layout::type> get_lin(data_type & data_, const size_t & v1) |
933 | { |
934 | return encapc<dim,T,typename layout::type>(data_.mem_r.operator[](v1)); |
935 | } |
936 | }; |
937 | |
938 | //! Case memory_traits_inte |
939 | template<unsigned int dim, typename T,typename layout, typename data_type, typename g1_type, typename key_type> |
940 | struct mem_geto<dim,T,layout,data_type,g1_type,key_type,1> |
941 | { |
942 | __device__ __host__ static inline encapc<dim,T,typename layout::type> get(data_type & data_, const g1_type & g1, const key_type & v1) |
943 | { |
944 | return encapc<dim,T,typename layout::type>(data_,g1.LinId(v1)); |
945 | } |
946 | |
947 | static inline encapc<dim,T,typename layout::type> get_lin(data_type & data_, const size_t & v1) |
948 | { |
949 | return encapc<dim,T,typename layout::type>(data_,v1); |
950 | } |
951 | }; |
952 | |
953 | #endif /* ENCAP_HPP_ */ |
954 | |