21#ifndef BATCHLAS_VERIFY_HAVE_LAPACKE
22#error "batchlas/verify/reference.hh: link batchlas::verify, which defines BATCHLAS_VERIFY_HAVE_LAPACKE"
25#if BATCHLAS_VERIFY_HAVE_LAPACKE
30std::string host_dgemm_defect();
44#if BATCHLAS_VERIFY_HAVE_LAPACKE
45 if constexpr (std::is_same_v<D, double> || std::is_same_v<D, std::complex<double>>) {
46 static const std::string defect = host_dgemm_defect();
47 if (!defect.empty())
throw batchlas::unsupported(
"batchlas::verify: host LAPACKE reference refused\n" + defect);
56 const auto m = A.template astype<U>(std::span<const int>(&item, 1));
57 return std::vector<U>(m.data().data(), m.data().data() + std::size_t(A.
rows()) * std::size_t(A.
cols()));
63 requires(std::is_same_v<D, double> || std::is_same_v<D, std::complex<double>>)
64bool eigenvalues(
int n, std::vector<D>& a, std::vector<double>& w) {
65 w.assign(
static_cast<std::size_t
>(n), 0.0);
66#if BATCHLAS_VERIFY_HAVE_LAPACKE
67 if (n == 0)
return true;
69 if constexpr (std::is_same_v<D, double>)
70 return LAPACKE_dsyevd(LAPACK_COL_MAJOR,
'N',
'L', n, a.data(), n, w.data()) == 0;
72 return LAPACKE_zheevd(LAPACK_COL_MAJOR,
'N',
'L', n,
reinterpret_cast<lapack_complex_double*
>(a.data()), n,
82 requires(std::is_same_v<D, double> || std::is_same_v<D, std::complex<double>>)
84 s.assign(
static_cast<std::size_t
>(std::min(m, n)), 0.0);
85#if BATCHLAS_VERIFY_HAVE_LAPACKE
86 if (s.empty())
return true;
88 if constexpr (std::is_same_v<D, double>)
89 return LAPACKE_dgesdd(LAPACK_COL_MAJOR,
'N', m, n, a.data(), m, s.data(),
nullptr, 1,
nullptr, 1) == 0;
91 return LAPACKE_zgesdd(LAPACK_COL_MAJOR,
'N', m, n,
reinterpret_cast<lapack_complex_double*
>(a.data()), m,
92 s.data(),
nullptr, 1,
nullptr, 1) == 0;
107template <
class E>
bool getrf_pivots(
int m,
int n, std::vector<E>& a, std::vector<std::int32_t>& ipiv) {
108 static_assert(std::is_same_v<E, float> || std::is_same_v<E, double> || std::is_same_v<E, std::complex<float>> ||
109 std::is_same_v<E, std::complex<double>>,
110 "getrf_pivots: float, double, complex<float> or complex<double> only");
111 ipiv.assign(
static_cast<std::size_t
>(std::min(m, n)), 0);
112#if BATCHLAS_VERIFY_HAVE_LAPACKE
113 if (ipiv.empty())
return true;
115 std::vector<lapack_int> p(ipiv.size());
117 if constexpr (std::is_same_v<E, float>)
118 info = LAPACKE_sgetrf(LAPACK_COL_MAJOR, m, n, a.data(), m, p.data());
119 else if constexpr (std::is_same_v<E, double>)
120 info = LAPACKE_dgetrf(LAPACK_COL_MAJOR, m, n, a.data(), m, p.data());
121 else if constexpr (std::is_same_v<E, std::complex<float>>)
122 info = LAPACKE_cgetrf(LAPACK_COL_MAJOR, m, n,
reinterpret_cast<lapack_complex_float*
>(a.data()), m, p.data());
124 info = LAPACKE_zgetrf(LAPACK_COL_MAJOR, m, n,
reinterpret_cast<lapack_complex_double*
>(a.data()), m, p.data());
126 if (info < 0)
return false;
127 for (std::size_t i = 0; i < p.size(); ++i) ipiv[i] =
static_cast<std::int32_t
>(p[i]);
143template <
class D>
bool geqrf_tau(
int m,
int n, std::vector<D>& a, std::vector<D>& tau) {
144 static_assert(std::is_same_v<D, double> || std::is_same_v<D, std::complex<double>>,
145 "geqrf_tau: double or complex<double> only");
146 tau.assign(
static_cast<std::size_t
>(std::min(m, n)), D(0));
147#if BATCHLAS_VERIFY_HAVE_LAPACKE
148 if (tau.empty())
return true;
150 if constexpr (std::is_same_v<D, double>)
151 return LAPACKE_dgeqrf(LAPACK_COL_MAJOR, m, n, a.data(), m, tau.data()) == 0;
153 return LAPACKE_zgeqrf(LAPACK_COL_MAJOR, m, n,
reinterpret_cast<lapack_complex_double*
>(a.data()), m,
154 reinterpret_cast<lapack_complex_double*
>(tau.data())) == 0;
163#if BATCHLAS_VERIFY_HAVE_LAPACKE
164 if (d.empty())
return true;
165 return LAPACKE_dsterf(
static_cast<lapack_int
>(d.size()), d.data(), e.data()) == 0;
Non-owning view of a batch of matrices: the argument type of every entry point.
int rows() const
Rows per item (the capacity on a heterogeneous batch).
int cols() const
Columns per item (the capacity on a heterogeneous batch).
std::conditional_t< is_std_complex_v< T >, std::complex< double >, double > promoted_type
T's promoted type: double, or complex<double> for complex T.
No kernel, backend or vendor entry point in this build on this device serves the request.
The BatchLAS exception hierarchy.
The batched containers: Matrix (owning), MatrixView (non-owning), KernelMatrixView (device-side),...
void require_host_dgemm()
std::vector< U > item_vector(const MatrixView< T, MatrixFormat::Dense > &A, int item)
constexpr bool have_reference
True when this build has host LAPACKE references; a reference that returns false here failed.
bool getrf_pivots(int m, int n, std::vector< E > &a, std::vector< std::int32_t > &ipiv)
1-based pivots of the m x n a (column-major, ld = m; overwritten by its LU factor): min(m,...
bool singular_values(int m, int n, std::vector< D > &a, std::vector< double > &s)
Descending singular values of the m x n a (column-major, ld = m; destroyed).
bool tridiagonal_eigenvalues(std::vector< double > &d, std::vector< double > &e)
Eigenvalues of the symmetric tridiagonal (diagonal d, off-diagonal e): ascending, written to d.
bool eigenvalues(int n, std::vector< D > &a, std::vector< double > &w)
Ascending eigenvalues of the n x n Hermitian a (column-major, ld = n, both triangles valid; destroyed...
bool geqrf_tau(int m, int n, std::vector< D > &a, std::vector< D > &tau)
LAPACK geqrf of the m x n a (column-major, ld = m; overwritten by R and the reflectors) and its min(m...