12 #include <boost/functional/hash.hpp>
14 #include <type_traits>
19 template<
typename View,
typename BoundRecordCoord,
bool OwnView>
23 template<
typename View>
27 template<
typename View,
typename BoundRecordCoord,
bool OwnView>
28 inline constexpr
auto isRecordRef<RecordRef<View, BoundRecordCoord, OwnView>> =
true;
32 template<
typename View,
typename BoundRecordCoord,
bool OwnView>
47 typename RightBoundRecordDim,
56 using LARD =
typename LeftRecord::AccessibleRecordDim;
57 using RARD =
typename RightRecord::AccessibleRecordDim;
58 if constexpr(std::is_same_v<LARD, RARD>)
60 forEachLeafCoord<LARD>([&](
auto rc)
LLAMA_LAMBDA_INLINE { Functor{}(left(rc), right(rc)); });
64 forEachLeafCoord<LARD>(
67 using LeftInnerCoord = decltype(leftRC);
68 forEachLeafCoord<RARD>(
71 using RightInnerCoord = decltype(rightRC);
72 if constexpr(hasSameTags<LARD, LeftInnerCoord, RARD, RightInnerCoord>)
74 Functor{}(left(leftRC), right(rightRC));
82 template<
typename Functor,
typename LeftRecord,
typename T>
85 forEachLeafCoord<typename LeftRecord::AccessibleRecordDim>([&](
auto leftRC)
LLAMA_LAMBDA_INLINE
86 { Functor{}(left(leftRC), right); });
94 typename RightBoundRecordDim,
97 const LeftRecord& left,
104 using LARD =
typename LeftRecord::AccessibleRecordDim;
105 using RARD =
typename RightRecord::AccessibleRecordDim;
106 if constexpr(std::is_same_v<LARD, RARD>)
108 forEachLeafCoord<LARD>([&](
auto rc)
LLAMA_LAMBDA_INLINE { result &= Functor{}(left(rc), right(rc)); });
112 forEachLeafCoord<LARD>(
115 using LeftInnerCoord = decltype(leftRC);
116 forEachLeafCoord<RARD>(
119 using RightInnerCoord = decltype(rightRC);
120 if constexpr(hasSameTags<LARD, LeftInnerCoord, RARD, RightInnerCoord>)
122 result &= Functor{}(left(leftRC), right(rightRC));
130 template<
typename Functor,
typename LeftRecord,
typename T>
134 forEachLeafCoord<typename LeftRecord::AccessibleRecordDim>([&](
auto leftRC)
LLAMA_LAMBDA_INLINE
135 { result &= Functor{}(left(leftRC), right); });
141 template<
typename A,
typename B>
144 return std::forward<A>(a) = b;
150 template<
typename A,
typename B>
153 return std::forward<A>(a) += b;
159 template<
typename A,
typename B>
162 return std::forward<A>(a) -= b;
168 template<
typename A,
typename B>
171 return std::forward<A>(a) *= b;
177 template<
typename A,
typename B>
180 return std::forward<A>(a) /= b;
186 template<
typename A,
typename B>
189 return std::forward<A>(a) %= b;
194 typename ProxyReference,
196 std::enable_if_t<!isRecordRef<std::decay_t<ProxyReference>>,
int> = 0>
203 typename TWithOptionalConst,
205 std::enable_if_t<!isRecordRef<std::decay_t<TWithOptionalConst>>,
int> = 0>
207 -> std::reference_wrapper<TWithOptionalConst>
212 template<
typename RecordRef,
typename T, std::size_t N, std::size_t... Is>
218 template<
typename RecordRef,
typename T, std::
size_t N>
221 return asTupleImplForArray(std::forward<RecordRef>(vd), std::move(a), std::make_index_sequence<N>{});
224 template<
typename RecordRef,
typename... Fields>
231 typename ProxyReference,
233 std::enable_if_t<!isRecordRef<std::decay_t<ProxyReference>>,
int> = 0>
236 static_assert(!std::is_reference_v<ProxyReference>);
237 return {std::move(leaf)};
241 typename TWithOptionalConst,
243 std::enable_if_t<!isRecordRef<std::decay_t<TWithOptionalConst>>,
int> = 0>
249 template<
typename RecordRef,
typename T, std::size_t N, std::size_t... Is>
255 template<
typename RecordRef,
typename T, std::
size_t N>
261 template<
typename RecordRef,
typename... Fields>
267 template<
typename T,
typename =
void>
273 inline constexpr
auto isTupleLike<T, std::void_t<decltype(get<0>(std::declval<T>())), std::tuple_size<T>>>
276 template<
typename... Ts>
279 template<
typename Tuple1,
typename Tuple2, std::size_t... Is>
282 template<
typename T1,
typename T2>
287 static_assert(std::tuple_size_v<std::decay_t<T1>> == std::tuple_size_v<std::decay_t<T2>>);
288 assignTuples(dst, src, std::make_index_sequence<std::tuple_size_v<std::decay_t<T1>>>{});
291 std::forward<T1>(dst) = std::forward<T2>(src);
294 dependentFalse<T1, T2>,
295 "Elements to assign are not tuple/tuple or non-tuple/non-tuple.");
298 template<
typename Tuple1,
typename Tuple2, std::size_t... Is>
301 static_assert(std::tuple_size_v<std::decay_t<Tuple1>> == std::tuple_size_v<std::decay_t<Tuple2>>);
303 (
assignTupleElement(get<Is>(std::forward<Tuple1>(dst)), get<Is>(std::forward<Tuple2>(src))), ...);
306 template<
typename T,
typename Tuple, std::size_t... Is>
310 return T{get<Is>(src)...};
313 template<
typename T,
typename SFINAE,
typename... Args>
316 template<
typename T,
typename... Args>
317 inline constexpr
auto
321 template<typename T, typename... Args>
324 template<typename T, typename Tuple>
327 template<
typename T, template<typename...>
typename Tuple,
typename... Args>
329 = isDirectListInitializable<T, Args...>;
331 template<typename T, typename Simd, typename SrcRC, typename DstRC>
334 template<
typename Simd,
typename TFwd,
typename SrcRC,
typename DstRC>
344 template<
typename TView,
typename TBoundRecordCoord,
bool OwnView>
345 struct RecordRef :
private TView::Mapping::ArrayExtents::Index
352 using ArrayIndex =
typename View::Mapping::ArrayExtents::Index;
353 using RecordDim =
typename View::Mapping::RecordDim;
355 std::conditional_t<OwnView, View, View&> view;
368 static_assert(OwnView,
"The default constructor of RecordRef is only available if it owns the view.");
372 RecordRef(ArrayIndex ai, std::conditional_t<OwnView, View&&, View&> view)
374 , view{static_cast<decltype(view)>(view)}
384 return this->
operator=<
RecordRef>(other);
394 return static_cast<const ArrayIndex&
>(*this);
399 template<
typename OtherView,
typename OtherBoundRecordCoord,
bool OtherOwnView>
407 "The copy constructor of RecordRef from a different RecordRef is only available if it owns "
415 template<
typename T,
typename = std::enable_if_t<!isRecordRef<T>>>
422 "The constructor of RecordRef from a scalar is only available if it owns the view.");
429 template<std::size_t... Coord>
434 if constexpr(isRecordDim<AccessedType>)
437 return this->view.access(
arrayIndex(), AbsolutCoord{});
441 template<std::size_t... Coord>
446 if constexpr(isRecordDim<AccessedType>)
449 return this->view.access(
arrayIndex(), AbsolutCoord{});
455 template<
typename... Tags>
463 template<
typename... Tags>
470 #ifdef LLAMA_HAS_STRING_FIELDS
472 template<
internal::FixedString Name>
481 template<
internal::FixedString Name>
484 using RecordCoord = GetCoordFromTags<AccessibleRecordDim, internal::StringTag<Name>>;
493 return internal::recordRefArithOperator<internal::Assign>(*
this, other);
499 return internal::recordRefArithOperator<internal::PlusAssign>(*
this, other);
505 return internal::recordRefArithOperator<internal::MinusAssign>(*
this, other);
511 return internal::recordRefArithOperator<internal::MultiplyAssign>(*
this, other);
517 return internal::recordRefArithOperator<internal::DivideAssign>(*
this, other);
523 return internal::recordRefArithOperator<internal::ModuloAssign>(*
this, other);
532 template<
typename T,
typename = std::enable_if_t<!isRecordRef<T>>>
550 template<
typename T,
typename = std::enable_if_t<!isRecordRef<T>>>
571 return internal::recordRefRelOperator<std::equal_to<>>(vd, t);
574 template<
typename T,
typename = std::enable_if_t<!isRecordRef<T>>>
586 template<
typename T,
typename = std::enable_if_t<!isRecordRef<T>>>
595 return internal::recordRefRelOperator<std::less<>>(vd, t);
598 template<
typename T,
typename = std::enable_if_t<!isRecordRef<T>>>
607 return internal::recordRefRelOperator<std::less_equal<>>(vd, t);
610 template<
typename T,
typename = std::enable_if_t<!isRecordRef<T>>>
619 return internal::recordRefRelOperator<std::greater<>>(vd, t);
622 template<
typename T,
typename = std::enable_if_t<!isRecordRef<T>>>
631 return internal::recordRefRelOperator<std::greater_equal<>>(vd, t);
634 template<
typename T,
typename = std::enable_if_t<!isRecordRef<T>>>
660 template<std::
size_t I>
666 template<std::
size_t I>
672 template<
typename TupleLike>
677 "TupleLike must be constructible from as many values as this RecordRef recursively represents "
679 "this: TupleLike{values...}");
680 return internal::makeFromTuple<TupleLike>(
682 std::make_index_sequence<std::tuple_size_v<decltype(
asFlatTuple())>>{});
685 template<
typename TupleLike>
690 "TupleLike must be constructible from as many values as this RecordRef recursively represents "
692 "this: TupleLike{values...}");
693 return internal::makeFromTuple<TupleLike>(
695 std::make_index_sequence<std::tuple_size_v<decltype(
asFlatTuple())>>{});
732 template<
typename TupleLike>
740 std::conditional_t<OwnView, RecordRef&, RecordRef> a,
741 std::conditional_t<OwnView, RecordRef&, RecordRef> b) noexcept
743 forEachLeafCoord<AccessibleRecordDim>(
759 template<
typename T,
typename Simd,
typename SrcRC,
typename DstRC>
765 template<
typename Simd,
typename TFwd,
typename SrcRC,
typename DstRC>
777 typename BoundRecordDimA,
780 typename BoundRecordDimB,
785 -> std::enable_if_t<std::is_same_v<
790 forEachLeafCoord<typename LeftRecord::AccessibleRecordDim>(
799 template<
typename View,
typename BoundRecordCoord,
bool OwnView>
804 if constexpr(std::is_array_v<RecordDim>)
806 mp_for_each_inline<mp_iota_c<std::extent_v<RecordDim>>>(
809 constexpr std::size_t i = decltype(ic)::value;
817 mp_for_each_inline<mp_iota<mp_size<RecordDim>>>(
820 constexpr std::size_t i = decltype(ic)::value;
823 using Field = mp_at_c<RecordDim, i>;
824 os << structName<GetFieldTag<Field>>() <<
": " << vr(
RecordCoord<i>{});
832 template<
typename RecordRefFwd,
typename Functor>
835 using RecordRef = std::remove_reference_t<RecordRefFwd>;
836 forEachLeafCoord<typename RecordRef::AccessibleRecordDim>(
837 [functor = std::forward<Functor>(functor), &vr = vr](
auto rc)
845 template<
typename T,
typename =
void>
852 struct ValueOf<T, std::enable_if_t<isRecordRef<T>>>
857 #ifdef __cpp_lib_concepts
858 template<ProxyReference T>
862 struct ValueOf<T, std::enable_if_t<isProxyReference<T>>>
864 using type =
typename T::value_type;
870 using type = std::remove_const_t<T>;
879 return std::forward<T>(valueOrRef);
887 template<
typename Reference,
typename =
void>
928 template<
typename Reference>
931 std::enable_if_t<std::is_fundamental_v<typename internal::ValueOf<Reference>::type>>>
932 :
ProxyRefOpMixin<ScopedUpdate<Reference>, typename internal::ValueOf<Reference>::type>
986 template<
typename T,
typename =
void>
993 struct ReferenceTo<T, std::enable_if_t<isRecordRef<T> && !isOne<T>>>
998 #ifdef __cpp_lib_concepts
999 template<ProxyReference T>
1001 template<
typename T>
1010 template<
typename T>
1015 template<
typename View,
typename BoundRecordCoord,
bool OwnView>
1016 struct std::tuple_size<
llama::RecordRef<View, BoundRecordCoord, OwnView>>
1017 : boost::mp11::mp_size<typename llama::RecordRef<View, BoundRecordCoord, OwnView>::AccessibleRecordDim>
1022 template<std::
size_t I,
typename View,
typename BoundRecordCoord,
bool OwnView>
1023 struct std::tuple_element<I,
llama::RecordRef<View, BoundRecordCoord, OwnView>>
1029 template<std::
size_t I,
typename View,
typename BoundRecordCoord,
bool OwnView>
1030 struct std::tuple_element<I, const
llama::RecordRef<View, BoundRecordCoord, OwnView>>
1036 template<
typename View,
typename BoundRecordCoord,
bool OwnView>
1037 struct std::hash<
llama::RecordRef<View, BoundRecordCoord, OwnView>>
1042 std::size_t acc = 0;
1065 basic_common_reference<llama::RecordRef<ViewA, BoundA, OwnA>, llama::RecordRef<ViewB, BoundB, OwnB>, TQual, UQual>
1067 using type = std::enable_if_t<
#define LLAMA_LAMBDA_INLINE_WITH_SPECIFIERS(...)
#define LLAMA_LAMBDA_INLINE
Gives strong indication to the compiler to inline the attributed lambda.
#define LLAMA_BEGIN_SUPPRESS_HOST_DEVICE_WARNING
#define LLAMA_FN_HOST_ACC_INLINE
#define LLAMA_END_SUPPRESS_HOST_DEVICE_WARNING
void loadSimdFromField(const T &srcRef, Simd &dstSimd, SrcRC srcRC, DstRC dstRC)
auto makeFromTuple(Tuple &&src, std::index_sequence< Is... >)
auto asFlatTupleImplForArray(RecordRef &&vd, T(&&)[N], std::index_sequence< Is... >)
auto recordRefArithOperator(LeftRecord &left, const RecordRef< RightView, RightBoundRecordDim, RightOwnView > &right) -> LeftRecord &
void assignTupleElement(T1 &&dst, T2 &&src)
auto asFlatTupleImpl(ProxyReference &&leaf, T) -> std::tuple< ProxyReference >
void storeSimdToField(const Simd &srcSimd, TFwd &&dstRef, SrcRC srcRC, DstRC dstRC)
auto asTupleImpl(ProxyReference &&leaf, T) -> ProxyReference
constexpr auto dependentFalse
constexpr auto isTupleLike
void assignTuples(Tuple1 &&dst, Tuple2 &&src, std::index_sequence< Is... >)
constexpr auto isDirectListInitializable
constexpr auto isDirectListInitializableFromTuple
constexpr auto isDirectListInitializableImpl
auto asTupleImplForArray(RecordRef &&vd, T(&&)[N], std::index_sequence< Is... >)
auto recordRefRelOperator(const LeftRecord &left, const RecordRef< RightView, RightBoundRecordDim, RightOwnView > &right) -> bool
auto decayCopy(T &&valueOrRef) -> typename internal::ValueOf< T >::type
Pulls a copy of the given value or reference. Proxy references are resolved to their value types.
Tuple(Elements...) -> Tuple< std::remove_cv_t< std::remove_reference_t< Elements >>... >
auto allocScalarView() -> decltype(auto)
auto copyRecord(const RecordRef< View, BoundRecordCoord, OwnView > &rr)
Returns a One with the same record dimension as the given record ref, with values copyied from rr.
auto operator<<(std::ostream &os, const Array< T, N > &a) -> std::ostream &
mp_second< Field > GetFieldType
Get the type from a Field.
constexpr void forEachLeaf(RecordRefFwd &&vr, Functor &&functor)
constexpr auto get(Tuple< Elements... > &tuple) -> auto &
typename internal::GetCoordFromTagsImpl< RecordDim, RecordCoord<>, TagsOrTagList... >::type GetCoordFromTags
mp_first< Field > GetFieldTag
Get the tag from a Field.
RecordCoordFromList< mp_append< typename RecordCoords::List... > > Cat
Concatenate a set of RecordCoords.
typename internal::GetTypeImpl< RecordDim, RecordCoordOrTags... >::type GetType
ScopedUpdate(T) -> ScopedUpdate< typename internal::ReferenceTo< std::remove_reference_t< T >>::type >
typename std::conditional_t< isRecordDim< T >, mp_identity< One< Simdize< T, MakeSimd > >>, mp_identity< Simdize< T, MakeSimd > >>::type Simd
auto swap(RecordRef< ViewA, BoundRecordDimA, OwnViewA > &a, RecordRef< ViewB, BoundRecordDimB, OwnViewB > &b) noexcept -> std::enable_if_t< std::is_same_v< typename RecordRef< ViewA, BoundRecordDimA, OwnViewA >::AccessibleRecordDim, typename RecordRef< ViewB, BoundRecordDimB, OwnViewB >::AccessibleRecordDim >>
constexpr auto isRecordRef
CRTP mixin for proxy reference types to support all compound assignment and increment/decrement opera...
friend auto operator>=(const RecordRef &vd, const T &t) -> bool
auto operator()(Tags...) -> decltype(auto)
auto get() const -> decltype(auto)
auto operator()(RecordCoord< Coord... >) -> decltype(auto)
friend auto operator>=(const T &t, const RecordRef &vd) -> bool
friend auto operator>(const T &t, const RecordRef &vd) -> bool
auto operator=(const RecordRef &other) -> RecordRef &
friend auto operator<=(const RecordRef &vd, const T &t) -> bool
auto operator*=(const T &other) -> RecordRef &
friend auto operator*(const RecordRef &vd, const T &t)
GetType< RecordDim, BoundRecordCoord > AccessibleRecordDim
friend auto operator==(const T &t, const RecordRef &vd) -> bool
auto operator()(Tags...) const -> decltype(auto)
friend auto operator!=(const T &t, const RecordRef &vd) -> bool
auto operator=(const T &other) -> RecordRef &
friend auto operator<(const T &t, const RecordRef &vd) -> bool
friend auto operator!=(const RecordRef &vd, const T &t) -> bool
friend auto operator-(const RecordRef &vd, const T &t)
friend auto operator>(const RecordRef &vd, const T &t) -> bool
auto operator/=(const T &other) -> RecordRef &
friend auto operator<(const RecordRef &vd, const T &t) -> bool
friend auto operator+(const T &t, const RecordRef &vd)
RecordRef(ArrayIndex ai, std::conditional_t< OwnView, View &&, View & > view)
auto operator()(RecordCoord< Coord... >) const -> decltype(auto)
auto get() -> decltype(auto)
RecordRef(const RecordRef &)=default
friend auto operator%(const RecordRef &vd, const T &t)
auto operator+=(const T &other) -> RecordRef &
auto loadAs() -> TupleLike
friend auto operator==(const RecordRef &vd, const T &t) -> bool
auto operator%=(const T &other) -> RecordRef &
auto loadAs() const -> TupleLike
TBoundRecordCoord BoundRecordCoord
Record coords into View::RecordDim which are already bound by this RecordRef.
TView View
View this record reference points into.
void store(const TupleLike &t)
RecordRef(RecordRef &&) noexcept=default
constexpr auto arrayIndex() const -> ArrayIndex
friend auto operator+(const RecordRef &vd, const T &t)
friend auto operator*(const T &t, const RecordRef &vd)
friend void swap(std::conditional_t< OwnView, RecordRef &, RecordRef > a, std::conditional_t< OwnView, RecordRef &, RecordRef > b) noexcept
friend auto operator/(const RecordRef &vd, const T &t)
RecordRef(const T &scalar)
Create a RecordRef from a scalar. Only available for if the view is owned. Used by llama::One.
friend auto operator<=(const T &t, const RecordRef &vd) -> bool
auto operator-=(const T &other) -> RecordRef &
RecordRef(const RecordRef< OtherView, OtherBoundRecordCoord, OtherOwnView > &recordRef)
RecordRef()
Creates an empty RecordRef. Only available for if the view is owned. Used by llama::One.
auto load() const -> LoaderConst
A type list of Fields which may be used to define a record dimension.
auto get() const -> const value_type &
auto operator=(const ScopedUpdate &) -> ScopedUpdate &=delete
ScopedUpdate(const ScopedUpdate &)=delete
ScopedUpdate(ScopedUpdate &&) noexcept=default
ScopedUpdate(Reference r)
auto operator=(value_type v) -> ScopedUpdate &
typename internal::ValueOf< Reference >::type value_type
ScopedUpdate(const ScopedUpdate &)=delete
auto operator=(const ScopedUpdate &) -> ScopedUpdate &=delete
auto get() -> value_type &
Get access to the stored value.
auto get() const -> const value_type &
Get access to the stored value.
ScopedUpdate(Reference r)
Loads a copy of the value referenced by r. Stores r and the loaded value.
ScopedUpdate(ScopedUpdate &&) noexcept=default
typename internal::ValueOf< Reference >::type value_type
auto operator()(A &&a, const B &b) const -> decltype(auto)
auto operator()(A &&a, const B &b) const -> decltype(auto)
auto operator()(A &&a, const B &b) const -> decltype(auto)
auto operator()(A &&a, const B &b) const -> decltype(auto)
auto operator()(A &&a, const B &b) const -> decltype(auto)
auto operator()(A &&a, const B &b) const -> decltype(auto)
typename T::value_type type
std::remove_const_t< T > type
auto operator()(const llama::RecordRef< View, BoundRecordCoord, OwnView > &rr) const -> std::size_t
decltype(std::declval< const llama::RecordRef< View, BoundRecordCoord, OwnView > >().template get< I >()) type
decltype(std::declval< llama::RecordRef< View, BoundRecordCoord, OwnView > >().template get< I >()) type