Kokkos Core Kernels Package Version of the Day
Loading...
Searching...
No Matches
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
34namespace Kokkos {
35
36#ifdef KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK
37namespace Impl {
38template <typename Integral, bool Signed = std::is_signed_v<Integral>>
39struct ArrayBoundsCheck;
40
41template <typename Integral>
42struct 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
55template <typename Integral>
56struct 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
83template <class T = void, size_t N = KOKKOS_INVALID_INDEX, class Proxy = void>
84#else
85template <class T, size_t N>
86#endif
87struct 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
161template <class T, class Proxy>
162struct Array<T, 0, Proxy> {
163#else
164template <class T>
165struct 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 constexpr pointer data() { return nullptr; }
199 KOKKOS_INLINE_FUNCTION constexpr const_pointer data() const {
200 return nullptr;
201 }
202
203 friend KOKKOS_FUNCTION constexpr bool operator==(Array const&,
204 Array const&) noexcept {
205 return true;
206 }
207 friend KOKKOS_FUNCTION constexpr bool operator!=(Array const&,
208 Array const&) noexcept {
209 return false;
210 }
211
212 private:
213 friend KOKKOS_INLINE_FUNCTION constexpr void kokkos_swap(
214 Array<T, 0>&, Array<T, 0>&) noexcept {}
215};
216
217#ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
218namespace Impl {
219struct KokkosArrayContiguous {};
220struct KokkosArrayStrided {};
221} // namespace Impl
222
223template <>
224struct KOKKOS_DEPRECATED Array<void, KOKKOS_INVALID_INDEX, void> {
225 using contiguous = Impl::KokkosArrayContiguous;
226 using strided = Impl::KokkosArrayStrided;
227};
228
229template <class T>
230struct KOKKOS_DEPRECATED
231 Array<T, KOKKOS_INVALID_INDEX, Impl::KokkosArrayContiguous> {
232 private:
233 T* m_elem;
234 size_t m_size;
235
236 public:
237 using reference = T&;
238 using const_reference = std::add_const_t<T>&;
239 using size_type = size_t;
240 using difference_type = ptrdiff_t;
241 using value_type = T;
242 using pointer = T*;
243 using const_pointer = std::add_const_t<T>*;
244
245 KOKKOS_INLINE_FUNCTION constexpr size_type size() const { return m_size; }
246 KOKKOS_INLINE_FUNCTION constexpr bool empty() const { return 0 == m_size; }
247 KOKKOS_INLINE_FUNCTION constexpr size_type max_size() const { return m_size; }
248
249 template <typename iType>
250 KOKKOS_INLINE_FUNCTION reference operator[](const iType& i) {
251 static_assert(
252 (std::is_integral<iType>::value || std::is_enum<iType>::value),
253 "Must be integral argument");
254 KOKKOS_ARRAY_BOUNDS_CHECK(i, m_size);
255 return m_elem[i];
256 }
257
258 template <typename iType>
259 KOKKOS_INLINE_FUNCTION const_reference operator[](const iType& i) const {
260 static_assert(
261 (std::is_integral<iType>::value || std::is_enum<iType>::value),
262 "Must be integral argument");
263 KOKKOS_ARRAY_BOUNDS_CHECK(i, m_size);
264 return m_elem[i];
265 }
266
267 KOKKOS_INLINE_FUNCTION pointer data() { return m_elem; }
268 KOKKOS_INLINE_FUNCTION const_pointer data() const { return m_elem; }
269
270 KOKKOS_DEFAULTED_FUNCTION ~Array() = default;
271 KOKKOS_INLINE_FUNCTION_DELETED Array() = delete;
272 KOKKOS_INLINE_FUNCTION_DELETED Array(const Array& rhs) = delete;
273
274 // Some supported compilers are not sufficiently C++11 compliant
275 // for default move constructor and move assignment operator.
276 // Array( Array && rhs ) = default ;
277 // Array & operator = ( Array && rhs ) = delete ;
278
279 KOKKOS_INLINE_FUNCTION
280 Array& operator=(const Array& rhs) {
281 const size_t n = size() < rhs.size() ? size() : rhs.size();
282 for (size_t i = 0; i < n; ++i) m_elem[i] = rhs[i];
283 return *this;
284 }
285
286 template <size_t N, class P>
287 KOKKOS_INLINE_FUNCTION Array& operator=(const Array<T, N, P>& rhs) {
288 const size_t n = size() < rhs.size() ? size() : rhs.size();
289 for (size_t i = 0; i < n; ++i) m_elem[i] = rhs[i];
290 return *this;
291 }
292
293 KOKKOS_INLINE_FUNCTION constexpr Array(pointer arg_ptr, size_type arg_size,
294 size_type = 0)
295 : m_elem(arg_ptr), m_size(arg_size) {}
296};
297
298template <class T>
299struct KOKKOS_DEPRECATED
300 Array<T, KOKKOS_INVALID_INDEX, Impl::KokkosArrayStrided> {
301 private:
302 T* m_elem;
303 size_t m_size;
304 size_t m_stride;
305
306 public:
307 using reference = T&;
308 using const_reference = std::add_const_t<T>&;
309 using size_type = size_t;
310 using difference_type = ptrdiff_t;
311 using value_type = T;
312 using pointer = T*;
313 using const_pointer = std::add_const_t<T>*;
314
315 KOKKOS_INLINE_FUNCTION constexpr size_type size() const { return m_size; }
316 KOKKOS_INLINE_FUNCTION constexpr bool empty() const { return 0 == m_size; }
317 KOKKOS_INLINE_FUNCTION constexpr size_type max_size() const { return m_size; }
318
319 template <typename iType>
320 KOKKOS_INLINE_FUNCTION reference operator[](const iType& i) {
321 static_assert(
322 (std::is_integral<iType>::value || std::is_enum<iType>::value),
323 "Must be integral argument");
324 KOKKOS_ARRAY_BOUNDS_CHECK(i, m_size);
325 return m_elem[i * m_stride];
326 }
327
328 template <typename iType>
329 KOKKOS_INLINE_FUNCTION const_reference operator[](const iType& i) const {
330 static_assert(
331 (std::is_integral<iType>::value || std::is_enum<iType>::value),
332 "Must be integral argument");
333 KOKKOS_ARRAY_BOUNDS_CHECK(i, m_size);
334 return m_elem[i * m_stride];
335 }
336
337 KOKKOS_INLINE_FUNCTION pointer data() { return m_elem; }
338 KOKKOS_INLINE_FUNCTION const_pointer data() const { return m_elem; }
339
340 KOKKOS_DEFAULTED_FUNCTION ~Array() = default;
341 KOKKOS_INLINE_FUNCTION_DELETED Array() = delete;
342 KOKKOS_INLINE_FUNCTION_DELETED Array(const Array&) = delete;
343
344 // Some supported compilers are not sufficiently C++11 compliant
345 // for default move constructor and move assignment operator.
346 // Array( Array && rhs ) = default ;
347 // Array & operator = ( Array && rhs ) = delete ;
348
349 KOKKOS_INLINE_FUNCTION
350 Array& operator=(const Array& rhs) {
351 const size_t n = size() < rhs.size() ? size() : rhs.size();
352 for (size_t i = 0; i < n; ++i) m_elem[i * m_stride] = rhs[i];
353 return *this;
354 }
355
356 template <size_t N, class P>
357 KOKKOS_INLINE_FUNCTION Array& operator=(const Array<T, N, P>& rhs) {
358 const size_t n = size() < rhs.size() ? size() : rhs.size();
359 for (size_t i = 0; i < n; ++i) m_elem[i * m_stride] = rhs[i];
360 return *this;
361 }
362
363 KOKKOS_INLINE_FUNCTION constexpr Array(pointer arg_ptr, size_type arg_size,
364 size_type arg_stride)
365 : m_elem(arg_ptr), m_size(arg_size), m_stride(arg_stride) {}
366};
367#endif
368
369template <typename T, typename... Us>
370Array(T, Us...) -> Array<T, 1 + sizeof...(Us)>;
371
372namespace Impl {
373
374template <typename T, size_t N, size_t... I>
375KOKKOS_FUNCTION constexpr Array<std::remove_cv_t<T>, N> to_array_impl(
376 T (&a)[N], std::index_sequence<I...>) {
377 return {{a[I]...}};
378}
379
380template <typename T, size_t N, size_t... I>
381KOKKOS_FUNCTION constexpr Array<std::remove_cv_t<T>, N> to_array_impl(
382 T (&&a)[N], std::index_sequence<I...>) {
383 return {{std::move(a[I])...}};
384}
385
386} // namespace Impl
387
388template <typename T, size_t N>
389KOKKOS_FUNCTION constexpr auto to_array(T (&a)[N]) {
390 return Impl::to_array_impl(a, std::make_index_sequence<N>{});
391}
392
393template <typename T, size_t N>
394KOKKOS_FUNCTION constexpr auto to_array(T (&&a)[N]) {
395 return Impl::to_array_impl(std::move(a), std::make_index_sequence<N>{});
396}
397
398} // namespace Kokkos
399
400//<editor-fold desc="Support for structured binding">
401template <class T, std::size_t N>
402struct std::tuple_size<Kokkos::Array<T, N>>
403 : std::integral_constant<std::size_t, N> {};
404
405template <std::size_t I, class T, std::size_t N>
406struct std::tuple_element<I, Kokkos::Array<T, N>> {
407 static_assert(I < N);
408 using type = T;
409};
410
411namespace Kokkos {
412
413template <std::size_t I, class T, std::size_t N>
414KOKKOS_FUNCTION constexpr T& get(Array<T, N>& a) noexcept {
415 static_assert(I < N);
416 return a[I];
417}
418
419template <std::size_t I, class T, std::size_t N>
420KOKKOS_FUNCTION constexpr T const& get(Array<T, N> const& a) noexcept {
421 static_assert(I < N);
422 return a[I];
423}
424
425template <std::size_t I, class T, std::size_t N>
426KOKKOS_FUNCTION constexpr T&& get(Array<T, N>&& a) noexcept {
427 static_assert(I < N);
428 return std::move(a[I]);
429}
430
431template <std::size_t I, class T, std::size_t N>
432KOKKOS_FUNCTION constexpr T const&& get(Array<T, N> const&& a) noexcept {
433 static_assert(I < N);
434 return std::move(a[I]);
435}
436
437} // namespace Kokkos
438//</editor-fold>
439
440//<editor-fold desc="Support for range-based for loop">
441namespace Kokkos {
442
443template <class T, std::size_t N>
444KOKKOS_FUNCTION constexpr T const* begin(Array<T, N> const& a) noexcept {
445 return a.data();
446}
447
448template <class T, std::size_t N>
449KOKKOS_FUNCTION constexpr T* begin(Array<T, N>& a) noexcept {
450 return a.data();
451}
452
453template <class T, std::size_t N>
454KOKKOS_FUNCTION constexpr T const* end(Array<T, N> const& a) noexcept {
455 return a.data() + a.size();
456}
457
458template <class T, std::size_t N>
459KOKKOS_FUNCTION constexpr T* end(Array<T, N>& a) noexcept {
460 return a.data() + a.size();
461}
462
463} // namespace Kokkos
464//</editor-fold>
465
466#ifdef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_ARRAY
467#undef KOKKOS_IMPL_PUBLIC_INCLUDE
468#undef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_ARRAY
469#endif
470#endif /* #ifndef KOKKOS_ARRAY_HPP */
ScopeGuard Some user scope issues have been identified with some Kokkos::finalize calls; ScopeGuard a...
Derived from the C++17 'std::array'. Dropping the iterator interface.