Low-Level Abstraction of Memory Access
View.hpp
Go to the documentation of this file.
1 // Copyright 2022 Alexander Matthes, Bernhard Manfred Gruber
2 // SPDX-License-Identifier: MPL-2.0
3 
4 #pragma once
5 
6 #include "Accessors.hpp"
7 #include "Array.hpp"
8 #include "ArrayIndexRange.hpp"
9 #include "BlobAllocators.hpp"
10 #include "Concepts.hpp"
11 #include "Core.hpp"
12 #include "macros.hpp"
13 #include "mapping/One.hpp"
14 
15 #include <type_traits>
16 
17 namespace llama
18 {
20 #ifdef __cpp_lib_concepts
21  template<typename TMapping, Blob BlobType, typename TAccessor>
22 #else
23  template<typename TMapping, typename BlobType, typename TAccessor>
24 #endif
25  struct View;
26 
27  namespace internal
28  {
29  template<typename Allocator, typename RecordDim>
31  = decltype(std::declval<Allocator>()(std::integral_constant<std::size_t, alignOf<RecordDim>>{}, 0));
32 
33  template<typename Allocator, typename Mapping, std::size_t... Is>
35  const Allocator& alloc,
36  const Mapping& mapping,
37  std::integer_sequence<std::size_t, Is...>)
39  {
40  [[maybe_unused]] constexpr auto alignment
41  = alignOf<typename Mapping::RecordDim>; // g++-12 warns that alignment is unused
43  return {alloc(std::integral_constant<std::size_t, alignment>{}, mapping.blobSize(Is))...};
45  } // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
46  } // namespace internal
47 
50 #ifdef __cpp_lib_concepts
51  template<typename Mapping, BlobAllocator Allocator = bloballoc::Vector, typename Accessor = accessor::Default>
52 #else
53  template<typename Mapping, typename Allocator = bloballoc::Vector, typename Accessor = accessor::Default>
54 #endif
56  Mapping mapping = {},
57  const Allocator& alloc = {},
58  Accessor accessor = {})
59  {
60  auto blobs = internal::makeBlobArray(alloc, mapping, std::make_index_sequence<Mapping::blobCount>{});
61  return View<Mapping, internal::AllocatorBlobType<Allocator, typename Mapping::RecordDim>, Accessor>{
62  std::move(mapping),
63  std::move(blobs),
64  std::move(accessor)};
65  }
66 
67  namespace internal
68  {
69  template<typename Mapping, typename RecordCoord, typename = void>
70  struct IsComputed : std::false_type
71  {
72  };
73 
74  template<typename Mapping, typename RecordCoord>
75  struct IsComputed<Mapping, RecordCoord, std::void_t<decltype(Mapping::isComputed(RecordCoord{}))>>
76  : std::bool_constant<Mapping::isComputed(RecordCoord{})>
77  {
78  };
79  } // namespace internal
80 
83  template<typename Mapping, typename RecordCoord>
85 
87  // TODO(bgruber): harmonize this with LLAMA's concepts from Concepts.hpp
89  template<typename Mapping>
90  inline constexpr bool hasAnyComputedField = mp_any_of<
92  mp_bind_front<internal::IsComputed, Mapping>::template fn>::value;
93 
95  template<typename Mapping, typename BlobType, typename Accessor, std::size_t... RCs>
98  typename Mapping::ArrayExtents::Index ai,
100  {
101  auto init = [](auto&& ref) LLAMA_LAMBDA_INLINE
102  {
103  using FieldType = GetType<typename Mapping::RecordDim, RecordCoord<RCs...>>;
104  using RefType = decltype(ref);
105  if constexpr(isProxyReference<std::remove_reference_t<RefType>>)
106  {
107  ref = FieldType{};
108  }
109  else if constexpr(
110  std::is_lvalue_reference_v<RefType> && !std::is_const_v<std::remove_reference_t<RefType>>)
111  {
112  new(&ref) FieldType{};
113  }
114  };
115 
116  // this handles physical and computed mappings
117  if constexpr(sizeof...(RCs) == 0)
118  {
119  init(view(ai));
120  }
121  else
122  {
123  init(view(ai)(rc));
124  }
125  }
126 
131  template<typename Mapping, typename BlobType, typename Accessor>
133  {
135  using RecordDim = typename View::RecordDim;
137  view.extents(),
138  [&](typename View::ArrayIndex ai) LLAMA_LAMBDA_INLINE
139  { forEachLeafCoord<RecordDim>([&](auto rc) LLAMA_LAMBDA_INLINE { constructField(view, ai, rc); }); });
140  }
141 
148 #ifdef __cpp_lib_concepts
149  template<typename Mapping, BlobAllocator Allocator = bloballoc::Vector, typename Accessor = accessor::Default>
150 #else
151  template<typename Mapping, typename Allocator = bloballoc::Vector, typename Accessor = accessor::Default>
152 #endif
153  LLAMA_FN_HOST_ACC_INLINE auto allocView(Mapping mapping = {}, const Allocator& alloc = {}, Accessor accessor = {})
154  -> View<Mapping, internal::AllocatorBlobType<Allocator, typename Mapping::RecordDim>, Accessor>
155  {
156  auto view = allocViewUninitialized(std::move(mapping), alloc, std::move(accessor));
157  constructFields(view);
158  return view;
159  }
160 
163  template<std::size_t Dim, typename RecordDim>
165  {
166  constexpr auto mapping = mapping::MinAlignedOne<ArrayExtentsNCube<int, Dim, 1>, RecordDim>{};
167  return allocViewUninitialized(mapping, bloballoc::Array<mapping.blobSize(0)>{});
168  }
169 
173  template<std::size_t Dim, typename RecordDim>
174  LLAMA_FN_HOST_ACC_INLINE auto allocScalarView() -> decltype(auto)
175  {
176  auto view = allocScalarViewUninitialized<Dim, RecordDim>();
177  constructFields(view);
178  return view;
179  }
180 
182  template<typename View, typename BoundRecordCoord = RecordCoord<>, bool OwnView = false>
183  struct RecordRef;
184 
187  template<typename RecordDim>
189 
192  template<typename T>
193  inline constexpr bool isOne = false;
194 
196  template<typename View, typename BoundRecordCoord>
197  inline constexpr bool isOne<RecordRef<View, BoundRecordCoord, true>> = true;
198 
199  // TODO(bgruber): Higher dimensional iterators might not have good codegen. Multiple nested loops seem to be
200  // superior to a single iterator over multiple dimensions. At least compilers are able to produce better code.
201  // std::mdspan also discovered similar difficulties and there was a discussion in WG21 in Oulu 2016 to
202  // remove/postpone iterators from the design. In std::mdspan's design, the iterator iterated over the co-domain.
204  template<typename View>
205  struct Iterator
206  {
208 
209  using iterator_category = std::random_access_iterator_tag;
214 
215  constexpr Iterator() = default;
216 
218  : arrayIndex(arrayIndex)
219  , view(view)
220  {
221  }
222 
224  constexpr auto operator++() -> Iterator&
225  {
226  ++arrayIndex;
227  return *this;
228  }
229 
231  constexpr auto operator++(int) -> Iterator
232  {
233  auto tmp = *this;
234  ++*this;
235  return tmp;
236  }
237 
239  constexpr auto operator--() -> Iterator&
240  {
241  --arrayIndex;
242  return *this;
243  }
244 
246  constexpr auto operator--(int) -> Iterator
247  {
248  auto tmp{*this};
249  --*this;
250  return tmp;
251  }
252 
254  constexpr auto operator*() const -> reference
255  {
256  return (*view)(*arrayIndex);
257  }
258 
260  constexpr auto operator->() const -> pointer
261  {
262  return {**this};
263  }
264 
266  constexpr auto operator[](difference_type i) const -> reference
267  {
268  return *(*this + i);
269  }
270 
272  constexpr auto operator+=(difference_type n) -> Iterator&
273  {
274  arrayIndex += n;
275  return *this;
276  }
277 
279  friend constexpr auto operator+(Iterator it, difference_type n) -> Iterator
280  {
281  it += n;
282  return it;
283  }
284 
286  friend constexpr auto operator+(difference_type n, Iterator it) -> Iterator
287  {
288  return it + n;
289  }
290 
292  constexpr auto operator-=(difference_type n) -> Iterator&
293  {
294  arrayIndex -= n;
295  return *this;
296  }
297 
299  friend constexpr auto operator-(Iterator it, difference_type n) -> Iterator
300  {
301  it -= n;
302  return it;
303  }
304 
306  friend constexpr auto operator-(const Iterator& a, const Iterator& b) -> difference_type
307  {
308  assert(a.view == b.view);
309  return static_cast<std::ptrdiff_t>(a.arrayIndex - b.arrayIndex);
310  }
311 
313  friend constexpr auto operator==(const Iterator& a, const Iterator& b) -> bool
314  {
315  assert(a.view == b.view);
316  return a.arrayIndex == b.arrayIndex;
317  }
318 
320  friend constexpr auto operator!=(const Iterator& a, const Iterator& b) -> bool
321  {
322  return !(a == b);
323  }
324 
326  friend constexpr auto operator<(const Iterator& a, const Iterator& b) -> bool
327  {
328  assert(a.view == b.view);
329  return a.arrayIndex < b.arrayIndex;
330  }
331 
333  friend constexpr auto operator>(const Iterator& a, const Iterator& b) -> bool
334  {
335  return b < a;
336  }
337 
339  friend constexpr auto operator<=(const Iterator& a, const Iterator& b) -> bool
340  {
341  return !(a > b);
342  }
343 
345  friend constexpr auto operator>=(const Iterator& a, const Iterator& b) -> bool
346  {
347  return !(a < b);
348  }
349 
352  };
353 
358  template<typename Mapping, typename RecordCoord, typename Blobs>
360  Mapping& mapping,
361  typename Mapping::ArrayExtents::Index ai,
362  RecordCoord rc,
363  Blobs& blobs) -> decltype(auto)
364  {
365  if constexpr(llama::isComputed<Mapping, RecordCoord>)
366  return mapping.compute(ai, rc, blobs);
367  else
368  {
369  const auto [nr, offset] = mapping.blobNrAndOffset(ai, rc);
372  return reinterpret_cast<CopyConst<std::remove_reference_t<decltype(blobs[nr][offset])>, Type>&>(
373  blobs[nr][offset]);
375  }
376  }
377 
383 #ifdef __cpp_lib_concepts
384  template<typename TMapping, Blob TBlobType, typename TAccessor = accessor::Default>
385 #else
386  template<typename TMapping, typename TBlobType, typename TAccessor = accessor::Default>
387 #endif
389  : private TMapping
390  , private TAccessor
391 #if CAN_USE_RANGES
392  , std::ranges::view_base
393 #endif
394  {
395  static_assert(!std::is_const_v<TMapping>);
396  using Mapping = TMapping;
397  using BlobType = TBlobType;
399  using ArrayIndex = typename ArrayExtents::Index;
400  using RecordDim = typename Mapping::RecordDim;
401  using Accessor = TAccessor;
404 
405  private:
406  using size_type = typename ArrayExtents::value_type;
407 
408  public:
409  static_assert(
410  std::is_same_v<Mapping, std::decay_t<Mapping>>,
411  "Mapping must not be const qualified or a reference. Are you using decltype(...) as View template "
412  "argument?");
413  static_assert(
414  std::is_same_v<ArrayExtents, std::decay_t<ArrayExtents>>,
415  "Mapping::ArrayExtents must not be const qualified or a reference. Are you using decltype(...) as "
416  "mapping "
417  "template argument?");
418 
420  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
421  View() = default;
422 
429  explicit View(Mapping mapping, Array<BlobType, Mapping::blobCount> blobs = {}, Accessor accessor = {})
430  : Mapping(std::move(mapping))
431  , Accessor(std::move(accessor))
432  , m_blobs(std::move(blobs))
433  {
434  }
435 
437  {
438  return static_cast<Mapping&>(*this);
439  }
440 
441  LLAMA_FN_HOST_ACC_INLINE auto mapping() const -> const Mapping&
442  {
443  return static_cast<const Mapping&>(*this);
444  }
445 
447  {
448  return static_cast<Accessor&>(*this);
449  }
450 
452  {
453  return static_cast<const Accessor&>(*this);
454  }
455 
457  {
458  return mapping().extents();
459  }
460 
461 #if !(defined(_MSC_VER) && defined(__NVCC__))
462  template<typename V>
464  {
465  static_assert(!sizeof(V), "Passed ArrayIndex with SizeType different than Mapping::ArrayExtent");
466  }
467 #endif
468 
470  LLAMA_FN_HOST_ACC_INLINE auto operator()(ArrayIndex ai) const -> decltype(auto)
471  {
472  if constexpr(isRecordDim<RecordDim>)
473  return RecordRef<const View>{ai, *this};
474  else
475  return access(ai, RecordCoord<>{});
476  }
477 
478  LLAMA_FN_HOST_ACC_INLINE auto operator()(ArrayIndex ai) -> decltype(auto)
479  {
480  if constexpr(isRecordDim<RecordDim>)
481  return RecordRef<View>{ai, *this};
482  else
483  return access(ai, RecordCoord<>{});
484  }
485 
488  template<
489  typename... Indices,
490  std::enable_if_t<std::conjunction_v<std::is_convertible<Indices, size_type>...>, int> = 0>
491  LLAMA_FN_HOST_ACC_INLINE auto operator()(Indices... indices) const -> decltype(auto)
492  {
493  static_assert(
494  sizeof...(Indices) == ArrayIndex::rank,
495  "Please specify as many indices as you have array dimensions");
496  return (*this)(ArrayIndex{static_cast<typename ArrayIndex::value_type>(indices)...});
497  }
498 
499  template<
500  typename... Indices,
501  std::enable_if_t<std::conjunction_v<std::is_convertible<Indices, size_type>...>, int> = 0>
502  LLAMA_FN_HOST_ACC_INLINE auto operator()(Indices... indices) -> decltype(auto)
503  {
504  static_assert(
505  sizeof...(Indices) == ArrayIndex::rank,
506  "Please specify as many indices as you have array dimensions");
507  return (*this)(ArrayIndex{static_cast<typename ArrayIndex::value_type>(indices)...});
508  }
509 
512  LLAMA_FN_HOST_ACC_INLINE auto operator[](ArrayIndex ai) const -> decltype(auto)
513  {
514  return (*this)(ai);
515  }
516 
517  LLAMA_FN_HOST_ACC_INLINE auto operator[](ArrayIndex ai) -> decltype(auto)
518  {
519  return (*this)(ai);
520  }
521 
522 #if !(defined(_MSC_VER) && defined(__NVCC__))
523  template<typename V>
525  {
526  static_assert(!sizeof(V), "Passed ArrayIndex with SizeType different than Mapping::ArrayExtent");
527  }
528 #endif
529 
531  LLAMA_FN_HOST_ACC_INLINE auto operator[](size_type index) const -> decltype(auto)
532  {
533  return (*this)(index);
534  }
535 
536  LLAMA_FN_HOST_ACC_INLINE auto operator[](size_type index) -> decltype(auto)
537  {
538  return (*this)(index);
539  }
540 
542  auto begin() -> iterator
543  {
544  return {ArrayIndexRange<ArrayExtents>{extents()}.begin(), this};
545  }
546 
548  auto begin() const -> const_iterator
549  {
550  return {ArrayIndexRange<ArrayExtents>{extents()}.begin(), this};
551  }
552 
554  auto end() -> iterator
555  {
556  return {ArrayIndexRange<ArrayExtents>{extents()}.end(), this};
557  }
558 
560  auto end() const -> const_iterator
561  {
562  return {ArrayIndexRange<ArrayExtents>{extents()}.end(), this};
563  }
564 
566  {
567  return m_blobs;
568  }
569 
570  LLAMA_FN_HOST_ACC_INLINE auto blobs() const -> const Array<BlobType, Mapping::blobCount>&
571  {
572  return m_blobs;
573  }
574 
575  private:
576  template<typename TView, typename TBoundRecordCoord, bool OwnView>
577  friend struct RecordRef;
578 
579  template<std::size_t... Coords>
580  LLAMA_FN_HOST_ACC_INLINE auto access(ArrayIndex ai, RecordCoord<Coords...> rc = {}) const -> decltype(auto)
581  {
582  return accessor()(mapToMemory(mapping(), ai, rc, m_blobs));
583  }
584 
585  template<std::size_t... Coords>
586  LLAMA_FN_HOST_ACC_INLINE auto access(ArrayIndex ai, RecordCoord<Coords...> rc = {}) -> decltype(auto)
587  {
588  return accessor()(mapToMemory(mapping(), ai, rc, m_blobs));
589  }
590 
591  Array<BlobType, Mapping::blobCount> m_blobs;
592  };
593 
595 #ifdef __cpp_lib_concepts
596  template<typename View>
597  inline constexpr auto isView = AnyView<View>;
598 #else
599  template<typename View>
600  inline constexpr auto isView = false;
601 
602  // this definition does neither capture SubView nor user defined view's, but the issue resolves itself with a C++20
603  // upgrade.
604  template<typename Mapping, typename BlobType, typename Accessor>
605  inline constexpr auto isView<View<Mapping, BlobType, Accessor>> = true;
606 #endif
607 
608  namespace internal
609  {
610  // remove in C++23, from: https://en.cppreference.com/w/cpp/utility/forward_like
611  // NOLINTBEGIN
612  template<class T, class U>
613  [[nodiscard]] LLAMA_FN_HOST_ACC_INLINE constexpr auto&& forward_like(U&& x) noexcept
614  {
615  constexpr bool is_adding_const = std::is_const_v<std::remove_reference_t<T>>;
616  if constexpr(std::is_lvalue_reference_v<T&&>)
617  {
618  if constexpr(is_adding_const)
619  return std::as_const(x);
620  else
621  return static_cast<U&>(x);
622  }
623  else
624  {
625  if constexpr(is_adding_const)
626  return std::move(std::as_const(x));
627  else
628  return std::move(x);
629  }
630  }
631  // NOLINTEND
632 
633  template<typename Blobs, typename TransformBlobFunc, std::size_t... Is>
635  Blobs&& blobs,
636  const TransformBlobFunc& transformBlob,
637  std::integer_sequence<std::size_t, Is...>)
638  {
639  return llama::Array{transformBlob(forward_like<Blobs>(blobs[Is]))...};
640  }
641  } // namespace internal
642 
646  template<typename ViewFwd, typename TransformBlobFunc, typename = std::enable_if_t<isView<std::decay_t<ViewFwd>>>>
647  LLAMA_FN_HOST_ACC_INLINE auto transformBlobs(ViewFwd&& view, const TransformBlobFunc& transformBlob)
648  {
649  using View = std::decay_t<ViewFwd>;
650  constexpr auto blobCount = View::Mapping::blobCount;
651 
653  internal::forward_like<ViewFwd>(view.blobs()),
654  transformBlob,
655  std::make_index_sequence<blobCount>{});
656  return llama::View<typename View::Mapping, typename decltype(blobs)::value_type, typename View::Accessor>{
657  view.mapping(),
658  std::move(blobs),
659  view.accessor()};
660  }
661 
666  template<
667  typename View,
668  typename NewBlobType = CopyConst<std::remove_reference_t<View>, std::byte>*,
669  typename = std::enable_if_t<isView<std::decay_t<View>>>>
671  {
672  if constexpr(std::is_same_v<typename std::decay_t<View>::BlobType, NewBlobType>)
673  return view;
674  else
675  return transformBlobs(
676  std::forward<View>(view),
677  [](auto& blob)
678  {
680  return static_cast<NewBlobType>(&blob[0]);
682  });
683  }
684 
685  // Creates a new view from an existing view with the given accessor.
686  // \param view A view which's mapping and blobs are forwarded into a new view with the different accessor.
688  template<typename NewAccessor, typename ViewFwd, typename = std::enable_if_t<isView<std::decay_t<ViewFwd>>>>
689  LLAMA_FN_HOST_ACC_INLINE auto withAccessor(ViewFwd&& view, NewAccessor newAccessor = {})
690  {
691  using OldView = std::decay_t<ViewFwd>;
692  return View<typename OldView::Mapping, typename OldView::BlobType, NewAccessor>{
693  internal::forward_like<ViewFwd>(view.mapping()),
694  internal::forward_like<ViewFwd>(view.blobs()),
695  std::move(newAccessor)};
696  }
697 
698  // Creates a new view from an existing view with the given mapping.
699  // \param view A view which's accessor and blobs are forwarded into a new view with the different mapping.
701  template<typename NewMapping, typename ViewFwd, typename = std::enable_if_t<isView<std::decay_t<ViewFwd>>>>
702  LLAMA_FN_HOST_ACC_INLINE auto withMapping(ViewFwd&& view, NewMapping newMapping = {})
703  {
704  using OldView = std::decay_t<ViewFwd>;
705  static_assert(OldView::Mapping::blobCount == NewMapping::blobCount);
706  for(std::size_t i = 0; i < NewMapping::blobCount; i++)
707  {
708  assert(view.mapping().blobSize(i) == newMapping.blobSize(i));
709  }
710 
711  return View<NewMapping, typename OldView::BlobType, typename OldView::Accessor>{
712  std::move(newMapping),
713  internal::forward_like<ViewFwd>(view.blobs()),
714  internal::forward_like<ViewFwd>(view.accessor())};
715  }
716 
720  template<typename TStoredParentView>
721  struct SubView
722  {
723  using StoredParentView = TStoredParentView;
724  using ParentView = std::remove_const_t<std::remove_reference_t<StoredParentView>>;
725 
726  using Mapping = typename ParentView::Mapping;
729  using BlobType = typename ParentView::BlobType;
730  using RecordDim = typename ParentView::RecordDim;
731  using Accessor = typename ParentView::Accessor;
732  using iterator = typename ParentView::iterator;
733  using const_iterator = typename ParentView::const_iterator;
734 
735  private:
736  using size_type = typename ArrayExtents::value_type;
737 
738  public:
740  LLAMA_FN_HOST_ACC_INLINE explicit SubView(ArrayIndex offset) : offset(offset)
741  {
742  }
743 
745  template<typename StoredParentViewFwd>
746  LLAMA_FN_HOST_ACC_INLINE SubView(StoredParentViewFwd&& parentView, ArrayIndex offset)
747  : parentView(std::forward<StoredParentViewFwd>(parentView))
748  , offset(offset)
749  {
750  }
751 
753  {
754  return parentView.mapping();
755  }
756 
757  LLAMA_FN_HOST_ACC_INLINE auto mapping() const -> const Mapping&
758  {
759  return parentView.mapping();
760  }
761 
763  {
764  return parentView.accessor();
765  }
766 
768  {
769  return parentView.accessor();
770  }
771 
773  {
774  return parentView.extents();
775  }
776 
778  LLAMA_FN_HOST_ACC_INLINE auto operator()(ArrayIndex ai) const -> decltype(auto)
779  {
780  return parentView(ArrayIndex{ai + offset});
781  }
782 
783  LLAMA_FN_HOST_ACC_INLINE auto operator()(ArrayIndex ai) -> decltype(auto)
784  {
785  return parentView(ArrayIndex{ai + offset});
786  }
787 
789  template<typename... Indices>
790  LLAMA_FN_HOST_ACC_INLINE auto operator()(Indices... indices) const -> decltype(auto)
791  {
792  static_assert(
793  sizeof...(Indices) == ArrayIndex::rank,
794  "Please specify as many indices as you have array dimensions");
795  static_assert(
796  std::conjunction_v<std::is_convertible<Indices, size_type>...>,
797  "Indices must be convertible to ArrayExtents::size_type");
798  return parentView(
799  ArrayIndex{ArrayIndex{static_cast<typename ArrayIndex::value_type>(indices)...} + offset});
800  }
801 
802  template<typename... Indices>
803  LLAMA_FN_HOST_ACC_INLINE auto operator()(Indices... indices) -> decltype(auto)
804  {
805  static_assert(
806  sizeof...(Indices) == ArrayIndex::rank,
807  "Please specify as many indices as you have array dimensions");
808  static_assert(
809  std::conjunction_v<std::is_convertible<Indices, size_type>...>,
810  "Indices must be convertible to ArrayExtents::size_type");
811  return parentView(
812  ArrayIndex{ArrayIndex{static_cast<typename ArrayIndex::value_type>(indices)...} + offset});
813  }
814 
815  template<std::size_t... Coords>
816  LLAMA_FN_HOST_ACC_INLINE auto operator()(RecordCoord<Coords...> rc = {}) const -> decltype(auto)
817  {
818  return parentView(ArrayIndex{} + offset, rc);
819  }
820 
821  template<std::size_t... Coords>
823  {
824  return parentView(ArrayIndex{} + offset, rc);
825  }
826 
827  // TODO(bgruber): implement iterators. Those would be transform iterators on top of the parent view's
828  // iterators, applying the offset on access.
829 
831  {
832  return parentView.blobs();
833  }
834 
835  LLAMA_FN_HOST_ACC_INLINE auto blobs() const -> const Array<BlobType, Mapping::blobCount>&
836  {
837  return parentView.blobs();
838  }
839 
843  };
844 
848  template<typename TStoredParentView>
849  SubView(TStoredParentView&&, typename std::remove_reference_t<TStoredParentView>::Mapping::ArrayExtents::Index)
851 } // namespace llama
#define LLAMA_EXPORT
Definition: macros.hpp:192
#define LLAMA_DECLSPEC_EMPTY_BASES
Definition: macros.hpp:164
#define LLAMA_LAMBDA_INLINE
Gives strong indication to the compiler to inline the attributed lambda.
Definition: macros.hpp:113
#define LLAMA_BEGIN_SUPPRESS_HOST_DEVICE_WARNING
Definition: macros.hpp:141
#define LLAMA_FN_HOST_ACC_INLINE
Definition: macros.hpp:96
#define LLAMA_END_SUPPRESS_HOST_DEVICE_WARNING
Definition: macros.hpp:153
auto makeBlobArray(const Allocator &alloc, const Mapping &mapping, std::integer_sequence< std::size_t, Is... >) -> Array< AllocatorBlobType< Allocator, typename Mapping::RecordDim >, Mapping::blobCount >
Definition: View.hpp:34
decltype(std::declval< Allocator >()(std::integral_constant< std::size_t, alignOf< RecordDim > >{}, 0)) AllocatorBlobType
Definition: View.hpp:31
auto makeTransformedBlobArray(Blobs &&blobs, const TransformBlobFunc &transformBlob, std::integer_sequence< std::size_t, Is... >)
Definition: View.hpp:634
constexpr auto && forward_like(U &&x) noexcept
Definition: View.hpp:613
void constructField(View< Mapping, BlobType, Accessor > &view, typename Mapping::ArrayExtents::Index ai, RecordCoord< RCs... > rc)
Definition: View.hpp:96
constexpr bool isProxyReference
Definition: Concepts.hpp:242
SubView(TStoredParentView &&, typename std::remove_reference_t< TStoredParentView >::Mapping::ArrayExtents::Index) -> SubView< TStoredParentView >
ArrayIndex(Args...) -> ArrayIndex< typename internal::IndexTypeFromArgs< std::size_t, Args... >::type, sizeof...(Args)>
constexpr bool hasAnyComputedField
Returns true if any field accessed via the given mapping is a computed value.
Definition: View.hpp:90
auto transformBlobs(ViewFwd &&view, const TransformBlobFunc &transformBlob)
Definition: View.hpp:647
auto allocViewUninitialized(Mapping mapping={}, const Allocator &alloc={}, Accessor accessor={})
Same as allocView but does not run field constructors.
Definition: View.hpp:55
void forEachArrayIndex([[maybe_unused]] const ArrayIndex< SizeType, Dim > &extents, Func &&func, OuterIndices... outerIndices)
constexpr auto isView
Definition: View.hpp:600
auto allocScalarView() -> decltype(auto)
Definition: View.hpp:174
ArrayExtents(Args...) -> ArrayExtents< typename internal::IndexTypeFromArgs< std::size_t, Args... >::type,(Args{}, dyn)... >
auto shallowCopy(View &&view)
Definition: View.hpp:670
auto withAccessor(ViewFwd &&view, NewAccessor newAccessor={})
Definition: View.hpp:689
auto withMapping(ViewFwd &&view, NewMapping newMapping={})
Definition: View.hpp:702
auto allocView(Mapping mapping={}, const Allocator &alloc={}, Accessor accessor={}) -> View< Mapping, internal::AllocatorBlobType< Allocator, typename Mapping::RecordDim >, Accessor >
Definition: View.hpp:153
constexpr bool isComputed
Returns true if the field accessed via the given mapping and record coordinate is a computed value.
Definition: View.hpp:84
std::conditional_t< std::is_const_v< FromT >, const ToT, ToT > CopyConst
Alias for ToT, adding const if FromT is const qualified.
Definition: Core.hpp:824
typename internal::LeafRecordCoordsImpl< RecordDim, RecordCoord<> >::type LeafRecordCoords
Returns a flat type list containing all record coordinates to all leaves of the given record dimensio...
Definition: Core.hpp:428
auto allocScalarViewUninitialized() -> decltype(auto)
Same as allocScalarView but does not run field constructors.
Definition: View.hpp:164
typename internal::GetTypeImpl< RecordDim, RecordCoordOrTags... >::type GetType
Definition: Core.hpp:388
auto mapToMemory(Mapping &mapping, typename Mapping::ArrayExtents::Index ai, RecordCoord rc, Blobs &blobs) -> decltype(auto)
Definition: View.hpp:359
constexpr bool isOne
Is true, if T is an instance of One.
Definition: View.hpp:193
void constructFields(View< Mapping, BlobType, Accessor > &view)
Definition: View.hpp:132
Range allowing to iterate over all indices in an ArrayExtents.
constexpr auto end() const noexcept -> ArrayIndexIterator< ArrayExtents >
constexpr auto begin() const noexcept -> ArrayIndexIterator< ArrayExtents >
constexpr friend auto operator<=(const Iterator &a, const Iterator &b) -> bool
Definition: View.hpp:339
constexpr auto operator-=(difference_type n) -> Iterator &
Definition: View.hpp:292
constexpr friend auto operator-(Iterator it, difference_type n) -> Iterator
Definition: View.hpp:299
typename ArrayIndexIterator::difference_type difference_type
Definition: View.hpp:211
constexpr auto operator[](difference_type i) const -> reference
Definition: View.hpp:266
constexpr friend auto operator>=(const Iterator &a, const Iterator &b) -> bool
Definition: View.hpp:345
constexpr friend auto operator+(difference_type n, Iterator it) -> Iterator
Definition: View.hpp:286
View * view
Definition: View.hpp:351
constexpr friend auto operator!=(const Iterator &a, const Iterator &b) -> bool
Definition: View.hpp:320
constexpr friend auto operator>(const Iterator &a, const Iterator &b) -> bool
Definition: View.hpp:333
constexpr auto operator++(int) -> Iterator
Definition: View.hpp:231
constexpr Iterator(ArrayIndexIterator arrayIndex, View *view)
Definition: View.hpp:217
constexpr auto operator--() -> Iterator &
Definition: View.hpp:239
constexpr friend auto operator==(const Iterator &a, const Iterator &b) -> bool
Definition: View.hpp:313
std::random_access_iterator_tag iterator_category
Definition: View.hpp:209
constexpr friend auto operator+(Iterator it, difference_type n) -> Iterator
Definition: View.hpp:279
constexpr auto operator+=(difference_type n) -> Iterator &
Definition: View.hpp:272
constexpr auto operator->() const -> pointer
Definition: View.hpp:260
constexpr friend auto operator<(const Iterator &a, const Iterator &b) -> bool
Definition: View.hpp:326
constexpr auto operator*() const -> reference
Definition: View.hpp:254
constexpr friend auto operator-(const Iterator &a, const Iterator &b) -> difference_type
Definition: View.hpp:306
constexpr auto operator++() -> Iterator &
Definition: View.hpp:224
constexpr auto operator--(int) -> Iterator
Definition: View.hpp:246
constexpr Iterator()=default
ArrayIndexIterator arrayIndex
Definition: View.hpp:350
StoredParentView parentView
Definition: View.hpp:840
auto mapping() const -> const Mapping &
Definition: View.hpp:757
auto blobs() const -> const Array< BlobType, Mapping::blobCount > &
Definition: View.hpp:835
auto accessor() const -> const Accessor &
Definition: View.hpp:767
auto mapping() -> Mapping &
Definition: View.hpp:752
const ArrayIndex offset
Definition: View.hpp:841
typename ParentView::ArrayIndex ArrayIndex
Definition: View.hpp:728
typename ParentView::ArrayExtents ArrayExtents
Definition: View.hpp:727
auto operator()(ArrayIndex ai) -> decltype(auto)
Definition: View.hpp:783
auto operator()(RecordCoord< Coords... > rc={}) -> decltype(auto)
Definition: View.hpp:822
typename ParentView::RecordDim RecordDim
Definition: View.hpp:730
auto operator()(ArrayIndex ai) const -> decltype(auto)
Same as View::operator()(ArrayIndex), but shifted by the offset of this SubView.
Definition: View.hpp:778
std::remove_const_t< std::remove_reference_t< StoredParentView > > ParentView
type of the parent view
Definition: View.hpp:724
typename ParentView::iterator iterator
Definition: View.hpp:732
auto operator()(RecordCoord< Coords... > rc={}) const -> decltype(auto)
Definition: View.hpp:816
auto operator()(Indices... indices) const -> decltype(auto)
Same as corresponding operator in View, but shifted by the offset of this SubView.
Definition: View.hpp:790
auto accessor() -> Accessor &
Definition: View.hpp:762
typename ParentView::Accessor Accessor
Definition: View.hpp:731
SubView(ArrayIndex offset)
Creates a SubView given an offset. The parent view is default constructed.
Definition: View.hpp:740
auto operator()(Indices... indices) -> decltype(auto)
Definition: View.hpp:803
typename ParentView::BlobType BlobType
Definition: View.hpp:729
auto blobs() -> Array< BlobType, Mapping::blobCount > &
Definition: View.hpp:830
typename ParentView::Mapping Mapping
Definition: View.hpp:726
typename ParentView::const_iterator const_iterator
Definition: View.hpp:733
SubView(StoredParentViewFwd &&parentView, ArrayIndex offset)
Creates a SubView given a parent View and offset.
Definition: View.hpp:746
auto extents() const -> ArrayExtents
Definition: View.hpp:772
TStoredParentView StoredParentView
Definition: View.hpp:723
auto mapping() -> Mapping &
Definition: View.hpp:436
typename ArrayExtents::Index ArrayIndex
Definition: View.hpp:399
typename Mapping::RecordDim RecordDim
Definition: View.hpp:400
auto operator[](ArrayIndex ai) const -> decltype(auto)
Definition: View.hpp:512
auto mapping() const -> const Mapping &
Definition: View.hpp:441
typename Mapping::ArrayExtents ArrayExtents
Definition: View.hpp:398
View(Mapping mapping, Array< BlobType, Mapping::blobCount > blobs={}, Accessor accessor={})
Definition: View.hpp:429
auto blobs() -> Array< BlobType, Mapping::blobCount > &
Definition: View.hpp:565
TBlobType BlobType
Definition: View.hpp:397
auto blobs() const -> const Array< BlobType, Mapping::blobCount > &
Definition: View.hpp:570
auto operator[](ArrayIndex ai) -> decltype(auto)
Definition: View.hpp:517
auto operator[](llama::ArrayIndex< V, ArrayIndex::rank >) const
Definition: View.hpp:524
auto begin() -> iterator
Definition: View.hpp:542
auto end() -> iterator
Definition: View.hpp:554
auto operator()(Indices... indices) -> decltype(auto)
Definition: View.hpp:502
auto begin() const -> const_iterator
Definition: View.hpp:548
auto operator()(ArrayIndex ai) const -> decltype(auto)
Retrieves the RecordRef at the given ArrayIndex index.
Definition: View.hpp:470
auto operator()(ArrayIndex ai) -> decltype(auto)
Definition: View.hpp:478
auto accessor() const -> const Accessor &
Definition: View.hpp:451
auto end() const -> const_iterator
Definition: View.hpp:560
auto accessor() -> Accessor &
Definition: View.hpp:446
auto operator()(Indices... indices) const -> decltype(auto)
Definition: View.hpp:491
View()=default
Performs default initialization of the blob array.
TMapping Mapping
Definition: View.hpp:396
TAccessor Accessor
Definition: View.hpp:401
auto operator[](size_type index) -> decltype(auto)
Definition: View.hpp:536
auto extents() const -> ArrayExtents
Definition: View.hpp:456
auto operator[](size_type index) const -> decltype(auto)
Retrieves the RecordRef at the 1D ArrayIndex index constructed from the passed index.
Definition: View.hpp:531
auto operator()(llama::ArrayIndex< V, ArrayIndex::rank >) const
Definition: View.hpp:463