1 | /* |
2 | * multi_array_ref_openfpm.hpp |
3 | * |
4 | * Created on: Jun 29, 2018 |
5 | * Author: i-bird |
6 | */ |
7 | |
8 | #ifndef MULTI_ARRAY_REF_OPENFPM_HPP_ |
9 | #define MULTI_ARRAY_REF_OPENFPM_HPP_ |
10 | |
11 | #include "util/cuda_util.hpp" |
12 | #include "boost/multi_array/collection_concept.hpp" |
13 | #include "boost/multi_array/concept_checks.hpp" |
14 | #include "boost/multi_array/algorithm.hpp" |
15 | #include <boost/mpl/placeholders.hpp> |
16 | #include <boost/mpl/accumulate.hpp> |
17 | #include <boost/mpl/multiplies.hpp> |
18 | #include <boost/concept_check.hpp> |
19 | #include "array_openfpm.hpp" |
20 | #include "types.hpp" |
21 | #include "multi_array_ref_base_openfpm.hpp" |
22 | #include "multi_array_ref_subarray_openfpm.hpp" |
23 | #include "storage_order.hpp" |
24 | #include "multi_array_iterator_openfpm.hpp" |
25 | #include "util/common.hpp" |
26 | |
27 | namespace openfpm { |
28 | |
29 | |
30 | |
31 | template <typename T, std::size_t NumDims, typename vector, typename TPtr> |
32 | class const_multi_array_ref_openfpm : public detail::multi_array::multi_array_impl_base_openfpm<T,NumDims,vector> |
33 | { |
34 | typedef detail::multi_array::multi_array_impl_base_openfpm<T,NumDims,vector> super_type; |
35 | |
36 | typedef typename boost::mpl::accumulate<vector, |
37 | typename boost::mpl::int_<1>, |
38 | typename boost::mpl::multiplies<typename boost::mpl::_2,typename boost::mpl::_1> >::type size_ct; |
39 | |
40 | public: |
41 | |
42 | /* typedef typename super_type::value_type value_type;*/ |
43 | typedef typename super_type::const_reference const_reference; |
44 | typedef typename super_type::const_iterator const_iterator; |
45 | /* typedef typename super_type::const_reverse_iterator const_reverse_iterator;*/ |
46 | typedef T element; |
47 | typedef size_t size_type; |
48 | /* typedef typename super_type::difference_type difference_type;*/ |
49 | typedef typename super_type::index index; |
50 | /* typedef typename super_type::extent_range extent_range;*/ |
51 | typedef general_storage_order<NumDims> storage_order_type; |
52 | |
53 | template <typename ExtentType> |
54 | explicit const_multi_array_ref_openfpm(TPtr base, const ExtentType& extents, const general_storage_order<NumDims>& so) |
55 | :base_(base),storage_(so) |
56 | { |
57 | init_multi_array_ref(extents); |
58 | } |
59 | |
60 | |
61 | template <class InputIterator> |
62 | void assign(InputIterator begin, InputIterator end) |
63 | { |
64 | boost::function_requires<boost::InputIteratorConcept<InputIterator> >(); |
65 | |
66 | InputIterator in_iter = begin; |
67 | T* out_iter = base_; |
68 | std::size_t copy_count=0; |
69 | while (in_iter != end && copy_count < num_elements_) |
70 | { |
71 | *out_iter++ = *in_iter++; |
72 | copy_count++; |
73 | } |
74 | } |
75 | |
76 | size_type num_dimensions() const { return NumDims; } |
77 | |
78 | size_type size() const { return extent_sz; } |
79 | |
80 | // given reshaping functionality, this is the max possible size. |
81 | size_type max_size() const { return num_elements(); } |
82 | |
83 | bool empty() const { return size() == 0; } |
84 | |
85 | inline __device__ __host__ const index* strides() const {return stride_list_.data();} |
86 | inline __device__ __host__ const element* origin() const { return base_; } |
87 | inline __device__ __host__ const element* data() const { return base_; } |
88 | |
89 | size_type num_elements() const { return num_elements_; } |
90 | |
91 | const_iterator begin() const |
92 | { |
93 | return const_iterator(0,origin(),size(),strides()); |
94 | } |
95 | |
96 | const_iterator end() const |
97 | { |
98 | return const_iterator(size(),origin(),size(),strides()); |
99 | } |
100 | |
101 | typedef openfpm::array<index,NumDims> index_list; |
102 | |
103 | // This is used by multi_array, which is a subclass of this |
104 | void set_base_ptr(TPtr new_base) { base_ = new_base; } |
105 | |
106 | |
107 | TPtr base_; |
108 | storage_order_type storage_; |
109 | size_type extent_sz; |
110 | size_type num_elements_; |
111 | index_list stride_list_; |
112 | |
113 | private: |
114 | |
115 | // const_multi_array_ref cannot be assigned to (no deep copies!) |
116 | const_multi_array_ref_openfpm& operator=(const const_multi_array_ref_openfpm & other); |
117 | |
118 | void init_multi_array_ref(const index sz) |
119 | { |
120 | // calculate the extents |
121 | extent_sz = sz; |
122 | |
123 | this->compute_strides(stride_list_,extent_sz,storage_); |
124 | |
125 | num_elements_ = sz * size_ct::value; |
126 | } |
127 | }; |
128 | |
129 | |
130 | template <typename T, int NumDims, typename vector> |
131 | class multi_array_ref_openfpm : public const_multi_array_ref_openfpm<T,NumDims,vector,T *> |
132 | { |
133 | typedef const_multi_array_ref_openfpm<T,NumDims,vector,T *> super_type; |
134 | public: |
135 | /* typedef typename super_type::value_type value_type;*/ |
136 | typedef typename super_type::reference reference; |
137 | typedef typename super_type::iterator iterator; |
138 | /* typedef typename super_type::reverse_iterator reverse_iterator;*/ |
139 | typedef typename super_type::const_reference const_reference; |
140 | typedef typename super_type::const_iterator const_iterator; |
141 | /* typedef typename super_type::const_reverse_iterator const_reverse_iterator;*/ |
142 | typedef typename super_type::element element; |
143 | typedef typename super_type::size_type size_type; |
144 | // typedef typename super_type::difference_type difference_type; |
145 | typedef typename super_type::index index; |
146 | /* typedef typename super_type::extent_range extent_range;*/ |
147 | |
148 | typedef typename super_type::storage_order_type storage_order_type; |
149 | typedef typename super_type::index_list index_list; |
150 | |
151 | //! indicate that this class is a multi dimensional array |
152 | typedef int yes_is_multi_array; |
153 | |
154 | /* typedef typename super_type::size_list size_list;*/ |
155 | |
156 | template <class ExtentType> |
157 | explicit multi_array_ref_openfpm(T* base, const ExtentType r_sz, const general_storage_order<NumDims>& so) |
158 | :super_type(base,r_sz,so) |
159 | { |
160 | } |
161 | |
162 | // Assignment from other ConstMultiArray types. |
163 | template <typename ConstMultiArray> |
164 | multi_array_ref_openfpm & operator=(const ConstMultiArray& other) |
165 | { |
166 | boost::function_requires< |
167 | boost::multi_array_concepts:: |
168 | ConstMultiArrayConcept<ConstMultiArray,NumDims> >(); |
169 | |
170 | // make sure the dimensions agree |
171 | BOOST_ASSERT(other.num_dimensions() == this->num_dimensions()); |
172 | BOOST_ASSERT(std::equal(other.shape(),other.shape()+this->num_dimensions(), |
173 | this->shape())); |
174 | // iterator-based copy |
175 | std::copy(other.begin(),other.end(),this->begin()); |
176 | return *this; |
177 | } |
178 | |
179 | multi_array_ref_openfpm & operator=(const multi_array_ref_openfpm & other) |
180 | { |
181 | if (&other != this) |
182 | { |
183 | // make sure the dimensions agree |
184 | |
185 | BOOST_ASSERT(other.num_dimensions() == this->num_dimensions()); |
186 | |
187 | // iterator-based copy |
188 | std::copy(other.begin(),other.end(),this->begin()); |
189 | } |
190 | return *this; |
191 | } |
192 | |
193 | multi_array_ref_openfpm & bind_ref(const multi_array_ref_openfpm & other) |
194 | { |
195 | if (&other != this) { |
196 | |
197 | this->base_ = other.base_; |
198 | this->storage_ = other.storage_; |
199 | this->extent_sz = other.extent_sz; |
200 | this->stride_list_ = other.stride_list_; |
201 | this->num_elements_ = other.num_elements_; |
202 | } |
203 | return *this; |
204 | } |
205 | |
206 | /* \brief Set the internal pointer |
207 | * |
208 | * \param base internal pointer |
209 | * |
210 | */ |
211 | void set_pointer(void * base) |
212 | { |
213 | this->base_ = static_cast<T *>(base); |
214 | } |
215 | |
216 | /* \brief Get the internal pointer |
217 | * |
218 | * \return the internal pointer |
219 | * |
220 | */ |
221 | __device__ __host__ void * get_pointer() |
222 | { |
223 | return this->base_; |
224 | } |
225 | |
226 | /* \brief Get the internal pointer |
227 | * |
228 | * \return the internal pointer |
229 | * |
230 | */ |
231 | __device__ __host__ const void * get_pointer() const |
232 | { |
233 | return this->base_; |
234 | } |
235 | |
236 | multi_array_ref_openfpm & operator=(multi_array_ref_openfpm && other) |
237 | { |
238 | swap(other); |
239 | |
240 | return *this; |
241 | } |
242 | |
243 | void swap(multi_array_ref_openfpm & other) |
244 | { |
245 | T* base_tmp = this->base_; |
246 | this->base_ = other.base_; |
247 | other.base_ = base_tmp; |
248 | |
249 | storage_order_type storage_tmp = this->storage_; |
250 | this->storage_ = other.storage_; |
251 | other.storage_ = storage_tmp; |
252 | |
253 | size_type extent_tmp = this->extent_sz; |
254 | this->extent_sz = other.extent_sz; |
255 | other.extent_sz = extent_tmp; |
256 | |
257 | index_list stride_list_tmp = this->stride_list_; |
258 | this->stride_list_ = other.stride_list_; |
259 | other.stride_list_ = stride_list_tmp; |
260 | |
261 | size_type num_elements_tmp = this->num_elements_; |
262 | this->num_elements_ = other.num_elements_; |
263 | other.num_elements_ = num_elements_tmp; |
264 | } |
265 | |
266 | __device__ __host__ element* origin() { return super_type::base_; } |
267 | |
268 | __device__ __host__ const element* origin() const { return super_type::origin(); } |
269 | |
270 | __device__ __host__ reference operator[](index idx) |
271 | { |
272 | return super_type::access(boost::type<reference>(), |
273 | idx, |
274 | this->strides(), |
275 | this->origin()); |
276 | } |
277 | |
278 | |
279 | |
280 | iterator begin() |
281 | {return iterator(0,origin(),this->size(),this->strides());} |
282 | |
283 | iterator end() |
284 | {return iterator(this->size(),origin(),this->size(),this->strides());} |
285 | |
286 | __inline__ __device__ __host__ const_reference operator[](index idx) const |
287 | { |
288 | return super_type::access(boost::type<const_reference>(), |
289 | idx, |
290 | this->strides(), |
291 | this->origin()); |
292 | } |
293 | |
294 | const_iterator begin() const |
295 | {return super_type::begin();} |
296 | |
297 | const_iterator end() const |
298 | {return super_type::end();} |
299 | }; |
300 | |
301 | template<typename T, typename Sfinae = void> |
302 | struct is_multi_array: std::false_type {}; |
303 | |
304 | |
305 | /*! \brief has_noPointers check if a type has defined a |
306 | * method called noPointers |
307 | * |
308 | * ### Example |
309 | * |
310 | * \snippet util_test.hpp Check no pointers |
311 | * |
312 | * return true if T::noPointers() is a valid expression (function pointers) |
313 | * and produce a defined type |
314 | * |
315 | */ |
316 | template<typename T> |
317 | struct is_multi_array<T, typename Void<typename T::yes_is_multi_array >::type> : std::true_type |
318 | {}; |
319 | |
320 | } // namespace openfpm |
321 | |
322 | |
323 | #endif /* MULTI_ARRAY_REF_OPENFPM_HPP_ */ |
324 | |