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