Kokkos Core Kernels Package  Version of the Day
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 <impl/Kokkos_Error.hpp>
26 #include <impl/Kokkos_StringManipulation.hpp>
27 
28 #include <type_traits>
29 #include <algorithm>
30 #include <utility>
31 #include <limits>
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 template <class T = void, size_t N = KOKKOS_INVALID_INDEX, class Proxy = void>
83 struct Array {
84  public:
91  T m_internal_implementation_private_member_data[N];
92 
93  public:
94  using reference = T&;
95  using const_reference = std::add_const_t<T>&;
96  using size_type = size_t;
97  using difference_type = ptrdiff_t;
98  using value_type = T;
99  using pointer = T*;
100  using const_pointer = std::add_const_t<T>*;
101 
102  KOKKOS_INLINE_FUNCTION static constexpr size_type size() { return N; }
103  KOKKOS_INLINE_FUNCTION static constexpr bool empty() { return false; }
104  KOKKOS_INLINE_FUNCTION constexpr size_type max_size() const { return N; }
105 
106  template <typename iType>
107  KOKKOS_INLINE_FUNCTION constexpr reference operator[](const iType& i) {
108  static_assert(
109  (std::is_integral<iType>::value || std::is_enum<iType>::value),
110  "Must be integral argument");
111  KOKKOS_ARRAY_BOUNDS_CHECK(i, N);
112  return m_internal_implementation_private_member_data[i];
113  }
114 
115  template <typename iType>
116  KOKKOS_INLINE_FUNCTION constexpr const_reference operator[](
117  const iType& i) const {
118  static_assert(
119  (std::is_integral<iType>::value || std::is_enum<iType>::value),
120  "Must be integral argument");
121  KOKKOS_ARRAY_BOUNDS_CHECK(i, N);
122  return m_internal_implementation_private_member_data[i];
123  }
124 
125  KOKKOS_INLINE_FUNCTION constexpr pointer data() {
126  return &m_internal_implementation_private_member_data[0];
127  }
128  KOKKOS_INLINE_FUNCTION constexpr const_pointer data() const {
129  return &m_internal_implementation_private_member_data[0];
130  }
131 };
132 
133 template <class T, class Proxy>
134 struct Array<T, 0, Proxy> {
135  public:
136  using reference = T&;
137  using const_reference = std::add_const_t<T>&;
138  using size_type = size_t;
139  using difference_type = ptrdiff_t;
140  using value_type = T;
141  using pointer = T*;
142  using const_pointer = std::add_const_t<T>*;
143 
144  KOKKOS_INLINE_FUNCTION static constexpr size_type size() { return 0; }
145  KOKKOS_INLINE_FUNCTION static constexpr bool empty() { return true; }
146  KOKKOS_INLINE_FUNCTION constexpr size_type max_size() const { return 0; }
147 
148  template <typename iType>
149  KOKKOS_INLINE_FUNCTION reference operator[](const iType&) {
150  static_assert(
151  (std::is_integral<iType>::value || std::is_enum<iType>::value),
152  "Must be integer argument");
153  Kokkos::abort("Unreachable code");
154  return *reinterpret_cast<pointer>(-1);
155  }
156 
157  template <typename iType>
158  KOKKOS_INLINE_FUNCTION const_reference operator[](const iType&) const {
159  static_assert(
160  (std::is_integral<iType>::value || std::is_enum<iType>::value),
161  "Must be integer argument");
162  Kokkos::abort("Unreachable code");
163  return *reinterpret_cast<const_pointer>(-1);
164  }
165 
166  KOKKOS_INLINE_FUNCTION pointer data() { return pointer(0); }
167  KOKKOS_INLINE_FUNCTION const_pointer data() const { return const_pointer(0); }
168 
169  KOKKOS_DEFAULTED_FUNCTION ~Array() = default;
170  KOKKOS_DEFAULTED_FUNCTION Array() = default;
171  KOKKOS_DEFAULTED_FUNCTION Array(const Array&) = default;
172  KOKKOS_DEFAULTED_FUNCTION 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 
180 template <>
181 struct Array<void, KOKKOS_INVALID_INDEX, void> {
182  struct contiguous {};
183  struct strided {};
184 };
185 
186 template <class T>
187 struct Array<T, KOKKOS_INVALID_INDEX, Array<>::contiguous> {
188  private:
189  T* m_elem;
190  size_t m_size;
191 
192  public:
193  using reference = T&;
194  using const_reference = std::add_const_t<T>&;
195  using size_type = size_t;
196  using difference_type = ptrdiff_t;
197  using value_type = T;
198  using pointer = T*;
199  using const_pointer = std::add_const_t<T>*;
200 
201  KOKKOS_INLINE_FUNCTION constexpr size_type size() const { return m_size; }
202  KOKKOS_INLINE_FUNCTION constexpr bool empty() const { return 0 != m_size; }
203  KOKKOS_INLINE_FUNCTION constexpr size_type max_size() const { return m_size; }
204 
205  template <typename iType>
206  KOKKOS_INLINE_FUNCTION reference operator[](const iType& i) {
207  static_assert(
208  (std::is_integral<iType>::value || std::is_enum<iType>::value),
209  "Must be integral argument");
210  KOKKOS_ARRAY_BOUNDS_CHECK(i, m_size);
211  return m_elem[i];
212  }
213 
214  template <typename iType>
215  KOKKOS_INLINE_FUNCTION const_reference operator[](const iType& i) const {
216  static_assert(
217  (std::is_integral<iType>::value || std::is_enum<iType>::value),
218  "Must be integral argument");
219  KOKKOS_ARRAY_BOUNDS_CHECK(i, m_size);
220  return m_elem[i];
221  }
222 
223  KOKKOS_INLINE_FUNCTION pointer data() { return m_elem; }
224  KOKKOS_INLINE_FUNCTION const_pointer data() const { return m_elem; }
225 
226  KOKKOS_DEFAULTED_FUNCTION ~Array() = default;
227  KOKKOS_INLINE_FUNCTION_DELETED Array() = delete;
228  KOKKOS_INLINE_FUNCTION_DELETED Array(const Array& rhs) = delete;
229 
230  // Some supported compilers are not sufficiently C++11 compliant
231  // for default move constructor and move assignment operator.
232  // Array( Array && rhs ) = default ;
233  // Array & operator = ( Array && rhs ) = delete ;
234 
235  KOKKOS_INLINE_FUNCTION
236  Array& operator=(const Array& rhs) {
237  const size_t n = std::min(m_size, rhs.size());
238  for (size_t i = 0; i < n; ++i) m_elem[i] = rhs[i];
239  return *this;
240  }
241 
242  template <size_t N, class P>
243  KOKKOS_INLINE_FUNCTION Array& operator=(const Array<T, N, P>& rhs) {
244  const size_t n = std::min(m_size, rhs.size());
245  for (size_t i = 0; i < n; ++i) m_elem[i] = rhs[i];
246  return *this;
247  }
248 
249  KOKKOS_INLINE_FUNCTION constexpr Array(pointer arg_ptr, size_type arg_size,
250  size_type = 0)
251  : m_elem(arg_ptr), m_size(arg_size) {}
252 };
253 
254 template <class T>
255 struct Array<T, KOKKOS_INVALID_INDEX, Array<>::strided> {
256  private:
257  T* m_elem;
258  size_t m_size;
259  size_t m_stride;
260 
261  public:
262  using reference = T&;
263  using const_reference = std::add_const_t<T>&;
264  using size_type = size_t;
265  using difference_type = ptrdiff_t;
266  using value_type = T;
267  using pointer = T*;
268  using const_pointer = std::add_const_t<T>*;
269 
270  KOKKOS_INLINE_FUNCTION constexpr size_type size() const { return m_size; }
271  KOKKOS_INLINE_FUNCTION constexpr bool empty() const { return 0 != m_size; }
272  KOKKOS_INLINE_FUNCTION constexpr size_type max_size() const { return m_size; }
273 
274  template <typename iType>
275  KOKKOS_INLINE_FUNCTION reference operator[](const iType& i) {
276  static_assert(
277  (std::is_integral<iType>::value || std::is_enum<iType>::value),
278  "Must be integral argument");
279  KOKKOS_ARRAY_BOUNDS_CHECK(i, m_size);
280  return m_elem[i * m_stride];
281  }
282 
283  template <typename iType>
284  KOKKOS_INLINE_FUNCTION const_reference operator[](const iType& i) const {
285  static_assert(
286  (std::is_integral<iType>::value || std::is_enum<iType>::value),
287  "Must be integral argument");
288  KOKKOS_ARRAY_BOUNDS_CHECK(i, m_size);
289  return m_elem[i * m_stride];
290  }
291 
292  KOKKOS_INLINE_FUNCTION pointer data() { return m_elem; }
293  KOKKOS_INLINE_FUNCTION const_pointer data() const { return m_elem; }
294 
295  KOKKOS_DEFAULTED_FUNCTION ~Array() = default;
296  KOKKOS_INLINE_FUNCTION_DELETED Array() = delete;
297  KOKKOS_INLINE_FUNCTION_DELETED Array(const Array&) = 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  const size_t n = std::min(m_size, rhs.size());
307  for (size_t i = 0; i < n; ++i) m_elem[i] = rhs[i];
308  return *this;
309  }
310 
311  template <size_t N, class P>
312  KOKKOS_INLINE_FUNCTION Array& operator=(const Array<T, N, P>& rhs) {
313  const size_t n = std::min(m_size, rhs.size());
314  for (size_t i = 0; i < n; ++i) m_elem[i] = rhs[i];
315  return *this;
316  }
317 
318  KOKKOS_INLINE_FUNCTION constexpr Array(pointer arg_ptr, size_type arg_size,
319  size_type arg_stride)
320  : m_elem(arg_ptr), m_size(arg_size), m_stride(arg_stride) {}
321 };
322 
323 } // namespace Kokkos
324 
325 //<editor-fold desc="Support for structured binding">
326 template <class T, std::size_t N>
327 struct std::tuple_size<Kokkos::Array<T, N>>
328  : std::integral_constant<std::size_t, N> {};
329 
330 template <std::size_t I, class T, std::size_t N>
331 struct std::tuple_element<I, Kokkos::Array<T, N>> {
332  using type = T;
333 };
334 
335 namespace Kokkos {
336 
337 template <std::size_t I, class T, std::size_t N>
338 KOKKOS_FUNCTION constexpr T& get(Array<T, N>& a) noexcept {
339  return a[I];
340 }
341 
342 template <std::size_t I, class T, std::size_t N>
343 KOKKOS_FUNCTION constexpr T const& get(Array<T, N> const& a) noexcept {
344  return a[I];
345 }
346 
347 template <std::size_t I, class T, std::size_t N>
348 KOKKOS_FUNCTION constexpr T&& get(Array<T, N>&& a) noexcept {
349  return std::move(a[I]);
350 }
351 
352 template <std::size_t I, class T, std::size_t N>
353 KOKKOS_FUNCTION constexpr T const&& get(Array<T, N> const&& a) noexcept {
354  return std::move(a[I]);
355 }
356 
357 } // namespace Kokkos
358 //</editor-fold>
359 
360 #ifdef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_ARRAY
361 #undef KOKKOS_IMPL_PUBLIC_INCLUDE
362 #undef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_ARRAY
363 #endif
364 #endif /* #ifndef KOKKOS_ARRAY_HPP */
Derived from the C++17 &#39;std::array&#39;. Dropping the iterator interface.
Definition: dummy.cpp:17