Skip to main content

baracuda_cusolver_sys/
lib.rs

1//! Raw FFI + dynamic loader for NVIDIA cuSOLVER (Dense + Sparse + Refactor).
2//!
3//! `baracuda-cusolver` wraps this with a safe, typed API. Use this
4//! crate directly only if you need a function that the safe layer
5//! hasn't wrapped yet (in which case please file a bug).
6
7#![allow(non_camel_case_types, non_snake_case, non_upper_case_globals)]
8#![warn(missing_debug_implementations)]
9
10use core::ffi::{c_int, c_void};
11use std::sync::OnceLock;
12
13use baracuda_core::{platform, Library, LoaderError};
14use baracuda_cuda_sys::runtime::cudaStream_t;
15use baracuda_types::CudaStatus;
16
17// ---- handles --------------------------------------------------------------
18
19/// Opaque dense cuSOLVER handle.
20pub type cusolverDnHandle_t = *mut c_void;
21/// Opaque sparse cuSOLVER handle.
22pub type cusolverSpHandle_t = *mut c_void;
23/// Opaque sparse-refactor cuSOLVER handle.
24pub type cusolverRfHandle_t = *mut c_void;
25/// Opaque generic-API parameter object for `cusolverDnX*` routines.
26pub type cusolverDnParams_t = *mut c_void;
27/// Opaque parameter object for iterative-refinement solvers.
28pub type cusolverDnIRSParams_t = *mut c_void;
29/// Opaque info object for iterative-refinement solvers.
30pub type cusolverDnIRSInfos_t = *mut c_void;
31/// Opaque control object for Jacobi-based symmetric eigendecomposition.
32pub type syevjInfo_t = *mut c_void;
33/// Opaque control object for Jacobi-based SVD.
34pub type gesvdjInfo_t = *mut c_void;
35
36// ---- enums ----------------------------------------------------------------
37
38/// Transpose selector — same values as `cublasOperation_t` (N=0, T=1, C=2).
39#[repr(i32)]
40#[derive(Copy, Clone, Debug, Eq, PartialEq)]
41pub enum cublasOperation_t {
42    /// No transpose.
43    N = 0,
44    /// Transpose.
45    T = 1,
46    /// Conjugate transpose.
47    C = 2,
48}
49
50/// Triangular fill mode (matches the cuBLAS enum).
51#[repr(i32)]
52#[derive(Copy, Clone, Debug, Eq, PartialEq)]
53pub enum cublasFillMode_t {
54    /// Lower-triangular.
55    Lower = 0,
56    /// Upper-triangular.
57    Upper = 1,
58    /// Full / dense matrix.
59    Full = 2,
60}
61
62/// Side selector for one-sided operators (apply from left or right).
63#[repr(i32)]
64#[derive(Copy, Clone, Debug, Eq, PartialEq)]
65pub enum cublasSideMode_t {
66    /// Apply from the left.
67    Left = 0,
68    /// Apply from the right.
69    Right = 1,
70}
71
72/// Diagonal-unit selector (matches the cuBLAS enum).
73#[repr(i32)]
74#[derive(Copy, Clone, Debug, Eq, PartialEq)]
75pub enum cublasDiagType_t {
76    /// Non-unit diagonal.
77    NonUnit = 0,
78    /// Unit diagonal.
79    Unit = 1,
80}
81
82/// Generalized eigenproblem variant for `sygv*` / `hegv*` routines.
83#[repr(i32)]
84#[derive(Copy, Clone, Debug, Eq, PartialEq)]
85pub enum cusolverEigType_t {
86    /// Type-1 generalized eigenproblem: `A*x = lambda*B*x`.
87    Type1 = 1,
88    /// Type-2 generalized eigenproblem: `A*B*x = lambda*x`.
89    Type2 = 2,
90    /// Type-3 generalized eigenproblem: `B*A*x = lambda*x`.
91    Type3 = 3,
92}
93
94/// Eigenvalue-only vs eigenvalue-and-vector selector for eigensolvers.
95#[repr(i32)]
96#[derive(Copy, Clone, Debug, Eq, PartialEq)]
97pub enum cusolverEigMode_t {
98    /// Compute eigenvalues only.
99    NoVector = 0,
100    /// Compute eigenvalues and eigenvectors.
101    Vector = 1,
102}
103
104/// Subset-of-spectrum selector for partial eigensolvers.
105#[repr(i32)]
106#[derive(Copy, Clone, Debug, Eq, PartialEq)]
107pub enum cusolverEigRange_t {
108    /// Compute all eigenvalues.
109    All = 1001,
110    /// Compute eigenvalues with indices in `[il, iu]`.
111    I = 1002,
112    /// Compute eigenvalues in the half-open interval `(vl, vu]`.
113    V = 1003,
114}
115
116/// Element-dtype selector used by the generic-API (`cusolverDnX*`) routines.
117#[repr(i32)]
118#[derive(Copy, Clone, Debug, Eq, PartialEq)]
119pub enum cudaDataType {
120    /// 32-bit real (`f32`).
121    R_32F = 0,
122    /// 64-bit real (`f64`).
123    R_64F = 1,
124    /// 16-bit real (IEEE half / `f16`).
125    R_16F = 2,
126    /// 32-bit complex (`Complex<f32>`).
127    C_32F = 4,
128    /// 64-bit complex (`Complex<f64>`).
129    C_64F = 5,
130    /// 16-bit real bfloat16.
131    R_16BF = 14,
132}
133
134// ---- status ---------------------------------------------------------------
135
136/// Status / error code returned by cuSOLVER FFI calls.
137#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
138#[repr(transparent)]
139pub struct cusolverStatus_t(pub i32);
140
141impl cusolverStatus_t {
142    /// Status: success.
143    pub const SUCCESS: Self = Self(0);
144    /// Status: not initialized.
145    pub const NOT_INITIALIZED: Self = Self(1);
146    /// Status: alloc failed.
147    pub const ALLOC_FAILED: Self = Self(2);
148    /// Status: invalid value.
149    pub const INVALID_VALUE: Self = Self(3);
150    /// Status: arch mismatch.
151    pub const ARCH_MISMATCH: Self = Self(4);
152    /// Status: execution failed.
153    pub const EXECUTION_FAILED: Self = Self(6);
154    /// Status: internal error.
155    pub const INTERNAL_ERROR: Self = Self(7);
156    /// Status: not supported.
157    pub const NOT_SUPPORTED: Self = Self(9);
158    /// Status: zero pivot.
159    pub const ZERO_PIVOT: Self = Self(10);
160
161    /// Returns `true` when this is the success status code.
162    pub const fn is_success(self) -> bool {
163        self.0 == 0
164    }
165}
166
167impl CudaStatus for cusolverStatus_t {
168    fn code(self) -> i32 {
169        self.0
170    }
171    fn name(self) -> &'static str {
172        match self.0 {
173            0 => "CUSOLVER_STATUS_SUCCESS",
174            1 => "CUSOLVER_STATUS_NOT_INITIALIZED",
175            2 => "CUSOLVER_STATUS_ALLOC_FAILED",
176            3 => "CUSOLVER_STATUS_INVALID_VALUE",
177            6 => "CUSOLVER_STATUS_EXECUTION_FAILED",
178            7 => "CUSOLVER_STATUS_INTERNAL_ERROR",
179            9 => "CUSOLVER_STATUS_NOT_SUPPORTED",
180            10 => "CUSOLVER_STATUS_ZERO_PIVOT",
181            _ => "CUSOLVER_STATUS_UNRECOGNIZED",
182        }
183    }
184    fn description(self) -> &'static str {
185        match self.0 {
186            0 => "success",
187            1 => "cuSOLVER not initialized",
188            6 => "execution failed on device",
189            10 => "factorization produced a zero pivot",
190            _ => "unrecognized cuSOLVER status code",
191        }
192    }
193    fn is_success(self) -> bool {
194        cusolverStatus_t::is_success(self)
195    }
196    fn library(self) -> &'static str {
197        "cusolver"
198    }
199}
200
201// ---- complex types (alias to plain 2-element arrays) ---------------------
202
203/// Single-precision complex number, ABI-compatible with cuBLAS / cuSOLVER `cuComplex`.
204#[repr(C)]
205#[derive(Copy, Clone, Debug)]
206pub struct cuComplex {
207    /// Real component (`f32`).
208    pub x: f32,
209    /// Imaginary component (`f32`).
210    pub y: f32,
211}
212
213/// Double-precision complex number, ABI-compatible with cuBLAS / cuSOLVER `cuDoubleComplex`.
214#[repr(C)]
215#[derive(Copy, Clone, Debug)]
216pub struct cuDoubleComplex {
217    /// Real component (`f64`).
218    pub x: f64,
219    /// Imaginary component (`f64`).
220    pub y: f64,
221}
222
223// ---- PFN type declaration macros -----------------------------------------
224
225/// `getrf_bufferSize(handle, m, n, a, lda, lwork) -> status`
226macro_rules! dn_getrf_bufsize {
227    ($(#[$attr:meta])* $name:ident, $t:ty) => {
228        $(#[$attr])*
229        pub type $name = unsafe extern "C" fn(
230            handle: cusolverDnHandle_t,
231            m: c_int,
232            n: c_int,
233            a: *mut $t,
234            lda: c_int,
235            lwork: *mut c_int,
236        ) -> cusolverStatus_t;
237    };
238}
239
240macro_rules! dn_getrf {
241    ($(#[$attr:meta])* $name:ident, $t:ty) => {
242        $(#[$attr])*
243        pub type $name = unsafe extern "C" fn(
244            handle: cusolverDnHandle_t,
245            m: c_int,
246            n: c_int,
247            a: *mut $t,
248            lda: c_int,
249            workspace: *mut $t,
250            ipiv: *mut c_int,
251            info: *mut c_int,
252        ) -> cusolverStatus_t;
253    };
254}
255
256macro_rules! dn_getrs {
257    ($(#[$attr:meta])* $name:ident, $t:ty) => {
258        $(#[$attr])*
259        pub type $name = unsafe extern "C" fn(
260            handle: cusolverDnHandle_t,
261            trans: cublasOperation_t,
262            n: c_int,
263            nrhs: c_int,
264            a: *const $t,
265            lda: c_int,
266            ipiv: *const c_int,
267            b: *mut $t,
268            ldb: c_int,
269            info: *mut c_int,
270        ) -> cusolverStatus_t;
271    };
272}
273
274macro_rules! dn_geqrf_bufsize {
275    ($(#[$attr:meta])* $name:ident, $t:ty) => {
276        $(#[$attr])*
277        pub type $name = unsafe extern "C" fn(
278            handle: cusolverDnHandle_t,
279            m: c_int,
280            n: c_int,
281            a: *mut $t,
282            lda: c_int,
283            lwork: *mut c_int,
284        ) -> cusolverStatus_t;
285    };
286}
287
288macro_rules! dn_geqrf {
289    ($(#[$attr:meta])* $name:ident, $t:ty) => {
290        $(#[$attr])*
291        pub type $name = unsafe extern "C" fn(
292            handle: cusolverDnHandle_t,
293            m: c_int,
294            n: c_int,
295            a: *mut $t,
296            lda: c_int,
297            tau: *mut $t,
298            workspace: *mut $t,
299            lwork: c_int,
300            info: *mut c_int,
301        ) -> cusolverStatus_t;
302    };
303}
304
305macro_rules! dn_potrf_bufsize {
306    ($(#[$attr:meta])* $name:ident, $t:ty) => {
307        $(#[$attr])*
308        pub type $name = unsafe extern "C" fn(
309            handle: cusolverDnHandle_t,
310            uplo: cublasFillMode_t,
311            n: c_int,
312            a: *mut $t,
313            lda: c_int,
314            lwork: *mut c_int,
315        ) -> cusolverStatus_t;
316    };
317}
318
319macro_rules! dn_potrf {
320    ($(#[$attr:meta])* $name:ident, $t:ty) => {
321        $(#[$attr])*
322        pub type $name = unsafe extern "C" fn(
323            handle: cusolverDnHandle_t,
324            uplo: cublasFillMode_t,
325            n: c_int,
326            a: *mut $t,
327            lda: c_int,
328            workspace: *mut $t,
329            lwork: c_int,
330            info: *mut c_int,
331        ) -> cusolverStatus_t;
332    };
333}
334
335macro_rules! dn_potrs {
336    ($(#[$attr:meta])* $name:ident, $t:ty) => {
337        $(#[$attr])*
338        pub type $name = unsafe extern "C" fn(
339            handle: cusolverDnHandle_t,
340            uplo: cublasFillMode_t,
341            n: c_int,
342            nrhs: c_int,
343            a: *const $t,
344            lda: c_int,
345            b: *mut $t,
346            ldb: c_int,
347            info: *mut c_int,
348        ) -> cusolverStatus_t;
349    };
350}
351
352macro_rules! dn_gesvd_bufsize {
353    ($(#[$attr:meta])* $name:ident) => {
354        $(#[$attr])*
355        pub type $name = unsafe extern "C" fn(
356            handle: cusolverDnHandle_t,
357            m: c_int,
358            n: c_int,
359            lwork: *mut c_int,
360        ) -> cusolverStatus_t;
361    };
362}
363
364macro_rules! dn_gesvd_real {
365    ($(#[$attr:meta])* $name:ident, $t:ty) => {
366        $(#[$attr])*
367        pub type $name = unsafe extern "C" fn(
368            handle: cusolverDnHandle_t,
369            jobu: u8,
370            jobvt: u8,
371            m: c_int,
372            n: c_int,
373            a: *mut $t,
374            lda: c_int,
375            s: *mut $t,
376            u: *mut $t,
377            ldu: c_int,
378            vt: *mut $t,
379            ldvt: c_int,
380            work: *mut $t,
381            lwork: c_int,
382            rwork: *mut $t,
383            info: *mut c_int,
384        ) -> cusolverStatus_t;
385    };
386}
387
388macro_rules! dn_gesvd_complex {
389    ($(#[$attr:meta])* $name:ident, $t:ty, $real:ty) => {
390        $(#[$attr])*
391        pub type $name = unsafe extern "C" fn(
392            handle: cusolverDnHandle_t,
393            jobu: u8,
394            jobvt: u8,
395            m: c_int,
396            n: c_int,
397            a: *mut $t,
398            lda: c_int,
399            s: *mut $real,
400            u: *mut $t,
401            ldu: c_int,
402            vt: *mut $t,
403            ldvt: c_int,
404            work: *mut $t,
405            lwork: c_int,
406            rwork: *mut $real,
407            info: *mut c_int,
408        ) -> cusolverStatus_t;
409    };
410}
411
412macro_rules! dn_syevd_bufsize {
413    ($(#[$attr:meta])* $name:ident, $t:ty, $real:ty) => {
414        $(#[$attr])*
415        pub type $name = unsafe extern "C" fn(
416            handle: cusolverDnHandle_t,
417            jobz: cusolverEigMode_t,
418            uplo: cublasFillMode_t,
419            n: c_int,
420            a: *const $t,
421            lda: c_int,
422            w: *const $real,
423            lwork: *mut c_int,
424        ) -> cusolverStatus_t;
425    };
426}
427
428macro_rules! dn_syevd {
429    ($(#[$attr:meta])* $name:ident, $t:ty, $real:ty) => {
430        $(#[$attr])*
431        pub type $name = unsafe extern "C" fn(
432            handle: cusolverDnHandle_t,
433            jobz: cusolverEigMode_t,
434            uplo: cublasFillMode_t,
435            n: c_int,
436            a: *mut $t,
437            lda: c_int,
438            w: *mut $real,
439            work: *mut $t,
440            lwork: c_int,
441            info: *mut c_int,
442        ) -> cusolverStatus_t;
443    };
444}
445
446// ---- core Dn handle ------------------------------------------------------
447
448/// cuSOLVER: create a dense cuSOLVER handle. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
449pub type PFN_cusolverDnCreate =
450    unsafe extern "C" fn(handle: *mut cusolverDnHandle_t) -> cusolverStatus_t;
451/// cuSOLVER: destroy a dense cuSOLVER handle. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
452pub type PFN_cusolverDnDestroy =
453    unsafe extern "C" fn(handle: cusolverDnHandle_t) -> cusolverStatus_t;
454/// cuSOLVER: bind a CUDA stream to a dense cuSOLVER handle. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
455pub type PFN_cusolverDnSetStream =
456    unsafe extern "C" fn(handle: cusolverDnHandle_t, stream: cudaStream_t) -> cusolverStatus_t;
457/// cuSOLVER: query the CUDA stream bound to a dense cuSOLVER handle. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
458pub type PFN_cusolverDnGetStream =
459    unsafe extern "C" fn(handle: cusolverDnHandle_t, stream: *mut cudaStream_t) -> cusolverStatus_t;
460
461/// cuSOLVER: return the cuSOLVER library version. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
462pub type PFN_cusolverGetVersion = unsafe extern "C" fn(version: *mut c_int) -> cusolverStatus_t;
463
464// ---- LU factorization (getrf / getrs) — S/D/C/Z --------------------------
465
466dn_getrf_bufsize!(#[doc = "cuSOLVER: single-precision workspace-size query for LU factorization with partial pivoting. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnSgetrf_bufferSize, f32);
467dn_getrf_bufsize!(#[doc = "cuSOLVER: double-precision workspace-size query for LU factorization with partial pivoting. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnDgetrf_bufferSize, f64);
468dn_getrf_bufsize!(#[doc = "cuSOLVER: single-precision complex workspace-size query for LU factorization with partial pivoting. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnCgetrf_bufferSize, cuComplex);
469dn_getrf_bufsize!(#[doc = "cuSOLVER: double-precision complex workspace-size query for LU factorization with partial pivoting. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnZgetrf_bufferSize, cuDoubleComplex);
470
471dn_getrf!(#[doc = "cuSOLVER: single-precision LU factorization with partial pivoting. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnSgetrf, f32);
472dn_getrf!(#[doc = "cuSOLVER: double-precision LU factorization with partial pivoting. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnDgetrf, f64);
473dn_getrf!(#[doc = "cuSOLVER: single-precision complex LU factorization with partial pivoting. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnCgetrf, cuComplex);
474dn_getrf!(#[doc = "cuSOLVER: double-precision complex LU factorization with partial pivoting. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnZgetrf, cuDoubleComplex);
475
476dn_getrs!(#[doc = "cuSOLVER: single-precision solve linear system using LU factors. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnSgetrs, f32);
477dn_getrs!(#[doc = "cuSOLVER: double-precision solve linear system using LU factors. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnDgetrs, f64);
478dn_getrs!(#[doc = "cuSOLVER: single-precision complex solve linear system using LU factors. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnCgetrs, cuComplex);
479dn_getrs!(#[doc = "cuSOLVER: double-precision complex solve linear system using LU factors. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnZgetrs, cuDoubleComplex);
480
481// ---- QR factorization (geqrf) — S/D/C/Z ----------------------------------
482
483dn_geqrf_bufsize!(#[doc = "cuSOLVER: single-precision workspace-size query for QR factorization (Householder). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnSgeqrf_bufferSize, f32);
484dn_geqrf_bufsize!(#[doc = "cuSOLVER: double-precision workspace-size query for QR factorization (Householder). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnDgeqrf_bufferSize, f64);
485dn_geqrf_bufsize!(#[doc = "cuSOLVER: single-precision complex workspace-size query for QR factorization (Householder). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnCgeqrf_bufferSize, cuComplex);
486dn_geqrf_bufsize!(#[doc = "cuSOLVER: double-precision complex workspace-size query for QR factorization (Householder). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnZgeqrf_bufferSize, cuDoubleComplex);
487
488dn_geqrf!(#[doc = "cuSOLVER: single-precision QR factorization (Householder). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnSgeqrf, f32);
489dn_geqrf!(#[doc = "cuSOLVER: double-precision QR factorization (Householder). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnDgeqrf, f64);
490dn_geqrf!(#[doc = "cuSOLVER: single-precision complex QR factorization (Householder). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnCgeqrf, cuComplex);
491dn_geqrf!(#[doc = "cuSOLVER: double-precision complex QR factorization (Householder). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnZgeqrf, cuDoubleComplex);
492
493// ---- Cholesky (potrf / potrs) — S/D/C/Z ----------------------------------
494
495dn_potrf_bufsize!(#[doc = "cuSOLVER: single-precision workspace-size query for Cholesky factorization. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnSpotrf_bufferSize, f32);
496dn_potrf_bufsize!(#[doc = "cuSOLVER: double-precision workspace-size query for Cholesky factorization. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnDpotrf_bufferSize, f64);
497dn_potrf_bufsize!(#[doc = "cuSOLVER: single-precision complex workspace-size query for Cholesky factorization. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnCpotrf_bufferSize, cuComplex);
498dn_potrf_bufsize!(#[doc = "cuSOLVER: double-precision complex workspace-size query for Cholesky factorization. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnZpotrf_bufferSize, cuDoubleComplex);
499
500dn_potrf!(#[doc = "cuSOLVER: single-precision Cholesky factorization. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnSpotrf, f32);
501dn_potrf!(#[doc = "cuSOLVER: double-precision Cholesky factorization. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnDpotrf, f64);
502dn_potrf!(#[doc = "cuSOLVER: single-precision complex Cholesky factorization. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnCpotrf, cuComplex);
503dn_potrf!(#[doc = "cuSOLVER: double-precision complex Cholesky factorization. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnZpotrf, cuDoubleComplex);
504
505dn_potrs!(#[doc = "cuSOLVER: single-precision solve linear system using Cholesky factors. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnSpotrs, f32);
506dn_potrs!(#[doc = "cuSOLVER: double-precision solve linear system using Cholesky factors. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnDpotrs, f64);
507dn_potrs!(#[doc = "cuSOLVER: single-precision complex solve linear system using Cholesky factors. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnCpotrs, cuComplex);
508dn_potrs!(#[doc = "cuSOLVER: double-precision complex solve linear system using Cholesky factors. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnZpotrs, cuDoubleComplex);
509
510// ---- SVD — S/D/C/Z -------------------------------------------------------
511
512dn_gesvd_bufsize!(#[doc = "cuSOLVER: single-precision workspace-size query for singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnSgesvd_bufferSize);
513dn_gesvd_bufsize!(#[doc = "cuSOLVER: double-precision workspace-size query for singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnDgesvd_bufferSize);
514dn_gesvd_bufsize!(#[doc = "cuSOLVER: single-precision complex workspace-size query for singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnCgesvd_bufferSize);
515dn_gesvd_bufsize!(#[doc = "cuSOLVER: double-precision complex workspace-size query for singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnZgesvd_bufferSize);
516
517dn_gesvd_real!(#[doc = "cuSOLVER: single-precision singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnSgesvd, f32);
518dn_gesvd_real!(#[doc = "cuSOLVER: double-precision singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnDgesvd, f64);
519dn_gesvd_complex!(#[doc = "cuSOLVER: single-precision complex singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnCgesvd, cuComplex, f32);
520dn_gesvd_complex!(#[doc = "cuSOLVER: double-precision complex singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnZgesvd, cuDoubleComplex, f64);
521
522// ---- Symmetric/Hermitian eigendecomposition (syevd/heevd) --------------
523
524dn_syevd_bufsize!(#[doc = "cuSOLVER: single-precision workspace-size query for symmetric eigendecomposition (divide-and-conquer). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnSsyevd_bufferSize, f32, f32);
525dn_syevd_bufsize!(#[doc = "cuSOLVER: double-precision workspace-size query for symmetric eigendecomposition (divide-and-conquer). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnDsyevd_bufferSize, f64, f64);
526dn_syevd_bufsize!(#[doc = "cuSOLVER: single-precision complex workspace-size query for Hermitian eigendecomposition (divide-and-conquer). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnCheevd_bufferSize, cuComplex, f32);
527dn_syevd_bufsize!(#[doc = "cuSOLVER: double-precision complex workspace-size query for Hermitian eigendecomposition (divide-and-conquer). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnZheevd_bufferSize, cuDoubleComplex, f64);
528
529dn_syevd!(#[doc = "cuSOLVER: single-precision symmetric eigendecomposition (divide-and-conquer). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnSsyevd, f32, f32);
530dn_syevd!(#[doc = "cuSOLVER: double-precision symmetric eigendecomposition (divide-and-conquer). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnDsyevd, f64, f64);
531dn_syevd!(#[doc = "cuSOLVER: single-precision complex Hermitian eigendecomposition (divide-and-conquer). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnCheevd, cuComplex, f32);
532dn_syevd!(#[doc = "cuSOLVER: double-precision complex Hermitian eigendecomposition (divide-and-conquer). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnZheevd, cuDoubleComplex, f64);
533
534// ---- Generic 64-bit / mixed-precision API (cusolverDnX…) ----------------
535
536/// cuSOLVER: create a generic-API parameter object. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
537pub type PFN_cusolverDnCreateParams =
538    unsafe extern "C" fn(params: *mut cusolverDnParams_t) -> cusolverStatus_t;
539/// cuSOLVER: destroy a generic-API parameter object. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
540pub type PFN_cusolverDnDestroyParams =
541    unsafe extern "C" fn(params: cusolverDnParams_t) -> cusolverStatus_t;
542
543/// cuSOLVER: generic-API workspace-size query for LU factorization with partial pivoting (dtype configurable via `cudaDataType`). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
544pub type PFN_cusolverDnXgetrf_bufferSize = unsafe extern "C" fn(
545    handle: cusolverDnHandle_t,
546    params: cusolverDnParams_t,
547    m: i64,
548    n: i64,
549    data_type_a: cudaDataType,
550    a: *const c_void,
551    lda: i64,
552    compute_type: cudaDataType,
553    workspace_in_bytes_on_device: *mut usize,
554    workspace_in_bytes_on_host: *mut usize,
555) -> cusolverStatus_t;
556
557/// cuSOLVER: generic-API LU factorization with partial pivoting (dtype configurable via `cudaDataType`). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
558pub type PFN_cusolverDnXgetrf = unsafe extern "C" fn(
559    handle: cusolverDnHandle_t,
560    params: cusolverDnParams_t,
561    m: i64,
562    n: i64,
563    data_type_a: cudaDataType,
564    a: *mut c_void,
565    lda: i64,
566    ipiv: *mut i64,
567    compute_type: cudaDataType,
568    bufferondevice: *mut c_void,
569    workspace_in_bytes_on_device: usize,
570    bufferonhost: *mut c_void,
571    workspace_in_bytes_on_host: usize,
572    info: *mut c_int,
573) -> cusolverStatus_t;
574
575/// cuSOLVER: generic-API solve linear system using LU factors (dtype configurable via `cudaDataType`). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
576pub type PFN_cusolverDnXgetrs = unsafe extern "C" fn(
577    handle: cusolverDnHandle_t,
578    params: cusolverDnParams_t,
579    trans: cublasOperation_t,
580    n: i64,
581    nrhs: i64,
582    data_type_a: cudaDataType,
583    a: *const c_void,
584    lda: i64,
585    ipiv: *const i64,
586    data_type_b: cudaDataType,
587    b: *mut c_void,
588    ldb: i64,
589    info: *mut c_int,
590) -> cusolverStatus_t;
591
592/// cuSOLVER: generic-API workspace-size query for QR factorization (Householder) (dtype configurable via `cudaDataType`). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
593pub type PFN_cusolverDnXgeqrf_bufferSize = unsafe extern "C" fn(
594    handle: cusolverDnHandle_t,
595    params: cusolverDnParams_t,
596    m: i64,
597    n: i64,
598    data_type_a: cudaDataType,
599    a: *const c_void,
600    lda: i64,
601    data_type_tau: cudaDataType,
602    tau: *const c_void,
603    compute_type: cudaDataType,
604    workspace_in_bytes_on_device: *mut usize,
605    workspace_in_bytes_on_host: *mut usize,
606) -> cusolverStatus_t;
607
608/// cuSOLVER: generic-API QR factorization (Householder) (dtype configurable via `cudaDataType`). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
609pub type PFN_cusolverDnXgeqrf = unsafe extern "C" fn(
610    handle: cusolverDnHandle_t,
611    params: cusolverDnParams_t,
612    m: i64,
613    n: i64,
614    data_type_a: cudaDataType,
615    a: *mut c_void,
616    lda: i64,
617    data_type_tau: cudaDataType,
618    tau: *mut c_void,
619    compute_type: cudaDataType,
620    bufferondevice: *mut c_void,
621    workspace_in_bytes_on_device: usize,
622    bufferonhost: *mut c_void,
623    workspace_in_bytes_on_host: usize,
624    info: *mut c_int,
625) -> cusolverStatus_t;
626
627/// cuSOLVER: generic-API workspace-size query for Cholesky factorization (dtype configurable via `cudaDataType`). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
628pub type PFN_cusolverDnXpotrf_bufferSize = unsafe extern "C" fn(
629    handle: cusolverDnHandle_t,
630    params: cusolverDnParams_t,
631    uplo: cublasFillMode_t,
632    n: i64,
633    data_type_a: cudaDataType,
634    a: *const c_void,
635    lda: i64,
636    compute_type: cudaDataType,
637    workspace_in_bytes_on_device: *mut usize,
638    workspace_in_bytes_on_host: *mut usize,
639) -> cusolverStatus_t;
640
641/// cuSOLVER: generic-API Cholesky factorization (dtype configurable via `cudaDataType`). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
642pub type PFN_cusolverDnXpotrf = unsafe extern "C" fn(
643    handle: cusolverDnHandle_t,
644    params: cusolverDnParams_t,
645    uplo: cublasFillMode_t,
646    n: i64,
647    data_type_a: cudaDataType,
648    a: *mut c_void,
649    lda: i64,
650    compute_type: cudaDataType,
651    bufferondevice: *mut c_void,
652    workspace_in_bytes_on_device: usize,
653    bufferonhost: *mut c_void,
654    workspace_in_bytes_on_host: usize,
655    info: *mut c_int,
656) -> cusolverStatus_t;
657
658/// cuSOLVER: generic-API solve linear system using Cholesky factors (dtype configurable via `cudaDataType`). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
659pub type PFN_cusolverDnXpotrs = unsafe extern "C" fn(
660    handle: cusolverDnHandle_t,
661    params: cusolverDnParams_t,
662    uplo: cublasFillMode_t,
663    n: i64,
664    nrhs: i64,
665    data_type_a: cudaDataType,
666    a: *const c_void,
667    lda: i64,
668    data_type_b: cudaDataType,
669    b: *mut c_void,
670    ldb: i64,
671    info: *mut c_int,
672) -> cusolverStatus_t;
673
674/// cuSOLVER: generic-API workspace-size query for symmetric eigendecomposition (divide-and-conquer) (dtype configurable via `cudaDataType`). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
675pub type PFN_cusolverDnXsyevd_bufferSize = unsafe extern "C" fn(
676    handle: cusolverDnHandle_t,
677    params: cusolverDnParams_t,
678    jobz: cusolverEigMode_t,
679    uplo: cublasFillMode_t,
680    n: i64,
681    data_type_a: cudaDataType,
682    a: *const c_void,
683    lda: i64,
684    data_type_w: cudaDataType,
685    w: *const c_void,
686    compute_type: cudaDataType,
687    device_bytes: *mut usize,
688    host_bytes: *mut usize,
689) -> cusolverStatus_t;
690
691/// cuSOLVER: generic-API symmetric eigendecomposition (divide-and-conquer) (dtype configurable via `cudaDataType`). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
692pub type PFN_cusolverDnXsyevd = unsafe extern "C" fn(
693    handle: cusolverDnHandle_t,
694    params: cusolverDnParams_t,
695    jobz: cusolverEigMode_t,
696    uplo: cublasFillMode_t,
697    n: i64,
698    data_type_a: cudaDataType,
699    a: *mut c_void,
700    lda: i64,
701    data_type_w: cudaDataType,
702    w: *mut c_void,
703    compute_type: cudaDataType,
704    bufferondevice: *mut c_void,
705    device_bytes: usize,
706    bufferonhost: *mut c_void,
707    host_bytes: usize,
708    info: *mut c_int,
709) -> cusolverStatus_t;
710
711// ==========================================================================
712// Jacobi-based eigendecompositions + SVD
713// ==========================================================================
714
715/// cuSOLVER: create a Jacobi-eigendecomposition control object. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
716pub type PFN_cusolverDnCreateSyevjInfo =
717    unsafe extern "C" fn(info: *mut syevjInfo_t) -> cusolverStatus_t;
718/// cuSOLVER: destroy a Jacobi-eigendecomposition control object. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
719pub type PFN_cusolverDnDestroySyevjInfo =
720    unsafe extern "C" fn(info: syevjInfo_t) -> cusolverStatus_t;
721/// cuSOLVER: set convergence tolerance on a Jacobi-eigendecomposition control object. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
722pub type PFN_cusolverDnXsyevjSetTolerance =
723    unsafe extern "C" fn(info: syevjInfo_t, tolerance: f64) -> cusolverStatus_t;
724/// cuSOLVER: set the maximum number of sweeps on a Jacobi-eigendecomposition control object. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
725pub type PFN_cusolverDnXsyevjSetMaxSweeps =
726    unsafe extern "C" fn(info: syevjInfo_t, max_sweeps: c_int) -> cusolverStatus_t;
727
728macro_rules! dn_syevj_bufsize {
729    ($(#[$attr:meta])* $name:ident, $t:ty, $real:ty) => {
730        $(#[$attr])*
731        pub type $name = unsafe extern "C" fn(
732            handle: cusolverDnHandle_t,
733            jobz: cusolverEigMode_t,
734            uplo: cublasFillMode_t,
735            n: c_int,
736            a: *const $t,
737            lda: c_int,
738            w: *const $real,
739            lwork: *mut c_int,
740            params: syevjInfo_t,
741        ) -> cusolverStatus_t;
742    };
743}
744dn_syevj_bufsize!(#[doc = "cuSOLVER: single-precision workspace-size query for symmetric eigendecomposition (Jacobi). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnSsyevj_bufferSize, f32, f32);
745dn_syevj_bufsize!(#[doc = "cuSOLVER: double-precision workspace-size query for symmetric eigendecomposition (Jacobi). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnDsyevj_bufferSize, f64, f64);
746dn_syevj_bufsize!(#[doc = "cuSOLVER: single-precision complex workspace-size query for Hermitian eigendecomposition (Jacobi). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnCheevj_bufferSize, cuComplex, f32);
747dn_syevj_bufsize!(#[doc = "cuSOLVER: double-precision complex workspace-size query for Hermitian eigendecomposition (Jacobi). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnZheevj_bufferSize, cuDoubleComplex, f64);
748
749macro_rules! dn_syevj {
750    ($(#[$attr:meta])* $name:ident, $t:ty, $real:ty) => {
751        $(#[$attr])*
752        pub type $name = unsafe extern "C" fn(
753            handle: cusolverDnHandle_t,
754            jobz: cusolverEigMode_t,
755            uplo: cublasFillMode_t,
756            n: c_int,
757            a: *mut $t,
758            lda: c_int,
759            w: *mut $real,
760            work: *mut $t,
761            lwork: c_int,
762            info: *mut c_int,
763            params: syevjInfo_t,
764        ) -> cusolverStatus_t;
765    };
766}
767dn_syevj!(#[doc = "cuSOLVER: single-precision symmetric eigendecomposition (Jacobi). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnSsyevj, f32, f32);
768dn_syevj!(#[doc = "cuSOLVER: double-precision symmetric eigendecomposition (Jacobi). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnDsyevj, f64, f64);
769dn_syevj!(#[doc = "cuSOLVER: single-precision complex Hermitian eigendecomposition (Jacobi). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnCheevj, cuComplex, f32);
770dn_syevj!(#[doc = "cuSOLVER: double-precision complex Hermitian eigendecomposition (Jacobi). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnZheevj, cuDoubleComplex, f64);
771
772/// cuSOLVER: create a Jacobi-SVD control object. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
773pub type PFN_cusolverDnCreateGesvdjInfo =
774    unsafe extern "C" fn(info: *mut gesvdjInfo_t) -> cusolverStatus_t;
775/// cuSOLVER: destroy a Jacobi-SVD control object. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
776pub type PFN_cusolverDnDestroyGesvdjInfo =
777    unsafe extern "C" fn(info: gesvdjInfo_t) -> cusolverStatus_t;
778
779macro_rules! dn_gesvdj_bufsize {
780    ($(#[$attr:meta])* $name:ident, $t:ty, $real:ty) => {
781        $(#[$attr])*
782        pub type $name = unsafe extern "C" fn(
783            handle: cusolverDnHandle_t,
784            jobz: cusolverEigMode_t,
785            econ: c_int,
786            m: c_int,
787            n: c_int,
788            a: *const $t,
789            lda: c_int,
790            s: *const $real,
791            u: *const $t,
792            ldu: c_int,
793            v: *const $t,
794            ldv: c_int,
795            lwork: *mut c_int,
796            params: gesvdjInfo_t,
797        ) -> cusolverStatus_t;
798    };
799}
800dn_gesvdj_bufsize!(#[doc = "cuSOLVER: single-precision workspace-size query for Jacobi-method singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnSgesvdj_bufferSize, f32, f32);
801dn_gesvdj_bufsize!(#[doc = "cuSOLVER: double-precision workspace-size query for Jacobi-method singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnDgesvdj_bufferSize, f64, f64);
802dn_gesvdj_bufsize!(#[doc = "cuSOLVER: single-precision complex workspace-size query for Jacobi-method singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnCgesvdj_bufferSize, cuComplex, f32);
803dn_gesvdj_bufsize!(#[doc = "cuSOLVER: double-precision complex workspace-size query for Jacobi-method singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnZgesvdj_bufferSize, cuDoubleComplex, f64);
804
805macro_rules! dn_gesvdj {
806    ($(#[$attr:meta])* $name:ident, $t:ty, $real:ty) => {
807        $(#[$attr])*
808        pub type $name = unsafe extern "C" fn(
809            handle: cusolverDnHandle_t,
810            jobz: cusolverEigMode_t,
811            econ: c_int,
812            m: c_int,
813            n: c_int,
814            a: *mut $t,
815            lda: c_int,
816            s: *mut $real,
817            u: *mut $t,
818            ldu: c_int,
819            v: *mut $t,
820            ldv: c_int,
821            work: *mut $t,
822            lwork: c_int,
823            info: *mut c_int,
824            params: gesvdjInfo_t,
825        ) -> cusolverStatus_t;
826    };
827}
828dn_gesvdj!(#[doc = "cuSOLVER: single-precision Jacobi-method singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnSgesvdj, f32, f32);
829dn_gesvdj!(#[doc = "cuSOLVER: double-precision Jacobi-method singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnDgesvdj, f64, f64);
830dn_gesvdj!(#[doc = "cuSOLVER: single-precision complex Jacobi-method singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnCgesvdj, cuComplex, f32);
831dn_gesvdj!(#[doc = "cuSOLVER: double-precision complex Jacobi-method singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnZgesvdj, cuDoubleComplex, f64);
832
833// ==========================================================================
834// Apply Q from QR (orgqr / ormqr)
835// ==========================================================================
836
837macro_rules! dn_orgqr_bufsize {
838    ($(#[$attr:meta])* $name:ident, $t:ty) => {
839        $(#[$attr])*
840        pub type $name = unsafe extern "C" fn(
841            handle: cusolverDnHandle_t,
842            m: c_int,
843            n: c_int,
844            k: c_int,
845            a: *const $t,
846            lda: c_int,
847            tau: *const $t,
848            lwork: *mut c_int,
849        ) -> cusolverStatus_t;
850    };
851}
852dn_orgqr_bufsize!(#[doc = "cuSOLVER: single-precision workspace-size query for generate the explicit Q from a QR factorization. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnSorgqr_bufferSize, f32);
853dn_orgqr_bufsize!(#[doc = "cuSOLVER: double-precision workspace-size query for generate the explicit Q from a QR factorization. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnDorgqr_bufferSize, f64);
854dn_orgqr_bufsize!(#[doc = "cuSOLVER: single-precision complex workspace-size query for generate the explicit unitary Q from a QR factorization. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnCungqr_bufferSize, cuComplex);
855dn_orgqr_bufsize!(#[doc = "cuSOLVER: double-precision complex workspace-size query for generate the explicit unitary Q from a QR factorization. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnZungqr_bufferSize, cuDoubleComplex);
856
857macro_rules! dn_orgqr {
858    ($(#[$attr:meta])* $name:ident, $t:ty) => {
859        $(#[$attr])*
860        pub type $name = unsafe extern "C" fn(
861            handle: cusolverDnHandle_t,
862            m: c_int,
863            n: c_int,
864            k: c_int,
865            a: *mut $t,
866            lda: c_int,
867            tau: *const $t,
868            work: *mut $t,
869            lwork: c_int,
870            info: *mut c_int,
871        ) -> cusolverStatus_t;
872    };
873}
874dn_orgqr!(#[doc = "cuSOLVER: single-precision generate the explicit Q from a QR factorization. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnSorgqr, f32);
875dn_orgqr!(#[doc = "cuSOLVER: double-precision generate the explicit Q from a QR factorization. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnDorgqr, f64);
876dn_orgqr!(#[doc = "cuSOLVER: single-precision complex generate the explicit unitary Q from a QR factorization. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnCungqr, cuComplex);
877dn_orgqr!(#[doc = "cuSOLVER: double-precision complex generate the explicit unitary Q from a QR factorization. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnZungqr, cuDoubleComplex);
878
879macro_rules! dn_ormqr_bufsize {
880    ($(#[$attr:meta])* $name:ident, $t:ty) => {
881        $(#[$attr])*
882        pub type $name = unsafe extern "C" fn(
883            handle: cusolverDnHandle_t,
884            side: c_int,
885            trans: cublasOperation_t,
886            m: c_int,
887            n: c_int,
888            k: c_int,
889            a: *const $t,
890            lda: c_int,
891            tau: *const $t,
892            c: *const $t,
893            ldc: c_int,
894            lwork: *mut c_int,
895        ) -> cusolverStatus_t;
896    };
897}
898dn_ormqr_bufsize!(#[doc = "cuSOLVER: single-precision workspace-size query for apply Q (or Q^T) from a QR factorization to a matrix. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnSormqr_bufferSize, f32);
899dn_ormqr_bufsize!(#[doc = "cuSOLVER: double-precision workspace-size query for apply Q (or Q^T) from a QR factorization to a matrix. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnDormqr_bufferSize, f64);
900dn_ormqr_bufsize!(#[doc = "cuSOLVER: single-precision complex workspace-size query for apply Q (or Q^H) from a QR factorization to a matrix. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnCunmqr_bufferSize, cuComplex);
901dn_ormqr_bufsize!(#[doc = "cuSOLVER: double-precision complex workspace-size query for apply Q (or Q^H) from a QR factorization to a matrix. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnZunmqr_bufferSize, cuDoubleComplex);
902
903macro_rules! dn_ormqr {
904    ($(#[$attr:meta])* $name:ident, $t:ty) => {
905        $(#[$attr])*
906        pub type $name = unsafe extern "C" fn(
907            handle: cusolverDnHandle_t,
908            side: c_int,
909            trans: cublasOperation_t,
910            m: c_int,
911            n: c_int,
912            k: c_int,
913            a: *const $t,
914            lda: c_int,
915            tau: *const $t,
916            c: *mut $t,
917            ldc: c_int,
918            work: *mut $t,
919            lwork: c_int,
920            info: *mut c_int,
921        ) -> cusolverStatus_t;
922    };
923}
924dn_ormqr!(#[doc = "cuSOLVER: single-precision apply Q (or Q^T) from a QR factorization to a matrix. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnSormqr, f32);
925dn_ormqr!(#[doc = "cuSOLVER: double-precision apply Q (or Q^T) from a QR factorization to a matrix. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnDormqr, f64);
926dn_ormqr!(#[doc = "cuSOLVER: single-precision complex apply Q (or Q^H) from a QR factorization to a matrix. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnCunmqr, cuComplex);
927dn_ormqr!(#[doc = "cuSOLVER: double-precision complex apply Q (or Q^H) from a QR factorization to a matrix. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnZunmqr, cuDoubleComplex);
928
929// ---- Sparse cuSOLVER -----------------------------------------------------
930
931/// cuSOLVER: create a sparse cuSOLVER handle. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
932pub type PFN_cusolverSpCreate =
933    unsafe extern "C" fn(handle: *mut cusolverSpHandle_t) -> cusolverStatus_t;
934/// cuSOLVER: destroy a sparse cuSOLVER handle. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
935pub type PFN_cusolverSpDestroy =
936    unsafe extern "C" fn(handle: cusolverSpHandle_t) -> cusolverStatus_t;
937/// cuSOLVER: bind a CUDA stream to a sparse cuSOLVER handle. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
938pub type PFN_cusolverSpSetStream =
939    unsafe extern "C" fn(handle: cusolverSpHandle_t, stream: cudaStream_t) -> cusolverStatus_t;
940
941/// cuSOLVER: single-precision sparse linear solve via Cholesky on a CSR matrix. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
942pub type PFN_cusolverSpScsrlsvchol = unsafe extern "C" fn(
943    handle: cusolverSpHandle_t,
944    m: c_int,
945    nnz: c_int,
946    descr_a: *mut c_void,
947    csr_val: *const f32,
948    csr_row_ptr: *const c_int,
949    csr_col_ind: *const c_int,
950    b: *const f32,
951    tol: f32,
952    reorder: c_int,
953    x: *mut f32,
954    singularity: *mut c_int,
955) -> cusolverStatus_t;
956
957/// cuSOLVER: double-precision sparse linear solve via Cholesky on a CSR matrix. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
958pub type PFN_cusolverSpDcsrlsvchol = unsafe extern "C" fn(
959    handle: cusolverSpHandle_t,
960    m: c_int,
961    nnz: c_int,
962    descr_a: *mut c_void,
963    csr_val: *const f64,
964    csr_row_ptr: *const c_int,
965    csr_col_ind: *const c_int,
966    b: *const f64,
967    tol: f64,
968    reorder: c_int,
969    x: *mut f64,
970    singularity: *mut c_int,
971) -> cusolverStatus_t;
972
973/// cuSOLVER: single-precision sparse linear solve via QR on a CSR matrix. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
974pub type PFN_cusolverSpScsrlsvqr = unsafe extern "C" fn(
975    handle: cusolverSpHandle_t,
976    m: c_int,
977    nnz: c_int,
978    descr_a: *mut c_void,
979    csr_val: *const f32,
980    csr_row_ptr: *const c_int,
981    csr_col_ind: *const c_int,
982    b: *const f32,
983    tol: f32,
984    reorder: c_int,
985    x: *mut f32,
986    singularity: *mut c_int,
987) -> cusolverStatus_t;
988
989/// cuSOLVER: double-precision sparse linear solve via QR on a CSR matrix. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
990pub type PFN_cusolverSpDcsrlsvqr = unsafe extern "C" fn(
991    handle: cusolverSpHandle_t,
992    m: c_int,
993    nnz: c_int,
994    descr_a: *mut c_void,
995    csr_val: *const f64,
996    csr_row_ptr: *const c_int,
997    csr_col_ind: *const c_int,
998    b: *const f64,
999    tol: f64,
1000    reorder: c_int,
1001    x: *mut f64,
1002    singularity: *mut c_int,
1003) -> cusolverStatus_t;
1004
1005// ---- Refactor (Rf) sparse LU refactorization -----------------------------
1006
1007/// cuSOLVER: create a sparse-refactor cuSOLVER handle. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1008pub type PFN_cusolverRfCreate =
1009    unsafe extern "C" fn(handle: *mut cusolverRfHandle_t) -> cusolverStatus_t;
1010/// cuSOLVER: destroy a sparse-refactor cuSOLVER handle. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1011pub type PFN_cusolverRfDestroy =
1012    unsafe extern "C" fn(handle: cusolverRfHandle_t) -> cusolverStatus_t;
1013/// cuSOLVER: supply sparse triangular factors and pivot vectors to the refactor handle. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1014pub type PFN_cusolverRfSetupDevice = unsafe extern "C" fn(
1015    n: c_int,
1016    nnz_a: c_int,
1017    h_csr_row_ptr_a: *mut c_int,
1018    h_csr_col_ind_a: *mut c_int,
1019    h_csr_val_a: *mut f64,
1020    nnz_l: c_int,
1021    h_csr_row_ptr_l: *mut c_int,
1022    h_csr_col_ind_l: *mut c_int,
1023    h_csr_val_l: *mut f64,
1024    nnz_u: c_int,
1025    h_csr_row_ptr_u: *mut c_int,
1026    h_csr_col_ind_u: *mut c_int,
1027    h_csr_val_u: *mut f64,
1028    p: *mut c_int,
1029    q: *mut c_int,
1030    handle: cusolverRfHandle_t,
1031) -> cusolverStatus_t;
1032/// cuSOLVER: analyze the sparsity pattern of the refactor handle. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1033pub type PFN_cusolverRfAnalyze =
1034    unsafe extern "C" fn(handle: cusolverRfHandle_t) -> cusolverStatus_t;
1035/// cuSOLVER: refactor with new numerical values reusing the analyzed pattern. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1036pub type PFN_cusolverRfRefactor =
1037    unsafe extern "C" fn(handle: cusolverRfHandle_t) -> cusolverStatus_t;
1038/// cuSOLVER: solve linear systems using the refactor handle. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1039pub type PFN_cusolverRfSolve = unsafe extern "C" fn(
1040    handle: cusolverRfHandle_t,
1041    p: *mut c_int,
1042    q: *mut c_int,
1043    nrhs: c_int,
1044    temp: *mut f64,
1045    ld_temp: c_int,
1046    xf: *mut f64,
1047    ld_xf: c_int,
1048) -> cusolverStatus_t;
1049
1050// ==========================================================================
1051// Least-squares (gels): A*X = B → X
1052// ==========================================================================
1053
1054macro_rules! dn_gels_bufsize {
1055    ($(#[$attr:meta])* $name:ident, $t:ty) => {
1056        $(#[$attr])*
1057        pub type $name = unsafe extern "C" fn(
1058            handle: cusolverDnHandle_t,
1059            m: c_int,
1060            n: c_int,
1061            nrhs: c_int,
1062            d_a: *mut $t,
1063            lda: c_int,
1064            d_b: *mut $t,
1065            ldb: c_int,
1066            d_x: *mut $t,
1067            ldx: c_int,
1068            d_work: *mut c_void,
1069            lwork_bytes: *mut usize,
1070        ) -> cusolverStatus_t;
1071    };
1072}
1073dn_gels_bufsize!(#[doc = "cuSOLVER: single-precision workspace-size query for least-squares solver (A*X = B). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnSSgels_bufferSize, f32);
1074dn_gels_bufsize!(#[doc = "cuSOLVER: double-precision workspace-size query for least-squares solver (A*X = B). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnDDgels_bufferSize, f64);
1075dn_gels_bufsize!(#[doc = "cuSOLVER: single-precision complex workspace-size query for least-squares solver (A*X = B). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnCCgels_bufferSize, cuComplex);
1076dn_gels_bufsize!(#[doc = "cuSOLVER: double-precision complex workspace-size query for least-squares solver (A*X = B). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnZZgels_bufferSize, cuDoubleComplex);
1077
1078macro_rules! dn_gels {
1079    ($(#[$attr:meta])* $name:ident, $t:ty) => {
1080        $(#[$attr])*
1081        pub type $name = unsafe extern "C" fn(
1082            handle: cusolverDnHandle_t,
1083            m: c_int,
1084            n: c_int,
1085            nrhs: c_int,
1086            d_a: *mut $t,
1087            lda: c_int,
1088            d_b: *mut $t,
1089            ldb: c_int,
1090            d_x: *mut $t,
1091            ldx: c_int,
1092            d_work: *mut c_void,
1093            lwork_bytes: usize,
1094            iter: *mut c_int,
1095            d_info: *mut c_int,
1096        ) -> cusolverStatus_t;
1097    };
1098}
1099dn_gels!(#[doc = "cuSOLVER: single-precision least-squares solver (A*X = B). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnSSgels, f32);
1100dn_gels!(#[doc = "cuSOLVER: double-precision least-squares solver (A*X = B). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnDDgels, f64);
1101dn_gels!(#[doc = "cuSOLVER: single-precision complex least-squares solver (A*X = B). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnCCgels, cuComplex);
1102dn_gels!(#[doc = "cuSOLVER: double-precision complex least-squares solver (A*X = B). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnZZgels, cuDoubleComplex);
1103
1104// ==========================================================================
1105// Inverse from Cholesky (potri)
1106// ==========================================================================
1107
1108macro_rules! dn_potri_bufsize {
1109    ($(#[$attr:meta])* $name:ident, $t:ty) => {
1110        $(#[$attr])*
1111        pub type $name = unsafe extern "C" fn(
1112            handle: cusolverDnHandle_t,
1113            uplo: cublasFillMode_t,
1114            n: c_int,
1115            a: *mut $t,
1116            lda: c_int,
1117            lwork: *mut c_int,
1118        ) -> cusolverStatus_t;
1119    };
1120}
1121dn_potri_bufsize!(#[doc = "cuSOLVER: single-precision workspace-size query for matrix inverse from Cholesky factors. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnSpotri_bufferSize, f32);
1122dn_potri_bufsize!(#[doc = "cuSOLVER: double-precision workspace-size query for matrix inverse from Cholesky factors. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnDpotri_bufferSize, f64);
1123dn_potri_bufsize!(#[doc = "cuSOLVER: single-precision complex workspace-size query for matrix inverse from Cholesky factors. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnCpotri_bufferSize, cuComplex);
1124dn_potri_bufsize!(#[doc = "cuSOLVER: double-precision complex workspace-size query for matrix inverse from Cholesky factors. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnZpotri_bufferSize, cuDoubleComplex);
1125
1126macro_rules! dn_potri {
1127    ($(#[$attr:meta])* $name:ident, $t:ty) => {
1128        $(#[$attr])*
1129        pub type $name = unsafe extern "C" fn(
1130            handle: cusolverDnHandle_t,
1131            uplo: cublasFillMode_t,
1132            n: c_int,
1133            a: *mut $t,
1134            lda: c_int,
1135            work: *mut $t,
1136            lwork: c_int,
1137            info: *mut c_int,
1138        ) -> cusolverStatus_t;
1139    };
1140}
1141dn_potri!(#[doc = "cuSOLVER: single-precision matrix inverse from Cholesky factors. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnSpotri, f32);
1142dn_potri!(#[doc = "cuSOLVER: double-precision matrix inverse from Cholesky factors. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnDpotri, f64);
1143dn_potri!(#[doc = "cuSOLVER: single-precision complex matrix inverse from Cholesky factors. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnCpotri, cuComplex);
1144dn_potri!(#[doc = "cuSOLVER: double-precision complex matrix inverse from Cholesky factors. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnZpotri, cuDoubleComplex);
1145
1146// ==========================================================================
1147// Batched Jacobi eigen / SVD
1148// ==========================================================================
1149
1150macro_rules! dn_syevj_batched_bufsize {
1151    ($(#[$attr:meta])* $name:ident, $t:ty, $real:ty) => {
1152        $(#[$attr])*
1153        pub type $name = unsafe extern "C" fn(
1154            handle: cusolverDnHandle_t,
1155            jobz: cusolverEigMode_t,
1156            uplo: cublasFillMode_t,
1157            n: c_int,
1158            a: *const $t,
1159            lda: c_int,
1160            w: *const $real,
1161            lwork: *mut c_int,
1162            params: syevjInfo_t,
1163            batch_size: c_int,
1164        ) -> cusolverStatus_t;
1165    };
1166}
1167dn_syevj_batched_bufsize!(#[doc = "cuSOLVER: single-precision workspace-size query for batched symmetric eigendecomposition (Jacobi). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnSsyevjBatched_bufferSize, f32, f32);
1168dn_syevj_batched_bufsize!(#[doc = "cuSOLVER: double-precision workspace-size query for batched symmetric eigendecomposition (Jacobi). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnDsyevjBatched_bufferSize, f64, f64);
1169dn_syevj_batched_bufsize!(#[doc = "cuSOLVER: single-precision complex workspace-size query for batched Hermitian eigendecomposition (Jacobi). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnCheevjBatched_bufferSize, cuComplex, f32);
1170dn_syevj_batched_bufsize!(#[doc = "cuSOLVER: double-precision complex workspace-size query for batched Hermitian eigendecomposition (Jacobi). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnZheevjBatched_bufferSize, cuDoubleComplex, f64);
1171
1172macro_rules! dn_syevj_batched {
1173    ($(#[$attr:meta])* $name:ident, $t:ty, $real:ty) => {
1174        $(#[$attr])*
1175        pub type $name = unsafe extern "C" fn(
1176            handle: cusolverDnHandle_t,
1177            jobz: cusolverEigMode_t,
1178            uplo: cublasFillMode_t,
1179            n: c_int,
1180            a: *mut $t,
1181            lda: c_int,
1182            w: *mut $real,
1183            work: *mut $t,
1184            lwork: c_int,
1185            info: *mut c_int,
1186            params: syevjInfo_t,
1187            batch_size: c_int,
1188        ) -> cusolverStatus_t;
1189    };
1190}
1191dn_syevj_batched!(#[doc = "cuSOLVER: single-precision batched symmetric eigendecomposition (Jacobi). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnSsyevjBatched, f32, f32);
1192dn_syevj_batched!(#[doc = "cuSOLVER: double-precision batched symmetric eigendecomposition (Jacobi). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnDsyevjBatched, f64, f64);
1193dn_syevj_batched!(#[doc = "cuSOLVER: single-precision complex batched Hermitian eigendecomposition (Jacobi). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnCheevjBatched, cuComplex, f32);
1194dn_syevj_batched!(#[doc = "cuSOLVER: double-precision complex batched Hermitian eigendecomposition (Jacobi). See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnZheevjBatched, cuDoubleComplex, f64);
1195
1196macro_rules! dn_gesvdj_batched_bufsize {
1197    ($(#[$attr:meta])* $name:ident, $t:ty, $real:ty) => {
1198        $(#[$attr])*
1199        pub type $name = unsafe extern "C" fn(
1200            handle: cusolverDnHandle_t,
1201            jobz: cusolverEigMode_t,
1202            m: c_int,
1203            n: c_int,
1204            a: *const $t,
1205            lda: c_int,
1206            s: *const $real,
1207            u: *const $t,
1208            ldu: c_int,
1209            v: *const $t,
1210            ldv: c_int,
1211            lwork: *mut c_int,
1212            params: gesvdjInfo_t,
1213            batch_size: c_int,
1214        ) -> cusolverStatus_t;
1215    };
1216}
1217dn_gesvdj_batched_bufsize!(#[doc = "cuSOLVER: single-precision workspace-size query for batched Jacobi-method singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnSgesvdjBatched_bufferSize, f32, f32);
1218dn_gesvdj_batched_bufsize!(#[doc = "cuSOLVER: double-precision workspace-size query for batched Jacobi-method singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnDgesvdjBatched_bufferSize, f64, f64);
1219dn_gesvdj_batched_bufsize!(#[doc = "cuSOLVER: single-precision complex workspace-size query for batched Jacobi-method singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnCgesvdjBatched_bufferSize, cuComplex, f32);
1220dn_gesvdj_batched_bufsize!(#[doc = "cuSOLVER: double-precision complex workspace-size query for batched Jacobi-method singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnZgesvdjBatched_bufferSize, cuDoubleComplex, f64);
1221
1222macro_rules! dn_gesvdj_batched {
1223    ($(#[$attr:meta])* $name:ident, $t:ty, $real:ty) => {
1224        $(#[$attr])*
1225        pub type $name = unsafe extern "C" fn(
1226            handle: cusolverDnHandle_t,
1227            jobz: cusolverEigMode_t,
1228            m: c_int,
1229            n: c_int,
1230            a: *mut $t,
1231            lda: c_int,
1232            s: *mut $real,
1233            u: *mut $t,
1234            ldu: c_int,
1235            v: *mut $t,
1236            ldv: c_int,
1237            work: *mut $t,
1238            lwork: c_int,
1239            info: *mut c_int,
1240            params: gesvdjInfo_t,
1241            batch_size: c_int,
1242        ) -> cusolverStatus_t;
1243    };
1244}
1245dn_gesvdj_batched!(#[doc = "cuSOLVER: single-precision batched Jacobi-method singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnSgesvdjBatched, f32, f32);
1246dn_gesvdj_batched!(#[doc = "cuSOLVER: double-precision batched Jacobi-method singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnDgesvdjBatched, f64, f64);
1247dn_gesvdj_batched!(#[doc = "cuSOLVER: single-precision complex batched Jacobi-method singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnCgesvdjBatched, cuComplex, f32);
1248dn_gesvdj_batched!(#[doc = "cuSOLVER: double-precision complex batched Jacobi-method singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>."] PFN_cusolverDnZgesvdjBatched, cuDoubleComplex, f64);
1249
1250// ==========================================================================
1251// cuSOLVERMg — multi-GPU dense solvers (separate library libcusolverMg)
1252// ==========================================================================
1253
1254/// Opaque multi-GPU dense cuSOLVERMg handle.
1255pub type cusolverMgHandle_t = *mut c_void;
1256/// Opaque multi-GPU matrix descriptor.
1257pub type cudaLibMgMatrixDesc_t = *mut c_void;
1258/// Opaque multi-GPU device grid.
1259pub type cudaLibMgGrid_t = *mut c_void;
1260
1261/// cuSOLVER: create a multi-GPU dense cuSOLVERMg handle. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1262pub type PFN_cusolverMgCreate =
1263    unsafe extern "C" fn(handle: *mut cusolverMgHandle_t) -> cusolverStatus_t;
1264/// cuSOLVER: destroy a multi-GPU dense cuSOLVERMg handle. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1265pub type PFN_cusolverMgDestroy =
1266    unsafe extern "C" fn(handle: cusolverMgHandle_t) -> cusolverStatus_t;
1267/// cuSOLVER: select GPU devices for a cuSOLVERMg handle. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1268pub type PFN_cusolverMgDeviceSelect = unsafe extern "C" fn(
1269    handle: cusolverMgHandle_t,
1270    n_devices: c_int,
1271    device_id: *const c_int,
1272) -> cusolverStatus_t;
1273
1274/// cuSOLVER: create a multi-GPU device grid. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1275pub type PFN_cusolverMgCreateDeviceGrid = unsafe extern "C" fn(
1276    grid: *mut cudaLibMgGrid_t,
1277    num_row_devices: i32,
1278    num_col_devices: i32,
1279    device_id: *const i32,
1280    mapping: i32,
1281) -> cusolverStatus_t;
1282
1283/// cuSOLVER: destroy a multi-GPU device grid. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1284pub type PFN_cusolverMgDestroyGrid =
1285    unsafe extern "C" fn(grid: cudaLibMgGrid_t) -> cusolverStatus_t;
1286
1287/// cuSOLVER: create a multi-GPU matrix descriptor. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1288pub type PFN_cusolverMgCreateMatrixDesc = unsafe extern "C" fn(
1289    desc: *mut cudaLibMgMatrixDesc_t,
1290    num_rows: i64,
1291    num_cols: i64,
1292    row_block_size: i64,
1293    col_block_size: i64,
1294    data_type: cudaDataType,
1295    grid: cudaLibMgGrid_t,
1296) -> cusolverStatus_t;
1297
1298/// cuSOLVER: destroy a multi-GPU matrix descriptor. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1299pub type PFN_cusolverMgDestroyMatrixDesc =
1300    unsafe extern "C" fn(desc: cudaLibMgMatrixDesc_t) -> cusolverStatus_t;
1301
1302/// cuSOLVER: multi-GPU workspace-size query for LU factorization with partial pivoting. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1303pub type PFN_cusolverMgGetrf_bufferSize = unsafe extern "C" fn(
1304    handle: cusolverMgHandle_t,
1305    m: c_int,
1306    n: c_int,
1307    array_d_a: *mut *mut c_void,
1308    ia: c_int,
1309    ja: c_int,
1310    desc_a: cudaLibMgMatrixDesc_t,
1311    array_d_ipiv: *mut *mut c_int,
1312    compute_type: cudaDataType,
1313    lwork: *mut i64,
1314) -> cusolverStatus_t;
1315
1316/// cuSOLVER: multi-GPU LU factorization with partial pivoting. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1317pub type PFN_cusolverMgGetrf = unsafe extern "C" fn(
1318    handle: cusolverMgHandle_t,
1319    m: c_int,
1320    n: c_int,
1321    array_d_a: *mut *mut c_void,
1322    ia: c_int,
1323    ja: c_int,
1324    desc_a: cudaLibMgMatrixDesc_t,
1325    array_d_ipiv: *mut *mut c_int,
1326    compute_type: cudaDataType,
1327    array_d_work: *mut *mut c_void,
1328    lwork: i64,
1329    info: *mut c_int,
1330) -> cusolverStatus_t;
1331
1332/// cuSOLVER: multi-GPU workspace-size query for Cholesky factorization. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1333pub type PFN_cusolverMgPotrf_bufferSize = unsafe extern "C" fn(
1334    handle: cusolverMgHandle_t,
1335    uplo: cublasFillMode_t,
1336    n: c_int,
1337    array_d_a: *mut *mut c_void,
1338    ia: c_int,
1339    ja: c_int,
1340    desc_a: cudaLibMgMatrixDesc_t,
1341    compute_type: cudaDataType,
1342    lwork: *mut i64,
1343) -> cusolverStatus_t;
1344
1345/// cuSOLVER: multi-GPU Cholesky factorization. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1346pub type PFN_cusolverMgPotrf = unsafe extern "C" fn(
1347    handle: cusolverMgHandle_t,
1348    uplo: cublasFillMode_t,
1349    n: c_int,
1350    array_d_a: *mut *mut c_void,
1351    ia: c_int,
1352    ja: c_int,
1353    desc_a: cudaLibMgMatrixDesc_t,
1354    compute_type: cudaDataType,
1355    array_d_work: *mut *mut c_void,
1356    lwork: i64,
1357    info: *mut c_int,
1358) -> cusolverStatus_t;
1359
1360/// cuSOLVER: multi-GPU workspace-size query for symmetric eigendecomposition (divide-and-conquer). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1361pub type PFN_cusolverMgSyevd_bufferSize = unsafe extern "C" fn(
1362    handle: cusolverMgHandle_t,
1363    jobz: cusolverEigMode_t,
1364    uplo: cublasFillMode_t,
1365    n: c_int,
1366    array_d_a: *mut *mut c_void,
1367    ia: c_int,
1368    ja: c_int,
1369    desc_a: cudaLibMgMatrixDesc_t,
1370    w: *mut c_void,
1371    data_type_w: cudaDataType,
1372    compute_type: cudaDataType,
1373    lwork: *mut i64,
1374) -> cusolverStatus_t;
1375
1376/// cuSOLVER: multi-GPU symmetric eigendecomposition (divide-and-conquer). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1377pub type PFN_cusolverMgSyevd = unsafe extern "C" fn(
1378    handle: cusolverMgHandle_t,
1379    jobz: cusolverEigMode_t,
1380    uplo: cublasFillMode_t,
1381    n: c_int,
1382    array_d_a: *mut *mut c_void,
1383    ia: c_int,
1384    ja: c_int,
1385    desc_a: cudaLibMgMatrixDesc_t,
1386    w: *mut c_void,
1387    data_type_w: cudaDataType,
1388    compute_type: cudaDataType,
1389    array_d_work: *mut *mut c_void,
1390    lwork: i64,
1391    info: *mut c_int,
1392) -> cusolverStatus_t;
1393
1394// ---- loader --------------------------------------------------------------
1395
1396fn cusolver_candidates() -> Vec<String> {
1397    platform::versioned_library_candidates("cusolver", &["13", "12", "11"])
1398}
1399
1400macro_rules! cusolver_fns {
1401    ($($(#[$m:meta])* $name:ident as $sym:literal : $pfn:ty);* $(;)?) => {
1402        /// Loaded cuSOLVER shared library plus a per-symbol `OnceLock` of function pointers.
1403        pub struct Cusolver {
1404            lib: Library,
1405            $($name: OnceLock<$pfn>,)*
1406        }
1407        impl core::fmt::Debug for Cusolver {
1408            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1409                f.debug_struct("Cusolver").field("lib", &self.lib).finish_non_exhaustive()
1410            }
1411        }
1412        impl Cusolver {
1413            $(
1414                $(#[$m])*
1415                pub fn $name(&self) -> Result<$pfn, LoaderError> {
1416                    if let Some(&p) = self.$name.get() { return Ok(p); }
1417                    let raw: *mut () = unsafe { self.lib.raw_symbol($sym)? };
1418                    let p: $pfn = unsafe { core::mem::transmute_copy::<*mut (), $pfn>(&raw) };
1419                    let _ = self.$name.set(p);
1420                    Ok(p)
1421                }
1422            )*
1423            fn empty(lib: Library) -> Self {
1424                Self { lib, $($name: OnceLock::new(),)* }
1425            }
1426        }
1427    };
1428}
1429
1430cusolver_fns! {
1431    // Dn handle
1432    /// cuSOLVER: create a dense cuSOLVER handle. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1433    cusolver_dn_create as "cusolverDnCreate": PFN_cusolverDnCreate;
1434    /// cuSOLVER: destroy a dense cuSOLVER handle. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1435    cusolver_dn_destroy as "cusolverDnDestroy": PFN_cusolverDnDestroy;
1436    /// cuSOLVER: bind a CUDA stream to a dense cuSOLVER handle. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1437    cusolver_dn_set_stream as "cusolverDnSetStream": PFN_cusolverDnSetStream;
1438    /// cuSOLVER: query the CUDA stream bound to a dense cuSOLVER handle. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1439    cusolver_dn_get_stream as "cusolverDnGetStream": PFN_cusolverDnGetStream;
1440    /// cuSOLVER: return the cuSOLVER library version. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1441    cusolver_get_version as "cusolverGetVersion": PFN_cusolverGetVersion;
1442    // LU (getrf/getrs) S/D/C/Z
1443    /// cuSOLVER: single-precision workspace-size query for LU factorization with partial pivoting. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1444    cusolver_dn_sgetrf_buffer_size as "cusolverDnSgetrf_bufferSize": PFN_cusolverDnSgetrf_bufferSize;
1445    /// cuSOLVER: double-precision workspace-size query for LU factorization with partial pivoting. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1446    cusolver_dn_dgetrf_buffer_size as "cusolverDnDgetrf_bufferSize": PFN_cusolverDnDgetrf_bufferSize;
1447    /// cuSOLVER: single-precision complex workspace-size query for LU factorization with partial pivoting. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1448    cusolver_dn_cgetrf_buffer_size as "cusolverDnCgetrf_bufferSize": PFN_cusolverDnCgetrf_bufferSize;
1449    /// cuSOLVER: double-precision complex workspace-size query for LU factorization with partial pivoting. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1450    cusolver_dn_zgetrf_buffer_size as "cusolverDnZgetrf_bufferSize": PFN_cusolverDnZgetrf_bufferSize;
1451    /// cuSOLVER: single-precision LU factorization with partial pivoting. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1452    cusolver_dn_sgetrf as "cusolverDnSgetrf": PFN_cusolverDnSgetrf;
1453    /// cuSOLVER: double-precision LU factorization with partial pivoting. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1454    cusolver_dn_dgetrf as "cusolverDnDgetrf": PFN_cusolverDnDgetrf;
1455    /// cuSOLVER: single-precision complex LU factorization with partial pivoting. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1456    cusolver_dn_cgetrf as "cusolverDnCgetrf": PFN_cusolverDnCgetrf;
1457    /// cuSOLVER: double-precision complex LU factorization with partial pivoting. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1458    cusolver_dn_zgetrf as "cusolverDnZgetrf": PFN_cusolverDnZgetrf;
1459    /// cuSOLVER: single-precision solve linear system using LU factors. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1460    cusolver_dn_sgetrs as "cusolverDnSgetrs": PFN_cusolverDnSgetrs;
1461    /// cuSOLVER: double-precision solve linear system using LU factors. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1462    cusolver_dn_dgetrs as "cusolverDnDgetrs": PFN_cusolverDnDgetrs;
1463    /// cuSOLVER: single-precision complex solve linear system using LU factors. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1464    cusolver_dn_cgetrs as "cusolverDnCgetrs": PFN_cusolverDnCgetrs;
1465    /// cuSOLVER: double-precision complex solve linear system using LU factors. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1466    cusolver_dn_zgetrs as "cusolverDnZgetrs": PFN_cusolverDnZgetrs;
1467    // QR (geqrf) S/D/C/Z
1468    /// cuSOLVER: single-precision workspace-size query for QR factorization (Householder). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1469    cusolver_dn_sgeqrf_buffer_size as "cusolverDnSgeqrf_bufferSize": PFN_cusolverDnSgeqrf_bufferSize;
1470    /// cuSOLVER: double-precision workspace-size query for QR factorization (Householder). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1471    cusolver_dn_dgeqrf_buffer_size as "cusolverDnDgeqrf_bufferSize": PFN_cusolverDnDgeqrf_bufferSize;
1472    /// cuSOLVER: single-precision complex workspace-size query for QR factorization (Householder). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1473    cusolver_dn_cgeqrf_buffer_size as "cusolverDnCgeqrf_bufferSize": PFN_cusolverDnCgeqrf_bufferSize;
1474    /// cuSOLVER: double-precision complex workspace-size query for QR factorization (Householder). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1475    cusolver_dn_zgeqrf_buffer_size as "cusolverDnZgeqrf_bufferSize": PFN_cusolverDnZgeqrf_bufferSize;
1476    /// cuSOLVER: single-precision QR factorization (Householder). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1477    cusolver_dn_sgeqrf as "cusolverDnSgeqrf": PFN_cusolverDnSgeqrf;
1478    /// cuSOLVER: double-precision QR factorization (Householder). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1479    cusolver_dn_dgeqrf as "cusolverDnDgeqrf": PFN_cusolverDnDgeqrf;
1480    /// cuSOLVER: single-precision complex QR factorization (Householder). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1481    cusolver_dn_cgeqrf as "cusolverDnCgeqrf": PFN_cusolverDnCgeqrf;
1482    /// cuSOLVER: double-precision complex QR factorization (Householder). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1483    cusolver_dn_zgeqrf as "cusolverDnZgeqrf": PFN_cusolverDnZgeqrf;
1484    // Cholesky (potrf/potrs) S/D/C/Z
1485    /// cuSOLVER: single-precision workspace-size query for Cholesky factorization. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1486    cusolver_dn_spotrf_buffer_size as "cusolverDnSpotrf_bufferSize": PFN_cusolverDnSpotrf_bufferSize;
1487    /// cuSOLVER: double-precision workspace-size query for Cholesky factorization. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1488    cusolver_dn_dpotrf_buffer_size as "cusolverDnDpotrf_bufferSize": PFN_cusolverDnDpotrf_bufferSize;
1489    /// cuSOLVER: single-precision complex workspace-size query for Cholesky factorization. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1490    cusolver_dn_cpotrf_buffer_size as "cusolverDnCpotrf_bufferSize": PFN_cusolverDnCpotrf_bufferSize;
1491    /// cuSOLVER: double-precision complex workspace-size query for Cholesky factorization. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1492    cusolver_dn_zpotrf_buffer_size as "cusolverDnZpotrf_bufferSize": PFN_cusolverDnZpotrf_bufferSize;
1493    /// cuSOLVER: single-precision Cholesky factorization. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1494    cusolver_dn_spotrf as "cusolverDnSpotrf": PFN_cusolverDnSpotrf;
1495    /// cuSOLVER: double-precision Cholesky factorization. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1496    cusolver_dn_dpotrf as "cusolverDnDpotrf": PFN_cusolverDnDpotrf;
1497    /// cuSOLVER: single-precision complex Cholesky factorization. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1498    cusolver_dn_cpotrf as "cusolverDnCpotrf": PFN_cusolverDnCpotrf;
1499    /// cuSOLVER: double-precision complex Cholesky factorization. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1500    cusolver_dn_zpotrf as "cusolverDnZpotrf": PFN_cusolverDnZpotrf;
1501    /// cuSOLVER: single-precision solve linear system using Cholesky factors. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1502    cusolver_dn_spotrs as "cusolverDnSpotrs": PFN_cusolverDnSpotrs;
1503    /// cuSOLVER: double-precision solve linear system using Cholesky factors. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1504    cusolver_dn_dpotrs as "cusolverDnDpotrs": PFN_cusolverDnDpotrs;
1505    /// cuSOLVER: single-precision complex solve linear system using Cholesky factors. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1506    cusolver_dn_cpotrs as "cusolverDnCpotrs": PFN_cusolverDnCpotrs;
1507    /// cuSOLVER: double-precision complex solve linear system using Cholesky factors. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1508    cusolver_dn_zpotrs as "cusolverDnZpotrs": PFN_cusolverDnZpotrs;
1509    // SVD S/D/C/Z
1510    /// cuSOLVER: single-precision workspace-size query for singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1511    cusolver_dn_sgesvd_buffer_size as "cusolverDnSgesvd_bufferSize": PFN_cusolverDnSgesvd_bufferSize;
1512    /// cuSOLVER: double-precision workspace-size query for singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1513    cusolver_dn_dgesvd_buffer_size as "cusolverDnDgesvd_bufferSize": PFN_cusolverDnDgesvd_bufferSize;
1514    /// cuSOLVER: single-precision complex workspace-size query for singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1515    cusolver_dn_cgesvd_buffer_size as "cusolverDnCgesvd_bufferSize": PFN_cusolverDnCgesvd_bufferSize;
1516    /// cuSOLVER: double-precision complex workspace-size query for singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1517    cusolver_dn_zgesvd_buffer_size as "cusolverDnZgesvd_bufferSize": PFN_cusolverDnZgesvd_bufferSize;
1518    /// cuSOLVER: single-precision singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1519    cusolver_dn_sgesvd as "cusolverDnSgesvd": PFN_cusolverDnSgesvd;
1520    /// cuSOLVER: double-precision singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1521    cusolver_dn_dgesvd as "cusolverDnDgesvd": PFN_cusolverDnDgesvd;
1522    /// cuSOLVER: single-precision complex singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1523    cusolver_dn_cgesvd as "cusolverDnCgesvd": PFN_cusolverDnCgesvd;
1524    /// cuSOLVER: double-precision complex singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1525    cusolver_dn_zgesvd as "cusolverDnZgesvd": PFN_cusolverDnZgesvd;
1526    // syevd / heevd
1527    /// cuSOLVER: single-precision workspace-size query for symmetric eigendecomposition (divide-and-conquer). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1528    cusolver_dn_ssyevd_buffer_size as "cusolverDnSsyevd_bufferSize": PFN_cusolverDnSsyevd_bufferSize;
1529    /// cuSOLVER: double-precision workspace-size query for symmetric eigendecomposition (divide-and-conquer). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1530    cusolver_dn_dsyevd_buffer_size as "cusolverDnDsyevd_bufferSize": PFN_cusolverDnDsyevd_bufferSize;
1531    /// cuSOLVER: single-precision complex workspace-size query for Hermitian eigendecomposition (divide-and-conquer). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1532    cusolver_dn_cheevd_buffer_size as "cusolverDnCheevd_bufferSize": PFN_cusolverDnCheevd_bufferSize;
1533    /// cuSOLVER: double-precision complex workspace-size query for Hermitian eigendecomposition (divide-and-conquer). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1534    cusolver_dn_zheevd_buffer_size as "cusolverDnZheevd_bufferSize": PFN_cusolverDnZheevd_bufferSize;
1535    /// cuSOLVER: single-precision symmetric eigendecomposition (divide-and-conquer). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1536    cusolver_dn_ssyevd as "cusolverDnSsyevd": PFN_cusolverDnSsyevd;
1537    /// cuSOLVER: double-precision symmetric eigendecomposition (divide-and-conquer). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1538    cusolver_dn_dsyevd as "cusolverDnDsyevd": PFN_cusolverDnDsyevd;
1539    /// cuSOLVER: single-precision complex Hermitian eigendecomposition (divide-and-conquer). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1540    cusolver_dn_cheevd as "cusolverDnCheevd": PFN_cusolverDnCheevd;
1541    /// cuSOLVER: double-precision complex Hermitian eigendecomposition (divide-and-conquer). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1542    cusolver_dn_zheevd as "cusolverDnZheevd": PFN_cusolverDnZheevd;
1543    // Generic 64-bit X… API
1544    /// cuSOLVER: create a generic-API parameter object. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1545    cusolver_dn_create_params as "cusolverDnCreateParams": PFN_cusolverDnCreateParams;
1546    /// cuSOLVER: destroy a generic-API parameter object. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1547    cusolver_dn_destroy_params as "cusolverDnDestroyParams": PFN_cusolverDnDestroyParams;
1548    /// cuSOLVER: generic-API workspace-size query for LU factorization with partial pivoting (dtype configurable via `cudaDataType`). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1549    cusolver_dn_xgetrf_buffer_size as "cusolverDnXgetrf_bufferSize": PFN_cusolverDnXgetrf_bufferSize;
1550    /// cuSOLVER: generic-API LU factorization with partial pivoting (dtype configurable via `cudaDataType`). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1551    cusolver_dn_xgetrf as "cusolverDnXgetrf": PFN_cusolverDnXgetrf;
1552    /// cuSOLVER: generic-API solve linear system using LU factors (dtype configurable via `cudaDataType`). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1553    cusolver_dn_xgetrs as "cusolverDnXgetrs": PFN_cusolverDnXgetrs;
1554    /// cuSOLVER: generic-API workspace-size query for QR factorization (Householder) (dtype configurable via `cudaDataType`). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1555    cusolver_dn_xgeqrf_buffer_size as "cusolverDnXgeqrf_bufferSize": PFN_cusolverDnXgeqrf_bufferSize;
1556    /// cuSOLVER: generic-API QR factorization (Householder) (dtype configurable via `cudaDataType`). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1557    cusolver_dn_xgeqrf as "cusolverDnXgeqrf": PFN_cusolverDnXgeqrf;
1558    /// cuSOLVER: generic-API workspace-size query for Cholesky factorization (dtype configurable via `cudaDataType`). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1559    cusolver_dn_xpotrf_buffer_size as "cusolverDnXpotrf_bufferSize": PFN_cusolverDnXpotrf_bufferSize;
1560    /// cuSOLVER: generic-API Cholesky factorization (dtype configurable via `cudaDataType`). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1561    cusolver_dn_xpotrf as "cusolverDnXpotrf": PFN_cusolverDnXpotrf;
1562    /// cuSOLVER: generic-API solve linear system using Cholesky factors (dtype configurable via `cudaDataType`). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1563    cusolver_dn_xpotrs as "cusolverDnXpotrs": PFN_cusolverDnXpotrs;
1564    /// cuSOLVER: generic-API workspace-size query for symmetric eigendecomposition (divide-and-conquer) (dtype configurable via `cudaDataType`). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1565    cusolver_dn_xsyevd_buffer_size as "cusolverDnXsyevd_bufferSize": PFN_cusolverDnXsyevd_bufferSize;
1566    /// cuSOLVER: generic-API symmetric eigendecomposition (divide-and-conquer) (dtype configurable via `cudaDataType`). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1567    cusolver_dn_xsyevd as "cusolverDnXsyevd": PFN_cusolverDnXsyevd;
1568    // Jacobi eigen
1569    /// cuSOLVER: create a Jacobi-eigendecomposition control object. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1570    cusolver_dn_create_syevj_info as "cusolverDnCreateSyevjInfo": PFN_cusolverDnCreateSyevjInfo;
1571    /// cuSOLVER: destroy a Jacobi-eigendecomposition control object. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1572    cusolver_dn_destroy_syevj_info as "cusolverDnDestroySyevjInfo": PFN_cusolverDnDestroySyevjInfo;
1573    /// cuSOLVER: set convergence tolerance on a Jacobi-eigendecomposition control object. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1574    cusolver_dn_xsyevj_set_tolerance as "cusolverDnXsyevjSetTolerance": PFN_cusolverDnXsyevjSetTolerance;
1575    /// cuSOLVER: set the maximum number of sweeps on a Jacobi-eigendecomposition control object. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1576    cusolver_dn_xsyevj_set_max_sweeps as "cusolverDnXsyevjSetMaxSweeps": PFN_cusolverDnXsyevjSetMaxSweeps;
1577    /// cuSOLVER: single-precision workspace-size query for symmetric eigendecomposition (Jacobi). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1578    cusolver_dn_ssyevj_buffer_size as "cusolverDnSsyevj_bufferSize": PFN_cusolverDnSsyevj_bufferSize;
1579    /// cuSOLVER: double-precision workspace-size query for symmetric eigendecomposition (Jacobi). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1580    cusolver_dn_dsyevj_buffer_size as "cusolverDnDsyevj_bufferSize": PFN_cusolverDnDsyevj_bufferSize;
1581    /// cuSOLVER: single-precision complex workspace-size query for Hermitian eigendecomposition (Jacobi). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1582    cusolver_dn_cheevj_buffer_size as "cusolverDnCheevj_bufferSize": PFN_cusolverDnCheevj_bufferSize;
1583    /// cuSOLVER: double-precision complex workspace-size query for Hermitian eigendecomposition (Jacobi). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1584    cusolver_dn_zheevj_buffer_size as "cusolverDnZheevj_bufferSize": PFN_cusolverDnZheevj_bufferSize;
1585    /// cuSOLVER: single-precision symmetric eigendecomposition (Jacobi). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1586    cusolver_dn_ssyevj as "cusolverDnSsyevj": PFN_cusolverDnSsyevj;
1587    /// cuSOLVER: double-precision symmetric eigendecomposition (Jacobi). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1588    cusolver_dn_dsyevj as "cusolverDnDsyevj": PFN_cusolverDnDsyevj;
1589    /// cuSOLVER: single-precision complex Hermitian eigendecomposition (Jacobi). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1590    cusolver_dn_cheevj as "cusolverDnCheevj": PFN_cusolverDnCheevj;
1591    /// cuSOLVER: double-precision complex Hermitian eigendecomposition (Jacobi). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1592    cusolver_dn_zheevj as "cusolverDnZheevj": PFN_cusolverDnZheevj;
1593    // Jacobi SVD
1594    /// cuSOLVER: create a Jacobi-SVD control object. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1595    cusolver_dn_create_gesvdj_info as "cusolverDnCreateGesvdjInfo": PFN_cusolverDnCreateGesvdjInfo;
1596    /// cuSOLVER: destroy a Jacobi-SVD control object. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1597    cusolver_dn_destroy_gesvdj_info as "cusolverDnDestroyGesvdjInfo": PFN_cusolverDnDestroyGesvdjInfo;
1598    /// cuSOLVER: single-precision workspace-size query for Jacobi-method singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1599    cusolver_dn_sgesvdj_buffer_size as "cusolverDnSgesvdj_bufferSize": PFN_cusolverDnSgesvdj_bufferSize;
1600    /// cuSOLVER: double-precision workspace-size query for Jacobi-method singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1601    cusolver_dn_dgesvdj_buffer_size as "cusolverDnDgesvdj_bufferSize": PFN_cusolverDnDgesvdj_bufferSize;
1602    /// cuSOLVER: single-precision complex workspace-size query for Jacobi-method singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1603    cusolver_dn_cgesvdj_buffer_size as "cusolverDnCgesvdj_bufferSize": PFN_cusolverDnCgesvdj_bufferSize;
1604    /// cuSOLVER: double-precision complex workspace-size query for Jacobi-method singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1605    cusolver_dn_zgesvdj_buffer_size as "cusolverDnZgesvdj_bufferSize": PFN_cusolverDnZgesvdj_bufferSize;
1606    /// cuSOLVER: single-precision Jacobi-method singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1607    cusolver_dn_sgesvdj as "cusolverDnSgesvdj": PFN_cusolverDnSgesvdj;
1608    /// cuSOLVER: double-precision Jacobi-method singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1609    cusolver_dn_dgesvdj as "cusolverDnDgesvdj": PFN_cusolverDnDgesvdj;
1610    /// cuSOLVER: single-precision complex Jacobi-method singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1611    cusolver_dn_cgesvdj as "cusolverDnCgesvdj": PFN_cusolverDnCgesvdj;
1612    /// cuSOLVER: double-precision complex Jacobi-method singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1613    cusolver_dn_zgesvdj as "cusolverDnZgesvdj": PFN_cusolverDnZgesvdj;
1614    // orgqr / ormqr (apply/generate Q from QR)
1615    /// cuSOLVER: single-precision workspace-size query for generate the explicit Q from a QR factorization. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1616    cusolver_dn_sorgqr_buffer_size as "cusolverDnSorgqr_bufferSize": PFN_cusolverDnSorgqr_bufferSize;
1617    /// cuSOLVER: double-precision workspace-size query for generate the explicit Q from a QR factorization. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1618    cusolver_dn_dorgqr_buffer_size as "cusolverDnDorgqr_bufferSize": PFN_cusolverDnDorgqr_bufferSize;
1619    /// cuSOLVER: single-precision complex workspace-size query for generate the explicit unitary Q from a QR factorization. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1620    cusolver_dn_cungqr_buffer_size as "cusolverDnCungqr_bufferSize": PFN_cusolverDnCungqr_bufferSize;
1621    /// cuSOLVER: double-precision complex workspace-size query for generate the explicit unitary Q from a QR factorization. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1622    cusolver_dn_zungqr_buffer_size as "cusolverDnZungqr_bufferSize": PFN_cusolverDnZungqr_bufferSize;
1623    /// cuSOLVER: single-precision generate the explicit Q from a QR factorization. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1624    cusolver_dn_sorgqr as "cusolverDnSorgqr": PFN_cusolverDnSorgqr;
1625    /// cuSOLVER: double-precision generate the explicit Q from a QR factorization. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1626    cusolver_dn_dorgqr as "cusolverDnDorgqr": PFN_cusolverDnDorgqr;
1627    /// cuSOLVER: single-precision complex generate the explicit unitary Q from a QR factorization. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1628    cusolver_dn_cungqr as "cusolverDnCungqr": PFN_cusolverDnCungqr;
1629    /// cuSOLVER: double-precision complex generate the explicit unitary Q from a QR factorization. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1630    cusolver_dn_zungqr as "cusolverDnZungqr": PFN_cusolverDnZungqr;
1631    /// cuSOLVER: single-precision workspace-size query for apply Q (or Q^T) from a QR factorization to a matrix. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1632    cusolver_dn_sormqr_buffer_size as "cusolverDnSormqr_bufferSize": PFN_cusolverDnSormqr_bufferSize;
1633    /// cuSOLVER: double-precision workspace-size query for apply Q (or Q^T) from a QR factorization to a matrix. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1634    cusolver_dn_dormqr_buffer_size as "cusolverDnDormqr_bufferSize": PFN_cusolverDnDormqr_bufferSize;
1635    /// cuSOLVER: single-precision complex workspace-size query for apply Q (or Q^H) from a QR factorization to a matrix. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1636    cusolver_dn_cunmqr_buffer_size as "cusolverDnCunmqr_bufferSize": PFN_cusolverDnCunmqr_bufferSize;
1637    /// cuSOLVER: double-precision complex workspace-size query for apply Q (or Q^H) from a QR factorization to a matrix. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1638    cusolver_dn_zunmqr_buffer_size as "cusolverDnZunmqr_bufferSize": PFN_cusolverDnZunmqr_bufferSize;
1639    /// cuSOLVER: single-precision apply Q (or Q^T) from a QR factorization to a matrix. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1640    cusolver_dn_sormqr as "cusolverDnSormqr": PFN_cusolverDnSormqr;
1641    /// cuSOLVER: double-precision apply Q (or Q^T) from a QR factorization to a matrix. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1642    cusolver_dn_dormqr as "cusolverDnDormqr": PFN_cusolverDnDormqr;
1643    /// cuSOLVER: single-precision complex apply Q (or Q^H) from a QR factorization to a matrix. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1644    cusolver_dn_cunmqr as "cusolverDnCunmqr": PFN_cusolverDnCunmqr;
1645    /// cuSOLVER: double-precision complex apply Q (or Q^H) from a QR factorization to a matrix. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1646    cusolver_dn_zunmqr as "cusolverDnZunmqr": PFN_cusolverDnZunmqr;
1647    // Sparse
1648    /// cuSOLVER: create a sparse cuSOLVER handle. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1649    cusolver_sp_create as "cusolverSpCreate": PFN_cusolverSpCreate;
1650    /// cuSOLVER: destroy a sparse cuSOLVER handle. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1651    cusolver_sp_destroy as "cusolverSpDestroy": PFN_cusolverSpDestroy;
1652    /// cuSOLVER: bind a CUDA stream to a sparse cuSOLVER handle. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1653    cusolver_sp_set_stream as "cusolverSpSetStream": PFN_cusolverSpSetStream;
1654    /// cuSOLVER: single-precision sparse linear solve via Cholesky on a CSR matrix. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1655    cusolver_sp_scsrlsvchol as "cusolverSpScsrlsvchol": PFN_cusolverSpScsrlsvchol;
1656    /// cuSOLVER: double-precision sparse linear solve via Cholesky on a CSR matrix. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1657    cusolver_sp_dcsrlsvchol as "cusolverSpDcsrlsvchol": PFN_cusolverSpDcsrlsvchol;
1658    /// cuSOLVER: single-precision sparse linear solve via QR on a CSR matrix. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1659    cusolver_sp_scsrlsvqr as "cusolverSpScsrlsvqr": PFN_cusolverSpScsrlsvqr;
1660    /// cuSOLVER: double-precision sparse linear solve via QR on a CSR matrix. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1661    cusolver_sp_dcsrlsvqr as "cusolverSpDcsrlsvqr": PFN_cusolverSpDcsrlsvqr;
1662    // Refactor
1663    /// cuSOLVER: create a sparse-refactor cuSOLVER handle. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1664    cusolver_rf_create as "cusolverRfCreate": PFN_cusolverRfCreate;
1665    /// cuSOLVER: destroy a sparse-refactor cuSOLVER handle. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1666    cusolver_rf_destroy as "cusolverRfDestroy": PFN_cusolverRfDestroy;
1667    /// cuSOLVER: supply sparse triangular factors and pivot vectors to the refactor handle. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1668    cusolver_rf_setup_device as "cusolverRfSetupDevice": PFN_cusolverRfSetupDevice;
1669    /// cuSOLVER: analyze the sparsity pattern of the refactor handle. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1670    cusolver_rf_analyze as "cusolverRfAnalyze": PFN_cusolverRfAnalyze;
1671    /// cuSOLVER: refactor with new numerical values reusing the analyzed pattern. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1672    cusolver_rf_refactor as "cusolverRfRefactor": PFN_cusolverRfRefactor;
1673    /// cuSOLVER: solve linear systems using the refactor handle. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1674    cusolver_rf_solve as "cusolverRfSolve": PFN_cusolverRfSolve;
1675    // Least squares (gels) S/D/C/Z
1676    /// cuSOLVER: single-precision workspace-size query for least-squares solver (A*X = B). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1677    cusolver_dn_ssgels_buffer_size as "cusolverDnSSgels_bufferSize": PFN_cusolverDnSSgels_bufferSize;
1678    /// cuSOLVER: double-precision workspace-size query for least-squares solver (A*X = B). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1679    cusolver_dn_ddgels_buffer_size as "cusolverDnDDgels_bufferSize": PFN_cusolverDnDDgels_bufferSize;
1680    /// cuSOLVER: single-precision complex workspace-size query for least-squares solver (A*X = B). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1681    cusolver_dn_ccgels_buffer_size as "cusolverDnCCgels_bufferSize": PFN_cusolverDnCCgels_bufferSize;
1682    /// cuSOLVER: double-precision complex workspace-size query for least-squares solver (A*X = B). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1683    cusolver_dn_zzgels_buffer_size as "cusolverDnZZgels_bufferSize": PFN_cusolverDnZZgels_bufferSize;
1684    /// cuSOLVER: single-precision least-squares solver (A*X = B). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1685    cusolver_dn_ssgels as "cusolverDnSSgels": PFN_cusolverDnSSgels;
1686    /// cuSOLVER: double-precision least-squares solver (A*X = B). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1687    cusolver_dn_ddgels as "cusolverDnDDgels": PFN_cusolverDnDDgels;
1688    /// cuSOLVER: single-precision complex least-squares solver (A*X = B). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1689    cusolver_dn_ccgels as "cusolverDnCCgels": PFN_cusolverDnCCgels;
1690    /// cuSOLVER: double-precision complex least-squares solver (A*X = B). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1691    cusolver_dn_zzgels as "cusolverDnZZgels": PFN_cusolverDnZZgels;
1692    // potri (inverse from Cholesky) S/D/C/Z
1693    /// cuSOLVER: single-precision workspace-size query for matrix inverse from Cholesky factors. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1694    cusolver_dn_spotri_buffer_size as "cusolverDnSpotri_bufferSize": PFN_cusolverDnSpotri_bufferSize;
1695    /// cuSOLVER: double-precision workspace-size query for matrix inverse from Cholesky factors. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1696    cusolver_dn_dpotri_buffer_size as "cusolverDnDpotri_bufferSize": PFN_cusolverDnDpotri_bufferSize;
1697    /// cuSOLVER: single-precision complex workspace-size query for matrix inverse from Cholesky factors. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1698    cusolver_dn_cpotri_buffer_size as "cusolverDnCpotri_bufferSize": PFN_cusolverDnCpotri_bufferSize;
1699    /// cuSOLVER: double-precision complex workspace-size query for matrix inverse from Cholesky factors. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1700    cusolver_dn_zpotri_buffer_size as "cusolverDnZpotri_bufferSize": PFN_cusolverDnZpotri_bufferSize;
1701    /// cuSOLVER: single-precision matrix inverse from Cholesky factors. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1702    cusolver_dn_spotri as "cusolverDnSpotri": PFN_cusolverDnSpotri;
1703    /// cuSOLVER: double-precision matrix inverse from Cholesky factors. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1704    cusolver_dn_dpotri as "cusolverDnDpotri": PFN_cusolverDnDpotri;
1705    /// cuSOLVER: single-precision complex matrix inverse from Cholesky factors. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1706    cusolver_dn_cpotri as "cusolverDnCpotri": PFN_cusolverDnCpotri;
1707    /// cuSOLVER: double-precision complex matrix inverse from Cholesky factors. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1708    cusolver_dn_zpotri as "cusolverDnZpotri": PFN_cusolverDnZpotri;
1709    // Batched Jacobi eigen
1710    /// cuSOLVER: single-precision workspace-size query for batched symmetric eigendecomposition (Jacobi). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1711    cusolver_dn_ssyevj_batched_buffer_size as "cusolverDnSsyevjBatched_bufferSize": PFN_cusolverDnSsyevjBatched_bufferSize;
1712    /// cuSOLVER: double-precision workspace-size query for batched symmetric eigendecomposition (Jacobi). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1713    cusolver_dn_dsyevj_batched_buffer_size as "cusolverDnDsyevjBatched_bufferSize": PFN_cusolverDnDsyevjBatched_bufferSize;
1714    /// cuSOLVER: single-precision complex workspace-size query for batched Hermitian eigendecomposition (Jacobi). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1715    cusolver_dn_cheevj_batched_buffer_size as "cusolverDnCheevjBatched_bufferSize": PFN_cusolverDnCheevjBatched_bufferSize;
1716    /// cuSOLVER: double-precision complex workspace-size query for batched Hermitian eigendecomposition (Jacobi). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1717    cusolver_dn_zheevj_batched_buffer_size as "cusolverDnZheevjBatched_bufferSize": PFN_cusolverDnZheevjBatched_bufferSize;
1718    /// cuSOLVER: single-precision batched symmetric eigendecomposition (Jacobi). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1719    cusolver_dn_ssyevj_batched as "cusolverDnSsyevjBatched": PFN_cusolverDnSsyevjBatched;
1720    /// cuSOLVER: double-precision batched symmetric eigendecomposition (Jacobi). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1721    cusolver_dn_dsyevj_batched as "cusolverDnDsyevjBatched": PFN_cusolverDnDsyevjBatched;
1722    /// cuSOLVER: single-precision complex batched Hermitian eigendecomposition (Jacobi). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1723    cusolver_dn_cheevj_batched as "cusolverDnCheevjBatched": PFN_cusolverDnCheevjBatched;
1724    /// cuSOLVER: double-precision complex batched Hermitian eigendecomposition (Jacobi). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1725    cusolver_dn_zheevj_batched as "cusolverDnZheevjBatched": PFN_cusolverDnZheevjBatched;
1726    // Batched Jacobi SVD
1727    /// cuSOLVER: single-precision workspace-size query for batched Jacobi-method singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1728    cusolver_dn_sgesvdj_batched_buffer_size as "cusolverDnSgesvdjBatched_bufferSize": PFN_cusolverDnSgesvdjBatched_bufferSize;
1729    /// cuSOLVER: double-precision workspace-size query for batched Jacobi-method singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1730    cusolver_dn_dgesvdj_batched_buffer_size as "cusolverDnDgesvdjBatched_bufferSize": PFN_cusolverDnDgesvdjBatched_bufferSize;
1731    /// cuSOLVER: single-precision complex workspace-size query for batched Jacobi-method singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1732    cusolver_dn_cgesvdj_batched_buffer_size as "cusolverDnCgesvdjBatched_bufferSize": PFN_cusolverDnCgesvdjBatched_bufferSize;
1733    /// cuSOLVER: double-precision complex workspace-size query for batched Jacobi-method singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1734    cusolver_dn_zgesvdj_batched_buffer_size as "cusolverDnZgesvdjBatched_bufferSize": PFN_cusolverDnZgesvdjBatched_bufferSize;
1735    /// cuSOLVER: single-precision batched Jacobi-method singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1736    cusolver_dn_sgesvdj_batched as "cusolverDnSgesvdjBatched": PFN_cusolverDnSgesvdjBatched;
1737    /// cuSOLVER: double-precision batched Jacobi-method singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1738    cusolver_dn_dgesvdj_batched as "cusolverDnDgesvdjBatched": PFN_cusolverDnDgesvdjBatched;
1739    /// cuSOLVER: single-precision complex batched Jacobi-method singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1740    cusolver_dn_cgesvdj_batched as "cusolverDnCgesvdjBatched": PFN_cusolverDnCgesvdjBatched;
1741    /// cuSOLVER: double-precision complex batched Jacobi-method singular value decomposition. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1742    cusolver_dn_zgesvdj_batched as "cusolverDnZgesvdjBatched": PFN_cusolverDnZgesvdjBatched;
1743}
1744
1745/// Lazy-load the cuSOLVER dense / sparse / refactor shared library and return its function-pointer table.
1746pub fn cusolver() -> Result<&'static Cusolver, LoaderError> {
1747    static CUSOLVER: OnceLock<Cusolver> = OnceLock::new();
1748    if let Some(c) = CUSOLVER.get() {
1749        return Ok(c);
1750    }
1751    let candidates: Vec<&'static str> = cusolver_candidates()
1752        .into_iter()
1753        .map(|s| Box::leak(s.into_boxed_str()) as &'static str)
1754        .collect();
1755    let candidates_leaked: &'static [&'static str] = Box::leak(candidates.into_boxed_slice());
1756    let lib = Library::open("cusolver", candidates_leaked)?;
1757    let c = Cusolver::empty(lib);
1758    let _ = CUSOLVER.set(c);
1759    Ok(CUSOLVER.get().expect("OnceLock set or lost race"))
1760}
1761
1762// ==========================================================================
1763// cuSOLVERMg — multi-GPU solver, ships in libcusolverMg (separate library)
1764// ==========================================================================
1765
1766fn cusolver_mg_candidates() -> Vec<String> {
1767    platform::versioned_library_candidates("cusolverMg", &["13", "12", "11"])
1768}
1769
1770macro_rules! cusolver_mg_fns {
1771    ($($(#[$m:meta])* $name:ident as $sym:literal : $pfn:ty);* $(;)?) => {
1772        /// Loaded cuSOLVERMg shared library plus a per-symbol `OnceLock` of function pointers.
1773        pub struct CusolverMg {
1774            lib: Library,
1775            $($name: OnceLock<$pfn>,)*
1776        }
1777        impl core::fmt::Debug for CusolverMg {
1778            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1779                f.debug_struct("CusolverMg").field("lib", &self.lib).finish_non_exhaustive()
1780            }
1781        }
1782        impl CusolverMg {
1783            $(
1784                $(#[$m])*
1785                pub fn $name(&self) -> Result<$pfn, LoaderError> {
1786                    if let Some(&p) = self.$name.get() { return Ok(p); }
1787                    let raw: *mut () = unsafe { self.lib.raw_symbol($sym)? };
1788                    let p: $pfn = unsafe { core::mem::transmute_copy::<*mut (), $pfn>(&raw) };
1789                    let _ = self.$name.set(p);
1790                    Ok(p)
1791                }
1792            )*
1793            fn empty(lib: Library) -> Self {
1794                Self { lib, $($name: OnceLock::new(),)* }
1795            }
1796        }
1797    };
1798}
1799
1800cusolver_mg_fns! {
1801    /// cuSOLVER: create a multi-GPU dense cuSOLVERMg handle. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1802    cusolver_mg_create as "cusolverMgCreate": PFN_cusolverMgCreate;
1803    /// cuSOLVER: destroy a multi-GPU dense cuSOLVERMg handle. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1804    cusolver_mg_destroy as "cusolverMgDestroy": PFN_cusolverMgDestroy;
1805    /// cuSOLVER: select GPU devices for a cuSOLVERMg handle. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1806    cusolver_mg_device_select as "cusolverMgDeviceSelect": PFN_cusolverMgDeviceSelect;
1807    /// cuSOLVER: create a multi-GPU device grid. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1808    cusolver_mg_create_device_grid as "cusolverMgCreateDeviceGrid": PFN_cusolverMgCreateDeviceGrid;
1809    /// cuSOLVER: destroy a multi-GPU device grid. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1810    cusolver_mg_destroy_grid as "cusolverMgDestroyGrid": PFN_cusolverMgDestroyGrid;
1811    /// cuSOLVER: create a multi-GPU matrix descriptor. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1812    cusolver_mg_create_matrix_desc as "cusolverMgCreateMatrixDesc": PFN_cusolverMgCreateMatrixDesc;
1813    /// cuSOLVER: destroy a multi-GPU matrix descriptor. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1814    cusolver_mg_destroy_matrix_desc as "cusolverMgDestroyMatrixDesc": PFN_cusolverMgDestroyMatrixDesc;
1815    /// cuSOLVER: multi-GPU workspace-size query for LU factorization with partial pivoting. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1816    cusolver_mg_getrf_buffer_size as "cusolverMgGetrf_bufferSize": PFN_cusolverMgGetrf_bufferSize;
1817    /// cuSOLVER: multi-GPU LU factorization with partial pivoting. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1818    cusolver_mg_getrf as "cusolverMgGetrf": PFN_cusolverMgGetrf;
1819    /// cuSOLVER: multi-GPU workspace-size query for Cholesky factorization. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1820    cusolver_mg_potrf_buffer_size as "cusolverMgPotrf_bufferSize": PFN_cusolverMgPotrf_bufferSize;
1821    /// cuSOLVER: multi-GPU Cholesky factorization. See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1822    cusolver_mg_potrf as "cusolverMgPotrf": PFN_cusolverMgPotrf;
1823    /// cuSOLVER: multi-GPU workspace-size query for symmetric eigendecomposition (divide-and-conquer). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1824    cusolver_mg_syevd_buffer_size as "cusolverMgSyevd_bufferSize": PFN_cusolverMgSyevd_bufferSize;
1825    /// cuSOLVER: multi-GPU symmetric eigendecomposition (divide-and-conquer). See <https://docs.nvidia.com/cuda/cusolver/index.html>.
1826    cusolver_mg_syevd as "cusolverMgSyevd": PFN_cusolverMgSyevd;
1827}
1828
1829/// Lazy-load the cuSOLVERMg multi-GPU shared library and return its function-pointer table.
1830pub fn cusolver_mg() -> Result<&'static CusolverMg, LoaderError> {
1831    static MG: OnceLock<CusolverMg> = OnceLock::new();
1832    if let Some(c) = MG.get() {
1833        return Ok(c);
1834    }
1835    let candidates: Vec<&'static str> = cusolver_mg_candidates()
1836        .into_iter()
1837        .map(|s| Box::leak(s.into_boxed_str()) as &'static str)
1838        .collect();
1839    let leaked: &'static [&'static str] = Box::leak(candidates.into_boxed_slice());
1840    let lib = Library::open("cusolverMg", leaked)?;
1841    let _ = MG.set(CusolverMg::empty(lib));
1842    Ok(MG.get().expect("OnceLock set or lost race"))
1843}