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,
54 std::enable_if_t<std::is_integral_v<iType> && std::is_signed_v<iType>,
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::abort(buffer);))
126
127 KOKKOS_IF_ON_DEVICE(
128 (Kokkos::abort("OffsetView bounds error"); (void)tracker;))
129 }
130}
131
132inline void runtime_check_rank_host(const size_t rank_dynamic,
133 const size_t rank,
134 const index_list_type minIndices,
135 const std::string& label) {
136 bool isBad = false;
137 std::string message =
138 "Kokkos::Experimental::OffsetView ERROR: for OffsetView labeled '" +
139 label + "':";
140 if (rank_dynamic != rank) {
141 message +=
142 "The full rank must be the same as the dynamic rank. full rank = ";
143 message += std::to_string(rank) +
144 " dynamic rank = " + std::to_string(rank_dynamic) + "\n";
145 isBad = true;
146 }
147
148 size_t numOffsets = 0;
149 for (size_t i = 0; i < minIndices.size(); ++i) {
150 if (minIndices.begin()[i] != KOKKOS_INVALID_OFFSET) numOffsets++;
151 }
152 if (numOffsets != rank_dynamic) {
153 message += "The number of offsets provided ( " +
154 std::to_string(numOffsets) +
155 " ) must equal the dynamic rank ( " +
156 std::to_string(rank_dynamic) + " ).";
157 isBad = true;
158 }
159
160 if (isBad) Kokkos::abort(message.c_str());
161}
162
163KOKKOS_INLINE_FUNCTION
164void runtime_check_rank_device(const size_t rank_dynamic, const size_t rank,
165 const index_list_type minIndices) {
166 if (rank_dynamic != rank) {
167 Kokkos::abort(
168 "The full rank of an OffsetView must be the same as the dynamic rank.");
169 }
170 size_t numOffsets = 0;
171 for (size_t i = 0; i < minIndices.size(); ++i) {
172 if (minIndices.begin()[i] != KOKKOS_INVALID_OFFSET) numOffsets++;
173 }
174 if (numOffsets != rank) {
175 Kokkos::abort(
176 "The number of offsets provided to an OffsetView constructor must "
177 "equal the dynamic rank.");
178 }
179}
180} // namespace Impl
181
182template <class DataType, class... Properties>
183class OffsetView : public View<DataType, Properties...> {
184 private:
185 template <class, class...>
186 friend class OffsetView;
187
188 using base_t = View<DataType, Properties...>;
189
190 public:
191 // typedefs to reduce typing base_t:: further down
192 using traits = typename base_t::traits;
193 // FIXME: should be base_t::index_type after refactor
194 using index_type = typename base_t::memory_space::size_type;
195 using pointer_type = typename base_t::pointer_type;
196
197 using begins_type = Kokkos::Array<int64_t, base_t::rank()>;
198
199 template <typename iType,
200 std::enable_if_t<std::is_integral_v<iType>, iType> = 0>
201 KOKKOS_FUNCTION int64_t begin(const iType local_dimension) const {
202 return static_cast<size_t>(local_dimension) < base_t::rank()
203 ? m_begins[local_dimension]
204 : KOKKOS_INVALID_OFFSET;
205 }
206
207 KOKKOS_FUNCTION
208 begins_type begins() const { return m_begins; }
209
210 template <typename iType,
211 std::enable_if_t<std::is_integral_v<iType>, iType> = 0>
212 KOKKOS_FUNCTION int64_t end(const iType local_dimension) const {
213 return begin(local_dimension) + base_t::extent(local_dimension);
214 }
215
216 private:
217 begins_type m_begins;
218
219 public:
220 //----------------------------------------
222 using array_type =
223 OffsetView<typename traits::scalar_array_type,
224 typename traits::array_layout, typename traits::device_type,
225 typename traits::memory_traits>;
226
228 using const_type =
229 OffsetView<typename traits::const_data_type,
230 typename traits::array_layout, typename traits::device_type,
231 typename traits::memory_traits>;
232
234 using non_const_type =
235 OffsetView<typename traits::non_const_data_type,
236 typename traits::array_layout, typename traits::device_type,
237 typename traits::memory_traits>;
238
240 using HostMirror = OffsetView<typename traits::non_const_data_type,
241 typename traits::array_layout,
242 typename traits::host_mirror_space>;
243
244 template <size_t... I, class... OtherIndexTypes>
245 KOKKOS_FUNCTION typename base_t::reference_type offset_operator(
246 std::integer_sequence<size_t, I...>, OtherIndexTypes... indices) const {
247 return base_t::operator()((indices - m_begins[I])...);
248 }
249
250 template <class OtherIndexType>
251#ifndef KOKKOS_ENABLE_CXX17
252 requires(std::is_convertible_v<OtherIndexType, index_type> &&
253 std::is_nothrow_constructible_v<index_type, OtherIndexType> &&
254 (base_t::rank() == 1))
255#endif
256 KOKKOS_FUNCTION constexpr typename base_t::reference_type operator[](
257 const OtherIndexType& idx) const {
258#ifdef KOKKOS_ENABLE_CXX17
259 static_assert(std::is_convertible_v<OtherIndexType, index_type> &&
260 std::is_nothrow_constructible_v<index_type, OtherIndexType> &&
261 (base_t::rank() == 1));
262#endif
263 return base_t::operator[](idx - m_begins[0]);
264 }
265
266 template <class... OtherIndexTypes>
267#ifndef KOKKOS_ENABLE_CXX17
268 requires((std::is_convertible_v<OtherIndexTypes, index_type> && ...) &&
269 (std::is_nothrow_constructible_v<index_type, OtherIndexTypes> &&
270 ...) &&
271 (sizeof...(OtherIndexTypes) == base_t::rank()))
272#endif
273 KOKKOS_FUNCTION constexpr typename base_t::reference_type operator()(
274 OtherIndexTypes... indices) const {
275#ifdef KOKKOS_ENABLE_CXX17
276 static_assert(
277 (std::is_convertible_v<OtherIndexTypes, index_type> && ...) &&
278 (std::is_nothrow_constructible_v<index_type, OtherIndexTypes> && ...) &&
279 (sizeof...(OtherIndexTypes) == base_t::rank()));
280#endif
281 return offset_operator(std::make_index_sequence<base_t::rank()>(),
282 indices...);
283 }
284
285 template <class... OtherIndexTypes>
286 KOKKOS_FUNCTION constexpr typename base_t::reference_type access(
287 OtherIndexTypes... args) const = delete;
288
289 //----------------------------------------
290
291 //----------------------------------------
292 // Standard destructor, constructors, and assignment operators
293
294 KOKKOS_FUNCTION
295 OffsetView() : base_t() {
296 for (size_t i = 0; i < base_t::rank(); ++i)
297 m_begins[i] = KOKKOS_INVALID_OFFSET;
298 }
299
300 // interoperability with View
301 private:
302 using view_type =
303 View<typename traits::scalar_array_type, typename traits::array_layout,
304 typename traits::device_type, typename traits::memory_traits>;
305
306 public:
307 KOKKOS_FUNCTION
308 view_type view() const { return *this; }
309
310 template <class RT, class... RP>
311 KOKKOS_FUNCTION OffsetView(const View<RT, RP...>& aview) : base_t(aview) {
312 for (size_t i = 0; i < View<RT, RP...>::rank(); ++i) {
313 m_begins[i] = 0;
314 }
315 }
316
317 template <class RT, class... RP>
318 KOKKOS_FUNCTION OffsetView(const View<RT, RP...>& aview,
319 const index_list_type& minIndices)
320 : base_t(aview) {
321 KOKKOS_IF_ON_HOST(
322 (Kokkos::Experimental::Impl::runtime_check_rank_host(
323 traits::rank_dynamic, base_t::rank(), minIndices, aview.label());))
324
325 KOKKOS_IF_ON_DEVICE(
326 (Kokkos::Experimental::Impl::runtime_check_rank_device(
327 traits::rank_dynamic, base_t::rank(), minIndices);))
328 for (size_t i = 0; i < minIndices.size(); ++i) {
329 m_begins[i] = minIndices.begin()[i];
330 }
331 }
332 template <class RT, class... RP>
333 KOKKOS_FUNCTION OffsetView(const View<RT, RP...>& aview,
334 const begins_type& beg)
335 : base_t(aview), m_begins(beg) {}
336
337 // may assign unmanaged from managed.
338
339 template <class RT, class... RP>
340 KOKKOS_FUNCTION OffsetView(const OffsetView<RT, RP...>& rhs)
341 : base_t(rhs.view()), m_begins(rhs.m_begins) {}
342
343 private:
344 enum class subtraction_failure {
345 none,
346 negative,
347 overflow,
348 };
349
350 // Subtraction should return a non-negative number and not overflow
351 KOKKOS_FUNCTION static subtraction_failure check_subtraction(int64_t lhs,
352 int64_t rhs) {
353 if (lhs < rhs) return subtraction_failure::negative;
354
355 if (static_cast<uint64_t>(-1) / static_cast<uint64_t>(2) <
356 static_cast<uint64_t>(lhs) - static_cast<uint64_t>(rhs))
357 return subtraction_failure::overflow;
358
359 return subtraction_failure::none;
360 }
361
362 // Need a way to get at an element from both begins_type (aka Kokkos::Array
363 // which doesn't have iterators) and index_list_type (aka
364 // std::initializer_list which doesn't have .data() or operator[]).
365 // Returns by value
366 KOKKOS_FUNCTION
367 static int64_t at(const begins_type& a, size_t pos) { return a[pos]; }
368
369 KOKKOS_FUNCTION
370 static int64_t at(index_list_type a, size_t pos) {
371 return *(a.begin() + pos);
372 }
373
374 // Check that begins < ends for all elements
375 // B, E can be begins_type and/or index_list_type
376 template <typename B, typename E>
377 static subtraction_failure runtime_check_begins_ends_host(const B& begins,
378 const E& ends) {
379 std::string message;
380 if (begins.size() != base_t::rank())
381 message +=
382 "begins.size() "
383 "(" +
384 std::to_string(begins.size()) +
385 ")"
386 " != Rank "
387 "(" +
388 std::to_string(base_t::rank()) +
389 ")"
390 "\n";
391
392 if (ends.size() != base_t::rank())
393 message +=
394 "ends.size() "
395 "(" +
396 std::to_string(ends.size()) +
397 ")"
398 " != Rank "
399 "(" +
400 std::to_string(base_t::rank()) +
401 ")"
402 "\n";
403
404 // If there are no errors so far, then arg_rank == Rank
405 // Otherwise, check as much as possible
406 size_t arg_rank = begins.size() < ends.size() ? begins.size() : ends.size();
407 for (size_t i = 0; i != arg_rank; ++i) {
408 subtraction_failure sf = check_subtraction(at(ends, i), at(begins, i));
409 if (sf != subtraction_failure::none) {
410 message +=
411 "("
412 "ends[" +
413 std::to_string(i) +
414 "]"
415 " "
416 "(" +
417 std::to_string(at(ends, i)) +
418 ")"
419 " - "
420 "begins[" +
421 std::to_string(i) +
422 "]"
423 " "
424 "(" +
425 std::to_string(at(begins, i)) +
426 ")"
427 ")";
428 switch (sf) {
429 case subtraction_failure::negative:
430 message += " must be non-negative\n";
431 break;
432 case subtraction_failure::overflow: message += " overflows\n"; break;
433 default: break;
434 }
435 }
436 }
437
438 if (!message.empty()) {
439 message =
440 "Kokkos::Experimental::OffsetView ERROR: for unmanaged OffsetView\n" +
441 message;
442 Kokkos::abort(message.c_str());
443 }
444
445 return subtraction_failure::none;
446 }
447
448 // Check the begins < ends for all elements
449 template <typename B, typename E>
450 KOKKOS_FUNCTION static subtraction_failure runtime_check_begins_ends_device(
451 const B& begins, const E& ends) {
452 if (begins.size() != base_t::rank())
453 Kokkos::abort(
454 "Kokkos::Experimental::OffsetView ERROR: for unmanaged "
455 "OffsetView: begins has bad Rank");
456 if (ends.size() != base_t::rank())
457 Kokkos::abort(
458 "Kokkos::Experimental::OffsetView ERROR: for unmanaged "
459 "OffsetView: ends has bad Rank");
460
461 for (size_t i = 0; i != begins.size(); ++i) {
462 switch (check_subtraction(at(ends, i), at(begins, i))) {
463 case subtraction_failure::negative:
464 Kokkos::abort(
465 "Kokkos::Experimental::OffsetView ERROR: for unmanaged "
466 "OffsetView: bad range");
467 break;
468 case subtraction_failure::overflow:
469 Kokkos::abort(
470 "Kokkos::Experimental::OffsetView ERROR: for unmanaged "
471 "OffsetView: range overflows");
472 break;
473 default: break;
474 }
475 }
476
477 return subtraction_failure::none;
478 }
479
480 template <typename B, typename E>
481 KOKKOS_FUNCTION static subtraction_failure runtime_check_begins_ends(
482 const B& begins, const E& ends) {
483 KOKKOS_IF_ON_HOST((return runtime_check_begins_ends_host(begins, ends);))
484 KOKKOS_IF_ON_DEVICE(
485 (return runtime_check_begins_ends_device(begins, ends);))
486 }
487
488 // Constructor around unmanaged data after checking begins < ends for all
489 // elements
490 // Each of B, E can be begins_type and/or index_list_type
491 // Precondition: begins.size() == ends.size() == m_begins.size() == Rank
492 template <typename B, typename E>
493 KOKKOS_FUNCTION OffsetView(const pointer_type& p, const B& begins_,
494 const E& ends_, subtraction_failure)
495 : base_t(Kokkos::view_wrap(p),
496 typename traits::array_layout(
497 base_t::rank() > 0 ? at(ends_, 0) - at(begins_, 0)
498 : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
499 base_t::rank() > 1 ? at(ends_, 1) - at(begins_, 1)
500 : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
501 base_t::rank() > 2 ? at(ends_, 2) - at(begins_, 2)
502 : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
503 base_t::rank() > 3 ? at(ends_, 3) - at(begins_, 3)
504 : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
505 base_t::rank() > 4 ? at(ends_, 4) - at(begins_, 4)
506 : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
507 base_t::rank() > 5 ? at(ends_, 5) - at(begins_, 5)
508 : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
509 base_t::rank() > 6 ? at(ends_, 6) - at(begins_, 6)
510 : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
511 base_t::rank() > 7 ? at(ends_, 7) - at(begins_, 7)
512 : KOKKOS_IMPL_CTOR_DEFAULT_ARG)) {
513 for (size_t i = 0; i != m_begins.size(); ++i) {
514 m_begins[i] = at(begins_, i);
515 };
516 }
517
518 public:
519 // Constructor around unmanaged data
520 // Four overloads, as both begins and ends can be either
521 // begins_type or index_list_type
522 KOKKOS_FUNCTION
523 OffsetView(const pointer_type& p, const begins_type& begins_,
524 const begins_type& ends_)
525 : OffsetView(p, begins_, ends_,
526 runtime_check_begins_ends(begins_, ends_)) {}
527
528 KOKKOS_FUNCTION
529 OffsetView(const pointer_type& p, const begins_type& begins_,
530 index_list_type ends_)
531 : OffsetView(p, begins_, ends_,
532 runtime_check_begins_ends(begins_, ends_)) {}
533
534 KOKKOS_FUNCTION
535 OffsetView(const pointer_type& p, index_list_type begins_,
536 const begins_type& ends_)
537 : OffsetView(p, begins_, ends_,
538 runtime_check_begins_ends(begins_, ends_)) {}
539
540 KOKKOS_FUNCTION
541 OffsetView(const pointer_type& p, index_list_type begins_,
542 index_list_type ends_)
543 : OffsetView(p, begins_, ends_,
544 runtime_check_begins_ends(begins_, ends_)) {}
545
546 // Choosing std::pair as type for the arguments allows constructing an
547 // OffsetView using list initialization syntax, e.g.,
548 // OffsetView dummy("dummy", {-1, 3}, {-2,2});
549 // We could allow arbitrary types RangeType that support
550 // std::get<{0,1}>(RangeType const&) with std::tuple_size<RangeType>::value==2
551 // but this wouldn't allow using the syntax in the example above.
552 template <typename Label>
553 explicit OffsetView(
554 const Label& arg_label,
555 std::enable_if_t<Kokkos::Impl::is_view_label<Label>::value,
556 const std::pair<int64_t, int64_t>>
557 range0,
558 const std::pair<int64_t, int64_t> range1 = KOKKOS_INVALID_INDEX_RANGE,
559 const std::pair<int64_t, int64_t> range2 = KOKKOS_INVALID_INDEX_RANGE,
560 const std::pair<int64_t, int64_t> range3 = KOKKOS_INVALID_INDEX_RANGE,
561 const std::pair<int64_t, int64_t> range4 = KOKKOS_INVALID_INDEX_RANGE,
562 const std::pair<int64_t, int64_t> range5 = KOKKOS_INVALID_INDEX_RANGE,
563 const std::pair<int64_t, int64_t> range6 = KOKKOS_INVALID_INDEX_RANGE,
564 const std::pair<int64_t, int64_t> range7 = KOKKOS_INVALID_INDEX_RANGE
565
566 )
567 : OffsetView(Kokkos::Impl::ViewCtorProp<std::string>(arg_label),
568 typename traits::array_layout(
569 range0.first == KOKKOS_INVALID_OFFSET
570 ? KOKKOS_IMPL_CTOR_DEFAULT_ARG - 1
571 : range0.second - range0.first + 1,
572 range1.first == KOKKOS_INVALID_OFFSET
573 ? KOKKOS_IMPL_CTOR_DEFAULT_ARG
574 : range1.second - range1.first + 1,
575 range2.first == KOKKOS_INVALID_OFFSET
576 ? KOKKOS_IMPL_CTOR_DEFAULT_ARG
577 : range2.second - range2.first + 1,
578 range3.first == KOKKOS_INVALID_OFFSET
579 ? KOKKOS_IMPL_CTOR_DEFAULT_ARG
580 : range3.second - range3.first + 1,
581 range4.first == KOKKOS_INVALID_OFFSET
582 ? KOKKOS_IMPL_CTOR_DEFAULT_ARG
583 : range4.second - range4.first + 1,
584 range5.first == KOKKOS_INVALID_OFFSET
585 ? KOKKOS_IMPL_CTOR_DEFAULT_ARG
586 : range5.second - range5.first + 1,
587 range6.first == KOKKOS_INVALID_OFFSET
588 ? KOKKOS_IMPL_CTOR_DEFAULT_ARG
589 : range6.second - range6.first + 1,
590 range7.first == KOKKOS_INVALID_OFFSET
591 ? KOKKOS_IMPL_CTOR_DEFAULT_ARG
592 : range7.second - range7.first + 1),
593 {range0.first, range1.first, range2.first, range3.first,
594 range4.first, range5.first, range6.first, range7.first}) {}
595
596 template <class... P>
597 explicit OffsetView(
598 const Kokkos::Impl::ViewCtorProp<P...>& arg_prop,
599 const std::pair<int64_t, int64_t> range0 = KOKKOS_INVALID_INDEX_RANGE,
600 const std::pair<int64_t, int64_t> range1 = KOKKOS_INVALID_INDEX_RANGE,
601 const std::pair<int64_t, int64_t> range2 = KOKKOS_INVALID_INDEX_RANGE,
602 const std::pair<int64_t, int64_t> range3 = KOKKOS_INVALID_INDEX_RANGE,
603 const std::pair<int64_t, int64_t> range4 = KOKKOS_INVALID_INDEX_RANGE,
604 const std::pair<int64_t, int64_t> range5 = KOKKOS_INVALID_INDEX_RANGE,
605 const std::pair<int64_t, int64_t> range6 = KOKKOS_INVALID_INDEX_RANGE,
606 const std::pair<int64_t, int64_t> range7 = KOKKOS_INVALID_INDEX_RANGE)
607 : OffsetView(arg_prop,
608 typename traits::array_layout(
609 range0.first == KOKKOS_INVALID_OFFSET
610 ? KOKKOS_IMPL_CTOR_DEFAULT_ARG
611 : range0.second - range0.first + 1,
612 range1.first == KOKKOS_INVALID_OFFSET
613 ? KOKKOS_IMPL_CTOR_DEFAULT_ARG
614 : range1.second - range1.first + 1,
615 range2.first == KOKKOS_INVALID_OFFSET
616 ? KOKKOS_IMPL_CTOR_DEFAULT_ARG
617 : range2.second - range2.first + 1,
618 range3.first == KOKKOS_INVALID_OFFSET
619 ? KOKKOS_IMPL_CTOR_DEFAULT_ARG
620 : range3.second - range3.first + 1,
621 range4.first == KOKKOS_INVALID_OFFSET
622 ? KOKKOS_IMPL_CTOR_DEFAULT_ARG
623 : range4.second - range4.first + 1,
624 range5.first == KOKKOS_INVALID_OFFSET
625 ? KOKKOS_IMPL_CTOR_DEFAULT_ARG
626 : range5.second - range5.first + 1,
627 range6.first == KOKKOS_INVALID_OFFSET
628 ? KOKKOS_IMPL_CTOR_DEFAULT_ARG
629 : range6.second - range6.first + 1,
630 range7.first == KOKKOS_INVALID_OFFSET
631 ? KOKKOS_IMPL_CTOR_DEFAULT_ARG
632 : range7.second - range7.first + 1),
633 {range0.first, range1.first, range2.first, range3.first,
634 range4.first, range5.first, range6.first, range7.first}) {}
635
636 template <class... P>
637 explicit KOKKOS_FUNCTION OffsetView(
638 const Kokkos::Impl::ViewCtorProp<P...>& arg_prop,
639 std::enable_if_t<Kokkos::Impl::ViewCtorProp<P...>::has_pointer,
640 typename traits::array_layout> const& arg_layout,
641 const index_list_type minIndices)
642 : base_t(arg_prop, arg_layout) {
643 KOKKOS_IF_ON_HOST((Kokkos::Experimental::Impl::runtime_check_rank_host(
644 traits::rank_dynamic, base_t::rank(), minIndices,
645 base_t::label());))
646
647 KOKKOS_IF_ON_DEVICE(
648 (Kokkos::Experimental::Impl::runtime_check_rank_device(
649 traits::rank_dynamic, base_t::rank(), minIndices);))
650 for (size_t i = 0; i < minIndices.size(); ++i) {
651 m_begins[i] = minIndices.begin()[i];
652 }
653 static_assert(
654 std::is_same_v<pointer_type,
655 typename Kokkos::Impl::ViewCtorProp<P...>::pointer_type>,
656 "When constructing OffsetView to wrap user memory, you must supply "
657 "matching pointer type");
658 }
659
660 template <class... P>
661 explicit OffsetView(
662 const Kokkos::Impl::ViewCtorProp<P...>& arg_prop,
663 std::enable_if_t<!Kokkos::Impl::ViewCtorProp<P...>::has_pointer,
664 typename traits::array_layout> const& arg_layout,
665 const index_list_type minIndices)
666 : base_t(arg_prop, arg_layout) {
667 for (size_t i = 0; i < base_t::rank(); ++i)
668 m_begins[i] = minIndices.begin()[i];
669 }
670};
671
676template <typename D, class... P>
677KOKKOS_INLINE_FUNCTION constexpr unsigned rank(const OffsetView<D, P...>& V) {
678 return V.rank();
679} // Temporary until added to view
680
681//----------------------------------------------------------------------------
682//----------------------------------------------------------------------------
683namespace Impl {
684
685template <class T>
686KOKKOS_INLINE_FUNCTION std::enable_if_t<std::is_integral_v<T>, T> shift_input(
687 const T arg, const int64_t offset) {
688 return arg - offset;
689}
690
691KOKKOS_INLINE_FUNCTION
692Kokkos::ALL_t shift_input(const Kokkos::ALL_t arg, const int64_t /*offset*/) {
693 return arg;
694}
695
696template <class T>
697KOKKOS_INLINE_FUNCTION
698 std::enable_if_t<std::is_integral_v<T>, Kokkos::pair<T, T>>
699 shift_input(const Kokkos::pair<T, T> arg, const int64_t offset) {
700 return Kokkos::make_pair<T, T>(arg.first - offset, arg.second - offset);
701}
702template <class T>
703inline std::enable_if_t<std::is_integral_v<T>, std::pair<T, T>> shift_input(
704 const std::pair<T, T> arg, const int64_t offset) {
705 return std::make_pair<T, T>(arg.first - offset, arg.second - offset);
706}
707
708template <size_t N, class Arg, class A>
709KOKKOS_INLINE_FUNCTION void map_arg_to_new_begin(
710 const size_t i, Kokkos::Array<int64_t, N>& subviewBegins,
711 std::enable_if_t<N != 0, const Arg> shiftedArg, const Arg arg,
712 const A viewBegins, size_t& counter) {
713 if (!std::is_integral_v<Arg>) {
714 subviewBegins[counter] = shiftedArg == arg ? viewBegins[i] : 0;
715 counter++;
716 }
717}
718
719template <size_t N, class Arg, class A>
720KOKKOS_INLINE_FUNCTION void map_arg_to_new_begin(
721 const size_t /*i*/, Kokkos::Array<int64_t, N>& /*subviewBegins*/,
722 std::enable_if_t<N == 0, const Arg> /*shiftedArg*/, const Arg /*arg*/,
723 const A /*viewBegins*/, size_t& /*counter*/) {}
724
725template <class D, class... P, class T>
726KOKKOS_INLINE_FUNCTION
727 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
728 typename Kokkos::Impl::ViewMapping<void /* deduce subview type from
729 source view traits */
730 ,
731 ViewTraits<D, P...>, T>::type>::type
732 subview_offset(const OffsetView<D, P...>& src, T arg) {
733 auto theView = src.view();
734 auto begins = src.begins();
735
736 T shiftedArg = shift_input(arg, begins[0]);
737
738 constexpr size_t rank =
739 Kokkos::Impl::ViewMapping<void /* deduce subview type from source view
740 traits */
741 ,
742 ViewTraits<D, P...>, T>::type::rank;
743
744 auto theSubview = Kokkos::subview(theView, shiftedArg);
745
746 Kokkos::Array<int64_t, rank> subviewBegins;
747 size_t counter = 0;
748 Kokkos::Experimental::Impl::map_arg_to_new_begin(0, subviewBegins, shiftedArg,
749 arg, begins, counter);
750
751 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
752 typename Kokkos::Impl::ViewMapping<void /* deduce subview type from source
753 view traits */
754 ,
755 ViewTraits<D, P...>, T>::type>::type
756 offsetView(theSubview, subviewBegins);
757
758 return offsetView;
759}
760
761template <class D, class... P, class T0, class T1>
762KOKKOS_INLINE_FUNCTION
763 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
764 typename Kokkos::Impl::ViewMapping<
765 void /* deduce subview type from source view traits */
766 ,
767 ViewTraits<D, P...>, T0, T1>::type>::type
768 subview_offset(const Kokkos::Experimental::OffsetView<D, P...>& src,
769 T0 arg0, T1 arg1) {
770 auto theView = src.view();
771 auto begins = src.begins();
772
773 T0 shiftedArg0 = shift_input(arg0, begins[0]);
774 T1 shiftedArg1 = shift_input(arg1, begins[1]);
775
776 auto theSubview = Kokkos::subview(theView, shiftedArg0, shiftedArg1);
777 constexpr size_t rank =
778 Kokkos::Impl::ViewMapping<void /* deduce subview type from source view
779 traits */
780 ,
781 ViewTraits<D, P...>, T0, T1>::type::rank;
782
783 Kokkos::Array<int64_t, rank> subviewBegins;
784 size_t counter = 0;
785 Kokkos::Experimental::Impl::map_arg_to_new_begin(
786 0, subviewBegins, shiftedArg0, arg0, begins, counter);
787 Kokkos::Experimental::Impl::map_arg_to_new_begin(
788 1, subviewBegins, shiftedArg1, arg1, begins, counter);
789
790 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
791 typename Kokkos::Impl::ViewMapping<
792 void /* deduce subview type from source view traits */
793 ,
794 ViewTraits<D, P...>, T0, T1>::type>::type offsetView(theSubview,
795 subviewBegins);
796
797 return offsetView;
798}
799
800template <class D, class... P, class T0, class T1, class T2>
801KOKKOS_INLINE_FUNCTION
802 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
803 typename Kokkos::Impl::ViewMapping<
804 void /* deduce subview type from source view traits */
805 ,
806 ViewTraits<D, P...>, T0, T1, T2>::type>::type
807 subview_offset(const OffsetView<D, P...>& src, T0 arg0, T1 arg1, T2 arg2) {
808 auto theView = src.view();
809 auto begins = src.begins();
810
811 T0 shiftedArg0 = shift_input(arg0, begins[0]);
812 T1 shiftedArg1 = shift_input(arg1, begins[1]);
813 T2 shiftedArg2 = shift_input(arg2, begins[2]);
814
815 auto theSubview =
816 Kokkos::subview(theView, shiftedArg0, shiftedArg1, shiftedArg2);
817
818 constexpr size_t rank =
819 Kokkos::Impl::ViewMapping<void /* deduce subview type from source view
820 traits */
821 ,
822 ViewTraits<D, P...>, T0, T1, T2>::type::rank;
823
824 Kokkos::Array<int64_t, rank> subviewBegins;
825
826 size_t counter = 0;
827 Kokkos::Experimental::Impl::map_arg_to_new_begin(
828 0, subviewBegins, shiftedArg0, arg0, begins, counter);
829 Kokkos::Experimental::Impl::map_arg_to_new_begin(
830 1, subviewBegins, shiftedArg1, arg1, begins, counter);
831 Kokkos::Experimental::Impl::map_arg_to_new_begin(
832 2, subviewBegins, shiftedArg2, arg2, begins, counter);
833
834 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
835 typename Kokkos::Impl::ViewMapping<
836 void /* deduce subview type from source view traits */
837 ,
838 ViewTraits<D, P...>, T0, T1, T2>::type>::type
839 offsetView(theSubview, subviewBegins);
840
841 return offsetView;
842}
843
844template <class D, class... P, class T0, class T1, class T2, class T3>
845KOKKOS_INLINE_FUNCTION
846 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
847 typename Kokkos::Impl::ViewMapping<
848 void /* deduce subview type from source view traits */
849 ,
850 ViewTraits<D, P...>, T0, T1, T2, T3>::type>::type
851 subview_offset(const OffsetView<D, P...>& src, T0 arg0, T1 arg1, T2 arg2,
852 T3 arg3) {
853 auto theView = src.view();
854 auto begins = src.begins();
855
856 T0 shiftedArg0 = shift_input(arg0, begins[0]);
857 T1 shiftedArg1 = shift_input(arg1, begins[1]);
858 T2 shiftedArg2 = shift_input(arg2, begins[2]);
859 T3 shiftedArg3 = shift_input(arg3, begins[3]);
860
861 auto theSubview = Kokkos::subview(theView, shiftedArg0, shiftedArg1,
862 shiftedArg2, shiftedArg3);
863
864 constexpr size_t rank = Kokkos::Impl::ViewMapping<
865 void /* deduce subview type from source view traits */
866 ,
867 ViewTraits<D, P...>, T0, T1, T2, T3>::type::rank;
868 Kokkos::Array<int64_t, rank> subviewBegins;
869
870 size_t counter = 0;
871 Kokkos::Experimental::Impl::map_arg_to_new_begin(
872 0, subviewBegins, shiftedArg0, arg0, begins, counter);
873 Kokkos::Experimental::Impl::map_arg_to_new_begin(
874 1, subviewBegins, shiftedArg1, arg1, begins, counter);
875 Kokkos::Experimental::Impl::map_arg_to_new_begin(
876 2, subviewBegins, shiftedArg2, arg2, begins, counter);
877 Kokkos::Experimental::Impl::map_arg_to_new_begin(
878 3, subviewBegins, shiftedArg3, arg3, begins, counter);
879
880 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
881 typename Kokkos::Impl::ViewMapping<
882 void /* deduce subview type from source view traits */
883 ,
884 ViewTraits<D, P...>, T0, T1, T2, T3>::type>::type
885 offsetView(theSubview, subviewBegins);
886
887 return offsetView;
888}
889
890template <class D, class... P, class T0, class T1, class T2, class T3, class T4>
891KOKKOS_INLINE_FUNCTION
892 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
893 typename Kokkos::Impl::ViewMapping<
894 void /* deduce subview type from source view traits */
895 ,
896 ViewTraits<D, P...>, T0, T1, T2, T3, T4>::type>::type
897 subview_offset(const OffsetView<D, P...>& src, T0 arg0, T1 arg1, T2 arg2,
898 T3 arg3, T4 arg4) {
899 auto theView = src.view();
900 auto begins = src.begins();
901
902 T0 shiftedArg0 = shift_input(arg0, begins[0]);
903 T1 shiftedArg1 = shift_input(arg1, begins[1]);
904 T2 shiftedArg2 = shift_input(arg2, begins[2]);
905 T3 shiftedArg3 = shift_input(arg3, begins[3]);
906 T4 shiftedArg4 = shift_input(arg4, begins[4]);
907
908 auto theSubview = Kokkos::subview(theView, shiftedArg0, shiftedArg1,
909 shiftedArg2, shiftedArg3, shiftedArg4);
910
911 constexpr size_t rank = Kokkos::Impl::ViewMapping<
912 void /* deduce subview type from source view traits */
913 ,
914 ViewTraits<D, P...>, T0, T1, T2, T3, T4>::type::rank;
915 Kokkos::Array<int64_t, rank> subviewBegins;
916
917 size_t counter = 0;
918 Kokkos::Experimental::Impl::map_arg_to_new_begin(
919 0, subviewBegins, shiftedArg0, arg0, begins, counter);
920 Kokkos::Experimental::Impl::map_arg_to_new_begin(
921 1, subviewBegins, shiftedArg1, arg1, begins, counter);
922 Kokkos::Experimental::Impl::map_arg_to_new_begin(
923 2, subviewBegins, shiftedArg2, arg2, begins, counter);
924 Kokkos::Experimental::Impl::map_arg_to_new_begin(
925 3, subviewBegins, shiftedArg3, arg3, begins, counter);
926 Kokkos::Experimental::Impl::map_arg_to_new_begin(
927 4, subviewBegins, shiftedArg4, arg4, begins, counter);
928
929 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
930 typename Kokkos::Impl::ViewMapping<
931 void /* deduce subview type from source view traits */
932 ,
933 ViewTraits<D, P...>, T0, T1, T2, T3, T4>::type>::type
934 offsetView(theSubview, subviewBegins);
935
936 return offsetView;
937}
938
939template <class D, class... P, class T0, class T1, class T2, class T3, class T4,
940 class T5>
941KOKKOS_INLINE_FUNCTION
942 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
943 typename Kokkos::Impl::ViewMapping<
944 void /* deduce subview type from source view traits */
945 ,
946 ViewTraits<D, P...>, T0, T1, T2, T3, T4, T5>::type>::type
947 subview_offset(const OffsetView<D, P...>& src, T0 arg0, T1 arg1, T2 arg2,
948 T3 arg3, T4 arg4, T5 arg5) {
949 auto theView = src.view();
950 auto begins = src.begins();
951
952 T0 shiftedArg0 = shift_input(arg0, begins[0]);
953 T1 shiftedArg1 = shift_input(arg1, begins[1]);
954 T2 shiftedArg2 = shift_input(arg2, begins[2]);
955 T3 shiftedArg3 = shift_input(arg3, begins[3]);
956 T4 shiftedArg4 = shift_input(arg4, begins[4]);
957 T5 shiftedArg5 = shift_input(arg5, begins[5]);
958
959 auto theSubview =
960 Kokkos::subview(theView, shiftedArg0, shiftedArg1, shiftedArg2,
961 shiftedArg3, shiftedArg4, shiftedArg5);
962
963 constexpr size_t rank = Kokkos::Impl::ViewMapping<
964 void /* deduce subview type from source view traits */
965 ,
966 ViewTraits<D, P...>, T0, T1, T2, T3, T4, T5>::type::rank;
967
968 Kokkos::Array<int64_t, rank> subviewBegins;
969
970 size_t counter = 0;
971 Kokkos::Experimental::Impl::map_arg_to_new_begin(
972 0, subviewBegins, shiftedArg0, arg0, begins, counter);
973 Kokkos::Experimental::Impl::map_arg_to_new_begin(
974 1, subviewBegins, shiftedArg1, arg1, begins, counter);
975 Kokkos::Experimental::Impl::map_arg_to_new_begin(
976 2, subviewBegins, shiftedArg2, arg2, begins, counter);
977 Kokkos::Experimental::Impl::map_arg_to_new_begin(
978 3, subviewBegins, shiftedArg3, arg3, begins, counter);
979 Kokkos::Experimental::Impl::map_arg_to_new_begin(
980 4, subviewBegins, shiftedArg4, arg4, begins, counter);
981 Kokkos::Experimental::Impl::map_arg_to_new_begin(
982 5, subviewBegins, shiftedArg5, arg5, begins, counter);
983
984 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
985 typename Kokkos::Impl::ViewMapping<
986 void /* deduce subview type from source view traits */
987 ,
988 ViewTraits<D, P...>, T0, T1, T2, T3, T4, T5>::type>::type
989 offsetView(theSubview, subviewBegins);
990
991 return offsetView;
992}
993template <class D, class... P, class T0, class T1, class T2, class T3, class T4,
994 class T5, class T6>
995KOKKOS_INLINE_FUNCTION
996 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
997 typename Kokkos::Impl::ViewMapping<
998 void /* deduce subview type from source view traits */
999 ,
1000 ViewTraits<D, P...>, T0, T1, T2, T3, T4, T5, T6>::type>::type
1001 subview_offset(const OffsetView<D, P...>& src, T0 arg0, T1 arg1, T2 arg2,
1002 T3 arg3, T4 arg4, T5 arg5, T6 arg6) {
1003 auto theView = src.view();
1004 auto begins = src.begins();
1005
1006 T0 shiftedArg0 = shift_input(arg0, begins[0]);
1007 T1 shiftedArg1 = shift_input(arg1, begins[1]);
1008 T2 shiftedArg2 = shift_input(arg2, begins[2]);
1009 T3 shiftedArg3 = shift_input(arg3, begins[3]);
1010 T4 shiftedArg4 = shift_input(arg4, begins[4]);
1011 T5 shiftedArg5 = shift_input(arg5, begins[5]);
1012 T6 shiftedArg6 = shift_input(arg6, begins[6]);
1013
1014 auto theSubview =
1015 Kokkos::subview(theView, shiftedArg0, shiftedArg1, shiftedArg2,
1016 shiftedArg3, shiftedArg4, shiftedArg5, shiftedArg6);
1017
1018 constexpr size_t rank = Kokkos::Impl::ViewMapping<
1019 void /* deduce subview type from source view traits */
1020 ,
1021 ViewTraits<D, P...>, T0, T1, T2, T3, T4, T5, T6>::type::rank;
1022
1023 Kokkos::Array<int64_t, rank> subviewBegins;
1024
1025 size_t counter = 0;
1026 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1027 0, subviewBegins, shiftedArg0, arg0, begins, counter);
1028 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1029 1, subviewBegins, shiftedArg1, arg1, begins, counter);
1030 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1031 2, subviewBegins, shiftedArg2, arg2, begins, counter);
1032 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1033 3, subviewBegins, shiftedArg3, arg3, begins, counter);
1034 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1035 4, subviewBegins, shiftedArg4, arg4, begins, counter);
1036 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1037 5, subviewBegins, shiftedArg5, arg5, begins, counter);
1038 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1039 6, subviewBegins, shiftedArg6, arg6, begins, counter);
1040
1041 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1042 typename Kokkos::Impl::ViewMapping<
1043 void /* deduce subview type from source view traits */
1044 ,
1045 ViewTraits<D, P...>, T0, T1, T2, T3, T4, T5, T6>::type>::type
1046 offsetView(theSubview, subviewBegins);
1047
1048 return offsetView;
1049}
1050
1051template <class D, class... P, class T0, class T1, class T2, class T3, class T4,
1052 class T5, class T6, class T7>
1053KOKKOS_INLINE_FUNCTION
1054 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1055 typename Kokkos::Impl::ViewMapping<
1056 void /* deduce subview type from source view traits */
1057 ,
1058 ViewTraits<D, P...>, T0, T1, T2, T3, T4, T5, T6, T7>::type>::type
1059 subview_offset(const OffsetView<D, P...>& src, T0 arg0, T1 arg1, T2 arg2,
1060 T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) {
1061 auto theView = src.view();
1062 auto begins = src.begins();
1063
1064 T0 shiftedArg0 = shift_input(arg0, begins[0]);
1065 T1 shiftedArg1 = shift_input(arg1, begins[1]);
1066 T2 shiftedArg2 = shift_input(arg2, begins[2]);
1067 T3 shiftedArg3 = shift_input(arg3, begins[3]);
1068 T4 shiftedArg4 = shift_input(arg4, begins[4]);
1069 T5 shiftedArg5 = shift_input(arg5, begins[5]);
1070 T6 shiftedArg6 = shift_input(arg6, begins[6]);
1071 T7 shiftedArg7 = shift_input(arg7, begins[7]);
1072
1073 auto theSubview = Kokkos::subview(theView, shiftedArg0, shiftedArg1,
1074 shiftedArg2, shiftedArg3, shiftedArg4,
1075 shiftedArg5, shiftedArg6, shiftedArg7);
1076
1077 constexpr size_t rank = Kokkos::Impl::ViewMapping<
1078 void /* deduce subview type from source view traits */
1079 ,
1080 ViewTraits<D, P...>, T0, T1, T2, T3, T4, T5, T6, T7>::type::rank;
1081
1082 Kokkos::Array<int64_t, rank> subviewBegins;
1083
1084 size_t counter = 0;
1085 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1086 0, subviewBegins, shiftedArg0, arg0, begins, counter);
1087 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1088 1, subviewBegins, shiftedArg1, arg1, begins, counter);
1089 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1090 2, subviewBegins, shiftedArg2, arg2, begins, counter);
1091 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1092 3, subviewBegins, shiftedArg3, arg3, begins, counter);
1093 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1094 4, subviewBegins, shiftedArg4, arg4, begins, counter);
1095 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1096 5, subviewBegins, shiftedArg5, arg5, begins, counter);
1097 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1098 6, subviewBegins, shiftedArg6, arg6, begins, counter);
1099 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1100 7, subviewBegins, shiftedArg7, arg7, begins, counter);
1101
1102 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1103 typename Kokkos::Impl::ViewMapping<
1104 void /* deduce subview type from source view traits */
1105 ,
1106 ViewTraits<D, P...>, T0, T1, T2, T3, T4, T5, T6, T7>::type>::type
1107 offsetView(theSubview, subviewBegins);
1108
1109 return offsetView;
1110}
1111} // namespace Impl
1112
1113template <class D, class... P, class... Args>
1114KOKKOS_INLINE_FUNCTION
1115 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1116 typename Kokkos::Impl::ViewMapping<
1117 void /* deduce subview type from source view traits */
1118 ,
1119 ViewTraits<D, P...>, Args...>::type>::type
1120 subview(const OffsetView<D, P...>& src, Args... args) {
1121 static_assert(
1122 OffsetView<D, P...>::rank() == sizeof...(Args),
1123 "subview requires one argument for each source OffsetView rank");
1124
1125 return Kokkos::Experimental::Impl::subview_offset(src, args...);
1126}
1127
1128} // namespace Experimental
1129} // namespace Kokkos
1130//----------------------------------------------------------------------------
1131//----------------------------------------------------------------------------
1132
1133namespace Kokkos {
1134namespace Experimental {
1135template <class LT, class... LP, class RT, class... RP>
1136KOKKOS_INLINE_FUNCTION bool operator==(const OffsetView<LT, LP...>& lhs,
1137 const OffsetView<RT, RP...>& rhs) {
1138 // Same data, layout, dimensions
1139 using lhs_traits = ViewTraits<LT, LP...>;
1140 using rhs_traits = ViewTraits<RT, RP...>;
1141
1142 return std::is_same_v<typename lhs_traits::const_value_type,
1143 typename rhs_traits::const_value_type> &&
1144 std::is_same_v<typename lhs_traits::array_layout,
1145 typename rhs_traits::array_layout> &&
1146 std::is_same_v<typename lhs_traits::memory_space,
1147 typename rhs_traits::memory_space> &&
1148 unsigned(lhs_traits::rank) == unsigned(rhs_traits::rank) &&
1149 lhs.data() == rhs.data() && lhs.span() == rhs.span() &&
1150 lhs.extent(0) == rhs.extent(0) && lhs.extent(1) == rhs.extent(1) &&
1151 lhs.extent(2) == rhs.extent(2) && lhs.extent(3) == rhs.extent(3) &&
1152 lhs.extent(4) == rhs.extent(4) && lhs.extent(5) == rhs.extent(5) &&
1153 lhs.extent(6) == rhs.extent(6) && lhs.extent(7) == rhs.extent(7) &&
1154 lhs.begin(0) == rhs.begin(0) && lhs.begin(1) == rhs.begin(1) &&
1155 lhs.begin(2) == rhs.begin(2) && lhs.begin(3) == rhs.begin(3) &&
1156 lhs.begin(4) == rhs.begin(4) && lhs.begin(5) == rhs.begin(5) &&
1157 lhs.begin(6) == rhs.begin(6) && lhs.begin(7) == rhs.begin(7);
1158}
1159
1160template <class LT, class... LP, class RT, class... RP>
1161KOKKOS_INLINE_FUNCTION bool operator!=(const OffsetView<LT, LP...>& lhs,
1162 const OffsetView<RT, RP...>& rhs) {
1163 return !(operator==(lhs, rhs));
1164}
1165
1166template <class LT, class... LP, class RT, class... RP>
1167KOKKOS_INLINE_FUNCTION bool operator==(const View<LT, LP...>& lhs,
1168 const OffsetView<RT, RP...>& rhs) {
1169 // Same data, layout, dimensions
1170 using lhs_traits = ViewTraits<LT, LP...>;
1171 using rhs_traits = ViewTraits<RT, RP...>;
1172
1173 return std::is_same_v<typename lhs_traits::const_value_type,
1174 typename rhs_traits::const_value_type> &&
1175 std::is_same_v<typename lhs_traits::array_layout,
1176 typename rhs_traits::array_layout> &&
1177 std::is_same_v<typename lhs_traits::memory_space,
1178 typename rhs_traits::memory_space> &&
1179 unsigned(lhs_traits::rank) == unsigned(rhs_traits::rank) &&
1180 lhs.data() == rhs.data() && lhs.span() == rhs.span() &&
1181 lhs.extent(0) == rhs.extent(0) && lhs.extent(1) == rhs.extent(1) &&
1182 lhs.extent(2) == rhs.extent(2) && lhs.extent(3) == rhs.extent(3) &&
1183 lhs.extent(4) == rhs.extent(4) && lhs.extent(5) == rhs.extent(5) &&
1184 lhs.extent(6) == rhs.extent(6) && lhs.extent(7) == rhs.extent(7);
1185}
1186
1187template <class LT, class... LP, class RT, class... RP>
1188KOKKOS_INLINE_FUNCTION bool operator==(const OffsetView<LT, LP...>& lhs,
1189 const View<RT, RP...>& rhs) {
1190 return rhs == lhs;
1191}
1192
1193} // namespace Experimental
1194} /* namespace Kokkos */
1195
1196//----------------------------------------------------------------------------
1197//----------------------------------------------------------------------------
1198
1199namespace Kokkos {
1200
1201template <class DT, class... DP>
1202inline void deep_copy(
1203 const Experimental::OffsetView<DT, DP...>& dst,
1204 typename ViewTraits<DT, DP...>::const_value_type& value,
1205 std::enable_if_t<std::is_same_v<typename ViewTraits<DT, DP...>::specialize,
1206 void>>* = nullptr) {
1207 static_assert(
1208 std::is_same_v<typename ViewTraits<DT, DP...>::non_const_value_type,
1209 typename ViewTraits<DT, DP...>::value_type>,
1210 "deep_copy requires non-const type");
1211
1212 auto dstView = dst.view();
1213 Kokkos::deep_copy(dstView, value);
1214}
1215
1216template <class DT, class... DP, class ST, class... SP>
1217inline void deep_copy(
1218 const Experimental::OffsetView<DT, DP...>& dst,
1219 const Experimental::OffsetView<ST, SP...>& value,
1220 std::enable_if_t<std::is_same_v<typename ViewTraits<DT, DP...>::specialize,
1221 void>>* = nullptr) {
1222 static_assert(
1223 std::is_same_v<typename ViewTraits<DT, DP...>::value_type,
1224 typename ViewTraits<ST, SP...>::non_const_value_type>,
1225 "deep_copy requires matching non-const destination type");
1226
1227 auto dstView = dst.view();
1228 Kokkos::deep_copy(dstView, value.view());
1229}
1230template <class DT, class... DP, class ST, class... SP>
1231inline void deep_copy(
1232 const Experimental::OffsetView<DT, DP...>& dst,
1233 const View<ST, SP...>& value,
1234 std::enable_if_t<std::is_same_v<typename ViewTraits<DT, DP...>::specialize,
1235 void>>* = nullptr) {
1236 static_assert(
1237 std::is_same_v<typename ViewTraits<DT, DP...>::value_type,
1238 typename ViewTraits<ST, SP...>::non_const_value_type>,
1239 "deep_copy requires matching non-const destination type");
1240
1241 auto dstView = dst.view();
1242 Kokkos::deep_copy(dstView, value);
1243}
1244
1245template <class DT, class... DP, class ST, class... SP>
1246inline void deep_copy(
1247 const View<DT, DP...>& dst,
1248 const Experimental::OffsetView<ST, SP...>& value,
1249 std::enable_if_t<std::is_same_v<typename ViewTraits<DT, DP...>::specialize,
1250 void>>* = nullptr) {
1251 static_assert(
1252 std::is_same_v<typename ViewTraits<DT, DP...>::value_type,
1253 typename ViewTraits<ST, SP...>::non_const_value_type>,
1254 "deep_copy requires matching non-const destination type");
1255
1256 Kokkos::deep_copy(dst, value.view());
1257}
1258
1259namespace Impl {
1260
1261// Deduce Mirror Types
1262template <class Space, class T, class... P>
1263struct MirrorOffsetViewType {
1264 // The incoming view_type
1265 using src_view_type = typename Kokkos::Experimental::OffsetView<T, P...>;
1266 // The memory space for the mirror view
1267 using memory_space = typename Space::memory_space;
1268 // Check whether it is the same memory space
1269 enum {
1270 is_same_memspace =
1271 std::is_same_v<memory_space, typename src_view_type::memory_space>
1272 };
1273 // The array_layout
1274 using array_layout = typename src_view_type::array_layout;
1275 // The data type (we probably want it non-const since otherwise we can't even
1276 // deep_copy to it.)
1277 using data_type = typename src_view_type::non_const_data_type;
1278 // The destination view type if it is not the same memory space
1279 using dest_view_type =
1280 Kokkos::Experimental::OffsetView<data_type, array_layout, Space>;
1281 // If it is the same memory_space return the existing view_type
1282 // This will also keep the unmanaged trait if necessary
1283 using view_type =
1284 std::conditional_t<is_same_memspace, src_view_type, dest_view_type>;
1285};
1286
1287} // namespace Impl
1288
1289namespace Impl {
1290
1291// create a mirror
1292// private interface that accepts arbitrary view constructor args passed by a
1293// view_alloc
1294template <class T, class... P, class... ViewCtorArgs>
1295inline auto create_mirror(const Kokkos::Experimental::OffsetView<T, P...>& src,
1296 const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop) {
1297 check_view_ctor_args_create_mirror<ViewCtorArgs...>();
1298
1299 if constexpr (Impl::ViewCtorProp<ViewCtorArgs...>::has_memory_space) {
1300 using Space = typename Impl::ViewCtorProp<ViewCtorArgs...>::memory_space;
1301
1302 auto prop_copy = Impl::with_properties_if_unset(
1303 arg_prop, std::string(src.label()).append("_mirror"));
1304
1305 return typename Kokkos::Impl::MirrorOffsetViewType<
1306 Space, T, P...>::dest_view_type(prop_copy, src.layout(),
1307 {src.begin(0), src.begin(1),
1308 src.begin(2), src.begin(3),
1309 src.begin(4), src.begin(5),
1310 src.begin(6), src.begin(7)});
1311 } else {
1313 Kokkos::create_mirror(arg_prop, src.view()), src.begins());
1314 }
1315#if defined(KOKKOS_COMPILER_NVCC) && KOKKOS_COMPILER_NVCC >= 1130 && \
1316 !defined(KOKKOS_COMPILER_MSVC)
1317 __builtin_unreachable();
1318#endif
1319}
1320
1321} // namespace Impl
1322
1323// public interface
1324template <class T, class... P,
1325 typename = std::enable_if_t<
1326 std::is_void_v<typename ViewTraits<T, P...>::specialize>>>
1327inline auto create_mirror(
1328 const Kokkos::Experimental::OffsetView<T, P...>& src) {
1329 return Impl::create_mirror(src, Impl::ViewCtorProp<>{});
1330}
1331
1332// public interface that accepts a without initializing flag
1333template <class T, class... P,
1334 typename = std::enable_if_t<
1335 std::is_void_v<typename ViewTraits<T, P...>::specialize>>>
1336inline auto create_mirror(
1337 Kokkos::Impl::WithoutInitializing_t wi,
1338 const Kokkos::Experimental::OffsetView<T, P...>& src) {
1339 return Impl::create_mirror(src, Kokkos::view_alloc(wi));
1340}
1341
1342// public interface that accepts a space
1343template <class Space, class T, class... P,
1344 typename Enable = std::enable_if_t<
1345 Kokkos::is_space<Space>::value &&
1346 std::is_void_v<typename ViewTraits<T, P...>::specialize>>>
1347inline auto create_mirror(
1348 const Space&, const Kokkos::Experimental::OffsetView<T, P...>& src) {
1349 return Impl::create_mirror(
1350 src, Kokkos::view_alloc(typename Space::memory_space{}));
1351}
1352
1353// public interface that accepts a space and a without initializing flag
1354template <class Space, class T, class... P,
1355 typename Enable = std::enable_if_t<
1356 Kokkos::is_space<Space>::value &&
1357 std::is_void_v<typename ViewTraits<T, P...>::specialize>>>
1358inline auto create_mirror(
1359 Kokkos::Impl::WithoutInitializing_t wi, const Space&,
1360 const Kokkos::Experimental::OffsetView<T, P...>& src) {
1361 return Impl::create_mirror(
1362 src, Kokkos::view_alloc(typename Space::memory_space{}, wi));
1363}
1364
1365// public interface that accepts arbitrary view constructor args passed by a
1366// view_alloc
1367template <class T, class... P, class... ViewCtorArgs,
1368 typename = std::enable_if_t<
1369 std::is_void_v<typename ViewTraits<T, P...>::specialize>>>
1370inline auto create_mirror(
1371 const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
1372 const Kokkos::Experimental::OffsetView<T, P...>& src) {
1373 return Impl::create_mirror(src, arg_prop);
1374}
1375
1376namespace Impl {
1377
1378// create a mirror view
1379// private interface that accepts arbitrary view constructor args passed by a
1380// view_alloc
1381template <class T, class... P, class... ViewCtorArgs>
1382inline auto create_mirror_view(
1383 const Kokkos::Experimental::OffsetView<T, P...>& src,
1384 [[maybe_unused]] const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop) {
1385 if constexpr (!Impl::ViewCtorProp<ViewCtorArgs...>::has_memory_space) {
1386 if constexpr (std::is_same_v<typename Kokkos::Experimental::OffsetView<
1387 T, P...>::memory_space,
1388 typename Kokkos::Experimental::OffsetView<
1389 T, P...>::HostMirror::memory_space> &&
1390 std::is_same_v<typename Kokkos::Experimental::OffsetView<
1391 T, P...>::data_type,
1392 typename Kokkos::Experimental::OffsetView<
1393 T, P...>::HostMirror::data_type>) {
1394 return
1396 } else {
1397 return Kokkos::Impl::choose_create_mirror(src, arg_prop);
1398 }
1399 } else {
1400 if constexpr (Impl::MirrorOffsetViewType<typename Impl::ViewCtorProp<
1401 ViewCtorArgs...>::memory_space,
1402 T, P...>::is_same_memspace) {
1403 return typename Impl::MirrorOffsetViewType<
1404 typename Impl::ViewCtorProp<ViewCtorArgs...>::memory_space, T,
1405 P...>::view_type(src);
1406 } else {
1407 return Kokkos::Impl::choose_create_mirror(src, arg_prop);
1408 }
1409 }
1410#if defined(KOKKOS_COMPILER_NVCC) && KOKKOS_COMPILER_NVCC >= 1130 && \
1411 !defined(KOKKOS_COMPILER_MSVC)
1412 __builtin_unreachable();
1413#endif
1414}
1415
1416} // namespace Impl
1417
1418// public interface
1419template <class T, class... P>
1420inline auto create_mirror_view(
1421 const typename Kokkos::Experimental::OffsetView<T, P...>& src) {
1422 return Impl::create_mirror_view(src, Impl::ViewCtorProp<>{});
1423}
1424
1425// public interface that accepts a without initializing flag
1426template <class T, class... P>
1427inline auto create_mirror_view(
1428 Kokkos::Impl::WithoutInitializing_t wi,
1429 const typename Kokkos::Experimental::OffsetView<T, P...>& src) {
1430 return Impl::create_mirror_view(src, Kokkos::view_alloc(wi));
1431}
1432
1433// public interface that accepts a space
1434template <class Space, class T, class... P,
1435 typename Enable = std::enable_if_t<Kokkos::is_space<Space>::value>>
1436inline auto create_mirror_view(
1437 const Space&, const Kokkos::Experimental::OffsetView<T, P...>& src) {
1438 return Impl::create_mirror_view(
1439 src, Kokkos::view_alloc(typename Space::memory_space{}));
1440}
1441
1442// public interface that accepts a space and a without initializing flag
1443template <class Space, class T, class... P,
1444 typename Enable = std::enable_if_t<Kokkos::is_space<Space>::value>>
1445inline auto create_mirror_view(
1446 Kokkos::Impl::WithoutInitializing_t wi, const Space&,
1447 const Kokkos::Experimental::OffsetView<T, P...>& src) {
1448 return Impl::create_mirror_view(
1449 src, Kokkos::view_alloc(typename Space::memory_space{}, wi));
1450}
1451
1452// public interface that accepts arbitrary view constructor args passed by a
1453// view_alloc
1454template <class T, class... P, class... ViewCtorArgs>
1455inline auto create_mirror_view(
1456 const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
1457 const Kokkos::Experimental::OffsetView<T, P...>& src) {
1458 return Impl::create_mirror_view(src, arg_prop);
1459}
1460
1461// create a mirror view and deep copy it
1462// public interface that accepts arbitrary view constructor args passed by a
1463// view_alloc
1464template <class... ViewCtorArgs, class T, class... P>
1465typename Kokkos::Impl::MirrorOffsetViewType<
1466 typename Impl::ViewCtorProp<ViewCtorArgs...>::memory_space, T,
1467 P...>::view_type
1468create_mirror_view_and_copy(
1469 const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
1470 const Kokkos::Experimental::OffsetView<T, P...>& src) {
1471 return {create_mirror_view_and_copy(arg_prop, src.view()), src.begins()};
1472}
1473
1474template <class Space, class T, class... P>
1475typename Kokkos::Impl::MirrorOffsetViewType<Space, T, P...>::view_type
1476create_mirror_view_and_copy(
1477 const Space& space, const Kokkos::Experimental::OffsetView<T, P...>& src,
1478 std::string const& name = "") {
1479 return {create_mirror_view_and_copy(space, src.view(), name), src.begins()};
1480}
1481} /* namespace Kokkos */
1482
1483//----------------------------------------------------------------------------
1484//----------------------------------------------------------------------------
1485
1486#ifdef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_OFFSETVIEW
1487#undef KOKKOS_IMPL_PUBLIC_INCLUDE
1488#undef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_OFFSETVIEW
1489#endif
1490#endif /* KOKKOS_OFFSETVIEW_HPP_ */
A thread safe view to a bitset.
KOKKOS_FORCEINLINE_FUNCTION unsigned size() const
Derived from the C++17 'std::array'. Dropping the iterator interface.