23template <
class Extents>
25 { std::remove_cvref_t<Extents>::rank() } -> std::convertible_to<std::size_t>;
26 extents.extent(std::size_t{});
30template <TensorExtentsLike LhsExtents, TensorExtentsLike RhsExtents>
33 if constexpr (std::remove_cvref_t<LhsExtents>::rank() != std::remove_cvref_t<RhsExtents>::rank())
39 for (std::size_t axis = 0; axis < std::remove_cvref_t<LhsExtents>::rank(); ++axis)
41 if (lhs.extent(axis) != rhs.extent(axis))
return false;
49template <
class TargetExtents, TensorExtentsLike SourceExtents, std::size_t... Axis>
50[[nodiscard]] TargetExtents convert_tensor_extents_impl(SourceExtents
const& source, std::index_sequence<Axis...>)
52 for (std::size_t axis = 0; axis < TargetExtents::rank(); ++axis)
54 auto const fixed_extent = TargetExtents::static_extent(axis);
55 ERROR_IF(fixed_extent != stdex::dynamic_extent && !std::cmp_equal(source.extent(axis), fixed_extent),
56 "tensor extent does not match the destination's static extent");
58 using index_type =
typename TargetExtents::index_type;
59 return TargetExtents(
static_cast<index_type>(source.extent(Axis))...);
64template <
class TargetExtents, TensorExtentsLike SourceExtents>
67 static_assert(TargetExtents::rank() == std::remove_cvref_t<SourceExtents>::rank(),
68 "tensor output rank does not match the required shape");
69 return detail::convert_tensor_extents_impl<TargetExtents>(source, std::make_index_sequence<TargetExtents::rank()>{});
78 requires(std::remove_reference_t<T>& output, tensor_extents_t<T>
const& extents) { output.reset_shape(extents); };
83template <TensorView Output, TensorExtentsLike RequiredExtents>
87 "tensor output rank does not match the required shape");
89 "tensor output shape does not match the required extents");
103template <MutableTensorView Output, TensorExtentsLike RequiredExtents>
107 "tensor output rank does not match the required shape");
112 auto const converted = convert_tensor_extents<tensor_extents_t<Output>>(required);
113 if constexpr (
requires { output.reset_shape(
uninitialized, converted); })
116 output.reset_shape(converted);
136template <MutableTensorView Output, TensorExtentsLike RequiredExtents,
class Placement>
137 requires requires(Output& output, tensor_extents_t<Output>
const& extents, Placement
const& placement) {
138 { output.storage_is_compatible(placement) } -> std::convertible_to<bool>;
139 output.reset_shape(extents);
140 output.replace(extents, placement);
142Output&
prepare_output(Output& output, RequiredExtents
const& required, Placement
const& placement)
145 "tensor output rank does not match the required shape");
146 if (
tensor_extents_equal(output.extents(), required) && output.storage_is_compatible(placement))
return output;
148 auto const converted = convert_tensor_extents<tensor_extents_t<Output>>(required);
149 if (output.storage_is_compatible(placement))
151 if constexpr (
requires { output.reset_shape(
uninitialized, converted); })
154 output.reset_shape(converted);
158 if constexpr (
requires { output.replace(
uninitialized, converted, placement); })
161 output.replace(converted, placement);
165 CHECK(output.storage_is_compatible(placement));
180template <MutableTensorView Output, TensorExtentsLike RequiredExtents>
185 if constexpr (std::constructible_from<Output, tensor_extents_t<Output>
const&>)
187 auto const converted = convert_tensor_extents<tensor_extents_t<Output>>(required);
188 if constexpr (std::constructible_from<Output, uninitialized_t, tensor_extents_t<Output>
const&>)
191 return storage.
emplace(converted);
195 ERROR(
"unconstructed tensor output cannot be initialized from the required extents");
207template <MutableTensorView Output, TensorExtentsLike RequiredExtents,
class Placement>
208 requires std::constructible_from<Output, Placement const&, tensor_extents_t<Output>
const&> &&
209 requires(Output& output, tensor_extents_t<Output>
const& extents, Placement
const& placement) {
213 Placement
const& placement)
217 auto const converted = convert_tensor_extents<tensor_extents_t<Output>>(required);
218 if constexpr (std::constructible_from<Output, uninitialized_t, Placement const&, tensor_extents_t<Output>
const&>)
221 return storage.
emplace(placement, converted);
228template <MutableTensorView Output>
void record_output_precision(Output& output, Precision
p)
230 require_precision<tensor_element_t<Output>>(
p);
231 if constexpr (
requires { output.default_precision(
p); }) output.default_precision(
p);
240template <MutableTensorView Output, TensorExtentsLike RequiredExtents>
243 detail::record_output_precision(output,
p);
248template <MutableTensorView Output, TensorExtentsLike RequiredExtents>
249 requires(!has_runtime_precision_v<tensor_element_t<Output>> ||
250 std::constructible_from<Output, uninitialized_t, tensor_extents_t<Output>
const&, Precision>)
253 require_precision<tensor_element_t<Output>>(
p);
255 if constexpr (has_runtime_precision_v<tensor_element_t<Output>>)
257 auto const converted = convert_tensor_extents<tensor_extents_t<Output>>(required);
Exact arithmetic or an explicit binary working precision.
Definition core/precision.hpp:13
A lightweight, thread-safe, reference-counted storage for a single object.
Definition shared_storage.hpp:94
bool constructed() const noexcept
Reports whether a value is currently constructed.
Definition shared_storage.hpp:234
T & emplace(Args &&... args)
Destroy any existing value and construct a new one in place.
Definition shared_storage.hpp:270
TensorView whose writable mdspec supports eventual element assignment.
Definition tensor/concepts.hpp:133
Mutable tensor output that can replace its shape and storage.
Definition tensor/output.hpp:76
Extents-like shape accepted by tensor output preparation.
Definition tensor/output.hpp:24
Definition data_table.cpp:8
Definition async/async.hpp:26
constexpr uninitialized_t uninitialized
Explicit allocation tag for overwrite outputs and scratch space.
Definition common/initialization.hpp:22
TargetExtents convert_tensor_extents(SourceExtents const &source)
Convert tensor extents while validating the target's static extents.
Definition tensor/output.hpp:65
Output & prepare_output(Output &output, RequiredExtents const &required)
Prepare a mutable tensor output with the specified shape.
Definition tensor/output.hpp:104
void require_output(Output const &output, RequiredExtents const &required)
Require an existing tensor output to have the specified shape.
Definition tensor/output.hpp:84
typename tensor_mdspec_t< T >::extents_type tensor_extents_t
Extents type exposed by a tensor-level object.
Definition tensor/concepts.hpp:129
std::ptrdiff_t index_type
Definition types.hpp:19
constexpr bool tensor_extents_equal(LhsExtents const &lhs, RhsExtents const &rhs) noexcept
Compare two tensor extent objects by rank and per-axis extent.
Definition tensor/output.hpp:31
Reference-counted optional in-place storage used by async buffers.
Concepts for tensor-level objects that resolve mdspan kernel operands.
#define ERROR(...)
Definition trace.hpp:387
#define CHECK(cond,...)
Definition trace.hpp:299
#define ERROR_IF(cond,...)
Definition trace.hpp:389