| 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 | |