24template <
class MatrixTensor>
25using preserving_singular_values_result_t =
26 std::remove_cvref_t<decltype(uni20::linalg::singular_values(std::declval<MatrixTensor const&>()))>;
28template <
class MatrixTensor>
29using consuming_singular_values_result_t =
30 std::remove_cvref_t<decltype(uni20::linalg::singular_values(std::declval<MatrixTensor&&>()))>;
32template <
class MatrixTensor>
36template <
class MatrixTensor>
37using consuming_svd_left_result_t =
40template <
class MatrixTensor>
44template <
class MatrixTensor>
45using consuming_svd_right_result_t =
48template <
class MatrixTensor>
49using preserving_svd_result_t =
50 std::remove_cvref_t<decltype(uni20::linalg::svd(std::declval<MatrixTensor const&>(), SvdOptions{}))>;
52template <
class MatrixTensor>
53using consuming_svd_result_t =
54 std::remove_cvref_t<decltype(uni20::linalg::svd(std::declval<MatrixTensor&&>(), SvdOptions{}))>;
56template <
class Result>
57using async_svd_left_result_t = SvdLeftResult<async::Async<typename Result::left_singular_vector_tensor_type>,
60template <
class Result>
61using async_svd_right_result_t =
62 SvdRightResult<async::Async<typename Result::singular_value_tensor_type>,
65template <
class Result>
66using async_svd_result_t = SvdResult<async::Async<typename Result::left_singular_vector_tensor_type>,
70template <
class Result,
class MatrixTensor>
71[[nodiscard]]
constexpr auto select_async_consuming_singular_values_backend()
73 if constexpr (can_transfer_svd_storage<MatrixTensor>())
75 return select_backend_for<Result, std::remove_cvref_t<MatrixTensor>>(singular_values_op{});
79 using work_type = svd_matrix_tensor_t<MatrixTensor>;
80 return select_singular_values_backend<work_type>();
84template <
class Result,
class MatrixTensor>
85[[nodiscard]]
constexpr auto select_async_consuming_svd_left_backend(
SvdVectorExtent extent)
87 if constexpr (can_transfer_svd_storage<MatrixTensor>())
90 typename Result::left_singular_vector_tensor_type, std::remove_cvref_t<MatrixTensor>>(
91 svd_left_op{.left = extent});
95 using work_type = svd_matrix_tensor_t<MatrixTensor>;
96 return select_svd_left_backend<work_type>(extent);
100template <
class Result,
class MatrixTensor>
101[[nodiscard]]
constexpr auto select_async_consuming_svd_right_backend(
SvdVectorExtent extent)
103 if constexpr (can_transfer_svd_storage<MatrixTensor>())
106 typename Result::right_singular_vector_adjoint_tensor_type,
107 std::remove_cvref_t<MatrixTensor>>(svd_right_op{.right = extent});
111 using work_type = svd_matrix_tensor_t<MatrixTensor>;
112 return select_svd_right_backend<work_type>(extent);
116template <
class Result,
class MatrixTensor>
117[[nodiscard]]
constexpr auto select_async_consuming_svd_backend(SvdOptions options)
119 if constexpr (can_transfer_svd_storage<MatrixTensor>())
122 typename Result::singular_value_tensor_type,
typename Result::left_singular_vector_tensor_type,
123 typename Result::right_singular_vector_adjoint_tensor_type, std::remove_cvref_t<MatrixTensor>>(
124 svd_op{.left = options.left, .right = options.right});
128 using work_type = svd_matrix_tensor_t<MatrixTensor>;
129 return select_svd_backend<work_type>(options);
133template <KernelBackendSelector BackendSelector,
class SingularValueTensor, uni20::RankedTensorView<2> MatrixTensor>
139 auto& singular_value_storage =
co_await singular_value_storage_awaiter;
140 auto const& matrix_value =
co_await matrix;
145template <KernelBackendSelector BackendSelector,
class SingularValueTensor,
153 auto& singular_value_storage =
co_await singular_value_storage_awaiter;
154 auto matrix_value =
co_await matrix.
take();
159template <KernelBackendSelector BackendSelector,
class LeftTensor,
class SingularValueTensor,
166 auto left_storage_awaiter = left_singular_vectors.
storage();
168 auto& left_storage =
co_await left_storage_awaiter;
169 auto& singular_value_storage =
co_await singular_value_storage_awaiter;
170 auto const& matrix_value =
co_await matrix;
173 left_storage.emplace(std::move(result.left_singular_vectors));
174 singular_value_storage.emplace(std::move(result.singular_values));
178template <KernelBackendSelector BackendSelector,
class LeftTensor,
class SingularValueTensor,
186 auto left_storage_awaiter = left_singular_vectors.
storage();
188 auto& left_storage =
co_await left_storage_awaiter;
189 auto& singular_value_storage =
co_await singular_value_storage_awaiter;
190 auto matrix_value =
co_await matrix.
take();
193 left_storage.emplace(std::move(result.left_singular_vectors));
194 singular_value_storage.emplace(std::move(result.singular_values));
198template <KernelBackendSelector BackendSelector,
class SingularValueTensor,
class RightAdjointTensor,
204 std::optional<Precision> requested = {})
207 auto right_storage_awaiter = right_singular_vectors_adjoint.
storage();
208 auto& singular_value_storage =
co_await singular_value_storage_awaiter;
209 auto& right_storage =
co_await right_storage_awaiter;
210 auto const& matrix_value =
co_await matrix;
213 singular_value_storage.emplace(std::move(result.singular_values));
214 right_storage.emplace(std::move(result.right_singular_vectors_adjoint));
218template <KernelBackendSelector BackendSelector,
class SingularValueTensor,
class RightAdjointTensor,
225 std::optional<Precision> requested = {})
228 auto right_storage_awaiter = right_singular_vectors_adjoint.
storage();
229 auto& singular_value_storage =
co_await singular_value_storage_awaiter;
230 auto& right_storage =
co_await right_storage_awaiter;
231 auto matrix_value =
co_await matrix.
take();
234 singular_value_storage.emplace(std::move(result.singular_values));
235 right_storage.emplace(std::move(result.right_singular_vectors_adjoint));
239template <KernelBackendSelector BackendSelector,
class LeftTensor,
class SingularValueTensor,
class RightAdjointTensor,
245 std::optional<Precision> requested = {})
247 auto left_storage_awaiter = left_singular_vectors.
storage();
249 auto right_storage_awaiter = right_singular_vectors_adjoint.
storage();
250 auto& left_storage =
co_await left_storage_awaiter;
251 auto& singular_value_storage =
co_await singular_value_storage_awaiter;
252 auto& right_storage =
co_await right_storage_awaiter;
253 auto const& matrix_value =
co_await matrix;
256 left_storage.emplace(std::move(result.left_singular_vectors));
257 singular_value_storage.emplace(std::move(result.singular_values));
258 right_storage.emplace(std::move(result.right_singular_vectors_adjoint));
262template <KernelBackendSelector BackendSelector,
class LeftTensor,
class SingularValueTensor,
class RightAdjointTensor,
269 std::optional<Precision> requested = {})
271 auto left_storage_awaiter = left_singular_vectors.
storage();
273 auto right_storage_awaiter = right_singular_vectors_adjoint.
storage();
274 auto& left_storage =
co_await left_storage_awaiter;
275 auto& singular_value_storage =
co_await singular_value_storage_awaiter;
276 auto& right_storage =
co_await right_storage_awaiter;
279 auto matrix_value =
co_await matrix.
take();
281 auto result =
uni20::linalg::svd(selector, std::move(matrix_value), options, requested);
282 left_storage.emplace(std::move(result.left_singular_vectors));
283 singular_value_storage.emplace(std::move(result.singular_values));
284 right_storage.emplace(std::move(result.right_singular_vectors_adjoint));
288template <KernelBackendSelector BackendSelector, uni20::RankedTensorView<2> MatrixTensor>
289[[nodiscard]]
auto schedule_preserving_singular_values(BackendSelector selector,
291 std::optional<Precision> requested = {})
295 auto task = co_preserving_singular_values(std::move(selector), output.
write(), matrix.
read(), requested);
296 task.debug_name(
"singular_values");
301template <KernelBackendSelector BackendSelector, uni20::MutableRankedTensorView<2> MatrixTensor>
304 std::optional<Precision> requested = {})
308 auto task = co_consuming_singular_values(std::move(selector), output.
write(), matrix.
write(), requested);
309 task.debug_name(
"singular_values");
314template <KernelBackendSelector BackendSelector, uni20::RankedTensorView<2> MatrixTensor>
318 using result_type = preserving_svd_left_result_t<MatrixTensor>;
319 async_svd_left_result_t<result_type> outputs;
320 outputs.left_singular_vectors.debug_name(
"svd_left.left_singular_vectors");
321 outputs.singular_values.debug_name(
"svd_left.singular_values");
322 auto task = co_preserving_svd_left(std::move(selector), outputs.left_singular_vectors.write(),
323 outputs.singular_values.write(), matrix.
read(), extent, requested);
324 task.debug_name(
"svd_left");
329template <KernelBackendSelector BackendSelector, uni20::MutableRankedTensorView<2> MatrixTensor>
334 using result_type = consuming_svd_left_result_t<MatrixTensor>;
335 async_svd_left_result_t<result_type> outputs;
336 outputs.left_singular_vectors.debug_name(
"svd_left.left_singular_vectors");
337 outputs.singular_values.debug_name(
"svd_left.singular_values");
338 auto task = co_consuming_svd_left(std::move(selector), outputs.left_singular_vectors.write(),
339 outputs.singular_values.write(), matrix.
write(), extent, requested);
340 task.debug_name(
"svd_left");
345template <KernelBackendSelector BackendSelector, uni20::RankedTensorView<2> MatrixTensor>
349 using result_type = preserving_svd_right_result_t<MatrixTensor>;
350 async_svd_right_result_t<result_type> outputs;
351 outputs.singular_values.debug_name(
"svd_right.singular_values");
352 outputs.right_singular_vectors_adjoint.debug_name(
"svd_right.right_singular_vectors_adjoint");
353 auto task = co_preserving_svd_right(std::move(selector), outputs.singular_values.write(),
354 outputs.right_singular_vectors_adjoint.write(), matrix.
read(), extent, requested);
355 task.debug_name(
"svd_right");
360template <KernelBackendSelector BackendSelector, uni20::MutableRankedTensorView<2> MatrixTensor>
365 using result_type = consuming_svd_right_result_t<MatrixTensor>;
366 async_svd_right_result_t<result_type> outputs;
367 outputs.singular_values.debug_name(
"svd_right.singular_values");
368 outputs.right_singular_vectors_adjoint.debug_name(
"svd_right.right_singular_vectors_adjoint");
369 auto task = co_consuming_svd_right(std::move(selector), outputs.singular_values.write(),
370 outputs.right_singular_vectors_adjoint.write(), matrix.
write(), extent, requested);
371 task.debug_name(
"svd_right");
376template <KernelBackendSelector BackendSelector, uni20::RankedTensorView<2> MatrixTensor>
378 SvdOptions options, std::optional<Precision> requested = {})
380 using result_type = preserving_svd_result_t<MatrixTensor>;
381 async_svd_result_t<result_type> outputs;
382 outputs.left_singular_vectors.debug_name(
"svd.left_singular_vectors");
383 outputs.singular_values.debug_name(
"svd.singular_values");
384 outputs.right_singular_vectors_adjoint.debug_name(
"svd.right_singular_vectors_adjoint");
387 co_preserving_svd(std::move(selector), outputs.left_singular_vectors.write(), outputs.singular_values.write(),
388 outputs.right_singular_vectors_adjoint.write(), matrix.
read(), options, requested);
389 task.debug_name(
"svd");
394template <KernelBackendSelector BackendSelector, uni20::MutableRankedTensorView<2> MatrixTensor>
397 SvdOptions options, std::optional<Precision> requested = {})
399 using result_type = consuming_svd_result_t<MatrixTensor>;
400 async_svd_result_t<result_type> outputs;
401 outputs.left_singular_vectors.debug_name(
"svd.left_singular_vectors");
402 outputs.singular_values.debug_name(
"svd.singular_values");
403 outputs.right_singular_vectors_adjoint.debug_name(
"svd.right_singular_vectors_adjoint");
406 co_consuming_svd(std::move(selector), outputs.left_singular_vectors.write(), outputs.singular_values.write(),
407 outputs.right_singular_vectors_adjoint.write(), matrix.
write(), options, requested);
408 task.debug_name(
"svd");
415template <KernelBackendSelector BackendSelector, uni20::RankedTensorView<2> MatrixTensor>
417 std::optional<Precision> requested = {})
419 return detail::schedule_preserving_singular_values(std::move(selector), matrix, requested);
423template <uni20::RankedTensorView<2> MatrixTensor>
426 using work_type = detail::svd_matrix_tensor_t<MatrixTensor>;
427 auto selector = detail::select_singular_values_backend<work_type>();
428 return detail::schedule_preserving_singular_values(std::move(selector), matrix, requested);
432template <KernelBackendSelector BackendSelector,
class MatrixTensor>
435 std::optional<Precision> requested = {})
437 return detail::schedule_consuming_singular_values(std::move(selector), matrix, requested);
441template <
class MatrixTensor>
445 using result_type = detail::consuming_singular_values_result_t<MatrixTensor>;
446 auto selector = detail::select_async_consuming_singular_values_backend<result_type, MatrixTensor>();
447 return detail::schedule_consuming_singular_values(std::move(selector), matrix, requested);
451template <KernelBackendSelector BackendSelector, uni20::RankedTensorView<2> MatrixTensor>
455 return detail::schedule_preserving_svd_left(std::move(selector), matrix, extent, requested);
459template <uni20::RankedTensorView<2> MatrixTensor>
461 std::optional<Precision> requested = {})
463 using work_type = detail::svd_matrix_tensor_t<MatrixTensor>;
464 auto selector = detail::select_svd_left_backend<work_type>(extent);
465 return detail::schedule_preserving_svd_left(std::move(selector), matrix, extent, requested);
469template <KernelBackendSelector BackendSelector,
class MatrixTensor>
474 return detail::schedule_consuming_svd_left(std::move(selector), matrix, extent, requested);
478template <
class MatrixTensor>
481 std::optional<Precision> requested = {})
483 using result_type = detail::consuming_svd_left_result_t<MatrixTensor>;
484 auto selector = detail::select_async_consuming_svd_left_backend<result_type, MatrixTensor>(extent);
485 return detail::schedule_consuming_svd_left(std::move(selector), matrix, extent, requested);
489template <KernelBackendSelector BackendSelector, uni20::RankedTensorView<2> MatrixTensor>
493 return detail::schedule_preserving_svd_right(std::move(selector), matrix, extent, requested);
497template <uni20::RankedTensorView<2> MatrixTensor>
501 using work_type = detail::svd_matrix_tensor_t<MatrixTensor>;
502 auto selector = detail::select_svd_right_backend<work_type>(extent);
503 return detail::schedule_preserving_svd_right(std::move(selector), matrix, extent, requested);
507template <KernelBackendSelector BackendSelector,
class MatrixTensor>
512 return detail::schedule_consuming_svd_right(std::move(selector), matrix, extent, requested);
516template <
class MatrixTensor>
519 std::optional<Precision> requested = {})
521 using result_type = detail::consuming_svd_right_result_t<MatrixTensor>;
522 auto selector = detail::select_async_consuming_svd_right_backend<result_type, MatrixTensor>(extent);
523 return detail::schedule_consuming_svd_right(std::move(selector), matrix, extent, requested);
530template <KernelBackendSelector BackendSelector, uni20::RankedTensorView<2> MatrixTensor>
532 std::optional<Precision> requested = {})
534 return detail::schedule_preserving_svd(std::move(selector), matrix, options, requested);
540template <uni20::RankedTensorView<2> MatrixTensor>
542 std::optional<Precision> requested = {})
544 using work_type = detail::svd_matrix_tensor_t<MatrixTensor>;
545 auto selector = detail::select_svd_backend<work_type>(options);
546 return detail::schedule_preserving_svd(std::move(selector), matrix, options, requested);
550template <KernelBackendSelector BackendSelector,
class MatrixTensor>
553 std::optional<Precision> requested = {})
555 return detail::schedule_consuming_svd(std::move(selector), matrix, options, requested);
562template <
class MatrixTensor>
565 std::optional<Precision> requested = {})
567 using result_type = detail::consuming_svd_result_t<MatrixTensor>;
568 auto selector = detail::select_async_consuming_svd_backend<result_type, MatrixTensor>(options);
569 return detail::schedule_consuming_svd(std::move(selector), matrix, options, requested);
573template <RankedTensorView<2> Matrix>
580template <RankedTensorView<2> Matrix>
587template <KernelBackendSelector Selector, RankedTensorView<2> Matrix>
590 return uni20::linalg::svd(std::forward<Selector>(selector), matrix, options, std::optional<Precision>{
p});
594template <KernelBackendSelector Selector, RankedTensorView<2> Matrix>
597 return uni20::linalg::svd(std::forward<Selector>(selector), std::move(matrix), options, std::optional<Precision>{
p});
601template <RankedTensorView<2> Matrix>
609template <RankedTensorView<2> Matrix>
617template <KernelBackendSelector Selector, RankedTensorView<2> Matrix>
625template <KernelBackendSelector Selector, RankedTensorView<2> Matrix>
630 std::optional<Precision>{
p});
634template <RankedTensorView<2> Matrix>
642template <RankedTensorView<2> Matrix>
650template <KernelBackendSelector Selector, RankedTensorView<2> Matrix>
658template <KernelBackendSelector Selector, RankedTensorView<2> Matrix>
663 std::optional<Precision>{
p});
The Async<T> container: coroutineāsafe asynchronous read/write.
Exact arithmetic or an explicit binary working precision.
Definition core/precision.hpp:13
Canonical host-oriented coroutine task type.
Definition async_task.hpp:196
Async<T> is a container for coroutine-safe asynchronous read/write.
Definition async/async.hpp:93
ReadBuffer< T > read() const
Begin an asynchronous read of the value.
Definition async/async.hpp:339
WriteBuffer< T > write()
Begin exclusive asynchronous access to the payload.
Definition async/async.hpp:346
Async & debug_name(std::string const &label)
Assign an optional debug label for task-registry graph output.
Definition async/async.hpp:212
RAII handle for reading the value from an Async container at a given epoch.
Definition buffers.hpp:53
Exclusive mutable-access buffer for one Async<T> epoch.
Definition buffers.hpp:859
auto storage() &
Awaiter yielding direct access to writer shared storage.
Definition buffers.hpp:1029
auto take() &
Awaiter that takes the stored value.
Definition buffers.hpp:994
MutableTensorView with a specified static rank.
Definition tensor/concepts.hpp:166
Tensor-level object that owns the storage described by its multidimensional view.
Definition tensor/concepts.hpp:116
TensorView whose readable mdspec has a specified static rank.
Definition tensor/concepts.hpp:149
Coroutine scheduler for AsyncTask.
void schedule(AsyncTask &&task)
Schedule a task on the currently configured global scheduler.
Definition debug_scheduler.hpp:237
Definition linalg/async.hpp:28
constexpr auto select_backend_for(Operation const &operation)
Resolve the immutable backend selector for Tensor operand types.
Definition backend_selector.hpp:201
SvdVectorExtent
Extent policy for one side of an exact singular value decomposition.
Definition operation_tags.hpp:248
auto svd_right(BackendSelector selector, async::Async< MatrixTensor > const &matrix, SvdVectorExtent extent=SvdVectorExtent::Reduced, std::optional< Precision > requested={})
Schedule preserving right singular vectors through an explicit selector.
Definition async/svd.hpp:490
auto svd(BackendSelector selector, async::Async< MatrixTensor > const &matrix, SvdOptions options={}, std::optional< Precision > requested={})
Schedule a preserving exact SVD through an explicit selector.
Definition async/svd.hpp:531
auto singular_values(BackendSelector selector, async::Async< MatrixTensor > const &matrix, std::optional< Precision > requested={})
Schedule preserving exact singular values through an explicit selector.
Definition async/svd.hpp:416
auto svd_left(BackendSelector selector, async::Async< MatrixTensor > const &matrix, SvdVectorExtent extent=SvdVectorExtent::Reduced, std::optional< Precision > requested={})
Schedule preserving left singular vectors through an explicit selector.
Definition async/svd.hpp:452
Definition data_table.cpp:8
Destructive and value-producing exact dense singular value decompositions.
Output-shape options for an exact singular value decomposition.
Definition operation_tags.hpp:255