Kokkos Core Kernels Package  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
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 #include <impl/Kokkos_Error.hpp>
49 
50 #include <type_traits>
51 #include <algorithm>
52 #include <limits>
53 #include <cstddef>
54 #include <string>
55 
56 namespace Kokkos {
57 
58 #ifdef KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK
59 namespace Impl {
60 template <typename Integral, bool Signed = std::is_signed<Integral>::value>
61 struct ArrayBoundsCheck;
62 
63 template <typename Integral>
64 struct ArrayBoundsCheck<Integral, true> {
65  KOKKOS_INLINE_FUNCTION
66  ArrayBoundsCheck(Integral i, size_t N) {
67  if (i < 0) {
68 #ifdef KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST
69  std::string s = "Kokkos::Array: index ";
70  s += std::to_string(i);
71  s += " < 0";
72  Kokkos::Impl::throw_runtime_exception(s);
73 #else
74  Kokkos::abort("Kokkos::Array: negative index in device code");
75 #endif
76  }
77  ArrayBoundsCheck<Integral, false>(i, N);
78  }
79 };
80 
81 template <typename Integral>
82 struct ArrayBoundsCheck<Integral, false> {
83  KOKKOS_INLINE_FUNCTION
84  ArrayBoundsCheck(Integral i, size_t N) {
85  if ( size_t(i) >= N) {
86 #ifdef KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST
87  std::string s = "Kokkos::Array: index ";
88  s += std::to_string(i);
89  s += " >= ";
90  s += std::to_string(N);
91  Kokkos::Impl::throw_runtime_exception(s);
92 #else
93  Kokkos::abort("Kokkos::Array: index >= size");
94 #endif
95  }
96  }
97 };
98 } // end namespace Impl
99 
100 #define KOKKOS_ARRAY_BOUNDS_CHECK(i, N) \
101  Kokkos::Impl::ArrayBoundsCheck<decltype(i)>(i, N)
102 
103 #else // !defined( KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK )
104 
105 #define KOKKOS_ARRAY_BOUNDS_CHECK(i, N) (void)0
106 
107 #endif // !defined( KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK )
108 
112 template< class T = void
113  , size_t N =KOKKOS_INVALID_INDEX
114  , class Proxy = void
115  >
116 struct Array {
117 public:
124  T m_internal_implementation_private_member_data[N];
125 public:
126 
127  typedef T & reference ;
128  typedef typename std::add_const<T>::type & const_reference ;
129  typedef size_t size_type ;
130  typedef ptrdiff_t difference_type ;
131  typedef T value_type ;
132  typedef T * pointer ;
133  typedef typename std::add_const<T>::type * const_pointer ;
134 
135  KOKKOS_INLINE_FUNCTION static constexpr size_type size() { return N ; }
136  KOKKOS_INLINE_FUNCTION static constexpr bool empty(){ return false ; }
137  KOKKOS_INLINE_FUNCTION constexpr size_type max_size() const { return N ; }
138 
139  template< typename iType >
140  KOKKOS_INLINE_FUNCTION
141  reference operator[]( const iType & i )
142  {
143  static_assert( ( std::is_integral<iType>::value || std::is_enum<iType>::value ) , "Must be integral argument" );
144  KOKKOS_ARRAY_BOUNDS_CHECK(i, N);
145  return m_internal_implementation_private_member_data[i];
146  }
147 
148  template< typename iType >
149  KOKKOS_INLINE_FUNCTION
150  const_reference operator[]( const iType & i ) const
151  {
152  static_assert( ( std::is_integral<iType>::value || std::is_enum<iType>::value ) , "Must be integral argument" );
153  KOKKOS_ARRAY_BOUNDS_CHECK(i, N);
154  return m_internal_implementation_private_member_data[i];
155  }
156 
157  KOKKOS_INLINE_FUNCTION pointer data()
158  {
159  return & m_internal_implementation_private_member_data[0];
160  }
161  KOKKOS_INLINE_FUNCTION const_pointer data() const
162  {
163  return & m_internal_implementation_private_member_data[0];
164  }
165 
166  #ifdef KOKKOS_IMPL_ROCM_CLANG_WORKAROUND
167  // Do not default unless move and move-assignment are also defined
168  KOKKOS_INLINE_FUNCTION
169  ~Array() = default ;
170  Array() = default ;
171  Array( const Array & ) = default ;
172  Array & operator = ( const Array & ) = default ;
173 
174  // Some supported compilers are not sufficiently C++11 compliant
175  // for default move constructor and move assignment operator.
176  Array( Array && ) = default ;
177  Array & operator = ( Array && ) = default ;
178 
179  KOKKOS_INLINE_FUNCTION
180  Array(const std::initializer_list<T>& vals) {
181  for(int i=0; i<N; i++) {
182  m_internal_implementation_private_member_data[i] = vals.begin()[i];
183  }
184  }
185  #endif
186 };
187 
188 
189 template< class T , class Proxy >
190 struct Array<T,0,Proxy> {
191 public:
192 
193  typedef typename std::add_const<T>::type & reference ;
194  typedef typename std::add_const<T>::type & const_reference ;
195  typedef size_t size_type ;
196  typedef ptrdiff_t difference_type ;
197  typedef typename std::add_const<T>::type value_type ;
198  typedef typename std::add_const<T>::type * pointer ;
199  typedef typename std::add_const<T>::type * const_pointer ;
200 
201  KOKKOS_INLINE_FUNCTION static constexpr size_type size() { return 0 ; }
202  KOKKOS_INLINE_FUNCTION static constexpr bool empty() { return true ; }
203  KOKKOS_INLINE_FUNCTION constexpr size_type max_size() const { return 0 ; }
204 
205  template< typename iType >
206  KOKKOS_INLINE_FUNCTION
207  value_type operator[]( const iType & )
208  {
209  static_assert( ( std::is_integral<iType>::value || std::is_enum<iType>::value ) , "Must be integer argument" );
210  return value_type();
211  }
212 
213  template< typename iType >
214  KOKKOS_INLINE_FUNCTION
215  value_type operator[]( const iType & ) const
216  {
217  static_assert( ( std::is_integral<iType>::value || std::is_enum<iType>::value ) , "Must be integer argument" );
218  return value_type();
219  }
220 
221  KOKKOS_INLINE_FUNCTION pointer data() { return pointer(0) ; }
222  KOKKOS_INLINE_FUNCTION const_pointer data() const { return const_pointer(0); }
223 
224 #ifdef KOKKOS_CUDA_9_DEFAULTED_BUG_WORKAROUND
225  KOKKOS_INLINE_FUNCTION ~Array() {}
226  KOKKOS_INLINE_FUNCTION Array() {}
227  KOKKOS_INLINE_FUNCTION Array( const Array & ) {}
228  KOKKOS_INLINE_FUNCTION Array & operator = ( const Array & ) {}
229 #else
230  KOKKOS_INLINE_FUNCTION ~Array() = default;
231  KOKKOS_INLINE_FUNCTION Array() = default;
232  KOKKOS_INLINE_FUNCTION Array( const Array & ) = default;
233  KOKKOS_INLINE_FUNCTION Array & operator = ( const Array & ) = default;
234 #endif
235 
236  // Some supported compilers are not sufficiently C++11 compliant
237  // for default move constructor and move assignment operator.
238  // Array( Array && ) = default ;
239  // Array & operator = ( Array && ) = default ;
240 };
241 
242 
243 template<>
244 struct Array<void,KOKKOS_INVALID_INDEX,void>
245 {
246  struct contiguous {};
247  struct strided {};
248 };
249 
250 template< class T >
251 struct Array< T ,KOKKOS_INVALID_INDEX , Array<>::contiguous >
252 {
253 private:
254  T * m_elem ;
255  size_t m_size ;
256 public:
257 
258  typedef T & reference ;
259  typedef typename std::add_const<T>::type & const_reference ;
260  typedef size_t size_type ;
261  typedef ptrdiff_t difference_type ;
262  typedef T value_type ;
263  typedef T * pointer ;
264  typedef typename std::add_const<T>::type * const_pointer ;
265 
266  KOKKOS_INLINE_FUNCTION constexpr size_type size() const { return m_size ; }
267  KOKKOS_INLINE_FUNCTION constexpr bool empty() const { return 0 != m_size ; }
268  KOKKOS_INLINE_FUNCTION constexpr size_type max_size() const { return m_size ; }
269 
270  template< typename iType >
271  KOKKOS_INLINE_FUNCTION
272  reference operator[]( const iType & i )
273  {
274  static_assert( ( std::is_integral<iType>::value || std::is_enum<iType>::value ) , "Must be integral argument" );
275  KOKKOS_ARRAY_BOUNDS_CHECK(i, m_size);
276  return m_elem[i];
277  }
278 
279  template< typename iType >
280  KOKKOS_INLINE_FUNCTION
281  const_reference operator[]( const iType & i ) const
282  {
283  static_assert( ( std::is_integral<iType>::value || std::is_enum<iType>::value ) , "Must be integral argument" );
284  KOKKOS_ARRAY_BOUNDS_CHECK(i, m_size);
285  return m_elem[i];
286  }
287 
288  KOKKOS_INLINE_FUNCTION pointer data() { return m_elem ; }
289  KOKKOS_INLINE_FUNCTION const_pointer data() const { return m_elem ; }
290 
291 #ifdef KOKKOS_CUDA_9_DEFAULTED_BUG_WORKAROUND
292  KOKKOS_INLINE_FUNCTION ~Array() {}
293 #else
294  KOKKOS_INLINE_FUNCTION ~Array() = default;
295 #endif
296  Array() = delete ;
297  Array( const Array & rhs ) = delete ;
298 
299  // Some supported compilers are not sufficiently C++11 compliant
300  // for default move constructor and move assignment operator.
301  // Array( Array && rhs ) = default ;
302  // Array & operator = ( Array && rhs ) = delete ;
303 
304  KOKKOS_INLINE_FUNCTION
305  Array & operator = ( const Array & rhs )
306  {
307  const size_t n = std::min( m_size , rhs.size() );
308  for ( size_t i = 0 ; i < n ; ++i ) m_elem[i] = rhs[i] ;
309  return *this ;
310  }
311 
312  template< size_t N , class P >
313  KOKKOS_INLINE_FUNCTION
314  Array & operator = ( const Array<T,N,P> & rhs )
315  {
316  const size_t n = std::min( m_size , rhs.size() );
317  for ( size_t i = 0 ; i < n ; ++i ) m_elem[i] = rhs[i] ;
318  return *this ;
319  }
320 
321  KOKKOS_INLINE_FUNCTION constexpr Array( pointer arg_ptr , size_type arg_size , size_type = 0 )
322  : m_elem(arg_ptr), m_size(arg_size) {}
323 };
324 
325 template< class T >
326 struct Array< T ,KOKKOS_INVALID_INDEX , Array<>::strided >
327 {
328 private:
329  T * m_elem ;
330  size_t m_size ;
331  size_t m_stride ;
332 public:
333 
334  typedef T & reference ;
335  typedef typename std::add_const<T>::type & const_reference ;
336  typedef size_t size_type ;
337  typedef ptrdiff_t difference_type ;
338  typedef T value_type ;
339  typedef T * pointer ;
340  typedef typename std::add_const<T>::type * const_pointer ;
341 
342  KOKKOS_INLINE_FUNCTION constexpr size_type size() const { return m_size ; }
343  KOKKOS_INLINE_FUNCTION constexpr bool empty() const { return 0 != m_size ; }
344  KOKKOS_INLINE_FUNCTION constexpr size_type max_size() const { return m_size ; }
345 
346  template< typename iType >
347  KOKKOS_INLINE_FUNCTION
348  reference operator[]( const iType & i )
349  {
350  static_assert( ( std::is_integral<iType>::value || std::is_enum<iType>::value ) , "Must be integral argument" );
351  KOKKOS_ARRAY_BOUNDS_CHECK(i, m_size);
352  return m_elem[i*m_stride];
353  }
354 
355  template< typename iType >
356  KOKKOS_INLINE_FUNCTION
357  const_reference operator[]( const iType & i ) const
358  {
359  static_assert( ( std::is_integral<iType>::value || std::is_enum<iType>::value ) , "Must be integral argument" );
360  KOKKOS_ARRAY_BOUNDS_CHECK(i, m_size);
361  return m_elem[i*m_stride];
362  }
363 
364  KOKKOS_INLINE_FUNCTION pointer data() { return m_elem ; }
365  KOKKOS_INLINE_FUNCTION const_pointer data() const { return m_elem ; }
366 
367 #ifdef KOKKOS_CUDA_9_DEFAULTED_BUG_WORKAROUND
368  KOKKOS_INLINE_FUNCTION ~Array() {}
369 #else
370  KOKKOS_INLINE_FUNCTION ~Array() = default;
371 #endif
372  Array() = delete ;
373  Array( const Array & ) = delete ;
374 
375 
376  // Some supported compilers are not sufficiently C++11 compliant
377  // for default move constructor and move assignment operator.
378  // Array( Array && rhs ) = default ;
379  // Array & operator = ( Array && rhs ) = delete ;
380 
381  KOKKOS_INLINE_FUNCTION
382  Array & operator = ( const Array & rhs )
383  {
384  const size_t n = std::min( m_size , rhs.size() );
385  for ( size_t i = 0 ; i < n ; ++i ) m_elem[i] = rhs[i] ;
386  return *this ;
387  }
388 
389  template< size_t N , class P >
390  KOKKOS_INLINE_FUNCTION
391  Array & operator = ( const Array<T,N,P> & rhs )
392  {
393  const size_t n = std::min( m_size , rhs.size() );
394  for ( size_t i = 0 ; i < n ; ++i ) m_elem[i] = rhs[i] ;
395  return *this ;
396  }
397 
398  KOKKOS_INLINE_FUNCTION constexpr Array( pointer arg_ptr , size_type arg_size , size_type arg_stride )
399  : m_elem(arg_ptr), m_size(arg_size), m_stride(arg_stride) {}
400 };
401 
402 } // namespace Kokkos
403 
404 #endif /* #ifndef KOKKOS_ARRAY_HPP */
405 
Derived from the C++17 &#39;std::array&#39;. Dropping the iterator interface.