OpenFPM  5.2.0
Project that contain the implementation of distributed structures
multi_array_ref_base_openfpm.hpp
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/mpl/for_each.hpp>
19 #include <boost/mpl/range_c.hpp>
20 #include <boost/type.hpp>
21 
22 namespace openfpm
23 {
24 
26 // class declarations
28 
29 //template<typename T, std::size_t NumDims, typename Allocator = std::allocator<T> >
30 //class multi_array_openfpm;
31 
32 template <typename T, int NumDims, typename vector, typename StorageOrder=typename ofp_storage_order<NumDims>::value>
33 class multi_array_ref_openfpm;
34 
35 // This is a public interface for use by end users!
36 namespace multi_array_types
37 {
38  typedef openfpm::detail::multi_array::size_type size_type;
39  typedef std::ptrdiff_t difference_type;
40  typedef openfpm::detail::multi_array::index index;
41 }
42 
43 
44 namespace detail {
45 namespace multi_array {
46 
47 template <typename T, std::size_t NumDims, typename vector>
48 class sub_array_openfpm;
49 
50 template <typename T, std::size_t NumDims, typename vector, typename TPtr = const T*>
51 class const_sub_array_openfpm;
52 
53  template <typename T, typename TPtr, typename NumDims, typename vector, typename Reference,
54  typename IteratorCategory>
55 class array_iterator_openfpm;
56 
57 template <typename T, std::size_t NumDims, typename TPtr = const T*>
58 class const_multi_array_view_openfpm;
59 
60 template <typename T, std::size_t NumDims>
61 class multi_array_view_openfpm;
62 
63 
65 // class interfaces
67 
69 {
70 public:
71  typedef multi_array_types::size_type size_type;
72  typedef multi_array_types::difference_type difference_type;
73  typedef multi_array_types::index index;
74 };
75 
76 //
77 // value_accessor_n
78 // contains the routines for accessing elements from
79 // N-dimensional views.
80 //
81 template<typename T, std::size_t NumDims, typename vector>
83 {
85 public:
86  typedef typename super_type::index index;
87 
88  //
89  // public typedefs used by classes that inherit from this base
90  //
91  typedef T element;
92  typedef openfpm::multi_array_ref_openfpm<T,NumDims-1,typename boost::mpl::pop_front<vector>::type> value_type;
93  typedef sub_array_openfpm<T,NumDims-1,typename boost::mpl::pop_front<vector>::type> reference;
94  typedef const_sub_array_openfpm<T,NumDims-1,typename boost::mpl::pop_front<vector>::type> const_reference;
95 
96 protected:
97 
98  // used by array operator[] and iterators to get reference types.
99  template <typename Reference, typename TPtr>
100  __device__ __host__ inline Reference access(boost::type<Reference>,
101  index idx,
102  const index* strides,
103  TPtr base) const
104  {
105  TPtr newbase = base + idx * strides[0];
106  return Reference(newbase,strides+1);
107  }
108 
109  __device__ __host__ value_accessor_n_openfpm() { }
110  __device__ __host__ ~value_accessor_n_openfpm() { }
111 };
112 
113 template <class T> inline __device__ __host__ void ignore_unused_variable_warning_ofp(T const&) {}
114 
115 //
116 // value_accessor_one
117 // contains the routines for accessing reference elements from
118 // 1-dimensional views.
119 //
120 template<typename T, typename vector>
122 {
124 public:
125  typedef typename super_type::index index;
126  //
127  // public typedefs for use by classes that inherit it.
128  //
129  typedef T element;
130  typedef T value_type;
131  typedef T& reference;
132  typedef T const& const_reference;
133 
134 protected:
135 
136  // used by array operator[] and iterators to get reference types.
137  template <typename Reference, typename TPtr>
138  inline __device__ __host__ Reference access(boost::type<Reference>,index idx,
139  const index* strides,
140  TPtr base) const
141  {
142  return *(base + idx * strides[0]);
143  }
144 
145  // used by array operator[] and iterators to get reference types.
146  template <typename Reference, typename TPtr>
147  inline __device__ __host__ Reference access(boost::type<Reference>,index idx,TPtr base, const index* strides) const
148  {
149  BOOST_ASSERT(size_type(idx < boost::mpl::at<vector,boost::mpl::int_<0>>::type::value));
150  return *(base + idx * strides[0]);
151  }
152 
153  __device__ __host__ value_accessor_one_openfpm() { }
154  __device__ __host__ ~value_accessor_one_openfpm() { }
155 };
156 
157 
159 // choose value accessor begins
160 //
161 
162 template <typename T, std::size_t NumDims,typename vector>
164 {
166 };
167 
168 template <typename T,typename vector>
170 {
172 };
173 
174 template <typename T, typename NumDims, typename vector>
176 {
177  BOOST_STATIC_CONSTANT(std::size_t, dimensionality = NumDims::value);
178 
179  typedef typename
180  boost::mpl::eval_if_c<(dimensionality == 1),
183  >::type type;
184 };
185 
186 
187 template <class T, class NumDims, typename vector>
189 {};
190 
191 //
192 // choose value accessor ends
194 
195 // Due to some imprecision in the C++ Standard,
196 // MSVC 2010 is broken in debug mode: it requires
197 // that an Output Iterator have output_iterator_tag in its iterator_category if
198 // that iterator is not bidirectional_iterator or random_access_iterator.
199 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600)
200 struct mutable_iterator_tag
201  : boost::random_access_traversal_tag, std::input_iterator_tag
202 {
203  operator std::output_iterator_tag() const {
204  return std::output_iterator_tag();
205  }
206 };
207 #endif
208 
209 
211 // multi_array_base
213 template <typename T, std::size_t NumDims, typename vector>
214 class multi_array_impl_base_openfpm: public value_accessor_generator_openfpm<T,boost::mpl::size_t<NumDims>,vector>::type
215 {
217 public:
218 
219  typedef typename types::index index;
220  typedef typename types::size_type size_type;
221  typedef typename types::element element;
222  typedef typename types::value_type value_type;
223  typedef typename types::reference reference;
224  typedef typename types::const_reference const_reference;
225 
226  template <std::size_t NDims>
227  struct subarray
228  {
230  };
231 
232  template <std::size_t NDims>
234  {
236  };
237 
238  template <std::size_t NDims>
240  {
242  };
243 
244  template <std::size_t NDims>
246  {
247  public:
249  };
250 
251 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600)
252  // Deal with VC 2010 output_iterator_tag requirement
254  mutable_iterator_tag> iterator;
255 #else
257  boost::random_access_traversal_tag> iterator;
258 #endif
260  boost::random_access_traversal_tag> const_iterator;
261 
262  typedef ::boost::reverse_iterator<iterator> reverse_iterator;
263  typedef ::boost::reverse_iterator<const_iterator> const_reverse_iterator;
264 
265  BOOST_STATIC_CONSTANT(std::size_t, dimensionality = NumDims);
266 
267 protected:
268 
269  __device__ __host__ multi_array_impl_base_openfpm() { }
270  __device__ __host__ ~multi_array_impl_base_openfpm() { }
271 
272  template <typename StorageOrder, typename Stride_list, typename Extent_type>
273  void compute_strides(Stride_list& stride_list, Extent_type& extent)
274  {
275  // invariant: stride = the stride for dimension n
276  index stride = 1;
277 
278  boost::mpl::for_each<boost::mpl::range_c<int,0,NumDims>>([&](auto i) {
279  constexpr int ordering = boost::mpl::at<StorageOrder,boost::mpl::int_<i> >::type::value;
280  constexpr int extent_i = boost::mpl::int_<boost::mpl::at<vector,boost::mpl::int_<ordering>>::type::value>::value;
281 
282  // The stride for this dimension is the product of the
283  // lengths of the ranks minor to it.
284  stride_list[ordering] = stride;
285 
286  if (ordering == 0)
287  stride *= extent;
288  else
289  stride *= extent_i;
290  });
291  }
292 
293  // Used by operator() in our array classes
294  template <typename Reference, typename IndexList, typename TPtr>
295  Reference access_element(boost::type<Reference>,
296  const IndexList& indices,
297  TPtr base,
298  const size_type* extents,
299  const index* strides,
300  const index* index_bases) const
301  {
302  boost::function_requires<
303  boost::CollectionConcept<IndexList> >();
304  ignore_unused_variable_warning(index_bases);
305  ignore_unused_variable_warning(extents);
306 #ifdef SE_CLASS1
307  for (size_type i = 0; i != NumDims; ++i)
308  {
309  BOOST_ASSERT(indices[i] - index_bases[i] >= 0);
310  BOOST_ASSERT(size_type(indices[i] - index_bases[i]) < extents[i]);
311  }
312 #endif
313 
314  index offset = 0;
315  {
316  typename IndexList::const_iterator i = indices.begin();
317  size_type n = 0;
318  while (n != NumDims)
319  {
320  offset += (*i) * strides[n];
321  ++n;
322  ++i;
323  }
324  }
325  return base[offset];
326  }
327 };
328 
329 } // namespace multi_array
330 } // namespace detail
331 
332 } // namespace openfpm
333 
334 
335 #endif /* MULTI_ARRAY_REF_OPENFPM_BASE_HPP_ */
This class is a trick to indicate the compiler a specific specialization pattern.
Definition: memory_c.hpp:231
Implementation of 1-D std::vector like structure.
Definition: map_vector.hpp:204
convert a type into constant type
Definition: aggregate.hpp:302