Uni20
Asynchronous tensor and runtime library.
Loading...
Searching...
No Matches
mdspan/concepts.hpp
Go to the documentation of this file.
1#pragma once
2
17
18#include <concepts>
19#include <type_traits>
20#include <utility>
21
22namespace uni20
23{
24
28template <typename AP, typename = void> struct span_offset_type
29{
32 using type = std::size_t;
33};
34
38template <typename AP> struct span_offset_type<AP, std::void_t<typename AP::offset_type>>
39{
42 using type = typename AP::offset_type;
43};
44
48template <typename AP> using span_offset_t = typename span_offset_type<AP>::type;
49
61template <class AP>
62concept AccessorPolicy = requires {
63 typename AP::element_type;
64 typename AP::data_handle_type;
65 typename AP::offset_policy;
66 typename AP::reference;
67} && requires(AP a, typename AP::data_handle_type dh, span_offset_t<AP> off) {
68 { a.offset(dh, off) } -> std::convertible_to<typename AP::offset_policy::data_handle_type>;
69 { a.access(dh, off) } -> std::same_as<typename AP::reference>;
70};
71
74{};
75
78{};
79
85template <class Accessor, class Domain> inline constexpr bool enable_accessor_in_domain = false;
86
88template <class ElementType>
89inline constexpr bool enable_accessor_in_domain<stdex::default_accessor<ElementType>, host_access_domain> = true;
90
95template <class Accessor, class Domain>
97 enable_accessor_in_domain<std::remove_cvref_t<Accessor>, std::remove_cvref_t<Domain>>;
98
102template <class Accessor>
104
108template <class Accessor>
110
119template <AccessorPolicy Accessor>
120 requires std::is_same_v<typename Accessor::reference, typename Accessor::element_type&>
122 public:
123 using element_type = typename Accessor::element_type const;
125 using data_handle_type = typename Accessor::data_handle_type;
128
129 UNI20_HOST_DEVICE constexpr const_accessor_adaptor(Accessor const& to_be_wrapped) : wrapped_{to_be_wrapped} {}
130
132 {
133 return wrapped_.access(p, i);
134 }
135
137 {
138 return wrapped_.offset(p, i);
139 }
140
141 private:
142 Accessor wrapped_;
143};
144
146template <class Accessor, class Domain>
147inline constexpr bool enable_accessor_in_domain<const_accessor_adaptor<Accessor>, Domain> =
148 enable_accessor_in_domain<Accessor, Domain>;
149
150//
151// const_accessor overloads: build a read-only accessor from a mutable one.
152//
153
159template <typename T>
160constexpr stdex::default_accessor<T const> const_accessor(stdex::default_accessor<T> const& accessor_policy)
161{
162 (void)accessor_policy;
163 return stdex::default_accessor<T const>();
164}
165
169template <class Accessor> struct is_default_accessor : std::false_type
170{};
171
175template <class ElementType> struct is_default_accessor<stdex::default_accessor<ElementType>> : std::true_type
176{};
177
181template <class Accessor>
183
184// /// \brief const_accessor on const_default_accessor yields itself.
185// template <typename T> constexpr default_accessor<T const> const_accessor(default_accessor<T const> const&)
186// {
187// return default_accessor<T const>();
188// }
189
195template <AccessorPolicy Acc>
196 requires(!std::is_const_v<typename Acc::element_type> &&
197 std::is_same_v<typename Acc::reference, typename Acc::element_type&>)
198constexpr auto const_accessor(Acc const& acc)
199{
200 return const_accessor_adaptor<Acc>{acc};
201}
202
210template <AccessorPolicy Acc>
211 requires(std::is_const_v<typename Acc::element_type> && !is_default_accessor_v<Acc>)
212constexpr Acc const_accessor(Acc const& acc)
213{
214 return acc;
215}
216
220template <AccessorPolicy Acc> using const_accessor_t = decltype(const_accessor(std::declval<Acc>()));
221
222namespace detail
223{
224
225template <class S> using span_type_t = std::remove_cvref_t<S>;
226
227template <class S, std::size_t... Axis> consteval bool span_has_ranked_subscript(std::index_sequence<Axis...>)
228{
229 using span_type = span_type_t<S>;
230 return requires(span_type const& span, typename span_type::index_type index) {
231 { span.operator[](((void)Axis, index)...) } -> std::same_as<typename span_type::reference>;
232 };
233}
234
235template <class S, std::size_t... Axis> consteval bool span_has_ranked_assignment(std::index_sequence<Axis...>)
236{
237 using span_type = span_type_t<S>;
238 return requires(span_type& span, typename span_type::index_type index, typename span_type::value_type value) {
239 span.operator[](((void)Axis, index)...) = value;
240 };
241}
242
243template <class S>
244concept SpanMetadata =
245 requires(span_type_t<S> const& span, std::size_t axis) {
246 typename span_type_t<S>::element_type;
247 typename span_type_t<S>::value_type;
248 typename span_type_t<S>::index_type;
249 typename span_type_t<S>::extents_type;
250 typename span_type_t<S>::layout_type;
251 typename span_type_t<S>::mapping_type;
252 typename span_type_t<S>::accessor_type;
253 typename span_type_t<S>::data_handle_type;
254 typename span_type_t<S>::reference;
255 typename std::integral_constant<std::size_t, span_type_t<S>::rank()>;
256
257 { span.extents() } -> std::convertible_to<typename span_type_t<S>::extents_type>;
258 { span.extent(axis) } -> std::convertible_to<typename span_type_t<S>::index_type>;
259 { span.mapping() } -> std::convertible_to<typename span_type_t<S>::mapping_type>;
260 { span.accessor() } -> std::convertible_to<typename span_type_t<S>::accessor_type>;
261 } && std::same_as<typename span_type_t<S>::value_type, std::remove_cv_t<typename span_type_t<S>::element_type>> &&
262 std::same_as<typename span_type_t<S>::index_type, typename span_type_t<S>::extents_type::index_type> &&
263 std::same_as<typename span_type_t<S>::mapping_type,
264 typename span_type_t<S>::layout_type::template mapping<typename span_type_t<S>::extents_type>> &&
265 std::same_as<typename span_type_t<S>::data_handle_type, typename span_type_t<S>::accessor_type::data_handle_type> &&
266 std::same_as<typename span_type_t<S>::reference, typename span_type_t<S>::accessor_type::reference> &&
267 (span_type_t<S>::rank() == span_type_t<S>::extents_type::rank());
268
269template <class S>
270concept SpanDescriptor = SpanMetadata<S> && requires(span_type_t<S> const& span) {
271 { span.data_handle() } -> std::convertible_to<typename span_type_t<S>::data_handle_type>;
272};
273
274template <class S>
275concept MdspecDescriptor = SpanMetadata<S> && requires(span_type_t<S> const& span) {
276 typename span_type_t<S>::data_descriptor_type;
277 { span.data_descriptor() } -> std::convertible_to<typename span_type_t<S>::data_descriptor_type const&>;
278};
279
280} // namespace detail
281
290template <class S>
292 detail::span_has_ranked_subscript<S>(std::make_index_sequence<detail::span_type_t<S>::rank()>{});
293
303template <class S>
304concept MdspecLike =
306
310template <class S>
312
316template <class S>
318
322template <class S>
324
328template <class S>
330
331namespace detail
332{
333
334template <class Span, class... Index>
335concept MdspanIndexPack = MdspanLike<Span> && (sizeof...(Index) == span_type_t<Span>::rank()) &&
336 (std::is_convertible_v<Index, typename span_type_t<Span>::index_type> && ...) &&
337 (std::is_nothrow_constructible_v<typename span_type_t<Span>::index_type, Index> && ...);
338
339template <class Accessor>
340concept AccessorReferenceAssignable =
341 requires(Accessor const& accessor, typename Accessor::data_handle_type handle, span_offset_t<Accessor> offset,
342 std::remove_const_t<typename Accessor::element_type> value) { accessor.access(handle, offset) = value; };
343
344} // namespace detail
345
356template <MdspanLike Span, class... Index>
357 requires detail::MdspanIndexPack<Span, Index...>
358constexpr decltype(auto) const_access(Span const& span, Index... indices)
359{
360 using index_type = typename detail::span_type_t<Span>::index_type;
361 auto accessor = const_accessor(span.accessor());
362 return accessor.access(span.data_handle(), span.mapping()(static_cast<index_type>(std::move(indices))...));
363}
364
372template <MdspanLike Span> [[nodiscard]] constexpr auto make_const_mdspan(Span const& span)
373{
374 auto accessor = const_accessor(span.accessor());
375 using accessor_type = decltype(accessor);
376 using span_type = std::remove_cvref_t<Span>;
377 using const_mdspan_type = stdex::mdspan<typename accessor_type::element_type, typename span_type::extents_type,
378 typename span_type::layout_type, accessor_type>;
379 return const_mdspan_type{span.data_handle(), span.mapping(), std::move(accessor)};
380}
381
386template <class S>
388 MdspanLike<S> && (!std::is_const_v<typename detail::span_type_t<S>::element_type>) &&
389 detail::span_has_ranked_assignment<S>(std::make_index_sequence<detail::span_type_t<S>::rank()>{});
390
397template <class S>
399 MdspecLike<S> && (!std::is_const_v<typename detail::span_type_t<S>::element_type>) &&
400 (MutableMdspanLike<S> || detail::AccessorReferenceAssignable<typename detail::span_type_t<S>::accessor_type>);
401
405template <class MDS>
406concept StridedMdspanLike = MdspanLike<MDS> && detail::span_type_t<MDS>::is_always_strided() &&
407 requires(detail::span_type_t<MDS> const& span, std::size_t axis) {
408 {
409 span.stride(axis)
410 } -> std::convertible_to<typename detail::span_type_t<MDS>::index_type>;
411 {
412 span.mapping().stride(axis)
413 } -> std::convertible_to<typename detail::span_type_t<MDS>::index_type>;
414 };
415
420template <class MDS>
422
426template <class S>
427concept StridedMdspecLike = MdspecLike<S> && detail::span_type_t<S>::is_always_strided() &&
428 requires(detail::span_type_t<S> const& span, std::size_t axis) {
429 { span.stride(axis) } -> std::convertible_to<typename detail::span_type_t<S>::index_type>;
430 {
431 span.mapping().stride(axis)
432 } -> std::convertible_to<typename detail::span_type_t<S>::index_type>;
433 };
434
439template <class S>
441
446template <class MDS, std::size_t Rank>
447concept RankedMdspanLike = MdspanLike<std::remove_cvref_t<MDS>> && (std::remove_cvref_t<MDS>::rank() == Rank);
448
453template <class S, std::size_t Rank>
454concept RankedMdspecLike = MdspecLike<std::remove_cvref_t<S>> && (std::remove_cvref_t<S>::rank() == Rank);
455
464template <class S>
465concept DiagonalMdspecLike = MdspecLike<std::remove_cvref_t<S>> && requires(std::remove_cvref_t<S> const& span) {
467 requires RankedMdspecLike<decltype(diagonal_components(span)), 1>;
468 requires std::same_as<typename std::remove_cvref_t<decltype(diagonal_components(span))>::element_type,
469 typename std::remove_cvref_t<S>::element_type>;
470};
471
476template <class S>
479 MutableMdspecLike<decltype(diagonal_components(std::declval<std::remove_cvref_t<S> const&>()))>;
480
486template <class S, std::size_t Rank>
488
493template <class MDS, std::size_t Rank>
495 MutableMdspanLike<std::remove_cvref_t<MDS>> && (std::remove_cvref_t<MDS>::rank() == Rank);
496
500template <class MDS>
502 MdspanLike<std::remove_cvref_t<MDS>> && is_default_accessor_v<typename std::remove_cvref_t<MDS>::accessor_type>;
503
508template <class MDS, std::size_t Rank>
510
515template <class S, std::size_t Rank>
517
523template <class S, std::size_t Rank>
526
531template <class MDS, std::size_t Rank>
534
535namespace detail
536{
537
544template <StridedMdspecLike S, size_t... I> constexpr auto strides_impl(S const& s, std::index_sequence<I...>)
545{
546 using index_type = typename S::index_type;
547 // fold the pack I... into an array by calling s.mapping().stride(I) for each I
548 return std::array<index_type, sizeof...(I)>{s.mapping().stride(I)...};
549}
550
551} // namespace detail
552
558template <StridedMdspecLike S> auto strides(S const& s)
559{
560 return detail::strides_impl(s, std::make_index_sequence<S::rank()>{});
561}
562
563} // namespace uni20
Ordered domain spaces of a tensor morphism.
Definition morphism_boundary.hpp:24
Adaptor that exposes a mutable lvalue accessor as read-only.
Definition mdspan/concepts.hpp:121
UNI20_HOST_DEVICE constexpr const_accessor_adaptor(Accessor const &to_be_wrapped)
Definition mdspan/concepts.hpp:129
span_offset_t< Accessor > offset_type
Definition mdspan/concepts.hpp:127
typename Accessor::data_handle_type data_handle_type
Definition mdspan/concepts.hpp:125
typename Accessor::element_type const element_type
Definition mdspan/concepts.hpp:123
UNI20_HOST_DEVICE constexpr reference access(data_handle_type p, offset_type i) const
Definition mdspan/concepts.hpp:131
element_type & reference
Definition mdspan/concepts.hpp:124
UNI20_HOST_DEVICE constexpr data_handle_type offset(data_handle_type p, offset_type i) const
Definition mdspan/concepts.hpp:136
Project compiler annotations shared by host and device code.
#define UNI20_HOST_DEVICE
Definition compiler_attributes.hpp:12
Accessor policy explicitly valid in one execution domain.
Definition mdspan/concepts.hpp:96
A model of the C++ mdspan AccessorPolicy named requirement.
Definition mdspan/concepts.hpp:62
Accessor policy that may be evaluated directly by CUDA device code.
Definition mdspan/concepts.hpp:109
Mdspan whose accessor may be evaluated directly by CUDA device code.
Definition mdspan/concepts.hpp:317
Immediate or descriptor-backed mdspan metadata targeting CUDA access.
Definition mdspan/concepts.hpp:329
An mdspan-like type whose accessor is stdex::default_accessor.
Definition mdspan/concepts.hpp:501
Full logical mdspec with a rank-one view of its generalized diagonal components.
Definition mdspan/concepts.hpp:465
Accessor policy that may be evaluated directly by host code.
Definition mdspan/concepts.hpp:103
Mdspan whose accessor may be evaluated directly by host code.
Definition mdspan/concepts.hpp:311
Immediate or descriptor-backed mdspan metadata targeting host access.
Definition mdspan/concepts.hpp:323
A readable type implementing the mdspan observers and multidimensional subscript contract.
Definition mdspan/concepts.hpp:291
Mdspan metadata whose data handle is immediate or available through a data descriptor.
Definition mdspan/concepts.hpp:304
Writable generalized-diagonal mdspec with writable rank-one components.
Definition mdspan/concepts.hpp:477
MdspanLike types whose accessor supports indexed assignment.
Definition mdspan/concepts.hpp:387
MdspecLike types whose eventual storage supports writes.
Definition mdspan/concepts.hpp:398
A mutable mdspan-like type with a specified static rank.
Definition mdspan/concepts.hpp:494
Mutable mdspec-like type with a specified static rank.
Definition mdspan/concepts.hpp:487
A mutable strided mdspan-like type with a specified static rank.
Definition mdspan/concepts.hpp:532
Mutable strided mdspec-like type with a specified static rank.
Definition mdspan/concepts.hpp:524
Mutable mdspan-like types whose layout reports they are always strided.
Definition mdspan/concepts.hpp:421
Mutable mdspec-like type whose mapping is always strided.
Definition mdspan/concepts.hpp:440
An mdspan-like type with a specified static rank.
Definition mdspan/concepts.hpp:447
An mdspec-like type with a specified static rank.
Definition mdspan/concepts.hpp:454
A strided mdspan-like type with a specified static rank.
Definition mdspan/concepts.hpp:509
A strided mdspec-like type with a specified static rank.
Definition mdspan/concepts.hpp:516
An mdspan-like type whose mapping is always strided and exposes stride observers.
Definition mdspan/concepts.hpp:406
An mdspec-like type whose mapping exposes multidimensional strides.
Definition mdspan/concepts.hpp:427
cuda::ResourceLease< HandleSlot > handle
Definition cublas/execution.cpp:33
locale_t value
Definition data_table.cpp:49
auto strides(S const &s)
Retrieve the strides associated with a strided mdspec-like type.
Definition mdspan/concepts.hpp:558
decltype(const_accessor(std::declval< Acc >())) const_accessor_t
Type alias that produces the const-qualified version of an accessor policy.
Definition mdspan/concepts.hpp:220
typename AP::offset_type type
The resulting offset type defined by the accessor policy.
Definition mdspan/concepts.hpp:42
std::size_t type
The resulting offset type (std::size_t by default).
Definition mdspan/concepts.hpp:32
constexpr decltype(auto) const_access(Span const &span, Index... indices)
Access one mdspan element through a read-only adaptation of its stored accessor.
Definition mdspan/concepts.hpp:358
constexpr bool is_default_accessor_v
True when an accessor is stdex::default_accessor<T>.
Definition mdspan/concepts.hpp:182
typename span_offset_type< AP >::type span_offset_t
Convenience alias for accessor_offset_type<AP>::type.
Definition mdspan/concepts.hpp:48
constexpr stdex::default_accessor< T const > const_accessor(stdex::default_accessor< T > const &accessor_policy)
Wrap a default_accessor<T> into a const_default_accessor<T>.
Definition mdspan/concepts.hpp:160
Configured gateway to Uni20's mdspan implementation.
Definition qnum.hpp:403
Definition data_table.cpp:8
Definition async/async.hpp:26
constexpr bool enable_accessor_in_domain
Opt-in customization for the execution domains supported by an accessor.
Definition mdspan/concepts.hpp:85
std::ptrdiff_t index_type
Definition types.hpp:19
constexpr auto diagonal_components(stdex::mdspan< ElementType, Extents, LayoutPolicy, diagonal_accessor< ElementType, AccessorExtents > > const &span)
Expose the physically stored values of a generalized-diagonal mdspan.
Definition diagonal_accessor.hpp:252
constexpr auto make_const_mdspan(Span const &span)
Build a read-only mdspan descriptor over the same storage and mapping.
Definition mdspan/concepts.hpp:372
std::size_t span
Definition presentation.cpp:2017
Execution domain in which CUDA device code may evaluate an accessor.
Definition mdspan/concepts.hpp:78
Execution domain in which ordinary host code may evaluate an accessor.
Definition mdspan/concepts.hpp:74
Trait that recognizes the standard mdspan default accessor.
Definition mdspan/concepts.hpp:170
Trait to pull an AccessorPolicy’s offset_type if present, or fall back to std::size_t otherwise.
Definition mdspan/concepts.hpp:29