OpenFPM_pdata  4.1.0
Project that contain the implementation of distributed structures
 
Loading...
Searching...
No Matches
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
34namespace 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
392namespace 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