34template <
class Output,
class... Inputs>
35concept OverwriteTransformSpans =
36 MutableMdspanLike<Output> && (MdspanLike<Inputs> && ...) &&
37 ((std::remove_cvref_t<Output>::rank() == std::remove_cvref_t<Inputs>::rank()) && ...);
39template <
class Output,
class... Inputs>
40concept UpdateTransformSpans = MutableMdspanLike<Output> && (MdspanLike<Inputs> && ...) &&
41 ((std::remove_cvref_t<Output>::rank() == std::remove_cvref_t<Inputs>::rank()) && ...);
43template <
class Output,
class... Inputs>
44concept OverwriteTransformTensors =
45 MutableTensorView<Output> && (
sizeof...(Inputs) >= 1) && (TensorView<Inputs> && ...) &&
46 ((tensor_mdspec_t<Output>::rank() == tensor_mdspec_t<Inputs>::rank()) && ...);
48template <
class Output,
class... Inputs>
49concept UpdateTransformTensors = MutableTensorView<Output> && (TensorView<Inputs> && ...) &&
50 ((tensor_mdspec_t<Output>::rank() == tensor_mdspec_t<Inputs>::rank()) && ...);
52template <
class Reference,
class... Others>
53void require_transform_extents(Reference
const& reference, Others
const&... others)
55 if constexpr (
sizeof...(Others) > 0)
57 constexpr std::size_t Rank = [] {
58 if constexpr (TensorView<Reference>)
59 return tensor_mdspec_t<Reference>::rank();
61 return std::remove_cvref_t<Reference>::rank();
63 if constexpr (Rank > 0)
65 auto require_equal = [&](
auto const& other) {
66 for (std::size_t axis = 0; axis < Rank; ++axis)
67 ERROR_IF(reference.extent(axis) != other.extent(axis),
68 "elementwise transform operands have different extents");
70 (require_equal(others), ...);
75template <
class BackendSelector,
class Operation,
class OutputMdspan,
class... InputMdspans>
76void dispatch_transform(BackendSelector&& selector, Operation operation, OutputMdspan&& output,
77 InputMdspans&&... inputs)
80 std::forward<OutputMdspan>(output), std::forward<InputMdspans>(inputs)...);
89template <
class BackendSelector,
class OutputMdspan,
class Function,
class... InputMdspans>
90 requires detail::OverwriteTransformSpans<OutputMdspan, InputMdspans...>
91void assign_transform(BackendSelector&& selector, OutputMdspan&& output, Function&& function, InputMdspans&&... inputs)
93 detail::require_transform_extents(output, inputs...);
95 auto output_descriptor = std::forward<OutputMdspan>(output);
98 [&](
auto&... input_descriptor) {
99 detail::dispatch_transform(std::forward<BackendSelector>(selector), std::move(operation), output_descriptor,
100 input_descriptor...);
109template <
class BackendSelector,
class OutputMdspan,
class Function,
class... InputMdspans>
110 requires detail::UpdateTransformSpans<OutputMdspan, InputMdspans...>
111void transform_inplace(BackendSelector&& selector, OutputMdspan&& output, Function&& function, InputMdspans&&... inputs)
113 detail::require_transform_extents(output, inputs...);
115 auto output_descriptor = std::forward<OutputMdspan>(output);
118 [&](
auto&... input_descriptor) {
119 detail::dispatch_transform(std::forward<BackendSelector>(selector), std::move(operation), output_descriptor,
120 input_descriptor...);
127template <
class BackendSelector, MutableTensorView OutputTensor,
class Function>
128void assign_transform(BackendSelector&& selector, OutputTensor&& output, Function&& function)
131 auto output_descriptor =
mdspec_of(output);
132 detail::dispatch_transform(std::forward<BackendSelector>(selector), std::move(operation), output_descriptor);
136template <MutableTensorView OutputTensor,
class Function>
141 auto output_descriptor =
mdspec_of(output);
142 detail::dispatch_transform(std::move(selector), std::move(operation), output_descriptor);
146template <
class BackendSelector,
class Output,
class Value>
147 requires(detail::OverwriteTransformSpans<Output> || MutableTensorView<Output>)
148void fill(BackendSelector&& selector, Output&& output, Value&&
value)
150 assign_transform(std::forward<BackendSelector>(selector), std::forward<Output>(output),
155template <MutableTensorView Output,
class Value>
void fill(Output&& output, Value&&
value)
165template <
class BackendSelector,
class OutputTensor,
class Function,
class FirstInputTensor,
class... RestInputTensors>
166 requires detail::OverwriteTransformTensors<OutputTensor, FirstInputTensor, RestInputTensors...>
167void assign_transform(BackendSelector&& selector, OutputTensor&& output, Function&& function,
168 FirstInputTensor
const& first_input, RestInputTensors
const&... rest_inputs)
170 detail::require_transform_extents(first_input, rest_inputs...);
173 auto output_descriptor =
mdspec_of(output);
174 auto input_descriptors = std::tuple{
mdspec_of(first_input),
mdspec_of(rest_inputs)...};
176 [&](
auto&... inputs) {
177 detail::dispatch_transform(std::forward<BackendSelector>(selector), std::move(operation), output_descriptor,
184template <
class OutputTensor,
class Function,
class FirstInputTensor,
class... RestInputTensors>
185 requires detail::OverwriteTransformTensors<OutputTensor, FirstInputTensor, RestInputTensors...>
186void assign_transform(OutputTensor&& output, Function&& function, FirstInputTensor
const& first_input,
187 RestInputTensors
const&... rest_inputs)
191 detail::require_transform_extents(first_input, rest_inputs...);
193 auto output_descriptor =
mdspec_of(output);
194 auto input_descriptors = std::tuple{
mdspec_of(first_input),
mdspec_of(rest_inputs)...};
196 [&](
auto&... inputs) {
197 detail::dispatch_transform(selector, std::move(operation), output_descriptor, inputs...);
206template <
class BackendSelector,
class OutputTensor,
class Function,
class... InputTensors>
207 requires detail::UpdateTransformTensors<OutputTensor, InputTensors...>
209 InputTensors
const&... inputs)
211 detail::require_transform_extents(output, inputs...);
213 auto output_descriptor =
mdspec_of(output);
214 auto input_descriptors = std::tuple{
mdspec_of(inputs)...};
216 [&](
auto&... input_descriptors) {
217 detail::dispatch_transform(std::forward<BackendSelector>(selector), std::move(operation), output_descriptor,
218 input_descriptors...);
224template <
class OutputTensor,
class Function,
class... InputTensors>
225 requires detail::UpdateTransformTensors<OutputTensor, InputTensors...>
226void transform_inplace(OutputTensor&& output, Function&& function, InputTensors
const&... inputs)
230 detail::require_transform_extents(output, inputs...);
231 auto output_descriptor =
mdspec_of(output);
232 auto input_descriptors = std::tuple{
mdspec_of(inputs)...};
234 [&](
auto&... input_descriptors) {
235 detail::dispatch_transform(selector, std::move(operation), output_descriptor, input_descriptors...);
RAII leases that resolve device descriptors and tensor views to mdspans.
Ordered backend selector values shared by tensor storage and linalg dispatch.
locale_t value
Definition data_table.cpp:49
Operation-tag backend dispatch over tensor-view operands.
Named backend-neutral function objects for elementwise transforms.
Mdspan concept and accessor extensions for Uni20.
constexpr auto select_backend(Operation const &operation, FirstTensor const &, RestTensors const &...)
Select the default backend list for an operation on Tensor operands.
Definition backend_selector.hpp:252
void dispatch_kernel(BackendSelector &&selector, Op op, Args &&... args)
Normalize a selector and dispatch or report that every eligible backend declined.
Definition dispatch.hpp:374
Definition async/async.hpp:26
Output & prepare_output(Output &output, RequiredExtents const &required)
Prepare a mutable tensor output with the specified shape.
Definition tensor/output.hpp:104
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
void fill(BackendSelector selector, async::Async< OutputTensor > &output, Value &&value)
Fill an existing async Tensor without reading its old values.
Definition linalg/async/transform.hpp:205
void transform_inplace(BackendSelector selector, async::Async< OutputTensor > &output, Function &&function, async::Async< InputTensors > const &... inputs)
Schedule a variadic elementwise update with an explicit backend selector.
Definition linalg/async/transform.hpp:258
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
void assign_transform(BackendSelector selector, async::Async< OutputTensor > &output, Function &&function)
Schedule a nullary overwrite of an existing async Tensor.
Definition linalg/async/transform.hpp:188
Nullary elementwise function that returns one retained value.
Definition elementwise_functions.hpp:20
Concepts for tensor-level objects that resolve mdspan kernel operands.
Shape preparation contracts for tensor operation outputs.
#define ERROR_IF(cond,...)
Definition trace.hpp:389