Kokkos Core Kernels Package Version of the Day
Kokkos_Array.hpp
1/*
2//@HEADER
3// ************************************************************************
4//
5// Kokkos v. 3.0
6// Copyright (2020) National Technology & Engineering
7// Solutions of Sandia, LLC (NTESS).
8//
9// Under the terms of Contract DE-NA0003525 with NTESS,
10// the U.S. Government retains certain rights in this software.
11//
12// Redistribution and use in source and binary forms, with or without
13// modification, are permitted provided that the following conditions are
14// met:
15//
16// 1. Redistributions of source code must retain the above copyright
17// notice, this list of conditions and the following disclaimer.
18//
19// 2. Redistributions in binary form must reproduce the above copyright
20// notice, this list of conditions and the following disclaimer in the
21// documentation and/or other materials provided with the distribution.
22//
23// 3. Neither the name of the Corporation nor the names of the
24// contributors may be used to endorse or promote products derived from
25// this software without specific prior written permission.
26//
27// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
28// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
31// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
32// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
33// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
35// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
36// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38//
39// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
40//
41// ************************************************************************
42//@HEADER
43*/
44
45#ifndef KOKKOS_ARRAY_HPP
46#define KOKKOS_ARRAY_HPP
47
48#include <Kokkos_Macros.hpp>
49#include <impl/Kokkos_Error.hpp>
50
51#include <type_traits>
52#include <algorithm>
53#include <limits>
54#include <cstddef>
55#include <string>
56
57namespace Kokkos {
58
59#ifdef KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK
60namespace Impl {
61template <typename Integral, bool Signed = std::is_signed<Integral>::value>
62struct ArrayBoundsCheck;
63
64template <typename Integral>
65struct ArrayBoundsCheck<Integral, true> {
66 KOKKOS_INLINE_FUNCTION
67 ArrayBoundsCheck(Integral i, size_t N) {
68 if (i < 0) {
69#ifdef KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST
70 std::string s = "Kokkos::Array: index ";
71 s += std::to_string(i);
72 s += " < 0";
73 Kokkos::Impl::throw_runtime_exception(s);
74#else
75 Kokkos::abort("Kokkos::Array: negative index in device code");
76#endif
77 }
78 ArrayBoundsCheck<Integral, false>(i, N);
79 }
80};
81
82template <typename Integral>
83struct ArrayBoundsCheck<Integral, false> {
84 KOKKOS_INLINE_FUNCTION
85 ArrayBoundsCheck(Integral i, size_t N) {
86 if (size_t(i) >= N) {
87#ifdef KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST
88 std::string s = "Kokkos::Array: index ";
89 s += std::to_string(i);
90 s += " >= ";
91 s += std::to_string(N);
92 Kokkos::Impl::throw_runtime_exception(s);
93#else
94 Kokkos::abort("Kokkos::Array: index >= size");
95#endif
96 }
97 }
98};
99} // end namespace Impl
100
101#define KOKKOS_ARRAY_BOUNDS_CHECK(i, N) \
102 Kokkos::Impl::ArrayBoundsCheck<decltype(i)>(i, N)
103
104#else // !defined( KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK )
105
106#define KOKKOS_ARRAY_BOUNDS_CHECK(i, N) (void)0
107
108#endif // !defined( KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK )
109
113template <class T = void, size_t N = KOKKOS_INVALID_INDEX, class Proxy = void>
114struct Array {
115 public:
122 T m_internal_implementation_private_member_data[N];
123
124 public:
125 using reference = T&;
126 using const_reference = typename std::add_const<T>::type&;
127 using size_type = size_t;
128 using difference_type = ptrdiff_t;
129 using value_type = T;
130 using pointer = T*;
131 using const_pointer = typename std::add_const<T>::type*;
132
133 KOKKOS_INLINE_FUNCTION static constexpr size_type size() { return N; }
134 KOKKOS_INLINE_FUNCTION static constexpr bool empty() { return false; }
135 KOKKOS_INLINE_FUNCTION constexpr size_type max_size() const { return N; }
136
137 template <typename iType>
138 KOKKOS_INLINE_FUNCTION reference operator[](const iType& i) {
139 static_assert(
140 (std::is_integral<iType>::value || std::is_enum<iType>::value),
141 "Must be integral argument");
142 KOKKOS_ARRAY_BOUNDS_CHECK(i, N);
143 return m_internal_implementation_private_member_data[i];
144 }
145
146 template <typename iType>
147 KOKKOS_INLINE_FUNCTION const_reference operator[](const iType& i) const {
148 static_assert(
149 (std::is_integral<iType>::value || std::is_enum<iType>::value),
150 "Must be integral argument");
151 KOKKOS_ARRAY_BOUNDS_CHECK(i, N);
152 return m_internal_implementation_private_member_data[i];
153 }
154
155 KOKKOS_INLINE_FUNCTION pointer data() {
156 return &m_internal_implementation_private_member_data[0];
157 }
158 KOKKOS_INLINE_FUNCTION const_pointer data() const {
159 return &m_internal_implementation_private_member_data[0];
160 }
161};
162
163template <class T, class Proxy>
164struct Array<T, 0, Proxy> {
165 public:
166 using reference = T&;
167 using const_reference = typename std::add_const<T>::type&;
168 using size_type = size_t;
169 using difference_type = ptrdiff_t;
170 using value_type = T;
171 using pointer = T*;
172 using const_pointer = typename std::add_const<T>::type*;
173
174 KOKKOS_INLINE_FUNCTION static constexpr size_type size() { return 0; }
175 KOKKOS_INLINE_FUNCTION static constexpr bool empty() { return true; }
176 KOKKOS_INLINE_FUNCTION constexpr size_type max_size() const { return 0; }
177
178 template <typename iType>
179 KOKKOS_INLINE_FUNCTION reference operator[](const iType&) {
180 static_assert(
181 (std::is_integral<iType>::value || std::is_enum<iType>::value),
182 "Must be integer argument");
183 Kokkos::abort("Unreachable code");
184 return *reinterpret_cast<pointer>(-1);
185 }
186
187 template <typename iType>
188 KOKKOS_INLINE_FUNCTION const_reference operator[](const iType&) const {
189 static_assert(
190 (std::is_integral<iType>::value || std::is_enum<iType>::value),
191 "Must be integer argument");
192 Kokkos::abort("Unreachable code");
193 return *reinterpret_cast<const_pointer>(-1);
194 }
195
196 KOKKOS_INLINE_FUNCTION pointer data() { return pointer(0); }
197 KOKKOS_INLINE_FUNCTION const_pointer data() const { return const_pointer(0); }
198
199 KOKKOS_DEFAULTED_FUNCTION ~Array() = default;
200 KOKKOS_DEFAULTED_FUNCTION Array() = default;
201 KOKKOS_DEFAULTED_FUNCTION Array(const Array&) = default;
202 KOKKOS_DEFAULTED_FUNCTION Array& operator=(const Array&) = default;
203
204 // Some supported compilers are not sufficiently C++11 compliant
205 // for default move constructor and move assignment operator.
206 // Array( Array && ) = default ;
207 // Array & operator = ( Array && ) = default ;
208};
209
210template <>
211struct Array<void, KOKKOS_INVALID_INDEX, void> {
212 struct contiguous {};
213 struct strided {};
214};
215
216template <class T>
217struct Array<T, KOKKOS_INVALID_INDEX, Array<>::contiguous> {
218 private:
219 T* m_elem;
220 size_t m_size;
221
222 public:
223 using reference = T&;
224 using const_reference = typename std::add_const<T>::type&;
225 using size_type = size_t;
226 using difference_type = ptrdiff_t;
227 using value_type = T;
228 using pointer = T*;
229 using const_pointer = typename std::add_const<T>::type*;
230
231 KOKKOS_INLINE_FUNCTION constexpr size_type size() const { return m_size; }
232 KOKKOS_INLINE_FUNCTION constexpr bool empty() const { return 0 != m_size; }
233 KOKKOS_INLINE_FUNCTION constexpr size_type max_size() const { return m_size; }
234
235 template <typename iType>
236 KOKKOS_INLINE_FUNCTION reference operator[](const iType& i) {
237 static_assert(
238 (std::is_integral<iType>::value || std::is_enum<iType>::value),
239 "Must be integral argument");
240 KOKKOS_ARRAY_BOUNDS_CHECK(i, m_size);
241 return m_elem[i];
242 }
243
244 template <typename iType>
245 KOKKOS_INLINE_FUNCTION const_reference operator[](const iType& i) const {
246 static_assert(
247 (std::is_integral<iType>::value || std::is_enum<iType>::value),
248 "Must be integral argument");
249 KOKKOS_ARRAY_BOUNDS_CHECK(i, m_size);
250 return m_elem[i];
251 }
252
253 KOKKOS_INLINE_FUNCTION pointer data() { return m_elem; }
254 KOKKOS_INLINE_FUNCTION const_pointer data() const { return m_elem; }
255
256 KOKKOS_DEFAULTED_FUNCTION ~Array() = default;
257 KOKKOS_INLINE_FUNCTION_DELETED Array() = delete;
258 KOKKOS_INLINE_FUNCTION_DELETED Array(const Array& rhs) = delete;
259
260 // Some supported compilers are not sufficiently C++11 compliant
261 // for default move constructor and move assignment operator.
262 // Array( Array && rhs ) = default ;
263 // Array & operator = ( Array && rhs ) = delete ;
264
265 KOKKOS_INLINE_FUNCTION
266 Array& operator=(const Array& rhs) {
267 const size_t n = std::min(m_size, rhs.size());
268 for (size_t i = 0; i < n; ++i) m_elem[i] = rhs[i];
269 return *this;
270 }
271
272 template <size_t N, class P>
273 KOKKOS_INLINE_FUNCTION Array& operator=(const Array<T, N, P>& rhs) {
274 const size_t n = std::min(m_size, rhs.size());
275 for (size_t i = 0; i < n; ++i) m_elem[i] = rhs[i];
276 return *this;
277 }
278
279 KOKKOS_INLINE_FUNCTION constexpr Array(pointer arg_ptr, size_type arg_size,
280 size_type = 0)
281 : m_elem(arg_ptr), m_size(arg_size) {}
282};
283
284template <class T>
285struct Array<T, KOKKOS_INVALID_INDEX, Array<>::strided> {
286 private:
287 T* m_elem;
288 size_t m_size;
289 size_t m_stride;
290
291 public:
292 using reference = T&;
293 using const_reference = typename std::add_const<T>::type&;
294 using size_type = size_t;
295 using difference_type = ptrdiff_t;
296 using value_type = T;
297 using pointer = T*;
298 using const_pointer = typename std::add_const<T>::type*;
299
300 KOKKOS_INLINE_FUNCTION constexpr size_type size() const { return m_size; }
301 KOKKOS_INLINE_FUNCTION constexpr bool empty() const { return 0 != m_size; }
302 KOKKOS_INLINE_FUNCTION constexpr size_type max_size() const { return m_size; }
303
304 template <typename iType>
305 KOKKOS_INLINE_FUNCTION reference operator[](const iType& i) {
306 static_assert(
307 (std::is_integral<iType>::value || std::is_enum<iType>::value),
308 "Must be integral argument");
309 KOKKOS_ARRAY_BOUNDS_CHECK(i, m_size);
310 return m_elem[i * m_stride];
311 }
312
313 template <typename iType>
314 KOKKOS_INLINE_FUNCTION const_reference operator[](const iType& i) const {
315 static_assert(
316 (std::is_integral<iType>::value || std::is_enum<iType>::value),
317 "Must be integral argument");
318 KOKKOS_ARRAY_BOUNDS_CHECK(i, m_size);
319 return m_elem[i * m_stride];
320 }
321
322 KOKKOS_INLINE_FUNCTION pointer data() { return m_elem; }
323 KOKKOS_INLINE_FUNCTION const_pointer data() const { return m_elem; }
324
325 KOKKOS_DEFAULTED_FUNCTION ~Array() = default;
326 KOKKOS_INLINE_FUNCTION_DELETED Array() = delete;
327 KOKKOS_INLINE_FUNCTION_DELETED Array(const Array&) = delete;
328
329 // Some supported compilers are not sufficiently C++11 compliant
330 // for default move constructor and move assignment operator.
331 // Array( Array && rhs ) = default ;
332 // Array & operator = ( Array && rhs ) = delete ;
333
334 KOKKOS_INLINE_FUNCTION
335 Array& operator=(const Array& rhs) {
336 const size_t n = std::min(m_size, rhs.size());
337 for (size_t i = 0; i < n; ++i) m_elem[i] = rhs[i];
338 return *this;
339 }
340
341 template <size_t N, class P>
342 KOKKOS_INLINE_FUNCTION Array& operator=(const Array<T, N, P>& rhs) {
343 const size_t n = std::min(m_size, rhs.size());
344 for (size_t i = 0; i < n; ++i) m_elem[i] = rhs[i];
345 return *this;
346 }
347
348 KOKKOS_INLINE_FUNCTION constexpr Array(pointer arg_ptr, size_type arg_size,
349 size_type arg_stride)
350 : m_elem(arg_ptr), m_size(arg_size), m_stride(arg_stride) {}
351};
352
353} // namespace Kokkos
354
355#endif /* #ifndef KOKKOS_ARRAY_HPP */
Derived from the C++17 'std::array'. Dropping the iterator interface.