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