options.hh
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4#include <cstddef>
5#include <cstdlib>
6#include <concepts>
7#include <initializer_list>
8#include <optional>
9#include <stdexcept>
10#include <string>
11
17
18/// @file
19/// @brief Option-struct spellings of the dense BLAS and LAPACK-style entry points.
20/// @ingroup api_options
21
22/**
23 * @addtogroup api_options
24 * @details
25 * Each entry point here takes its non-matrix arguments as one designated-initialiser
26 * struct, so a call names only what differs from the defaults:
27 * @code
28 * gemm(ctx, A, B, C, {.alpha = 2.0f, .transA = Transpose::Trans});
29 * syev(ctx, A, W, {.jobz = JobType::NoEigenVectors});
30 * @endcode
31 * Every overload comes twice: `f(ctx, ...)` takes the backend from the Queue and
32 * checks that pointer arguments are device-accessible; `f<Backend>(ctx, ...)` fixes
33 * it at compile time. `T` is always deduced from the matrix arguments, never from
34 * the option struct. Matrix arguments may be `Matrix` or `MatrixView`.
35 *
36 * The LAPACK-style calls (`potrf`, `getrf`, `getrs`, `getri`, `geqrf`, `orgqr`,
37 * `syev`, `ormqr`, `gesvd`) come with and without a `Span<std::byte> ws` argument.
38 * Without it, scratch is leased from the Queue's arena, sized by the matching
39 * `*_buffer_size`; on an out-of-order queue releasing the lease drains the queue,
40 * so pass your own span there to stay asynchronous. Every option overload, both
41 * spellings, with and without `ws`, checks shapes (squareness, matching rows and
42 * batch sizes, minimum span lengths) and throws `batchlas::invalid_argument` on a
43 * violation; only the deducing spelling also checks pointers. The ordinary spelling
44 * with non-const lvalue arguments can resolve to the queue-dispatch overload, which
45 * lands on the `f<Backend>` form, so that form must check too.
46 *
47 * Every `uplo` defaults to `Uplo::Lower`. With an explicit workspace, write
48 * `PotrfOptions{}`, never a bare `{}`.
49 *
50 * The `*Params` structs of `blas/extensions.hh` are ordinary trailing arguments,
51 * not option structs; see @ref md_docs_2cpp-api. Design notes:
52 * @ref design_api_conventions.
53 */
54
55namespace batchlas {
56
57namespace detail {
58
59// Named counterpart of require_pack_accessible: the error says "gemm: A".
60template <typename... Args>
61inline void require_args_accessible(const Queue& ctx, const char* fn,
62 const char* const* names, const Args&... args) {
63 if (!pointer_checks_enabled()) return;
64 int i = 0;
65 (void)std::initializer_list<int>{
66 (require_arg_accessible(ctx, args, std::string(fn) + ": " + names[i++]), 0)...};
67}
68
69} // namespace detail
70
71// Check the pointer arguments of an entry point, naming the offending one.
72#define BATCHLAS_CHECK_ARGS(CTX, FN, ...) \
73 do { \
74 static const char* const _bl_names[] = {BATCHLAS_ARG_NAMES(__VA_ARGS__)}; \
75 ::batchlas::detail::require_args_accessible((CTX), FN, _bl_names, __VA_ARGS__); \
76 } while (0)
77
78#define BATCHLAS_ARG_NAMES_1(a) #a
79#define BATCHLAS_ARG_NAMES_2(a, b) #a, #b
80#define BATCHLAS_ARG_NAMES_3(a, b, c) #a, #b, #c
81#define BATCHLAS_ARG_NAMES_4(a, b, c, d) #a, #b, #c, #d
82#define BATCHLAS_ARG_NAMES_5(a, b, c, d, e) #a, #b, #c, #d, #e
83#define BATCHLAS_ARG_NAMES_6(a, b, c, d, e, f) #a, #b, #c, #d, #e, #f
84#define BATCHLAS_ARG_NAMES_PICK(_1, _2, _3, _4, _5, _6, NAME, ...) NAME
85#define BATCHLAS_ARG_NAMES(...) \
86 BATCHLAS_ARG_NAMES_PICK(__VA_ARGS__, BATCHLAS_ARG_NAMES_6, BATCHLAS_ARG_NAMES_5, \
87 BATCHLAS_ARG_NAMES_4, BATCHLAS_ARG_NAMES_3, \
88 BATCHLAS_ARG_NAMES_2, BATCHLAS_ARG_NAMES_1)(__VA_ARGS__)
89
90namespace detail {
91
92// Shape preconditions; invalid_argument (caller error), never runtime_error. They
93// are repeated on BOTH the deducing and the <Backend> overloads on purpose: the
94// variadic dispatch overload binds prvalues better and skips the deducing one.
95// Positional primaries stay unchecked (library code under src/ops/ calls them per iteration).
96// evidence: docs/design/api-conventions.md#api-conventions-shape-checks-live-on-both-option-overloads
97template <typename MV>
98inline void require_square(const char* fn, const char* name, const MV& A) {
99 if (A.rows() != A.cols())
100 throw batchlas::invalid_argument(std::string(fn) + ": " + name +
101 " must be square, got " + std::to_string(A.rows()) + "x" + std::to_string(A.cols()));
102}
103
104template <typename MA, typename MB>
105inline void require_same_rows(const char* fn, const char* an, const MA& A,
106 const char* bn, const MB& B) {
107 if (A.rows() != B.rows())
108 throw batchlas::invalid_argument(std::string(fn) + ": " + an + ".rows() (" +
109 std::to_string(A.rows()) + ") must equal " + bn + ".rows() (" +
110 std::to_string(B.rows()) + ")");
111}
112
113template <typename MA, typename MB>
114inline void require_same_batch(const char* fn, const char* an, const MA& A,
115 const char* bn, const MB& B) {
116 if (A.batch_size() != B.batch_size())
117 throw batchlas::invalid_argument(std::string(fn) + ": " + an + " and " + bn +
118 " must have the same batch size (" + std::to_string(A.batch_size()) + " vs " +
119 std::to_string(B.batch_size()) + ")");
120}
121
122// `>=`, not `==`: a caller may slice one big pivot/tau arena across several calls.
123inline void require_span_at_least(const char* fn, const char* name, size_t have, size_t need) {
124 if (have < need)
125 throw batchlas::invalid_argument(std::string(fn) + ": " + name + " holds " +
126 std::to_string(have) + " elements, needs at least " + std::to_string(need));
127}
128
129// Empty `info` = "no status wanted". A too-short one would fail silently (stale
130// zeros read as "all factorised"), hence the check.
131inline void require_info_span(const char* fn, size_t have, size_t batch_size) {
132 if (have != 0) require_span_at_least(fn, "info", have, batch_size);
133}
134
135} // namespace detail
136
137/// @addtogroup api_options
138/// @{
139
140// ---- dense BLAS ------------------------------------------------------------
141
142/// @brief Options for gemm(): \f$C := \alpha\,\mathrm{op}(A)\,\mathrm{op}(B) + \beta C\f$.
143template <typename T>
145 T alpha = T(1); ///< scale of the product
146 T beta = T(0); ///< scale of the incoming C; 0 means C is not read
149 ComputePrecision precision = ComputePrecision::Default; ///< internal compute type; Default = the input type
150};
151
152/// @brief Options for gemv(): \f$y := \alpha\,\mathrm{op}(A)\,x + \beta y\f$.
153template <typename T>
155 T alpha = T(1); ///< scale of the product
156 T beta = T(0); ///< scale of the incoming y
158};
159
160/// @brief Options for symm(): \f$C := \alpha A B + \beta C\f$ (Left) or \f$\alpha B A + \beta C\f$ (Right), A symmetric.
161template <typename T>
163 T alpha = T(1); ///< scale of the product
164 T beta = T(0); ///< scale of the incoming C
165 Side side = Side::Left; ///< which side A multiplies from
166 Uplo uplo = Uplo::Lower; ///< triangle of A that is read
167};
168
169/// @brief Options for hemm(): as SymmOptions, with A Hermitian.
170template <typename T>
172 T alpha = T(1); ///< scale of the product
173 T beta = T(0); ///< scale of the incoming C
174 Side side = Side::Left; ///< which side A multiplies from
175 Uplo uplo = Uplo::Lower; ///< triangle of A that is read
176};
177
178/// @brief Options for herk(): \f$C := \alpha\,\mathrm{op}(A)\,\mathrm{op}(A)^H + \beta C\f$.
179///
180/// `alpha` and `beta` are real, as the result must stay Hermitian.
181template <typename T>
183 float_t<T> alpha = float_t<T>(1); ///< real scale of the product
184 float_t<T> beta = float_t<T>(0); ///< real scale of the incoming C
185 Uplo uplo = Uplo::Lower; ///< triangle of C that is written
186 Transpose trans = Transpose::NoTrans; ///< NoTrans (\f$AA^H\f$) or ConjTrans (\f$A^HA\f$)
187};
188
189/// @brief Options for her2k(): \f$C := \alpha\,\mathrm{op}(A)\,\mathrm{op}(B)^H + \bar\alpha\,\mathrm{op}(B)\,\mathrm{op}(A)^H + \beta C\f$.
190///
191/// `alpha` is complex and `beta` real: the pair is Hermitian for any `alpha`.
192template <typename T>
194 T alpha = T(1); ///< complex scale
195 float_t<T> beta = float_t<T>(0); ///< real scale of the incoming C
196 Uplo uplo = Uplo::Lower; ///< triangle of C that is written
197 Transpose trans = Transpose::NoTrans; ///< NoTrans or ConjTrans
198};
199
200/// @brief Options for syrk(): \f$C := \alpha\,\mathrm{op}(A)\,\mathrm{op}(A)^T + \beta C\f$.
201template <typename T>
203 T alpha = T(1); ///< scale of the product
204 T beta = T(0); ///< scale of the incoming C
205 Uplo uplo = Uplo::Lower; ///< triangle of C that is written
206 Transpose trans = Transpose::NoTrans; ///< NoTrans (\f$AA^T\f$) or Trans (\f$A^TA\f$)
207};
208
209/// @brief Options for syr2k(): \f$C := \alpha(\mathrm{op}(A)\,\mathrm{op}(B)^T + \mathrm{op}(B)\,\mathrm{op}(A)^T) + \beta C\f$.
210template <typename T>
212 T alpha = T(1); ///< scale of the product pair
213 T beta = T(0); ///< scale of the incoming C
214 Uplo uplo = Uplo::Lower; ///< triangle of C that is written
215 Transpose trans = Transpose::NoTrans; ///< NoTrans or Trans
216};
217
218/// @brief Options for trmm(): \f$C := \alpha\,\mathrm{op}(A)\,B\f$ (Left) or \f$\alpha B\,\mathrm{op}(A)\f$ (Right). No `beta`.
219template <typename T>
221 T alpha = T(1); ///< scale of the product
222 Side side = Side::Left; ///< which side op(A) multiplies from
223 Uplo uplo = Uplo::Lower; ///< which triangle A is
225 Diag diag = Diag::NonUnit; ///< Unit: A's diagonal is taken as ones and not read
226};
227
228/// @brief Options for trsm(): solve \f$\mathrm{op}(A)X = \alpha B\f$ (Left) or \f$X\,\mathrm{op}(A) = \alpha B\f$ (Right).
229template <typename T>
231 T alpha = T(1); ///< scale of the right-hand side
232 Side side = Side::Left; ///< which side op(A) is on
233 Uplo uplo = Uplo::Lower; ///< which triangle A is
235 Diag diag = Diag::NonUnit; ///< Unit: A's diagonal is taken as ones and not read
236};
237
238/// @}
239
240// Library code under src/ops/ is templated on Backend and must call the `f<B>(ctx, ...)`
241// spelling: `f(ctx, ...)` would silently use ctx.backend() instead of B.
242
243namespace detail {
244template <typename M>
245struct dense_scalar {};
246template <typename T>
248 using type = T;
249};
250template <typename T>
252 using type = T;
253};
254template <typename M>
256
257template <typename M>
258concept DenseMatrixLike = requires { typename dense_scalar<std::remove_cvref_t<M>>::type; };
259
260} // namespace detail
261
262// Never collapse the two workspace spellings into `Span<std::byte> ws = {}` plus a
263// null check: sizing passes hand out empty spans over live matrices.
264// evidence: docs/design/api-conventions.md#api-conventions-two-workspace-spellings-never-a-defaulted-span
265
266#define BATCHLAS_DENSE_VIEW(T) MatrixView<T, MatrixFormat::Dense>
267
268/// @addtogroup api_options
269/// @{
270
271// ---- dense BLAS ------------------------------------------------------------
272
273/// @brief gemm with a compile-time backend; same contract as the Queue-deducing
274/// overload, without the pointer check.
275/// @tparam Back backend to run on
276template <Backend Back, detail::DenseMatrixLike MA, detail::DenseMatrixLike MB,
277 detail::DenseMatrixLike MC, typename T = detail::dense_scalar_t<MA>>
278inline Event gemm(Queue& ctx, const MA& A, const MB& B, const MC& C, const GemmOptions<T>& opts) {
279 using V = BATCHLAS_DENSE_VIEW(T);
280 return gemm<Back, T>(ctx, V(A), V(B), V(C), opts.alpha, opts.beta, opts.transA, opts.transB,
281 opts.precision);
282}
283
284/// @brief Batched matrix product \f$C_i := \alpha\,\mathrm{op}(A_i)\,\mathrm{op}(B_i) + \beta C_i\f$.
285///
286/// A batch whose items carry differing active extents is handled natively.
287/// @tparam MA,MB,MC `Matrix` or `MatrixView`, dense; `T` is deduced from `A`
288/// @param ctx queue; supplies the backend
289/// @param A `op(A)` is m x k per item
290/// @param B `op(B)` is k x n per item
291/// @param C m x n per item; read when `beta != 0`, overwritten
292/// @param opts alpha, beta, transA, transB, precision
293/// @return event of the last enqueued kernel
294/// @pre all operands have the same batch size
295/// @throws std::invalid_argument if a pointer is not reachable from the queue's device
296template <detail::DenseMatrixLike MA, detail::DenseMatrixLike MB, detail::DenseMatrixLike MC,
297 typename T = detail::dense_scalar_t<MA>>
298inline Event gemm(Queue& ctx, const MA& A, const MB& B, const MC& C, const GemmOptions<T>& opts) {
299 BATCHLAS_CHECK_ARGS(ctx, "gemm", A, B, C);
300 return with_backend_for<T>(ctx, "gemm",
301 [&](auto Back) { return gemm<Back.value>(ctx, A, B, C, opts); });
302}
303
304/// @brief gemv with a compile-time backend; same contract as the Queue-deducing
305/// overload, without the pointer check.
306/// @tparam Back backend to run on
307template <Backend Back, detail::DenseMatrixLike MA, typename T = detail::dense_scalar_t<MA>>
308inline Event gemv(Queue& ctx, const MA& A, const VectorView<T>& x, const VectorView<T>& y,
309 const GemvOptions<T>& opts) {
310 using V = BATCHLAS_DENSE_VIEW(T);
311 return gemv<Back, T>(ctx, V(A), x, y, opts.alpha, opts.beta, opts.transA);
312}
313
314/// @brief Batched matrix-vector product \f$y_i := \alpha\,\mathrm{op}(A_i)\,x_i + \beta y_i\f$.
315/// @param ctx queue; supplies the backend
316/// @param A `op(A)` is m x n per item
317/// @param x length n per item
318/// @param y length m per item; overwritten
319/// @param opts alpha, beta, transA
320/// @return event of the last enqueued kernel
321/// @throws std::invalid_argument if a pointer is not reachable from the queue's device
322template <detail::DenseMatrixLike MA, typename T = detail::dense_scalar_t<MA>>
323inline Event gemv(Queue& ctx, const MA& A, const VectorView<T>& x, const VectorView<T>& y,
324 const GemvOptions<T>& opts) {
325 BATCHLAS_CHECK_ARGS(ctx, "gemv", A, x, y);
326 return with_backend_for<T>(ctx, "gemv",
327 [&](auto Back) { return gemv<Back.value>(ctx, A, x, y, opts); });
328}
329
330/// @brief symm with a compile-time backend; same contract as the Queue-deducing
331/// overload, without the pointer check.
332/// @tparam Back backend to run on
333template <Backend Back, detail::DenseMatrixLike MA, detail::DenseMatrixLike MB,
334 detail::DenseMatrixLike MC, typename T = detail::dense_scalar_t<MA>>
335inline Event symm(Queue& ctx, const MA& A, const MB& B, const MC& C, const SymmOptions<T>& opts) {
336 using V = BATCHLAS_DENSE_VIEW(T);
337 return symm<Back, T>(ctx, V(A), V(B), V(C), opts.alpha, opts.beta, opts.side, opts.uplo);
338}
339
340/// @brief Batched symmetric product \f$C := \alpha AB + \beta C\f$ (Left) or \f$\alpha BA + \beta C\f$ (Right).
341/// @param A symmetric, m x m (Left) or n x n (Right); only the `uplo` triangle is read
342/// @param B m x n per item
343/// @param C m x n per item; overwritten
344/// @param opts alpha, beta, side, uplo
345/// @return event of the last enqueued kernel
346/// @note Real `T` only; use hemm() for complex.
347/// @throws std::invalid_argument if a pointer is not reachable from the queue's device
348template <detail::DenseMatrixLike MA, detail::DenseMatrixLike MB, detail::DenseMatrixLike MC,
349 typename T = detail::dense_scalar_t<MA>>
350inline Event symm(Queue& ctx, const MA& A, const MB& B, const MC& C, const SymmOptions<T>& opts) {
351 BATCHLAS_CHECK_ARGS(ctx, "symm", A, B, C);
352 return with_backend_for<T>(ctx, "symm",
353 [&](auto Back) { return symm<Back.value>(ctx, A, B, C, opts); });
354}
355
356/// @brief hemm with a compile-time backend; same contract as the Queue-deducing
357/// overload, without the pointer check.
358/// @tparam Back backend to run on
359template <Backend Back, detail::DenseMatrixLike MA, detail::DenseMatrixLike MB,
360 detail::DenseMatrixLike MC, typename T = detail::dense_scalar_t<MA>>
361 requires ComplexScalar<T>
362inline Event hemm(Queue& ctx, const MA& A, const MB& B, const MC& C, const HemmOptions<T>& opts) {
363 using V = BATCHLAS_DENSE_VIEW(T);
364 return hemm<Back, T>(ctx, V(A), V(B), V(C), opts.alpha, opts.beta, opts.side, opts.uplo);
365}
366
367/// @brief Batched Hermitian product; as symm() with A Hermitian.
368///
369/// The unread triangle is taken as the conjugate transpose of the `uplo` one and
370/// the diagonal's imaginary part as zero, whatever is stored there.
371/// @param opts alpha, beta, side, uplo
372/// @return event of the last enqueued kernel
373/// @note Complex `T` only.
374/// @throws std::invalid_argument if a pointer is not reachable from the queue's device
375template <detail::DenseMatrixLike MA, detail::DenseMatrixLike MB, detail::DenseMatrixLike MC,
376 typename T = detail::dense_scalar_t<MA>>
377 requires ComplexScalar<T>
378inline Event hemm(Queue& ctx, const MA& A, const MB& B, const MC& C, const HemmOptions<T>& opts) {
379 BATCHLAS_CHECK_ARGS(ctx, "hemm", A, B, C);
380 return with_backend_for<T>(ctx, "hemm",
381 [&](auto Back) { return hemm<Back.value>(ctx, A, B, C, opts); });
382}
383
384/// @brief herk with a compile-time backend; same contract as the Queue-deducing
385/// overload, without the pointer check.
386/// @tparam Back backend to run on
387template <Backend Back, detail::DenseMatrixLike MA, detail::DenseMatrixLike MC,
388 typename T = detail::dense_scalar_t<MA>>
389 requires ComplexScalar<T>
390inline Event herk(Queue& ctx, const MA& A, const MC& C, const HerkOptions<T>& opts) {
391 using V = BATCHLAS_DENSE_VIEW(T);
392 return herk<Back, T>(ctx, V(A), V(C), opts.alpha, opts.beta, opts.uplo, opts.trans);
393}
394
395/// @brief Batched Hermitian rank-k update \f$C := \alpha AA^H + \beta C\f$ (NoTrans) or \f$\alpha A^HA + \beta C\f$ (ConjTrans).
396/// @param A n x k (NoTrans) or k x n (ConjTrans) per item
397/// @param C n x n per item; only the `uplo` triangle is written, the other is
398/// left exactly as it was (mirror it with `hermitize` if needed)
399/// @param opts real alpha and beta, uplo, trans
400/// @return event of the last enqueued kernel
401/// @note Complex `T` only.
402/// @throws std::invalid_argument if a pointer is not reachable from the queue's device
403template <detail::DenseMatrixLike MA, detail::DenseMatrixLike MC,
404 typename T = detail::dense_scalar_t<MA>>
405 requires ComplexScalar<T>
406inline Event herk(Queue& ctx, const MA& A, const MC& C, const HerkOptions<T>& opts) {
407 BATCHLAS_CHECK_ARGS(ctx, "herk", A, C);
408 return with_backend_for<T>(ctx, "herk",
409 [&](auto Back) { return herk<Back.value>(ctx, A, C, opts); });
410}
411
412/// @brief her2k with a compile-time backend; same contract as the Queue-deducing
413/// overload, without the pointer check.
414/// @tparam Back backend to run on
415template <Backend Back, detail::DenseMatrixLike MA, detail::DenseMatrixLike MB,
416 detail::DenseMatrixLike MC, typename T = detail::dense_scalar_t<MA>>
417 requires ComplexScalar<T>
418inline Event her2k(Queue& ctx, const MA& A, const MB& B, const MC& C,
419 const Her2kOptions<T>& opts) {
420 using V = BATCHLAS_DENSE_VIEW(T);
421 return her2k<Back, T>(ctx, V(A), V(B), V(C), opts.alpha, opts.beta, opts.uplo, opts.trans);
422}
423
424/// @brief Batched Hermitian rank-2k update \f$C := \alpha\,\mathrm{op}(A)\,\mathrm{op}(B)^H + \bar\alpha\,\mathrm{op}(B)\,\mathrm{op}(A)^H + \beta C\f$.
425/// @param A,B n x k (NoTrans) or k x n (ConjTrans) per item
426/// @param C n x n per item; only the `uplo` triangle is written, real diagonal
427/// @param opts complex alpha, real beta, uplo, trans
428/// @return event of the last enqueued kernel
429/// @note Complex `T` only.
430/// @throws std::invalid_argument if a pointer is not reachable from the queue's device
431template <detail::DenseMatrixLike MA, detail::DenseMatrixLike MB, detail::DenseMatrixLike MC,
432 typename T = detail::dense_scalar_t<MA>>
433 requires ComplexScalar<T>
434inline Event her2k(Queue& ctx, const MA& A, const MB& B, const MC& C,
435 const Her2kOptions<T>& opts) {
436 BATCHLAS_CHECK_ARGS(ctx, "her2k", A, B, C);
437 return with_backend_for<T>(ctx, "her2k",
438 [&](auto Back) { return her2k<Back.value>(ctx, A, B, C, opts); });
439}
440
441/// @brief syrk with a compile-time backend; same contract as the Queue-deducing
442/// overload, without the pointer check.
443/// @tparam Back backend to run on
444template <Backend Back, detail::DenseMatrixLike MA, detail::DenseMatrixLike MC,
445 typename T = detail::dense_scalar_t<MA>>
446inline Event syrk(Queue& ctx, const MA& A, const MC& C, const SyrkOptions<T>& opts) {
447 using V = BATCHLAS_DENSE_VIEW(T);
448 return syrk<Back, T>(ctx, V(A), V(C), opts.alpha, opts.beta, opts.uplo, opts.trans);
449}
450
451/// @brief Batched symmetric rank-k update \f$C := \alpha AA^T + \beta C\f$ (NoTrans) or \f$\alpha A^TA + \beta C\f$ (Trans).
452/// @param A n x k (NoTrans) or k x n (Trans) per item
453/// @param C n x n per item; only the `uplo` triangle is written, the other is
454/// left exactly as it was (mirror it with `symmetrize` if needed)
455/// @param opts alpha, beta, uplo, trans
456/// @return event of the last enqueued kernel
457/// @note Real `T` only; use herk() for complex.
458/// @throws std::invalid_argument if a pointer is not reachable from the queue's device
459template <detail::DenseMatrixLike MA, detail::DenseMatrixLike MC,
460 typename T = detail::dense_scalar_t<MA>>
461inline Event syrk(Queue& ctx, const MA& A, const MC& C, const SyrkOptions<T>& opts) {
462 BATCHLAS_CHECK_ARGS(ctx, "syrk", A, C);
463 return with_backend_for<T>(ctx, "syrk",
464 [&](auto Back) { return syrk<Back.value>(ctx, A, C, opts); });
465}
466
467/// @brief syr2k with a compile-time backend; same contract as the Queue-deducing
468/// overload, without the pointer check.
469/// @tparam Back backend to run on
470template <Backend Back, detail::DenseMatrixLike MA, detail::DenseMatrixLike MB,
471 detail::DenseMatrixLike MC, typename T = detail::dense_scalar_t<MA>>
472inline Event syr2k(Queue& ctx, const MA& A, const MB& B, const MC& C,
473 const Syr2kOptions<T>& opts) {
474 using V = BATCHLAS_DENSE_VIEW(T);
475 return syr2k<Back, T>(ctx, V(A), V(B), V(C), opts.alpha, opts.beta, opts.uplo, opts.trans);
476}
477
478/// @brief Batched symmetric rank-2k update \f$C := \alpha(\mathrm{op}(A)\,\mathrm{op}(B)^T + \mathrm{op}(B)\,\mathrm{op}(A)^T) + \beta C\f$.
479/// @param A,B n x k (NoTrans) or k x n (Trans) per item, k > 0
480/// @param C n x n per item; only the `uplo` triangle is written
481/// @param opts alpha, beta, uplo, trans
482/// @return event of the last enqueued kernel
483/// @note Real `T` only; use her2k() for complex.
484/// @throws std::invalid_argument if a pointer is not reachable from the queue's device
485template <detail::DenseMatrixLike MA, detail::DenseMatrixLike MB, detail::DenseMatrixLike MC,
486 typename T = detail::dense_scalar_t<MA>>
487inline Event syr2k(Queue& ctx, const MA& A, const MB& B, const MC& C,
488 const Syr2kOptions<T>& opts) {
489 BATCHLAS_CHECK_ARGS(ctx, "syr2k", A, B, C);
490 return with_backend_for<T>(ctx, "syr2k",
491 [&](auto Back) { return syr2k<Back.value>(ctx, A, B, C, opts); });
492}
493
494/// @brief trmm with a compile-time backend; same contract as the Queue-deducing
495/// overload, without the pointer check.
496/// @tparam Back backend to run on
497template <Backend Back, detail::DenseMatrixLike MA, detail::DenseMatrixLike MB,
498 detail::DenseMatrixLike MC, typename T = detail::dense_scalar_t<MA>>
499inline Event trmm(Queue& ctx, const MA& A, const MB& B, const MC& C, const TrmmOptions<T>& opts) {
500 using V = BATCHLAS_DENSE_VIEW(T);
501 return trmm<Back, T>(ctx, V(A), V(B), V(C), opts.alpha, opts.side, opts.uplo, opts.trans,
502 opts.diag);
503}
504
505/// @brief Batched triangular product, out of place: \f$C := \alpha\,\mathrm{op}(A)\,B\f$ (Left) or \f$\alpha B\,\mathrm{op}(A)\f$ (Right).
506///
507/// Unlike reference BLAS `?trmm`, the result goes to `C`; `B` is not modified.
508/// @param A triangular, m x m (Left) or n x n (Right); `uplo` and `diag` describe it
509/// @param B m x n per item; read only
510/// @param C m x n per item; overwritten
511/// @param opts alpha, side, uplo, trans, diag
512/// @return event of the last enqueued kernel
513/// @throws std::invalid_argument if a pointer is not reachable from the queue's device
514template <detail::DenseMatrixLike MA, detail::DenseMatrixLike MB, detail::DenseMatrixLike MC,
515 typename T = detail::dense_scalar_t<MA>>
516inline Event trmm(Queue& ctx, const MA& A, const MB& B, const MC& C, const TrmmOptions<T>& opts) {
517 BATCHLAS_CHECK_ARGS(ctx, "trmm", A, B, C);
518 return with_backend_for<T>(ctx, "trmm",
519 [&](auto Back) { return trmm<Back.value>(ctx, A, B, C, opts); });
520}
521
522/// @brief trsm with a compile-time backend; same contract as the Queue-deducing
523/// overload, without the pointer check.
524/// @tparam Back backend to run on
525template <Backend Back, detail::DenseMatrixLike MA, detail::DenseMatrixLike MB,
526 typename T = detail::dense_scalar_t<MA>>
527inline Event trsm(Queue& ctx, const MA& A, const MB& B, const TrsmOptions<T>& opts) {
528 using V = BATCHLAS_DENSE_VIEW(T);
529 return trsm<Back, T>(ctx, V(A), V(B), opts.alpha, opts.side, opts.uplo, opts.trans, opts.diag);
530}
531
532/// @brief Batched triangular solve \f$\mathrm{op}(A)X = \alpha B\f$ (Left) or \f$X\,\mathrm{op}(A) = \alpha B\f$ (Right), in place.
533/// @param A triangular, m x m (Left) or n x n (Right); `uplo` and `diag` describe it
534/// @param B m x n per item; overwritten with X
535/// @param opts alpha, side, uplo, trans, diag
536/// @return event of the last enqueued kernel
537/// @throws std::invalid_argument if a pointer is not reachable from the queue's device
538template <detail::DenseMatrixLike MA, detail::DenseMatrixLike MB,
539 typename T = detail::dense_scalar_t<MA>>
540inline Event trsm(Queue& ctx, const MA& A, const MB& B, const TrsmOptions<T>& opts) {
541 BATCHLAS_CHECK_ARGS(ctx, "trsm", A, B);
542 return with_backend_for<T>(ctx, "trsm",
543 [&](auto Back) { return trsm<Back.value>(ctx, A, B, opts); });
544}
545
546// ---- dense LAPACK ----------------------------------------------------------
547
548/// @brief Options for potrf(): Cholesky \f$A = LL^H\f$ (Lower) or \f$U^HU\f$ (Upper).
550 Uplo uplo = Uplo::Lower; ///< triangle read and overwritten with the factor
551 /// Per-item status, one int32 per batch item: 0 = factorised, > 0 = the order of
552 /// the leading minor that is not positive definite. Empty (the default) reports
553 /// nothing; otherwise device-accessible, at least `batch_size` long, written in place.
555};
556
557/// @brief Options for getrs(): solve \f$\mathrm{op}(A)X = B\f$ with getrf's factors.
561
562/// @brief Options for syev(): symmetric/Hermitian eigendecomposition.
564 JobType jobz = JobType::EigenVectors; ///< eigenvectors too, or eigenvalues only
565 Uplo uplo = Uplo::Lower; ///< triangle of A that is read
566};
567
568/// @brief potrf with a compile-time backend and a caller workspace.
569/// @tparam B backend to run on
570/// @param ws at least `potrf_buffer_size<B, T>(ctx, A, opts.uplo)` bytes
571/// @throws batchlas::invalid_argument as the Queue-deducing overload
572template <Backend B, detail::DenseMatrixLike MA, typename T = detail::dense_scalar_t<MA>>
573inline Event potrf(Queue& ctx, const MA& A, const PotrfOptions& opts, Span<std::byte> ws) {
574 using V = BATCHLAS_DENSE_VIEW(T);
575 detail::require_square("potrf", "A", A);
576 detail::require_info_span("potrf", opts.info.size(), static_cast<size_t>(A.batch_size()));
577 return potrf<B, T>(ctx, V(A), opts.uplo, ws, opts.info);
578}
579
580/// @brief potrf with a compile-time backend; workspace leased from the arena.
581/// @tparam B backend to run on
582/// @throws batchlas::invalid_argument if `A` is not square or `opts.info` is non-empty and short
583template <Backend B, detail::DenseMatrixLike MA, typename T = detail::dense_scalar_t<MA>>
584inline Event potrf(Queue& ctx, const MA& A, const PotrfOptions& opts) {
585 using V = BATCHLAS_DENSE_VIEW(T);
586 detail::require_square("potrf", "A", A);
587 detail::require_info_span("potrf", opts.info.size(), static_cast<size_t>(A.batch_size()));
588 auto lease = ctx.workspace(potrf_buffer_size<B, T>(ctx, V(A), opts.uplo));
589 return potrf<B, T>(ctx, V(A), opts.uplo, lease.span(), opts.info);
590}
591
592/// @brief Batched Cholesky factorisation with a caller-owned workspace.
593///
594/// Same contract as the arena overload; the call stays asynchronous on any queue.
595/// @param ws device-accessible scratch of at least `potrf_buffer_size` bytes;
596/// must outlive the kernels
597/// @warning With an empty option struct, write `PotrfOptions{}`: a bare `{}` is
598/// rejected as ambiguous (it would otherwise mean `Uplo::Upper`).
599template <detail::DenseMatrixLike MA, typename T = detail::dense_scalar_t<MA>>
600inline Event potrf(Queue& ctx, const MA& A, const PotrfOptions& opts, Span<std::byte> ws) {
601 BATCHLAS_CHECK_ARGS(ctx, "potrf", A, ws, opts.info);
602 detail::require_square("potrf", "A", A);
603 detail::require_info_span("potrf", opts.info.size(), static_cast<size_t>(A.batch_size()));
604 return with_backend_for<T>(ctx, "potrf",
605 [&](auto Back) { return potrf<Back.value>(ctx, A, opts, ws); });
606}
607
608/// @brief Batched Cholesky factorisation \f$A_i = L_iL_i^H\f$ (Lower) or \f$U_i^HU_i\f$ (Upper), in place.
609///
610/// Workspace is leased from the queue's arena (blocking on an out-of-order queue).
611/// @param ctx queue; supplies the backend and the arena
612/// @param A n x n per item; the `uplo` triangle is read and overwritten with the
613/// factor, the other triangle is not referenced
614/// @param opts uplo (default Lower) and an optional per-item `info` span
615/// @return event of the last enqueued kernel
616/// @note A matrix that is not positive definite yields a non-zero `info` entry and
617/// an undefined factor for that item; no exception.
618/// @throws batchlas::invalid_argument if `A` is not square or `opts.info` is non-empty
619/// and shorter than the batch
620/// @throws std::invalid_argument if a pointer is not reachable from the queue's device
621template <detail::DenseMatrixLike MA, typename T = detail::dense_scalar_t<MA>>
622inline Event potrf(Queue& ctx, const MA& A, const PotrfOptions& opts = {}) {
623 BATCHLAS_CHECK_ARGS(ctx, "potrf", A, opts.info);
624 detail::require_square("potrf", "A", A);
625 detail::require_info_span("potrf", opts.info.size(), static_cast<size_t>(A.batch_size()));
626 return with_backend_for<T>(ctx, "potrf",
627 [&](auto Back) { return potrf<Back.value>(ctx, A, opts); });
628}
629
630/// @}
631
632namespace detail {
633// Trap guard: `potrf(ctx, A, {}, ws)` matched Uplo{} == Upper exactly and silently
634// factorised the wrong triangle. A third exact match for `{}` makes it ambiguous.
635// evidence: docs/design/api-conventions.md#api-conventions-the-bare-braces-potrf-trap
636enum class EmptyBracesAreAmbiguous {};
637} // namespace detail
638
639/// @addtogroup api_options
640/// @{
641
642/// @brief Deleted: makes `potrf<B>(ctx, A, {}, ws)` ambiguous. Write `PotrfOptions{}`.
643template <Backend B, detail::DenseMatrixLike MA, typename T = detail::dense_scalar_t<MA>>
644Event potrf(Queue&, const MA&, detail::EmptyBracesAreAmbiguous, Span<std::byte>) = delete;
645
646/// @brief Deleted: makes `potrf(ctx, A, {}, ws)` ambiguous. Write `PotrfOptions{}`.
647template <detail::DenseMatrixLike MA, typename T = detail::dense_scalar_t<MA>>
648Event potrf(Queue&, const MA&, detail::EmptyBracesAreAmbiguous, Span<std::byte>) = delete;
649
650// getrf, getri, geqrf, orgqr: arena spelling only; a workspace parameter here
651// would be ambiguous with the positional call.
652/// @brief getrf with a compile-time backend; workspace leased from the arena.
653/// @tparam B backend to run on
654/// @throws batchlas::invalid_argument as the Queue-deducing overload
655template <Backend B, detail::DenseMatrixLike MA, typename T = detail::dense_scalar_t<MA>>
656inline Event getrf(Queue& ctx, const MA& A, Span<int64_t> pivots, Span<int32_t> info = {}) {
657 using V = BATCHLAS_DENSE_VIEW(T);
658 detail::require_square("getrf", "A", A);
659 detail::require_span_at_least("getrf", "pivots", pivots.size(),
660 static_cast<size_t>(A.rows()) * A.batch_size());
661 detail::require_info_span("getrf", info.size(), static_cast<size_t>(A.batch_size()));
662 auto lease = ctx.workspace(getrf_buffer_size<B, T>(ctx, V(A)));
663 return getrf<B, T>(ctx, V(A), pivots, lease.span(), info);
664}
665
666/// @brief Batched LU factorisation with partial pivoting, \f$A_i = P_iL_iU_i\f$, in place.
667///
668/// Workspace is leased from the queue's arena. `L` (unit diagonal, implicit) and
669/// `U` overwrite `A`.
670/// @param ctx queue; supplies the backend and the arena
671/// @param A n x n per item
672/// @param pivots at least `n * batch_size` entries; pass it unchanged to getrs() or
673/// getri() (see the pivot format note on the positional getrf)
674/// @param info optional per-item status: 0 = success, > 0 = index of the first
675/// exactly-zero pivot; empty reports nothing
676/// @return event of the last enqueued kernel
677/// @throws batchlas::invalid_argument if `A` is not square or a span is too short
678/// @throws std::invalid_argument if a pointer is not reachable from the queue's device
679template <detail::DenseMatrixLike MA, typename T = detail::dense_scalar_t<MA>>
680inline Event getrf(Queue& ctx, const MA& A, Span<int64_t> pivots, Span<int32_t> info = {}) {
681 BATCHLAS_CHECK_ARGS(ctx, "getrf", A, pivots, info);
682 detail::require_square("getrf", "A", A);
683 detail::require_span_at_least("getrf", "pivots", pivots.size(),
684 static_cast<size_t>(A.rows()) * A.batch_size());
685 detail::require_info_span("getrf", info.size(), static_cast<size_t>(A.batch_size()));
686 return with_backend_for<T>(ctx, "getrf",
687 [&](auto Back) { return getrf<Back.value>(ctx, A, pivots, info); });
688}
689
690/// @brief getrs with a compile-time backend and a caller workspace.
691/// @tparam B backend to run on
692/// @throws batchlas::invalid_argument as the Queue-deducing overload
694 typename T = detail::dense_scalar_t<MA>>
695inline Event getrs(Queue& ctx, const MA& A, const MB& B_, Span<int64_t> pivots,
696 const GetrsOptions& opts, Span<std::byte> ws) {
697 using V = BATCHLAS_DENSE_VIEW(T);
698 detail::require_square("getrs", "A", A);
699 detail::require_same_rows("getrs", "A", A, "B", B_);
700 detail::require_same_batch("getrs", "A", A, "B", B_);
701 detail::require_span_at_least("getrs", "pivots", pivots.size(),
702 static_cast<size_t>(A.rows()) * A.batch_size());
703 return getrs<B, T>(ctx, V(A), V(B_), opts.trans, pivots, ws);
704}
705
706/// @brief getrs with a compile-time backend; workspace leased from the arena.
707/// @tparam B backend to run on
708/// @throws batchlas::invalid_argument as the Queue-deducing overload
709template <Backend B, detail::DenseMatrixLike MA, detail::DenseMatrixLike MB,
710 typename T = detail::dense_scalar_t<MA>>
711inline Event getrs(Queue& ctx, const MA& A, const MB& B_, Span<int64_t> pivots,
712 const GetrsOptions& opts) {
713 using V = BATCHLAS_DENSE_VIEW(T);
714 detail::require_square("getrs", "A", A);
715 detail::require_same_rows("getrs", "A", A, "B", B_);
716 detail::require_same_batch("getrs", "A", A, "B", B_);
717 detail::require_span_at_least("getrs", "pivots", pivots.size(),
718 static_cast<size_t>(A.rows()) * A.batch_size());
719 auto lease = ctx.workspace(getrs_buffer_size<B, T>(ctx, V(A), V(B_), opts.trans));
720 return getrs<B, T>(ctx, V(A), V(B_), opts.trans, pivots, lease.span());
721}
722
723/// @brief Batched LU solve with a caller-owned workspace; otherwise as the arena overload.
724/// @param ws device-accessible scratch of at least `getrs_buffer_size` bytes
725template <detail::DenseMatrixLike MA, detail::DenseMatrixLike MB,
726 typename T = detail::dense_scalar_t<MA>>
727inline Event getrs(Queue& ctx, const MA& A, const MB& B_, Span<int64_t> pivots,
728 const GetrsOptions& opts, Span<std::byte> ws) {
729 BATCHLAS_CHECK_ARGS(ctx, "getrs", A, B_, pivots, ws);
730 detail::require_square("getrs", "A", A);
731 detail::require_same_rows("getrs", "A", A, "B", B_);
732 detail::require_same_batch("getrs", "A", A, "B", B_);
733 detail::require_span_at_least("getrs", "pivots", pivots.size(),
734 static_cast<size_t>(A.rows()) * A.batch_size());
735 return with_backend_for<T>(
736 ctx, "getrs", [&](auto Back) { return getrs<Back.value>(ctx, A, B_, pivots, opts, ws); });
737}
738
739/// @brief Batched LU solve \f$\mathrm{op}(A_i)X_i = B_i\f$ from getrf()'s factors, in place.
740///
741/// Workspace is leased from the queue's arena. No status is reported: a singular
742/// factor produces non-finite or meaningless `X` without an exception.
743/// @param A n x n per item, already factorised by getrf()
744/// @param B_ n x nrhs per item; overwritten with X
745/// @param pivots getrf()'s pivots, at least `n * batch_size` entries
746/// @param opts trans
747/// @return event of the last enqueued kernel
748/// @throws batchlas::invalid_argument if `A` is not square, `A` and `B_` differ in rows
749/// or batch size, or `pivots` is too short
750/// @throws std::invalid_argument if a pointer is not reachable from the queue's device
751template <detail::DenseMatrixLike MA, detail::DenseMatrixLike MB,
752 typename T = detail::dense_scalar_t<MA>>
753inline Event getrs(Queue& ctx, const MA& A, const MB& B_, Span<int64_t> pivots,
754 const GetrsOptions& opts = {}) {
755 BATCHLAS_CHECK_ARGS(ctx, "getrs", A, B_, pivots);
756 detail::require_square("getrs", "A", A);
757 detail::require_same_rows("getrs", "A", A, "B", B_);
758 detail::require_same_batch("getrs", "A", A, "B", B_);
759 detail::require_span_at_least("getrs", "pivots", pivots.size(),
760 static_cast<size_t>(A.rows()) * A.batch_size());
761 return with_backend_for<T>(ctx, "getrs",
762 [&](auto Back) { return getrs<Back.value>(ctx, A, B_, pivots, opts); });
763}
764
765/// @brief getri with a compile-time backend; workspace leased from the arena.
766/// @tparam B backend to run on
767/// @throws batchlas::invalid_argument as the Queue-deducing overload
769 typename T = detail::dense_scalar_t<MA>>
770inline Event getri(Queue& ctx, const MA& A, const MB& Ainv, Span<int64_t> pivots,
771 Span<int32_t> info = {}) {
772 using V = BATCHLAS_DENSE_VIEW(T);
773 detail::require_square("getri", "A", A);
774 detail::require_square("getri", "Ainv", Ainv);
775 detail::require_same_rows("getri", "A", A, "Ainv", Ainv);
776 detail::require_same_batch("getri", "A", A, "Ainv", Ainv);
777 detail::require_span_at_least("getri", "pivots", pivots.size(),
778 static_cast<size_t>(A.rows()) * A.batch_size());
779 detail::require_info_span("getri", info.size(), static_cast<size_t>(A.batch_size()));
780 auto lease = ctx.workspace(getri_buffer_size<B, T>(ctx, V(A)));
781 return getri<B, T>(ctx, V(A), V(Ainv), pivots, lease.span(), info);
782}
783
784/// @brief Batched inverse \f$A_{\mathrm{inv},i} := A_i^{-1}\f$ from getrf()'s factors.
785///
786/// Workspace is leased from the queue's arena. `A` is read only.
787/// @param A n x n per item, already factorised by getrf()
788/// @param Ainv n x n per item; overwritten with the inverse
789/// @param pivots getrf()'s pivots, at least `n * batch_size` entries
790/// @param info optional per-item status (0 = success); empty reports nothing
791/// @return event of the last enqueued kernel
792/// @throws batchlas::invalid_argument on a non-square or mismatched operand or a short span
793/// @throws std::invalid_argument if a pointer is not reachable from the queue's device
795 typename T = detail::dense_scalar_t<MA>>
796inline Event getri(Queue& ctx, const MA& A, const MB& Ainv, Span<int64_t> pivots,
797 Span<int32_t> info = {}) {
798 BATCHLAS_CHECK_ARGS(ctx, "getri", A, Ainv, pivots, info);
799 detail::require_square("getri", "A", A);
800 detail::require_square("getri", "Ainv", Ainv);
801 detail::require_same_rows("getri", "A", A, "Ainv", Ainv);
802 detail::require_same_batch("getri", "A", A, "Ainv", Ainv);
803 detail::require_span_at_least("getri", "pivots", pivots.size(),
804 static_cast<size_t>(A.rows()) * A.batch_size());
805 detail::require_info_span("getri", info.size(), static_cast<size_t>(A.batch_size()));
806 return with_backend_for<T>(ctx, "getri",
807 [&](auto Back) { return getri<Back.value>(ctx, A, Ainv, pivots, info); });
808}
809
810/// @brief geqrf with a compile-time backend; workspace leased from the arena.
811/// @tparam B backend to run on
812template <Backend B, detail::DenseMatrixLike MA, typename T = detail::dense_scalar_t<MA>>
813inline Event geqrf(Queue& ctx, const MA& A, Span<T> tau) {
814 using V = BATCHLAS_DENSE_VIEW(T);
815 detail::require_span_at_least("geqrf", "tau", tau.size(),
816 static_cast<size_t>(std::min(A.rows(), A.cols())) * A.batch_size());
817 auto lease = ctx.workspace(geqrf_buffer_size<B, T>(ctx, V(A), tau));
818 return geqrf<B, T>(ctx, V(A), tau, lease.span());
819}
820
821/// @brief Batched Householder QR, \f$A_i = Q_iR_i\f$, in place.
822///
823/// `R` overwrites the upper triangle of `A`, the Householder vectors are stored
824/// below it, and their scalars go to `tau`. Workspace is leased from the arena.
825/// @param A m x n per item (rectangular allowed)
826/// @param tau at least `min(m, n) * batch_size` entries; item i's scalars start at
827/// `i * min(m, n)`
828/// @return event of the last enqueued kernel
829/// @throws batchlas::invalid_argument if `tau` is too short
830/// @throws std::invalid_argument if a pointer is not reachable from the queue's device
831template <detail::DenseMatrixLike MA, typename T = detail::dense_scalar_t<MA>>
832inline Event geqrf(Queue& ctx, const MA& A, Span<T> tau) {
833 BATCHLAS_CHECK_ARGS(ctx, "geqrf", A, tau);
834 // No squareness check (rectangular A is the point); the tau stride is fixed.
835 detail::require_span_at_least("geqrf", "tau", tau.size(),
836 static_cast<size_t>(std::min(A.rows(), A.cols())) * A.batch_size());
837 return with_backend_for<T>(ctx, "geqrf",
838 [&](auto Back) { return geqrf<Back.value>(ctx, A, tau); });
839}
840
841/// @brief orgqr with a compile-time backend; workspace leased from the arena.
842/// @tparam B backend to run on
843template <Backend B, detail::DenseMatrixLike MA, typename T = detail::dense_scalar_t<MA>>
844inline Event orgqr(Queue& ctx, const MA& A, Span<T> tau) {
845 using V = BATCHLAS_DENSE_VIEW(T);
846 detail::require_span_at_least("orgqr", "tau", tau.size(),
847 static_cast<size_t>(std::min(A.rows(), A.cols())) * A.batch_size());
848 auto lease = ctx.workspace(orgqr_buffer_size<B, T>(ctx, V(A), tau));
849 return orgqr<B, T>(ctx, V(A), tau, lease.span());
850}
851
852/// @brief Form the explicit Q of geqrf() in place.
853///
854/// Overwrites `A` (holding geqrf()'s reflectors) with the first min(m, n) columns
855/// of Q. Workspace is leased from the arena.
856/// @param A m x n per item, as left by geqrf()
857/// @param tau geqrf()'s scalars, at least `min(m, n) * batch_size` entries
858/// @return event of the last enqueued kernel
859/// @throws batchlas::invalid_argument if `tau` is too short
860/// @throws std::invalid_argument if a pointer is not reachable from the queue's device
861template <detail::DenseMatrixLike MA, typename T = detail::dense_scalar_t<MA>>
862inline Event orgqr(Queue& ctx, const MA& A, Span<T> tau) {
863 BATCHLAS_CHECK_ARGS(ctx, "orgqr", A, tau);
864 detail::require_span_at_least("orgqr", "tau", tau.size(),
865 static_cast<size_t>(std::min(A.rows(), A.cols())) * A.batch_size());
866 return with_backend_for<T>(ctx, "orgqr",
867 [&](auto Back) { return orgqr<Back.value>(ctx, A, tau); });
868}
869
870/// @brief syev with a compile-time backend and a caller workspace.
871/// @tparam B backend to run on
872/// @throws batchlas::invalid_argument as the Queue-deducing overload
873template <Backend B, detail::DenseMatrixLike MA, typename T = detail::dense_scalar_t<MA>>
874inline Event syev(Queue& ctx, const MA& A, Span<typename base_type<T>::type> W,
875 const SyevOptions& opts, Span<std::byte> ws) {
876 using V = BATCHLAS_DENSE_VIEW(T);
877 detail::require_square("syev", "A", A);
878 detail::require_span_at_least("syev", "W", W.size(),
879 static_cast<size_t>(A.rows()) * A.batch_size());
880 return syev<B, T>(ctx, V(A), W, opts.jobz, opts.uplo, ws);
881}
882
883/// @brief syev with a compile-time backend; workspace leased from the arena.
884/// @tparam B backend to run on
885/// @throws batchlas::invalid_argument as the Queue-deducing overload
886template <Backend B, detail::DenseMatrixLike MA, typename T = detail::dense_scalar_t<MA>>
887inline Event syev(Queue& ctx, const MA& A, Span<typename base_type<T>::type> W,
888 const SyevOptions& opts) {
889 using V = BATCHLAS_DENSE_VIEW(T);
890 detail::require_square("syev", "A", A);
891 detail::require_span_at_least("syev", "W", W.size(),
892 static_cast<size_t>(A.rows()) * A.batch_size());
893 auto lease = ctx.workspace(syev_buffer_size<B, T>(ctx, V(A), W, opts.jobz, opts.uplo));
894 return syev<B, T>(ctx, V(A), W, opts.jobz, opts.uplo, lease.span());
895}
896
897/// @brief Batched symmetric/Hermitian eigensolver with a caller-owned workspace;
898/// otherwise as the arena overload.
899/// @param ws device-accessible scratch of at least `syev_buffer_size` bytes
900template <detail::DenseMatrixLike MA, typename T = detail::dense_scalar_t<MA>>
901inline Event syev(Queue& ctx, const MA& A, Span<typename base_type<T>::type> W,
902 const SyevOptions& opts, Span<std::byte> ws) {
903 BATCHLAS_CHECK_ARGS(ctx, "syev", A, W, ws);
904 detail::require_square("syev", "A", A);
905 detail::require_span_at_least("syev", "W", W.size(),
906 static_cast<size_t>(A.rows()) * A.batch_size());
907 return with_backend_for<T>(ctx, "syev",
908 [&](auto Back) { return syev<Back.value>(ctx, A, W, opts, ws); });
909}
910
911/// @brief Batched symmetric/Hermitian eigendecomposition \f$A_i = V_i\Lambda_iV_i^H\f$.
912///
913/// Workspace is leased from the queue's arena. This spelling reports no per-item
914/// convergence status; use the positional syev() with an `info` span for that.
915/// @param A n x n per item; the `uplo` triangle is read. Overwritten with the
916/// eigenvectors (columns) when `opts.jobz == JobType::EigenVectors`,
917/// left unspecified otherwise
918/// @param W real, at least `n * batch_size` entries; eigenvalues ascending per item
919/// @param opts jobz, uplo
920/// @return event of the last enqueued kernel
921/// @throws batchlas::invalid_argument if `A` is not square or `W` is too short
922/// @throws std::invalid_argument if a pointer is not reachable from the queue's device
923template <detail::DenseMatrixLike MA, typename T = detail::dense_scalar_t<MA>>
924inline Event syev(Queue& ctx, const MA& A, Span<typename base_type<T>::type> W,
925 const SyevOptions& opts = {}) {
926 BATCHLAS_CHECK_ARGS(ctx, "syev", A, W);
927 detail::require_square("syev", "A", A);
928 detail::require_span_at_least("syev", "W", W.size(),
929 static_cast<size_t>(A.rows()) * A.batch_size());
930 return with_backend_for<T>(ctx, "syev",
931 [&](auto Back) { return syev<Back.value>(ctx, A, W, opts); });
932}
933
934// ---- ormqr and gesvd -------------------------------------------------------
935// As with getrs, the option forms do not mirror the positional parameter order.
936
937/// @brief Options for ormqr(): apply geqrf()'s Q, \f$C := \mathrm{op}(Q)C\f$ (Left) or \f$C\,\mathrm{op}(Q)\f$ (Right).
939 Side side = Side::Left; ///< which side Q multiplies from
941 int32_t block_size_hint = 0; ///< WY panel width; 0 lets the tuning table pick
942};
943
944/// @brief ormqr with a compile-time backend and a caller workspace.
945/// @tparam B backend to run on
946/// @throws batchlas::invalid_argument as the Queue-deducing overload
948 typename T = detail::dense_scalar_t<MA>>
949inline Event ormqr(Queue& ctx, const MA& A, const MC& C, Span<T> tau,
950 const OrmqrOptions& opts, Span<std::byte> ws) {
951 using V = BATCHLAS_DENSE_VIEW(T);
952 detail::require_same_batch("ormqr", "A", A, "C", C);
953 detail::require_span_at_least("ormqr", "tau", tau.size(),
954 static_cast<size_t>(std::min(A.rows(), A.cols())) * A.batch_size());
955 return ormqr<B, T>(ctx, V(A), V(C), opts.side, opts.trans, tau, ws, opts.block_size_hint);
956}
957
958/// @brief ormqr with a compile-time backend; workspace leased from the arena.
959/// @tparam B backend to run on
960/// @throws batchlas::invalid_argument as the Queue-deducing overload
961template <Backend B, detail::DenseMatrixLike MA, detail::DenseMatrixLike MC,
962 typename T = detail::dense_scalar_t<MA>>
963inline Event ormqr(Queue& ctx, const MA& A, const MC& C, Span<T> tau,
964 const OrmqrOptions& opts) {
965 using V = BATCHLAS_DENSE_VIEW(T);
966 detail::require_same_batch("ormqr", "A", A, "C", C);
967 detail::require_span_at_least("ormqr", "tau", tau.size(),
968 static_cast<size_t>(std::min(A.rows(), A.cols())) * A.batch_size());
969 // Size with the same hint the call uses, or the buffer is under-sized.
970 auto lease = ctx.workspace(ormqr_buffer_size<B, T>(ctx, V(A), V(C), opts.side, opts.trans,
971 tau, opts.block_size_hint));
972 return ormqr<B, T>(ctx, V(A), V(C), opts.side, opts.trans, tau, lease.span(),
973 opts.block_size_hint);
974}
975
976/// @brief Apply Q from geqrf() with a caller-owned workspace; otherwise as the arena overload.
977/// @param ws device-accessible scratch of at least `ormqr_buffer_size` bytes, sized
978/// with the same `block_size_hint`
979template <detail::DenseMatrixLike MA, detail::DenseMatrixLike MC,
980 typename T = detail::dense_scalar_t<MA>>
981inline Event ormqr(Queue& ctx, const MA& A, const MC& C, Span<T> tau,
982 const OrmqrOptions& opts, Span<std::byte> ws) {
983 BATCHLAS_CHECK_ARGS(ctx, "ormqr", A, C, tau, ws);
984 detail::require_same_batch("ormqr", "A", A, "C", C);
985 detail::require_span_at_least("ormqr", "tau", tau.size(),
986 static_cast<size_t>(std::min(A.rows(), A.cols())) * A.batch_size());
987 return with_backend_for<T>(ctx, "ormqr",
988 [&](auto Back) { return ormqr<Back.value>(ctx, A, C, tau, opts, ws); });
989}
990
991/// @brief Apply the Q of geqrf() to C: \f$C_i := \mathrm{op}(Q_i)C_i\f$ (Left) or \f$C_i\,\mathrm{op}(Q_i)\f$ (Right).
992///
993/// Workspace is leased from the queue's arena.
994/// @param A geqrf()'s output (reflectors below the diagonal), m x k per item
995/// @param C overwritten with the product
996/// @param tau geqrf()'s scalars, at least `min(A.rows(), A.cols()) * batch_size`
997/// @param opts side, trans, block_size_hint
998/// @return event of the last enqueued kernel
999/// @throws batchlas::invalid_argument if `A` and `C` differ in batch size or `tau` is too short
1000/// @throws std::invalid_argument if a pointer is not reachable from the queue's device
1001template <detail::DenseMatrixLike MA, detail::DenseMatrixLike MC,
1002 typename T = detail::dense_scalar_t<MA>>
1003inline Event ormqr(Queue& ctx, const MA& A, const MC& C, Span<T> tau,
1004 const OrmqrOptions& opts = {}) {
1005 BATCHLAS_CHECK_ARGS(ctx, "ormqr", A, C, tau);
1006 // tau is indexed at stride min(m, n): short = out of bounds (validate_ormqr_dims).
1007 detail::require_same_batch("ormqr", "A", A, "C", C);
1008 detail::require_span_at_least("ormqr", "tau", tau.size(),
1009 static_cast<size_t>(std::min(A.rows(), A.cols())) * A.batch_size());
1010 return with_backend_for<T>(ctx, "ormqr",
1011 [&](auto Back) { return ormqr<Back.value>(ctx, A, C, tau, opts); });
1012}
1013
1014/// @brief Options for gesvd(): \f$A = U\Sigma V^H\f$.
1016 SvdVectors jobu = SvdVectors::All; ///< which columns of U to compute
1017 SvdVectors jobvh = SvdVectors::All; ///< which rows of V^H to compute
1018 /// Engaged: A is Hermitian and the given triangle is read (square only); this
1019 /// selects a different entry point, hence optional rather than a sentinel.
1020 std::optional<Uplo> hermitian_uplo = std::nullopt;
1021};
1022
1023/// @brief gesvd with a compile-time backend and a caller workspace.
1024/// @tparam B backend to run on
1025/// @throws batchlas::invalid_argument as the Queue-deducing overload
1028inline Event gesvd(Queue& ctx, const MA& A, Span<typename base_type<T>::type> singular_values,
1029 const MU& U, const MV& Vh, const GesvdOptions& opts, Span<std::byte> ws) {
1030 using V = BATCHLAS_DENSE_VIEW(T);
1031 if (opts.hermitian_uplo) detail::require_square("gesvd", "A", A);
1032 detail::require_span_at_least("gesvd", "singular_values", singular_values.size(),
1033 static_cast<size_t>(std::min(A.rows(), A.cols())) * A.batch_size());
1034 return opts.hermitian_uplo
1035 ? gesvd<B, T>(ctx, V(A), singular_values, V(U), V(Vh), opts.jobu, opts.jobvh,
1036 *opts.hermitian_uplo, ws)
1037 : gesvd<B, T>(ctx, V(A), singular_values, V(U), V(Vh), opts.jobu, opts.jobvh, ws);
1038}
1039
1040/// @brief gesvd with a compile-time backend; workspace leased from the arena.
1041/// @tparam B backend to run on
1042/// @throws batchlas::invalid_argument as the Queue-deducing overload
1043template <Backend B, detail::DenseMatrixLike MA, detail::DenseMatrixLike MU,
1044 detail::DenseMatrixLike MV, typename T = detail::dense_scalar_t<MA>>
1045inline Event gesvd(Queue& ctx, const MA& A, Span<typename base_type<T>::type> singular_values,
1046 const MU& U, const MV& Vh, const GesvdOptions& opts) {
1047 using V = BATCHLAS_DENSE_VIEW(T);
1048 if (opts.hermitian_uplo) detail::require_square("gesvd", "A", A);
1049 detail::require_span_at_least("gesvd", "singular_values", singular_values.size(),
1050 static_cast<size_t>(std::min(A.rows(), A.cols())) * A.batch_size());
1051 // The query must take the same branch as the call (different scratch needs).
1052 const size_t bytes =
1053 opts.hermitian_uplo
1054 ? gesvd_buffer_size<B, T>(ctx, V(A), singular_values, V(U), V(Vh), opts.jobu,
1055 opts.jobvh, *opts.hermitian_uplo)
1056 : gesvd_buffer_size<B, T>(ctx, V(A), singular_values, V(U), V(Vh), opts.jobu,
1057 opts.jobvh);
1058 auto lease = ctx.workspace(bytes);
1059 return opts.hermitian_uplo
1060 ? gesvd<B, T>(ctx, V(A), singular_values, V(U), V(Vh), opts.jobu, opts.jobvh,
1061 *opts.hermitian_uplo, lease.span())
1062 : gesvd<B, T>(ctx, V(A), singular_values, V(U), V(Vh), opts.jobu, opts.jobvh,
1063 lease.span());
1064}
1065
1066/// @brief Batched SVD with a caller-owned workspace; otherwise as the arena overload.
1067/// @param ws device-accessible scratch of at least `gesvd_buffer_size` bytes, sized
1068/// for the same `hermitian_uplo` branch
1069template <detail::DenseMatrixLike MA, detail::DenseMatrixLike MU, detail::DenseMatrixLike MV,
1070 typename T = detail::dense_scalar_t<MA>>
1071inline Event gesvd(Queue& ctx, const MA& A, Span<typename base_type<T>::type> singular_values,
1072 const MU& U, const MV& Vh, const GesvdOptions& opts, Span<std::byte> ws) {
1073 BATCHLAS_CHECK_ARGS(ctx, "gesvd", A, singular_values, U, Vh, ws);
1074 if (opts.hermitian_uplo) detail::require_square("gesvd", "A", A);
1075 detail::require_span_at_least("gesvd", "singular_values", singular_values.size(),
1076 static_cast<size_t>(std::min(A.rows(), A.cols())) * A.batch_size());
1077 return with_backend_for<T>(
1078 ctx, "gesvd", [&](auto Back) { return gesvd<Back.value>(ctx, A, singular_values, U, Vh, opts, ws); });
1079}
1080
1081/// @brief Batched singular value decomposition \f$A_i = U_i\Sigma_iV_i^H\f$.
1082///
1083/// Workspace is leased from the queue's arena. `A` is overwritten. This spelling
1084/// reports no per-item convergence status; use the positional gesvd() with an
1085/// `info` span for that.
1086/// @param A m x n per item (square when `hermitian_uplo` is engaged)
1087/// @param singular_values real, at least `min(m, n) * batch_size`; descending per item
1088/// @param U m x m (All) or m x k (Thin); default-constructed for None
1089/// @param Vh n x n (All) or k x n (Thin); default-constructed for None
1090/// @param opts jobu, jobvh, hermitian_uplo
1091/// @return event of the last enqueued kernel
1092/// @throws batchlas::invalid_argument if `singular_values` is too short, or `A` is
1093/// not square with `hermitian_uplo` engaged
1094/// @throws std::invalid_argument if a pointer is not reachable from the queue's device
1095template <detail::DenseMatrixLike MA, detail::DenseMatrixLike MU, detail::DenseMatrixLike MV,
1096 typename T = detail::dense_scalar_t<MA>>
1097inline Event gesvd(Queue& ctx, const MA& A, Span<typename base_type<T>::type> singular_values,
1098 const MU& U, const MV& Vh, const GesvdOptions& opts = {}) {
1099 BATCHLAS_CHECK_ARGS(ctx, "gesvd", A, singular_values, U, Vh);
1100 // Only A is checked: a default-constructed U/Vh spells SvdVectors::None.
1101 if (opts.hermitian_uplo) detail::require_square("gesvd", "A", A);
1102 detail::require_span_at_least("gesvd", "singular_values", singular_values.size(),
1103 static_cast<size_t>(std::min(A.rows(), A.cols())) * A.batch_size());
1104 return with_backend_for<T>(
1105 ctx, "gesvd", [&](auto Back) { return gesvd<Back.value>(ctx, A, singular_values, U, Vh, opts); });
1106}
1107
1108/// @}
1109
1110#undef BATCHLAS_DENSE_VIEW
1111
1112} // namespace batchlas
Non-owning view of a batch of matrices: the argument type of every entry point.
Definition matrix.hh:485
Owning batch of batch_size() matrices of equal (capacity) shape.
Definition matrix.hh:1399
Non-owning view of a batch of strided vectors: the vector argument type of the entry points.
Definition matrix.hh:1754
The call violates the API contract.
Definition error.hh:77
Enumerations, scalar traits and scalar concepts shared by every public header.
Event gemv(Queue &ctx, const MatrixView< T, MatrixFormat::Dense > &A, const VectorView< T > &X, const VectorView< T > &Y, T alpha, T beta, Transpose transA)
Batched general matrix-vector multiply.
Event syr2k(Queue &ctx, const MatrixView< T, MatrixFormat::Dense > &A, const MatrixView< T, MatrixFormat::Dense > &B, const MatrixView< T, MatrixFormat::Dense > &C, T alpha, T beta, Uplo uplo, Transpose transA)
Batched symmetric rank-2k update.
Event herk(Queue &ctx, const MatrixView< T, MatrixFormat::Dense > &A, const MatrixView< T, MatrixFormat::Dense > &C, float_t< T > alpha, float_t< T > beta, Uplo uplo, Transpose transA)
Batched Hermitian rank-k update.
Event hemm(Queue &ctx, const MatrixView< T, MatrixFormat::Dense > &A, const MatrixView< T, MatrixFormat::Dense > &B, const MatrixView< T, MatrixFormat::Dense > &C, T alpha, T beta, Side side, Uplo uplo)
Batched Hermitian matrix-matrix multiply.
Event gemm(Queue &ctx, const MatrixView< T, MatrixFormat::Dense > &A, const MatrixView< T, MatrixFormat::Dense > &B, const MatrixView< T, MatrixFormat::Dense > &C, T alpha, T beta, Transpose transA, Transpose transB, ComputePrecision precision=ComputePrecision::Default)
Batched general matrix-matrix multiply.
Event syrk(Queue &ctx, const MatrixView< T, MatrixFormat::Dense > &A, const MatrixView< T, MatrixFormat::Dense > &C, T alpha, T beta, Uplo uplo, Transpose transA)
Batched symmetric rank-k update.
Event trsm(Queue &ctx, const MatrixView< T, MatrixFormat::Dense > &A, const MatrixView< T, MatrixFormat::Dense > &B, T alpha, Side side, Uplo uplo, Transpose transA, Diag diag)
Batched triangular solve with multiple right-hand sides, in place.
Event her2k(Queue &ctx, const MatrixView< T, MatrixFormat::Dense > &A, const MatrixView< T, MatrixFormat::Dense > &B, const MatrixView< T, MatrixFormat::Dense > &C, T alpha, float_t< T > beta, Uplo uplo, Transpose transA)
Batched Hermitian rank-2k update.
Event trmm(Queue &ctx, const MatrixView< T, MatrixFormat::Dense > &A, const MatrixView< T, MatrixFormat::Dense > &B, const MatrixView< T, MatrixFormat::Dense > &C, T alpha, Side side, Uplo uplo, Transpose transA, Diag diag)
Batched triangular matrix-matrix multiply, out of place.
Event symm(Queue &ctx, const MatrixView< T, MatrixFormat::Dense > &A, const MatrixView< T, MatrixFormat::Dense > &B, const MatrixView< T, MatrixFormat::Dense > &C, T alpha, T beta, Side side, Uplo uplo)
Batched symmetric matrix-matrix multiply.
auto with_backend_for(Queue &ctx, const char *op, F &&f)
with_backend() for a call on element type T: throws batchlas::unsupported before dispatch when T is d...
size_t syev_buffer_size(Queue &ctx, const MatrixView< T, MatrixFormat::Dense > &A, Span< typename base_type< T >::type > eigenvalues, JobType jobtype, Uplo uplo)
Workspace, in bytes, that syev() needs for the same arguments.
Event syev(Queue &ctx, const MatrixView< T, MatrixFormat::Dense > &descrA, Span< typename base_type< T >::type > eigenvalues, JobType jobtype, Uplo uplo, Span< std::byte > workspace, Span< int32_t > info)
Eigenvalues, and optionally eigenvectors, of a batch of symmetric/Hermitian matrices (LAPACK ?...
JobType
Whether an eigensolver computes eigenvectors (LAPACK jobz).
Definition enums.hh:189
Transpose
The operator op() applied to an operand: op(A) = A, A^T or A^H.
Definition enums.hh:171
Diag
Whether a triangular operand's diagonal is read or assumed to be one.
Definition enums.hh:303
Backend
Library family an entry point dispatches to, used as a template argument.
Definition enums.hh:111
ComputePrecision
Internal compute precision of a GEMM (the cuBLAS cublasComputeType_t).
Definition enums.hh:505
Uplo
Which triangle of a symmetric, Hermitian or triangular operand is referenced.
Definition enums.hh:287
SvdVectors
Which singular vectors gesvd computes for one factor (LAPACK jobu / jobvt).
Definition enums.hh:220
typename base_type< T >::type float_t
Shorthand for base_type<T>::type: the precision of T (tolerances, norms, eigenvalues).
Definition enums.hh:41
MatrixFormat
Storage format of a Matrix / MatrixView, used as a template argument.
Definition enums.hh:72
Side
Side on which a special operand multiplies: op(A) * B or B * op(A).
Definition enums.hh:319
@ EigenVectors
Eigenvalues and eigenvectors (jobz = 'V').
Definition enums.hh:190
@ NoTrans
op(A) = A.
Definition enums.hh:172
@ NonUnit
The stored diagonal is used.
Definition enums.hh:304
@ Default
The precision of the scalar type.
Definition enums.hh:506
@ Lower
The lower triangle (i >= j).
Definition enums.hh:289
@ All
Full square factor (LAPACK 'A').
Definition enums.hh:222
@ Dense
Column-major dense storage with leading dimension and batch stride.
Definition enums.hh:73
@ Left
The special operand is on the left.
Definition enums.hh:320
size_t getrf_buffer_size(Queue &ctx, const MatrixView< T, MatrixFormat::Dense > &A)
Workspace, in bytes, that getrf() needs for this shape on this queue.
size_t getrs_buffer_size(Queue &ctx, const MatrixView< T, MatrixFormat::Dense > &A, const MatrixView< T, MatrixFormat::Dense > &B, Transpose transA)
Workspace, in bytes, that getrs() needs for these operands on this queue.
size_t getri_buffer_size(Queue &ctx, const MatrixView< T, MatrixFormat::Dense > &A)
Workspace, in bytes, that getri() needs for A on this queue.
size_t potrf_buffer_size(Queue &ctx, const MatrixView< T, MatrixFormat::Dense > &A, Uplo uplo)
Workspace, in bytes, that potrf() needs for this shape on this queue.
Event potrf(Queue &ctx, const MatrixView< T, MatrixFormat::Dense > &descrA, Uplo uplo, Span< std::byte > workspace, Span< int32_t > info)
Batched Cholesky factorization of Hermitian positive-definite matrices.
Event getrs(Queue &ctx, const MatrixView< T, MatrixFormat::Dense > &A, const MatrixView< T, MatrixFormat::Dense > &B, Transpose transA, Span< int64_t > pivots, Span< std::byte > work_space)
Batched solve of using the LU factors from getrf().
Event getrf(Queue &ctx, const MatrixView< T, MatrixFormat::Dense > &A, Span< int64_t > pivots, Span< std::byte > work_space, Span< int32_t > info)
Batched LU factorization with partial pivoting.
Event getri(Queue &ctx, const MatrixView< T, MatrixFormat::Dense > &A, const MatrixView< T, MatrixFormat::Dense > &C, Span< int64_t > pivots, Span< std::byte > work_space, Span< int32_t > info)
Batched inverse from the LU factors produced by getrf().
size_t geqrf_buffer_size(Queue &ctx, const MatrixView< T, MatrixFormat::Dense > &A, Span< T > tau)
Workspace, in bytes, that geqrf() needs for this shape on this queue.
size_t orgqr_buffer_size(Queue &ctx, const MatrixView< T, MatrixFormat::Dense > &A, Span< T > tau)
Workspace, in bytes, that orgqr() needs for this shape on this queue.
size_t ormqr_buffer_size(Queue &ctx, const MatrixView< T, MatrixFormat::Dense > &A, const MatrixView< T, MatrixFormat::Dense > &C, Side side, Transpose trans, Span< T > tau, int32_t block_size_hint=0)
Workspace, in bytes, that ormqr() needs for these operands on this queue.
Event orgqr(Queue &ctx, const MatrixView< T, MatrixFormat::Dense > &A, Span< T > tau, Span< std::byte > workspace)
Batched formation of the first n columns of Q from geqrf() output.
Event geqrf(Queue &ctx, const MatrixView< T, MatrixFormat::Dense > &A, Span< T > tau, Span< std::byte > work_space)
Batched Householder QR factorization .
Event ormqr(Queue &ctx, const MatrixView< T, MatrixFormat::Dense > &A, const MatrixView< T, MatrixFormat::Dense > &C, Side side, Transpose trans, Span< T > tau, Span< std::byte > workspace, int32_t block_size_hint=0)
Batched multiplication by the orthogonal/unitary Q from geqrf().
size_t gesvd_buffer_size(Queue &ctx, const MatrixView< T, MatrixFormat::Dense > &A, Span< typename base_type< T >::type > singular_values, const MatrixView< T, MatrixFormat::Dense > &U, const MatrixView< T, MatrixFormat::Dense > &Vh, SvdVectors jobu, SvdVectors jobvh)
Workspace, in bytes, that gesvd() needs for the same arguments.
Event gesvd(Queue &ctx, const MatrixView< T, MatrixFormat::Dense > &A, Span< typename base_type< T >::type > singular_values, const MatrixView< T, MatrixFormat::Dense > &U, const MatrixView< T, MatrixFormat::Dense > &Vh, SvdVectors jobu, SvdVectors jobvh, Span< std::byte > workspace, Span< int32_t > info)
Singular value decomposition of a batch of matrices (LAPACK ?gesvd).
The batched containers: Matrix (owning), MatrixView (non-owning), KernelMatrixView (device-side),...
void require_square(const char *fn, const char *name, const MV &A)
Definition options.hh:98
void require_arg_accessible(const Queue &ctx, const A &arg, const std::string &what)
typename dense_scalar< std::remove_cvref_t< M > >::type dense_scalar_t
Definition options.hh:255
void require_info_span(const char *fn, size_t have, size_t batch_size)
Definition options.hh:131
void require_span_at_least(const char *fn, const char *name, size_t have, size_t need)
Definition options.hh:123
void require_args_accessible(const Queue &ctx, const char *fn, const char *const *names, const Args &... args)
Definition options.hh:61
void require_same_rows(const char *fn, const char *an, const MA &A, const char *bn, const MB &B)
Definition options.hh:105
void require_same_batch(const char *fn, const char *an, const MA &A, const char *bn, const MB &B)
Definition options.hh:114
#define BATCHLAS_DENSE_VIEW(T)
Definition options.hh:266
Backend deduction from the Queue and the USM pointer check.
Completion handle of enqueued work, returned by every entry point.
Options for gemm(): .
Definition options.hh:144
T alpha
scale of the product
Definition options.hh:145
T beta
scale of the incoming C; 0 means C is not read
Definition options.hh:146
ComputePrecision precision
internal compute type; Default = the input type
Definition options.hh:149
Transpose transA
op(A)
Definition options.hh:147
Transpose transB
op(B)
Definition options.hh:148
Options for gemv(): .
Definition options.hh:154
Transpose transA
op(A)
Definition options.hh:157
T beta
scale of the incoming y
Definition options.hh:156
T alpha
scale of the product
Definition options.hh:155
Options for gesvd(): .
Definition options.hh:1015
std::optional< Uplo > hermitian_uplo
Engaged: A is Hermitian and the given triangle is read (square only); this selects a different entry ...
Definition options.hh:1020
SvdVectors jobu
which columns of U to compute
Definition options.hh:1016
SvdVectors jobvh
which rows of V^H to compute
Definition options.hh:1017
Options for getrs(): solve with getrf's factors.
Definition options.hh:558
Transpose trans
op(A)
Definition options.hh:559
Options for hemm(): as SymmOptions, with A Hermitian.
Definition options.hh:171
T beta
scale of the incoming C
Definition options.hh:173
T alpha
scale of the product
Definition options.hh:172
Side side
which side A multiplies from
Definition options.hh:174
Uplo uplo
triangle of A that is read
Definition options.hh:175
Options for her2k(): .
Definition options.hh:193
Uplo uplo
triangle of C that is written
Definition options.hh:196
T alpha
complex scale
Definition options.hh:194
Transpose trans
NoTrans or ConjTrans.
Definition options.hh:197
float_t< T > beta
real scale of the incoming C
Definition options.hh:195
Options for herk(): .
Definition options.hh:182
Transpose trans
NoTrans ( ) or ConjTrans ( ).
Definition options.hh:186
float_t< T > alpha
real scale of the product
Definition options.hh:183
Uplo uplo
triangle of C that is written
Definition options.hh:185
float_t< T > beta
real scale of the incoming C
Definition options.hh:184
Options for ormqr(): apply geqrf()'s Q, (Left) or (Right).
Definition options.hh:938
int32_t block_size_hint
WY panel width; 0 lets the tuning table pick.
Definition options.hh:941
Transpose trans
op(Q)
Definition options.hh:940
Side side
which side Q multiplies from
Definition options.hh:939
Options for potrf(): Cholesky (Lower) or (Upper).
Definition options.hh:549
Span< int32_t > info
Per-item status, one int32 per batch item: 0 = factorised, > 0 = the order of the leading minor that ...
Definition options.hh:554
Uplo uplo
triangle read and overwritten with the factor
Definition options.hh:550
Where BatchLAS work runs: a device, a backend, an ordered SYCL queue and a workspace arena.
batchlas::WorkspaceLease workspace(size_t bytes)
Borrow bytes of device scratch from this Queue's arena.
Non-owning view of size() contiguous elements of type T.
Definition sycl-span.hh:39
constexpr size_t size() const
Number of elements.
Definition sycl-span.hh:106
Options for syev(): symmetric/Hermitian eigendecomposition.
Definition options.hh:563
JobType jobz
eigenvectors too, or eigenvalues only
Definition options.hh:564
Uplo uplo
triangle of A that is read
Definition options.hh:565
Options for symm(): (Left) or (Right), A symmetric.
Definition options.hh:162
Uplo uplo
triangle of A that is read
Definition options.hh:166
T beta
scale of the incoming C
Definition options.hh:164
Side side
which side A multiplies from
Definition options.hh:165
T alpha
scale of the product
Definition options.hh:163
Options for syr2k(): .
Definition options.hh:211
T beta
scale of the incoming C
Definition options.hh:213
T alpha
scale of the product pair
Definition options.hh:212
Uplo uplo
triangle of C that is written
Definition options.hh:214
Transpose trans
NoTrans or Trans.
Definition options.hh:215
Options for syrk(): .
Definition options.hh:202
T alpha
scale of the product
Definition options.hh:203
Uplo uplo
triangle of C that is written
Definition options.hh:205
T beta
scale of the incoming C
Definition options.hh:204
Transpose trans
NoTrans ( ) or Trans ( ).
Definition options.hh:206
Options for trmm(): (Left) or (Right). No beta.
Definition options.hh:220
Transpose trans
op(A)
Definition options.hh:224
Side side
which side op(A) multiplies from
Definition options.hh:222
Uplo uplo
which triangle A is
Definition options.hh:223
T alpha
scale of the product
Definition options.hh:221
Diag diag
Unit: A's diagonal is taken as ones and not read.
Definition options.hh:225
Options for trsm(): solve (Left) or (Right).
Definition options.hh:230
T alpha
scale of the right-hand side
Definition options.hh:231
Side side
which side op(A) is on
Definition options.hh:232
Diag diag
Unit: A's diagonal is taken as ones and not read.
Definition options.hh:235
Uplo uplo
which triangle A is
Definition options.hh:233
Transpose trans
op(A)
Definition options.hh:234
T type
The real type.
Definition enums.hh:30
batchlas::Device, batchlas::Event and batchlas::Queue: where work runs and how it is ordered.
batchlas::Span, the non-owning pointer + length every entry point takes for 1-D data.