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