Kokkos Core Kernels Package  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
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 
28 namespace Kokkos {
29 
30 namespace Experimental {
31 //----------------------------------------------------------------------------
32 //----------------------------------------------------------------------------
33 
34 template <class DataType, class... Properties>
35 class OffsetView;
36 
37 template <class>
38 struct is_offset_view : public std::false_type {};
39 
40 template <class D, class... P>
41 struct is_offset_view<OffsetView<D, P...>> : public std::true_type {};
42 
43 template <class D, class... P>
44 struct is_offset_view<const OffsetView<D, P...>> : public std::true_type {};
45 
46 template <class T>
47 inline 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 
53 template <typename iType,
54  std::enable_if_t<std::is_integral_v<iType> && std::is_signed_v<iType>,
55  iType> = 0>
56 using IndexRange = Kokkos::Array<iType, 2>;
57 
58 using 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 
65 namespace Impl {
66 
67 template <class ViewType>
68 struct 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 
75 template <unsigned, class MapType, class BeginsType>
76 KOKKOS_INLINE_FUNCTION bool offsetview_verify_operator_bounds(
77  const MapType&, const BeginsType&) {
78  return true;
79 }
80 
81 template <unsigned R, class MapType, class BeginsType, class iType,
82  class... Args>
83 KOKKOS_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 }
92 template <unsigned, class MapType, class BeginsType>
93 inline void offsetview_error_operator_bounds(char*, int, const MapType&,
94  const BeginsType&) {}
95 
96 template <unsigned R, class MapType, class BeginsType, class iType,
97  class... Args>
98 inline 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 
112 template <class MemorySpace, class MapType, class BeginsType, class... Args>
113 KOKKOS_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 
132 inline 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 
163 KOKKOS_INLINE_FUNCTION
164 void 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 
182 template <class DataType, class... Properties>
183 class 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<pointer_type, typename Kokkos::Impl::ViewCtorProp<
655  P...>::pointer_type>::value,
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 
676 template <typename D, class... P>
677 KOKKOS_INLINE_FUNCTION constexpr unsigned rank(const OffsetView<D, P...>& V) {
678  return V.rank();
679 } // Temporary until added to view
680 
681 //----------------------------------------------------------------------------
682 //----------------------------------------------------------------------------
683 namespace Impl {
684 
685 template <class T>
686 KOKKOS_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 
691 KOKKOS_INLINE_FUNCTION
692 Kokkos::ALL_t shift_input(const Kokkos::ALL_t arg, const int64_t /*offset*/) {
693  return arg;
694 }
695 
696 template <class T>
697 KOKKOS_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 }
702 template <class T>
703 inline 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 
708 template <size_t N, class Arg, class A>
709 KOKKOS_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 
719 template <size_t N, class Arg, class A>
720 KOKKOS_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 
725 template <class D, class... P, class T>
726 KOKKOS_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 
761 template <class D, class... P, class T0, class T1>
762 KOKKOS_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 
800 template <class D, class... P, class T0, class T1, class T2>
801 KOKKOS_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 
844 template <class D, class... P, class T0, class T1, class T2, class T3>
845 KOKKOS_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 
890 template <class D, class... P, class T0, class T1, class T2, class T3, class T4>
891 KOKKOS_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 
939 template <class D, class... P, class T0, class T1, class T2, class T3, class T4,
940  class T5>
941 KOKKOS_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 }
993 template <class D, class... P, class T0, class T1, class T2, class T3, class T4,
994  class T5, class T6>
995 KOKKOS_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 
1051 template <class D, class... P, class T0, class T1, class T2, class T3, class T4,
1052  class T5, class T6, class T7>
1053 KOKKOS_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 
1113 template <class D, class... P, class... Args>
1114 KOKKOS_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 
1133 namespace Kokkos {
1134 namespace Experimental {
1135 template <class LT, class... LP, class RT, class... RP>
1136 KOKKOS_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 
1160 template <class LT, class... LP, class RT, class... RP>
1161 KOKKOS_INLINE_FUNCTION bool operator!=(const OffsetView<LT, LP...>& lhs,
1162  const OffsetView<RT, RP...>& rhs) {
1163  return !(operator==(lhs, rhs));
1164 }
1165 
1166 template <class LT, class... LP, class RT, class... RP>
1167 KOKKOS_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 
1187 template <class LT, class... LP, class RT, class... RP>
1188 KOKKOS_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 
1199 namespace Kokkos {
1200 
1201 template <class DT, class... DP>
1202 inline 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 
1216 template <class DT, class... DP, class ST, class... SP>
1217 inline 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 }
1230 template <class DT, class... DP, class ST, class... SP>
1231 inline 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 
1245 template <class DT, class... DP, class ST, class... SP>
1246 inline 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 
1259 namespace Impl {
1260 
1261 // Deduce Mirror Types
1262 template <class Space, class T, class... P>
1263 struct 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 
1289 namespace Impl {
1290 
1291 // create a mirror
1292 // private interface that accepts arbitrary view constructor args passed by a
1293 // view_alloc
1294 template <class T, class... P, class... ViewCtorArgs>
1295 inline 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 {
1312  return typename Kokkos::Experimental::OffsetView<T, P...>::HostMirror(
1313  Kokkos::create_mirror(arg_prop, src.view()), src.begins());
1314  }
1315 #if defined(KOKKOS_COMPILER_INTEL) || \
1316  (defined(KOKKOS_COMPILER_NVCC) && KOKKOS_COMPILER_NVCC >= 1130 && \
1317  !defined(KOKKOS_COMPILER_MSVC))
1318  __builtin_unreachable();
1319 #endif
1320 }
1321 
1322 } // namespace Impl
1323 
1324 // public interface
1325 template <class T, class... P,
1326  typename = std::enable_if_t<
1327  std::is_void_v<typename ViewTraits<T, P...>::specialize>>>
1328 inline auto create_mirror(
1329  const Kokkos::Experimental::OffsetView<T, P...>& src) {
1330  return Impl::create_mirror(src, Impl::ViewCtorProp<>{});
1331 }
1332 
1333 // public interface that accepts a without initializing flag
1334 template <class T, class... P,
1335  typename = std::enable_if_t<
1336  std::is_void_v<typename ViewTraits<T, P...>::specialize>>>
1337 inline auto create_mirror(
1338  Kokkos::Impl::WithoutInitializing_t wi,
1339  const Kokkos::Experimental::OffsetView<T, P...>& src) {
1340  return Impl::create_mirror(src, Kokkos::view_alloc(wi));
1341 }
1342 
1343 // public interface that accepts a space
1344 template <class Space, class T, class... P,
1345  typename Enable = std::enable_if_t<
1346  Kokkos::is_space<Space>::value &&
1347  std::is_void_v<typename ViewTraits<T, P...>::specialize>>>
1348 inline auto create_mirror(
1349  const Space&, const Kokkos::Experimental::OffsetView<T, P...>& src) {
1350  return Impl::create_mirror(
1351  src, Kokkos::view_alloc(typename Space::memory_space{}));
1352 }
1353 
1354 // public interface that accepts a space and a without initializing flag
1355 template <class Space, class T, class... P,
1356  typename Enable = std::enable_if_t<
1357  Kokkos::is_space<Space>::value &&
1358  std::is_void_v<typename ViewTraits<T, P...>::specialize>>>
1359 inline auto create_mirror(
1360  Kokkos::Impl::WithoutInitializing_t wi, const Space&,
1361  const Kokkos::Experimental::OffsetView<T, P...>& src) {
1362  return Impl::create_mirror(
1363  src, Kokkos::view_alloc(typename Space::memory_space{}, wi));
1364 }
1365 
1366 // public interface that accepts arbitrary view constructor args passed by a
1367 // view_alloc
1368 template <class T, class... P, class... ViewCtorArgs,
1369  typename = std::enable_if_t<
1370  std::is_void_v<typename ViewTraits<T, P...>::specialize>>>
1371 inline auto create_mirror(
1372  const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
1373  const Kokkos::Experimental::OffsetView<T, P...>& src) {
1374  return Impl::create_mirror(src, arg_prop);
1375 }
1376 
1377 namespace Impl {
1378 
1379 // create a mirror view
1380 // private interface that accepts arbitrary view constructor args passed by a
1381 // view_alloc
1382 template <class T, class... P, class... ViewCtorArgs>
1383 inline auto create_mirror_view(
1384  const Kokkos::Experimental::OffsetView<T, P...>& src,
1385  [[maybe_unused]] const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop) {
1386  if constexpr (!Impl::ViewCtorProp<ViewCtorArgs...>::has_memory_space) {
1387  if constexpr (std::is_same_v<typename Kokkos::Experimental::OffsetView<
1388  T, P...>::memory_space,
1389  typename Kokkos::Experimental::OffsetView<
1390  T, P...>::HostMirror::memory_space> &&
1391  std::is_same_v<typename Kokkos::Experimental::OffsetView<
1392  T, P...>::data_type,
1393  typename Kokkos::Experimental::OffsetView<
1394  T, P...>::HostMirror::data_type>) {
1395  return
1396  typename Kokkos::Experimental::OffsetView<T, P...>::HostMirror(src);
1397  } else {
1398  return Kokkos::Impl::choose_create_mirror(src, arg_prop);
1399  }
1400  } else {
1401  if constexpr (Impl::MirrorOffsetViewType<typename Impl::ViewCtorProp<
1402  ViewCtorArgs...>::memory_space,
1403  T, P...>::is_same_memspace) {
1404  return typename Impl::MirrorOffsetViewType<
1405  typename Impl::ViewCtorProp<ViewCtorArgs...>::memory_space, T,
1406  P...>::view_type(src);
1407  } else {
1408  return Kokkos::Impl::choose_create_mirror(src, arg_prop);
1409  }
1410  }
1411 #if defined(KOKKOS_COMPILER_INTEL) || \
1412  (defined(KOKKOS_COMPILER_NVCC) && KOKKOS_COMPILER_NVCC >= 1130 && \
1413  !defined(KOKKOS_COMPILER_MSVC))
1414  __builtin_unreachable();
1415 #endif
1416 }
1417 
1418 } // namespace Impl
1419 
1420 // public interface
1421 template <class T, class... P>
1422 inline auto create_mirror_view(
1423  const typename Kokkos::Experimental::OffsetView<T, P...>& src) {
1424  return Impl::create_mirror_view(src, Impl::ViewCtorProp<>{});
1425 }
1426 
1427 // public interface that accepts a without initializing flag
1428 template <class T, class... P>
1429 inline auto create_mirror_view(
1430  Kokkos::Impl::WithoutInitializing_t wi,
1431  const typename Kokkos::Experimental::OffsetView<T, P...>& src) {
1432  return Impl::create_mirror_view(src, Kokkos::view_alloc(wi));
1433 }
1434 
1435 // public interface that accepts a space
1436 template <class Space, class T, class... P,
1437  typename Enable = std::enable_if_t<Kokkos::is_space<Space>::value>>
1438 inline auto create_mirror_view(
1439  const Space&, const Kokkos::Experimental::OffsetView<T, P...>& src) {
1440  return Impl::create_mirror_view(
1441  src, Kokkos::view_alloc(typename Space::memory_space{}));
1442 }
1443 
1444 // public interface that accepts a space and a without initializing flag
1445 template <class Space, class T, class... P,
1446  typename Enable = std::enable_if_t<Kokkos::is_space<Space>::value>>
1447 inline auto create_mirror_view(
1448  Kokkos::Impl::WithoutInitializing_t wi, const Space&,
1449  const Kokkos::Experimental::OffsetView<T, P...>& src) {
1450  return Impl::create_mirror_view(
1451  src, Kokkos::view_alloc(typename Space::memory_space{}, wi));
1452 }
1453 
1454 // public interface that accepts arbitrary view constructor args passed by a
1455 // view_alloc
1456 template <class T, class... P, class... ViewCtorArgs>
1457 inline auto create_mirror_view(
1458  const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
1459  const Kokkos::Experimental::OffsetView<T, P...>& src) {
1460  return Impl::create_mirror_view(src, arg_prop);
1461 }
1462 
1463 // create a mirror view and deep copy it
1464 // public interface that accepts arbitrary view constructor args passed by a
1465 // view_alloc
1466 template <class... ViewCtorArgs, class T, class... P>
1467 typename Kokkos::Impl::MirrorOffsetViewType<
1468  typename Impl::ViewCtorProp<ViewCtorArgs...>::memory_space, T,
1469  P...>::view_type
1470 create_mirror_view_and_copy(
1471  const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
1472  const Kokkos::Experimental::OffsetView<T, P...>& src) {
1473  return {create_mirror_view_and_copy(arg_prop, src.view()), src.begins()};
1474 }
1475 
1476 template <class Space, class T, class... P>
1477 typename Kokkos::Impl::MirrorOffsetViewType<Space, T, P...>::view_type
1478 create_mirror_view_and_copy(
1479  const Space& space, const Kokkos::Experimental::OffsetView<T, P...>& src,
1480  std::string const& name = "") {
1481  return {create_mirror_view_and_copy(space, src.view(), name), src.begins()};
1482 }
1483 } /* namespace Kokkos */
1484 
1485 //----------------------------------------------------------------------------
1486 //----------------------------------------------------------------------------
1487 
1488 #ifdef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_OFFSETVIEW
1489 #undef KOKKOS_IMPL_PUBLIC_INCLUDE
1490 #undef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_OFFSETVIEW
1491 #endif
1492 #endif /* KOKKOS_OFFSETVIEW_HPP_ */
Derived from the C++17 &#39;std::array&#39;. Dropping the iterator interface.
Replacement for std::pair that works on CUDA devices.
Definition: Kokkos_Pair.hpp:44
first_type first
The first element of the pair.
Definition: Kokkos_Pair.hpp:51
second_type second
The second element of the pair.
Definition: Kokkos_Pair.hpp:53