Kokkos Core Kernels Package Version of the Day
Loading...
Searching...
No Matches
Kokkos_OffsetView.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_OFFSETVIEW_HPP_
18#define KOKKOS_OFFSETVIEW_HPP_
19#ifndef KOKKOS_IMPL_PUBLIC_INCLUDE
20#define KOKKOS_IMPL_PUBLIC_INCLUDE
21#define KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_OFFSETVIEW
22#endif
23
24#include <Kokkos_Core.hpp>
25
26#include <Kokkos_View.hpp>
27
28namespace Kokkos {
29
30namespace Experimental {
31//----------------------------------------------------------------------------
32//----------------------------------------------------------------------------
33
34template <class DataType, class... Properties>
35class OffsetView;
36
37template <class>
38struct is_offset_view : public std::false_type {};
39
40template <class D, class... P>
41struct is_offset_view<OffsetView<D, P...>> : public std::true_type {};
42
43template <class D, class... P>
44struct is_offset_view<const OffsetView<D, P...>> : public std::true_type {};
45
46template <class T>
47inline constexpr bool is_offset_view_v = is_offset_view<T>::value;
48
49#define KOKKOS_INVALID_OFFSET int64_t(0x7FFFFFFFFFFFFFFFLL)
50#define KOKKOS_INVALID_INDEX_RANGE \
51 { KOKKOS_INVALID_OFFSET, KOKKOS_INVALID_OFFSET }
52
53template <typename iType, std::enable_if_t<std::is_integral<iType>::value &&
54 std::is_signed<iType>::value,
55 iType> = 0>
56using IndexRange = Kokkos::Array<iType, 2>;
57
58using index_list_type = std::initializer_list<int64_t>;
59
60// template <typename iType,
61// std::enable_if_t< std::is_integral<iType>::value &&
62// std::is_signed<iType>::value, iType > = 0> using min_index_type =
63// std::initializer_list<iType>;
64
65namespace Impl {
66
67template <class ViewType>
68struct GetOffsetViewTypeFromViewType {
69 using type =
70 OffsetView<typename ViewType::data_type, typename ViewType::array_layout,
71 typename ViewType::device_type,
72 typename ViewType::memory_traits>;
73};
74
75template <unsigned, class MapType, class BeginsType>
76KOKKOS_INLINE_FUNCTION bool offsetview_verify_operator_bounds(
77 const MapType&, const BeginsType&) {
78 return true;
79}
80
81template <unsigned R, class MapType, class BeginsType, class iType,
82 class... Args>
83KOKKOS_INLINE_FUNCTION bool offsetview_verify_operator_bounds(
84 const MapType& map, const BeginsType& begins, const iType& i,
85 Args... args) {
86 const bool legalIndex =
87 (int64_t(i) >= begins[R]) &&
88 (int64_t(i) <= int64_t(begins[R] + map.extent(R) - 1));
89 return legalIndex &&
90 offsetview_verify_operator_bounds<R + 1>(map, begins, args...);
91}
92template <unsigned, class MapType, class BeginsType>
93inline void offsetview_error_operator_bounds(char*, int, const MapType&,
94 const BeginsType&) {}
95
96template <unsigned R, class MapType, class BeginsType, class iType,
97 class... Args>
98inline void offsetview_error_operator_bounds(char* buf, int len,
99 const MapType& map,
100 const BeginsType begins,
101 const iType& i, Args... args) {
102 const int64_t b = begins[R];
103 const int64_t e = b + map.extent(R) - 1;
104 const int n =
105 snprintf(buf, len, " %ld <= %ld <= %ld %c", static_cast<unsigned long>(b),
106 static_cast<unsigned long>(i), static_cast<unsigned long>(e),
107 (sizeof...(Args) ? ',' : ')'));
108 offsetview_error_operator_bounds<R + 1>(buf + n, len - n, map, begins,
109 args...);
110}
111
112template <class MemorySpace, class MapType, class BeginsType, class... Args>
113KOKKOS_INLINE_FUNCTION void offsetview_verify_operator_bounds(
114 Kokkos::Impl::SharedAllocationTracker const& tracker, const MapType& map,
115 const BeginsType& begins, Args... args) {
116 if (!offsetview_verify_operator_bounds<0>(map, begins, args...)) {
117 KOKKOS_IF_ON_HOST(
118 (enum {LEN = 1024}; char buffer[LEN];
119 const std::string label = tracker.template get_label<MemorySpace>();
120 int n = snprintf(buffer, LEN,
121 "OffsetView bounds error of view labeled %s (",
122 label.c_str());
123 offsetview_error_operator_bounds<0>(buffer + n, LEN - n, map, begins,
124 args...);
125 Kokkos::Impl::throw_runtime_exception(std::string(buffer));))
126
127 KOKKOS_IF_ON_DEVICE((
128 /* Check #1: is there a SharedAllocationRecord?
129 (we won't use it, but if it is not there then there isn't
130 a corresponding SharedAllocationHeader containing a label).
131 This check should cover the case of Views that don't
132 have the Unmanaged trait but were initialized by pointer. */
133 if (tracker.has_record()) {
134 Kokkos::Impl::operator_bounds_error_on_device(map);
135 } else { Kokkos::abort("OffsetView bounds error"); }))
136 }
137}
138
139inline void runtime_check_rank_host(const size_t rank_dynamic,
140 const size_t rank,
141 const index_list_type minIndices,
142 const std::string& label) {
143 bool isBad = false;
144 std::string message =
145 "Kokkos::Experimental::OffsetView ERROR: for OffsetView labeled '" +
146 label + "':";
147 if (rank_dynamic != rank) {
148 message +=
149 "The full rank must be the same as the dynamic rank. full rank = ";
150 message += std::to_string(rank) +
151 " dynamic rank = " + std::to_string(rank_dynamic) + "\n";
152 isBad = true;
153 }
154
155 size_t numOffsets = 0;
156 for (size_t i = 0; i < minIndices.size(); ++i) {
157 if (minIndices.begin()[i] != KOKKOS_INVALID_OFFSET) numOffsets++;
158 }
159 if (numOffsets != rank_dynamic) {
160 message += "The number of offsets provided ( " +
161 std::to_string(numOffsets) +
162 " ) must equal the dynamic rank ( " +
163 std::to_string(rank_dynamic) + " ).";
164 isBad = true;
165 }
166
167 if (isBad) Kokkos::abort(message.c_str());
168}
169
170KOKKOS_INLINE_FUNCTION
171void runtime_check_rank_device(const size_t rank_dynamic, const size_t rank,
172 const index_list_type minIndices) {
173 if (rank_dynamic != rank) {
174 Kokkos::abort(
175 "The full rank of an OffsetView must be the same as the dynamic rank.");
176 }
177 size_t numOffsets = 0;
178 for (size_t i = 0; i < minIndices.size(); ++i) {
179 if (minIndices.begin()[i] != KOKKOS_INVALID_OFFSET) numOffsets++;
180 }
181 if (numOffsets != rank) {
182 Kokkos::abort(
183 "The number of offsets provided to an OffsetView constructor must "
184 "equal the dynamic rank.");
185 }
186}
187} // namespace Impl
188
189template <class DataType, class... Properties>
190class OffsetView : public ViewTraits<DataType, Properties...> {
191 public:
192 using traits = ViewTraits<DataType, Properties...>;
193
194 private:
195 template <class, class...>
196 friend class OffsetView;
197 template <class, class...>
198 friend class View; // FIXME delete this line
199 template <class, class...>
200 friend class Kokkos::Impl::ViewMapping;
201
202 using map_type = Kokkos::Impl::ViewMapping<traits, void>;
203 using track_type = Kokkos::Impl::SharedAllocationTracker;
204
205 public:
206 enum { Rank = map_type::Rank };
207 using begins_type = Kokkos::Array<int64_t, Rank>;
208
209 template <typename iType,
210 std::enable_if_t<std::is_integral<iType>::value, iType> = 0>
211 KOKKOS_FUNCTION int64_t begin(const iType local_dimension) const {
212 return local_dimension < Rank ? m_begins[local_dimension]
213 : KOKKOS_INVALID_OFFSET;
214 }
215
216 KOKKOS_FUNCTION
217 begins_type begins() const { return m_begins; }
218
219 template <typename iType,
220 std::enable_if_t<std::is_integral<iType>::value, iType> = 0>
221 KOKKOS_FUNCTION int64_t end(const iType local_dimension) const {
222 return begin(local_dimension) + m_map.extent(local_dimension);
223 }
224
225 private:
226 track_type m_track;
227 map_type m_map;
228 begins_type m_begins;
229
230 public:
231 //----------------------------------------
233 using array_type =
234 OffsetView<typename traits::scalar_array_type,
235 typename traits::array_layout, typename traits::device_type,
236 typename traits::memory_traits>;
237
239 using const_type =
240 OffsetView<typename traits::const_data_type,
241 typename traits::array_layout, typename traits::device_type,
242 typename traits::memory_traits>;
243
245 using non_const_type =
246 OffsetView<typename traits::non_const_data_type,
247 typename traits::array_layout, typename traits::device_type,
248 typename traits::memory_traits>;
249
251 using HostMirror = OffsetView<typename traits::non_const_data_type,
252 typename traits::array_layout,
253 typename traits::host_mirror_space>;
254
255 //----------------------------------------
256 // Domain rank and extents
257
260 // KOKKOS_FUNCTION
261 // static
262 // constexpr unsigned rank() { return map_type::Rank; }
263
264 template <typename iType>
265 KOKKOS_FUNCTION constexpr std::enable_if_t<std::is_integral<iType>::value,
266 size_t>
267 extent(const iType& r) const {
268 return m_map.extent(r);
269 }
270
271 template <typename iType>
272 KOKKOS_FUNCTION constexpr std::enable_if_t<std::is_integral<iType>::value,
273 int>
274 extent_int(const iType& r) const {
275 return static_cast<int>(m_map.extent(r));
276 }
277
278 KOKKOS_FUNCTION constexpr typename traits::array_layout layout() const {
279 return m_map.layout();
280 }
281
282 KOKKOS_FUNCTION constexpr size_t size() const {
283 return m_map.dimension_0() * m_map.dimension_1() * m_map.dimension_2() *
284 m_map.dimension_3() * m_map.dimension_4() * m_map.dimension_5() *
285 m_map.dimension_6() * m_map.dimension_7();
286 }
287
288 KOKKOS_FUNCTION constexpr size_t stride_0() const { return m_map.stride_0(); }
289 KOKKOS_FUNCTION constexpr size_t stride_1() const { return m_map.stride_1(); }
290 KOKKOS_FUNCTION constexpr size_t stride_2() const { return m_map.stride_2(); }
291 KOKKOS_FUNCTION constexpr size_t stride_3() const { return m_map.stride_3(); }
292 KOKKOS_FUNCTION constexpr size_t stride_4() const { return m_map.stride_4(); }
293 KOKKOS_FUNCTION constexpr size_t stride_5() const { return m_map.stride_5(); }
294 KOKKOS_FUNCTION constexpr size_t stride_6() const { return m_map.stride_6(); }
295 KOKKOS_FUNCTION constexpr size_t stride_7() const { return m_map.stride_7(); }
296
297 template <typename iType>
298 KOKKOS_FUNCTION constexpr std::enable_if_t<std::is_integral<iType>::value,
299 size_t>
300 stride(iType r) const {
301 return (
302 r == 0
303 ? m_map.stride_0()
304 : (r == 1
305 ? m_map.stride_1()
306 : (r == 2
307 ? m_map.stride_2()
308 : (r == 3
309 ? m_map.stride_3()
310 : (r == 4
311 ? m_map.stride_4()
312 : (r == 5
313 ? m_map.stride_5()
314 : (r == 6
315 ? m_map.stride_6()
316 : m_map.stride_7())))))));
317 }
318
319 template <typename iType>
320 KOKKOS_FUNCTION void stride(iType* const s) const {
321 m_map.stride(s);
322 }
323
324 //----------------------------------------
325 // Range span is the span which contains all members.
326
327 using reference_type = typename map_type::reference_type;
328 using pointer_type = typename map_type::pointer_type;
329
330 enum {
331 reference_type_is_lvalue_reference =
332 std::is_lvalue_reference<reference_type>::value
333 };
334
335 KOKKOS_FUNCTION constexpr size_t span() const { return m_map.span(); }
336 KOKKOS_FUNCTION bool span_is_contiguous() const {
337 return m_map.span_is_contiguous();
338 }
339 KOKKOS_FUNCTION constexpr bool is_allocated() const {
340 return m_map.data() != nullptr;
341 }
342 KOKKOS_FUNCTION constexpr pointer_type data() const { return m_map.data(); }
343
344 //----------------------------------------
345 // Allow specializations to query their specialized map
346
347 KOKKOS_FUNCTION
348 const Kokkos::Impl::ViewMapping<traits, void>& implementation_map() const {
349 return m_map;
350 }
351
352 //----------------------------------------
353
354 private:
355 static constexpr bool is_layout_left =
356 std::is_same<typename traits::array_layout, Kokkos::LayoutLeft>::value;
357
358 static constexpr bool is_layout_right =
359 std::is_same<typename traits::array_layout, Kokkos::LayoutRight>::value;
360
361 static constexpr bool is_layout_stride =
362 std::is_same<typename traits::array_layout, Kokkos::LayoutStride>::value;
363
364 static constexpr bool is_default_map =
365 std::is_void<typename traits::specialize>::value &&
366 (is_layout_left || is_layout_right || is_layout_stride);
367
368#if defined(KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK)
369
370#define KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY(ARG) \
371 Kokkos::Impl::runtime_check_memory_access_violation< \
372 typename traits::memory_space>( \
373 "Kokkos::OffsetView ERROR: attempt to access inaccessible memory " \
374 "space"); \
375 Kokkos::Experimental::Impl::offsetview_verify_operator_bounds< \
376 typename traits::memory_space> \
377 ARG;
378
379#else
380
381#define KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY(ARG) \
382 Kokkos::Impl::runtime_check_memory_access_violation< \
383 typename traits::memory_space>( \
384 "Kokkos::OffsetView ERROR: attempt to access inaccessible memory " \
385 "space");
386
387#endif
388 public:
389 //------------------------------
390 // Rank 0 operator()
391
392 KOKKOS_FORCEINLINE_FUNCTION
393 reference_type operator()() const { return m_map.reference(); }
394 //------------------------------
395 // Rank 1 operator()
396
397 template <typename I0>
398 KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
399 (Kokkos::Impl::are_integral<I0>::value && (1 == Rank) && !is_default_map),
400 reference_type>
401 operator()(const I0& i0) const {
402 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY((m_track, m_map, m_begins, i0))
403 const size_t j0 = i0 - m_begins[0];
404 return m_map.reference(j0);
405 }
406
407 template <typename I0>
408 KOKKOS_FORCEINLINE_FUNCTION
409 std::enable_if_t<(Kokkos::Impl::are_integral<I0>::value && (1 == Rank) &&
410 is_default_map && !is_layout_stride),
411 reference_type>
412 operator()(const I0& i0) const {
413 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY((m_track, m_map, m_begins, i0))
414 const size_t j0 = i0 - m_begins[0];
415 return m_map.m_impl_handle[j0];
416 }
417
418 template <typename I0>
419 KOKKOS_FORCEINLINE_FUNCTION
420 std::enable_if_t<(Kokkos::Impl::are_integral<I0>::value && (1 == Rank) &&
421 is_default_map && is_layout_stride),
422 reference_type>
423 operator()(const I0& i0) const {
424 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY((m_track, m_map, m_begins, i0))
425 const size_t j0 = i0 - m_begins[0];
426 return m_map.m_impl_handle[m_map.m_impl_offset.m_stride.S0 * j0];
427 }
428 //------------------------------
429 // Rank 1 operator[]
430
431 template <typename I0>
432 KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
433 (Kokkos::Impl::are_integral<I0>::value && (1 == Rank) && !is_default_map),
434 reference_type>
435 operator[](const I0& i0) const {
436 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY((m_track, m_map, m_begins, i0))
437 const size_t j0 = i0 - m_begins[0];
438 return m_map.reference(j0);
439 }
440
441 template <typename I0>
442 KOKKOS_FORCEINLINE_FUNCTION
443 std::enable_if_t<(Kokkos::Impl::are_integral<I0>::value && (1 == Rank) &&
444 is_default_map && !is_layout_stride),
445 reference_type>
446 operator[](const I0& i0) const {
447 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY((m_track, m_map, m_begins, i0))
448 const size_t j0 = i0 - m_begins[0];
449 return m_map.m_impl_handle[j0];
450 }
451
452 template <typename I0>
453 KOKKOS_FORCEINLINE_FUNCTION
454 std::enable_if_t<(Kokkos::Impl::are_integral<I0>::value && (1 == Rank) &&
455 is_default_map && is_layout_stride),
456 reference_type>
457 operator[](const I0& i0) const {
458 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY((m_track, m_map, m_begins, i0))
459 const size_t j0 = i0 - m_begins[0];
460 return m_map.m_impl_handle[m_map.m_impl_offset.m_stride.S0 * j0];
461 }
462
463 //------------------------------
464 // Rank 2
465
466 template <typename I0, typename I1>
467 KOKKOS_FORCEINLINE_FUNCTION
468 std::enable_if_t<(Kokkos::Impl::are_integral<I0, I1>::value &&
469 (2 == Rank) && !is_default_map),
470 reference_type>
471 operator()(const I0& i0, const I1& i1) const {
472 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY((m_track, m_map, m_begins, i0, i1))
473 const size_t j0 = i0 - m_begins[0];
474 const size_t j1 = i1 - m_begins[1];
475 return m_map.reference(j0, j1);
476 }
477
478 template <typename I0, typename I1>
479 KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
480 (Kokkos::Impl::are_integral<I0, I1>::value && (2 == Rank) &&
481 is_default_map && is_layout_left && (traits::rank_dynamic == 0)),
482 reference_type>
483 operator()(const I0& i0, const I1& i1) const {
484 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY((m_track, m_map, m_begins, i0, i1))
485 const size_t j0 = i0 - m_begins[0];
486 const size_t j1 = i1 - m_begins[1];
487 return m_map.m_impl_handle[j0 + m_map.m_impl_offset.m_dim.N0 * j1];
488 }
489
490 template <typename I0, typename I1>
491 KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
492 (Kokkos::Impl::are_integral<I0, I1>::value && (2 == Rank) &&
493 is_default_map && is_layout_left && (traits::rank_dynamic != 0)),
494 reference_type>
495 operator()(const I0& i0, const I1& i1) const {
496 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY((m_track, m_map, m_begins, i0, i1))
497 const size_t j0 = i0 - m_begins[0];
498 const size_t j1 = i1 - m_begins[1];
499 return m_map.m_impl_handle[j0 + m_map.m_impl_offset.m_stride * j1];
500 }
501
502 template <typename I0, typename I1>
503 KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
504 (Kokkos::Impl::are_integral<I0, I1>::value && (2 == Rank) &&
505 is_default_map && is_layout_right && (traits::rank_dynamic == 0)),
506 reference_type>
507 operator()(const I0& i0, const I1& i1) const {
508 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY((m_track, m_map, m_begins, i0, i1))
509 const size_t j0 = i0 - m_begins[0];
510 const size_t j1 = i1 - m_begins[1];
511 return m_map.m_impl_handle[j1 + m_map.m_impl_offset.m_dim.N1 * j0];
512 }
513
514 template <typename I0, typename I1>
515 KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
516 (Kokkos::Impl::are_integral<I0, I1>::value && (2 == Rank) &&
517 is_default_map && is_layout_right && (traits::rank_dynamic != 0)),
518 reference_type>
519 operator()(const I0& i0, const I1& i1) const {
520 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY((m_track, m_map, m_begins, i0, i1))
521 const size_t j0 = i0 - m_begins[0];
522 const size_t j1 = i1 - m_begins[1];
523 return m_map.m_impl_handle[j1 + m_map.m_impl_offset.m_stride * j0];
524 }
525
526 template <typename I0, typename I1>
527 KOKKOS_FORCEINLINE_FUNCTION
528 std::enable_if_t<(Kokkos::Impl::are_integral<I0, I1>::value &&
529 (2 == Rank) && is_default_map && is_layout_stride),
530 reference_type>
531 operator()(const I0& i0, const I1& i1) const {
532 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY((m_track, m_map, m_begins, i0, i1))
533 const size_t j0 = i0 - m_begins[0];
534 const size_t j1 = i1 - m_begins[1];
535 return m_map.m_impl_handle[j0 * m_map.m_impl_offset.m_stride.S0 +
536 j1 * m_map.m_impl_offset.m_stride.S1];
537 }
538
539 //------------------------------
540 // Rank 3
541
542 template <typename I0, typename I1, typename I2>
543 KOKKOS_FORCEINLINE_FUNCTION
544 std::enable_if_t<(Kokkos::Impl::are_integral<I0, I1, I2>::value &&
545 (3 == Rank) && is_default_map),
546 reference_type>
547 operator()(const I0& i0, const I1& i1, const I2& i2) const {
548 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY(
549 (m_track, m_map, m_begins, i0, i1, i2))
550 const size_t j0 = i0 - m_begins[0];
551 const size_t j1 = i1 - m_begins[1];
552 const size_t j2 = i2 - m_begins[2];
553 return m_map.m_impl_handle[m_map.m_impl_offset(j0, j1, j2)];
554 }
555
556 template <typename I0, typename I1, typename I2>
557 KOKKOS_FORCEINLINE_FUNCTION
558 std::enable_if_t<(Kokkos::Impl::are_integral<I0, I1, I2>::value &&
559 (3 == Rank) && !is_default_map),
560 reference_type>
561 operator()(const I0& i0, const I1& i1, const I2& i2) const {
562 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY(
563 (m_track, m_map, m_begins, i0, i1, i2))
564 const size_t j0 = i0 - m_begins[0];
565 const size_t j1 = i1 - m_begins[1];
566 const size_t j2 = i2 - m_begins[2];
567 return m_map.reference(j0, j1, j2);
568 }
569
570 //------------------------------
571 // Rank 4
572
573 template <typename I0, typename I1, typename I2, typename I3>
574 KOKKOS_FORCEINLINE_FUNCTION
575 std::enable_if_t<(Kokkos::Impl::are_integral<I0, I1, I2, I3>::value &&
576 (4 == Rank) && is_default_map),
577 reference_type>
578 operator()(const I0& i0, const I1& i1, const I2& i2, const I3& i3) const {
579 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY(
580 (m_track, m_map, m_begins, i0, i1, i2, i3))
581 const size_t j0 = i0 - m_begins[0];
582 const size_t j1 = i1 - m_begins[1];
583 const size_t j2 = i2 - m_begins[2];
584 const size_t j3 = i3 - m_begins[3];
585 return m_map.m_impl_handle[m_map.m_impl_offset(j0, j1, j2, j3)];
586 }
587
588 template <typename I0, typename I1, typename I2, typename I3>
589 KOKKOS_FORCEINLINE_FUNCTION
590 std::enable_if_t<(Kokkos::Impl::are_integral<I0, I1, I2, I3>::value &&
591 (4 == Rank) && !is_default_map),
592 reference_type>
593 operator()(const I0& i0, const I1& i1, const I2& i2, const I3& i3) const {
594 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY(
595 (m_track, m_map, m_begins, i0, i1, i2, i3))
596 const size_t j0 = i0 - m_begins[0];
597 const size_t j1 = i1 - m_begins[1];
598 const size_t j2 = i2 - m_begins[2];
599 const size_t j3 = i3 - m_begins[3];
600 return m_map.reference(j0, j1, j2, j3);
601 }
602
603 //------------------------------
604 // Rank 5
605
606 template <typename I0, typename I1, typename I2, typename I3, typename I4>
607 KOKKOS_FORCEINLINE_FUNCTION
608 std::enable_if_t<(Kokkos::Impl::are_integral<I0, I1, I2, I3, I4>::value &&
609 (5 == Rank) && is_default_map),
610 reference_type>
611 operator()(const I0& i0, const I1& i1, const I2& i2, const I3& i3,
612 const I4& i4) const {
613 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY(
614 (m_track, m_map, m_begins, i0, i1, i2, i3, i4))
615 const size_t j0 = i0 - m_begins[0];
616 const size_t j1 = i1 - m_begins[1];
617 const size_t j2 = i2 - m_begins[2];
618 const size_t j3 = i3 - m_begins[3];
619 const size_t j4 = i4 - m_begins[4];
620 return m_map.m_impl_handle[m_map.m_impl_offset(j0, j1, j2, j3, j4)];
621 }
622
623 template <typename I0, typename I1, typename I2, typename I3, typename I4>
624 KOKKOS_FORCEINLINE_FUNCTION
625 std::enable_if_t<(Kokkos::Impl::are_integral<I0, I1, I2, I3, I4>::value &&
626 (5 == Rank) && !is_default_map),
627 reference_type>
628 operator()(const I0& i0, const I1& i1, const I2& i2, const I3& i3,
629 const I4& i4) const {
630 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY(
631 (m_track, m_map, m_begins, i0, i1, i2, i3, i4))
632 const size_t j0 = i0 - m_begins[0];
633 const size_t j1 = i1 - m_begins[1];
634 const size_t j2 = i2 - m_begins[2];
635 const size_t j3 = i3 - m_begins[3];
636 const size_t j4 = i4 - m_begins[4];
637 return m_map.reference(j0, j1, j2, j3, j4);
638 }
639
640 //------------------------------
641 // Rank 6
642
643 template <typename I0, typename I1, typename I2, typename I3, typename I4,
644 typename I5>
645 KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
646 (Kokkos::Impl::are_integral<I0, I1, I2, I3, I4, I5>::value &&
647 (6 == Rank) && is_default_map),
648 reference_type>
649 operator()(const I0& i0, const I1& i1, const I2& i2, const I3& i3,
650 const I4& i4, const I5& i5) const {
651 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY(
652 (m_track, m_map, m_begins, i0, i1, i2, i3, i4, i5))
653 const size_t j0 = i0 - m_begins[0];
654 const size_t j1 = i1 - m_begins[1];
655 const size_t j2 = i2 - m_begins[2];
656 const size_t j3 = i3 - m_begins[3];
657 const size_t j4 = i4 - m_begins[4];
658 const size_t j5 = i5 - m_begins[5];
659 return m_map.m_impl_handle[m_map.m_impl_offset(j0, j1, j2, j3, j4, j5)];
660 }
661
662 template <typename I0, typename I1, typename I2, typename I3, typename I4,
663 typename I5>
664 KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
665 (Kokkos::Impl::are_integral<I0, I1, I2, I3, I4, I5>::value &&
666 (6 == Rank) && !is_default_map),
667 reference_type>
668 operator()(const I0& i0, const I1& i1, const I2& i2, const I3& i3,
669 const I4& i4, const I5& i5) const {
670 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY(
671 (m_track, m_map, m_begins, i0, i1, i2, i3, i4, i5))
672 const size_t j0 = i0 - m_begins[0];
673 const size_t j1 = i1 - m_begins[1];
674 const size_t j2 = i2 - m_begins[2];
675 const size_t j3 = i3 - m_begins[3];
676 const size_t j4 = i4 - m_begins[4];
677 const size_t j5 = i5 - m_begins[5];
678 return m_map.reference(j0, j1, j2, j3, j4, j5);
679 }
680
681 //------------------------------
682 // Rank 7
683
684 template <typename I0, typename I1, typename I2, typename I3, typename I4,
685 typename I5, typename I6>
686 KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
687 (Kokkos::Impl::are_integral<I0, I1, I2, I3, I4, I5, I6>::value &&
688 (7 == Rank) && is_default_map),
689 reference_type>
690 operator()(const I0& i0, const I1& i1, const I2& i2, const I3& i3,
691 const I4& i4, const I5& i5, const I6& i6) const {
692 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY(
693 (m_track, m_map, m_begins, i0, i1, i2, i3, i4, i5, i6))
694 const size_t j0 = i0 - m_begins[0];
695 const size_t j1 = i1 - m_begins[1];
696 const size_t j2 = i2 - m_begins[2];
697 const size_t j3 = i3 - m_begins[3];
698 const size_t j4 = i4 - m_begins[4];
699 const size_t j5 = i5 - m_begins[5];
700 const size_t j6 = i6 - m_begins[6];
701 return m_map.m_impl_handle[m_map.m_impl_offset(j0, j1, j2, j3, j4, j5, j6)];
702 }
703
704 template <typename I0, typename I1, typename I2, typename I3, typename I4,
705 typename I5, typename I6>
706 KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
707 (Kokkos::Impl::are_integral<I0, I1, I2, I3, I4, I5, I6>::value &&
708 (7 == Rank) && !is_default_map),
709 reference_type>
710 operator()(const I0& i0, const I1& i1, const I2& i2, const I3& i3,
711 const I4& i4, const I5& i5, const I6& i6) const {
712 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY(
713 (m_track, m_map, m_begins, i0, i1, i2, i3, i4, i5, i6))
714 const size_t j0 = i0 - m_begins[0];
715 const size_t j1 = i1 - m_begins[1];
716 const size_t j2 = i2 - m_begins[2];
717 const size_t j3 = i3 - m_begins[3];
718 const size_t j4 = i4 - m_begins[4];
719 const size_t j5 = i5 - m_begins[5];
720 const size_t j6 = i6 - m_begins[6];
721 return m_map.reference(j0, j1, j2, j3, j4, j5, j6);
722 }
723
724 //------------------------------
725 // Rank 8
726
727 template <typename I0, typename I1, typename I2, typename I3, typename I4,
728 typename I5, typename I6, typename I7>
729 KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
730 (Kokkos::Impl::are_integral<I0, I1, I2, I3, I4, I5, I6, I7>::value &&
731 (8 == Rank) && is_default_map),
732 reference_type>
733 operator()(const I0& i0, const I1& i1, const I2& i2, const I3& i3,
734 const I4& i4, const I5& i5, const I6& i6, const I7& i7) const {
735 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY(
736 (m_track, m_map, m_begins, i0, i1, i2, i3, i4, i5, i6, i7))
737 const size_t j0 = i0 - m_begins[0];
738 const size_t j1 = i1 - m_begins[1];
739 const size_t j2 = i2 - m_begins[2];
740 const size_t j3 = i3 - m_begins[3];
741 const size_t j4 = i4 - m_begins[4];
742 const size_t j5 = i5 - m_begins[5];
743 const size_t j6 = i6 - m_begins[6];
744 const size_t j7 = i7 - m_begins[7];
745 return m_map
746 .m_impl_handle[m_map.m_impl_offset(j0, j1, j2, j3, j4, j5, j6, j7)];
747 }
748
749 template <typename I0, typename I1, typename I2, typename I3, typename I4,
750 typename I5, typename I6, typename I7>
751 KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
752 (Kokkos::Impl::are_integral<I0, I1, I2, I3, I4, I5, I6, I7>::value &&
753 (8 == Rank) && !is_default_map),
754 reference_type>
755 operator()(const I0& i0, const I1& i1, const I2& i2, const I3& i3,
756 const I4& i4, const I5& i5, const I6& i6, const I7& i7) const {
757 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY(
758 (m_track, m_map, m_begins, i0, i1, i2, i3, i4, i5, i6, i7))
759 const size_t j0 = i0 - m_begins[0];
760 const size_t j1 = i1 - m_begins[1];
761 const size_t j2 = i2 - m_begins[2];
762 const size_t j3 = i3 - m_begins[3];
763 const size_t j4 = i4 - m_begins[4];
764 const size_t j5 = i5 - m_begins[5];
765 const size_t j6 = i6 - m_begins[6];
766 const size_t j7 = i7 - m_begins[7];
767 return m_map.reference(j0, j1, j2, j3, j4, j5, j6, j7);
768 }
769
770#undef KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY
771
772 //----------------------------------------
773 // Standard destructor, constructors, and assignment operators
774
775 KOKKOS_DEFAULTED_FUNCTION
776 ~OffsetView() = default;
777
778 KOKKOS_FUNCTION
779 OffsetView() : m_track(), m_map() {
780 for (size_t i = 0; i < Rank; ++i) m_begins[i] = KOKKOS_INVALID_OFFSET;
781 }
782
783 KOKKOS_FUNCTION
784 OffsetView(const OffsetView& rhs)
785 : m_track(rhs.m_track, traits::is_managed),
786 m_map(rhs.m_map),
787 m_begins(rhs.m_begins) {}
788
789 KOKKOS_FUNCTION
790 OffsetView(OffsetView&& rhs)
791 : m_track(std::move(rhs.m_track)),
792 m_map(std::move(rhs.m_map)),
793 m_begins(std::move(rhs.m_begins)) {}
794
795 KOKKOS_FUNCTION
796 OffsetView& operator=(const OffsetView& rhs) {
797 m_track = rhs.m_track;
798 m_map = rhs.m_map;
799 m_begins = rhs.m_begins;
800 return *this;
801 }
802
803 KOKKOS_FUNCTION
804 OffsetView& operator=(OffsetView&& rhs) {
805 m_track = std::move(rhs.m_track);
806 m_map = std::move(rhs.m_map);
807 m_begins = std::move(rhs.m_begins);
808 return *this;
809 }
810
811 // interoperability with View
812 private:
813 using view_type =
814 View<typename traits::scalar_array_type, typename traits::array_layout,
815 typename traits::device_type, typename traits::memory_traits>;
816
817 public:
818 KOKKOS_FUNCTION
819 view_type view() const {
820 view_type v(m_track, m_map);
821 return v;
822 }
823
824 template <class RT, class... RP>
825 KOKKOS_FUNCTION OffsetView(const View<RT, RP...>& aview)
826 : m_track(aview.impl_track()), m_map() {
827 using SrcTraits = typename OffsetView<RT, RP...>::traits;
828 using Mapping = Kokkos::Impl::ViewMapping<traits, SrcTraits, void>;
829 static_assert(Mapping::is_assignable,
830 "Incompatible OffsetView copy construction");
831 Mapping::assign(m_map, aview.impl_map(), m_track);
832
833 for (size_t i = 0; i < View<RT, RP...>::rank(); ++i) {
834 m_begins[i] = 0;
835 }
836 }
837
838 template <class RT, class... RP>
839 KOKKOS_FUNCTION OffsetView(const View<RT, RP...>& aview,
840 const index_list_type& minIndices)
841 : m_track(aview.impl_track()), m_map() {
842 using SrcTraits = typename OffsetView<RT, RP...>::traits;
843 using Mapping = Kokkos::Impl::ViewMapping<traits, SrcTraits, void>;
844 static_assert(Mapping::is_assignable,
845 "Incompatible OffsetView copy construction");
846 Mapping::assign(m_map, aview.impl_map(), m_track);
847
848 KOKKOS_IF_ON_HOST((Kokkos::Experimental::Impl::runtime_check_rank_host(
849 traits::rank_dynamic, Rank, minIndices, label());))
850
851 KOKKOS_IF_ON_DEVICE((Kokkos::Experimental::Impl::runtime_check_rank_device(
852 traits::rank_dynamic, Rank, minIndices);))
853
854 for (size_t i = 0; i < minIndices.size(); ++i) {
855 m_begins[i] = minIndices.begin()[i];
856 }
857 }
858 template <class RT, class... RP>
859 KOKKOS_FUNCTION OffsetView(const View<RT, RP...>& aview,
860 const begins_type& beg)
861 : m_track(aview.impl_track()), m_map(), m_begins(beg) {
862 using SrcTraits = typename OffsetView<RT, RP...>::traits;
863 using Mapping = Kokkos::Impl::ViewMapping<traits, SrcTraits, void>;
864 static_assert(Mapping::is_assignable,
865 "Incompatible OffsetView copy construction");
866 Mapping::assign(m_map, aview.impl_map(), m_track);
867 }
868
869 // may assign unmanaged from managed.
870
871 template <class RT, class... RP>
872 KOKKOS_FUNCTION OffsetView(const OffsetView<RT, RP...>& rhs)
873 : m_track(rhs.m_track, traits::is_managed),
874 m_map(),
875 m_begins(rhs.m_begins) {
876 using SrcTraits = typename OffsetView<RT, RP...>::traits;
877 using Mapping = Kokkos::Impl::ViewMapping<traits, SrcTraits, void>;
878 static_assert(Mapping::is_assignable,
879 "Incompatible OffsetView copy construction");
880 Mapping::assign(m_map, rhs.m_map, rhs.m_track); // swb what about assign?
881 }
882
883 private:
884 enum class subtraction_failure {
885 none,
886 negative,
887 overflow,
888 };
889
890 // Subtraction should return a non-negative number and not overflow
891 KOKKOS_FUNCTION static subtraction_failure check_subtraction(int64_t lhs,
892 int64_t rhs) {
893 if (lhs < rhs) return subtraction_failure::negative;
894
895 if (static_cast<uint64_t>(-1) / static_cast<uint64_t>(2) <
896 static_cast<uint64_t>(lhs) - static_cast<uint64_t>(rhs))
897 return subtraction_failure::overflow;
898
899 return subtraction_failure::none;
900 }
901
902 // Need a way to get at an element from both begins_type (aka Kokkos::Array
903 // which doesn't have iterators) and index_list_type (aka
904 // std::initializer_list which doesn't have .data() or operator[]).
905 // Returns by value
906 KOKKOS_FUNCTION
907 static int64_t at(const begins_type& a, size_t pos) { return a[pos]; }
908
909 KOKKOS_FUNCTION
910 static int64_t at(index_list_type a, size_t pos) {
911 return *(a.begin() + pos);
912 }
913
914 // Check that begins < ends for all elements
915 // B, E can be begins_type and/or index_list_type
916 template <typename B, typename E>
917 static subtraction_failure runtime_check_begins_ends_host(const B& begins,
918 const E& ends) {
919 std::string message;
920 if (begins.size() != Rank)
921 message +=
922 "begins.size() "
923 "(" +
924 std::to_string(begins.size()) +
925 ")"
926 " != Rank "
927 "(" +
928 std::to_string(Rank) +
929 ")"
930 "\n";
931
932 if (ends.size() != Rank)
933 message +=
934 "ends.size() "
935 "(" +
936 std::to_string(begins.size()) +
937 ")"
938 " != Rank "
939 "(" +
940 std::to_string(Rank) +
941 ")"
942 "\n";
943
944 // If there are no errors so far, then arg_rank == Rank
945 // Otherwise, check as much as possible
946 size_t arg_rank = begins.size() < ends.size() ? begins.size() : ends.size();
947 for (size_t i = 0; i != arg_rank; ++i) {
948 subtraction_failure sf = check_subtraction(at(ends, i), at(begins, i));
949 if (sf != subtraction_failure::none) {
950 message +=
951 "("
952 "ends[" +
953 std::to_string(i) +
954 "]"
955 " "
956 "(" +
957 std::to_string(at(ends, i)) +
958 ")"
959 " - "
960 "begins[" +
961 std::to_string(i) +
962 "]"
963 " "
964 "(" +
965 std::to_string(at(begins, i)) +
966 ")"
967 ")";
968 switch (sf) {
969 case subtraction_failure::negative:
970 message += " must be non-negative\n";
971 break;
972 case subtraction_failure::overflow: message += " overflows\n"; break;
973 default: break;
974 }
975 }
976 }
977
978 if (!message.empty()) {
979 message =
980 "Kokkos::Experimental::OffsetView ERROR: for unmanaged OffsetView\n" +
981 message;
982 Kokkos::Impl::throw_runtime_exception(message);
983 }
984
985 return subtraction_failure::none;
986 }
987
988 // Check the begins < ends for all elements
989 template <typename B, typename E>
990 KOKKOS_FUNCTION static subtraction_failure runtime_check_begins_ends_device(
991 const B& begins, const E& ends) {
992 if (begins.size() != Rank)
993 Kokkos::abort(
994 "Kokkos::Experimental::OffsetView ERROR: for unmanaged "
995 "OffsetView: begins has bad Rank");
996 if (ends.size() != Rank)
997 Kokkos::abort(
998 "Kokkos::Experimental::OffsetView ERROR: for unmanaged "
999 "OffsetView: ends has bad Rank");
1000
1001 for (size_t i = 0; i != begins.size(); ++i) {
1002 switch (check_subtraction(at(ends, i), at(begins, i))) {
1003 case subtraction_failure::negative:
1004 Kokkos::abort(
1005 "Kokkos::Experimental::OffsetView ERROR: for unmanaged "
1006 "OffsetView: bad range");
1007 break;
1008 case subtraction_failure::overflow:
1009 Kokkos::abort(
1010 "Kokkos::Experimental::OffsetView ERROR: for unmanaged "
1011 "OffsetView: range overflows");
1012 break;
1013 default: break;
1014 }
1015 }
1016
1017 return subtraction_failure::none;
1018 }
1019
1020 template <typename B, typename E>
1021 KOKKOS_FUNCTION static subtraction_failure runtime_check_begins_ends(
1022 const B& begins, const E& ends) {
1023 KOKKOS_IF_ON_HOST((return runtime_check_begins_ends_host(begins, ends);))
1024 KOKKOS_IF_ON_DEVICE(
1025 (return runtime_check_begins_ends_device(begins, ends);))
1026 }
1027
1028 // Constructor around unmanaged data after checking begins < ends for all
1029 // elements
1030 // Each of B, E can be begins_type and/or index_list_type
1031 // Precondition: begins.size() == ends.size() == m_begins.size() == Rank
1032 template <typename B, typename E>
1033 KOKKOS_FUNCTION OffsetView(const pointer_type& p, const B& begins_,
1034 const E& ends_,
1035 subtraction_failure)
1036 : m_track() // no tracking
1037 ,
1038 m_map(Kokkos::Impl::ViewCtorProp<pointer_type>(p),
1039 typename traits::array_layout(
1040 Rank > 0 ? at(ends_, 0) - at(begins_, 0) : 0,
1041 Rank > 1 ? at(ends_, 1) - at(begins_, 1) : 0,
1042 Rank > 2 ? at(ends_, 2) - at(begins_, 2) : 0,
1043 Rank > 3 ? at(ends_, 3) - at(begins_, 3) : 0,
1044 Rank > 4 ? at(ends_, 4) - at(begins_, 4) : 0,
1045 Rank > 5 ? at(ends_, 5) - at(begins_, 5) : 0,
1046 Rank > 6 ? at(ends_, 6) - at(begins_, 6) : 0,
1047 Rank > 7 ? at(ends_, 7) - at(begins_, 7) : 0)) {
1048 for (size_t i = 0; i != m_begins.size(); ++i) {
1049 m_begins[i] = at(begins_, i);
1050 };
1051 }
1052
1053 public:
1054 // Constructor around unmanaged data
1055 // Four overloads, as both begins and ends can be either
1056 // begins_type or index_list_type
1057 KOKKOS_FUNCTION
1058 OffsetView(const pointer_type& p, const begins_type& begins_,
1059 const begins_type& ends_)
1060 : OffsetView(p, begins_, ends_,
1061 runtime_check_begins_ends(begins_, ends_)) {}
1062
1063 KOKKOS_FUNCTION
1064 OffsetView(const pointer_type& p, const begins_type& begins_,
1065 index_list_type ends_)
1066 : OffsetView(p, begins_, ends_,
1067 runtime_check_begins_ends(begins_, ends_)) {}
1068
1069 KOKKOS_FUNCTION
1070 OffsetView(const pointer_type& p, index_list_type begins_,
1071 const begins_type& ends_)
1072 : OffsetView(p, begins_, ends_,
1073 runtime_check_begins_ends(begins_, ends_)) {}
1074
1075 KOKKOS_FUNCTION
1076 OffsetView(const pointer_type& p, index_list_type begins_,
1077 index_list_type ends_)
1078 : OffsetView(p, begins_, ends_,
1079 runtime_check_begins_ends(begins_, ends_)) {}
1080
1081 //----------------------------------------
1082 // Allocation tracking properties
1083 KOKKOS_FUNCTION
1084 int use_count() const { return m_track.use_count(); }
1085
1086 const std::string label() const {
1087 return m_track.template get_label<typename traits::memory_space>();
1088 }
1089
1090 // Choosing std::pair as type for the arguments allows constructing an
1091 // OffsetView using list initialization syntax, e.g.,
1092 // OffsetView dummy("dummy", {-1, 3}, {-2,2});
1093 // We could allow arbitrary types RangeType that support
1094 // std::get<{0,1}>(RangeType const&) with std::tuple_size<RangeType>::value==2
1095 // but this wouldn't allow using the syntax in the example above.
1096 template <typename Label>
1097 explicit OffsetView(
1098 const Label& arg_label,
1099 std::enable_if_t<Kokkos::Impl::is_view_label<Label>::value,
1100 const std::pair<int64_t, int64_t>>
1101 range0,
1102 const std::pair<int64_t, int64_t> range1 = KOKKOS_INVALID_INDEX_RANGE,
1103 const std::pair<int64_t, int64_t> range2 = KOKKOS_INVALID_INDEX_RANGE,
1104 const std::pair<int64_t, int64_t> range3 = KOKKOS_INVALID_INDEX_RANGE,
1105 const std::pair<int64_t, int64_t> range4 = KOKKOS_INVALID_INDEX_RANGE,
1106 const std::pair<int64_t, int64_t> range5 = KOKKOS_INVALID_INDEX_RANGE,
1107 const std::pair<int64_t, int64_t> range6 = KOKKOS_INVALID_INDEX_RANGE,
1108 const std::pair<int64_t, int64_t> range7 = KOKKOS_INVALID_INDEX_RANGE
1109
1110 )
1111 : OffsetView(
1112 Kokkos::Impl::ViewCtorProp<std::string>(arg_label),
1113 typename traits::array_layout(range0.second - range0.first + 1,
1114 range1.second - range1.first + 1,
1115 range2.second - range2.first + 1,
1116 range3.second - range3.first + 1,
1117 range4.second - range4.first + 1,
1118 range5.second - range5.first + 1,
1119 range6.second - range6.first + 1,
1120 range7.second - range7.first + 1),
1121 {range0.first, range1.first, range2.first, range3.first,
1122 range4.first, range5.first, range6.first, range7.first}) {}
1123
1124 template <class... P>
1125 explicit OffsetView(
1126 const Kokkos::Impl::ViewCtorProp<P...>& arg_prop,
1127 const std::pair<int64_t, int64_t> range0 = KOKKOS_INVALID_INDEX_RANGE,
1128 const std::pair<int64_t, int64_t> range1 = KOKKOS_INVALID_INDEX_RANGE,
1129 const std::pair<int64_t, int64_t> range2 = KOKKOS_INVALID_INDEX_RANGE,
1130 const std::pair<int64_t, int64_t> range3 = KOKKOS_INVALID_INDEX_RANGE,
1131 const std::pair<int64_t, int64_t> range4 = KOKKOS_INVALID_INDEX_RANGE,
1132 const std::pair<int64_t, int64_t> range5 = KOKKOS_INVALID_INDEX_RANGE,
1133 const std::pair<int64_t, int64_t> range6 = KOKKOS_INVALID_INDEX_RANGE,
1134 const std::pair<int64_t, int64_t> range7 = KOKKOS_INVALID_INDEX_RANGE)
1135 : OffsetView(
1136 arg_prop,
1137 typename traits::array_layout(range0.second - range0.first + 1,
1138 range1.second - range1.first + 1,
1139 range2.second - range2.first + 1,
1140 range3.second - range3.first + 1,
1141 range4.second - range4.first + 1,
1142 range5.second - range5.first + 1,
1143 range6.second - range6.first + 1,
1144 range7.second - range7.first + 1),
1145 {range0.first, range1.first, range2.first, range3.first,
1146 range4.first, range5.first, range6.first, range7.first}) {}
1147
1148 template <class... P>
1149 explicit KOKKOS_FUNCTION OffsetView(
1150 const Kokkos::Impl::ViewCtorProp<P...>& arg_prop,
1151 std::enable_if_t<Kokkos::Impl::ViewCtorProp<P...>::has_pointer,
1152 typename traits::array_layout> const& arg_layout,
1153 const index_list_type minIndices)
1154 : m_track() // No memory tracking
1155 ,
1156 m_map(arg_prop, arg_layout) {
1157 for (size_t i = 0; i < minIndices.size(); ++i) {
1158 m_begins[i] = minIndices.begin()[i];
1159 }
1160 static_assert(
1161 std::is_same<pointer_type, typename Kokkos::Impl::ViewCtorProp<
1162 P...>::pointer_type>::value,
1163 "When constructing OffsetView to wrap user memory, you must supply "
1164 "matching pointer type");
1165 }
1166
1167 template <class... P>
1168 explicit OffsetView(
1169 const Kokkos::Impl::ViewCtorProp<P...>& arg_prop,
1170 std::enable_if_t<!Kokkos::Impl::ViewCtorProp<P...>::has_pointer,
1171 typename traits::array_layout> const& arg_layout,
1172 const index_list_type minIndices)
1173 : m_track(),
1174 m_map()
1175
1176 {
1177 for (size_t i = 0; i < Rank; ++i) m_begins[i] = minIndices.begin()[i];
1178
1179 // Copy the input allocation properties with possibly defaulted properties
1180 auto prop_copy = Kokkos::Impl::with_properties_if_unset(
1181 arg_prop, std::string{}, typename traits::device_type::memory_space{},
1182 typename traits::device_type::execution_space{});
1183 using alloc_prop = decltype(prop_copy);
1184
1185 static_assert(traits::is_managed,
1186 "OffsetView allocation constructor requires managed memory");
1187
1188 if (alloc_prop::initialize &&
1189 !alloc_prop::execution_space::impl_is_initialized()) {
1190 // If initializing view data then
1191 // the execution space must be initialized.
1192 Kokkos::Impl::throw_runtime_exception(
1193 "Constructing OffsetView and initializing data with uninitialized "
1194 "execution space");
1195 }
1196
1197 Kokkos::Impl::SharedAllocationRecord<>* record = m_map.allocate_shared(
1198 prop_copy, arg_layout,
1199 Kokkos::Impl::ViewCtorProp<P...>::has_execution_space);
1200
1201 // Setup and initialization complete, start tracking
1202 m_track.assign_allocated_record_to_uninitialized(record);
1203
1204 KOKKOS_IF_ON_HOST((Kokkos::Experimental::Impl::runtime_check_rank_host(
1205 traits::rank_dynamic, Rank, minIndices, label());))
1206
1207 KOKKOS_IF_ON_DEVICE((Kokkos::Experimental::Impl::runtime_check_rank_device(
1208 traits::rank_dynamic, Rank, minIndices);))
1209 }
1210};
1211
1216template <typename D, class... P>
1217KOKKOS_INLINE_FUNCTION constexpr unsigned rank(const OffsetView<D, P...>& V) {
1218 return V.Rank;
1219} // Temporary until added to view
1220
1221//----------------------------------------------------------------------------
1222//----------------------------------------------------------------------------
1223namespace Impl {
1224
1225template <class T>
1226KOKKOS_INLINE_FUNCTION std::enable_if_t<std::is_integral<T>::value, T>
1227shift_input(const T arg, const int64_t offset) {
1228 return arg - offset;
1229}
1230
1231KOKKOS_INLINE_FUNCTION
1232Kokkos::ALL_t shift_input(const Kokkos::ALL_t arg, const int64_t /*offset*/) {
1233 return arg;
1234}
1235
1236template <class T>
1237KOKKOS_INLINE_FUNCTION
1238 std::enable_if_t<std::is_integral<T>::value, Kokkos::pair<T, T>>
1239 shift_input(const Kokkos::pair<T, T> arg, const int64_t offset) {
1240 return Kokkos::make_pair<T, T>(arg.first - offset, arg.second - offset);
1241}
1242template <class T>
1243inline std::enable_if_t<std::is_integral<T>::value, std::pair<T, T>>
1244shift_input(const std::pair<T, T> arg, const int64_t offset) {
1245 return std::make_pair<T, T>(arg.first - offset, arg.second - offset);
1246}
1247
1248template <size_t N, class Arg, class A>
1249KOKKOS_INLINE_FUNCTION void map_arg_to_new_begin(
1250 const size_t i, Kokkos::Array<int64_t, N>& subviewBegins,
1251 std::enable_if_t<N != 0, const Arg> shiftedArg, const Arg arg,
1252 const A viewBegins, size_t& counter) {
1253 if (!std::is_integral<Arg>::value) {
1254 subviewBegins[counter] = shiftedArg == arg ? viewBegins[i] : 0;
1255 counter++;
1256 }
1257}
1258
1259template <size_t N, class Arg, class A>
1260KOKKOS_INLINE_FUNCTION void map_arg_to_new_begin(
1261 const size_t /*i*/, Kokkos::Array<int64_t, N>& /*subviewBegins*/,
1262 std::enable_if_t<N == 0, const Arg> /*shiftedArg*/, const Arg /*arg*/,
1263 const A /*viewBegins*/, size_t& /*counter*/) {}
1264
1265template <class D, class... P, class T>
1266KOKKOS_INLINE_FUNCTION
1267 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1268 typename Kokkos::Impl::ViewMapping<void /* deduce subview type from
1269 source view traits */
1270 ,
1271 ViewTraits<D, P...>, T>::type>::type
1272 subview_offset(const OffsetView<D, P...>& src, T arg) {
1273 auto theView = src.view();
1274 auto begins = src.begins();
1275
1276 T shiftedArg = shift_input(arg, begins[0]);
1277
1278 constexpr size_t rank =
1279 Kokkos::Impl::ViewMapping<void /* deduce subview type from source view
1280 traits */
1281 ,
1282 ViewTraits<D, P...>, T>::type::rank;
1283
1284 auto theSubview = Kokkos::subview(theView, shiftedArg);
1285
1286 Kokkos::Array<int64_t, rank> subviewBegins;
1287 size_t counter = 0;
1288 Kokkos::Experimental::Impl::map_arg_to_new_begin(0, subviewBegins, shiftedArg,
1289 arg, begins, counter);
1290
1291 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1292 typename Kokkos::Impl::ViewMapping<void /* deduce subview type from source
1293 view traits */
1294 ,
1295 ViewTraits<D, P...>, T>::type>::type
1296 offsetView(theSubview, subviewBegins);
1297
1298 return offsetView;
1299}
1300
1301template <class D, class... P, class T0, class T1>
1302KOKKOS_INLINE_FUNCTION
1303 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1304 typename Kokkos::Impl::ViewMapping<
1305 void /* deduce subview type from source view traits */
1306 ,
1307 ViewTraits<D, P...>, T0, T1>::type>::type
1308 subview_offset(const Kokkos::Experimental::OffsetView<D, P...>& src,
1309 T0 arg0, T1 arg1) {
1310 auto theView = src.view();
1311 auto begins = src.begins();
1312
1313 T0 shiftedArg0 = shift_input(arg0, begins[0]);
1314 T1 shiftedArg1 = shift_input(arg1, begins[1]);
1315
1316 auto theSubview = Kokkos::subview(theView, shiftedArg0, shiftedArg1);
1317 constexpr size_t rank =
1318 Kokkos::Impl::ViewMapping<void /* deduce subview type from source view
1319 traits */
1320 ,
1321 ViewTraits<D, P...>, T0, T1>::type::rank;
1322
1323 Kokkos::Array<int64_t, rank> subviewBegins;
1324 size_t counter = 0;
1325 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1326 0, subviewBegins, shiftedArg0, arg0, begins, counter);
1327 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1328 1, subviewBegins, shiftedArg1, arg1, begins, counter);
1329
1330 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1331 typename Kokkos::Impl::ViewMapping<
1332 void /* deduce subview type from source view traits */
1333 ,
1334 ViewTraits<D, P...>, T0, T1>::type>::type offsetView(theSubview,
1335 subviewBegins);
1336
1337 return offsetView;
1338}
1339
1340template <class D, class... P, class T0, class T1, class T2>
1341KOKKOS_INLINE_FUNCTION
1342 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1343 typename Kokkos::Impl::ViewMapping<
1344 void /* deduce subview type from source view traits */
1345 ,
1346 ViewTraits<D, P...>, T0, T1, T2>::type>::type
1347 subview_offset(const OffsetView<D, P...>& src, T0 arg0, T1 arg1, T2 arg2) {
1348 auto theView = src.view();
1349 auto begins = src.begins();
1350
1351 T0 shiftedArg0 = shift_input(arg0, begins[0]);
1352 T1 shiftedArg1 = shift_input(arg1, begins[1]);
1353 T2 shiftedArg2 = shift_input(arg2, begins[2]);
1354
1355 auto theSubview =
1356 Kokkos::subview(theView, shiftedArg0, shiftedArg1, shiftedArg2);
1357
1358 constexpr size_t rank =
1359 Kokkos::Impl::ViewMapping<void /* deduce subview type from source view
1360 traits */
1361 ,
1362 ViewTraits<D, P...>, T0, T1, T2>::type::rank;
1363
1364 Kokkos::Array<int64_t, rank> subviewBegins;
1365
1366 size_t counter = 0;
1367 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1368 0, subviewBegins, shiftedArg0, arg0, begins, counter);
1369 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1370 1, subviewBegins, shiftedArg1, arg1, begins, counter);
1371 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1372 2, subviewBegins, shiftedArg2, arg2, begins, counter);
1373
1374 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1375 typename Kokkos::Impl::ViewMapping<
1376 void /* deduce subview type from source view traits */
1377 ,
1378 ViewTraits<D, P...>, T0, T1, T2>::type>::type
1379 offsetView(theSubview, subviewBegins);
1380
1381 return offsetView;
1382}
1383
1384template <class D, class... P, class T0, class T1, class T2, class T3>
1385KOKKOS_INLINE_FUNCTION
1386 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1387 typename Kokkos::Impl::ViewMapping<
1388 void /* deduce subview type from source view traits */
1389 ,
1390 ViewTraits<D, P...>, T0, T1, T2, T3>::type>::type
1391 subview_offset(const OffsetView<D, P...>& src, T0 arg0, T1 arg1, T2 arg2,
1392 T3 arg3) {
1393 auto theView = src.view();
1394 auto begins = src.begins();
1395
1396 T0 shiftedArg0 = shift_input(arg0, begins[0]);
1397 T1 shiftedArg1 = shift_input(arg1, begins[1]);
1398 T2 shiftedArg2 = shift_input(arg2, begins[2]);
1399 T3 shiftedArg3 = shift_input(arg3, begins[3]);
1400
1401 auto theSubview = Kokkos::subview(theView, shiftedArg0, shiftedArg1,
1402 shiftedArg2, shiftedArg3);
1403
1404 constexpr size_t rank = Kokkos::Impl::ViewMapping<
1405 void /* deduce subview type from source view traits */
1406 ,
1407 ViewTraits<D, P...>, T0, T1, T2, T3>::type::rank;
1408 Kokkos::Array<int64_t, rank> subviewBegins;
1409
1410 size_t counter = 0;
1411 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1412 0, subviewBegins, shiftedArg0, arg0, begins, counter);
1413 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1414 1, subviewBegins, shiftedArg1, arg1, begins, counter);
1415 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1416 2, subviewBegins, shiftedArg2, arg2, begins, counter);
1417 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1418 3, subviewBegins, shiftedArg3, arg3, begins, counter);
1419
1420 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1421 typename Kokkos::Impl::ViewMapping<
1422 void /* deduce subview type from source view traits */
1423 ,
1424 ViewTraits<D, P...>, T0, T1, T2, T3>::type>::type
1425 offsetView(theSubview, subviewBegins);
1426
1427 return offsetView;
1428}
1429
1430template <class D, class... P, class T0, class T1, class T2, class T3, class T4>
1431KOKKOS_INLINE_FUNCTION
1432 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1433 typename Kokkos::Impl::ViewMapping<
1434 void /* deduce subview type from source view traits */
1435 ,
1436 ViewTraits<D, P...>, T0, T1, T2, T3, T4>::type>::type
1437 subview_offset(const OffsetView<D, P...>& src, T0 arg0, T1 arg1, T2 arg2,
1438 T3 arg3, T4 arg4) {
1439 auto theView = src.view();
1440 auto begins = src.begins();
1441
1442 T0 shiftedArg0 = shift_input(arg0, begins[0]);
1443 T1 shiftedArg1 = shift_input(arg1, begins[1]);
1444 T2 shiftedArg2 = shift_input(arg2, begins[2]);
1445 T3 shiftedArg3 = shift_input(arg3, begins[3]);
1446 T4 shiftedArg4 = shift_input(arg4, begins[4]);
1447
1448 auto theSubview = Kokkos::subview(theView, shiftedArg0, shiftedArg1,
1449 shiftedArg2, shiftedArg3, shiftedArg4);
1450
1451 constexpr size_t rank = Kokkos::Impl::ViewMapping<
1452 void /* deduce subview type from source view traits */
1453 ,
1454 ViewTraits<D, P...>, T0, T1, T2, T3, T4>::type::rank;
1455 Kokkos::Array<int64_t, rank> subviewBegins;
1456
1457 size_t counter = 0;
1458 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1459 0, subviewBegins, shiftedArg0, arg0, begins, counter);
1460 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1461 1, subviewBegins, shiftedArg1, arg1, begins, counter);
1462 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1463 2, subviewBegins, shiftedArg2, arg2, begins, counter);
1464 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1465 3, subviewBegins, shiftedArg3, arg3, begins, counter);
1466 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1467 4, subviewBegins, shiftedArg4, arg4, begins, counter);
1468
1469 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1470 typename Kokkos::Impl::ViewMapping<
1471 void /* deduce subview type from source view traits */
1472 ,
1473 ViewTraits<D, P...>, T0, T1, T2, T3, T4>::type>::type
1474 offsetView(theSubview, subviewBegins);
1475
1476 return offsetView;
1477}
1478
1479template <class D, class... P, class T0, class T1, class T2, class T3, class T4,
1480 class T5>
1481KOKKOS_INLINE_FUNCTION
1482 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1483 typename Kokkos::Impl::ViewMapping<
1484 void /* deduce subview type from source view traits */
1485 ,
1486 ViewTraits<D, P...>, T0, T1, T2, T3, T4, T5>::type>::type
1487 subview_offset(const OffsetView<D, P...>& src, T0 arg0, T1 arg1, T2 arg2,
1488 T3 arg3, T4 arg4, T5 arg5) {
1489 auto theView = src.view();
1490 auto begins = src.begins();
1491
1492 T0 shiftedArg0 = shift_input(arg0, begins[0]);
1493 T1 shiftedArg1 = shift_input(arg1, begins[1]);
1494 T2 shiftedArg2 = shift_input(arg2, begins[2]);
1495 T3 shiftedArg3 = shift_input(arg3, begins[3]);
1496 T4 shiftedArg4 = shift_input(arg4, begins[4]);
1497 T5 shiftedArg5 = shift_input(arg5, begins[5]);
1498
1499 auto theSubview =
1500 Kokkos::subview(theView, shiftedArg0, shiftedArg1, shiftedArg2,
1501 shiftedArg3, shiftedArg4, shiftedArg5);
1502
1503 constexpr size_t rank = Kokkos::Impl::ViewMapping<
1504 void /* deduce subview type from source view traits */
1505 ,
1506 ViewTraits<D, P...>, T0, T1, T2, T3, T4, T5>::type::rank;
1507
1508 Kokkos::Array<int64_t, rank> subviewBegins;
1509
1510 size_t counter = 0;
1511 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1512 0, subviewBegins, shiftedArg0, arg0, begins, counter);
1513 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1514 1, subviewBegins, shiftedArg1, arg1, begins, counter);
1515 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1516 2, subviewBegins, shiftedArg2, arg2, begins, counter);
1517 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1518 3, subviewBegins, shiftedArg3, arg3, begins, counter);
1519 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1520 4, subviewBegins, shiftedArg4, arg4, begins, counter);
1521 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1522 5, subviewBegins, shiftedArg5, arg5, begins, counter);
1523
1524 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1525 typename Kokkos::Impl::ViewMapping<
1526 void /* deduce subview type from source view traits */
1527 ,
1528 ViewTraits<D, P...>, T0, T1, T2, T3, T4, T5>::type>::type
1529 offsetView(theSubview, subviewBegins);
1530
1531 return offsetView;
1532}
1533template <class D, class... P, class T0, class T1, class T2, class T3, class T4,
1534 class T5, class T6>
1535KOKKOS_INLINE_FUNCTION
1536 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1537 typename Kokkos::Impl::ViewMapping<
1538 void /* deduce subview type from source view traits */
1539 ,
1540 ViewTraits<D, P...>, T0, T1, T2, T3, T4, T5, T6>::type>::type
1541 subview_offset(const OffsetView<D, P...>& src, T0 arg0, T1 arg1, T2 arg2,
1542 T3 arg3, T4 arg4, T5 arg5, T6 arg6) {
1543 auto theView = src.view();
1544 auto begins = src.begins();
1545
1546 T0 shiftedArg0 = shift_input(arg0, begins[0]);
1547 T1 shiftedArg1 = shift_input(arg1, begins[1]);
1548 T2 shiftedArg2 = shift_input(arg2, begins[2]);
1549 T3 shiftedArg3 = shift_input(arg3, begins[3]);
1550 T4 shiftedArg4 = shift_input(arg4, begins[4]);
1551 T5 shiftedArg5 = shift_input(arg5, begins[5]);
1552 T6 shiftedArg6 = shift_input(arg6, begins[6]);
1553
1554 auto theSubview =
1555 Kokkos::subview(theView, shiftedArg0, shiftedArg1, shiftedArg2,
1556 shiftedArg3, shiftedArg4, shiftedArg5, shiftedArg6);
1557
1558 constexpr size_t rank = Kokkos::Impl::ViewMapping<
1559 void /* deduce subview type from source view traits */
1560 ,
1561 ViewTraits<D, P...>, T0, T1, T2, T3, T4, T5, T6>::type::rank;
1562
1563 Kokkos::Array<int64_t, rank> subviewBegins;
1564
1565 size_t counter = 0;
1566 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1567 0, subviewBegins, shiftedArg0, arg0, begins, counter);
1568 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1569 1, subviewBegins, shiftedArg1, arg1, begins, counter);
1570 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1571 2, subviewBegins, shiftedArg2, arg2, begins, counter);
1572 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1573 3, subviewBegins, shiftedArg3, arg3, begins, counter);
1574 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1575 4, subviewBegins, shiftedArg4, arg4, begins, counter);
1576 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1577 5, subviewBegins, shiftedArg5, arg5, begins, counter);
1578 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1579 6, subviewBegins, shiftedArg6, arg6, begins, counter);
1580
1581 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1582 typename Kokkos::Impl::ViewMapping<
1583 void /* deduce subview type from source view traits */
1584 ,
1585 ViewTraits<D, P...>, T0, T1, T2, T3, T4, T5, T6>::type>::type
1586 offsetView(theSubview, subviewBegins);
1587
1588 return offsetView;
1589}
1590
1591template <class D, class... P, class T0, class T1, class T2, class T3, class T4,
1592 class T5, class T6, class T7>
1593KOKKOS_INLINE_FUNCTION
1594 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1595 typename Kokkos::Impl::ViewMapping<
1596 void /* deduce subview type from source view traits */
1597 ,
1598 ViewTraits<D, P...>, T0, T1, T2, T3, T4, T5, T6, T7>::type>::type
1599 subview_offset(const OffsetView<D, P...>& src, T0 arg0, T1 arg1, T2 arg2,
1600 T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) {
1601 auto theView = src.view();
1602 auto begins = src.begins();
1603
1604 T0 shiftedArg0 = shift_input(arg0, begins[0]);
1605 T1 shiftedArg1 = shift_input(arg1, begins[1]);
1606 T2 shiftedArg2 = shift_input(arg2, begins[2]);
1607 T3 shiftedArg3 = shift_input(arg3, begins[3]);
1608 T4 shiftedArg4 = shift_input(arg4, begins[4]);
1609 T5 shiftedArg5 = shift_input(arg5, begins[5]);
1610 T6 shiftedArg6 = shift_input(arg6, begins[6]);
1611 T7 shiftedArg7 = shift_input(arg7, begins[7]);
1612
1613 auto theSubview = Kokkos::subview(theView, shiftedArg0, shiftedArg1,
1614 shiftedArg2, shiftedArg3, shiftedArg4,
1615 shiftedArg5, shiftedArg6, shiftedArg7);
1616
1617 constexpr size_t rank = Kokkos::Impl::ViewMapping<
1618 void /* deduce subview type from source view traits */
1619 ,
1620 ViewTraits<D, P...>, T0, T1, T2, T3, T4, T5, T6, T7>::type::rank;
1621
1622 Kokkos::Array<int64_t, rank> subviewBegins;
1623
1624 size_t counter = 0;
1625 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1626 0, subviewBegins, shiftedArg0, arg0, begins, counter);
1627 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1628 1, subviewBegins, shiftedArg1, arg1, begins, counter);
1629 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1630 2, subviewBegins, shiftedArg2, arg2, begins, counter);
1631 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1632 3, subviewBegins, shiftedArg3, arg3, begins, counter);
1633 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1634 4, subviewBegins, shiftedArg4, arg4, begins, counter);
1635 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1636 5, subviewBegins, shiftedArg5, arg5, begins, counter);
1637 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1638 6, subviewBegins, shiftedArg6, arg6, begins, counter);
1639 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1640 7, subviewBegins, shiftedArg7, arg7, begins, counter);
1641
1642 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1643 typename Kokkos::Impl::ViewMapping<
1644 void /* deduce subview type from source view traits */
1645 ,
1646 ViewTraits<D, P...>, T0, T1, T2, T3, T4, T5, T6, T7>::type>::type
1647 offsetView(theSubview, subviewBegins);
1648
1649 return offsetView;
1650}
1651} // namespace Impl
1652
1653template <class D, class... P, class... Args>
1654KOKKOS_INLINE_FUNCTION
1655 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1656 typename Kokkos::Impl::ViewMapping<
1657 void /* deduce subview type from source view traits */
1658 ,
1659 ViewTraits<D, P...>, Args...>::type>::type
1660 subview(const OffsetView<D, P...>& src, Args... args) {
1661 static_assert(
1662 OffsetView<D, P...>::Rank == sizeof...(Args),
1663 "subview requires one argument for each source OffsetView rank");
1664
1665 return Kokkos::Experimental::Impl::subview_offset(src, args...);
1666}
1667
1668} // namespace Experimental
1669} // namespace Kokkos
1670//----------------------------------------------------------------------------
1671//----------------------------------------------------------------------------
1672
1673namespace Kokkos {
1674namespace Experimental {
1675template <class LT, class... LP, class RT, class... RP>
1676KOKKOS_INLINE_FUNCTION bool operator==(const OffsetView<LT, LP...>& lhs,
1677 const OffsetView<RT, RP...>& rhs) {
1678 // Same data, layout, dimensions
1679 using lhs_traits = ViewTraits<LT, LP...>;
1680 using rhs_traits = ViewTraits<RT, RP...>;
1681
1682 return std::is_same<typename lhs_traits::const_value_type,
1683 typename rhs_traits::const_value_type>::value &&
1684 std::is_same<typename lhs_traits::array_layout,
1685 typename rhs_traits::array_layout>::value &&
1686 std::is_same<typename lhs_traits::memory_space,
1687 typename rhs_traits::memory_space>::value &&
1688 unsigned(lhs_traits::rank) == unsigned(rhs_traits::rank) &&
1689 lhs.data() == rhs.data() && lhs.span() == rhs.span() &&
1690 lhs.extent(0) == rhs.extent(0) && lhs.extent(1) == rhs.extent(1) &&
1691 lhs.extent(2) == rhs.extent(2) && lhs.extent(3) == rhs.extent(3) &&
1692 lhs.extent(4) == rhs.extent(4) && lhs.extent(5) == rhs.extent(5) &&
1693 lhs.extent(6) == rhs.extent(6) && lhs.extent(7) == rhs.extent(7) &&
1694 lhs.begin(0) == rhs.begin(0) && lhs.begin(1) == rhs.begin(1) &&
1695 lhs.begin(2) == rhs.begin(2) && lhs.begin(3) == rhs.begin(3) &&
1696 lhs.begin(4) == rhs.begin(4) && lhs.begin(5) == rhs.begin(5) &&
1697 lhs.begin(6) == rhs.begin(6) && lhs.begin(7) == rhs.begin(7);
1698}
1699
1700template <class LT, class... LP, class RT, class... RP>
1701KOKKOS_INLINE_FUNCTION bool operator!=(const OffsetView<LT, LP...>& lhs,
1702 const OffsetView<RT, RP...>& rhs) {
1703 return !(operator==(lhs, rhs));
1704}
1705
1706template <class LT, class... LP, class RT, class... RP>
1707KOKKOS_INLINE_FUNCTION bool operator==(const View<LT, LP...>& lhs,
1708 const OffsetView<RT, RP...>& rhs) {
1709 // Same data, layout, dimensions
1710 using lhs_traits = ViewTraits<LT, LP...>;
1711 using rhs_traits = ViewTraits<RT, RP...>;
1712
1713 return std::is_same<typename lhs_traits::const_value_type,
1714 typename rhs_traits::const_value_type>::value &&
1715 std::is_same<typename lhs_traits::array_layout,
1716 typename rhs_traits::array_layout>::value &&
1717 std::is_same<typename lhs_traits::memory_space,
1718 typename rhs_traits::memory_space>::value &&
1719 unsigned(lhs_traits::rank) == unsigned(rhs_traits::rank) &&
1720 lhs.data() == rhs.data() && lhs.span() == rhs.span() &&
1721 lhs.extent(0) == rhs.extent(0) && lhs.extent(1) == rhs.extent(1) &&
1722 lhs.extent(2) == rhs.extent(2) && lhs.extent(3) == rhs.extent(3) &&
1723 lhs.extent(4) == rhs.extent(4) && lhs.extent(5) == rhs.extent(5) &&
1724 lhs.extent(6) == rhs.extent(6) && lhs.extent(7) == rhs.extent(7);
1725}
1726
1727template <class LT, class... LP, class RT, class... RP>
1728KOKKOS_INLINE_FUNCTION bool operator==(const OffsetView<LT, LP...>& lhs,
1729 const View<RT, RP...>& rhs) {
1730 return rhs == lhs;
1731}
1732
1733} // namespace Experimental
1734} /* namespace Kokkos */
1735
1736//----------------------------------------------------------------------------
1737//----------------------------------------------------------------------------
1738
1739namespace Kokkos {
1740
1741template <class DT, class... DP>
1742inline void deep_copy(
1743 const Experimental::OffsetView<DT, DP...>& dst,
1744 typename ViewTraits<DT, DP...>::const_value_type& value,
1745 std::enable_if_t<std::is_same<typename ViewTraits<DT, DP...>::specialize,
1746 void>::value>* = nullptr) {
1747 static_assert(
1748 std::is_same<typename ViewTraits<DT, DP...>::non_const_value_type,
1749 typename ViewTraits<DT, DP...>::value_type>::value,
1750 "deep_copy requires non-const type");
1751
1752 auto dstView = dst.view();
1753 Kokkos::deep_copy(dstView, value);
1754}
1755
1756template <class DT, class... DP, class ST, class... SP>
1757inline void deep_copy(
1758 const Experimental::OffsetView<DT, DP...>& dst,
1759 const Experimental::OffsetView<ST, SP...>& value,
1760 std::enable_if_t<std::is_same<typename ViewTraits<DT, DP...>::specialize,
1761 void>::value>* = nullptr) {
1762 static_assert(
1763 std::is_same<typename ViewTraits<DT, DP...>::value_type,
1764 typename ViewTraits<ST, SP...>::non_const_value_type>::value,
1765 "deep_copy requires matching non-const destination type");
1766
1767 auto dstView = dst.view();
1768 Kokkos::deep_copy(dstView, value.view());
1769}
1770template <class DT, class... DP, class ST, class... SP>
1771inline void deep_copy(
1772 const Experimental::OffsetView<DT, DP...>& dst,
1773 const View<ST, SP...>& value,
1774 std::enable_if_t<std::is_same<typename ViewTraits<DT, DP...>::specialize,
1775 void>::value>* = nullptr) {
1776 static_assert(
1777 std::is_same<typename ViewTraits<DT, DP...>::value_type,
1778 typename ViewTraits<ST, SP...>::non_const_value_type>::value,
1779 "deep_copy requires matching non-const destination type");
1780
1781 auto dstView = dst.view();
1782 Kokkos::deep_copy(dstView, value);
1783}
1784
1785template <class DT, class... DP, class ST, class... SP>
1786inline void deep_copy(
1787 const View<DT, DP...>& dst,
1788 const Experimental::OffsetView<ST, SP...>& value,
1789 std::enable_if_t<std::is_same<typename ViewTraits<DT, DP...>::specialize,
1790 void>::value>* = nullptr) {
1791 static_assert(
1792 std::is_same<typename ViewTraits<DT, DP...>::value_type,
1793 typename ViewTraits<ST, SP...>::non_const_value_type>::value,
1794 "deep_copy requires matching non-const destination type");
1795
1796 Kokkos::deep_copy(dst, value.view());
1797}
1798
1799namespace Impl {
1800
1801// Deduce Mirror Types
1802template <class Space, class T, class... P>
1803struct MirrorOffsetViewType {
1804 // The incoming view_type
1805 using src_view_type = typename Kokkos::Experimental::OffsetView<T, P...>;
1806 // The memory space for the mirror view
1807 using memory_space = typename Space::memory_space;
1808 // Check whether it is the same memory space
1809 enum {
1810 is_same_memspace =
1811 std::is_same<memory_space, typename src_view_type::memory_space>::value
1812 };
1813 // The array_layout
1814 using array_layout = typename src_view_type::array_layout;
1815 // The data type (we probably want it non-const since otherwise we can't even
1816 // deep_copy to it.)
1817 using data_type = typename src_view_type::non_const_data_type;
1818 // The destination view type if it is not the same memory space
1819 using dest_view_type =
1820 Kokkos::Experimental::OffsetView<data_type, array_layout, Space>;
1821 // If it is the same memory_space return the existing view_type
1822 // This will also keep the unmanaged trait if necessary
1823 using view_type =
1824 std::conditional_t<is_same_memspace, src_view_type, dest_view_type>;
1825};
1826
1827template <class Space, class T, class... P>
1828struct MirrorOffsetType {
1829 // The incoming view_type
1830 using src_view_type = typename Kokkos::Experimental::OffsetView<T, P...>;
1831 // The memory space for the mirror view
1832 using memory_space = typename Space::memory_space;
1833 // Check whether it is the same memory space
1834 enum {
1835 is_same_memspace =
1836 std::is_same<memory_space, typename src_view_type::memory_space>::value
1837 };
1838 // The array_layout
1839 using array_layout = typename src_view_type::array_layout;
1840 // The data type (we probably want it non-const since otherwise we can't even
1841 // deep_copy to it.)
1842 using data_type = typename src_view_type::non_const_data_type;
1843 // The destination view type if it is not the same memory space
1844 using view_type =
1845 Kokkos::Experimental::OffsetView<data_type, array_layout, Space>;
1846};
1847
1848} // namespace Impl
1849
1850namespace Impl {
1851template <class T, class... P, class... ViewCtorArgs>
1852inline std::enable_if_t<
1853 !Impl::ViewCtorProp<ViewCtorArgs...>::has_memory_space,
1854 typename Kokkos::Experimental::OffsetView<T, P...>::HostMirror>
1855create_mirror(const Kokkos::Experimental::OffsetView<T, P...>& src,
1856 const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop) {
1857 return typename Kokkos::Experimental::OffsetView<T, P...>::HostMirror(
1858 Kokkos::create_mirror(arg_prop, src.view()), src.begins());
1859}
1860
1861template <class T, class... P, class... ViewCtorArgs,
1862 class = std::enable_if_t<
1863 Impl::ViewCtorProp<ViewCtorArgs...>::has_memory_space>>
1864inline auto create_mirror(const Kokkos::Experimental::OffsetView<T, P...>& src,
1865 const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop) {
1866 using alloc_prop_input = Impl::ViewCtorProp<ViewCtorArgs...>;
1867 using Space = typename Impl::ViewCtorProp<ViewCtorArgs...>::memory_space;
1868
1869 static_assert(
1870 !alloc_prop_input::has_label,
1871 "The view constructor arguments passed to Kokkos::create_mirror "
1872 "must not include a label!");
1873 static_assert(
1874 !alloc_prop_input::has_pointer,
1875 "The view constructor arguments passed to Kokkos::create_mirror must "
1876 "not include a pointer!");
1877 static_assert(
1878 !alloc_prop_input::allow_padding,
1879 "The view constructor arguments passed to Kokkos::create_mirror must "
1880 "not explicitly allow padding!");
1881
1882 auto prop_copy = Impl::with_properties_if_unset(
1883 arg_prop, std::string(src.label()).append("_mirror"));
1884
1885 return typename Kokkos::Impl::MirrorOffsetType<Space, T, P...>::view_type(
1886 prop_copy, src.layout(),
1887 {src.begin(0), src.begin(1), src.begin(2), src.begin(3), src.begin(4),
1888 src.begin(5), src.begin(6), src.begin(7)});
1889}
1890} // namespace Impl
1891
1892// Create a mirror in host space
1893template <class T, class... P>
1894inline auto create_mirror(
1895 const Kokkos::Experimental::OffsetView<T, P...>& src) {
1896 return Impl::create_mirror(src, Impl::ViewCtorProp<>{});
1897}
1898
1899template <class T, class... P>
1900inline auto create_mirror(
1901 Kokkos::Impl::WithoutInitializing_t wi,
1902 const Kokkos::Experimental::OffsetView<T, P...>& src) {
1903 return Impl::create_mirror(src, Kokkos::view_alloc(wi));
1904}
1905
1906// Create a mirror in a new space
1907template <class Space, class T, class... P,
1908 typename Enable = std::enable_if_t<Kokkos::is_space<Space>::value>>
1909inline auto create_mirror(
1910 const Space&, const Kokkos::Experimental::OffsetView<T, P...>& src) {
1911 return Impl::create_mirror(
1912 src, Kokkos::view_alloc(typename Space::memory_space{}));
1913}
1914
1915template <class Space, class T, class... P>
1916typename Kokkos::Impl::MirrorOffsetType<Space, T, P...>::view_type
1917create_mirror(Kokkos::Impl::WithoutInitializing_t wi, const Space&,
1918 const Kokkos::Experimental::OffsetView<T, P...>& src) {
1919 return Impl::create_mirror(
1920 src, Kokkos::view_alloc(typename Space::memory_space{}, wi));
1921}
1922
1923template <class T, class... P, class... ViewCtorArgs>
1924inline auto create_mirror(
1925 const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
1926 const Kokkos::Experimental::OffsetView<T, P...>& src) {
1927 return Impl::create_mirror(src, arg_prop);
1928}
1929
1930namespace Impl {
1931template <class T, class... P, class... ViewCtorArgs>
1932inline std::enable_if_t<
1933 !Impl::ViewCtorProp<ViewCtorArgs...>::has_memory_space &&
1934 (std::is_same<
1935 typename Kokkos::Experimental::OffsetView<T, P...>::memory_space,
1936 typename Kokkos::Experimental::OffsetView<
1937 T, P...>::HostMirror::memory_space>::value &&
1938 std::is_same<
1939 typename Kokkos::Experimental::OffsetView<T, P...>::data_type,
1940 typename Kokkos::Experimental::OffsetView<
1941 T, P...>::HostMirror::data_type>::value),
1942 typename Kokkos::Experimental::OffsetView<T, P...>::HostMirror>
1943create_mirror_view(const Kokkos::Experimental::OffsetView<T, P...>& src,
1944 const Impl::ViewCtorProp<ViewCtorArgs...>&) {
1945 return src;
1946}
1947
1948template <class T, class... P, class... ViewCtorArgs>
1949inline std::enable_if_t<
1950 !Impl::ViewCtorProp<ViewCtorArgs...>::has_memory_space &&
1951 !(std::is_same<
1952 typename Kokkos::Experimental::OffsetView<T, P...>::memory_space,
1953 typename Kokkos::Experimental::OffsetView<
1954 T, P...>::HostMirror::memory_space>::value &&
1955 std::is_same<
1956 typename Kokkos::Experimental::OffsetView<T, P...>::data_type,
1957 typename Kokkos::Experimental::OffsetView<
1958 T, P...>::HostMirror::data_type>::value),
1959 typename Kokkos::Experimental::OffsetView<T, P...>::HostMirror>
1960create_mirror_view(const Kokkos::Experimental::OffsetView<T, P...>& src,
1961 const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop) {
1962 return Kokkos::create_mirror(arg_prop, src);
1963}
1964
1965template <class T, class... P, class... ViewCtorArgs,
1966 class = std::enable_if_t<
1967 Impl::ViewCtorProp<ViewCtorArgs...>::has_memory_space>>
1968std::enable_if_t<Impl::MirrorOffsetViewType<
1969 typename Impl::ViewCtorProp<ViewCtorArgs...>::memory_space,
1970 T, P...>::is_same_memspace,
1971 typename Impl::MirrorOffsetViewType<
1972 typename Impl::ViewCtorProp<ViewCtorArgs...>::memory_space,
1973 T, P...>::view_type>
1974create_mirror_view(const Kokkos::Experimental::OffsetView<T, P...>& src,
1975 const Impl::ViewCtorProp<ViewCtorArgs...>&) {
1976 return src;
1977}
1978
1979template <class T, class... P, class... ViewCtorArgs,
1980 class = std::enable_if_t<
1981 Impl::ViewCtorProp<ViewCtorArgs...>::has_memory_space>>
1982std::enable_if_t<!Impl::MirrorOffsetViewType<
1983 typename Impl::ViewCtorProp<ViewCtorArgs...>::memory_space,
1984 T, P...>::is_same_memspace,
1985 typename Impl::MirrorOffsetViewType<
1986 typename Impl::ViewCtorProp<ViewCtorArgs...>::memory_space,
1987 T, P...>::view_type>
1988create_mirror_view(const Kokkos::Experimental::OffsetView<T, P...>& src,
1989 const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop) {
1990 return Kokkos::Impl::create_mirror(src, arg_prop);
1991}
1992} // namespace Impl
1993
1994// Create a mirror view in host space
1995template <class T, class... P>
1996inline auto create_mirror_view(
1997 const typename Kokkos::Experimental::OffsetView<T, P...>& src) {
1998 return Impl::create_mirror_view(src, Impl::ViewCtorProp<>{});
1999}
2000
2001template <class T, class... P>
2002inline auto create_mirror_view(
2003 Kokkos::Impl::WithoutInitializing_t wi,
2004 const typename Kokkos::Experimental::OffsetView<T, P...>& src) {
2005 return Impl::create_mirror_view(src, Kokkos::view_alloc(wi));
2006}
2007
2008// Create a mirror view in a new space
2009template <class Space, class T, class... P,
2010 typename Enable = std::enable_if_t<Kokkos::is_space<Space>::value>>
2011inline auto create_mirror_view(
2012 const Space&, const Kokkos::Experimental::OffsetView<T, P...>& src) {
2013 return Impl::create_mirror_view(
2014 src, Kokkos::view_alloc(typename Space::memory_space{}));
2015}
2016
2017template <class Space, class T, class... P>
2018inline auto create_mirror_view(
2019 Kokkos::Impl::WithoutInitializing_t wi, const Space&,
2020 const Kokkos::Experimental::OffsetView<T, P...>& src) {
2021 return Impl::create_mirror_view(
2022 src, Kokkos::view_alloc(typename Space::memory_space{}, wi));
2023}
2024
2025template <class T, class... P, class... ViewCtorArgs>
2026inline auto create_mirror_view(
2027 const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
2028 const Kokkos::Experimental::OffsetView<T, P...>& src) {
2029 return Impl::create_mirror_view(src, arg_prop);
2030}
2031
2032// Create a mirror view and deep_copy in a new space
2033template <class... ViewCtorArgs, class T, class... P>
2034typename Kokkos::Impl::MirrorOffsetViewType<
2035 typename Impl::ViewCtorProp<ViewCtorArgs...>::memory_space, T,
2036 P...>::view_type
2037create_mirror_view_and_copy(
2038 const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
2039 const Kokkos::Experimental::OffsetView<T, P...>& src) {
2040 return {create_mirror_view_and_copy(arg_prop, src.view()), src.begins()};
2041}
2042
2043template <class Space, class T, class... P>
2044typename Kokkos::Impl::MirrorOffsetViewType<Space, T, P...>::view_type
2045create_mirror_view_and_copy(
2046 const Space& space, const Kokkos::Experimental::OffsetView<T, P...>& src,
2047 std::string const& name = "") {
2048 return {create_mirror_view_and_copy(space, src.view(), name), src.begins()};
2049}
2050} /* namespace Kokkos */
2051
2052//----------------------------------------------------------------------------
2053//----------------------------------------------------------------------------
2054
2055#ifdef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_OFFSETVIEW
2056#undef KOKKOS_IMPL_PUBLIC_INCLUDE
2057#undef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_OFFSETVIEW
2058#endif
2059#endif /* KOKKOS_OFFSETVIEW_HPP_ */
View to an array of data.
ScopeGuard Some user scope issues have been identified with some Kokkos::finalize calls; ScopeGuard a...
Traits class for accessing attributes of a View.
first_type first
The first element of the pair.
second_type second
The second element of the pair.