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