Kokkos Core Kernels Package  Version of the Day
Kokkos_Array.hpp
1 /*
2 //@HEADER
3 // ************************************************************************
4 //
5 // Kokkos v. 2.0
6 // Copyright (2014) Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Christian R. Trott (crtrott@sandia.gov)
39 //
40 // ************************************************************************
41 //@HEADER
42 */
43 
44 #ifndef KOKKOS_ARRAY_HPP
45 #define KOKKOS_ARRAY_HPP
46 
47 #include <Kokkos_Macros.hpp>
48 
49 #include <type_traits>
50 #include <algorithm>
51 #include <limits>
52 #include <cstddef>
53 
54 namespace Kokkos {
55 
56 #ifdef KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK
57 namespace Impl {
58 template <typename Integral, bool Signed = std::is_signed<Integral>::value>
59 struct ArrayBoundsCheck;
60 
61 template <typename Integral>
62 struct ArrayBoundsCheck<Integral, true> {
63  KOKKOS_INLINE_FUNCTION
64  ArrayBoundsCheck(Integral i, size_t N) {
65  if (i < 0) {
66 #ifdef KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST
67  std::string s = "Kokkos::Array: index ";
68  s += std::to_string(i);
69  s += " < 0";
70  Kokkos::Impl::throw_runtime_exception(s);
71 #else
72  Kokkos::abort("Kokkos::Array: negative index in device code");
73 #endif
74  }
75  ArrayBoundsCheck<Integral, false>(i, N);
76  }
77 };
78 
79 template <typename Integral>
80 struct ArrayBoundsCheck<Integral, false> {
81  KOKKOS_INLINE_FUNCTION
82  ArrayBoundsCheck(Integral i, size_t N) {
83  if ( size_t(i) >= N) {
84 #ifdef KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST
85  std::string s = "Kokkos::Array: index ";
86  s += std::to_string(i);
87  s += " >= ";
88  s += std::to_string(N);
89  Kokkos::Impl::throw_runtime_exception(s);
90 #else
91  Kokkos::abort("Kokkos::Array: index >= size");
92 #endif
93  }
94  }
95 };
96 } // end namespace Impl
97 
98 #define KOKKOS_ARRAY_BOUNDS_CHECK(i, N) \
99  Kokkos::Impl::ArrayBoundsCheck<decltype(i)>(i, N)
100 
101 #else // !defined( KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK )
102 
103 #define KOKKOS_ARRAY_BOUNDS_CHECK(i, N) (void)0
104 
105 #endif // !defined( KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK )
106 
110 template< class T = void
111  , size_t N =KOKKOS_INVALID_INDEX
112  , class Proxy = void
113  >
114 struct Array {
115 public:
122  T m_internal_implementation_private_member_data[N];
123 public:
124 
125  typedef T & reference ;
126  typedef typename std::add_const<T>::type & const_reference ;
127  typedef size_t size_type ;
128  typedef ptrdiff_t difference_type ;
129  typedef T value_type ;
130  typedef T * pointer ;
131  typedef typename std::add_const<T>::type * const_pointer ;
132 
133  KOKKOS_INLINE_FUNCTION static constexpr size_type size() { return N ; }
134  KOKKOS_INLINE_FUNCTION static constexpr bool empty(){ return false ; }
135 
136  template< typename iType >
137  KOKKOS_INLINE_FUNCTION
138  reference operator[]( const iType & i )
139  {
140  static_assert( ( std::is_integral<iType>::value || std::is_enum<iType>::value ) , "Must be integral argument" );
141  KOKKOS_ARRAY_BOUNDS_CHECK(i, N);
142  return m_internal_implementation_private_member_data[i];
143  }
144 
145  template< typename iType >
146  KOKKOS_INLINE_FUNCTION
147  const_reference operator[]( const iType & i ) const
148  {
149  static_assert( ( std::is_integral<iType>::value || std::is_enum<iType>::value ) , "Must be integral argument" );
150  KOKKOS_ARRAY_BOUNDS_CHECK(i, N);
151  return m_internal_implementation_private_member_data[i];
152  }
153 
154  KOKKOS_INLINE_FUNCTION pointer data()
155  {
156  return & m_internal_implementation_private_member_data[0];
157  }
158  KOKKOS_INLINE_FUNCTION const_pointer data() const
159  {
160  return & m_internal_implementation_private_member_data[0];
161  }
162 
163  #ifdef KOKKOS_ROCM_CLANG_WORKAROUND
164  // Do not default unless move and move-assignment are also defined
165  KOKKOS_INLINE_FUNCTION
166  ~Array() = default ;
167  Array() = default ;
168  Array( const Array & ) = default ;
169  Array & operator = ( const Array & ) = default ;
170 
171  // Some supported compilers are not sufficiently C++11 compliant
172  // for default move constructor and move assignment operator.
173  Array( Array && ) = default ;
174  Array & operator = ( Array && ) = default ;
175 
176  KOKKOS_INLINE_FUNCTION
177  Array(const std::initializer_list<T>& vals) {
178  for(int i=0; i<N; i++) {
179  m_internal_implementation_private_member_data[i] = vals.begin()[i];
180  }
181  }
182  #endif
183 };
184 
185 
186 template< class T , class Proxy >
187 struct Array<T,0,Proxy> {
188 public:
189 
190  typedef typename std::add_const<T>::type & reference ;
191  typedef typename std::add_const<T>::type & const_reference ;
192  typedef size_t size_type ;
193  typedef ptrdiff_t difference_type ;
194  typedef typename std::add_const<T>::type value_type ;
195  typedef typename std::add_const<T>::type * pointer ;
196  typedef typename std::add_const<T>::type * const_pointer ;
197 
198  KOKKOS_INLINE_FUNCTION static constexpr size_type size() { return 0 ; }
199  KOKKOS_INLINE_FUNCTION static constexpr bool empty() { return true ; }
200 
201  template< typename iType >
202  KOKKOS_INLINE_FUNCTION
203  value_type operator[]( const iType & )
204  {
205  static_assert( ( std::is_integral<iType>::value || std::is_enum<iType>::value ) , "Must be integer argument" );
206  return value_type();
207  }
208 
209  template< typename iType >
210  KOKKOS_INLINE_FUNCTION
211  value_type operator[]( const iType & ) const
212  {
213  static_assert( ( std::is_integral<iType>::value || std::is_enum<iType>::value ) , "Must be integer argument" );
214  return value_type();
215  }
216 
217  KOKKOS_INLINE_FUNCTION pointer data() { return pointer(0) ; }
218  KOKKOS_INLINE_FUNCTION const_pointer data() const { return const_pointer(0); }
219 
220 #ifdef KOKKOS_CUDA_9_DEFAULTED_BUG_WORKAROUND
221  KOKKOS_INLINE_FUNCTION ~Array() {}
222  KOKKOS_INLINE_FUNCTION Array() {}
223  KOKKOS_INLINE_FUNCTION Array( const Array & ) {}
224  KOKKOS_INLINE_FUNCTION Array & operator = ( const Array & ) {}
225 #else
226  KOKKOS_INLINE_FUNCTION ~Array() = default;
227  KOKKOS_INLINE_FUNCTION Array() = default;
228  KOKKOS_INLINE_FUNCTION Array( const Array & ) = default;
229  KOKKOS_INLINE_FUNCTION Array & operator = ( const Array & ) = default;
230 #endif
231 
232  // Some supported compilers are not sufficiently C++11 compliant
233  // for default move constructor and move assignment operator.
234  // Array( Array && ) = default ;
235  // Array & operator = ( Array && ) = default ;
236 };
237 
238 
239 template<>
240 struct Array<void,KOKKOS_INVALID_INDEX,void>
241 {
242  struct contiguous {};
243  struct strided {};
244 };
245 
246 template< class T >
247 struct Array< T ,KOKKOS_INVALID_INDEX , Array<>::contiguous >
248 {
249 private:
250  T * m_elem ;
251  size_t m_size ;
252 public:
253 
254  typedef T & reference ;
255  typedef typename std::add_const<T>::type & const_reference ;
256  typedef size_t size_type ;
257  typedef ptrdiff_t difference_type ;
258  typedef T value_type ;
259  typedef T * pointer ;
260  typedef typename std::add_const<T>::type * const_pointer ;
261 
262  KOKKOS_INLINE_FUNCTION constexpr size_type size() const { return m_size ; }
263  KOKKOS_INLINE_FUNCTION constexpr bool empty() const { return 0 != m_size ; }
264 
265  template< typename iType >
266  KOKKOS_INLINE_FUNCTION
267  reference operator[]( const iType & i )
268  {
269  static_assert( ( std::is_integral<iType>::value || std::is_enum<iType>::value ) , "Must be integral argument" );
270  KOKKOS_ARRAY_BOUNDS_CHECK(i, m_size);
271  return m_elem[i];
272  }
273 
274  template< typename iType >
275  KOKKOS_INLINE_FUNCTION
276  const_reference operator[]( const iType & i ) const
277  {
278  static_assert( ( std::is_integral<iType>::value || std::is_enum<iType>::value ) , "Must be integral argument" );
279  KOKKOS_ARRAY_BOUNDS_CHECK(i, m_size);
280  return m_elem[i];
281  }
282 
283  KOKKOS_INLINE_FUNCTION pointer data() { return m_elem ; }
284  KOKKOS_INLINE_FUNCTION const_pointer data() const { return m_elem ; }
285 
286 #ifdef KOKKOS_CUDA_9_DEFAULTED_BUG_WORKAROUND
287  KOKKOS_INLINE_FUNCTION ~Array() {}
288 #else
289  KOKKOS_INLINE_FUNCTION ~Array() = default;
290 #endif
291  Array() = delete ;
292  Array( const Array & rhs ) = delete ;
293 
294  // Some supported compilers are not sufficiently C++11 compliant
295  // for default move constructor and move assignment operator.
296  // Array( Array && rhs ) = default ;
297  // Array & operator = ( Array && rhs ) = delete ;
298 
299  KOKKOS_INLINE_FUNCTION
300  Array & operator = ( const Array & rhs )
301  {
302  const size_t n = std::min( m_size , rhs.size() );
303  for ( size_t i = 0 ; i < n ; ++i ) m_elem[i] = rhs[i] ;
304  return *this ;
305  }
306 
307  template< size_t N , class P >
308  KOKKOS_INLINE_FUNCTION
309  Array & operator = ( const Array<T,N,P> & rhs )
310  {
311  const size_t n = std::min( m_size , rhs.size() );
312  for ( size_t i = 0 ; i < n ; ++i ) m_elem[i] = rhs[i] ;
313  return *this ;
314  }
315 
316  KOKKOS_INLINE_FUNCTION constexpr Array( pointer arg_ptr , size_type arg_size , size_type = 0 )
317  : m_elem(arg_ptr), m_size(arg_size) {}
318 };
319 
320 template< class T >
321 struct Array< T ,KOKKOS_INVALID_INDEX , Array<>::strided >
322 {
323 private:
324  T * m_elem ;
325  size_t m_size ;
326  size_t m_stride ;
327 public:
328 
329  typedef T & reference ;
330  typedef typename std::add_const<T>::type & const_reference ;
331  typedef size_t size_type ;
332  typedef ptrdiff_t difference_type ;
333  typedef T value_type ;
334  typedef T * pointer ;
335  typedef typename std::add_const<T>::type * const_pointer ;
336 
337  KOKKOS_INLINE_FUNCTION constexpr size_type size() const { return m_size ; }
338  KOKKOS_INLINE_FUNCTION constexpr bool empty() const { return 0 != m_size ; }
339 
340  template< typename iType >
341  KOKKOS_INLINE_FUNCTION
342  reference operator[]( const iType & i )
343  {
344  static_assert( ( std::is_integral<iType>::value || std::is_enum<iType>::value ) , "Must be integral argument" );
345  KOKKOS_ARRAY_BOUNDS_CHECK(i, m_size);
346  return m_elem[i*m_stride];
347  }
348 
349  template< typename iType >
350  KOKKOS_INLINE_FUNCTION
351  const_reference operator[]( const iType & i ) const
352  {
353  static_assert( ( std::is_integral<iType>::value || std::is_enum<iType>::value ) , "Must be integral argument" );
354  KOKKOS_ARRAY_BOUNDS_CHECK(i, m_size);
355  return m_elem[i*m_stride];
356  }
357 
358  KOKKOS_INLINE_FUNCTION pointer data() { return m_elem ; }
359  KOKKOS_INLINE_FUNCTION const_pointer data() const { return m_elem ; }
360 
361 #ifdef KOKKOS_CUDA_9_DEFAULTED_BUG_WORKAROUND
362  KOKKOS_INLINE_FUNCTION ~Array() {}
363 #else
364  KOKKOS_INLINE_FUNCTION ~Array() = default;
365 #endif
366  Array() = delete ;
367  Array( const Array & ) = delete ;
368 
369 
370  // Some supported compilers are not sufficiently C++11 compliant
371  // for default move constructor and move assignment operator.
372  // Array( Array && rhs ) = default ;
373  // Array & operator = ( Array && rhs ) = delete ;
374 
375  KOKKOS_INLINE_FUNCTION
376  Array & operator = ( const Array & rhs )
377  {
378  const size_t n = std::min( m_size , rhs.size() );
379  for ( size_t i = 0 ; i < n ; ++i ) m_elem[i] = rhs[i] ;
380  return *this ;
381  }
382 
383  template< size_t N , class P >
384  KOKKOS_INLINE_FUNCTION
385  Array & operator = ( const Array<T,N,P> & rhs )
386  {
387  const size_t n = std::min( m_size , rhs.size() );
388  for ( size_t i = 0 ; i < n ; ++i ) m_elem[i] = rhs[i] ;
389  return *this ;
390  }
391 
392  KOKKOS_INLINE_FUNCTION constexpr Array( pointer arg_ptr , size_type arg_size , size_type arg_stride )
393  : m_elem(arg_ptr), m_size(arg_size), m_stride(arg_stride) {}
394 };
395 
396 } // namespace Kokkos
397 
398 #endif /* #ifndef KOKKOS_ARRAY_HPP */
399 
Derived from the C++17 &#39;std::array&#39;. Dropping the iterator interface.