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