Kokkos Core Kernels Package  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Kokkos_Array.hpp
1 //@HEADER
2 // ************************************************************************
3 //
4 // Kokkos v. 4.0
5 // Copyright (2022) National Technology & Engineering
6 // Solutions of Sandia, LLC (NTESS).
7 //
8 // Under the terms of Contract DE-NA0003525 with NTESS,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions.
12 // See https://kokkos.org/LICENSE for license information.
13 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
14 //
15 //@HEADER
16 
17 #ifndef KOKKOS_ARRAY_HPP
18 #define KOKKOS_ARRAY_HPP
19 #ifndef KOKKOS_IMPL_PUBLIC_INCLUDE
20 #define KOKKOS_IMPL_PUBLIC_INCLUDE
21 #define KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_ARRAY
22 #endif
23 
24 #include <Kokkos_Macros.hpp>
25 #include <Kokkos_Swap.hpp>
26 #include <impl/Kokkos_Error.hpp>
27 #include <impl/Kokkos_StringManipulation.hpp>
28 
29 #include <type_traits>
30 #include <algorithm>
31 #include <utility>
32 #include <cstddef>
33 
34 namespace Kokkos {
35 
36 #ifdef KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK
37 namespace Impl {
38 template <typename Integral, bool Signed = std::is_signed<Integral>::value>
39 struct ArrayBoundsCheck;
40 
41 template <typename Integral>
42 struct ArrayBoundsCheck<Integral, true> {
43  KOKKOS_INLINE_FUNCTION
44  constexpr ArrayBoundsCheck(Integral i, size_t N) {
45  if (i < 0) {
46  char err[128] = "Kokkos::Array: index ";
47  to_chars_i(err + strlen(err), err + 128, i);
48  strcat(err, " < 0");
49  Kokkos::abort(err);
50  }
51  ArrayBoundsCheck<Integral, false>(i, N);
52  }
53 };
54 
55 template <typename Integral>
56 struct ArrayBoundsCheck<Integral, false> {
57  KOKKOS_INLINE_FUNCTION
58  constexpr ArrayBoundsCheck(Integral i, size_t N) {
59  if (size_t(i) >= N) {
60  char err[128] = "Kokkos::Array: index ";
61  to_chars_i(err + strlen(err), err + 128, i);
62  strcat(err, " >= ");
63  to_chars_i(err + strlen(err), err + 128, N);
64  Kokkos::abort(err);
65  }
66  }
67 };
68 } // end namespace Impl
69 
70 #define KOKKOS_ARRAY_BOUNDS_CHECK(i, N) \
71  Kokkos::Impl::ArrayBoundsCheck<decltype(i)>(i, N)
72 
73 #else // !defined( KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK )
74 
75 #define KOKKOS_ARRAY_BOUNDS_CHECK(i, N) (void)0
76 
77 #endif // !defined( KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK )
78 
82 #ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
83 template <class T = void, size_t N = KOKKOS_INVALID_INDEX, class Proxy = void>
84 #else
85 template <class T, size_t N>
86 #endif
87 struct Array {
88  public:
95  T m_internal_implementation_private_member_data[N];
96 
97  public:
98  using reference = T&;
99  using const_reference = std::add_const_t<T>&;
100  using size_type = size_t;
101  using difference_type = ptrdiff_t;
102  using value_type = T;
103  using pointer = T*;
104  using const_pointer = std::add_const_t<T>*;
105 
106  KOKKOS_INLINE_FUNCTION static constexpr size_type size() { return N; }
107  KOKKOS_INLINE_FUNCTION static constexpr bool empty() { return false; }
108  KOKKOS_INLINE_FUNCTION constexpr size_type max_size() const { return N; }
109 
110  template <typename iType>
111  KOKKOS_INLINE_FUNCTION constexpr reference operator[](const iType& i) {
112  static_assert(
113  (std::is_integral<iType>::value || std::is_enum<iType>::value),
114  "Must be integral argument");
115  KOKKOS_ARRAY_BOUNDS_CHECK(i, N);
116  return m_internal_implementation_private_member_data[i];
117  }
118 
119  template <typename iType>
120  KOKKOS_INLINE_FUNCTION constexpr const_reference operator[](
121  const iType& i) const {
122  static_assert(
123  (std::is_integral<iType>::value || std::is_enum<iType>::value),
124  "Must be integral argument");
125  KOKKOS_ARRAY_BOUNDS_CHECK(i, N);
126  return m_internal_implementation_private_member_data[i];
127  }
128 
129  KOKKOS_INLINE_FUNCTION constexpr pointer data() {
130  return &m_internal_implementation_private_member_data[0];
131  }
132  KOKKOS_INLINE_FUNCTION constexpr const_pointer data() const {
133  return &m_internal_implementation_private_member_data[0];
134  }
135 
136  friend KOKKOS_FUNCTION constexpr bool operator==(Array const& lhs,
137  Array const& rhs) noexcept {
138  for (size_t i = 0; i != N; ++i)
139  if (lhs[i] != rhs[i]) return false;
140  return true;
141  }
142 
143  friend KOKKOS_FUNCTION constexpr bool operator!=(Array const& lhs,
144  Array const& rhs) noexcept {
145  return !(lhs == rhs);
146  }
147 
148  private:
149  template <class U = T>
150  friend KOKKOS_INLINE_FUNCTION constexpr std::enable_if_t<
151  Impl::is_swappable<U>::value>
152  kokkos_swap(Array<T, N>& a,
153  Array<T, N>& b) noexcept(Impl::is_nothrow_swappable_v<U>) {
154  for (std::size_t i = 0; i < N; ++i) {
155  kokkos_swap(a[i], b[i]);
156  }
157  }
158 };
159 
160 #ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
161 template <class T, class Proxy>
162 struct Array<T, 0, Proxy> {
163 #else
164 template <class T>
165 struct Array<T, 0> {
166 #endif
167  public:
168  using reference = T&;
169  using const_reference = std::add_const_t<T>&;
170  using size_type = size_t;
171  using difference_type = ptrdiff_t;
172  using value_type = T;
173  using pointer = T*;
174  using const_pointer = std::add_const_t<T>*;
175 
176  KOKKOS_INLINE_FUNCTION static constexpr size_type size() { return 0; }
177  KOKKOS_INLINE_FUNCTION static constexpr bool empty() { return true; }
178  KOKKOS_INLINE_FUNCTION constexpr size_type max_size() const { return 0; }
179 
180  template <typename iType>
181  KOKKOS_INLINE_FUNCTION reference operator[](const iType&) {
182  static_assert(
183  (std::is_integral<iType>::value || std::is_enum<iType>::value),
184  "Must be integer argument");
185  Kokkos::abort("Unreachable code");
186  return *reinterpret_cast<pointer>(-1);
187  }
188 
189  template <typename iType>
190  KOKKOS_INLINE_FUNCTION const_reference operator[](const iType&) const {
191  static_assert(
192  (std::is_integral<iType>::value || std::is_enum<iType>::value),
193  "Must be integer argument");
194  Kokkos::abort("Unreachable code");
195  return *reinterpret_cast<const_pointer>(-1);
196  }
197 
198  KOKKOS_INLINE_FUNCTION pointer data() { return nullptr; }
199  KOKKOS_INLINE_FUNCTION const_pointer data() const { return nullptr; }
200 
201  friend KOKKOS_FUNCTION constexpr bool operator==(Array const&,
202  Array const&) noexcept {
203  return true;
204  }
205  friend KOKKOS_FUNCTION constexpr bool operator!=(Array const&,
206  Array const&) noexcept {
207  return false;
208  }
209 
210  private:
211  friend KOKKOS_INLINE_FUNCTION constexpr void kokkos_swap(
212  Array<T, 0>&, Array<T, 0>&) noexcept {}
213 };
214 
215 #ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
216 namespace Impl {
217 struct KokkosArrayContiguous {};
218 struct KokkosArrayStrided {};
219 } // namespace Impl
220 
221 template <>
222 struct KOKKOS_DEPRECATED Array<void, KOKKOS_INVALID_INDEX, void> {
223  using contiguous = Impl::KokkosArrayContiguous;
224  using strided = Impl::KokkosArrayStrided;
225 };
226 
227 template <class T>
228 struct KOKKOS_DEPRECATED
229  Array<T, KOKKOS_INVALID_INDEX, Impl::KokkosArrayContiguous> {
230  private:
231  T* m_elem;
232  size_t m_size;
233 
234  public:
235  using reference = T&;
236  using const_reference = std::add_const_t<T>&;
237  using size_type = size_t;
238  using difference_type = ptrdiff_t;
239  using value_type = T;
240  using pointer = T*;
241  using const_pointer = std::add_const_t<T>*;
242 
243  KOKKOS_INLINE_FUNCTION constexpr size_type size() const { return m_size; }
244  KOKKOS_INLINE_FUNCTION constexpr bool empty() const { return 0 == m_size; }
245  KOKKOS_INLINE_FUNCTION constexpr size_type max_size() const { return m_size; }
246 
247  template <typename iType>
248  KOKKOS_INLINE_FUNCTION reference operator[](const iType& i) {
249  static_assert(
250  (std::is_integral<iType>::value || std::is_enum<iType>::value),
251  "Must be integral argument");
252  KOKKOS_ARRAY_BOUNDS_CHECK(i, m_size);
253  return m_elem[i];
254  }
255 
256  template <typename iType>
257  KOKKOS_INLINE_FUNCTION const_reference operator[](const iType& i) const {
258  static_assert(
259  (std::is_integral<iType>::value || std::is_enum<iType>::value),
260  "Must be integral argument");
261  KOKKOS_ARRAY_BOUNDS_CHECK(i, m_size);
262  return m_elem[i];
263  }
264 
265  KOKKOS_INLINE_FUNCTION pointer data() { return m_elem; }
266  KOKKOS_INLINE_FUNCTION const_pointer data() const { return m_elem; }
267 
268  KOKKOS_DEFAULTED_FUNCTION ~Array() = default;
269  KOKKOS_INLINE_FUNCTION_DELETED Array() = delete;
270  KOKKOS_INLINE_FUNCTION_DELETED Array(const Array& rhs) = delete;
271 
272  // Some supported compilers are not sufficiently C++11 compliant
273  // for default move constructor and move assignment operator.
274  // Array( Array && rhs ) = default ;
275  // Array & operator = ( Array && rhs ) = delete ;
276 
277  KOKKOS_INLINE_FUNCTION
278  Array& operator=(const Array& rhs) {
279  const size_t n = size() < rhs.size() ? size() : rhs.size();
280  for (size_t i = 0; i < n; ++i) m_elem[i] = rhs[i];
281  return *this;
282  }
283 
284  template <size_t N, class P>
285  KOKKOS_INLINE_FUNCTION Array& operator=(const Array<T, N, P>& rhs) {
286  const size_t n = size() < rhs.size() ? size() : rhs.size();
287  for (size_t i = 0; i < n; ++i) m_elem[i] = rhs[i];
288  return *this;
289  }
290 
291  KOKKOS_INLINE_FUNCTION constexpr Array(pointer arg_ptr, size_type arg_size,
292  size_type = 0)
293  : m_elem(arg_ptr), m_size(arg_size) {}
294 };
295 
296 template <class T>
297 struct KOKKOS_DEPRECATED
298  Array<T, KOKKOS_INVALID_INDEX, Impl::KokkosArrayStrided> {
299  private:
300  T* m_elem;
301  size_t m_size;
302  size_t m_stride;
303 
304  public:
305  using reference = T&;
306  using const_reference = std::add_const_t<T>&;
307  using size_type = size_t;
308  using difference_type = ptrdiff_t;
309  using value_type = T;
310  using pointer = T*;
311  using const_pointer = std::add_const_t<T>*;
312 
313  KOKKOS_INLINE_FUNCTION constexpr size_type size() const { return m_size; }
314  KOKKOS_INLINE_FUNCTION constexpr bool empty() const { return 0 == m_size; }
315  KOKKOS_INLINE_FUNCTION constexpr size_type max_size() const { return m_size; }
316 
317  template <typename iType>
318  KOKKOS_INLINE_FUNCTION reference operator[](const iType& i) {
319  static_assert(
320  (std::is_integral<iType>::value || std::is_enum<iType>::value),
321  "Must be integral argument");
322  KOKKOS_ARRAY_BOUNDS_CHECK(i, m_size);
323  return m_elem[i * m_stride];
324  }
325 
326  template <typename iType>
327  KOKKOS_INLINE_FUNCTION const_reference operator[](const iType& i) const {
328  static_assert(
329  (std::is_integral<iType>::value || std::is_enum<iType>::value),
330  "Must be integral argument");
331  KOKKOS_ARRAY_BOUNDS_CHECK(i, m_size);
332  return m_elem[i * m_stride];
333  }
334 
335  KOKKOS_INLINE_FUNCTION pointer data() { return m_elem; }
336  KOKKOS_INLINE_FUNCTION const_pointer data() const { return m_elem; }
337 
338  KOKKOS_DEFAULTED_FUNCTION ~Array() = default;
339  KOKKOS_INLINE_FUNCTION_DELETED Array() = delete;
340  KOKKOS_INLINE_FUNCTION_DELETED Array(const Array&) = delete;
341 
342  // Some supported compilers are not sufficiently C++11 compliant
343  // for default move constructor and move assignment operator.
344  // Array( Array && rhs ) = default ;
345  // Array & operator = ( Array && rhs ) = delete ;
346 
347  KOKKOS_INLINE_FUNCTION
348  Array& operator=(const Array& rhs) {
349  const size_t n = size() < rhs.size() ? size() : rhs.size();
350  for (size_t i = 0; i < n; ++i) m_elem[i * m_stride] = rhs[i];
351  return *this;
352  }
353 
354  template <size_t N, class P>
355  KOKKOS_INLINE_FUNCTION Array& operator=(const Array<T, N, P>& rhs) {
356  const size_t n = size() < rhs.size() ? size() : rhs.size();
357  for (size_t i = 0; i < n; ++i) m_elem[i * m_stride] = rhs[i];
358  return *this;
359  }
360 
361  KOKKOS_INLINE_FUNCTION constexpr Array(pointer arg_ptr, size_type arg_size,
362  size_type arg_stride)
363  : m_elem(arg_ptr), m_size(arg_size), m_stride(arg_stride) {}
364 };
365 #endif
366 
367 template <typename T, typename... Us>
368 Array(T, Us...)->Array<T, 1 + sizeof...(Us)>;
369 
370 namespace Impl {
371 
372 template <typename T, size_t N, size_t... I>
373 KOKKOS_FUNCTION constexpr Array<std::remove_cv_t<T>, N> to_array_impl(
374  T (&a)[N], std::index_sequence<I...>) {
375  return {{a[I]...}};
376 }
377 
378 template <typename T, size_t N, size_t... I>
379 KOKKOS_FUNCTION constexpr Array<std::remove_cv_t<T>, N> to_array_impl(
380  T(&&a)[N], std::index_sequence<I...>) {
381  return {{std::move(a[I])...}};
382 }
383 
384 } // namespace Impl
385 
386 template <typename T, size_t N>
387 KOKKOS_FUNCTION constexpr auto to_array(T (&a)[N]) {
388  return Impl::to_array_impl(a, std::make_index_sequence<N>{});
389 }
390 
391 template <typename T, size_t N>
392 KOKKOS_FUNCTION constexpr auto to_array(T(&&a)[N]) {
393  return Impl::to_array_impl(std::move(a), std::make_index_sequence<N>{});
394 }
395 
396 } // namespace Kokkos
397 
398 //<editor-fold desc="Support for structured binding">
399 template <class T, std::size_t N>
400 struct std::tuple_size<Kokkos::Array<T, N>>
401  : std::integral_constant<std::size_t, N> {};
402 
403 template <std::size_t I, class T, std::size_t N>
404 struct std::tuple_element<I, Kokkos::Array<T, N>> {
405  static_assert(I < N);
406  using type = T;
407 };
408 
409 namespace Kokkos {
410 
411 template <std::size_t I, class T, std::size_t N>
412 KOKKOS_FUNCTION constexpr T& get(Array<T, N>& a) noexcept {
413  static_assert(I < N);
414  return a[I];
415 }
416 
417 template <std::size_t I, class T, std::size_t N>
418 KOKKOS_FUNCTION constexpr T const& get(Array<T, N> const& a) noexcept {
419  static_assert(I < N);
420  return a[I];
421 }
422 
423 template <std::size_t I, class T, std::size_t N>
424 KOKKOS_FUNCTION constexpr T&& get(Array<T, N>&& a) noexcept {
425  static_assert(I < N);
426  return std::move(a[I]);
427 }
428 
429 template <std::size_t I, class T, std::size_t N>
430 KOKKOS_FUNCTION constexpr T const&& get(Array<T, N> const&& a) noexcept {
431  static_assert(I < N);
432  return std::move(a[I]);
433 }
434 
435 } // namespace Kokkos
436 //</editor-fold>
437 
438 #ifdef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_ARRAY
439 #undef KOKKOS_IMPL_PUBLIC_INCLUDE
440 #undef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_ARRAY
441 #endif
442 #endif /* #ifndef KOKKOS_ARRAY_HPP */
Derived from the C++17 &#39;std::array&#39;. Dropping the iterator interface.