32template <
class LayoutPolicy>
33concept CanonicalReshapeLayout =
34 std::same_as<LayoutPolicy, stdex::layout_left> || std::same_as<LayoutPolicy, stdex::layout_right>;
37concept CanonicallyLaidOutMdspan =
38 StridedMdspanLike<Span> && CanonicalReshapeLayout<typename std::remove_cvref_t<Span>::layout_type>;
41concept CanonicallyLaidOutOwningTensor =
42 OwningTensor<T> && MutableStridedTensorView<T> && CanonicalReshapeLayout<typename tensor_mdspec_t<T>::layout_type>;
44template <
class T,
class NewExtents>
45using reshape_rebind_t =
typename std::remove_cvref_t<T>::template rebind_extents_type<NewExtents>;
47template <
class T,
class NewExtents>
48concept StorageTransferReshapableTensor =
49 CanonicallyLaidOutOwningTensor<T> &&
50 requires(std::remove_cvref_t<T>&& tensor,
typename std::remove_cvref_t<T>::storage_type storage,
51 typename std::remove_cvref_t<T>::accessor_factory_type accessor_factory,
52 typename reshape_rebind_t<T, NewExtents>::mapping_type mapping) {
53 { std::move(tensor).release_storage() } -> std::same_as<typename std::remove_cvref_t<T>::storage_type>;
55 std::move(tensor).release_accessor_factory()
56 } -> std::same_as<typename std::remove_cvref_t<T>::accessor_factory_type>;
58 reshape_rebind_t<T, NewExtents>::adopt_storage(std::move(mapping), std::move(storage),
59 std::move(accessor_factory))
60 } -> std::same_as<reshape_rebind_t<T, NewExtents>>;
63template <
class Index> [[nodiscard]]
constexpr bool positive_stride_equals(Index stride, std::size_t expected)
65 if constexpr (std::signed_integral<Index>)
66 if (stride < 0)
return false;
67 return std::in_range<std::size_t>(stride) &&
static_cast<std::size_t
>(stride) == expected;
70template <Str
idedMdspecLike Span> [[nodiscard]]
bool has_row_major_contiguous_mapping(Span
const&
span)
72 std::size_t expected = 1;
73 for (std::size_t axis = Span::rank(); axis > 0; --axis)
75 auto const extent =
static_cast<std::size_t
>(
span.extent(axis - 1));
76 if (extent > 1 && !positive_stride_equals(
span.stride(axis - 1), expected))
return false;
79 if (expected > std::numeric_limits<std::size_t>::max() / extent)
return false;
86template <Str
idedMdspecLike Span> [[nodiscard]]
bool has_column_major_contiguous_mapping(Span
const&
span)
88 std::size_t expected = 1;
89 for (std::size_t axis = 0; axis < Span::rank(); ++axis)
91 auto const extent =
static_cast<std::size_t
>(
span.extent(axis));
92 if (extent > 1 && !positive_stride_equals(
span.stride(axis), expected))
return false;
95 if (expected > std::numeric_limits<std::size_t>::max() / extent)
return false;
102template <CanonicalReshapeLayout LayoutPolicy, Str
idedMdspecLike Span>
103[[nodiscard]]
bool has_canonical_contiguous_mapping(Span
const&
span)
105 auto const logical_size = checked_element_count(
span.extents());
106 if constexpr (
requires {
span.mapping().is_unique(); })
107 if (!
span.mapping().is_unique())
return false;
108 if constexpr (
requires {
span.mapping().is_exhaustive(); })
109 if (!
span.mapping().is_exhaustive())
return false;
110 if constexpr (
requires {
span.mapping().required_span_size(); })
112 auto const required_size =
span.mapping().required_span_size();
113 if (!std::in_range<std::size_t>(required_size) ||
static_cast<std::size_t
>(required_size) != logical_size)
118 if (logical_size <= 1)
return true;
120 if constexpr (std::same_as<LayoutPolicy, stdex::layout_left>)
121 return has_column_major_contiguous_mapping(
span);
123 return has_row_major_contiguous_mapping(
span);
126template <CanonicalReshapeLayout LayoutPolicy, Str
idedMdspecLike Span>
127void require_canonical_contiguous_mapping(Span
const&
span)
129 if constexpr (std::same_as<LayoutPolicy, stdex::layout_left>)
131 ERROR_IF(!has_canonical_contiguous_mapping<LayoutPolicy>(
span),
132 "reshape requires a unique, exhaustive, canonical column-major source mapping");
136 ERROR_IF(!has_canonical_contiguous_mapping<LayoutPolicy>(
span),
137 "reshape requires a unique, exhaustive, canonical row-major source mapping");
141template <CanonicalReshapeLayout LayoutPolicy, StridedMdspecLike Span, std::integral... Extents>
142[[nodiscard]]
auto make_reshape_view(Span&& source, Extents... requested_extents)
144 using source_type = std::remove_cvref_t<Span>;
145 require_canonical_contiguous_mapping<LayoutPolicy>(source);
146 auto const source_size = checked_element_count(source.extents());
147 auto new_extents = make_reshape_extents(source_size, requested_extents...);
148 using extents_type =
decltype(new_extents);
149 using accessor_type =
typename source_type::accessor_type;
150 using element_type =
typename source_type::element_type;
151 using mapping_type =
typename LayoutPolicy::template mapping<extents_type>;
152 if constexpr (MdspanLike<source_type>)
154 using result_type = stdex::mdspan<element_type, extents_type, LayoutPolicy, accessor_type>;
155 return result_type{source.data_handle(), mapping_type{new_extents}, source.accessor()};
159 using descriptor_type =
typename source_type::data_descriptor_type;
160 using result_type = mdspec<element_type, extents_type, LayoutPolicy, accessor_type, descriptor_type>;
161 return result_type{source.data_descriptor(), mapping_type{new_extents}, source.accessor()};
165template <CanonicalReshapeLayout LayoutPolicy, ImmediateTensorView
Tensor, std::integral... Extents>
166 requires(std::is_lvalue_reference_v<Tensor &&> && StridedImmediateTensorView<Tensor>)
167[[nodiscard]]
auto make_tensor_reshape_view(Tensor&& tensor, Extents... requested_extents);
174template <detail::CanonicallyLaidOutMdspan Span, std::integral... Extents>
175[[nodiscard]]
auto reshape_view(Span&& source, Extents... requested_extents)
177 using layout_type =
typename std::remove_cvref_t<Span>::layout_type;
178 return detail::make_reshape_view<layout_type>(std::forward<Span>(source), requested_extents...);
184template <StridedMdspanLike Span, std::integral... Extents>
187 return detail::make_reshape_view<stdex::layout_left>(std::forward<Span>(source), requested_extents...);
193template <StridedMdspanLike Span, std::integral... Extents>
196 return detail::make_reshape_view<stdex::layout_right>(std::forward<Span>(source), requested_extents...);
202template <MdspanLike Mdspan,
class StoragePolicy,
class BackendSelector>
203class ReshapedTensor :
public detail::precision_default<typename Mdspan::value_type> {
217 using const_mdspan_type = stdex::mdspan<const_element_type, extents_type, layout_type, const_accessor_type>;
221 : span_(
std::move(
span)), selector_(
std::move(selector))
240 [[nodiscard]]
constexpr auto extent(std::size_t axis)
const noexcept ->
index_type {
return span_.extent(axis); }
243 template <
class... Index>
244 requires(
sizeof...(Index) == extents_type::rank())
247 return span_[indices...];
251 template <
class... Index>
252 requires detail::MdspanIndexPack<
mdspan_type, Index...>
253 constexpr decltype(
auto)
operator[](Index... indices)
const
267template <
class Tensor, detail::CanonicalReshapeLayout LayoutPolicy, std::integral... RequestedExtents>
268 requires TensorView<Tensor> && StridedTensorView<Tensor>
276 std::declval<RequestedExtents>()...));
278 mdspec_of(std::declval<tensor_type const&>()), std::declval<RequestedExtents>()...));
291 static_cast<void>(this->
mdspec());
298 : tensor_(tensor), requested_extents_(requested_extents...)
300 CHECK(tensor_ !=
nullptr);
306 [[nodiscard]]
Precision default_precision() const
309 return this->
base().default_precision();
313 [[nodiscard]] std::optional<Precision> default_precision_if_set() const
316 return this->
base().default_precision_if_set();
327 [
this](
auto... requested_extents) {
328 return detail::make_reshape_view<LayoutPolicy>(
mdspec_of(this->
base()), requested_extents...);
337 [
this](
auto... requested_extents) {
338 return detail::make_reshape_view<LayoutPolicy>(
mdspec_of(this->
base()), requested_extents...);
364 template <
class... Index>
368 return this->
mdspan()[indices...];
372 template <
class... Index>
376 return this->
mdspan()[indices...];
383 [[nodiscard]]
tensor_type const&
base() const noexcept {
return *std::launder(tensor_); }
393template <CanonicalReshapeLayout LayoutPolicy, ImmediateTensorView Tensor, std::integral... Extents>
394 requires(std::is_lvalue_reference_v<Tensor &&> && StridedImmediateTensorView<Tensor>)
395[[nodiscard]]
auto make_tensor_reshape_view(Tensor&& tensor, Extents... requested_extents)
397 if constexpr (has_runtime_precision_v<tensor_element_t<Tensor>>)
400 return IndirectReshapedTensorView<std::remove_reference_t<Tensor>, LayoutPolicy, Extents...>{tensor,
401 requested_extents...};
405 auto span = make_reshape_view<LayoutPolicy>(tensor.mdspan(), requested_extents...);
406 using span_type =
decltype(
span);
407 using storage_policy = tensor_storage_policy_t<std::remove_cvref_t<Tensor>>;
408 using selector_type = std::remove_cvref_t<
decltype(tensor.backend_selector())>;
409 return ReshapedTensor<span_type, storage_policy, selector_type>{std::move(
span), tensor.backend_selector()};
420template <ImmediateTensorView
Tensor, std::integral... Extents>
421 requires(std::is_lvalue_reference_v<Tensor &&> && StridedImmediateTensorView<Tensor> &&
422 detail::CanonicalReshapeLayout<typename immediate_tensor_mdspan_t<Tensor>::layout_type>)
426 return detail::make_tensor_reshape_view<layout_type>(std::forward<Tensor>(tensor), requested_extents...);
430template <ImmediateTensorView Tensor, std::integral... Extents>
431 requires(std::is_lvalue_reference_v<Tensor &&> && StridedImmediateTensorView<Tensor>)
434 return detail::make_tensor_reshape_view<stdex::layout_left>(std::forward<Tensor>(tensor), requested_extents...);
438template <ImmediateTensorView Tensor, std::integral... Extents>
439 requires(std::is_lvalue_reference_v<Tensor &&> && StridedImmediateTensorView<Tensor>)
442 return detail::make_tensor_reshape_view<stdex::layout_right>(std::forward<Tensor>(tensor), requested_extents...);
448template <detail::CanonicallyLaidOutOwningTensor TensorType, std::integral... Extents>
449 requires(
sizeof...(Extents) == tensor_extents_t<TensorType>::rank() &&
450 requires(TensorType& tensor,
typename TensorType::mapping_type mapping) {
451 tensor.replace_mapping(std::move(mapping));
457 auto const source_size = detail::checked_element_count(tensor.extents());
458 auto requested = detail::make_reshape_extents(source_size, requested_extents...);
459 auto new_extents = detail::convert_reshape_extents<tensor_extents>(requested);
460 using mapping_type =
typename layout_type::template mapping<tensor_extents>;
461 tensor.replace_mapping(mapping_type{new_extents});
467template <
class TensorType, std::integral... Extents>
468 requires detail::StorageTransferReshapableTensor<TensorType, stdex::dextents<
index_type,
sizeof...(Extents)>>
469[[nodiscard]]
auto reshape(TensorType tensor, Extents... requested_extents)
471 auto const source_size = detail::checked_element_count(tensor.extents());
472 auto new_extents = detail::make_reshape_extents(source_size, requested_extents...);
474 using source_type = std::remove_cvref_t<TensorType>;
475 using result_type =
typename source_type::template rebind_extents_type<
decltype(new_extents)>;
477 using mapping_type =
typename layout_type::template mapping<
decltype(new_extents)>;
478 auto accessor_factory = std::move(tensor).release_accessor_factory();
479 auto storage = std::move(tensor).release_storage();
480 return result_type::adopt_storage(mapping_type{new_extents}, std::move(storage), std::move(accessor_factory));
Owning tensor implementation and configurable extents alias.
Tensor-level descriptor that resolves a reshape through its parent tensor.
Definition reshape.hpp:269
IndirectReshapedTensorView(tensor_type *tensor, RequestedExtents... requested_extents)
Bind a reshape to externally retained tensor storage.
Definition reshape.hpp:297
typename mdspec_type::value_type value_type
Definition reshape.hpp:281
tensor_type const & base() const noexcept
Return the tensor referenced by this descriptor.
Definition reshape.hpp:383
typename mdspec_type::index_type index_type
Definition reshape.hpp:283
tensor_storage_policy_t< std::remove_cv_t< tensor_type > > storage_policy
Definition reshape.hpp:272
auto mdspan() const &-> const_mdspec_type
Resolve the read-only reshaped mdspan when the parent is immediately accessible.
Definition reshape.hpp:351
typename mdspec_type::layout_type layout_type
Definition reshape.hpp:284
IndirectReshapedTensorView(tensor_type &tensor, RequestedExtents... requested_extents)
Bind and immediately validate a reshape of an existing tensor.
Definition reshape.hpp:288
auto mdspec() const &-> const_mdspec_type
Return the reshaped immediate or deferred metadata for read-only access.
Definition reshape.hpp:334
typename mdspec_type::element_type element_type
Definition reshape.hpp:280
auto extents() const -> extents_type
Return the reshaped extents.
Definition reshape.hpp:358
auto extent(std::size_t axis) const -> index_type
Return one reshaped extent.
Definition reshape.hpp:361
decltype(auto) operator[](Index... indices)
Evaluate or assign one reshaped element according to source mutability.
Definition reshape.hpp:366
auto mdspec() &-> mdspec_type
Return the reshaped immediate or deferred metadata with source mutability.
Definition reshape.hpp:324
std::remove_cvref_t< decltype(std::declval< tensor_type const & >().backend_selector())> backend_selector_type
Definition reshape.hpp:273
void async_alias_tag
Definition reshape.hpp:279
typename mdspec_type::extents_type extents_type
Definition reshape.hpp:282
decltype(detail::make_reshape_view< LayoutPolicy >(mdspec_of(std::declval< tensor_type const & >()), std::declval< RequestedExtents >()...)) const_mdspec_type
Definition reshape.hpp:278
std::tuple< RequestedExtents... > requested_extents_type
Definition reshape.hpp:274
decltype(detail::make_reshape_view< LayoutPolicy >(mdspec_of(std::declval< tensor_type & >()), std::declval< RequestedExtents >()...)) mdspec_type
Definition reshape.hpp:276
decltype(auto) operator[](Index... indices) const
Evaluate one reshaped element through the read-only accessor.
Definition reshape.hpp:374
typename mdspec_type::mapping_type mapping_type
Definition reshape.hpp:285
tensor_type & base() noexcept
Return the tensor referenced by this descriptor.
Definition reshape.hpp:380
constexpr decltype(auto) backend_selector() const
Return the source storage's backend selector.
Definition reshape.hpp:321
auto mdspan() &-> mdspec_type
Resolve the reshaped mdspan when the parent is immediately accessible.
Definition reshape.hpp:344
std::remove_reference_t< Tensor > tensor_type
Definition reshape.hpp:271
Exact arithmetic or an explicit binary working precision.
Definition core/precision.hpp:13
Tensor-level descriptor owning a reshaped mdspan and backend selector.
Definition reshape.hpp:203
BackendSelector backend_selector_type
Definition reshape.hpp:207
typename mdspan_type::value_type value_type
Definition reshape.hpp:210
typename mdspan_type::mapping_type mapping_type
Definition reshape.hpp:214
void async_alias_tag
Definition reshape.hpp:208
typename mdspan_type::element_type element_type
Definition reshape.hpp:209
stdex::mdspan< const_element_type, extents_type, layout_type, const_accessor_type > const_mdspan_type
Definition reshape.hpp:217
constexpr auto backend_selector() const -> backend_selector_type
Return the source storage's backend selector.
Definition reshape.hpp:225
const_accessor_t< typename mdspan_type::accessor_type > const_accessor_type
Definition reshape.hpp:215
constexpr ReshapedTensor(mdspan_type span, backend_selector_type selector)
Construct from a reshaped mdspan and source backend selector.
Definition reshape.hpp:220
typename mdspan_type::layout_type layout_type
Definition reshape.hpp:213
constexpr decltype(auto) operator[](Index... indices)
Evaluate or assign one reshaped element according to accessor mutability.
Definition reshape.hpp:245
constexpr auto mdspan() const &-> const_mdspan_type
Resolve the stored reshaped mdspan descriptor for read-only access.
Definition reshape.hpp:231
std::add_const_t< std::remove_const_t< element_type > > const_element_type
Definition reshape.hpp:216
typename mdspan_type::extents_type extents_type
Definition reshape.hpp:211
StoragePolicy storage_policy
Definition reshape.hpp:206
Mdspan mdspan_type
Definition reshape.hpp:205
constexpr auto mdspan() &-> mdspan_type
Resolve the stored reshaped mdspan descriptor for mutable access.
Definition reshape.hpp:228
typename mdspan_type::index_type index_type
Definition reshape.hpp:212
constexpr auto extents() const noexcept -> extents_type const &
Return the reshaped extents.
Definition reshape.hpp:237
constexpr auto extent(std::size_t axis) const noexcept -> index_type
Return one reshaped extent.
Definition reshape.hpp:240
General-purpose owning tensor with immediate or deferred mdspan metadata.
Definition basic_tensor.hpp:109
Store a data descriptor with the mapping and accessor for an eventual mdspan.
Definition mdspec.hpp:31
constexpr index_type extent(rank_type axis) const noexcept
Return the runtime extent of one axis.
Definition mdspec.hpp:93
constexpr auto extents() const noexcept -> extents_type const &
Return the stored extents.
Definition mdspec.hpp:89
A readable type implementing the mdspan observers and multidimensional subscript contract.
Definition mdspan/concepts.hpp:291
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
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 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
Mdspan concept and accessor extensions for Uni20.
Configured gateway to Uni20's mdspan implementation.
Mdspan-shaped metadata for storage whose data handle requires acquisition.
Definition async/async.hpp:26
typename detail::TensorStoragePolicy< std::remove_cvref_t< Tensor > >::type tensor_storage_policy_t
Storage-policy type exposed by a tensor-level object, or void.
Definition tensor/concepts.hpp:40
void reshape_inplace(async::Async< Tensor > &input, Extents... requested_extents)
Schedule an in-place mapping change on an async owning Tensor.
Definition tensor/async.hpp:189
auto reshape_view_right(Span &&source, Extents... requested_extents)
Return a no-copy row-major reshape of a compatible strided mdspan.
Definition reshape.hpp:194
constexpr bool has_runtime_precision_v
Whether numerical values of this scalar family carry runtime precision.
Definition runtime_precision.hpp:10
auto reshape_view_left(Span &&source, Extents... requested_extents)
Return a no-copy column-major reshape of a compatible strided mdspan.
Definition reshape.hpp:185
auto reshape_view(Span &&source, Extents... requested_extents)
Return a no-copy mdspan reshape preserving a canonical source layout.
Definition reshape.hpp:175
typename tensor_mdspec_t< T >::extents_type tensor_extents_t
Extents type exposed by a tensor-level object.
Definition tensor/concepts.hpp:129
constexpr decltype(auto) mdspec_of(Tensor &tensor) noexcept(noexcept(tensor.mdspec()))
Return a tensor's immediate or descriptor-backed multidimensional metadata.
Definition tensor/concepts.hpp:50
std::remove_cv_t< typename tensor_mdspec_t< T >::element_type > tensor_element_t
Scalar value type exposed by a tensor-level object.
Definition tensor/concepts.hpp:126
std::ptrdiff_t index_type
Definition types.hpp:19
auto reshape(async::Async< InputTensor > const &input, Extents... requested_extents)
Schedule a preserving owning reshape of an async Tensor.
Definition tensor/async.hpp:156
Tensor(InputTensor const &) -> Tensor< tensor_element_t< InputTensor >, tensor_mdspec_t< InputTensor >::rank(), HostStorage, detail::materialized_layout_t< void, tensor_mdspec_t< InputTensor > >, DefaultAccessorFactory >
Deduce a runtime-extents host tensor that materializes a tensor view.
std::remove_cvref_t< detail::tensor_const_mdspan_t< T > > immediate_tensor_mdspan_t
Resolved readable mdspan type exposed by a tensor-level object.
Definition tensor/concepts.hpp:120
std::remove_cvref_t< detail::normalized_const_mdspec_t< T > > tensor_mdspec_t
Normalized readable MdspecLike type exposed by a tensor-level object.
Definition tensor/concepts.hpp:123
std::size_t span
Definition presentation.cpp:2017
Checked helpers for constructing runtime tensor extents.
Concepts for tensor-level objects that resolve mdspan kernel operands.
#define CHECK(cond,...)
Definition trace.hpp:299
#define ERROR_IF(cond,...)
Definition trace.hpp:389