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