1 | /* |
2 | * multi_array_view_openfpm.hpp |
3 | * |
4 | * Created on: Jul 1, 2018 |
5 | * Author: i-bird |
6 | */ |
7 | |
8 | #ifndef MULTI_ARRAY_VIEW_OPENFPM_HPP_ |
9 | #define MULTI_ARRAY_VIEW_OPENFPM_HPP_ |
10 | |
11 | //#include "util/boost/boost_multi_array_base_openfpm.hpp" |
12 | #include "boost/utility/enable_if.hpp" |
13 | #include "boost/multi_array/index_gen.hpp" |
14 | |
15 | namespace openfpm { |
16 | namespace detail { |
17 | namespace multi_array { |
18 | |
19 | |
20 | |
21 | // TPtr = const T* defaulted in base.hpp |
22 | template <typename T, std::size_t NumDims, typename vector> |
23 | class const_multi_array_view_openfpm : public openfpm::detail::multi_array::multi_array_impl_base_openfpm<T,NumDims,vector> |
24 | { |
25 | typedef openfpm::detail::multi_array::multi_array_impl_base_openfpm<T,NumDims,vector> super_type; |
26 | public: |
27 | typedef typename super_type::value_type value_type; |
28 | typedef typename super_type::const_reference const_reference; |
29 | typedef typename super_type::const_iterator const_iterator; |
30 | typedef typename super_type::const_reverse_iterator const_reverse_iterator; |
31 | typedef typename super_type::element element; |
32 | typedef typename super_type::size_type size_type; |
33 | typedef typename super_type::difference_type difference_type; |
34 | typedef typename super_type::index index; |
35 | typedef typename super_type::extent_range extent_range; |
36 | typedef T * TPtr; |
37 | |
38 | typedef typename boost::mpl::accumulate<vector, |
39 | typename boost::mpl::int_<1>, |
40 | typename boost::mpl::multiplies<typename boost::mpl::_2,typename boost::mpl::_1> >::type size_ct; |
41 | |
42 | // template typedefs |
43 | template <std::size_t NDims> |
44 | struct const_array_view_openfpm { |
45 | typedef openfpm::detail::multi_array::const_multi_array_view_openfpm<T,NDims,vector> type; |
46 | }; |
47 | |
48 | template <std::size_t NDims> |
49 | struct array_view_openfpm { |
50 | typedef openfpm::detail::multi_array::multi_array_view_openfpm<T,NDims> type; |
51 | }; |
52 | |
53 | template <typename OPtr> |
54 | const_multi_array_view_openfpm(const |
55 | const_multi_array_view_openfpm<T,NumDims,OPtr>& other) : |
56 | base_(other.base_), origin_offset_(other.origin_offset_), |
57 | num_elements_(other.num_elements_), |
58 | stride_list_(other.stride_list_), index_base_list_(other.index_base_list_) |
59 | { } |
60 | |
61 | |
62 | template <class BaseList> |
63 | #ifdef BOOST_NO_SFINAE |
64 | void |
65 | #else |
66 | typename |
67 | boost::disable_if<typename boost::is_integral<BaseList>::type,void >::type |
68 | #endif |
69 | reindex(const BaseList& values) |
70 | { |
71 | boost::function_requires< |
72 | boost::CollectionConcept<BaseList> >(); |
73 | boost::detail::multi_array:: |
74 | copy_n(values.begin(),num_dimensions(),index_base_list_.begin()); |
75 | origin_offset_ = |
76 | this->calculate_indexing_offset(stride_list_,index_base_list_); |
77 | } |
78 | |
79 | void reindex(index value) |
80 | { |
81 | index_base_list_.assign(value); |
82 | origin_offset_ = |
83 | this->calculate_indexing_offset(stride_list_,index_base_list_); |
84 | } |
85 | |
86 | size_type num_dimensions() const { return NumDims; } |
87 | |
88 | size_type size() const { return extent; } |
89 | size_type max_size() const { return num_elements(); } |
90 | bool empty() const { return size() == 0; } |
91 | |
92 | __device__ __host__ const index* strides() const { |
93 | return stride_list_.data(); |
94 | } |
95 | |
96 | __device__ __host__ const T* origin() const { return base_+origin_offset_; } |
97 | |
98 | size_type num_elements() const { return num_elements_; } |
99 | |
100 | __device__ __host__ const index* index_bases() const { |
101 | return index_base_list_.data(); |
102 | } |
103 | |
104 | template <typename IndexList> |
105 | const element& operator()(IndexList indices) const |
106 | { |
107 | boost::function_requires<boost::CollectionConcept<IndexList> >(); |
108 | return super_type::access_element(boost::type<const element&>(), |
109 | indices,origin(),strides(),index_bases()); |
110 | } |
111 | |
112 | // Only allow const element access |
113 | __device__ __host__ const_reference operator[](index idx) const { |
114 | return super_type::access(boost::type<const_reference>(), |
115 | idx,origin(),strides(), |
116 | index_bases()); |
117 | } |
118 | |
119 | // see generate_array_view in base.hpp |
120 | template <int NDims> |
121 | __device__ __host__ typename const_array_view_openfpm<NDims>::type |
122 | operator[](const boost::detail::multi_array::index_gen<NumDims,NDims>& indices) const |
123 | { |
124 | typedef typename const_array_view_openfpm<NDims>::type return_type; |
125 | return |
126 | super_type::generate_array_view(boost::type<return_type>(), |
127 | indices, |
128 | strides(), |
129 | index_bases(), |
130 | origin()); |
131 | } |
132 | |
133 | const_iterator begin() const { |
134 | return const_iterator(*index_bases(),origin(),strides(),index_bases()); |
135 | } |
136 | |
137 | const_reverse_iterator rend() const { |
138 | return const_reverse_iterator(begin()); |
139 | } |
140 | |
141 | template <typename OPtr> |
142 | bool operator!=(const const_multi_array_view_openfpm<T,NumDims,OPtr>& rhs) const |
143 | { |
144 | return !(*this == rhs); |
145 | } |
146 | |
147 | template <typename OPtr> |
148 | bool operator>(const |
149 | const_multi_array_view_openfpm<T,NumDims,OPtr>& rhs) |
150 | const { |
151 | return rhs < *this; |
152 | } |
153 | |
154 | template <typename OPtr> |
155 | bool operator<=(const |
156 | const_multi_array_view_openfpm<T,NumDims,OPtr>& rhs) |
157 | const { |
158 | return !(*this > rhs); |
159 | } |
160 | |
161 | template <typename OPtr> |
162 | bool operator>=(const |
163 | const_multi_array_view_openfpm<T,NumDims,OPtr>& rhs) |
164 | const { |
165 | return !(*this < rhs); |
166 | } |
167 | |
168 | |
169 | #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS |
170 | protected: |
171 | template <typename,std::size_t,typename> friend class multi_array_impl_base_openfpm; |
172 | template <typename,std::size_t,typename> friend class const_multi_array_view_openfpm; |
173 | #else |
174 | public: // should be protected |
175 | #endif |
176 | |
177 | // This constructor is used by multi_array_impl_base::generate_array_view |
178 | // to create strides |
179 | template <typename ExtentType, typename Index> |
180 | explicit const_multi_array_view_openfpm(TPtr base, |
181 | const ExtentType extent, |
182 | const boost::array<Index,NumDims>& strides): |
183 | base_(base), origin_offset_(0) ,extent(extent) |
184 | { |
185 | |
186 | index_base_list_.assign(0); |
187 | |
188 | // Get the extents and strides |
189 | boost::detail::multi_array:: |
190 | copy_n(strides.begin(),NumDims,stride_list_.begin()); |
191 | |
192 | // Calculate the array size |
193 | num_elements_ = extent * size_ct::type::value; |
194 | } |
195 | |
196 | typedef boost::array<index,NumDims> index_list; |
197 | |
198 | TPtr base_; |
199 | index origin_offset_; |
200 | size_type num_elements_; |
201 | size_type extent; |
202 | index_list stride_list_; |
203 | index_list index_base_list_; |
204 | |
205 | private: |
206 | // const_multi_array_view cannot be assigned to (no deep copies!) |
207 | const_multi_array_view_openfpm& operator=(const const_multi_array_view_openfpm& other); |
208 | }; |
209 | |
210 | |
211 | template <typename T, std::size_t NumDims> |
212 | class multi_array_view_openfpm : |
213 | public const_multi_array_view_openfpm<T,NumDims,T*> |
214 | { |
215 | typedef const_multi_array_view_openfpm<T,NumDims,T*> super_type; |
216 | public: |
217 | typedef typename super_type::value_type value_type; |
218 | typedef typename super_type::reference reference; |
219 | typedef typename super_type::iterator iterator; |
220 | typedef typename super_type::reverse_iterator reverse_iterator; |
221 | typedef typename super_type::const_reference const_reference; |
222 | typedef typename super_type::const_iterator const_iterator; |
223 | typedef typename super_type::const_reverse_iterator const_reverse_iterator; |
224 | typedef typename super_type::element element; |
225 | typedef typename super_type::size_type size_type; |
226 | typedef typename super_type::difference_type difference_type; |
227 | typedef typename super_type::index index; |
228 | typedef typename super_type::extent_range extent_range; |
229 | |
230 | // template typedefs |
231 | template <std::size_t NDims> |
232 | struct const_array_view_openfpm |
233 | { |
234 | typedef openfpm::detail::multi_array::const_multi_array_view_openfpm<T,NDims> type; |
235 | }; |
236 | |
237 | template <std::size_t NDims> |
238 | struct array_view_openfpm { |
239 | typedef openfpm::detail::multi_array::multi_array_view_openfpm<T,NDims> type; |
240 | }; |
241 | |
242 | // Assignment from other ConstMultiArray types. |
243 | template <typename ConstMultiArray> |
244 | multi_array_view_openfpm& operator=(const ConstMultiArray& other) { |
245 | boost::function_requires< |
246 | boost::multi_array_concepts:: |
247 | ConstMultiArrayConcept<ConstMultiArray,NumDims> >(); |
248 | |
249 | // make sure the dimensions agree |
250 | BOOST_ASSERT(other.num_dimensions() == this->num_dimensions()); |
251 | BOOST_ASSERT(std::equal(other.shape(),other.shape()+this->num_dimensions(), |
252 | this->shape())); |
253 | // iterator-based copy |
254 | std::copy(other.begin(),other.end(),begin()); |
255 | return *this; |
256 | } |
257 | |
258 | |
259 | multi_array_view_openfpm& operator=(const multi_array_view_openfpm& other) { |
260 | if (&other != this) { |
261 | // make sure the dimensions agree |
262 | BOOST_ASSERT(other.num_dimensions() == this->num_dimensions()); |
263 | BOOST_ASSERT(std::equal(other.shape(), |
264 | other.shape()+this->num_dimensions(), |
265 | this->shape())); |
266 | // iterator-based copy |
267 | std::copy(other.begin(),other.end(),begin()); |
268 | } |
269 | return *this; |
270 | } |
271 | |
272 | element* origin() { return this->base_+this->origin_offset_; } |
273 | |
274 | template <class IndexList> |
275 | element& operator()(const IndexList& indices) { |
276 | boost::function_requires< |
277 | boost::CollectionConcept<IndexList> >(); |
278 | return super_type::access_element(boost::type<element&>(), |
279 | indices,origin(), |
280 | this->shape(),this->strides(), |
281 | this->index_bases()); |
282 | } |
283 | |
284 | |
285 | reference operator[](index idx) { |
286 | return super_type::access(boost::type<reference>(), |
287 | idx,origin(), |
288 | this->shape(),this->strides(), |
289 | this->index_bases()); |
290 | } |
291 | |
292 | |
293 | // see generate_array_view in base.hpp |
294 | /* template <int NDims> |
295 | typename array_view_openfpm<NDims>::type |
296 | operator[](const boost::detail::multi_array:: |
297 | index_gen<NumDims,NDims>& indices) { |
298 | typedef typename array_view_openfpm<NDims>::type return_type; |
299 | return |
300 | super_type::generate_array_view(boost::type<return_type>(), |
301 | indices, |
302 | this->shape(), |
303 | this->strides(), |
304 | this->index_bases(), |
305 | origin()); |
306 | }*/ |
307 | |
308 | |
309 | iterator begin() { |
310 | return iterator(*this->index_bases(),origin(), |
311 | this->shape(),this->strides(), |
312 | this->index_bases()); |
313 | } |
314 | |
315 | iterator end() { |
316 | return iterator(*this->index_bases()+(index)*this->shape(),origin(), |
317 | this->shape(),this->strides(), |
318 | this->index_bases()); |
319 | } |
320 | |
321 | reverse_iterator rbegin() { |
322 | return reverse_iterator(end()); |
323 | } |
324 | |
325 | reverse_iterator rend() { |
326 | return reverse_iterator(begin()); |
327 | } |
328 | |
329 | // Using declarations don't seem to work for g++ |
330 | // These are the proxies to work around this. |
331 | |
332 | const element* origin() const { return super_type::origin(); } |
333 | |
334 | template <class IndexList> |
335 | const element& operator()(const IndexList& indices) const { |
336 | boost::function_requires< |
337 | boost::CollectionConcept<IndexList> >(); |
338 | return super_type::operator()(indices); |
339 | } |
340 | |
341 | const_reference operator[](index idx) const { |
342 | return super_type::operator[](idx); |
343 | } |
344 | |
345 | // see generate_array_view in base.hpp |
346 | /* template <int NDims> |
347 | typename const_array_view_openfpm<NDims>::type |
348 | operator[](const boost::detail::multi_array:: |
349 | index_gen<NumDims,NDims>& indices) |
350 | const { |
351 | return super_type::operator[](indices); |
352 | }*/ |
353 | |
354 | const_iterator begin() const { |
355 | return super_type::begin(); |
356 | } |
357 | |
358 | const_iterator end() const { |
359 | return super_type::end(); |
360 | } |
361 | |
362 | const_reverse_iterator rbegin() const { |
363 | return super_type::rbegin(); |
364 | } |
365 | |
366 | const_reverse_iterator rend() const { |
367 | return super_type::rend(); |
368 | } |
369 | |
370 | #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS |
371 | private: |
372 | template <typename,std::size_t> friend class multi_array_impl_base; |
373 | #else |
374 | public: // should be private |
375 | #endif |
376 | |
377 | // constructor used by multi_array_impl_base::generate_array_view to |
378 | // generate array views |
379 | template <typename ExtentList, typename Index> |
380 | explicit multi_array_view_openfpm(T* base, |
381 | const ExtentList& extents, |
382 | const openfpm::array<Index,NumDims>& strides) : |
383 | super_type(base,extents,strides) { } |
384 | |
385 | }; |
386 | |
387 | } // namespace multi_array |
388 | } // namespace detail |
389 | |
390 | // |
391 | // traits classes to get array_view types |
392 | // |
393 | template <typename Array, int N> |
394 | class array_view_gen_openfpm { |
395 | typedef typename Array::element element; |
396 | public: |
397 | typedef openfpm::detail::multi_array::multi_array_view_openfpm<element,N> type; |
398 | }; |
399 | |
400 | template <typename Array, int N> |
401 | class const_array_view_gen_openfpm { |
402 | typedef typename Array::element element; |
403 | public: |
404 | typedef openfpm::detail::multi_array::const_multi_array_view_openfpm<element,N> type; |
405 | }; |
406 | |
407 | } // namespace boost |
408 | |
409 | |
410 | |
411 | #endif /* MULTI_ARRAY_VIEW_OPENFPM_HPP_ */ |
412 | |