1 | /* |
2 | * multi_array_ref_openfpm_base.hpp |
3 | * |
4 | * Created on: Jun 30, 2018 |
5 | * Author: i-bird |
6 | */ |
7 | |
8 | #ifndef MULTI_ARRAY_REF_OPENFPM_BASE_HPP_ |
9 | #define MULTI_ARRAY_REF_OPENFPM_BASE_HPP_ |
10 | |
11 | #include "types.hpp" |
12 | #include <boost/mpl/size_t.hpp> |
13 | #include "boost/iterator/reverse_iterator.hpp" |
14 | #include "storage_order.hpp" |
15 | #include <boost/mpl/at.hpp> |
16 | #include <boost/mpl/size.hpp> |
17 | #include <boost/mpl/pop_front.hpp> |
18 | #include <boost/type.hpp> |
19 | |
20 | namespace openfpm |
21 | { |
22 | |
23 | ///////////////////////////////////////////////////////////////////////// |
24 | // class declarations |
25 | ///////////////////////////////////////////////////////////////////////// |
26 | |
27 | //template<typename T, std::size_t NumDims, typename Allocator = std::allocator<T> > |
28 | //class multi_array_openfpm; |
29 | |
30 | template <typename T, int NumDims, typename vector> |
31 | class multi_array_ref_openfpm; |
32 | |
33 | // This is a public interface for use by end users! |
34 | namespace multi_array_types |
35 | { |
36 | typedef openfpm::detail::multi_array::size_type size_type; |
37 | typedef std::ptrdiff_t difference_type; |
38 | typedef openfpm::detail::multi_array::index index; |
39 | } |
40 | |
41 | |
42 | namespace detail { |
43 | namespace multi_array { |
44 | |
45 | template <typename T, std::size_t NumDims, typename vector> |
46 | class sub_array_openfpm; |
47 | |
48 | template <typename T, std::size_t NumDims, typename vector, typename TPtr = const T*> |
49 | class const_sub_array_openfpm; |
50 | |
51 | template <typename T, typename TPtr, typename NumDims, typename vector, typename Reference, |
52 | typename IteratorCategory> |
53 | class array_iterator_openfpm; |
54 | |
55 | template <typename T, std::size_t NumDims, typename TPtr = const T*> |
56 | class const_multi_array_view_openfpm; |
57 | |
58 | template <typename T, std::size_t NumDims> |
59 | class multi_array_view_openfpm; |
60 | |
61 | |
62 | ///////////////////////////////////////////////////////////////////////// |
63 | // class interfaces |
64 | ///////////////////////////////////////////////////////////////////////// |
65 | |
66 | class multi_array_base_openfpm |
67 | { |
68 | public: |
69 | typedef multi_array_types::size_type size_type; |
70 | typedef multi_array_types::difference_type difference_type; |
71 | typedef multi_array_types::index index; |
72 | }; |
73 | |
74 | // |
75 | // value_accessor_n |
76 | // contains the routines for accessing elements from |
77 | // N-dimensional views. |
78 | // |
79 | template<typename T, std::size_t NumDims, typename vector> |
80 | class value_accessor_n_openfpm : public multi_array_base_openfpm |
81 | { |
82 | typedef multi_array_base_openfpm super_type; |
83 | public: |
84 | typedef typename super_type::index index; |
85 | |
86 | // |
87 | // public typedefs used by classes that inherit from this base |
88 | // |
89 | typedef T element; |
90 | typedef openfpm::multi_array_ref_openfpm<T,NumDims-1,typename boost::mpl::pop_front<vector>::type> value_type; |
91 | typedef sub_array_openfpm<T,NumDims-1,typename boost::mpl::pop_front<vector>::type> reference; |
92 | typedef const_sub_array_openfpm<T,NumDims-1,typename boost::mpl::pop_front<vector>::type> const_reference; |
93 | |
94 | protected: |
95 | |
96 | // used by array operator[] and iterators to get reference types. |
97 | template <typename Reference, typename TPtr> |
98 | __device__ __host__ inline Reference access(boost::type<Reference>, |
99 | index idx, |
100 | const index* strides, |
101 | TPtr base) const |
102 | { |
103 | TPtr newbase = base + idx * strides[0]; |
104 | return Reference(newbase,strides+1); |
105 | } |
106 | |
107 | __device__ __host__ value_accessor_n_openfpm() { } |
108 | __device__ __host__ ~value_accessor_n_openfpm() { } |
109 | }; |
110 | |
111 | template <class T> inline __device__ __host__ void ignore_unused_variable_warning_ofp(T const&) {} |
112 | |
113 | // |
114 | // value_accessor_one |
115 | // contains the routines for accessing reference elements from |
116 | // 1-dimensional views. |
117 | // |
118 | template<typename T, typename vector> |
119 | class value_accessor_one_openfpm : public multi_array_base_openfpm |
120 | { |
121 | typedef multi_array_base_openfpm super_type; |
122 | public: |
123 | typedef typename super_type::index index; |
124 | // |
125 | // public typedefs for use by classes that inherit it. |
126 | // |
127 | typedef T element; |
128 | typedef T value_type; |
129 | typedef T& reference; |
130 | typedef T const& const_reference; |
131 | |
132 | protected: |
133 | |
134 | // used by array operator[] and iterators to get reference types. |
135 | template <typename Reference, typename TPtr> |
136 | inline __device__ __host__ Reference access(boost::type<Reference>,index idx, |
137 | const index* strides, |
138 | TPtr base) const |
139 | { |
140 | return *(base + idx * strides[0]); |
141 | } |
142 | |
143 | // used by array operator[] and iterators to get reference types. |
144 | template <typename Reference, typename TPtr> |
145 | inline __device__ __host__ Reference access(boost::type<Reference>,index idx,TPtr base, const index* strides) const |
146 | { |
147 | BOOST_ASSERT(size_type(idx < boost::mpl::at<vector,boost::mpl::int_<0>>::type::value)); |
148 | return *(base + idx * strides[0]); |
149 | } |
150 | |
151 | __device__ __host__ value_accessor_one_openfpm() { } |
152 | __device__ __host__ ~value_accessor_one_openfpm() { } |
153 | }; |
154 | |
155 | |
156 | ///////////////////////////////////////////////////////////////////////// |
157 | // choose value accessor begins |
158 | // |
159 | |
160 | template <typename T, std::size_t NumDims,typename vector> |
161 | struct choose_value_accessor_n_openfpm |
162 | { |
163 | typedef value_accessor_n_openfpm<T,NumDims,vector> type; |
164 | }; |
165 | |
166 | template <typename T,typename vector> |
167 | struct choose_value_accessor_one_openfpm |
168 | { |
169 | typedef value_accessor_one_openfpm<T,vector> type; |
170 | }; |
171 | |
172 | template <typename T, typename NumDims, typename vector> |
173 | struct value_accessor_generator_openfpm |
174 | { |
175 | BOOST_STATIC_CONSTANT(std::size_t, dimensionality = NumDims::value); |
176 | |
177 | typedef typename |
178 | boost::mpl::eval_if_c<(dimensionality == 1), |
179 | choose_value_accessor_one_openfpm<T,vector>, |
180 | choose_value_accessor_n_openfpm<T,dimensionality,vector> |
181 | >::type type; |
182 | }; |
183 | |
184 | |
185 | template <class T, class NumDims, typename vector> |
186 | struct associated_types_openfpm: value_accessor_generator_openfpm<T,NumDims,vector>::type |
187 | {}; |
188 | |
189 | // |
190 | // choose value accessor ends |
191 | ///////////////////////////////////////////////////////////////////////// |
192 | |
193 | // Due to some imprecision in the C++ Standard, |
194 | // MSVC 2010 is broken in debug mode: it requires |
195 | // that an Output Iterator have output_iterator_tag in its iterator_category if |
196 | // that iterator is not bidirectional_iterator or random_access_iterator. |
197 | #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600) |
198 | struct mutable_iterator_tag |
199 | : boost::random_access_traversal_tag, std::input_iterator_tag |
200 | { |
201 | operator std::output_iterator_tag() const { |
202 | return std::output_iterator_tag(); |
203 | } |
204 | }; |
205 | #endif |
206 | |
207 | |
208 | //////////////////////////////////////////////////////////////////////// |
209 | // multi_array_base |
210 | //////////////////////////////////////////////////////////////////////// |
211 | template <typename T, std::size_t NumDims, typename vector> |
212 | class multi_array_impl_base_openfpm: public value_accessor_generator_openfpm<T,boost::mpl::size_t<NumDims>,vector>::type |
213 | { |
214 | typedef associated_types_openfpm<T,boost::mpl::size_t<NumDims>,vector > types; |
215 | public: |
216 | |
217 | typedef typename types::index index; |
218 | typedef typename types::size_type size_type; |
219 | typedef typename types::element element; |
220 | typedef typename types::value_type value_type; |
221 | typedef typename types::reference reference; |
222 | typedef typename types::const_reference const_reference; |
223 | |
224 | template <std::size_t NDims> |
225 | struct subarray |
226 | { |
227 | typedef openfpm::detail::multi_array::sub_array_openfpm<T,NDims,vector> type; |
228 | }; |
229 | |
230 | template <std::size_t NDims> |
231 | struct const_subarray |
232 | { |
233 | typedef openfpm::detail::multi_array::const_sub_array_openfpm<T,NDims,vector> type; |
234 | }; |
235 | |
236 | template <std::size_t NDims> |
237 | struct array_view_openfpm |
238 | { |
239 | typedef openfpm::detail::multi_array::multi_array_view_openfpm<T,NDims> type; |
240 | }; |
241 | |
242 | template <std::size_t NDims> |
243 | struct const_array_view_openfpm |
244 | { |
245 | public: |
246 | typedef openfpm::detail::multi_array::const_multi_array_view_openfpm<T,NDims> type; |
247 | }; |
248 | |
249 | #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600) |
250 | // Deal with VC 2010 output_iterator_tag requirement |
251 | typedef array_iterator_openfpm<T,T*,mpl::size_t<NumDims>,vector,reference, |
252 | mutable_iterator_tag> iterator; |
253 | #else |
254 | typedef array_iterator_openfpm<T,T*,boost::mpl::size_t<NumDims>, vector,reference, |
255 | boost::random_access_traversal_tag> iterator; |
256 | #endif |
257 | typedef array_iterator_openfpm<T,T const*,boost::mpl::size_t<NumDims>,vector,const_reference, |
258 | boost::random_access_traversal_tag> const_iterator; |
259 | |
260 | typedef ::boost::reverse_iterator<iterator> reverse_iterator; |
261 | typedef ::boost::reverse_iterator<const_iterator> const_reverse_iterator; |
262 | |
263 | BOOST_STATIC_CONSTANT(std::size_t, dimensionality = NumDims); |
264 | |
265 | protected: |
266 | |
267 | __device__ __host__ multi_array_impl_base_openfpm() { } |
268 | __device__ __host__ ~multi_array_impl_base_openfpm() { } |
269 | |
270 | |
271 | template <typename Stride_list, typename Extent_type> |
272 | void compute_strides(Stride_list& stride_list, Extent_type& extent, |
273 | const general_storage_order<NumDims>& storage) |
274 | { |
275 | // invariant: stride = the stride for dimension n |
276 | index stride = 1; |
277 | for (size_type n = 0; n != NumDims; ++n) |
278 | { |
279 | // The stride for this dimension is the product of the |
280 | // lengths of the ranks minor to it. |
281 | stride_list[storage.ordering(n)] = stride; |
282 | |
283 | if (storage.ordering(n) == 0) |
284 | {stride *= extent;} |
285 | else |
286 | { |
287 | switch(storage.ordering(n)) |
288 | { |
289 | case 1: |
290 | stride *= at_impl<vector,1>::type::value; |
291 | break; |
292 | case 2: |
293 | stride *= at_impl<vector,2>::type::value; |
294 | break; |
295 | case 3: |
296 | stride *= at_impl<vector,3>::type::value; |
297 | break; |
298 | case 4: |
299 | stride *= at_impl<vector,4>::type::value; |
300 | break; |
301 | case 5: |
302 | stride *= at_impl<vector,5>::type::value; |
303 | break; |
304 | case 6: |
305 | stride *= at_impl<vector,6>::type::value; |
306 | break; |
307 | case 7: |
308 | stride *= at_impl<vector,7>::type::value; |
309 | break; |
310 | case 8: |
311 | stride *= at_impl<vector,8>::type::value; |
312 | break; |
313 | case 9: |
314 | stride *= at_impl<vector,9>::type::value; |
315 | break; |
316 | case 10: |
317 | stride *= at_impl<vector,10>::type::value; |
318 | break; |
319 | case 11: |
320 | stride *= at_impl<vector,11>::type::value; |
321 | break; |
322 | case 12: |
323 | stride *= at_impl<vector,12>::type::value; |
324 | break; |
325 | case 13: |
326 | stride *= at_impl<vector,13>::type::value; |
327 | break; |
328 | case 14: |
329 | stride *= at_impl<vector,14>::type::value; |
330 | break; |
331 | case 15: |
332 | stride *= at_impl<vector,15>::type::value; |
333 | break; |
334 | } |
335 | } |
336 | } |
337 | } |
338 | |
339 | // Used by operator() in our array classes |
340 | template <typename Reference, typename IndexList, typename TPtr> |
341 | Reference access_element(boost::type<Reference>, |
342 | const IndexList& indices, |
343 | TPtr base, |
344 | const size_type* extents, |
345 | const index* strides, |
346 | const index* index_bases) const |
347 | { |
348 | boost::function_requires< |
349 | boost::CollectionConcept<IndexList> >(); |
350 | ignore_unused_variable_warning(index_bases); |
351 | ignore_unused_variable_warning(extents); |
352 | #ifdef SE_CLASS1 |
353 | for (size_type i = 0; i != NumDims; ++i) |
354 | { |
355 | BOOST_ASSERT(indices[i] - index_bases[i] >= 0); |
356 | BOOST_ASSERT(size_type(indices[i] - index_bases[i]) < extents[i]); |
357 | } |
358 | #endif |
359 | |
360 | index offset = 0; |
361 | { |
362 | typename IndexList::const_iterator i = indices.begin(); |
363 | size_type n = 0; |
364 | while (n != NumDims) |
365 | { |
366 | offset += (*i) * strides[n]; |
367 | ++n; |
368 | ++i; |
369 | } |
370 | } |
371 | return base[offset]; |
372 | } |
373 | }; |
374 | |
375 | } // namespace multi_array |
376 | } // namespace detail |
377 | |
378 | } // namespace openfpm |
379 | |
380 | |
381 | #endif /* MULTI_ARRAY_REF_OPENFPM_BASE_HPP_ */ |
382 | |