Uni20
Asynchronous tensor and runtime library.
Loading...
Searching...
No Matches
backends/lapack/svd.hpp
Go to the documentation of this file.
1#pragma once
2
9#include "common.hpp"
10
21
22#include <algorithm>
23#include <concepts>
24#include <cstddef>
25#include <type_traits>
26#include <utility>
27#include <vector>
28
29namespace uni20::linalg
30{
31namespace lapack_detail
32{
33template <class Operation>
34concept SvdOperation =
35 std::same_as<std::remove_cvref_t<Operation>, singular_values_op> ||
36 std::same_as<std::remove_cvref_t<Operation>, svd_left_op> ||
37 std::same_as<std::remove_cvref_t<Operation>, svd_right_op> || std::same_as<std::remove_cvref_t<Operation>, svd_op>;
38
39inline char svd_job(SvdVectorExtent extent)
40{
41 switch (extent)
42 {
44 return 'S';
46 return 'A';
47 }
48 PANIC("invalid SvdVectorExtent", std::to_underlying(extent));
49}
50
51template <class MatrixMdspan> void set_identity(MatrixMdspan&& matrix)
52{
53 using scalar_type = std::remove_cv_t<typename std::remove_cvref_t<MatrixMdspan>::element_type>;
54 for (std::size_t row = 0; row < static_cast<std::size_t>(matrix.extent(0)); ++row)
55 {
56 for (std::size_t column = 0; column < static_cast<std::size_t>(matrix.extent(1)); ++column)
57 {
58 matrix[row, column] = row == column ? scalar_type{1} : scalar_type{};
59 }
60 }
61}
62
63template <class SingularValueMdspan, class MatrixMdspan> consteval bool svd_base_types_supported()
64{
65 using matrix_scalar = std::remove_cv_t<typename MatrixMdspan::element_type>;
66 using singular_value_scalar = std::remove_cv_t<typename SingularValueMdspan::element_type>;
68 std::same_as<singular_value_scalar, uni20::make_real_t<matrix_scalar>> &&
70}
71
72template <class FactorMdspan, class MatrixMdspan> consteval bool svd_factor_types_supported()
73{
74 using matrix_scalar = std::remove_cv_t<typename MatrixMdspan::element_type>;
75 using factor_scalar = std::remove_cv_t<typename FactorMdspan::element_type>;
76 return std::same_as<factor_scalar, matrix_scalar> && uni20::DefaultAccessorMdspanLike<FactorMdspan>;
77}
78
79template <uni20::LapackScalar Scalar, class MatrixHandle, class ValueHandle>
80KernelAttempt run_gesvd(char jobu, char jobvt, std::size_t rank,
83 Scalar* left, blas_int left_leading_dimension, Scalar* right, blas_int right_leading_dimension)
84{
85 using real_type = uni20::make_real_t<Scalar>;
86 Scalar work_query{};
87 if constexpr (uni20::LapackReal<Scalar>)
88 {
89 uni20::lapack::gesvd(jobu, jobvt, matrix.rows, matrix.cols, matrix.data, matrix.leading_dimension, values.data,
90 left, left_leading_dimension, right, right_leading_dimension, &work_query, -1);
91 blas_int const lwork = workspace_size(work_query);
92 std::vector<Scalar> work(static_cast<std::size_t>(lwork), Scalar{});
93 uni20::lapack::gesvd(jobu, jobvt, matrix.rows, matrix.cols, matrix.data, matrix.leading_dimension, values.data,
94 left, left_leading_dimension, right, right_leading_dimension, work.data(), lwork);
95 }
96 else
97 {
98 auto const rwork_size = try_size_product(5, rank);
99 if (!rwork_size)
100 {
102 }
103 std::vector<real_type> rwork(std::max<std::size_t>(1, *rwork_size), real_type{});
104 uni20::lapack::gesvd(jobu, jobvt, matrix.rows, matrix.cols, matrix.data, matrix.leading_dimension, values.data,
105 left, left_leading_dimension, right, right_leading_dimension, &work_query, -1, rwork.data());
106 blas_int const lwork = workspace_size(work_query);
107 std::vector<Scalar> work(static_cast<std::size_t>(lwork), Scalar{});
108 uni20::lapack::gesvd(jobu, jobvt, matrix.rows, matrix.cols, matrix.data, matrix.leading_dimension, values.data,
109 left, left_leading_dimension, right, right_leading_dimension, work.data(), lwork,
110 rwork.data());
111 }
113}
114
115template <class SingularValueMdspan, class MatrixMdspan>
116KernelAttempt try_singular_values_kernel(char jobu, char jobvt, SingularValueMdspan&& singular_values,
117 MatrixMdspan&& matrix_work)
118{
119 using matrix_scalar = std::remove_cv_t<typename std::remove_cvref_t<MatrixMdspan>::element_type>;
120 std::size_t const rows = static_cast<std::size_t>(matrix_work.extent(0));
121 std::size_t const cols = static_cast<std::size_t>(matrix_work.extent(1));
122 std::size_t const rank = std::min(rows, cols);
123 CHECK_EQUAL(static_cast<std::size_t>(singular_values.extent(0)), rank);
124 if (rank == 0)
125 {
127 }
128
129 auto matrix = uni20::linalg::blas::try_lapack_writable_matrix(matrix_work);
131 if (!matrix || !values)
132 {
134 }
135
136 blas_int const k = uni20::blas::try_blas_int(rank);
138 {
140 }
141 CHECK_EQUAL(values->size, k);
142 return run_gesvd(jobu, jobvt, rank, *matrix, *values, static_cast<matrix_scalar*>(matrix->data), 1,
143 static_cast<matrix_scalar*>(matrix->data), 1);
144}
145} // namespace lapack_detail
146
147namespace lapack_detail
148{
150template <uni20::MutableRankedStridedMdspanLike<1> SingularValueMdspan,
151 uni20::MutableRankedStridedMdspanLike<2> MatrixMdspan>
152consteval auto svd_acceptance(singular_values_op const&, std::type_identity<SingularValueMdspan>,
153 std::type_identity<MatrixMdspan>)
154{
155 if constexpr (lapack_detail::svd_base_types_supported<SingularValueMdspan, MatrixMdspan>())
156 {
157 return kernel_types_maybe;
158 }
159 else
160 {
161 return kernel_types_no;
162 }
163}
164
166template <uni20::MutableRankedStridedMdspanLike<1> SingularValueMdspan,
167 uni20::MutableRankedStridedMdspanLike<2> MatrixMdspan>
168KernelAttempt try_svd(singular_values_op const&, SingularValueMdspan& singular_values, MatrixMdspan& matrix_work)
169{
170 return try_singular_values_kernel('N', 'N', singular_values, matrix_work);
171}
172
174template <uni20::MutableRankedStridedMdspanLike<1> SingularValueMdspan,
175 uni20::MutableRankedStridedMdspanLike<2> LeftMdspan, uni20::MutableRankedStridedMdspanLike<2> MatrixMdspan>
176consteval auto svd_acceptance(svd_left_op const&, std::type_identity<SingularValueMdspan>,
177 std::type_identity<LeftMdspan>, std::type_identity<MatrixMdspan>)
178{
179 if constexpr (lapack_detail::svd_base_types_supported<SingularValueMdspan, MatrixMdspan>() &&
180 lapack_detail::svd_factor_types_supported<LeftMdspan, MatrixMdspan>())
181 {
182 return kernel_types_maybe;
183 }
184 else
185 {
186 return kernel_types_no;
187 }
188}
189
191template <uni20::MutableRankedStridedMdspanLike<1> SingularValueMdspan,
192 uni20::MutableRankedStridedMdspanLike<2> MatrixMdspan>
193consteval auto svd_acceptance(svd_left_op const&, std::type_identity<SingularValueMdspan>,
194 std::type_identity<MatrixMdspan>)
195{
196 if constexpr (lapack_detail::svd_base_types_supported<SingularValueMdspan, MatrixMdspan>())
197 {
198 return kernel_types_maybe;
199 }
200 else
201 {
202 return kernel_types_no;
203 }
204}
205
207template <uni20::MutableRankedStridedMdspanLike<1> SingularValueMdspan,
208 uni20::MutableRankedStridedMdspanLike<2> LeftMdspan, uni20::MutableRankedStridedMdspanLike<2> MatrixMdspan>
209KernelAttempt try_svd(svd_left_op const& op, SingularValueMdspan& singular_values, LeftMdspan& left_singular_vectors,
210 MatrixMdspan& matrix_work)
211{
213 using matrix_scalar = std::remove_cv_t<typename std::remove_cvref_t<MatrixMdspan>::element_type>;
214 std::size_t const rows = static_cast<std::size_t>(matrix_work.extent(0));
215 std::size_t const cols = static_cast<std::size_t>(matrix_work.extent(1));
216 std::size_t const rank = std::min(rows, cols);
217 std::size_t const left_cols = op.left == SvdVectorExtent::Full ? rows : rank;
218 CHECK_EQUAL(static_cast<std::size_t>(singular_values.extent(0)), rank);
219 CHECK_EQUAL(static_cast<std::size_t>(left_singular_vectors.extent(0)), rows);
220 CHECK_EQUAL(static_cast<std::size_t>(left_singular_vectors.extent(1)), left_cols);
221 if (rank == 0)
222 {
223 set_identity(left_singular_vectors);
225 }
226
227 auto matrix = uni20::linalg::blas::try_lapack_writable_matrix(matrix_work);
229 auto left = uni20::linalg::blas::try_lapack_writable_matrix(left_singular_vectors);
230 if (!matrix || !values || !left)
231 {
233 }
234
235 blas_int const k = uni20::blas::try_blas_int(rank);
236 blas_int const left_columns = uni20::blas::try_blas_int(left_cols);
238 {
240 }
241 CHECK_EQUAL(values->size, k);
242 CHECK_EQUAL(left->rows, matrix->rows);
243 CHECK_EQUAL(left->cols, left_columns);
244 return run_gesvd(svd_job(op.left), 'N', rank, *matrix, *values, left->data, left->leading_dimension,
245 static_cast<matrix_scalar*>(matrix->data), 1);
246}
247
249template <uni20::MutableRankedStridedMdspanLike<1> SingularValueMdspan,
250 uni20::MutableRankedStridedMdspanLike<2> MatrixMdspan>
251KernelAttempt try_svd(svd_left_op const& op, SingularValueMdspan& singular_values, MatrixMdspan& matrix_work)
252{
255 return try_singular_values_kernel('O', 'N', singular_values, matrix_work);
256}
257
259template <uni20::MutableRankedStridedMdspanLike<1> SingularValueMdspan,
260 uni20::MutableRankedStridedMdspanLike<2> RightAdjointMdspan,
261 uni20::MutableRankedStridedMdspanLike<2> MatrixMdspan>
262consteval auto svd_acceptance(svd_right_op const&, std::type_identity<SingularValueMdspan>,
263 std::type_identity<RightAdjointMdspan>, std::type_identity<MatrixMdspan>)
264{
265 if constexpr (lapack_detail::svd_base_types_supported<SingularValueMdspan, MatrixMdspan>() &&
266 lapack_detail::svd_factor_types_supported<RightAdjointMdspan, MatrixMdspan>())
267 {
268 return kernel_types_maybe;
269 }
270 else
271 {
272 return kernel_types_no;
273 }
274}
275
277template <uni20::MutableRankedStridedMdspanLike<1> SingularValueMdspan,
278 uni20::MutableRankedStridedMdspanLike<2> MatrixMdspan>
279consteval auto svd_acceptance(svd_right_op const&, std::type_identity<SingularValueMdspan>,
280 std::type_identity<MatrixMdspan>)
281{
282 if constexpr (lapack_detail::svd_base_types_supported<SingularValueMdspan, MatrixMdspan>())
283 {
284 return kernel_types_maybe;
285 }
286 else
287 {
288 return kernel_types_no;
289 }
290}
291
293template <uni20::MutableRankedStridedMdspanLike<1> SingularValueMdspan,
294 uni20::MutableRankedStridedMdspanLike<2> RightAdjointMdspan,
295 uni20::MutableRankedStridedMdspanLike<2> MatrixMdspan>
296KernelAttempt try_svd(svd_right_op const& op, SingularValueMdspan& singular_values,
297 RightAdjointMdspan& right_singular_vectors_adjoint, MatrixMdspan& matrix_work)
298{
300 using matrix_scalar = std::remove_cv_t<typename std::remove_cvref_t<MatrixMdspan>::element_type>;
301 std::size_t const rows = static_cast<std::size_t>(matrix_work.extent(0));
302 std::size_t const cols = static_cast<std::size_t>(matrix_work.extent(1));
303 std::size_t const rank = std::min(rows, cols);
304 std::size_t const right_rows = op.right == SvdVectorExtent::Full ? cols : rank;
305 CHECK_EQUAL(static_cast<std::size_t>(singular_values.extent(0)), rank);
306 CHECK_EQUAL(static_cast<std::size_t>(right_singular_vectors_adjoint.extent(0)), right_rows);
307 CHECK_EQUAL(static_cast<std::size_t>(right_singular_vectors_adjoint.extent(1)), cols);
308 if (rank == 0)
309 {
310 set_identity(right_singular_vectors_adjoint);
312 }
313
314 auto matrix = uni20::linalg::blas::try_lapack_writable_matrix(matrix_work);
316 auto right = uni20::linalg::blas::try_lapack_writable_matrix(right_singular_vectors_adjoint);
317 if (!matrix || !values || !right)
318 {
320 }
321
322 blas_int const k = uni20::blas::try_blas_int(rank);
323 blas_int const right_rows_blas = uni20::blas::try_blas_int(right_rows);
325 {
327 }
328 CHECK_EQUAL(values->size, k);
329 CHECK_EQUAL(right->rows, right_rows_blas);
330 CHECK_EQUAL(right->cols, matrix->cols);
331 return run_gesvd('N', svd_job(op.right), rank, *matrix, *values, static_cast<matrix_scalar*>(matrix->data), 1,
332 right->data, right->leading_dimension);
333}
334
336template <uni20::MutableRankedStridedMdspanLike<1> SingularValueMdspan,
337 uni20::MutableRankedStridedMdspanLike<2> MatrixMdspan>
338KernelAttempt try_svd(svd_right_op const& op, SingularValueMdspan& singular_values, MatrixMdspan& matrix_work)
339{
342 return try_singular_values_kernel('N', 'O', singular_values, matrix_work);
343}
344
346template <
349consteval auto svd_acceptance(svd_op const&, std::type_identity<SingularValueMdspan>, std::type_identity<LeftMdspan>,
350 std::type_identity<RightAdjointMdspan>, std::type_identity<MatrixMdspan>)
351{
352 if constexpr (lapack_detail::svd_base_types_supported<SingularValueMdspan, MatrixMdspan>() &&
353 lapack_detail::svd_factor_types_supported<LeftMdspan, MatrixMdspan>() &&
354 lapack_detail::svd_factor_types_supported<RightAdjointMdspan, MatrixMdspan>())
355 {
356 return kernel_types_maybe;
357 }
358 else
359 {
360 return kernel_types_no;
361 }
362}
363
365template <uni20::MutableRankedStridedMdspanLike<1> SingularValueMdspan,
366 uni20::MutableRankedStridedMdspanLike<2> OtherFactorMdspan,
367 uni20::MutableRankedStridedMdspanLike<2> MatrixMdspan>
368consteval auto svd_acceptance(svd_op const&, std::type_identity<SingularValueMdspan>,
369 std::type_identity<OtherFactorMdspan>, std::type_identity<MatrixMdspan>)
370{
371 if constexpr (lapack_detail::svd_base_types_supported<SingularValueMdspan, MatrixMdspan>() &&
372 lapack_detail::svd_factor_types_supported<OtherFactorMdspan, MatrixMdspan>())
373 {
374 return kernel_types_maybe;
375 }
376 else
377 {
378 return kernel_types_no;
379 }
380}
381
386template <
389KernelAttempt try_svd(svd_op const& op, SingularValueMdspan& singular_values, LeftMdspan& left_singular_vectors,
390 RightAdjointMdspan& right_singular_vectors_adjoint, MatrixMdspan& matrix_work)
391{
393 std::size_t const rows = static_cast<std::size_t>(matrix_work.extent(0));
394 std::size_t const cols = static_cast<std::size_t>(matrix_work.extent(1));
395 std::size_t const rank = std::min(rows, cols);
396 std::size_t const left_cols = op.left == SvdVectorExtent::Full ? rows : rank;
397 std::size_t const right_rows = op.right == SvdVectorExtent::Full ? cols : rank;
398
399 CHECK_EQUAL(static_cast<std::size_t>(singular_values.extent(0)), rank);
400 CHECK_EQUAL(static_cast<std::size_t>(left_singular_vectors.extent(0)), rows);
401 CHECK_EQUAL(static_cast<std::size_t>(left_singular_vectors.extent(1)), left_cols);
402 CHECK_EQUAL(static_cast<std::size_t>(right_singular_vectors_adjoint.extent(0)), right_rows);
403 CHECK_EQUAL(static_cast<std::size_t>(right_singular_vectors_adjoint.extent(1)), cols);
404 if (rank == 0)
405 {
406 set_identity(left_singular_vectors);
407 set_identity(right_singular_vectors_adjoint);
409 }
410
411 auto matrix = uni20::linalg::blas::try_lapack_writable_matrix(matrix_work);
413 auto left = uni20::linalg::blas::try_lapack_writable_matrix(left_singular_vectors);
414 auto right = uni20::linalg::blas::try_lapack_writable_matrix(right_singular_vectors_adjoint);
415 if (!matrix || !values || !left || !right)
416 {
418 }
419
420 blas_int const k = uni20::blas::try_blas_int(rank);
421 blas_int const left_columns = uni20::blas::try_blas_int(left_cols);
422 blas_int const right_rows_blas = uni20::blas::try_blas_int(right_rows);
424 !uni20::blas::is_valid_blas_int(right_rows_blas))
425 {
427 }
428
429 CHECK_EQUAL(values->size, k);
430 CHECK_EQUAL(left->rows, matrix->rows);
431 CHECK_EQUAL(left->cols, left_columns);
432 CHECK_EQUAL(right->rows, right_rows_blas);
433 CHECK_EQUAL(right->cols, matrix->cols);
434 return run_gesvd(svd_job(op.left), svd_job(op.right), rank, *matrix, *values, left->data, left->leading_dimension,
435 right->data, right->leading_dimension);
436}
437
439template <uni20::MutableRankedStridedMdspanLike<1> SingularValueMdspan,
440 uni20::MutableRankedStridedMdspanLike<2> OtherFactorMdspan,
441 uni20::MutableRankedStridedMdspanLike<2> MatrixMdspan>
442KernelAttempt try_svd(svd_op const& op, SingularValueMdspan& singular_values, OtherFactorMdspan& other_factor,
443 MatrixMdspan& matrix_work)
444{
445 using matrix_scalar = std::remove_cv_t<typename std::remove_cvref_t<MatrixMdspan>::element_type>;
446 std::size_t const rows = static_cast<std::size_t>(matrix_work.extent(0));
447 std::size_t const cols = static_cast<std::size_t>(matrix_work.extent(1));
448 std::size_t const rank = std::min(rows, cols);
449 CHECK_EQUAL(static_cast<std::size_t>(singular_values.extent(0)), rank);
450
451 char jobu = 'N';
452 char jobvt = 'N';
453 bool const overwrite_left = op.overwrite == SvdOverwrite::Left;
454 if (overwrite_left)
455 {
457 std::size_t const right_rows = op.right == SvdVectorExtent::Full ? cols : rank;
458 CHECK_EQUAL(static_cast<std::size_t>(other_factor.extent(0)), right_rows);
459 CHECK_EQUAL(static_cast<std::size_t>(other_factor.extent(1)), cols);
460 jobu = 'O';
461 jobvt = svd_job(op.right);
462 }
463 else
464 {
467 std::size_t const left_cols = op.left == SvdVectorExtent::Full ? rows : rank;
468 CHECK_EQUAL(static_cast<std::size_t>(other_factor.extent(0)), rows);
469 CHECK_EQUAL(static_cast<std::size_t>(other_factor.extent(1)), left_cols);
470 jobu = svd_job(op.left);
471 jobvt = 'O';
472 }
473
474 if (rank == 0)
475 {
476 set_identity(other_factor);
478 }
479
480 auto matrix = uni20::linalg::blas::try_lapack_writable_matrix(matrix_work);
482 auto other = uni20::linalg::blas::try_lapack_writable_matrix(other_factor);
483 if (!matrix || !values || !other)
484 {
486 }
487
488 blas_int const k = uni20::blas::try_blas_int(rank);
490 {
492 }
493 CHECK_EQUAL(values->size, k);
494
495 matrix_scalar* left = static_cast<matrix_scalar*>(matrix->data);
496 blas_int left_leading_dimension = 1;
497 matrix_scalar* right = static_cast<matrix_scalar*>(matrix->data);
498 blas_int right_leading_dimension = 1;
499 if (overwrite_left)
500 {
501 CHECK_EQUAL(other->cols, matrix->cols);
502 right = other->data;
503 right_leading_dimension = other->leading_dimension;
504 }
505 else
506 {
507 CHECK_EQUAL(other->rows, matrix->rows);
508 left = other->data;
509 left_leading_dimension = other->leading_dimension;
510 }
511 return run_gesvd(jobu, jobvt, rank, *matrix, *values, left, left_leading_dimension, right, right_leading_dimension);
512}
513} // namespace lapack_detail
514
516template <lapack_detail::SvdOperation Operation, uni20::MutableStridedMdspecLike... Mdspans>
518 requires {
519 lapack_detail::svd_acceptance(Operation{}, std::type_identity<uni20::host_write_mdspan_t<Mdspans>>{}...);
520 }
521consteval auto kernel_accepts_types(LapackBackend const&, Operation const&, Mdspans&...)
522{
523 constexpr auto acceptance =
524 lapack_detail::svd_acceptance(Operation{}, std::type_identity<uni20::host_write_mdspan_t<Mdspans>>{}...);
525 if constexpr (acceptance == KernelTypeAcceptance::no)
526 return kernel_types_no;
527 else
528 return kernel_types_maybe;
529}
530
532template <lapack_detail::SvdOperation Operation, uni20::MutableStridedMdspecLike... Mdspans>
534 requires {
535 lapack_detail::svd_acceptance(Operation{}, std::type_identity<uni20::host_write_mdspan_t<Mdspans>>{}...);
536 }
537KernelAttempt try_kernel(LapackBackend, Operation const& operation, Mdspans&... mdspans)
538{
540 [&](auto&... spans) { return lapack_detail::try_svd(operation, spans...); }, mdspans...);
541}
542
543} // namespace uni20::linalg
544
545#if UNI20_HAS_MPLAPACK_MPREAL || UNI20_HAS_MPLAPACK_FLOAT80
547#endif
RAII leases that resolve device descriptors and tensor views to mdspans.
Safe conversion helpers for the configured signed BLAS integer ABI.
An mdspan-like type whose accessor is stdex::default_accessor.
Definition mdspan/concepts.hpp:501
Mutable mdspec metadata supporting host write acquisition.
Definition access.hpp:694
Real scalar types supported by the configured raw-pointer LAPACK wrappers.
Definition scalar_concepts.hpp:115
Concept for scalar types with a configured dense LAPACK backend.
Definition scalar_concepts.hpp:147
A mutable strided mdspan-like type with a specified static rank.
Definition mdspan/concepts.hpp:532
Mutable mdspec-like type whose mapping is always strided.
Definition mdspan/concepts.hpp:440
Concept for numeric scalar types (integer, real, or complex).
Definition scalar_concepts.hpp:81
Definition backends/lapack/svd.hpp:34
Logical host adapters for value-converting dense decompositions.
Operation-tag backend dispatch over tensor-view operands.
typename make_real< T >::type make_real_t
Alias for the underlying real-valued type of T.
Definition scalar_traits.hpp:168
Checked LAPACK wrappers over provider-specific unchecked overloads.
Shared helpers for LAPACK operation-tag backend adapters.
Lower mdspan matrix views to provider-ready BLAS operands.
Lower rank-one mdspan views to provider-ready BLAS operands.
constexpr blas_int try_blas_int(Value value) noexcept
Convert a non-negative integer to blas_int, or return the negative invalid sentinel.
Definition blas_int.hpp:28
constexpr bool is_valid_blas_int(blas_int value) noexcept
Return whether a non-throwing BLAS integer conversion succeeded.
Definition blas_int.hpp:25
void gesvd(char jobu, char jobvt, blas_int m, blas_int n, Scalar *a, blas_int lda, Scalar *s, Scalar *u, blas_int ldu, Scalar *vt, blas_int ldvt, Scalar *work, blas_int lwork)
Compute a real dense singular value decomposition.
Definition lapack.hpp:1186
auto try_lapack_writable_vector(Mdspan const &span) -> std::optional< BlasWritableVector< std::remove_cv_t< typename Mdspan::element_type >, typename Mdspan::data_handle_type > >
Try to lower an mdspan to the contiguous writable vector shape expected by LAPACK.
Definition mdspan_vector.hpp:130
auto try_lapack_writable_matrix(Mdspan const &span) -> std::optional< BlasWritableMatrix< std::remove_cv_t< typename Mdspan::element_type >, typename Mdspan::data_handle_type > >
Try to lower an mdspan to the strict column-major shape expected by LAPACK.
Definition mdspan_matrix.hpp:285
consteval auto svd_acceptance(singular_values_op const &, std::type_identity< SingularValueMdspan >, std::type_identity< MatrixMdspan >)
Report compile-time eligibility for resolved LAPACK singular values.
Definition backends/lapack/svd.hpp:152
KernelAttempt try_svd(singular_values_op const &, SingularValueMdspan &singular_values, MatrixMdspan &matrix_work)
Compute exact singular values through LAPACK gesvd.
Definition backends/lapack/svd.hpp:168
KernelAttempt try_singular_values_kernel(char jobu, char jobvt, SingularValueMdspan &&singular_values, MatrixMdspan &&matrix_work)
Definition backends/lapack/svd.hpp:116
blas_int workspace_size(Scalar const &query)
Convert a provider workspace query result to the configured LAPACK integer type.
Definition linalg/backends/lapack/common.hpp:43
KernelAttempt with_host_write_mdspans(Function &&function, Mdspecs &... mdspecs)
Invoke a LAPACK attempt with host-writable mdspans under simultaneous leases.
Definition linalg/backends/lapack/common.hpp:29
void set_identity(MatrixMdspan &&matrix)
Definition backends/lapack/svd.hpp:51
consteval bool svd_factor_types_supported()
Definition backends/lapack/svd.hpp:72
consteval bool svd_base_types_supported()
Definition backends/lapack/svd.hpp:63
KernelAttempt run_gesvd(char jobu, char jobvt, std::size_t rank, uni20::linalg::blas::BlasWritableMatrix< Scalar, MatrixHandle > const &matrix, uni20::linalg::blas::BlasWritableVector< uni20::make_real_t< Scalar >, ValueHandle > const &values, Scalar *left, blas_int left_leading_dimension, Scalar *right, blas_int right_leading_dimension)
Definition backends/lapack/svd.hpp:80
char svd_job(SvdVectorExtent extent)
Definition backends/lapack/svd.hpp:39
constexpr std::optional< std::size_t > try_size_product(std::size_t left, std::size_t right) noexcept
Multiply allocation extents without wrapping std::size_t.
Definition linalg/backends/lapack/common.hpp:69
Definition linalg/async.hpp:28
KernelAttempt try_kernel(BlasBackend, gemm_op const &, C &c, S const &alpha, A &a, B &b, S const &beta)
Pack logical host values and execute GEMM through value-preserving provider conversion.
Definition linalg/backends/blas/binary80.hpp:30
KernelAttempt
Result of one runtime kernel backend attempt.
Definition kernel_attempt.hpp:27
constexpr KernelAcceptance< KernelTypeAcceptance::no > kernel_types_no
Report that a backend rejects the argument types.
Definition dispatch_error.hpp:34
SvdVectorExtent
Extent policy for one side of an exact singular value decomposition.
Definition operation_tags.hpp:248
consteval auto kernel_accepts_types(BlasBackend, gemm_op const &, C &, S const &, A &, B &, S const &)
Accept host-readable native binary80 operands, including transforming accessors.
Definition linalg/backends/blas/binary80.hpp:19
constexpr KernelAcceptance< KernelTypeAcceptance::maybe > kernel_types_maybe
Report that runtime operand values determine backend acceptance.
Definition dispatch_error.hpp:37
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
Backend-independent operation values used with normalized kernel operands.
Backend family for configured dense LAPACK kernels, including MPLAPACK scalar adapters.
Definition backend_selector.hpp:20
Writable matrix shape as seen by a BLAS/LAPACK provider.
Definition blas_matrix.hpp:119
blas_int rows
Definition blas_matrix.hpp:121
blas_int leading_dimension
Definition blas_matrix.hpp:123
Handle data
Definition blas_matrix.hpp:120
blas_int cols
Definition blas_matrix.hpp:122
Writable vector shape as seen by a BLAS provider.
Definition blas_vector.hpp:16
Exact dense singular-values-only operation tag.
Definition operation_tags.hpp:270
Exact dense left singular-vector operation tag.
Definition operation_tags.hpp:276
SvdVectorExtent left
Definition operation_tags.hpp:278
bool overwrite_input
Definition operation_tags.hpp:279
Exact dense singular value decomposition operation tag.
Definition operation_tags.hpp:292
SvdVectorExtent left
Definition operation_tags.hpp:294
SvdVectorExtent right
Definition operation_tags.hpp:295
SvdOverwrite overwrite
Definition operation_tags.hpp:296
Exact dense right singular-vector operation tag.
Definition operation_tags.hpp:284
SvdVectorExtent right
Definition operation_tags.hpp:286
bool overwrite_input
Definition operation_tags.hpp:287
Trait to extract the scalar type from a type T.
Definition scalar_traits.hpp:93
Concepts for tensor-level objects that resolve mdspan kernel operands.
#define CHECK(cond,...)
Definition trace.hpp:299
#define PANIC(...)
Definition trace.hpp:382
#define CHECK_EQUAL(a, b,...)
Definition trace.hpp:309