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
27namespace openfpm {
28
29
30
31template <typename T, std::size_t NumDims, typename vector, typename TPtr>
32class 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
40public:
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
113private:
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
130template <typename T, int NumDims, typename vector>
131class 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;
134public:
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
301template<typename T, typename Sfinae = void>
302struct 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 */
316template<typename T>
317struct 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