Extended CUDA Library (ecuda)  2.0
 All Classes Namespaces Files Functions Variables Typedefs Friends Macros
array.hpp
Go to the documentation of this file.
1 /*
2 Copyright (c) 2014-2016, Scott Zuyderduyn
3 All rights reserved.
4 
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7 
8 1. Redistributions of source code must retain the above copyright notice, this
9  list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright notice,
11  this list of conditions and the following disclaimer in the documentation
12  and/or other materials provided with the distribution.
13 
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
18 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 
25 The views and conclusions contained in the software and documentation are those
26 of the authors and should not be interpreted as representing official policies,
27 either expressed or implied, of the FreeBSD Project.
28 */
29 
30 //----------------------------------------------------------------------------
31 // array.hpp
32 //
33 // An STL-like structure that resides in video memory.
34 //
35 // Author: Scott D. Zuyderduyn, Ph.D. (scott.zuyderduyn@utoronto.ca)
36 //----------------------------------------------------------------------------
37 
38 #pragma once
39 #ifndef ECUDA_ARRAY_HPP
40 #define ECUDA_ARRAY_HPP
41 
42 #include <algorithm>
43 #include <limits>
44 #include <stdexcept>
45 #ifdef ECUDA_CPP11_AVAILABLE
46 #include <initializer_list>
47 #include <utility>
48 #include <vector>
49 #endif
50 
51 #include "global.hpp"
52 #include "algorithm.hpp" // for copy
53 #include "allocators.hpp" // for device_allocator
54 #include "memory.hpp" // for shared_ptr
55 
57 
58 namespace ecuda {
59 
61 namespace impl {
62 
63 template<typename T,std::size_t N> class array_kernel_argument; // forward declaration
64 
65 } // namespace impl
67 
79 template< typename T, std::size_t N, class P=shared_ptr<T> >
80 class array : private model::device_fixed_sequence< T, N, P > {
81 
82 private:
83  typedef model::device_fixed_sequence< T, N, P > base_type;
84 
85 public:
86  typedef typename base_type::value_type value_type;
87  typedef typename base_type::size_type size_type;
88  typedef typename base_type::difference_type difference_type;
89  typedef typename base_type::reference reference;
90  typedef typename base_type::const_reference const_reference;
91  typedef typename base_type::pointer pointer;
92  typedef typename make_const<pointer>::type const_pointer;
93 
94  typedef typename base_type::iterator iterator;
95  typedef typename base_type::const_iterator const_iterator;
96  typedef typename base_type::reverse_iterator reverse_iterator;
97  typedef typename base_type::const_reverse_iterator const_reverse_iterator;
98 
99  typedef impl::array_kernel_argument<T,N> kernel_argument;
100  typedef const impl::array_kernel_argument<T,N> const_kernel_argument;
101 
102  template<typename U,std::size_t M,class Q> friend class array;
103 
104 protected:
108  template<class Q> __HOST__ __DEVICE__ array( const array<T,N,Q>& src, ecuda::true_type ) : base_type( unmanaged_cast(src.get_pointer()) ) {}
109 
113  template<class Q>
114  __HOST__ __DEVICE__ array& shallow_assign( const array<T,N,Q>& other )
115  {
116  base_type::get_pointer() = unmanaged_cast(other.get_pointer());
117  return *this;
118  }
119 
120 public:
126  __HOST__ array() : base_type( shared_ptr<T>( device_allocator<T>().allocate(N) ) )
127  {
128  fill( value_type() );
129  }
130 
138  __HOST__ array( const array& src ) : base_type( shared_ptr<T>( device_allocator<T>().allocate(src.size()) ) )
139  {
140  ecuda::copy( src.begin(), src.end(), begin() );
141  }
142 
143  #ifdef ECUDA_CPP11_AVAILABLE
144  template<typename U>
145  __HOST__ array( std::initializer_list<U> il ) : base_type( shared_ptr<T>( device_allocator<T>().allocate(N) ) )
146  {
147  #ifdef ECUDA_CONSTEXPR_KEYWORD_ENABLED
148  static_assert( il.size() <= N, EXCEPTION_MSG("size of initializer list must not be greater than the array size") );
149  #else
150  if( il.size() > N ) throw std::invalid_argument( EXCEPTION_MSG("size of initializer list must not be greater than the array size") );
151  #endif
152  ecuda::copy( il.begin(), il.end(), begin() );
153  }
154  #endif
155 
163  __HOST__ array& operator=( const array& other )
164  {
165  ecuda::copy( other.begin(), other.end(), begin() );
166  return *this;
167  }
168 
169  #ifdef ECUDA_CPP11_AVAILABLE
170  __HOST__ array( array&& src ) : base_type(std::move(src)) {}
179 
186  __HOST__ array& operator=( array&& src )
187  {
188  base_type::operator=(std::move(src));
189  return *this;
190  }
191  #endif
192 
203  {
204  if( !(index < size()) ) {
205  #ifndef __CUDACC__
206  throw std::out_of_range( EXCEPTION_MSG("ecuda::array::at() index parameter is out of range") );
207  #else
208  // this strategy is taken from:
209  // http://stackoverflow.com/questions/12521721/crashing-a-kernel-gracefully
211  //__threadfence();
212  asm("trap;");
213  #endif
214  }
215  return base_type::operator[](index);
216  }
217 
227  __DEVICE__ inline const_reference at( size_type index ) const
228  {
229  if( !(index < size()) ) {
230  #ifndef __CUDACC__
231  throw std::out_of_range( EXCEPTION_MSG("ecuda::array::at() index parameter is out of range") );
232  #else
233  // this strategy is taken from:
234  // http://stackoverflow.com/questions/12521721/crashing-a-kernel-gracefully
236  //__threadfence();
237  asm("trap;");
238  #endif
239  }
240  return base_type::operator[](index);
241  }
242 
249  __DEVICE__ inline reference operator[]( size_type index ) { return base_type::operator[](index); }
250 
257  __DEVICE__ inline const_reference operator[]( size_type index ) const { return base_type::operator[](index); }
258 
267  __DEVICE__ inline reference operator()( const size_type index ) { return base_type::operator[](index); }
268 
277  __DEVICE__ inline const_reference operator()( const size_type index ) const { return base_type::operator[](index); }
278 
286  __DEVICE__ inline reference front() { return base_type::operator[](0); }
287 
295  __DEVICE__ inline reference back() { return base_type::operator[](size()-1); }
303  __DEVICE__ inline const_reference front() const { return base_type::operator[](0); }
304 
312  __DEVICE__ inline const_reference back() const { return base_type::operator[](size()-1); }
313 
322  __HOST__ __DEVICE__ inline pointer data() __NOEXCEPT__ { return base_type::get_pointer(); }
323 
332  __HOST__ __DEVICE__ inline const_pointer data() const __NOEXCEPT__ { return base_type::get_pointer(); }
333 
341  __HOST__ __DEVICE__ inline iterator begin() __NOEXCEPT__ { return base_type::begin(); }
342 
350  __HOST__ __DEVICE__ inline iterator end() __NOEXCEPT__ { return base_type::end(); }
351 
359  __HOST__ __DEVICE__ inline const_iterator begin() const __NOEXCEPT__ { return base_type::begin(); }
360 
368  __HOST__ __DEVICE__ inline const_iterator end() const __NOEXCEPT__ { return base_type::end(); }
369 
377  __HOST__ __DEVICE__ inline reverse_iterator rbegin() __NOEXCEPT__ { return base_type::rbegin(); }
378 
387  __HOST__ __DEVICE__ inline reverse_iterator rend() __NOEXCEPT__ { return base_type::rend(); }
388 
396  __HOST__ __DEVICE__ inline const_reverse_iterator rbegin() const __NOEXCEPT__ { return base_type::rbegin(); }
397 
406  __HOST__ __DEVICE__ inline const_reverse_iterator rend() const __NOEXCEPT__ { return base_type::rend(); }
407 
408  #ifdef ECUDA_CPP11_AVAILABLE
409 
417  __HOST__ __DEVICE__ inline const_iterator cbegin() const __NOEXCEPT__ { return base_type::cbegin(); }
418 
426  __HOST__ __DEVICE__ inline const_iterator cend() const __NOEXCEPT__ { return base_type::cend(); }
427 
435  __HOST__ __DEVICE__ inline const_reverse_iterator crbegin() const __NOEXCEPT__ { return base_type::crbegin(); }
436 
445  __HOST__ __DEVICE__ inline const_reverse_iterator crend() const __NOEXCEPT__ { return base_type::crend(); }
446 
447  #endif
448 
454  __HOST__ __DEVICE__ __CONSTEXPR__ inline bool empty() const __NOEXCEPT__ { return size() == 0; }
455 
461  __HOST__ __DEVICE__ __CONSTEXPR__ inline size_type size() const __NOEXCEPT__ { return base_type::size(); }
462 
471 
472 
478  __HOST__ __DEVICE__ inline void fill( const value_type& value ) { ecuda::fill( begin(), end(), value ); }
479 
487  __HOST__ __DEVICE__ inline void swap( array& other )
488  #if defined(ECUDA_CPP11_AVAILABLE) && defined(ECUDA_NOEXCEPT_KEYWORD_ENABLED)
489  noexcept(noexcept(swap(std::declval<T&>(),std::declval<T&>())))
490  #endif
491  {
492  base_type::swap( other );
493  }
494 
504  __HOST__ __DEVICE__ inline bool operator==( const array& other ) const { return ecuda::equal( begin(), end(), other.begin() ); }
505 
515  __HOST__ __DEVICE__ inline bool operator!=( const array& other ) const { return !operator==(other); }
516 
523  __HOST__ __DEVICE__ inline bool operator<( const array& other ) const { return ecuda::lexicographical_compare( begin(), end(), other.begin(), other.end() ); }
524 
531  __HOST__ __DEVICE__ inline bool operator>( const array& other ) const { return ecuda::lexicographical_compare( other.begin(), other.end(), begin(), end() ); }
532 
539  __HOST__ __DEVICE__ inline bool operator<=( const array& other ) const { return !operator>(other); }
540 
547  __HOST__ __DEVICE__ inline bool operator>=( const array& other ) const { return !operator<(other); }
548 
549 };
550 
552 namespace impl {
553 
563 template<typename T,std::size_t N>
564 class array_kernel_argument : public array<T,N,typename ecuda::add_pointer<T>::type>
565 {
566 
567 private:
568  typedef array<T,N,typename ecuda::add_pointer<T>::type> base_type;
569 
570 public:
571  template<class P>
572  __HOST__ array_kernel_argument( const array<T,N,P>& src ) : base_type( src, ecuda::true_type() ) {}
573 
574  __HOST__ __DEVICE__ array_kernel_argument( const array_kernel_argument& src ) : base_type( src, ecuda::true_type() ) {}
575 
576  template<class P>
577  __HOST__ array_kernel_argument& operator=( const array<T,N,P>& src )
578  {
579  base_type::shallow_assign(src);
580  return *this;
581  }
582 
583  #ifdef ECUDA_CPP11_AVAILABLE
584  array_kernel_argument( array_kernel_argument&& src ) : base_type(std::move(src)) {}
585 
586  array_kernel_argument& operator=( array_kernel_argument&& src )
587  {
588  base_type::operator=(std::move(src));
589  return *this;
590  }
591  #endif
592 
593 };
594 
595 } // namespace impl
597 
598 } // namespace ecuda
599 
600 #endif
__HOST__ __DEVICE__ iterator begin() __NOEXCEPT__
Returns an iterator to the first element of the container.
Definition: array.hpp:341
__HOST__ __DEVICE__ const_iterator begin() const __NOEXCEPT__
Returns a const_iterator to the first element of the container.
Definition: array.hpp:359
A smart pointer that retains shared ownership of an object in device memory.
Definition: shared_ptr.hpp:122
__HOST__ __DEVICE__ OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result)
Replacement for std::copy.
Definition: copy.hpp:801
base_type::reference reference
cell reference type
Definition: array.hpp:89
__DEVICE__ reference back()
Returns a reference to the last element in the container.
Definition: array.hpp:295
#define __CONSTEXPR__
Definition: global.hpp:141
__HOST__ __DEVICE__ iterator end() __NOEXCEPT__
Returns an iterator to the element following the last element of the container.
Definition: array.hpp:350
__DEVICE__ const_reference front() const
Returns a reference to the first element in the container.
Definition: array.hpp:303
__DEVICE__ const_reference operator()(const size_type index) const
Returns a reference to the element at specified location index. No bounds checking is performed...
Definition: array.hpp:277
__HOST__ array()
Constructs a fixed-size array with N elements.
Definition: array.hpp:126
__HOST__ __DEVICE__ bool operator!=(const array &other) const
Checks if the contents of two arrays are not equal.
Definition: array.hpp:515
base_type::iterator iterator
iterator type
Definition: array.hpp:94
__HOST__ __DEVICE__ const_reverse_iterator rbegin() const __NOEXCEPT__
Returns a const_reverse_iterator to the first element of the reversed container.
Definition: array.hpp:396
__HOST__ __DEVICE__ const_pointer data() const __NOEXCEPT__
Returns pointer to the underlying array serving as element storage.
Definition: array.hpp:332
base_type::value_type value_type
cell data type
Definition: array.hpp:86
#define __NOEXCEPT__
Definition: global.hpp:140
base_type::size_type size_type
unsigned integral type
Definition: array.hpp:87
impl::array_kernel_argument< T, N > kernel_argument
kernel argument type
Definition: array.hpp:99
__HOST__ __DEVICE__ const_iterator end() const __NOEXCEPT__
Returns a const_iterator to the element following the last element of the container.
Definition: array.hpp:368
base_type::const_iterator const_iterator
const iterator type
Definition: array.hpp:95
__DEVICE__ reference at(size_type index)
Returns a reference to the element at specified location index, with bounds checking.
Definition: array.hpp:202
#define __HOST__
Definition: global.hpp:150
__DEVICE__ const_reference back() const
Returns a reference to the last element in the container.
Definition: array.hpp:312
base_type::difference_type difference_type
signed integral type
Definition: array.hpp:88
__HOST__ __DEVICE__ void swap(T &a, T &b) __NOEXCEPT__
Definition: algorithm.hpp:54
base_type::const_reverse_iterator const_reverse_iterator
const reverse iterator type
Definition: array.hpp:97
__HOST__ __DEVICE__ reverse_iterator rbegin() __NOEXCEPT__
Returns a reverse iterator to the first element of the reversed container.
Definition: array.hpp:377
base_type::pointer pointer
cell pointer type
Definition: array.hpp:91
__HOST__ __DEVICE__ __CONSTEXPR__ bool empty() const __NOEXCEPT__
Checks if the container has no elements.
Definition: array.hpp:454
__HOST__ __CONSTEXPR__ size_type max_size() const __NOEXCEPT__
Returns the maximum number of elements the container is able to hold.
Definition: array.hpp:470
base_type::reverse_iterator reverse_iterator
reverse iterator type
Definition: array.hpp:96
make_const< pointer >::type const_pointer
cell const pointer type
Definition: array.hpp:92
__HOST__ __DEVICE__ reverse_iterator rend() __NOEXCEPT__
Returns a reverse iterator to the element following the last element of the reversed container...
Definition: array.hpp:387
base_type::const_reference const_reference
cell const reference type
Definition: array.hpp:90
Allocator for device memory.
Definition: allocators.hpp:227
__HOST__ __DEVICE__ void swap(array &other)
Exchanges the contents of the container with those of the other.
Definition: array.hpp:487
__HOST__ __DEVICE__ bool operator>(const array &other) const
Compares the contents of two arrays lexicographically.
Definition: array.hpp:531
__HOST__ __DEVICE__ pointer data() __NOEXCEPT__
Returns pointer to the underlying array serving as element storage.
Definition: array.hpp:322
__HOST__ __DEVICE__ __CONSTEXPR__ size_type size() const __NOEXCEPT__
Returns the number of elements in the container.
Definition: array.hpp:461
__HOST__ __DEVICE__ bool operator>=(const array &other) const
Compares the contents of two arrays lexicographically.
Definition: array.hpp:547
__DEVICE__ reference front()
Returns a reference to the first element in the container.
Definition: array.hpp:286
const impl::array_kernel_argument< T, N > const_kernel_argument
const kernel argument type
Definition: array.hpp:100
__DEVICE__ reference operator()(const size_type index)
Returns a reference to the element at specified location index. No bounds checking is performed...
Definition: array.hpp:267
__DEVICE__ const_reference operator[](size_type index) const
Returns a reference to the element at specified location index. No bounds checking is performed...
Definition: array.hpp:257
__HOST__ __DEVICE__ bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2)
Replacement for std::equal.
Definition: equal.hpp:173
__DEVICE__ void threadfence()
__HOST__ __DEVICE__ const T & max(const T &a, const T &b)
Definition: algorithm.hpp:51
#define EXCEPTION_MSG(x)
Definition: global.hpp:92
#define __DEVICE__
Definition: global.hpp:151
__HOST__ array(const array &src)
Copy constructor.
Definition: array.hpp:138
__HOST__ __DEVICE__ bool operator<=(const array &other) const
Compares the contents of two arrays lexicographically.
Definition: array.hpp:539
__HOST__ __DEVICE__ bool lexicographical_compare(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2)
A fixed-size array stored in device memory.
Definition: array.hpp:80
__DEVICE__ const_reference at(size_type index) const
Returns a reference to the element at specified location index, with bounds checking.
Definition: array.hpp:227
__HOST__ array & operator=(const array &other)
Assignment operator.
Definition: array.hpp:163
__DEVICE__ reference operator[](size_type index)
Returns a reference to the element at specified location index. No bounds checking is performed...
Definition: array.hpp:249
__HOST__ __DEVICE__ const_reverse_iterator rend() const __NOEXCEPT__
Returns a const_reverse_iterator to the element following the last element of the reversed container...
Definition: array.hpp:406
__HOST__ __DEVICE__ bool operator==(const array &other) const
Checks if the contents of two arrays are equal.
Definition: array.hpp:504
__HOST__ __DEVICE__ bool operator<(const array &other) const
Compares the contents of two arrays lexicographically.
Definition: array.hpp:523
__HOST__ __DEVICE__ void fill(const value_type &value)
Assigns a given value to all elements in the container.
Definition: array.hpp:478
__HOST__ __DEVICE__ void fill(ForwardIterator first, ForwardIterator last, const T &val)
Definition: fill.hpp:156