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 <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
34namespace Kokkos {
35
36#ifdef KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK
37namespace Impl {
38template <typename Integral, bool Signed = std::is_signed<Integral>::value>
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
82template <class T = void, size_t N = KOKKOS_INVALID_INDEX, class Proxy = void>
83struct 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
133template <class T, class Proxy>
134struct 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
180template <>
181struct Array<void, KOKKOS_INVALID_INDEX, void> {
182 struct contiguous {};
183 struct strided {};
184};
185
186template <class T>
187struct 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
254template <class T>
255struct 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">
326template <class T, std::size_t N>
327struct std::tuple_size<Kokkos::Array<T, N>>
328 : std::integral_constant<std::size_t, N> {};
329
330template <std::size_t I, class T, std::size_t N>
331struct std::tuple_element<I, Kokkos::Array<T, N>> {
332 using type = T;
333};
334
335namespace Kokkos {
336
337template <std::size_t I, class T, std::size_t N>
338KOKKOS_FUNCTION constexpr T& get(Array<T, N>& a) noexcept {
339 return a[I];
340}
341
342template <std::size_t I, class T, std::size_t N>
343KOKKOS_FUNCTION constexpr T const& get(Array<T, N> const& a) noexcept {
344 return a[I];
345}
346
347template <std::size_t I, class T, std::size_t N>
348KOKKOS_FUNCTION constexpr T&& get(Array<T, N>&& a) noexcept {
349 return std::move(a[I]);
350}
351
352template <std::size_t I, class T, std::size_t N>
353KOKKOS_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 'std::array'. Dropping the iterator interface.