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