17#include <initializer_list>
31template <std::
size_t A, std::
size_t B>
static constexpr std::size_t merge_extent()
35 else if constexpr (A == stdex::dynamic_extent)
37 else if constexpr (B == stdex::dynamic_extent)
40 static_assert(A == B || A == stdex::dynamic_extent || B == stdex::dynamic_extent,
"Incompatible static extents");
45template <std::size_t... Ns>
struct merge_pack;
48template <std::
size_t A>
struct merge_pack<A>
50 static constexpr std::size_t
value = A;
54template <std::size_t A, std::size_t B, std::size_t... Rest>
struct merge_pack<A, B, Rest...>
56 static constexpr std::size_t
value = merge_pack<merge_extent<A, B>(), Rest...>
::value;
60template <
typename FirstSpan,
typename... OtherSpans>
struct common_extents
62 static constexpr std::size_t NumSpans = 1 +
sizeof...(OtherSpans);
65 static constexpr std::size_t R = FirstSpan::rank();
66 static_assert((... && (OtherSpans::rank() == R)),
"common_extents: ranks must match");
72 template <std::
size_t I>
static constexpr std::size_t merged_static_extent()
75 return merge_pack<FirstSpan::extents_type::static_extent(I),
76 OtherSpans::extents_type::static_extent(I)...>
::value;
80 template <std::size_t... Is>
static constexpr auto make_extents(std::index_sequence<Is...>)
83 merged_static_extent<Is>()...
89 using type =
decltype(make_extents(std::make_index_sequence<R>{}));
92 template <std::size_t... Is>
94 static type make_impl(std::index_sequence<Is...>, FirstSpan
const& first, OtherSpans
const&... otherspans)
97 type ext{first.extent(Is)...};
99 auto do_check = [&](
auto const& sp) { assert(ext == sp.extents()); };
101 (do_check(otherspans), ...);
109 static type make(FirstSpan
const& firstspan, OtherSpans
const&... otherspans)
111 return make_impl(std::make_index_sequence<R>{}, firstspan, otherspans...);
120template <
typename... Spans>
using common_extents_t =
typename detail::common_extents<Spans...>::type;
129 return detail::common_extents<Spans...>::make(spans...);
135template <
typename T, std::size_t N1, std::size_t N2, std::size_t... I, std::size_t... J>
136UNI20_HOST_DEVICE constexpr std::array<T, N1 + N2> concat_impl(
const std::array<T, N1>& a1,
const std::array<T, N2>& a2,
137 std::index_sequence<I...>, std::index_sequence<J...>)
140 return {{a1[I]..., a2[J]...}};
143template <
typename T, std::size_t N, std::size_t... I>
144UNI20_HOST_DEVICE constexpr std::array<T, N + 1> concat_impl(
const std::array<T, N>& a,
const T& x,
145 std::index_sequence<I...>)
147 return {{a[I]..., x}};
150template <
typename T, std::size_t N, std::size_t... I>
151UNI20_HOST_DEVICE constexpr std::array<T, N + 1> concat_impl(
const T& x,
const std::array<T, N>& a,
152 std::index_sequence<I...>)
154 return {{x, a[I]...}};
167template <
typename T, std::
size_t N1, std::
size_t N2>
170 return detail::concat_impl(a1, a2, std::make_index_sequence<N1>{}, std::make_index_sequence<N2>{});
180template <
typename T, std::
size_t N>
183 return detail::concat_impl(x, a, std::make_index_sequence<N>{});
193template <
typename T, std::
size_t N>
196 return detail::concat_impl(a, x, std::make_index_sequence<N>{});
202template <
typename IndexType, std::size_t Rank,
typename Mapping, std::size_t... I>
203UNI20_HOST_DEVICE constexpr std::array<IndexType, Rank> mapping_strides_impl(Mapping
const& mapping,
204 std::index_sequence<I...>)
206 return {
static_cast<IndexType
>(mapping.stride(I))...};
209template <
typename IndexType, std::
size_t Rank,
typename Mapping>
210UNI20_HOST_DEVICE constexpr std::array<IndexType, Rank> mapping_strides(Mapping
const& mapping)
212 return mapping_strides_impl<IndexType, Rank>(mapping, std::make_index_sequence<Rank>{});
216template <
typename T, std::size_t... I>
constexpr auto make_tuple_n_impl(std::index_sequence<I...>)
219 return std::tuple{(
static_cast<void>(I), T{})...};
228template <
typename T, std::
size_t N>
229using tuple_n =
decltype(detail::make_tuple_n_impl<T>(std::make_index_sequence<N>{}));
236 static_assert(NumSpans >= 1,
"StridedZipLayout requires at least one span");
283 for (std::size_t d = 0; d < Ext::rank(); ++d)
285 auto s0 = all_strides_[0][d];
286 for (std::size_t i = 1; i < NumSpans; ++i)
288 if (all_strides_[i][d] != s0)
return false;
300 return all_strides_[0];
311 return all_strides_[0][r];
323 template <
typename... Mappings>
329 : extents_(exts), all_strides_{detail::mapping_strides<index_type, Ext::rank()>(maps)...}
338 std::array<std::array<
index_type, Ext::rank()>, NumSpans>
const& strides_pack) noexcept
339 : extents_(exts), all_strides_(strides_pack)
345 template <
typename OtherExt>
347 std::array<
index_type, Ext::rank()>
const& new_strides,
349 : extents_(other.extents()), all_strides_(
concat(new_strides, other.all_strides()))
355 template <
typename OtherExt>
358 std::array<
index_type, Ext::rank()>
const& new_strides) noexcept
359 : extents_(other.extents()), all_strides_(
concat(other.all_strides(), new_strides))
366 template <
typename LeftMap,
typename RightMap>
367 requires(LeftMap::num_spans + RightMap::num_spans ==
num_spans)
369 : extents_(left.extents()), all_strides_(
concat(left.all_strides(), right.all_strides()))
384 static_assert(
sizeof...(Idx) == Ext::rank(),
"Wrong number of indices");
388 return offset_impl(ix, std::make_index_sequence<NumSpans>{});
393 template <std::size_t S, std::size_t... D>
395 std::index_sequence<D...>)
const noexcept
398 return ((all_strides_[S][D] * ix[D]) + ... +
index_type(0));
402 template <std::size_t... S>
404 std::index_sequence<S...>)
const noexcept
407 return offset_type{span_offset<S>(ix, std::make_index_sequence<Ext::rank()>{})...};
429 using offset_type = std::tuple<span_offset_t<typename Layouts::template mapping<Extents>>...>;
448 : extents_(ext), impls_{m...}
461 std::size_t max_sz = 0;
463 [&](
auto const&... m) {
464 (void)std::initializer_list<int>{
465 (max_sz = std::max<std::size_t>(max_sz, m.required_span_size()), 0)...};
478 return std::apply([&](
auto const&... m) {
return offset_type{m(idxs...)...}; }, impls_);
487 return extents_ == o.extents_ && impls_ == o.impls_;
497 std::tuple<typename Layouts::template mapping<Extents>...> impls_;
Project compiler annotations shared by host and device code.
#define UNI20_HOST_DEVICE
Definition compiler_attributes.hpp:12
An mdspan-like type whose mapping is always strided and exposes stride observers.
Definition mdspan/concepts.hpp:406
locale_t value
Definition data_table.cpp:49
auto make_common_extents(Spans... spans)
Build an extents object representing the common shape of the given spans.
Definition zip_layout.hpp:127
decltype(detail::make_tuple_n_impl< T >(std::make_index_sequence< N >{})) tuple_n
Alias: tuple_n<T,N> is std::tuple<T,T,…> with N repetitions of T.
Definition zip_layout.hpp:229
typename detail::common_extents< Spans... >::type common_extents_t
Convenience alias that represents the common extents of a set of mdspans.
Definition zip_layout.hpp:120
UNI20_HOST_DEVICE constexpr std::array< T, N1+N2 > concat(const std::array< T, N1 > &a1, const std::array< T, N2 > &a2)
Concatenate two std::array instances into one (constexpr helper).
Definition zip_layout.hpp:168
UNI20_HOST_DEVICE constexpr mapping(LeftMap const &left, RightMap const &right) noexcept
Merge two sub-mappings whose span counts sum to NumSpans.
Definition zip_layout.hpp:368
static UNI20_HOST_DEVICE constexpr bool is_always_unique() noexcept
Always unique for uni20 tensors.
Definition zip_layout.hpp:261
UNI20_HOST_DEVICE constexpr extents_type const & extents() const noexcept
Return the extents of the layout.
Definition zip_layout.hpp:375
UNI20_HOST_DEVICE constexpr mapping(extents_type const &exts, std::array< std::array< index_type, Ext::rank()>, NumSpans > const &strides_pack) noexcept
Construct from shared extents and per-span raw strides.
Definition zip_layout.hpp:336
UNI20_HOST_DEVICE constexpr index_type stride(rank_type r) const noexcept
Return the common stride in dimension r.
Definition zip_layout.hpp:308
UNI20_HOST_DEVICE constexpr bool is_strided() const noexcept
True if every dimension uses the same stride across all spans.
Definition zip_layout.hpp:281
UNI20_HOST_DEVICE constexpr mapping(extents_type const &exts, Mappings... maps) noexcept
Construct from extents and existing child mappings.
Definition zip_layout.hpp:328
UNI20_HOST_DEVICE constexpr bool operator!=(mapping const &o) const noexcept
Compare two mappings for inequality.
Definition zip_layout.hpp:493
UNI20_HOST_DEVICE constexpr bool is_exhaustive() const noexcept
Never exhaustive at runtime.
Definition zip_layout.hpp:274
static UNI20_HOST_DEVICE constexpr bool is_always_exhaustive() noexcept
Never exhaustive: no single contiguous backing buffer.
Definition zip_layout.hpp:437
UNI20_HOST_DEVICE constexpr std::array< index_type, Ext::rank()> strides() const noexcept
Return the common strides for each dimension.
Definition zip_layout.hpp:297
UNI20_HOST_DEVICE constexpr extents_type const & extents() const noexcept
Access the common extents.
Definition zip_layout.hpp:454
UNI20_HOST_DEVICE constexpr offset_type operator()(Idx... idxs) const noexcept
Compute per-span linear offsets for a multi-index.
Definition zip_layout.hpp:382
UNI20_HOST_DEVICE std::array< std::array< index_type, Ext::rank()>, num_spans > const & all_strides() const noexcept
Retrieve the 2-D array of all per-span strides.
Definition zip_layout.hpp:318
UNI20_HOST_DEVICE constexpr bool is_unique() const noexcept
Always unique at runtime.
Definition zip_layout.hpp:271
static UNI20_HOST_DEVICE constexpr bool is_always_unique() noexcept
Always unique for uni20 tensors.
Definition zip_layout.hpp:434
UNI20_HOST_DEVICE constexpr mapping(typename StridedZipLayout< num_spans - 1 >::template mapping< OtherExt > const &other, std::array< index_type, Ext::rank()> const &new_strides) noexcept
Append one span’s strides after an existing mapping of N–1 spans.
Definition zip_layout.hpp:356
UNI20_HOST_DEVICE constexpr offset_type operator()(Idx... idxs) const noexcept
Compute the per-layout offsets for a given multi-index.
Definition zip_layout.hpp:476
static UNI20_HOST_DEVICE constexpr bool is_always_strided() noexcept
Statically unknown if strided: may differ per dimension.
Definition zip_layout.hpp:267
static UNI20_HOST_DEVICE constexpr bool is_always_exhaustive() noexcept
Never exhaustive: no single contiguous backing buffer.
Definition zip_layout.hpp:264
UNI20_HOST_DEVICE constexpr std::size_t required_span_size() const noexcept
Return the maximum required span size among the child mappings.
Definition zip_layout.hpp:459
UNI20_HOST_DEVICE constexpr mapping(Extents const &ext, typename Layouts::template mapping< Extents > const &... m) noexcept
Construct child mappings.
Definition zip_layout.hpp:446
static UNI20_HOST_DEVICE constexpr bool is_always_strided() noexcept
Not strided.
Definition zip_layout.hpp:440
UNI20_HOST_DEVICE constexpr bool operator==(mapping const &o) const noexcept
Compare two mappings for equality.
Definition zip_layout.hpp:485
typename zip_layout_selector< Spans... >::type zip_layout_t
Alias to extract the chosen layout policy for the given spans.
Definition zip_layout.hpp:520
static constexpr std::size_t num_spans
Number of spans in this zip layout.
Definition zip_layout.hpp:257
UNI20_HOST_DEVICE constexpr mapping(std::array< index_type, Ext::rank()> const &new_strides, typename StridedZipLayout< num_spans - 1 >::template mapping< OtherExt > const &other) noexcept
Prepend one span’s strides before an existing mapping of N–1 spans.
Definition zip_layout.hpp:346
Mdspan concept and accessor extensions for Uni20.
Configured gateway to Uni20's mdspan implementation.
Definition async/async.hpp:26
std::ptrdiff_t index_type
Definition types.hpp:19
Definition zip_layout.hpp:422
std::tuple< span_offset_t< typename Layouts::template mapping< Extents > >... > offset_type
Definition zip_layout.hpp:429
static UNI20_HOST_DEVICE constexpr rank_type rank_dynamic() noexcept
Definition zip_layout.hpp:428
typename Extents::rank_type rank_type
Definition zip_layout.hpp:426
Extents extents_type
Definition zip_layout.hpp:424
static UNI20_HOST_DEVICE constexpr rank_type rank() noexcept
Definition zip_layout.hpp:427
typename Extents::index_type index_type
Definition zip_layout.hpp:425
Fallback zip layout for arbitrary mapping policies.
Definition zip_layout.hpp:420
Nested mapping policy for extents Ext, modeling LayoutMappingPolicy.
Definition zip_layout.hpp:245
typename Ext::rank_type rank_type
Definition zip_layout.hpp:249
tuple_n< index_type, NumSpans > offset_type
Definition zip_layout.hpp:251
Ext extents_type
multidimensional shape
Definition zip_layout.hpp:247
typename Ext::index_type index_type
Definition zip_layout.hpp:248
Zip layout for NumSpans strided spans (all using layout_stride).
Definition zip_layout.hpp:235
static constexpr std::size_t num_spans
Number of spans in this zip layout.
Definition zip_layout.hpp:239
Picks the right zip layout for a pack of mdspan types.
Definition zip_layout.hpp:505