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