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 <limits>
33 #include <cstddef>
34 
35 namespace Kokkos {
36 
37 #ifdef KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK
38 namespace Impl {
39 template <typename Integral, bool Signed = std::is_signed<Integral>::value>
40 struct ArrayBoundsCheck;
41 
42 template <typename Integral>
43 struct ArrayBoundsCheck<Integral, true> {
44  KOKKOS_INLINE_FUNCTION
45  constexpr ArrayBoundsCheck(Integral i, size_t N) {
46  if (i < 0) {
47  char err[128] = "Kokkos::Array: index ";
48  to_chars_i(err + strlen(err), err + 128, i);
49  strcat(err, " < 0");
50  Kokkos::abort(err);
51  }
52  ArrayBoundsCheck<Integral, false>(i, N);
53  }
54 };
55 
56 template <typename Integral>
57 struct ArrayBoundsCheck<Integral, false> {
58  KOKKOS_INLINE_FUNCTION
59  constexpr ArrayBoundsCheck(Integral i, size_t N) {
60  if (size_t(i) >= N) {
61  char err[128] = "Kokkos::Array: index ";
62  to_chars_i(err + strlen(err), err + 128, i);
63  strcat(err, " >= ");
64  to_chars_i(err + strlen(err), err + 128, N);
65  Kokkos::abort(err);
66  }
67  }
68 };
69 } // end namespace Impl
70 
71 #define KOKKOS_ARRAY_BOUNDS_CHECK(i, N) \
72  Kokkos::Impl::ArrayBoundsCheck<decltype(i)>(i, N)
73 
74 #else // !defined( KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK )
75 
76 #define KOKKOS_ARRAY_BOUNDS_CHECK(i, N) (void)0
77 
78 #endif // !defined( KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK )
79 
83 template <class T = void, size_t N = KOKKOS_INVALID_INDEX, class Proxy = void>
84 struct Array {
85  public:
92  T m_internal_implementation_private_member_data[N];
93 
94  public:
95  using reference = T&;
96  using const_reference = std::add_const_t<T>&;
97  using size_type = size_t;
98  using difference_type = ptrdiff_t;
99  using value_type = T;
100  using pointer = T*;
101  using const_pointer = std::add_const_t<T>*;
102 
103  KOKKOS_INLINE_FUNCTION static constexpr size_type size() { return N; }
104  KOKKOS_INLINE_FUNCTION static constexpr bool empty() { return false; }
105  KOKKOS_INLINE_FUNCTION constexpr size_type max_size() const { return N; }
106 
107  template <typename iType>
108  KOKKOS_INLINE_FUNCTION constexpr reference operator[](const iType& i) {
109  static_assert(
110  (std::is_integral<iType>::value || std::is_enum<iType>::value),
111  "Must be integral argument");
112  KOKKOS_ARRAY_BOUNDS_CHECK(i, N);
113  return m_internal_implementation_private_member_data[i];
114  }
115 
116  template <typename iType>
117  KOKKOS_INLINE_FUNCTION constexpr const_reference operator[](
118  const iType& i) const {
119  static_assert(
120  (std::is_integral<iType>::value || std::is_enum<iType>::value),
121  "Must be integral argument");
122  KOKKOS_ARRAY_BOUNDS_CHECK(i, N);
123  return m_internal_implementation_private_member_data[i];
124  }
125 
126  KOKKOS_INLINE_FUNCTION constexpr pointer data() {
127  return &m_internal_implementation_private_member_data[0];
128  }
129  KOKKOS_INLINE_FUNCTION constexpr const_pointer data() const {
130  return &m_internal_implementation_private_member_data[0];
131  }
132 };
133 
134 template <class T, class Proxy>
135 struct Array<T, 0, Proxy> {
136  public:
137  using reference = T&;
138  using const_reference = std::add_const_t<T>&;
139  using size_type = size_t;
140  using difference_type = ptrdiff_t;
141  using value_type = T;
142  using pointer = T*;
143  using const_pointer = std::add_const_t<T>*;
144 
145  KOKKOS_INLINE_FUNCTION static constexpr size_type size() { return 0; }
146  KOKKOS_INLINE_FUNCTION static constexpr bool empty() { return true; }
147  KOKKOS_INLINE_FUNCTION constexpr size_type max_size() const { return 0; }
148 
149  template <typename iType>
150  KOKKOS_INLINE_FUNCTION reference operator[](const iType&) {
151  static_assert(
152  (std::is_integral<iType>::value || std::is_enum<iType>::value),
153  "Must be integer argument");
154  Kokkos::abort("Unreachable code");
155  return *reinterpret_cast<pointer>(-1);
156  }
157 
158  template <typename iType>
159  KOKKOS_INLINE_FUNCTION const_reference operator[](const iType&) const {
160  static_assert(
161  (std::is_integral<iType>::value || std::is_enum<iType>::value),
162  "Must be integer argument");
163  Kokkos::abort("Unreachable code");
164  return *reinterpret_cast<const_pointer>(-1);
165  }
166 
167  KOKKOS_INLINE_FUNCTION pointer data() { return nullptr; }
168  KOKKOS_INLINE_FUNCTION const_pointer data() const { return nullptr; }
169 
170  KOKKOS_DEFAULTED_FUNCTION ~Array() = default;
171  KOKKOS_DEFAULTED_FUNCTION Array() = default;
172  KOKKOS_DEFAULTED_FUNCTION Array(const Array&) = default;
173  KOKKOS_DEFAULTED_FUNCTION Array& operator=(const Array&) = default;
174 
175  // Some supported compilers are not sufficiently C++11 compliant
176  // for default move constructor and move assignment operator.
177  // Array( Array && ) = default ;
178  // Array & operator = ( Array && ) = default ;
179 };
180 
181 template <>
182 struct Array<void, KOKKOS_INVALID_INDEX, void> {
183  struct contiguous {};
184  struct strided {};
185 };
186 
187 template <class T>
188 struct Array<T, KOKKOS_INVALID_INDEX, Array<>::contiguous> {
189  private:
190  T* m_elem;
191  size_t m_size;
192 
193  public:
194  using reference = T&;
195  using const_reference = std::add_const_t<T>&;
196  using size_type = size_t;
197  using difference_type = ptrdiff_t;
198  using value_type = T;
199  using pointer = T*;
200  using const_pointer = std::add_const_t<T>*;
201 
202  KOKKOS_INLINE_FUNCTION constexpr size_type size() const { return m_size; }
203  KOKKOS_INLINE_FUNCTION constexpr bool empty() const { return 0 == m_size; }
204  KOKKOS_INLINE_FUNCTION constexpr size_type max_size() const { return m_size; }
205 
206  template <typename iType>
207  KOKKOS_INLINE_FUNCTION reference operator[](const iType& i) {
208  static_assert(
209  (std::is_integral<iType>::value || std::is_enum<iType>::value),
210  "Must be integral argument");
211  KOKKOS_ARRAY_BOUNDS_CHECK(i, m_size);
212  return m_elem[i];
213  }
214 
215  template <typename iType>
216  KOKKOS_INLINE_FUNCTION const_reference operator[](const iType& i) const {
217  static_assert(
218  (std::is_integral<iType>::value || std::is_enum<iType>::value),
219  "Must be integral argument");
220  KOKKOS_ARRAY_BOUNDS_CHECK(i, m_size);
221  return m_elem[i];
222  }
223 
224  KOKKOS_INLINE_FUNCTION pointer data() { return m_elem; }
225  KOKKOS_INLINE_FUNCTION const_pointer data() const { return m_elem; }
226 
227  KOKKOS_DEFAULTED_FUNCTION ~Array() = default;
228  KOKKOS_INLINE_FUNCTION_DELETED Array() = delete;
229  KOKKOS_INLINE_FUNCTION_DELETED Array(const Array& rhs) = delete;
230 
231  // Some supported compilers are not sufficiently C++11 compliant
232  // for default move constructor and move assignment operator.
233  // Array( Array && rhs ) = default ;
234  // Array & operator = ( Array && rhs ) = delete ;
235 
236  KOKKOS_INLINE_FUNCTION
237  Array& operator=(const Array& rhs) {
238  const size_t n = size() < rhs.size() ? size() : rhs.size();
239  for (size_t i = 0; i < n; ++i) m_elem[i] = rhs[i];
240  return *this;
241  }
242 
243  template <size_t N, class P>
244  KOKKOS_INLINE_FUNCTION Array& operator=(const Array<T, N, P>& rhs) {
245  const size_t n = size() < rhs.size() ? size() : rhs.size();
246  for (size_t i = 0; i < n; ++i) m_elem[i] = rhs[i];
247  return *this;
248  }
249 
250  KOKKOS_INLINE_FUNCTION constexpr Array(pointer arg_ptr, size_type arg_size,
251  size_type = 0)
252  : m_elem(arg_ptr), m_size(arg_size) {}
253 };
254 
255 template <class T>
256 struct Array<T, KOKKOS_INVALID_INDEX, Array<>::strided> {
257  private:
258  T* m_elem;
259  size_t m_size;
260  size_t m_stride;
261 
262  public:
263  using reference = T&;
264  using const_reference = std::add_const_t<T>&;
265  using size_type = size_t;
266  using difference_type = ptrdiff_t;
267  using value_type = T;
268  using pointer = T*;
269  using const_pointer = std::add_const_t<T>*;
270 
271  KOKKOS_INLINE_FUNCTION constexpr size_type size() const { return m_size; }
272  KOKKOS_INLINE_FUNCTION constexpr bool empty() const { return 0 == m_size; }
273  KOKKOS_INLINE_FUNCTION constexpr size_type max_size() const { return m_size; }
274 
275  template <typename iType>
276  KOKKOS_INLINE_FUNCTION reference operator[](const iType& i) {
277  static_assert(
278  (std::is_integral<iType>::value || std::is_enum<iType>::value),
279  "Must be integral argument");
280  KOKKOS_ARRAY_BOUNDS_CHECK(i, m_size);
281  return m_elem[i * m_stride];
282  }
283 
284  template <typename iType>
285  KOKKOS_INLINE_FUNCTION const_reference operator[](const iType& i) const {
286  static_assert(
287  (std::is_integral<iType>::value || std::is_enum<iType>::value),
288  "Must be integral argument");
289  KOKKOS_ARRAY_BOUNDS_CHECK(i, m_size);
290  return m_elem[i * m_stride];
291  }
292 
293  KOKKOS_INLINE_FUNCTION pointer data() { return m_elem; }
294  KOKKOS_INLINE_FUNCTION const_pointer data() const { return m_elem; }
295 
296  KOKKOS_DEFAULTED_FUNCTION ~Array() = default;
297  KOKKOS_INLINE_FUNCTION_DELETED Array() = delete;
298  KOKKOS_INLINE_FUNCTION_DELETED Array(const Array&) = delete;
299 
300  // Some supported compilers are not sufficiently C++11 compliant
301  // for default move constructor and move assignment operator.
302  // Array( Array && rhs ) = default ;
303  // Array & operator = ( Array && rhs ) = delete ;
304 
305  KOKKOS_INLINE_FUNCTION
306  Array& operator=(const Array& rhs) {
307  const size_t n = size() < rhs.size() ? size() : rhs.size();
308  for (size_t i = 0; i < n; ++i) m_elem[i * m_stride] = rhs[i];
309  return *this;
310  }
311 
312  template <size_t N, class P>
313  KOKKOS_INLINE_FUNCTION Array& operator=(const Array<T, N, P>& rhs) {
314  const size_t n = size() < rhs.size() ? size() : rhs.size();
315  for (size_t i = 0; i < n; ++i) m_elem[i * m_stride] = rhs[i];
316  return *this;
317  }
318 
319  KOKKOS_INLINE_FUNCTION constexpr Array(pointer arg_ptr, size_type arg_size,
320  size_type arg_stride)
321  : m_elem(arg_ptr), m_size(arg_size), m_stride(arg_stride) {}
322 };
323 
324 template <typename T, typename... Us>
325 Array(T, Us...)->Array<T, 1 + sizeof...(Us)>;
326 
327 } // namespace Kokkos
328 
329 //<editor-fold desc="Support for structured binding">
330 template <class T, std::size_t N>
331 struct std::tuple_size<Kokkos::Array<T, N>>
332  : std::integral_constant<std::size_t, N> {};
333 
334 template <std::size_t I, class T, std::size_t N>
335 struct std::tuple_element<I, Kokkos::Array<T, N>> {
336  using type = T;
337 };
338 
339 namespace Kokkos {
340 
341 template <std::size_t I, class T, std::size_t N>
342 KOKKOS_FUNCTION constexpr T& get(Array<T, N>& a) noexcept {
343  return a[I];
344 }
345 
346 template <std::size_t I, class T, std::size_t N>
347 KOKKOS_FUNCTION constexpr T const& get(Array<T, N> const& a) noexcept {
348  return a[I];
349 }
350 
351 template <std::size_t I, class T, std::size_t N>
352 KOKKOS_FUNCTION constexpr T&& get(Array<T, N>&& a) noexcept {
353  return std::move(a[I]);
354 }
355 
356 template <std::size_t I, class T, std::size_t N>
357 KOKKOS_FUNCTION constexpr T const&& get(Array<T, N> const&& a) noexcept {
358  return std::move(a[I]);
359 }
360 
361 } // namespace Kokkos
362 //</editor-fold>
363 
364 #ifdef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_ARRAY
365 #undef KOKKOS_IMPL_PUBLIC_INCLUDE
366 #undef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_ARRAY
367 #endif
368 #endif /* #ifndef KOKKOS_ARRAY_HPP */
Derived from the C++17 &#39;std::array&#39;. Dropping the iterator interface.