OpenFPM_pdata  4.1.0
Project that contain the implementation of distributed structures
array_openfpm.hpp
1 /*
2  * array_openfpm.hpp
3  *
4  * Created on: Jun 30, 2018
5  * Author: i-bird
6  */
7 
8 #ifndef ARRAY_OPENFPM_HPP_
9 #define ARRAY_OPENFPM_HPP_
10 
11 #include <boost/detail/workaround.hpp>
12 
13 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
14 # pragma warning(push)
15 # pragma warning(disable:4996) // 'std::equal': Function call with parameters that may be unsafe
16 # pragma warning(disable:4510) // boost::array<T,N>' : default constructor could not be generated
17 # pragma warning(disable:4610) // warning C4610: class 'boost::array<T,N>' can never be instantiated - user defined constructor required
18 #endif
19 
20 #include <cstddef>
21 #include <stdexcept>
22 #include <boost/assert.hpp>
23 #include <boost/static_assert.hpp>
24 #include <boost/swap.hpp>
25 
26 // Handles broken standard libraries better than <iterator>
27 #include <boost/throw_exception.hpp>
28 #include <algorithm>
29 
30 // FIXES for broken compilers
31 #include <boost/config.hpp>
32 
33 
34 namespace openfpm
35 {
36  template<class T, std::size_t N, typename ids_type = std::size_t>
37  class array
38  {
39  public:
40  T elems[N]; // fixed-size array of elements of type T
41 
42  public:
43  // type definitions
44  typedef T value_type;
45  typedef T* iterator;
46  typedef const T* const_iterator;
47  typedef T& reference;
48  typedef const T& const_reference;
49  typedef ids_type size_type;
50  typedef std::ptrdiff_t difference_type;
51 
52  // iterator support
53  iterator begin() { return elems; }
54  const_iterator begin() const { return elems; }
55  const_iterator cbegin() const { return elems; }
56 
57  iterator end() { return elems+N; }
58  const_iterator end() const { return elems+N; }
59  const_iterator cend() const { return elems+N; }
60 
61  // reverse iterator support
62 #if !defined(BOOST_MSVC_STD_ITERATOR) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
63  typedef std::reverse_iterator<iterator> reverse_iterator;
64  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
65 #elif defined(_RWSTD_NO_CLASS_PARTIAL_SPEC)
66  typedef std::reverse_iterator<iterator, std::random_access_iterator_tag,
67  value_type, reference, iterator, difference_type> reverse_iterator;
68  typedef std::reverse_iterator<const_iterator, std::random_access_iterator_tag,
69  value_type, const_reference, const_iterator, difference_type> const_reverse_iterator;
70 #else
71  // workaround for broken reverse_iterator implementations
72  typedef std::reverse_iterator<iterator,T> reverse_iterator;
73  typedef std::reverse_iterator<const_iterator,T> const_reverse_iterator;
74 #endif
75 
76  reverse_iterator rbegin() { return reverse_iterator(end()); }
77  const_reverse_iterator rbegin() const {return const_reverse_iterator(end());}
78  const_reverse_iterator crbegin() const {return const_reverse_iterator(end());}
79 
80  reverse_iterator rend() { return reverse_iterator(begin()); }
81  const_reverse_iterator rend() const {return const_reverse_iterator(begin());}
82  const_reverse_iterator crend() const {return const_reverse_iterator(begin());}
83 
84  // operator[]
85  __device__ __host__ reference operator[](size_type i)
86  {
87  return BOOST_ASSERT_MSG( i < N, "out of range" ), elems[i];
88  }
89 
90  __device__ __host__ const_reference operator[](size_type i) const
91  {
92  return BOOST_ASSERT_MSG( i < N, "out of range" ), elems[i];
93  }
94 
95  // at() with range check
96  reference at(size_type i) { return rangecheck(i), elems[i]; }
97  /*BOOST_CONSTEXPR*/ const_reference at(size_type i) const { return rangecheck(i), elems[i]; }
98 
99  // front() and back()
100  reference front()
101  {
102  return elems[0];
103  }
104 
105  BOOST_CONSTEXPR const_reference front() const
106  {
107  return elems[0];
108  }
109 
110  reference back()
111  {
112  return elems[N-1];
113  }
114 
115  BOOST_CONSTEXPR const_reference back() const
116  {
117  return elems[N-1];
118  }
119 
120  // size is constant
121  static BOOST_CONSTEXPR size_type size() { return N; }
122  static BOOST_CONSTEXPR bool empty() { return false; }
123  static BOOST_CONSTEXPR size_type max_size() { return N; }
124  enum { static_size = N };
125 
126  // swap (note: linear complexity)
127  void swap (array<T,N,ids_type>& y)
128  {
129  for (size_type i = 0; i < N; ++i)
130  {boost::swap(elems[i],y.elems[i]);}
131  }
132 
133  // direct access to data (read-only)
134  inline __device__ __host__ const T* data() const { return elems; }
135  inline __device__ __host__ T* data() { return elems; }
136 
137  // use array as C array (direct read/write access to data)
138  T* c_array() { return elems; }
139 
140  // assignment with type conversion
141  template <typename T2>
142  array<T,N>& operator= (const array<T2,N>& rhs)
143  {
144  std::copy(rhs.begin(),rhs.end(), begin());
145  return *this;
146  }
147 
148  // assign one value to all elements
149  void assign (const T& value) { fill ( value ); } // A synonym for fill
150  void fill (const T& value)
151  {
152  std::fill_n(begin(),size(),value);
153  }
154 
155  // check range (may be private because it is static)
156  static BOOST_CONSTEXPR bool rangecheck (size_type i)
157  {return i > size() ? boost::throw_exception(std::out_of_range ("array<>: index out of range")), true : true;}
158  };
159 
160  template< class T >
161  class array< T, 0 >
162  {
163 
164  public:
165  // type definitions
166  typedef T value_type;
167  typedef T* iterator;
168  typedef const T* const_iterator;
169  typedef T& reference;
170  typedef const T& const_reference;
171  typedef std::size_t size_type;
172  typedef std::ptrdiff_t difference_type;
173 
174  // iterator support
175  iterator begin() { return iterator( reinterpret_cast< T * >( this ) ); }
176  const_iterator begin() const { return const_iterator( reinterpret_cast< const T * >( this ) ); }
177  const_iterator cbegin() const { return const_iterator( reinterpret_cast< const T * >( this ) ); }
178 
179  iterator end() { return begin(); }
180  const_iterator end() const { return begin(); }
181  const_iterator cend() const { return cbegin(); }
182 
183  // reverse iterator support
184 #if !defined(BOOST_MSVC_STD_ITERATOR) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
185  typedef std::reverse_iterator<iterator> reverse_iterator;
186  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
187 #elif defined(_RWSTD_NO_CLASS_PARTIAL_SPEC)
188  typedef std::reverse_iterator<iterator, std::random_access_iterator_tag,
189  value_type, reference, iterator, difference_type> reverse_iterator;
190  typedef std::reverse_iterator<const_iterator, std::random_access_iterator_tag,
191  value_type, const_reference, const_iterator, difference_type> const_reverse_iterator;
192 #else
193  // workaround for broken reverse_iterator implementations
194  typedef std::reverse_iterator<iterator,T> reverse_iterator;
195  typedef std::reverse_iterator<const_iterator,T> const_reverse_iterator;
196 #endif
197 
198  reverse_iterator rbegin() { return reverse_iterator(end()); }
199  const_reverse_iterator rbegin() const {
200  return const_reverse_iterator(end());
201  }
202  const_reverse_iterator crbegin() const {
203  return const_reverse_iterator(end());
204  }
205 
206  reverse_iterator rend() { return reverse_iterator(begin()); }
207  const_reverse_iterator rend() const {
208  return const_reverse_iterator(begin());
209  }
210  const_reverse_iterator crend() const {
211  return const_reverse_iterator(begin());
212  }
213 
214  // operator[]
215  reference operator[](size_type /*i*/)
216  {
217  return failed_rangecheck();
218  }
219 
220  /*BOOST_CONSTEXPR*/ const_reference operator[](size_type /*i*/) const
221  {
222  return failed_rangecheck();
223  }
224 
225  // at() with range check
226  reference at(size_type /*i*/) { return failed_rangecheck(); }
227  /*BOOST_CONSTEXPR*/ const_reference at(size_type /*i*/) const { return failed_rangecheck(); }
228 
229  // front() and back()
230  reference front()
231  {
232  return failed_rangecheck();
233  }
234 
235  BOOST_CONSTEXPR const_reference front() const
236  {
237  return failed_rangecheck();
238  }
239 
240  reference back()
241  {
242  return failed_rangecheck();
243  }
244 
245  BOOST_CONSTEXPR const_reference back() const
246  {
247  return failed_rangecheck();
248  }
249 
250  // size is constant
251  static BOOST_CONSTEXPR size_type size() { return 0; }
252  static BOOST_CONSTEXPR bool empty() { return true; }
253  static BOOST_CONSTEXPR size_type max_size() { return 0; }
254  enum { static_size = 0 };
255 
256  void swap (array<T,0>&) {}
257 
258  // direct access to data (read-only)
259  const T* data() const { return 0; }
260  T* data() { return 0; }
261 
262  // use array as C array (direct read/write access to data)
263  T* c_array() { return 0; }
264 
265  // assignment with type conversion
266  template <typename T2>
267  array<T,0>& operator= (const array<T2,0>& )
268  {return *this;}
269 
270  // assign one value to all elements
271  void assign (const T& value) { fill ( value ); }
272  void fill (const T& ) {}
273 
274  // check range (may be private because it is static)
275  static reference failed_rangecheck ()
276  {
277  std::out_of_range e("attempt to access element of an empty array");
278  boost::throw_exception(e);
279 #if defined(BOOST_NO_EXCEPTIONS) || (!defined(BOOST_MSVC) && !defined(__PATHSCALE__))
280  //
281  // We need to return something here to keep
282  // some compilers happy: however we will never
283  // actually get here....
284  //
285  static T placeholder;
286  return placeholder;
287 #endif
288  }
289  };
290 
291  // comparisons
292  template<class T, std::size_t N>
293  bool operator== (const array<T,N>& x, const array<T,N>& y) {
294  return std::equal(x.begin(), x.end(), y.begin());
295  }
296  template<class T, std::size_t N>
297  bool operator< (const array<T,N>& x, const array<T,N>& y) {
298  return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end());
299  }
300  template<class T, std::size_t N>
301  bool operator!= (const array<T,N>& x, const array<T,N>& y) {
302  return !(x==y);
303  }
304  template<class T, std::size_t N>
305  bool operator> (const array<T,N>& x, const array<T,N>& y) {
306  return y<x;
307  }
308  template<class T, std::size_t N>
309  bool operator<= (const array<T,N>& x, const array<T,N>& y) {
310  return !(y<x);
311  }
312  template<class T, std::size_t N>
313  bool operator>= (const array<T,N>& x, const array<T,N>& y) {
314  return !(x<y);
315  }
316 
317  // global swap()
318  template<class T, std::size_t N>
319  inline void swap (array<T,N>& x, array<T,N>& y)
320  {x.swap(y);}
321 
322 #if defined(__SUNPRO_CC)
323 // Trac ticket #4757; the Sun Solaris compiler can't handle
324 // syntax like 'T(&get_c_array(boost::array<T,N>& arg))[N]'
325 //
326 // We can't just use this for all compilers, because the
327 // borland compilers can't handle this form.
328  namespace detail
329  {
330  template <typename T, std::size_t N> struct c_array
331  {
332  typedef T type[N];
333  };
334  }
335 
336  // Specific for boost::array: simply returns its elems data member.
337  template <typename T, std::size_t N>
338  typename detail::c_array<T,N>::type& get_c_array(boost::array_openfpm<T,N>& arg)
339  {
340  return arg.elems;
341  }
342 
343  // Specific for boost::array: simply returns its elems data member.
344  template <typename T, std::size_t N>
345  typename detail::c_array<T,N>::type const& get_c_array(const boost::array_openfpm<T,N>& arg)
346  {
347  return arg.elems;
348  }
349 #else
350 // Specific for boost::array: simply returns its elems data member.
351  template <typename T, std::size_t N>
352  T(&get_c_array(openfpm::array<T,N>& arg))[N]
353  {
354  return arg.elems;
355  }
356 
357  // Const version.
358  template <typename T, std::size_t N>
359  const T(&get_c_array(const openfpm::array<T,N>& arg))[N]
360  {
361  return arg.elems;
362  }
363 #endif
364 
365 
366  template <class It> std::size_t hash_range(It, It);
367 
368  template<class T, std::size_t N>
369  std::size_t hash_value(const array<T,N>& arr)
370  {
371  return openfpm::hash_range(arr.begin(), arr.end());
372  }
373 
374  template <size_t Idx, typename T, size_t N>
375  T &get(openfpm::array<T,N> &arr) noexcept
376  {
377  BOOST_STATIC_ASSERT_MSG ( Idx < N, "boost::get<>(boost::array &) index out of range" );
378  return arr[Idx];
379  }
380 
381  template <size_t Idx, typename T, size_t N>
382  const T &get(const openfpm::array<T,N> &arr) noexcept
383  {
384  BOOST_STATIC_ASSERT_MSG ( Idx < N, "boost::get<>(const boost::array &) index out of range" );
385  return arr[Idx];
386  }
387 
388 } /* namespace boost */
389 
390 #ifndef BOOST_NO_CXX11_HDR_ARRAY
391 // If we don't have std::array, I'm assuming that we don't have std::get
392 namespace std {
393  template <size_t Idx, typename T, size_t N>
394  T &get(openfpm::array<T,N> &arr) noexcept
395  {
396  BOOST_STATIC_ASSERT_MSG ( Idx < N, "std::get<>(boost::array &) index out of range" );
397  return arr[Idx];
398  }
399 
400  template <size_t Idx, typename T, size_t N>
401  const T &get(const openfpm::array<T,N> &arr) noexcept
402  {
403  BOOST_STATIC_ASSERT_MSG ( Idx < N, "std::get<>(const boost::array &) index out of range" );
404  return arr[Idx];
405  }
406 }
407 #endif
408 
409 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
410 # pragma warning(pop)
411 #endif
412 
413 
414 #endif /* ARRAY_OPENFPM_HPP_ */
convert a type into constant type
Definition: aggregate.hpp:292