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