1/*
2 * map_vector.hpp
3 *
4 * Created on: Aug 30, 2014
5 * Author: Pietro Incardona
6 */
7
8#ifndef MAP_VECTOR_HPP
9#define MAP_VECTOR_HPP
10
11#include "util/cuda_launch.hpp"
12#include <iostream>
13#include <typeinfo>
14#include "util/common.hpp"
15#include "memory/PtrMemory.hpp"
16#include "util/object_util.hpp"
17#include "Grid/util.hpp"
18#include "Vector/util.hpp"
19#include "Vector/map_vector_grow_p.hpp"
20#include "memory/ExtPreAlloc.hpp"
21#include "util/util_debug.hpp"
22#include "util/Pack_stat.hpp"
23#include "Grid/map_grid.hpp"
24#include "memory/HeapMemory.hpp"
25#include "vect_isel.hpp"
26#include "util/object_s_di.hpp"
27#include "util.hpp"
28#include "util/Pack_stat.hpp"
29#include "memory/ExtPreAlloc.hpp"
30#include <string.h>
31#include "Packer_Unpacker/Unpacker.hpp"
32#include "Packer_Unpacker/Packer.hpp"
33#include <fstream>
34#include "Packer_Unpacker/Packer_util.hpp"
35#include "Packer_Unpacker/has_pack_agg.hpp"
36#include "timer.hpp"
37#include "map_vector_std_util.hpp"
38#include "data_type/aggregate.hpp"
39#include "vector_map_iterator.hpp"
40#include "util/cuda_util.hpp"
41#include "cuda/map_vector_cuda_ker.cuh"
42#include "map_vector_printers.hpp"
43
44namespace openfpm
45{
46
47 template<bool is_ok_cuda,typename T, typename Memory,
48 template<typename> class layout_base,
49 typename grow_p>
50 struct add_prp_device_impl
51 {
52 template <typename S,
53 typename M,
54 typename gp,
55 unsigned int impl,
56 template <typename> class layout_base2,
57 unsigned int ...args>
58 static void run(openfpm::vector<T,Memory,layout_base,grow_p,impl> & this_ ,const openfpm::vector<S,M,layout_base2,gp,impl> & v)
59 {
60 std::cout << __FILE__ << ":" << __LINE__ << " Error the function add_prp_device only work with cuda enabled vector" << std::endl;
61 }
62 };
63
64 template<bool is_ok_cuda,typename T, typename Memory,
65 template<typename> class layout_base,
66 typename grow_p>
67 struct merge_prp_device_impl
68 {
69 template <typename S,
70 typename M,
71 typename gp,
72 unsigned int impl,
73 template <typename> class layout_base2,
74 unsigned int ...args>
75 static void run(openfpm::vector<T,Memory,layout_base,grow_p,impl> & this_ ,
76 const openfpm::vector<S,M,layout_base2,gp,impl> & v,
77 unsigned int offset)
78 {
79 std::cout << __FILE__ << ":" << __LINE__ << " Error the function merge_prp_device only work with cuda enabled vector" << std::endl;
80 }
81 };
82
83 template<typename T, typename Memory,
84 template<typename> class layout_base,
85 typename grow_p>
86 struct add_prp_device_impl<true,T,Memory,layout_base,grow_p>
87 {
88 template <typename S,
89 typename M,
90 typename gp,
91 unsigned int impl,
92 template <typename> class layout_base2,
93 unsigned int ...args>
94 static void run(vector<T,Memory,layout_base,grow_p,impl> & this_ ,const vector<S,M,layout_base2,gp,impl> & v)
95 {
96 // merge the data on device
97
98 #if defined(CUDA_GPU) && defined(__NVCC__)
99
100 size_t old_sz = this_.size();
101 this_.resize(this_.size() + v.size(),DATA_ON_DEVICE);
102
103 auto ite = v.getGPUIterator();
104
105 CUDA_LAUNCH((merge_add_prp_device_impl<decltype(v.toKernel()),decltype(this_.toKernel()),args...>),ite,v.toKernel(),this_.toKernel(),(unsigned int)old_sz);
106
107 #else
108 std::cout << __FILE__ << ":" << __LINE__ << " Error the function add_prp_device only work when map_vector is compiled with nvcc" << std::endl;
109 #endif
110 }
111 };
112
113 template<typename T, typename Memory,
114 template<typename> class layout_base,
115 typename grow_p>
116 struct merge_prp_device_impl<true,T,Memory,layout_base,grow_p>
117 {
118 template <typename S,
119 typename M,
120 typename gp,
121 unsigned int impl,
122 template <typename> class layout_base2,
123 unsigned int ...args>
124 static void run(vector<T,Memory,layout_base,grow_p,impl> & this_ ,
125 const vector<S,M,layout_base2,gp,impl> & v,
126 unsigned int offset)
127 {
128 // merge the data on device
129
130 #if defined(CUDA_GPU) && defined(__NVCC__)
131
132 auto ite = v.getGPUIterator();
133
134 CUDA_LAUNCH((merge_add_prp_device_impl<decltype(v.toKernel()),decltype(this_.toKernel()),args...>),ite,v.toKernel(),this_.toKernel(),(unsigned int)offset);
135
136 #else
137 std::cout << __FILE__ << ":" << __LINE__ << " Error the function merge_prp_device only work when map_vector is compiled with nvcc" << std::endl;
138 #endif
139 }
140 };
141
142
143 /*! \brief Implementation of 1-D std::vector like structure
144 *
145 * Stub object look at the various implementations
146 *
147 * \tparam T type of object the vector store
148 * \tparam Memory allocator to use
149 * \tparam layout layout to use
150 * \tparam grow_p grow policy for vector in case of reallocation
151 *
152 * \see vector<T,HeapMemory,grow_policy_double,STD_VECTOR>
153 * \see vector<T,Memory,grow_p,OPENFPM_NATIVE>
154 * \see vector<T,Memory,grow_p,OPENFPM_NATIVE>
155 *
156 */
157 template<typename T, typename Memory, template<typename> class layout_base, typename grow_p, unsigned int impl>
158 class vector
159 {
160 /*! \brief Stub size
161 *
162 * Report an error
163 *
164 * \return 0
165 *
166 */
167 size_t size()
168 {
169 std::cerr << __FILE__ << ":" << __LINE__ << " Error stub vector created" << std::endl;
170 return 0;
171 }
172 };
173
174 #include "map_vector_std.hpp"
175 #include "map_vector_std_ptr.hpp"
176
177#ifdef CUDA_GPU
178 #include "cuda/map_vector_std_cuda.hpp"
179#endif
180
181 /*! \brief Implementation of 1-D std::vector like structure
182 *
183 * The layout is memory_traits_lin
184 *
185 * ### Add and access elements
186 * \snippet vector_test_util.hpp Create add and access
187 *
188 * \tparam T type of object the vector store
189 * \tparam Memory allocator to use
190 * \tparam layout layout to use
191 * \tparam grow_p grow policy for vector in case of reallocation
192 *
193 * OPENFPM_NATIVE implementation
194 *
195 */
196 template<typename T,typename Memory, template <typename> class layout_base, typename grow_p>
197 class vector<T,Memory,layout_base,grow_p,OPENFPM_NATIVE>
198 {
199 typedef vector<T,Memory,layout_base,grow_p,OPENFPM_NATIVE> self_type;
200
201 //! Actual size of the vector, warning: it is not the space allocated in grid
202 //! grid size increase by a fixed amount every time we need a vector bigger than
203 //! the actually allocated space
204 size_t v_size;
205
206 //! 1-D static grid
207 grid_base<1,T,Memory,typename layout_base<T>::type> base;
208
209 /*! \brief If the argument is zero return 1 otherwise return the argument
210 *
211 * \param sz output
212 * \param arg argument
213 *
214 */
215 void non_zero_one(size_t sz[1], size_t arg)
216 {
217 if (arg == 0)
218 {sz[0] = 1;}
219 else
220 {sz[0] = arg;}
221 }
222
223#ifdef SE_CLASS1
224
225 /*! \brief Check that id is not bigger than the vector size
226 *
227 * \param id element id
228 *
229 */
230
231 void check_overflow(size_t id) const
232 {
233 if (id >= v_size)
234 {
235 std::cerr << "Error " << __FILE__ << ":" << __LINE__ << " overflow id: " << id << "\n";
236 ACTION_ON_ERROR(VECTOR_ERROR_OBJECT);
237 }
238 }
239
240#endif
241
242 public:
243
244 //! it define that it is a vector
245 typedef int yes_i_am_vector;
246
247 //! it define that it is a vector
248 typedef int yes_i_am_vector_native;
249
250 //! Type of the encapsulation memory parameter
251 typedef typename layout_base<T>::type layout_type;
252
253 //! Type of the encapsulation memory parameter
254 typedef layout_base<T> layout_base_;
255
256 //! iterator for the vector
257 typedef vector_key_iterator iterator_key;
258
259 //! Object container for T, it is the return type of get_o it return a object type trough
260 // you can access all the properties of T
261 typedef typename grid_base<1,T,Memory,typename layout_base<T>::type>::container container;
262
263 //! Type of the value the vector is storing
264 typedef T value_type;
265
266 //! Type of memory this vector use
267 typedef Memory Memory_type;
268
269 //! growing policy of this vector
270 typedef grow_p grow_policy;
271
272 template<typename Tobj>
273 struct layout_base__
274 {
275 typedef layout_base<Tobj> type;
276 };
277
278 // Implementation of packer and unpacker for vector
279#include "vector_pack_unpack.ipp"
280
281 /*! \brief Return the size of the vector
282 *
283 * \return the size
284 *
285 */
286 size_t size() const
287 {
288 return v_size;
289 }
290
291 /*! \brief return the maximum capacity of the vector before reallocation
292 *
293 * \return the capacity of the vector
294 *
295 */
296
297 size_t capacity()
298 {
299 return base.size();
300 }
301
302 /*! \brief Reserve slots in the vector to avoid reallocation
303 *
304 * Reserve slots in the vector to avoid reallocation
305 *
306 * \param sp number of slot to reserve
307 *
308 */
309
310 void reserve(size_t sp)
311 {
312 if (sp > base.size())
313 {
314 //! Resize the memory
315 size_t sz[1] = {sp};
316 base.resize(sz);
317 }
318 }
319
320 /*! \brief Clear the vector
321 *
322 * Eliminate all the elements for from the vector
323 *
324 */
325 void clear()
326 {
327 resize(0);
328 }
329
330 /*! \brief Clear the vector
331 *
332 * Eliminate all the elements for from the vector
333 *
334 */
335 void shrink_to_fit()
336 {
337 size_t sz[1] = {size()};
338 base.resize(sz);
339 }
340
341 /*! \brief Resize the vector
342 *
343 * Resize the vector and allocate n elements
344 *
345 * \param opt options for resize. In case we know that the data are only on device memory we can use DATA_ONLY_DEVICE,
346 * In case we know that the data are only on host memory we can use DATA_ONLY_HOST
347 *
348 * \param blockSize The default is equal to 1. In case of accelerator buffer resize indicate the size of the block of
349 * threads ( this is used in case of a vector of blocks where the block object override to operator=
350 * to distribute threads on each block element )
351 *
352 */
353 void resize(size_t slot, size_t opt = DATA_ON_DEVICE | DATA_ON_HOST, unsigned int blockSize = 1)
354 {
355 // If we need more space than what we allocated, allocate new memory
356
357 if (slot > base.size())
358 {
359 size_t gr = slot;
360 // If you increase by one we smartly resize the internal capacity more than 1
361 // This is to make faster patterns like resize(size()+1)
362 if (slot - base.size() == 1 && opt && (opt & EXACT_RESIZE) == 0)
363 {
364 gr = grow_p::grow(base.size(),slot);
365 }
366
367 //! Resize the memory
368 size_t sz[1] = {gr};
369
370 base.resize(sz,opt,blockSize);
371 }
372
373 // update the vector size
374 v_size = slot;
375 }
376
377
378 /*! \brief Resize the vector ()
379 *
380 * Resize the vector and allocate n elements
381 *
382 * \param slot number of elements
383 * \param opt options
384 *
385 */
386 void resize_no_device(size_t slot)
387 {
388 // If we need more space than what we allocated, allocate new memory
389
390 if (slot > base.size())
391 {
392 size_t gr = grow_p::grow(base.size(),slot);
393
394 //! Resize the memory
395 size_t sz[1] = {gr};
396 base.resize_no_device(sz);
397 }
398
399 // update the vector size
400 v_size = slot;
401 }
402
403 //! Access key for the vector
404 typedef size_t access_key;
405
406 /*! \brief It insert a new emtpy object on the vector, eventually it reallocate the grid
407 *
408 * \warning It is not thread safe should not be used in multi-thread environment
409 * reallocation, work only on cpu
410 *
411 */
412 void add()
413 {
414 //! Check if we have enough space
415
416 if (v_size >= base.size())
417 {
418 //! Resize the memory, double up the actual memory allocated for the vector
419 size_t sz[1];
420 non_zero_one(sz,2*base.size());
421 base.resize(sz);
422 }
423
424 //! increase the vector size
425 v_size++;
426 }
427
428 /*! \brief It insert a new emtpy object on the vector, eventually it reallocate the grid
429 *
430 * \warning It is not thread safe should not be used in multi-thread environment
431 * reallocation, work only on cpu
432 *
433 */
434 void add_no_device()
435 {
436 //! Check if we have enough space
437
438 if (v_size >= base.size())
439 {
440 //! Resize the memory, double up the actual memory allocated for the vector
441 size_t sz[1];
442 non_zero_one(sz,2*base.size());
443 base.resize_no_device(sz);
444 }
445
446 //! increase the vector size
447 v_size++;
448 }
449
450 /*! \brief It insert a new object on the vector, eventually it reallocate the grid
451 *
452 * \param v element to add
453 *
454 * \warning It is not thread safe should not be used in multi-thread environment
455 * reallocation, work only on cpu
456 *
457 */
458 void add(const T & v)
459 {
460 //! Check if we have enough space
461
462 if (v_size >= base.size())
463 {
464 //! Resize the memory, double up the actual memory allocated for the vector
465 size_t sz[1];
466 non_zero_one(sz,2*base.size());
467 base.resize(sz);
468 }
469
470 //! copy the element
471 base.set(v_size,v);
472
473 //! increase the vector size
474 v_size++;
475 }
476
477 /*! \brief It insert a new object on the vector, eventually it reallocate the vector
478 *
479 * \param v object (encapsulated)
480 *
481 * \warning It is not thread safe should not be used in multi-thread environment
482 * reallocation, work only on cpu
483 *
484 *
485 */
486 void add(const typename grid_base<1,T,Memory,typename layout_base<T>::type>::container & v)
487 {
488 //! Check if we have enough space
489
490 if (v_size >= base.size())
491 {
492 //! Resize the memory, double up the actual memory allocated for the vector
493 size_t sz[1];
494 non_zero_one(sz,2*base.size());
495 base.resize(sz);
496 }
497
498 //! copy the added element
499 base.set(v_size,v);
500
501 //! increase the vector size
502 v_size++;
503 }
504
505 /*! \brief It add the element of another vector to this vector
506 *
507 * \param v from where to take the vector
508 *
509 */
510 template <typename M, typename gp> void add(const vector<T, M, layout_base,gp,OPENFPM_NATIVE> & v)
511 {
512 //! Add the element of v
513 for (size_t i = 0 ; i < v.size() ; i++)
514 add(v.get(i));
515 }
516
517 /*! \brief It merge the elements of a source vector to this vector
518 *
519 * Given 2 vector v1 and v2 of size 7,3. and as merging operation the function add.
520 * Merging the second vector v2 to
521 * the first one v1 starting from the element 2. Mean
522 *
523 * \verbatim
524 *
525 * 6 8 3 2 1 0 3 v1 elements
526 * | | |
527 * op op op
528 * | | |
529 * 5 1 9 v2 elements
530 *
531 *-------------------------------------
532 * 6 8 8 3 10 0 3 updated v1 elements
533 *
534 * This operation is done for each selected property in args
535 *
536 * \endverbatim
537 *
538 * The number of properties in the source vector must be smaller than the destination
539 * all the properties of S must be mapped so if S has 3 properties
540 * 3 numbers for args are required
541 *
542 * \tparam op merging operation
543 * \tparam S Base object of the source vector
544 * \tparam M memory type of the source vector
545 * \tparam gp Grow policy of the source vector
546 * \tparam args one or more number that define which property to set-up
547 *
548 * \param v source vector
549 * \param start index from where to start the merging
550 *
551 */
552 template <template<typename,typename> class op, typename S, typename M, typename gp, unsigned int ...args>
553 void merge_prp(const vector<S,M,layout_base,gp,OPENFPM_NATIVE> & v,
554 const openfpm::vector<size_t> & opart)
555 {
556#ifdef SE_CLASS1
557
558 if (v.size() != opart.size())
559 std::cerr << __FILE__ << ":" << __LINE__ << " error merge_prp: v.size()=" << v.size() << " must be the same as o_part.size()" << opart.size() << std::endl;
560
561#endif
562 //! Add the element of v
563 for (size_t i = 0 ; i < v.size() ; i++)
564 {
565#ifdef SE_CLASS1
566
567 if (opart.get(i) > size())
568 std::cerr << "Error: " << __FILE__ << ":" << __LINE__ << " try to access element " << opart.get(i) << " but the vector has size " << size() << std::endl;
569
570#endif
571 // write the object in the last element
572 object_s_di_op<op,decltype(v.get(i)),decltype(get(size()-1)),OBJ_ENCAP,args...>(v.get(i),get(opart.get(i)));
573 }
574 }
575
576 /*! \brief It merge the elements of a source vector to this vector (on device)
577 *
578 * Given 2 vector v1 and v2 of size 7,3. and as merging operation the function add.
579 * Merging the second vector v2 to
580 * the first one v1 starting from the element 2. Mean
581 *
582 * \verbatim
583 *
584 * 6 8 3 2 1 0 3 v1 elements
585 * | | |
586 * op op op
587 * | | |
588 * 5 1 9 v2 elements
589 *
590 *-------------------------------------
591 * 6 8 8 3 10 0 3 updated v1 elements
592 *
593 * This operation is done for each selected property in args
594 *
595 * \endverbatim
596 *
597 * The number of properties in the source vector must be smaller than the destination
598 * all the properties of S must be mapped so if S has 3 properties
599 * 3 numbers for args are required
600 *
601 * \tparam op merging operation
602 * \tparam S Base object of the source vector
603 * \tparam M memory type of the source vector
604 * \tparam gp Grow policy of the source vector
605 * \tparam args one or more number that define which property to set-up
606 *
607 * \param v source vector
608 * \param start index from where to start the merging
609 *
610 */
611 template <template<typename,typename> class op, typename S, typename M, typename gp, unsigned int ...args>
612 void merge_prp_device(const vector<S,M,layout_base,gp,OPENFPM_NATIVE> & v,
613 unsigned int start)
614 {
615 merge_prp_device_impl<std::is_same<Memory,CudaMemory>::value,T,Memory,layout_base,grow_p>
616 ::template run<S,M,gp,OPENFPM_NATIVE,layout_base,args...>(*this,v,start);
617 }
618
619
620 /*! \brief It merge the elements of a source vector to this vector
621 *
622 * Given 2 vector v1 and v2 of size 7,3. and as merging operation the function add.
623 * Merging the second vector v2 to
624 * the first one v1 starting from the element 2. Mean
625 *
626 * \verbarim
627 *
628 * 6 8 3 2 1 0 3 v1 elements
629 * | | |
630 * op op op
631 * | | |
632 * 5 1 9 v2 elements
633 *
634 *-------------------------------------
635 * 6 8 8 3 10 0 3 updated v1 elements
636 *
637 * This operation is done for each selected property in args
638 *
639 * \endverbatim
640 *
641 * The number of properties in the source vector must be smaller than the destination
642 * all the properties of S must be mapped so if S has 3 properties
643 * 3 numbers for args are required
644 *
645 * \tparam op merging operation
646 * \tparam S Base object of the source vector
647 * \tparam M memory type of the source vector
648 * \tparam gp Grow policy of the source vector
649 * \tparam args one or more number that define which property to set-up
650 *
651 * \param v source vector
652 * \param start index from where to start the merging
653 *
654 */
655 template <template<typename,typename> class op,
656 typename S,
657 typename M,
658 typename gp,
659 template <typename> class layout_base2,
660 typename vector_opart_type,
661 unsigned int ...args>
662 void merge_prp_v(const vector<S,M,layout_base2,gp,OPENFPM_NATIVE> & v,
663 const vector_opart_type & opart)
664 {
665#ifdef SE_CLASS1
666
667 if (v.size() != opart.size())
668 std::cerr << __FILE__ << ":" << __LINE__ << " error merge_prp: v.size()=" << v.size() << " must be the same as o_part.size()" << opart.size() << std::endl;
669
670#endif
671 //! Add the element of v
672 for (size_t i = 0 ; i < v.size() ; i++)
673 {
674#ifdef SE_CLASS1
675
676 if (i >= opart.size())
677 std::cerr << "Error: " << __FILE__ << ":" << __LINE__ << " try to access element " << opart.template get<0>(i) << " but the vector has size " << size() << std::endl;
678
679#endif
680 // write the object in the last element
681 object_s_di_op<op,decltype(v.get(i)),decltype(get(size()-1)),OBJ_ENCAP,args...>(v.get(i),get(opart.template get<0>(i)));
682 }
683 }
684
685 /*! \brief It merge the elements of a source vector to this vector
686 *
687 * Given 2 vector v1 and v2 of size 7,3. and as merging operation the function add.
688 * Merging the second vector v2 to
689 * the first one v1 starting from the element 2. Mean
690 *
691 * \verbarim
692 *
693 * 6 8 3 2 1 0 3 v1 elements
694 * | | |
695 * op op op
696 * | | |
697 * 5 1 9 v2 elements
698 *
699 *-------------------------------------
700 * 6 8 8 3 10 0 3 updated v1 elements
701 *
702 * This operation is done for each selected property in args
703 *
704 * \endverbatim
705 *
706 * The number of properties in the source vector must be smaller than the destination
707 * all the properties of S must be mapped so if S has 3 properties
708 * 3 numbers for args are required
709 *
710 * \tparam op merging operation
711 * \tparam S Base object of the source vector
712 * \tparam M memory type of the source vector
713 * \tparam gp Grow policy of the source vector
714 * \tparam args one or more number that define which property to set-up
715 *
716 * \param v source vector
717 * \param offset offset from where to copy in v
718 * \param start index from where to start the merging
719 *
720 */
721 template <template<typename,typename> class op,
722 typename S,
723 typename M,
724 typename gp,
725 template <typename> class layout_base2,
726 typename vector_opart_type,
727 unsigned int ...args>
728 void merge_prp_v(const vector<S,M,layout_base2,gp,OPENFPM_NATIVE> & v,
729 unsigned int offset,
730 const vector_opart_type & opart)
731 {
732 size_t i2 = 0;
733
734 for (size_t i = offset ; i < v.size() ; i++)
735 {
736 auto dst = v.get(opart.template get<0>(i2));
737 auto src = v.get(i);
738 copy_cpu_encap_encap_op_prp<op,decltype(v.get(0)),decltype(v.get(0)),args...> cp(src,dst);
739
740 boost::mpl::for_each_ref< boost::mpl::range_c<int,0,sizeof...(args)> >(cp);
741 i2++;
742 }
743 }
744
745 /*! \brief It merge the elements of a source vector to this vector
746 *
747 * Given 2 vector v1 and v2 of size 7,3. and as merging operation the function add.
748 * Merging the second vector v2 to
749 * the first one v1 starting from the element 2. Mean
750 *
751 * \verbarim
752 *
753 * 6 8 3 2 1 0 3 v1 elements
754 * | | |
755 * op op op
756 * | | |
757 * 5 1 9 v2 elements
758 *
759 *-------------------------------------
760 * 6 8 8 3 10 0 3 updated v1 elements
761 *
762 * This operation is done for each selected property in args
763 *
764 * \endverbatim
765 *
766 * The number of properties in the source vector must be smaller than the destination
767 * all the properties of S must be mapped so if S has 3 properties
768 * 3 numbers for args are required
769 *
770 * \tparam op merging operation
771 * \tparam S Base object of the source vector
772 * \tparam M memory type of the source vector
773 * \tparam gp Grow policy of the source vector
774 * \tparam args one or more number that define which property to set-up
775 *
776 * \param v source vector
777 * \param opart merging indexes (property 1)
778 * \param start starting merging index for opart
779 * \param stop stop merging index for opart
780 *
781 */
782 template <template<typename,typename> class op,
783 typename S,
784 typename M,
785 typename gp,
786 template <typename> class layout_base2,
787 typename vector_opart_type,
788 unsigned int ...args>
789 void merge_prp_v_device(const vector<S,M,layout_base2,gp,OPENFPM_NATIVE> & v,
790 const vector_opart_type & opart,
791 unsigned int start,
792 unsigned int stop)
793 {
794#ifdef SE_CLASS1
795
796 if (v.size() != stop - start)
797 std::cerr << __FILE__ << ":" << __LINE__ << " error merge_prp: v.size()=" << v.size() << " must be the same as stop - start" << stop - start << std::endl;
798
799#endif
800
801#ifdef __NVCC__
802
803 size_t sz[1] = {stop - start};
804 grid_sm<1,void> nm(sz);
805
806 auto ite = nm.getGPUIterator();
807
808 // write the object in the last element
809 CUDA_LAUNCH((merge_add_prp_device_impl_src_dst_opar_offset<op,
810 decltype(v.toKernel()),
811 decltype(this->toKernel()),
812 decltype(opart.toKernel()),
813 args...>),ite,v.toKernel(),this->toKernel(),opart.toKernel(),start);
814
815 // calculate
816#else
817 std::cout << __FILE__ << ":" << __LINE__ << " Error you have to compile map_vector.hpp with nvcc to make GPU code working" << std::endl;
818
819#endif
820 }
821
822 /*! \brief It merge the elements of a source vector to this vector
823 *
824 * Given 2 vector v1 and v2 of size 7,3. and as merging operation the function add.
825 * Merging the second vector v2 to
826 * the first one v1 starting from the element 2. Mean
827 *
828 * \verbarim
829 *
830 * 6 8 3 2 1 0 3 v1 elements
831 * | | |
832 * op op op
833 * | | |
834 * 5 1 9 v2 elements
835 *
836 *-------------------------------------
837 * 6 8 8 3 10 0 3 updated v1 elements
838 *
839 * This operation is done for each selected property in args
840 *
841 * \endverbatim
842 *
843 * The number of properties in the source vector must be smaller than the destination
844 * all the properties of S must be mapped so if S has 3 properties
845 * 3 numbers for args are required
846 *
847 * \tparam op merging operation
848 * \tparam S Base object of the source vector
849 * \tparam M memory type of the source vector
850 * \tparam gp Grow policy of the source vector
851 * \tparam args one or more number that define which property to set-up
852 *
853 * \param v source vector
854 * \param opart merging indexes (property 0)
855 * \param i starting mergong indexes
856 *
857 */
858 template <template<typename,typename> class op,
859 typename S,
860 typename M,
861 typename gp,
862 template <typename> class layout_base2,
863 typename vector_opart_type,
864 unsigned int ...args>
865 void merge_prp_v_device(const vector<S,M,layout_base2,gp,OPENFPM_NATIVE> & v,
866 unsigned int start,
867 const vector_opart_type & opart)
868 {
869#ifdef SE_CLASS1
870
871 if (v.size() < opart.size() + start)
872 std::cerr << __FILE__ << ":" << __LINE__ << " error merge_prp: v.size()=" << v.size() << " must be snaller than o_part.size() + start " << opart.size() + start << std::endl;
873
874#endif
875
876#ifdef __NVCC__
877
878 auto ite = opart.getGPUIterator();
879
880 // write the object in the last element
881 CUDA_LAUNCH((merge_add_prp_device_impl_src_offset_dst_opar<op,
882 decltype(v.toKernel()),
883 decltype(this->toKernel()),
884 decltype(opart.toKernel()),
885 args... >),ite,v.toKernel(),this->toKernel(),opart.toKernel(),start);
886
887 // calculate
888#else
889 std::cout << __FILE__ << ":" << __LINE__ << " Error you have to compile map_vector.hpp with nvcc to make GPU code working" << std::endl;
890
891#endif
892 }
893
894 /*! \brief It merge the elements of a source vector to this vector
895 *
896 * Given 2 vector v1 and v2 of size 7,3. and as merging operation the function add.
897 * Merging the second vector v2 to
898 * the first one v1 starting from the element 2. Mean
899 *
900 * \verbarim
901 *
902 * 6 8 3 2 1 0 3 v1 elements
903 * | | |
904 * op op op
905 * | | |
906 * 5 1 9 v2 elements
907 *
908 *-------------------------------------
909 * 6 8 8 3 10 0 3 updated v1 elements
910 *
911 * This operation is done for each selected property in args
912 *
913 * \endverbatim
914 *
915 * The number of properties in the source vector must be smaller than the destination
916 * all the properties of S must be mapped so if S has 3 properties
917 * 3 numbers for args are required
918 *
919 * \tparam op merging operation
920 * \tparam S Base object of the source vector
921 * \tparam M memory type of the source vector
922 * \tparam gp Grow policy of the source vector
923 * \tparam args one or more number that define which property to set-up
924 *
925 * \param v source vector
926 * \param start index from where to start the merging
927 *
928 */
929 template <template<typename,typename> class op,
930 typename S,
931 typename M,
932 typename gp,
933 template <typename> class layout_base2,
934 unsigned int ...args>
935 void merge_prp_v(const vector<S,M,layout_base2,gp,OPENFPM_NATIVE> & v,
936 size_t start)
937 {
938 //! Add the element of v
939 for (size_t i = 0 ; i < v.size() ; i++)
940 {
941#ifdef SE_CLASS1
942
943 if (start + i >= v_size)
944 std::cerr << "Error: " << __FILE__ << ":" << __LINE__ << " try to access element " << start+i << " but the vector has size " << size() << std::endl;
945
946#endif
947 // write the object in the last element
948 object_s_di_op<op,decltype(v.get(0)),decltype(get(0)),OBJ_ENCAP,args...>(v.get(i),get(start+i));
949 }
950 }
951
952 /*! \brief It add the element of a source vector to this vector
953 *
954 * The number of properties in the source vector must be smaller than the destination
955 * all the properties of S must be mapped so if S has 3 properties
956 * 3 numbers for args are required
957 *
958 * \tparam S Base object of the source vector
959 * \tparam M memory type of the source vector
960 * \tparam gp Grow policy of the source vector
961 * \tparam args one or more number that define which property to set-up
962 *
963 * \param v source vector
964 *
965 */
966 template <typename S,
967 typename M,
968 typename gp,
969 unsigned int impl,
970 template <typename> class layout_base2,
971 unsigned int ...args>
972 void add_prp(const vector<S,M,layout_base2,gp,impl> & v)
973 {
974 //! Add the element of v
975 for (size_t i = 0 ; i < v.size() ; i++)
976 {
977 // Add a new element
978 add();
979
980 // write the object in the last element
981 object_s_di<decltype(v.get(i)),decltype(get(size()-1)),OBJ_ENCAP,args...>(v.get(i),get(size()-1));
982 }
983 }
984
985 /*! \brief It add the element of a source vector to this vector
986 *
987 * The number of properties in the source vector must be smaller than the destination
988 * all the properties of S must be mapped so if S has 3 properties
989 * 3 numbers for args are required
990 *
991 * \tparam S Base object of the source vector
992 * \tparam M memory type of the source vector
993 * \tparam gp Grow policy of the source vector
994 * \tparam args one or more number that define which property to set-up
995 *
996 * \param v source vector
997 *
998 */
999 template <typename S,
1000 typename M,
1001 typename gp,
1002 unsigned int impl,
1003 template <typename> class layout_base2,
1004 unsigned int ...args>
1005 void add_prp_device(const vector<S,M,layout_base2,gp,impl> & v)
1006 {
1007 add_prp_device_impl<std::is_same<Memory,CudaMemory>::value,T,Memory,layout_base,grow_p>
1008 ::template run<S,M,gp,impl,layout_base2,args...>(*this,v);
1009 }
1010
1011 /*! \brief Insert an entry in the vector
1012 *
1013 * \size_t key Where to insert the element
1014 *
1015 */
1016 void insert(size_t key)
1017 {
1018 add();
1019
1020 long int d_k = (long int)size()-1;
1021 long int s_k = (long int)size()-2;
1022
1023 // keys
1024 while (s_k >= (long int)key)
1025 {
1026 set(d_k,get(s_k));
1027 d_k--;
1028 s_k--;
1029 }
1030 }
1031
1032
1033 /*! \brief Remove one entry from the vector
1034 *
1035 * \param key element to remove
1036 *
1037 */
1038 void remove(size_t key)
1039 {
1040 size_t d_k = key;
1041 size_t s_k = key + 1;
1042
1043 // keys
1044 while (s_k < size())
1045 {
1046 set(d_k,get(s_k));
1047 d_k++;
1048 s_k++;
1049 }
1050
1051 // re-calculate the vector size
1052
1053 v_size--;
1054 }
1055
1056 /*! \brief Remove several entries from the vector
1057 *
1058 * \warning the keys in the vector MUST be sorted
1059 *
1060 * \param keys objects id to remove
1061 * \param start key starting point
1062 *
1063 */
1064 void remove(openfpm::vector<size_t> & keys, size_t start = 0)
1065 {
1066 // Nothing to remove return
1067 if (keys.size() <= start )
1068 return;
1069
1070 size_t a_key = start;
1071 size_t d_k = keys.get(a_key);
1072 size_t s_k = keys.get(a_key) + 1;
1073
1074 // keys
1075 while (s_k < size())
1076 {
1077 // s_k should always point to a key that is not going to be deleted
1078 while (a_key+1 < keys.size() && s_k == keys.get(a_key+1))
1079 {
1080 a_key++;
1081 s_k = keys.get(a_key) + 1;
1082 }
1083
1084 // In case of overflow
1085 if (s_k >= size())
1086 break;
1087
1088 set(d_k,get(s_k));
1089 d_k++;
1090 s_k++;
1091 }
1092
1093 // re-calculate the vector size
1094
1095 v_size -= keys.size() - start;
1096 }
1097
1098 /*! \brief Get an element of the vector
1099 *
1100 * Get an element of the vector
1101 *
1102 * \tparam p Property to get
1103 * \param id Element to get
1104 *
1105 * \return the element value requested
1106 *
1107 */
1108
1109 template <unsigned int p>
1110 inline auto get(size_t id) const -> decltype(base.template get<p>(grid_key_dx<1>(0)))
1111 {
1112#if defined(SE_CLASS1) && !defined(__NVCC__)
1113 check_overflow(id);
1114#endif
1115 grid_key_dx<1> key(id);
1116
1117
1118 return base.template get<p>(key);
1119 }
1120
1121 /*! \brief Get an element of the vector
1122 *
1123 * Get an element of the vector
1124 *
1125 * \param id Element to get
1126 *
1127 * \return the element (encapsulated)
1128 *
1129 */
1130 inline auto get(size_t id) -> decltype(base.get_o(grid_key_dx<1>(id)))
1131 {
1132#if defined(SE_CLASS1) && !defined(__NVCC__)
1133 check_overflow(id);
1134#endif
1135 grid_key_dx<1> key(id);
1136
1137 return base.get_o(key);
1138 }
1139
1140 /*! \brief Get an element of the vector
1141 *
1142 * Get an element of the vector
1143 *
1144 * \param id Element to get
1145 *
1146 * \return the element (encapsulated)
1147 *
1148 */
1149 inline auto get(size_t id) const -> const decltype(base.get_o(grid_key_dx<1>(id)))
1150 {
1151#if defined(SE_CLASS1) && !defined(__NVCC__)
1152 check_overflow(id);
1153#endif
1154 grid_key_dx<1> key(id);
1155
1156 return base.get_o(key);
1157 }
1158
1159 /*! \brief Get an element of the vector
1160 *
1161 * \deprecated
1162 *
1163 * exactly as get, exist to keep the compatibility with grid
1164 *
1165 * \param id Element to get
1166 *
1167 * \return the element (encapsulated)
1168 *
1169 */
1170
1171 inline const typename grid_base<1,T,Memory,typename layout_base<T>::type>::container get_o(size_t id) const
1172 {
1173#if defined(SE_CLASS1) && !defined(__NVCC__)
1174 check_overflow(id);
1175#endif
1176 grid_key_dx<1> key(id);
1177
1178 return base.get_o(key);
1179 }
1180
1181 /*! \brief Fill the buffer with a byte
1182 *
1183 * \param c char to fill the buffer with
1184 *
1185 */
1186 template<unsigned int id> void fill(unsigned char c)
1187 {
1188 base.template fill<id>(c);
1189 }
1190
1191 /*! \brief It return the properties arrays.
1192 *
1193 * In case of Cuda memory it return the device pointers to pass to the kernels
1194 *
1195 *
1196 */
1197 template<unsigned int id> void * getDeviceBufferCopy()
1198 {
1199 return base.template getDeviceBuffer<id>();
1200 }
1201
1202 /*! \brief It return the properties arrays.
1203 *
1204 * In case of Cuda memory it return the device pointers to pass to the kernels
1205 *
1206 * This variant does not copy the host memory to the device memory
1207 *
1208 *
1209 */
1210 template<unsigned int id> void * getDeviceBuffer()
1211 {
1212 return base.template getDeviceBuffer<id>();
1213 }
1214
1215
1216 /*! \brief Get the last element of the vector
1217 *
1218 * \return the last element (encapsulated)
1219 *
1220 */
1221 inline const typename grid_base<1,T,Memory,layout_type>::container last() const
1222 {
1223 grid_key_dx<1> key(size()-1);
1224
1225 return base.get_o(key);
1226 }
1227
1228 /*! \brief Get an element of the vector
1229 *
1230 * Get an element of the vector
1231 *
1232 * \tparam p Property to get
1233 * \param id Element to get
1234 *
1235 * \return the element value requested
1236 *
1237 */
1238
1239 template <unsigned int p>
1240 inline auto get(size_t id) -> decltype(base.template get<p>(grid_key_dx<1>(0)))
1241 {
1242#if defined(SE_CLASS1) && !defined(__NVCC__)
1243 check_overflow(id);
1244#endif
1245 grid_key_dx<1> key(id);
1246
1247 return base.template get<p>(key);
1248 }
1249
1250 /*! \brief Get the last element of the vector
1251 *
1252 * \return the element (encapsulated)
1253 *
1254 */
1255
1256 inline typename grid_base<1,T,Memory,typename layout_base<T>::type >::container last()
1257 {
1258 grid_key_dx<1> key(size()-1);
1259
1260 return base.get_o(key);
1261 }
1262
1263 //! Destructor
1264 ~vector() THROW
1265 {
1266 // Eliminate the pointer
1267 }
1268
1269 /*! \brief It duplicate the vector
1270 *
1271 * \return a duplicated vector
1272 *
1273 */
1274 vector<T, Memory,layout_base,grow_p,OPENFPM_NATIVE> duplicate() const
1275 {
1276 vector<T, Memory,layout_base,grow_p,OPENFPM_NATIVE> dup;
1277
1278 dup.v_size = v_size;
1279 dup.base.swap(base.duplicate());
1280
1281 // copy the device part
1282 // and device
1283 if (Memory::isDeviceHostSame() == false)
1284 {
1285#ifdef __NVCC__
1286 if (dup.size() != 0)
1287 {
1288 auto it = dup.getGPUIterator();
1289 CUDA_LAUNCH(copy_two_vectors,it,dup.toKernel(),toKernel());
1290 }
1291#endif
1292 }
1293
1294 return dup;
1295 }
1296
1297 /*! \brief Constructor from another temporal vector
1298 *
1299 * \param v the vector
1300 *
1301 */
1302 vector(vector<T, Memory,layout_base,grow_p,OPENFPM_NATIVE> && v)
1303 :v_size(0)
1304 {
1305 swap(v);
1306 }
1307
1308 /*! \brief Constructor from another constant vector
1309 *
1310 * \param v the vector
1311 *
1312 */
1313 vector(const vector<T, Memory,layout_base,grow_p,OPENFPM_NATIVE> & v) THROW
1314 :v_size(0)
1315 {
1316 swap(v.duplicate());
1317 }
1318
1319 //! Constructor, vector of size 0
1320 vector() THROW
1321 :v_size(0),base(0)
1322 {
1323 base.setMemory();
1324 }
1325
1326 //! Constructor, vector of size sz
1327 vector(size_t sz) THROW
1328 :v_size(sz),base(sz)
1329 {
1330 base.setMemory();
1331 }
1332
1333 /*! \brief Set the object id to obj
1334 *
1335 * \param id element
1336 * \param obj object (encapsulated)
1337 *
1338 */
1339 void set(size_t id, const typename grid_base<1,T,Memory,typename layout_base<T>::type>::container & obj)
1340 {
1341#ifdef SE_CLASS1
1342 check_overflow(id);
1343#endif
1344 //! copy the element
1345 base.set(id,obj);
1346 }
1347
1348 /*! \brief It set an element of the vector from a object that is a subset of the vector properties
1349 *
1350 * The number of properties in the source vector must be smaller than the destination
1351 * all the properties of S must be mapped so if S has 3 properties
1352 * 3 numbers for args are required
1353 *
1354 * \tparam encap_S object that encapsulate the object
1355 * \tparam args ids of the properties to map the object to
1356 *
1357 * \param i element to set
1358 * \param obj object that encapsulate the object
1359 *
1360 * \param v source vector
1361 *
1362 */
1363 template <typename encap_S, unsigned int ...args> void set_o(size_t i, const encap_S & obj)
1364 {
1365 // write the object in the last element
1366 object_s_di<encap_S,decltype(get(i)),OBJ_ENCAP,args...>(obj,get(i));
1367 }
1368
1369 /*! \brief Set the object id to obj
1370 *
1371 * \param id
1372 * \param obj
1373 *
1374 */
1375 void set(size_t id, const T & obj)
1376 {
1377#ifdef SE_CLASS1
1378 check_overflow(id);
1379#endif
1380 //! copy the element
1381 base.set(id,obj);
1382 }
1383
1384 /*! \brief Set the element of the vector v from another element of another vector
1385 *
1386 * \param id element id
1387 * \param v vector source
1388 * \param src source element
1389 *
1390 */
1391 void set(size_t id, vector<T,Memory,layout_base,grow_p,OPENFPM_NATIVE> & v, size_t src)
1392 {
1393#ifdef SE_CLASS1
1394 check_overflow(id);
1395#endif
1396 base.set(id,v.base,src);
1397 }
1398
1399
1400 /*! \brief Assignment operator
1401 *
1402 * move semantic movement operator=
1403 *
1404 * \param mv vector
1405 *
1406 * \return itself
1407 *
1408 */
1409 vector<T, Memory,layout_base,grow_p,OPENFPM_NATIVE> & operator=(vector<T, Memory, layout_base,grow_p,OPENFPM_NATIVE> && mv)
1410 {
1411 v_size = mv.v_size;
1412 base.swap(mv.base);
1413
1414 return *this;
1415 }
1416
1417 /*! \brief Assignment operator
1418 *
1419 * it copy
1420 *
1421 * \param mv vector
1422 *
1423 * \return itself
1424 *
1425 */
1426 vector<T, Memory,layout_base,grow_p,OPENFPM_NATIVE> & operator=(const vector<T, Memory, layout_base ,grow_p,OPENFPM_NATIVE> & mv)
1427 {
1428 v_size = mv.v_size;
1429 size_t rsz[1] = {v_size};
1430 base.resize(rsz);
1431
1432 // copy the object on cpu
1433 for (size_t i = 0 ; i < v_size ; i++ )
1434 {
1435 grid_key_dx<1> key(i);
1436 base.set(key,mv.base,key);
1437 }
1438
1439 // and device
1440 if (Memory::isDeviceHostSame() == false)
1441 {
1442#ifdef __NVCC__
1443 if (mv.size() != 0)
1444 {
1445 auto it = mv.getGPUIterator();
1446 CUDA_LAUNCH(copy_two_vectors,it,toKernel(),mv.toKernel());
1447 }
1448#endif
1449 }
1450
1451
1452 return *this;
1453 }
1454
1455 /*! \brief Assignment operator
1456 *
1457 * move semantic movement operator=
1458 *
1459 * \param mv vector
1460 *
1461 * \return itself
1462 *
1463 */
1464 template<typename Mem, typename gp> vector<T, Memory,layout_base,grow_p,OPENFPM_NATIVE> & operator=(vector<T, Mem, layout_base,gp,OPENFPM_NATIVE> && mv)
1465 {
1466 v_size = mv.v_size;
1467 base.swap(mv.base);
1468
1469 return *this;
1470 }
1471
1472 /*! \brief Assignment operator
1473 *
1474 * it copy
1475 *
1476 * \param mv vector
1477 *
1478 * \return itself
1479 *
1480 */
1481 template<typename Mem, typename gp> vector<T, Memory,layout_base,grow_p,OPENFPM_NATIVE> & operator=(const vector<T, Mem, layout_base ,gp,OPENFPM_NATIVE> & mv)
1482 {
1483 v_size = mv.getInternal_v_size();
1484 size_t rsz[1] = {v_size};
1485 base.resize(rsz);
1486
1487 // copy the object
1488 for (size_t i = 0 ; i < v_size ; i++ )
1489 {
1490 grid_key_dx<1> key(i);
1491 base.set(key,mv.getInternal_base(),key);
1492 }
1493
1494 // and device
1495 if (Memory::isDeviceHostSame() == false && Mem::isDeviceHostSame() == false)
1496 {
1497#ifdef __NVCC__
1498 if (mv.size() != 0)
1499 {
1500 auto it = mv.getGPUIterator();
1501 CUDA_LAUNCH(copy_two_vectors,it,toKernel(),mv.toKernel());
1502 }
1503#endif
1504 }
1505
1506 return *this;
1507 }
1508
1509 /*! \brief Assignment operator
1510 *
1511 * move semantic movement operator=
1512 *
1513 * \param mv vector
1514 *
1515 * \return itself
1516 *
1517 */
1518 template<typename Mem, template <typename> class layout_base2>
1519 vector<T, Memory,layout_base2,grow_p,OPENFPM_NATIVE> & operator=(vector<T, Mem, layout_base2,grow_p,OPENFPM_NATIVE> && mv)
1520 {
1521 v_size = mv.v_size;
1522 base.swap(mv.base);
1523
1524 return *this;
1525 }
1526
1527 /*! \brief Assignment operator
1528 *
1529 *
1530 * \param mv vector to copy
1531 *
1532 * \return itself
1533 *
1534 *
1535 */
1536 template<typename Mem,
1537 template <typename> class layout_base2,
1538 typename check = typename std::enable_if<!std::is_same<typename layout_base2<T>::type,typename layout_base<T>::type>::value >::type>
1539 vector<T, Memory,layout_base,grow_p,OPENFPM_NATIVE> &
1540 operator=(const vector<T, Mem, layout_base2 ,grow_p,OPENFPM_NATIVE> & mv)
1541 {
1542 v_size = mv.getInternal_v_size();
1543 size_t rsz[1] = {v_size};
1544 base.resize(rsz);
1545
1546 // copy the object
1547 for (size_t i = 0 ; i < v_size ; i++ )
1548 {
1549 grid_key_dx<1> key(i);
1550 base.set_general(key,mv.getInternal_base(),key);
1551 }
1552
1553 // and device
1554 if (Memory::isDeviceHostSame() == false && Mem::isDeviceHostSame() == false)
1555 {
1556#ifdef __NVCC__
1557 if (mv.size() != 0)
1558 {
1559 auto it = mv.getGPUIterator();
1560 CUDA_LAUNCH(copy_two_vectors,it,toKernel(),mv.toKernel());
1561 }
1562#endif
1563 }
1564
1565 return *this;
1566 }
1567
1568 /*! \brief Check that two vectors are equal
1569 *
1570 * \param vector to compare
1571 *
1572 */
1573 bool operator!=(const vector<T, Memory, layout_base,grow_p,OPENFPM_NATIVE> & v) const
1574 {
1575 return !this->operator==(v);
1576 }
1577
1578 /*! \brief Check that two vectors are not equal
1579 *
1580 * \param vector to compare
1581 *
1582 */
1583 bool operator==(const vector<T, Memory, layout_base, grow_p,OPENFPM_NATIVE> & v) const
1584 {
1585 if (v_size != v.v_size)
1586 return false;
1587
1588 // check object by object
1589 for (size_t i = 0 ; i < v_size ; i++ )
1590 {
1591 grid_key_dx<1> key(i);
1592
1593 if (base.get_o(key) != v.base.get_o(key))
1594 return false;
1595 }
1596
1597 return true;
1598 }
1599
1600 /*! \brief Swap the memory with another vector
1601 *
1602 * \note this is different from the normal swap please look a grid_base_implementation.hpp method swap_nomode
1603 * for info
1604 *
1605 * \param v vector
1606 *
1607 */
1608 void swap_nomode(openfpm::vector<T,Memory, layout_base,grow_p,OPENFPM_NATIVE> & v)
1609 {
1610 size_t sz_sp = v_size;
1611
1612 // swap the v_size
1613 v_size = v.v_size;
1614
1615 base.swap_nomode(v.base);
1616 v.v_size = sz_sp;
1617 }
1618
1619 /*! \brief Swap the memory with another vector
1620 *
1621 * \param v vector
1622 *
1623 */
1624 void swap(openfpm::vector<T,Memory, layout_base,grow_p,OPENFPM_NATIVE> & v)
1625 {
1626 size_t sz_sp = v_size;
1627
1628 // swap the v_size
1629 v_size = v.v_size;
1630
1631 base.swap(v.base);
1632 v.v_size = sz_sp;
1633 }
1634
1635 /*! \brief Swap the memory with another vector
1636 *
1637 * \param v vector
1638 *
1639 */
1640 void swap(openfpm::vector<T,Memory, layout_base,grow_p,OPENFPM_NATIVE> && v)
1641 {
1642 size_t sz_sp = v_size;
1643
1644 // swap the v_size
1645 v_size = v.v_size;
1646
1647 base.swap(v.base);
1648 v.v_size = sz_sp;
1649 }
1650
1651 /*! \brief Get iterator over the particles from a particular index
1652 *
1653 * \param start starting point
1654 *
1655 * \return an iterator to iterate from a particular index
1656 *
1657 */
1658 vector_key_iterator getIteratorFrom(size_t start) const
1659 {
1660 return vector_key_iterator(v_size,start);
1661 }
1662
1663 /*! \brief Get iterator over the particles from 0 until a particular index
1664 *
1665 * \warning stop point is not included
1666 *
1667 * \param stop stop point
1668 *
1669 * \return an iterator to iterate until a particular index
1670 *
1671 */
1672 vector_key_iterator getIteratorTo(size_t stop) const
1673 {
1674 return vector_key_iterator(stop,0);
1675 }
1676
1677#ifdef CUDA_GPU
1678
1679 /*! \brief Get an iterator for the GPU
1680 *
1681 *
1682 */
1683 ite_gpu<1> getGPUIteratorTo(long int stop, size_t n_thr = 1024) const
1684 {
1685 grid_key_dx<1,long int> start(0);
1686 grid_key_dx<1,long int> stop_(stop);
1687
1688 return base.getGPUIterator(start,stop_,n_thr);
1689 }
1690
1691#endif
1692
1693 /*! \brief Get the vector elements iterator
1694 *
1695 *
1696 * \return an iterator to iterate through all the elements of the vector
1697 *
1698 */
1699
1700 vector_key_iterator getIterator() const
1701 {
1702 return vector_key_iterator(v_size);
1703 }
1704
1705#ifdef CUDA_GPU
1706
1707 /*! \brief Get an iterator for the GPU
1708 *
1709 *
1710 */
1711 ite_gpu<1> getGPUIterator(size_t n_thr = 1024) const
1712 {
1713 grid_key_dx<1> start(0);
1714 grid_key_dx<1> stop(size()-1);
1715
1716 return base.getGPUIterator(start,stop,n_thr);
1717 }
1718
1719#endif
1720 /*! \brief Return the size of the message needed to pack this object
1721 *
1722 * \return The size
1723 *
1724 */
1725
1726 size_t packObjectSize()
1727 {
1728 return base.packObjectSize();
1729 }
1730
1731 /*! \brief Pack the object into the given pointer
1732 *
1733 * \param mem pointer
1734 *
1735 * \return the size of the packed message
1736 *
1737 */
1738 size_t packObject(void * mem)
1739 {
1740 return base.packObject(mem);
1741 }
1742
1743 /*! \brief Calculate the memory size required to allocate n elements
1744 *
1745 * Calculate the total size required to store n-elements in a vector
1746 *
1747 * \param n number of elements
1748 * \param e unused
1749 *
1750 * \return the size of the allocation number e
1751 *
1752 */
1753 template<int ... prp> static inline size_t calculateMem(size_t n, size_t e)
1754 {
1755 if (n == 0)
1756 {
1757 return 0;
1758 }
1759 else
1760 {
1761 if (sizeof...(prp) == 0)
1762 return grow_p::grow(0,n) * sizeof(typename T::type);
1763
1764 typedef object<typename object_creator<typename T::type,prp...>::type> prp_object;
1765
1766 return grow_p::grow(0,n) * sizeof(prp_object);
1767 }
1768 }
1769
1770 /*! \brief Calculate the memory size required to pack n elements
1771 *
1772 * Calculate the total size required to store n-elements in a vector
1773 *
1774 * \param n number of elements
1775 * \param e unused
1776 *
1777 * \return the size of the allocation number e
1778 *
1779 */
1780 template<int ... prp> static inline size_t packMem(size_t n, size_t e)
1781 {
1782 if (sizeof...(prp) == 0)
1783 return n * sizeof(typename T::type);
1784
1785 typedef object<typename object_creator<typename T::type,prp...>::type> prp_object;
1786
1787 return n * sizeof(prp_object);
1788 }
1789
1790 /*! \brief How many allocation are required to create n-elements
1791 *
1792 * \param n number of elements
1793 *
1794 * \return the number of allocations
1795 *
1796 */
1797 inline static size_t calculateNMem(size_t n)
1798 {
1799 return 1;
1800 }
1801
1802 /*! \brief Set the memory of the base structure using an object
1803 *
1804 * \param mem Memory object to use for allocation
1805 *
1806 */
1807 template<unsigned int p = 0> void setMemory(Memory & mem)
1808 {
1809 base.template setMemory<p>(mem);
1810 }
1811
1812 /*! \brief Set the memory of the base structure using an object
1813 *
1814 * \param mem Memory object to use for allocation
1815 *
1816 */
1817 void setMemoryArray(Memory * mem)
1818 {
1819 base.setMemoryArray(mem);
1820 }
1821
1822 /*! \brief Return the pointer that store the data
1823 *
1824 * \tparam property from which take the pointer
1825 *
1826 * \return the pointer that store the data
1827 *
1828 */
1829 template<unsigned int p = 0> void * getPointer()
1830 {
1831 return base.template getPointer<p>();
1832 }
1833
1834 /*! \brief Return the pointer that store the data
1835 *
1836 * \return the pointer that store the data
1837 *
1838 */
1839 template<unsigned int p = 0> const void * getPointer() const
1840 {
1841 return base.getPointer();
1842 }
1843
1844 /*! \brief This class has pointer inside
1845 *
1846 * \return false
1847 *
1848 */
1849 static bool noPointers()
1850 {
1851 return false;
1852 }
1853
1854 /*! \brief Internal function
1855 *
1856 * \return the size of the vector
1857 *
1858 */
1859 const size_t & getInternal_v_size() const
1860 {
1861 return v_size;
1862 }
1863
1864 /*! \brief Internal function
1865 *
1866 * \return the internal 1D grid base
1867 *
1868 */
1869 const grid_base<1,T,Memory,layout_type> & getInternal_base() const
1870 {
1871 return base;
1872 }
1873
1874 /*! \brief Copy the memory from host to device
1875 *
1876 *
1877 */
1878 template<unsigned int ... prp> void hostToDevice()
1879 {
1880 base.template hostToDevice<prp ...>();
1881 }
1882
1883 /*! \brief Synchronize the memory buffer in the device with the memory in the host
1884 *
1885 *
1886 */
1887 template<unsigned int ... prp> void deviceToHost()
1888 {
1889 base.template deviceToHost<prp ...>();
1890 }
1891
1892
1893 /*! \brief Synchronize the memory buffer in the device with the memory in the host
1894 *
1895 *
1896 */
1897 template<unsigned int ... prp> void deviceToHost(size_t start, size_t stop)
1898 {
1899 base.template deviceToHost<prp ...>(start,stop);
1900 }
1901
1902 /*! \brief Synchronize the memory buffer in the device with the memory in the host
1903 *
1904 *
1905 */
1906 template<unsigned int ... prp> void hostToDevice(size_t start, size_t stop)
1907 {
1908 base.template hostToDevice<prp ...>(start,stop);
1909 }
1910
1911
1912 /*! \brief Convert the grid into a data-structure compatible for computing into GPU
1913 *
1914 * The object created can be considered like a reference of the original
1915 *
1916 * \return an usable vector in the kernel
1917 *
1918 */
1919 vector_gpu_ker<typename apply_transform<layout_base,T>::type,layout_base> toKernel()
1920 {
1921 vector_gpu_ker<typename apply_transform<layout_base,T>::type,layout_base> v(v_size,this->base.toKernel());
1922
1923 return v;
1924 }
1925
1926 /*! \brief Convert the grid into a data-structure compatible for computing into GPU
1927 *
1928 * The object created can be considered like a reference of the original
1929 *
1930 * \return an usable vector in the kernel
1931 *
1932 */
1933 const vector_gpu_ker<typename apply_transform<layout_base,T>::type,layout_base> toKernel() const
1934 {
1935 if (base.size() == 0)
1936 {std::cout << __FILE__ << ":" << __LINE__ << " Warning you are off-loading with toGPU a vector that seem to be empty or not initialized" << std::endl; }
1937
1938 vector_gpu_ker<typename apply_transform<layout_base,T>::type,layout_base> v(v_size,this->base.toKernel());
1939
1940 return v;
1941 }
1942
1943 /*! Convert this vector into a string
1944 *
1945 * \param prefix prefix to use for printing
1946 *
1947 * \return a string showing thid vector
1948 *
1949 */
1950 template<unsigned int ... prps>
1951 const std::string toString(std::string prefix = std::string())
1952 {
1953 std::stringstream ss;
1954 auto it = getIterator();
1955
1956 while (it.isNext())
1957 {
1958 auto p = it.get();
1959
1960 ss << prefix;
1961
1962 ss << prefix << " element[" << p << "]" << " ";
1963
1964 vector_printer<self_type,prps ...> vp(*this,p,ss);
1965 boost::mpl::for_each_ref<boost::mpl::range_c<int,0,sizeof...(prps)>>(vp);
1966
1967 ss << std::endl;
1968
1969 ++it;
1970 }
1971
1972 return ss.str();
1973 }
1974
1975 void * internal_get_size_pointer() {return &v_size;}
1976
1977 void print_size()
1978 {
1979#ifndef DISABLE_ALL_RTTI
1980 std::cout << "the size of: " << demangle(typeid(self_type).name()) << " is " << sizeof(self_type) << std::endl;
1981 std::cout << " " << demangle(typeid(decltype(v_size)).name()) << ":" << sizeof(decltype(v_size)) << std::endl;
1982 std::cout << " " << demangle(typeid(decltype(base)).name()) << ":" << sizeof(decltype(base)) << std::endl;
1983#endif
1984 }
1985
1986 };
1987
1988 template <typename T> using vector_std = vector<T, HeapMemory, memory_traits_lin, openfpm::grow_policy_double, STD_VECTOR>;
1989 template<typename T> using vector_gpu = openfpm::vector<T,CudaMemory,memory_traits_inte>;
1990 template<typename T> using vector_gpu_single = openfpm::vector<T,CudaMemory,memory_traits_inte,openfpm::grow_policy_identity>;
1991 template<typename T> using vector_custd = vector<T, CudaMemory, memory_traits_inte, openfpm::grow_policy_double, STD_VECTOR>;
1992}
1993
1994#endif
1995