Uni20
Asynchronous tensor and runtime library.
Loading...
Searching...
No Matches
async/svd.hpp
Go to the documentation of this file.
1#pragma once
2
13#include <uni20/async/async.hpp>
16
17#include <type_traits>
18#include <utility>
19
20namespace uni20::linalg
21{
22namespace detail
23{
24template <class MatrixTensor>
25using preserving_singular_values_result_t =
26 std::remove_cvref_t<decltype(uni20::linalg::singular_values(std::declval<MatrixTensor const&>()))>;
27
28template <class MatrixTensor>
29using consuming_singular_values_result_t =
30 std::remove_cvref_t<decltype(uni20::linalg::singular_values(std::declval<MatrixTensor&&>()))>;
31
32template <class MatrixTensor>
33using preserving_svd_left_result_t = std::remove_cvref_t<decltype(uni20::linalg::svd_left(
34 std::declval<MatrixTensor const&>(), SvdVectorExtent::Reduced))>;
35
36template <class MatrixTensor>
37using consuming_svd_left_result_t =
38 std::remove_cvref_t<decltype(uni20::linalg::svd_left(std::declval<MatrixTensor&&>(), SvdVectorExtent::Reduced))>;
39
40template <class MatrixTensor>
41using preserving_svd_right_result_t = std::remove_cvref_t<decltype(uni20::linalg::svd_right(
42 std::declval<MatrixTensor const&>(), SvdVectorExtent::Reduced))>;
43
44template <class MatrixTensor>
45using consuming_svd_right_result_t =
46 std::remove_cvref_t<decltype(uni20::linalg::svd_right(std::declval<MatrixTensor&&>(), SvdVectorExtent::Reduced))>;
47
48template <class MatrixTensor>
49using preserving_svd_result_t =
50 std::remove_cvref_t<decltype(uni20::linalg::svd(std::declval<MatrixTensor const&>(), SvdOptions{}))>;
51
52template <class MatrixTensor>
53using consuming_svd_result_t =
54 std::remove_cvref_t<decltype(uni20::linalg::svd(std::declval<MatrixTensor&&>(), SvdOptions{}))>;
55
56template <class Result>
57using async_svd_left_result_t = SvdLeftResult<async::Async<typename Result::left_singular_vector_tensor_type>,
59
60template <class Result>
61using async_svd_right_result_t =
62 SvdRightResult<async::Async<typename Result::singular_value_tensor_type>,
64
65template <class Result>
66using async_svd_result_t = SvdResult<async::Async<typename Result::left_singular_vector_tensor_type>,
69
70template <class Result, class MatrixTensor>
71[[nodiscard]] constexpr auto select_async_consuming_singular_values_backend()
72{
73 if constexpr (can_transfer_svd_storage<MatrixTensor>())
74 {
75 return select_backend_for<Result, std::remove_cvref_t<MatrixTensor>>(singular_values_op{});
76 }
77 else
78 {
79 using work_type = svd_matrix_tensor_t<MatrixTensor>;
80 return select_singular_values_backend<work_type>();
81 }
82}
83
84template <class Result, class MatrixTensor>
85[[nodiscard]] constexpr auto select_async_consuming_svd_left_backend(SvdVectorExtent extent)
86{
87 if constexpr (can_transfer_svd_storage<MatrixTensor>())
88 {
89 return select_backend_for<typename Result::singular_value_tensor_type,
90 typename Result::left_singular_vector_tensor_type, std::remove_cvref_t<MatrixTensor>>(
91 svd_left_op{.left = extent});
92 }
93 else
94 {
95 using work_type = svd_matrix_tensor_t<MatrixTensor>;
96 return select_svd_left_backend<work_type>(extent);
97 }
98}
99
100template <class Result, class MatrixTensor>
101[[nodiscard]] constexpr auto select_async_consuming_svd_right_backend(SvdVectorExtent extent)
102{
103 if constexpr (can_transfer_svd_storage<MatrixTensor>())
104 {
105 return select_backend_for<typename Result::singular_value_tensor_type,
106 typename Result::right_singular_vector_adjoint_tensor_type,
107 std::remove_cvref_t<MatrixTensor>>(svd_right_op{.right = extent});
108 }
109 else
110 {
111 using work_type = svd_matrix_tensor_t<MatrixTensor>;
112 return select_svd_right_backend<work_type>(extent);
113 }
114}
115
116template <class Result, class MatrixTensor>
117[[nodiscard]] constexpr auto select_async_consuming_svd_backend(SvdOptions options)
118{
119 if constexpr (can_transfer_svd_storage<MatrixTensor>())
120 {
121 return select_backend_for<
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});
125 }
126 else
127 {
128 using work_type = svd_matrix_tensor_t<MatrixTensor>;
129 return select_svd_backend<work_type>(options);
130 }
131}
132
133template <KernelBackendSelector BackendSelector, class SingularValueTensor, uni20::RankedTensorView<2> MatrixTensor>
135co_preserving_singular_values(BackendSelector const selector, async::WriteBuffer<SingularValueTensor> singular_values,
136 async::ReadBuffer<MatrixTensor> matrix, std::optional<Precision> requested = {})
137{
138 auto singular_value_storage_awaiter = singular_values.storage();
139 auto& singular_value_storage = co_await singular_value_storage_awaiter;
140 auto const& matrix_value = co_await matrix;
141 singular_value_storage.emplace(uni20::linalg::singular_values(selector, matrix_value, requested));
142 co_return;
143}
144
145template <KernelBackendSelector BackendSelector, class SingularValueTensor,
149co_consuming_singular_values(BackendSelector const selector, async::WriteBuffer<SingularValueTensor> singular_values,
150 async::WriteBuffer<MatrixTensor> matrix, std::optional<Precision> requested = {})
151{
152 auto singular_value_storage_awaiter = singular_values.storage();
153 auto& singular_value_storage = co_await singular_value_storage_awaiter;
154 auto matrix_value = co_await matrix.take();
155 singular_value_storage.emplace(uni20::linalg::singular_values(selector, std::move(matrix_value), requested));
156 co_return;
157}
158
159template <KernelBackendSelector BackendSelector, class LeftTensor, class SingularValueTensor,
160 uni20::RankedTensorView<2> MatrixTensor>
162co_preserving_svd_left(BackendSelector const selector, async::WriteBuffer<LeftTensor> left_singular_vectors,
164 SvdVectorExtent const extent, std::optional<Precision> requested = {})
165{
166 auto left_storage_awaiter = left_singular_vectors.storage();
167 auto singular_value_storage_awaiter = singular_values.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;
171
172 auto result = uni20::linalg::svd_left(selector, matrix_value, extent, requested);
173 left_storage.emplace(std::move(result.left_singular_vectors));
174 singular_value_storage.emplace(std::move(result.singular_values));
175 co_return;
176}
177
178template <KernelBackendSelector BackendSelector, class LeftTensor, class SingularValueTensor,
182co_consuming_svd_left(BackendSelector const selector, async::WriteBuffer<LeftTensor> left_singular_vectors,
184 SvdVectorExtent const extent, std::optional<Precision> requested = {})
185{
186 auto left_storage_awaiter = left_singular_vectors.storage();
187 auto singular_value_storage_awaiter = singular_values.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();
191
192 auto result = uni20::linalg::svd_left(selector, std::move(matrix_value), extent, requested);
193 left_storage.emplace(std::move(result.left_singular_vectors));
194 singular_value_storage.emplace(std::move(result.singular_values));
195 co_return;
196}
197
198template <KernelBackendSelector BackendSelector, class SingularValueTensor, class RightAdjointTensor,
199 uni20::RankedTensorView<2> MatrixTensor>
200async::AsyncTask co_preserving_svd_right(BackendSelector const selector,
202 async::WriteBuffer<RightAdjointTensor> right_singular_vectors_adjoint,
204 std::optional<Precision> requested = {})
205{
206 auto singular_value_storage_awaiter = singular_values.storage();
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;
211
212 auto result = uni20::linalg::svd_right(selector, matrix_value, extent, requested);
213 singular_value_storage.emplace(std::move(result.singular_values));
214 right_storage.emplace(std::move(result.right_singular_vectors_adjoint));
215 co_return;
216}
217
218template <KernelBackendSelector BackendSelector, class SingularValueTensor, class RightAdjointTensor,
221async::AsyncTask co_consuming_svd_right(BackendSelector const selector,
223 async::WriteBuffer<RightAdjointTensor> right_singular_vectors_adjoint,
225 std::optional<Precision> requested = {})
226{
227 auto singular_value_storage_awaiter = singular_values.storage();
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();
232
233 auto result = uni20::linalg::svd_right(selector, std::move(matrix_value), extent, requested);
234 singular_value_storage.emplace(std::move(result.singular_values));
235 right_storage.emplace(std::move(result.right_singular_vectors_adjoint));
236 co_return;
237}
238
239template <KernelBackendSelector BackendSelector, class LeftTensor, class SingularValueTensor, class RightAdjointTensor,
240 uni20::RankedTensorView<2> MatrixTensor>
241async::AsyncTask co_preserving_svd(BackendSelector const selector, async::WriteBuffer<LeftTensor> left_singular_vectors,
243 async::WriteBuffer<RightAdjointTensor> right_singular_vectors_adjoint,
244 async::ReadBuffer<MatrixTensor> matrix, SvdOptions const options,
245 std::optional<Precision> requested = {})
246{
247 auto left_storage_awaiter = left_singular_vectors.storage();
248 auto singular_value_storage_awaiter = singular_values.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;
254
255 auto result = uni20::linalg::svd(selector, matrix_value, options, requested);
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));
259 co_return;
260}
261
262template <KernelBackendSelector BackendSelector, class LeftTensor, class SingularValueTensor, class RightAdjointTensor,
265async::AsyncTask co_consuming_svd(BackendSelector const selector, async::WriteBuffer<LeftTensor> left_singular_vectors,
267 async::WriteBuffer<RightAdjointTensor> right_singular_vectors_adjoint,
268 async::WriteBuffer<MatrixTensor> matrix, SvdOptions const options,
269 std::optional<Precision> requested = {})
270{
271 auto left_storage_awaiter = left_singular_vectors.storage();
272 auto singular_value_storage_awaiter = singular_values.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;
277 // Retain the consumed writer gate until every output commits, so a failure
278 // reaches the input and all independent result epochs.
279 auto matrix_value = co_await matrix.take();
280
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));
285 co_return;
286}
287
288template <KernelBackendSelector BackendSelector, uni20::RankedTensorView<2> MatrixTensor>
289[[nodiscard]] auto schedule_preserving_singular_values(BackendSelector selector,
290 async::Async<MatrixTensor> const& matrix,
291 std::optional<Precision> requested = {})
292{
294 output.debug_name("singular_values.values");
295 auto task = co_preserving_singular_values(std::move(selector), output.write(), matrix.read(), requested);
296 task.debug_name("singular_values");
297 async::schedule(std::move(task));
298 return output;
299}
300
301template <KernelBackendSelector BackendSelector, uni20::MutableRankedTensorView<2> MatrixTensor>
303[[nodiscard]] auto schedule_consuming_singular_values(BackendSelector selector, async::Async<MatrixTensor>& matrix,
304 std::optional<Precision> requested = {})
305{
307 output.debug_name("singular_values.values");
308 auto task = co_consuming_singular_values(std::move(selector), output.write(), matrix.write(), requested);
309 task.debug_name("singular_values");
310 async::schedule(std::move(task));
311 return output;
312}
313
314template <KernelBackendSelector BackendSelector, uni20::RankedTensorView<2> MatrixTensor>
315[[nodiscard]] auto schedule_preserving_svd_left(BackendSelector selector, async::Async<MatrixTensor> const& matrix,
316 SvdVectorExtent extent, std::optional<Precision> requested = {})
317{
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");
325 async::schedule(std::move(task));
326 return outputs;
327}
328
329template <KernelBackendSelector BackendSelector, uni20::MutableRankedTensorView<2> MatrixTensor>
331[[nodiscard]] auto schedule_consuming_svd_left(BackendSelector selector, async::Async<MatrixTensor>& matrix,
332 SvdVectorExtent extent, std::optional<Precision> requested = {})
333{
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");
341 async::schedule(std::move(task));
342 return outputs;
343}
344
345template <KernelBackendSelector BackendSelector, uni20::RankedTensorView<2> MatrixTensor>
346[[nodiscard]] auto schedule_preserving_svd_right(BackendSelector selector, async::Async<MatrixTensor> const& matrix,
347 SvdVectorExtent extent, std::optional<Precision> requested = {})
348{
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");
356 async::schedule(std::move(task));
357 return outputs;
358}
359
360template <KernelBackendSelector BackendSelector, uni20::MutableRankedTensorView<2> MatrixTensor>
362[[nodiscard]] auto schedule_consuming_svd_right(BackendSelector selector, async::Async<MatrixTensor>& matrix,
363 SvdVectorExtent extent, std::optional<Precision> requested = {})
364{
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");
372 async::schedule(std::move(task));
373 return outputs;
374}
375
376template <KernelBackendSelector BackendSelector, uni20::RankedTensorView<2> MatrixTensor>
377[[nodiscard]] auto schedule_preserving_svd(BackendSelector selector, async::Async<MatrixTensor> const& matrix,
378 SvdOptions options, std::optional<Precision> requested = {})
379{
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");
385
386 auto task =
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");
390 async::schedule(std::move(task));
391 return outputs;
392}
393
394template <KernelBackendSelector BackendSelector, uni20::MutableRankedTensorView<2> MatrixTensor>
396[[nodiscard]] auto schedule_consuming_svd(BackendSelector selector, async::Async<MatrixTensor>& matrix,
397 SvdOptions options, std::optional<Precision> requested = {})
398{
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");
404
405 auto task =
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");
409 async::schedule(std::move(task));
410 return outputs;
411}
412} // namespace detail
413
415template <KernelBackendSelector BackendSelector, uni20::RankedTensorView<2> MatrixTensor>
416[[nodiscard]] auto singular_values(BackendSelector selector, async::Async<MatrixTensor> const& matrix,
417 std::optional<Precision> requested = {})
418{
419 return detail::schedule_preserving_singular_values(std::move(selector), matrix, requested);
420}
421
423template <uni20::RankedTensorView<2> MatrixTensor>
424[[nodiscard]] auto singular_values(async::Async<MatrixTensor> const& matrix, std::optional<Precision> requested = {})
425{
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);
429}
430
432template <KernelBackendSelector BackendSelector, class MatrixTensor>
434[[nodiscard]] auto singular_values(BackendSelector selector, async::Async<MatrixTensor>&& matrix,
435 std::optional<Precision> requested = {})
436{
437 return detail::schedule_consuming_singular_values(std::move(selector), matrix, requested);
438}
439
441template <class MatrixTensor>
443[[nodiscard]] auto singular_values(async::Async<MatrixTensor>&& matrix, std::optional<Precision> requested = {})
444{
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);
448}
449
451template <KernelBackendSelector BackendSelector, uni20::RankedTensorView<2> MatrixTensor>
452[[nodiscard]] auto svd_left(BackendSelector selector, async::Async<MatrixTensor> const& matrix,
453 SvdVectorExtent extent = SvdVectorExtent::Reduced, std::optional<Precision> requested = {})
454{
455 return detail::schedule_preserving_svd_left(std::move(selector), matrix, extent, requested);
456}
457
459template <uni20::RankedTensorView<2> MatrixTensor>
461 std::optional<Precision> requested = {})
462{
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);
466}
467
469template <KernelBackendSelector BackendSelector, class MatrixTensor>
471[[nodiscard]] auto svd_left(BackendSelector selector, async::Async<MatrixTensor>&& matrix,
472 SvdVectorExtent extent = SvdVectorExtent::Reduced, std::optional<Precision> requested = {})
473{
474 return detail::schedule_consuming_svd_left(std::move(selector), matrix, extent, requested);
475}
476
478template <class MatrixTensor>
481 std::optional<Precision> requested = {})
482{
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);
486}
487
489template <KernelBackendSelector BackendSelector, uni20::RankedTensorView<2> MatrixTensor>
490[[nodiscard]] auto svd_right(BackendSelector selector, async::Async<MatrixTensor> const& matrix,
491 SvdVectorExtent extent = SvdVectorExtent::Reduced, std::optional<Precision> requested = {})
492{
493 return detail::schedule_preserving_svd_right(std::move(selector), matrix, extent, requested);
494}
495
497template <uni20::RankedTensorView<2> MatrixTensor>
498[[nodiscard]] auto svd_right(async::Async<MatrixTensor> const& matrix,
499 SvdVectorExtent extent = SvdVectorExtent::Reduced, std::optional<Precision> requested = {})
500{
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);
504}
505
507template <KernelBackendSelector BackendSelector, class MatrixTensor>
509[[nodiscard]] auto svd_right(BackendSelector selector, async::Async<MatrixTensor>&& matrix,
510 SvdVectorExtent extent = SvdVectorExtent::Reduced, std::optional<Precision> requested = {})
511{
512 return detail::schedule_consuming_svd_right(std::move(selector), matrix, extent, requested);
513}
514
516template <class MatrixTensor>
519 std::optional<Precision> requested = {})
520{
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);
524}
525
530template <KernelBackendSelector BackendSelector, uni20::RankedTensorView<2> MatrixTensor>
531[[nodiscard]] auto svd(BackendSelector selector, async::Async<MatrixTensor> const& matrix, SvdOptions options = {},
532 std::optional<Precision> requested = {})
533{
534 return detail::schedule_preserving_svd(std::move(selector), matrix, options, requested);
535}
536
540template <uni20::RankedTensorView<2> MatrixTensor>
541[[nodiscard]] auto svd(async::Async<MatrixTensor> const& matrix, SvdOptions options = {},
542 std::optional<Precision> requested = {})
543{
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);
547}
548
550template <KernelBackendSelector BackendSelector, class MatrixTensor>
552[[nodiscard]] auto svd(BackendSelector selector, async::Async<MatrixTensor>&& matrix, SvdOptions options = {},
553 std::optional<Precision> requested = {})
554{
555 return detail::schedule_consuming_svd(std::move(selector), matrix, options, requested);
556}
557
562template <class MatrixTensor>
564[[nodiscard]] auto svd(async::Async<MatrixTensor>&& matrix, SvdOptions options = {},
565 std::optional<Precision> requested = {})
566{
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);
570}
571
573template <RankedTensorView<2> Matrix>
574[[nodiscard]] auto svd(async::Async<Matrix> const& matrix, Precision p, SvdOptions options = {})
575{
576 return uni20::linalg::svd(matrix, options, std::optional<Precision>{p});
577}
578
580template <RankedTensorView<2> Matrix>
581[[nodiscard]] auto svd(async::Async<Matrix>&& matrix, Precision p, SvdOptions options = {})
582{
583 return uni20::linalg::svd(std::move(matrix), options, std::optional<Precision>{p});
584}
585
587template <KernelBackendSelector Selector, RankedTensorView<2> Matrix>
588[[nodiscard]] auto svd(Selector&& selector, async::Async<Matrix> const& matrix, Precision p, SvdOptions options = {})
589{
590 return uni20::linalg::svd(std::forward<Selector>(selector), matrix, options, std::optional<Precision>{p});
591}
592
594template <KernelBackendSelector Selector, RankedTensorView<2> Matrix>
595[[nodiscard]] auto svd(Selector&& selector, async::Async<Matrix>&& matrix, Precision p, SvdOptions options = {})
596{
597 return uni20::linalg::svd(std::forward<Selector>(selector), std::move(matrix), options, std::optional<Precision>{p});
598}
599
601template <RankedTensorView<2> Matrix>
602[[nodiscard]] auto svd_left(async::Async<Matrix> const& matrix, Precision p,
604{
605 return uni20::linalg::svd_left(matrix, extent, std::optional<Precision>{p});
606}
607
609template <RankedTensorView<2> Matrix>
610[[nodiscard]] auto svd_left(async::Async<Matrix>&& matrix, Precision p,
612{
613 return uni20::linalg::svd_left(std::move(matrix), extent, std::optional<Precision>{p});
614}
615
617template <KernelBackendSelector Selector, RankedTensorView<2> Matrix>
618[[nodiscard]] auto svd_left(Selector&& selector, async::Async<Matrix> const& matrix, Precision p,
620{
621 return uni20::linalg::svd_left(std::forward<Selector>(selector), matrix, extent, std::optional<Precision>{p});
622}
623
625template <KernelBackendSelector Selector, RankedTensorView<2> Matrix>
626[[nodiscard]] auto svd_left(Selector&& selector, async::Async<Matrix>&& matrix, Precision p,
628{
629 return uni20::linalg::svd_left(std::forward<Selector>(selector), std::move(matrix), extent,
630 std::optional<Precision>{p});
631}
632
634template <RankedTensorView<2> Matrix>
635[[nodiscard]] auto svd_right(async::Async<Matrix> const& matrix, Precision p,
637{
638 return uni20::linalg::svd_right(matrix, extent, std::optional<Precision>{p});
639}
640
642template <RankedTensorView<2> Matrix>
643[[nodiscard]] auto svd_right(async::Async<Matrix>&& matrix, Precision p,
645{
646 return uni20::linalg::svd_right(std::move(matrix), extent, std::optional<Precision>{p});
647}
648
650template <KernelBackendSelector Selector, RankedTensorView<2> Matrix>
651[[nodiscard]] auto svd_right(Selector&& selector, async::Async<Matrix> const& matrix, Precision p,
653{
654 return uni20::linalg::svd_right(std::forward<Selector>(selector), matrix, extent, std::optional<Precision>{p});
655}
656
658template <KernelBackendSelector Selector, RankedTensorView<2> Matrix>
659[[nodiscard]] auto svd_right(Selector&& selector, async::Async<Matrix>&& matrix, Precision p,
661{
662 return uni20::linalg::svd_right(std::forward<Selector>(selector), std::move(matrix), extent,
663 std::optional<Precision>{p});
664}
665
666} // namespace uni20::linalg
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