Uni20
Asynchronous tensor and runtime library.
Loading...
Searching...
No Matches
backends/lapack/self_adjoint_eigh.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{
33inline char lapack_triangle(MatrixTriangle triangle)
34{
35 switch (triangle)
36 {
38 return 'U';
40 return 'L';
41 }
42 PANIC("invalid MatrixTriangle", std::to_underlying(triangle));
43}
44
46template <uni20::MutableRankedStridedMdspanLike<1> EigenvalueMdspan,
47 uni20::MutableRankedStridedMdspanLike<2> MatrixMdspan>
49{
50 using matrix_scalar = std::remove_cv_t<typename MatrixMdspan::element_type>;
51 using eigenvalue_scalar = std::remove_cv_t<typename EigenvalueMdspan::element_type>;
53 std::same_as<eigenvalue_scalar, uni20::make_real_t<matrix_scalar>> &&
55 {
56 return kernel_types_maybe;
57 }
58 else
59 {
60 return kernel_types_no;
61 }
62}
63
67template <uni20::MutableRankedStridedMdspanLike<1> EigenvalueMdspan,
68 uni20::MutableRankedStridedMdspanLike<2> MatrixMdspan>
69KernelAttempt try_self_adjoint_eigh(self_adjoint_eigh_op const& op, EigenvalueMdspan& eigenvalues,
70 MatrixMdspan& matrix_work)
71{
72 using matrix_type = std::remove_cvref_t<MatrixMdspan>;
73 using matrix_scalar = std::remove_cv_t<typename matrix_type::element_type>;
74 using real_type = uni20::make_real_t<matrix_scalar>;
75
76 CHECK_EQUAL(matrix_work.extent(0), matrix_work.extent(1));
77 std::size_t const n = static_cast<std::size_t>(matrix_work.extent(0));
78 CHECK_EQUAL(static_cast<std::size_t>(eigenvalues.extent(0)), n);
79
80 blas_int const order = uni20::blas::try_blas_int(n);
82 {
84 }
85 if (order == 0)
86 {
88 }
89
90 auto matrix = uni20::linalg::blas::try_lapack_writable_matrix(matrix_work);
91 auto values = uni20::linalg::blas::try_lapack_writable_vector(eigenvalues);
92 if (!matrix || !values)
93 {
95 }
96 CHECK_EQUAL(matrix->rows, order);
97 CHECK_EQUAL(matrix->cols, order);
98 CHECK_EQUAL(values->size, order);
99
100 char const jobz = op.compute_vectors ? 'V' : 'N';
101 char const uplo = lapack_detail::lapack_triangle(op.triangle);
103 {
104 matrix_scalar work_query{};
105 uni20::lapack::syev(jobz, uplo, order, matrix->data, matrix->leading_dimension, values->data, &work_query, -1);
106 blas_int const lwork = lapack_detail::workspace_size(work_query);
107 std::vector<matrix_scalar> work(static_cast<std::size_t>(lwork), matrix_scalar{});
108 uni20::lapack::syev(jobz, uplo, order, matrix->data, matrix->leading_dimension, values->data, work.data(), lwork);
109 }
110 else
111 {
112 auto const three_order = lapack_detail::try_size_product(3, n);
113 if (!three_order)
114 {
116 }
117 std::size_t const rwork_size = std::max<std::size_t>(1, *three_order - 2);
118 std::vector<real_type> rwork(rwork_size, real_type{});
119
120 matrix_scalar work_query{};
121 uni20::lapack::heev(jobz, uplo, order, matrix->data, matrix->leading_dimension, values->data, &work_query, -1,
122 rwork.data());
123 blas_int const lwork = lapack_detail::workspace_size(work_query);
124 std::vector<matrix_scalar> work(static_cast<std::size_t>(lwork), matrix_scalar{});
125 uni20::lapack::heev(jobz, uplo, order, matrix->data, matrix->leading_dimension, values->data, work.data(), lwork,
126 rwork.data());
127 }
128
130}
131} // namespace lapack_detail
132
134template <uni20::MutableRankedStridedMdspecLike<1> EigenvalueMdspan,
135 uni20::MutableRankedStridedMdspecLike<2> MatrixMdspan>
138consteval auto kernel_accepts_types(LapackBackend const&, self_adjoint_eigh_op const&, EigenvalueMdspan&, MatrixMdspan&)
139{
140 using eigenvalue_span = uni20::host_write_mdspan_t<EigenvalueMdspan>;
142 constexpr auto acceptance = lapack_detail::self_adjoint_eigh_acceptance<eigenvalue_span, matrix_span>();
143 if constexpr (acceptance == KernelTypeAcceptance::no)
144 return kernel_types_no;
145 else
146 return kernel_types_maybe;
147}
148
150template <uni20::MutableRankedStridedMdspecLike<1> EigenvalueMdspan,
151 uni20::MutableRankedStridedMdspecLike<2> MatrixMdspan>
154KernelAttempt try_kernel(LapackBackend, self_adjoint_eigh_op const& operation, EigenvalueMdspan& eigenvalues,
155 MatrixMdspan& matrix_work)
156{
158 [&](auto& eigenvalue_span, auto& matrix_span) {
159 return lapack_detail::try_self_adjoint_eigh(operation, eigenvalue_span, matrix_span);
160 },
161 eigenvalues, matrix_work);
162}
163
164} // namespace uni20::linalg
165
166#if UNI20_HAS_MPLAPACK_MPREAL || UNI20_HAS_MPLAPACK_FLOAT80
168#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
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 heev(char jobz, char uplo, blas_int n, uni20::detail::standard_complex< Real > *a, blas_int lda, Real *w, uni20::detail::standard_complex< Real > *work, blas_int lwork, Real *rwork)
Compute eigenvalues and optionally eigenvectors of a complex Hermitian matrix.
Definition lapack.hpp:723
void syev(char jobz, char uplo, blas_int n, Scalar *a, blas_int lda, Scalar *w, Scalar *work, blas_int lwork)
Compute eigenvalues and optionally eigenvectors of a real symmetric matrix.
Definition lapack.hpp:664
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
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
char lapack_triangle(MatrixTriangle triangle)
Definition backends/lapack/self_adjoint_eigh.hpp:33
KernelAttempt try_self_adjoint_eigh(self_adjoint_eigh_op const &op, EigenvalueMdspan &eigenvalues, MatrixMdspan &matrix_work)
Compute an in-place symmetric or Hermitian eigensystem through syev or heev.
Definition backends/lapack/self_adjoint_eigh.hpp:69
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
consteval auto self_adjoint_eigh_acceptance()
Report compile-time eligibility for resolved LAPACK self-adjoint eigenanalysis.
Definition backends/lapack/self_adjoint_eigh.hpp:48
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
MatrixTriangle
Triangle of a symmetric or Hermitian matrix supplied to an operation.
Definition operation_tags.hpp:226
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
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
std::remove_cvref_t< decltype(std::declval< detail::host_write_mdspan_lease_t< Mdspec > & >().mdspan())> host_write_mdspan_t
Writable mdspan type resolved by host descriptor acquisition.
Definition access.hpp:684
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
Dense symmetric or Hermitian eigensystem operation tag.
Definition operation_tags.hpp:240
bool compute_vectors
Definition operation_tags.hpp:242
MatrixTriangle triangle
Definition operation_tags.hpp:243
Concepts for tensor-level objects that resolve mdspan kernel operands.
#define PANIC(...)
Definition trace.hpp:382
#define CHECK_EQUAL(a, b,...)
Definition trace.hpp:309