Skip to main content

singe_cusolver/
error.rs

1use std::{
2    ffi::NulError,
3    fmt::{self, Display, Formatter},
4};
5
6use num_enum::{IntoPrimitive, TryFromPrimitive};
7use singe_core::impl_enum_conversion;
8use singe_cuda::error::Error as CudaError;
9use singe_cusolver_sys as sys;
10use thiserror::Error;
11
12#[derive(Error, Debug)]
13pub enum Error {
14    #[error("cuda error: {0}")]
15    Cuda(#[from] CudaError),
16
17    #[error("cusolver error ({code}): {message}")]
18    Cusolver { code: Status, message: String },
19
20    #[error("string contains interior nul byte")]
21    InteriorNul,
22
23    #[error("unexpected null handle")]
24    NullHandle,
25
26    #[error("{name} is out of range")]
27    OutOfRange { name: String },
28
29    #[error("invalid matrix leading dimension")]
30    InvalidLeadingDimension,
31
32    #[error("invalid matrix shape")]
33    InvalidMatrixShape,
34
35    #[error("invalid vector shape")]
36    InvalidVectorShape,
37
38    #[error("invalid eigensolver range")]
39    InvalidEigRange,
40
41    #[error("invalid svd mode")]
42    InvalidSvdMode,
43
44    #[error("invalid precision configuration")]
45    InvalidPrecisionConfiguration,
46
47    #[error("insufficient workspace size: {actual} provided (required {required})")]
48    InsufficientWorkspaceSize { required: usize, actual: usize },
49
50    #[error("invalid residual history")]
51    InvalidResidualHistory,
52
53    #[error("stream belongs to a different cuda context")]
54    StreamContextMismatch,
55}
56
57pub type Result<T> = std::result::Result<T, Error>;
58
59impl From<sys::cusolverStatus_t> for Error {
60    fn from(status: sys::cusolverStatus_t) -> Self {
61        debug_assert_ne!(status, sys::cusolverStatus_t::CUSOLVER_STATUS_SUCCESS);
62
63        let message = match status {
64            sys::cusolverStatus_t::CUSOLVER_STATUS_NOT_INITIALIZED => "library not initialized",
65            sys::cusolverStatus_t::CUSOLVER_STATUS_ALLOC_FAILED => "allocation failed",
66            sys::cusolverStatus_t::CUSOLVER_STATUS_INVALID_VALUE => "invalid value",
67            sys::cusolverStatus_t::CUSOLVER_STATUS_ARCH_MISMATCH => "architecture mismatch",
68            sys::cusolverStatus_t::CUSOLVER_STATUS_MAPPING_ERROR => "mapping error",
69            sys::cusolverStatus_t::CUSOLVER_STATUS_EXECUTION_FAILED => "execution failed",
70            sys::cusolverStatus_t::CUSOLVER_STATUS_INTERNAL_ERROR => "internal error",
71            sys::cusolverStatus_t::CUSOLVER_STATUS_MATRIX_TYPE_NOT_SUPPORTED => {
72                "matrix type not supported"
73            }
74            sys::cusolverStatus_t::CUSOLVER_STATUS_NOT_SUPPORTED => "not supported",
75            sys::cusolverStatus_t::CUSOLVER_STATUS_ZERO_PIVOT => "zero pivot",
76            sys::cusolverStatus_t::CUSOLVER_STATUS_INVALID_LICENSE => "invalid license",
77            sys::cusolverStatus_t::CUSOLVER_STATUS_IRS_PARAMS_NOT_INITIALIZED => {
78                "irs params not initialized"
79            }
80            sys::cusolverStatus_t::CUSOLVER_STATUS_IRS_PARAMS_INVALID => "irs params invalid",
81            sys::cusolverStatus_t::CUSOLVER_STATUS_IRS_PARAMS_INVALID_PREC => {
82                "irs params invalid precision"
83            }
84            sys::cusolverStatus_t::CUSOLVER_STATUS_IRS_PARAMS_INVALID_REFINE => {
85                "irs params invalid refinement"
86            }
87            sys::cusolverStatus_t::CUSOLVER_STATUS_IRS_PARAMS_INVALID_MAXITER => {
88                "irs params invalid maxiter"
89            }
90            sys::cusolverStatus_t::CUSOLVER_STATUS_IRS_INTERNAL_ERROR => "irs internal error",
91            sys::cusolverStatus_t::CUSOLVER_STATUS_IRS_NOT_SUPPORTED => "irs not supported",
92            sys::cusolverStatus_t::CUSOLVER_STATUS_IRS_OUT_OF_RANGE => "irs out of range",
93            sys::cusolverStatus_t::CUSOLVER_STATUS_IRS_NRHS_NOT_SUPPORTED_FOR_REFINE_GMRES => {
94                "irs nrhs not supported for refine gmres"
95            }
96            sys::cusolverStatus_t::CUSOLVER_STATUS_IRS_INFOS_NOT_INITIALIZED => {
97                "irs infos not initialized"
98            }
99            sys::cusolverStatus_t::CUSOLVER_STATUS_IRS_INFOS_NOT_DESTROYED => {
100                "irs infos not destroyed"
101            }
102            sys::cusolverStatus_t::CUSOLVER_STATUS_IRS_MATRIX_SINGULAR => "irs matrix singular",
103            sys::cusolverStatus_t::CUSOLVER_STATUS_INVALID_WORKSPACE => "invalid workspace",
104            _ => "unknown cusolver error",
105        };
106
107        Self::Cusolver {
108            code: status.into(),
109            message: message.to_string(),
110        }
111    }
112}
113
114impl From<NulError> for Error {
115    fn from(_: NulError) -> Self {
116        Self::InteriorNul
117    }
118}
119
120#[macro_export]
121macro_rules! try_ffi {
122    ($expr:expr) => {{
123        let status = { $expr };
124        if status != singe_cusolver_sys::cusolverStatus_t::CUSOLVER_STATUS_SUCCESS {
125            Err($crate::error::Error::from(status))
126        } else {
127            Ok(())
128        }
129    }};
130}
131
132/// cuSOLVER status code returned by wrapper operations.
133/// All cuSOLVER operations report one of these values.
134#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive, IntoPrimitive)]
135#[repr(u32)]
136pub enum Status {
137    /// The operation completed successfully.
138    Success = sys::cusolverStatus_t::CUSOLVER_STATUS_SUCCESS as _,
139    /// The cuSOLVER library was not initialized.
140    NotInitialized = sys::cusolverStatus_t::CUSOLVER_STATUS_NOT_INITIALIZED as _,
141    /// Resource allocation failed.
142    AllocFailed = sys::cusolverStatus_t::CUSOLVER_STATUS_ALLOC_FAILED as _,
143    /// An invalid value was provided.
144    InvalidValue = sys::cusolverStatus_t::CUSOLVER_STATUS_INVALID_VALUE as _,
145    /// The current device architecture is not supported.
146    ArchMismatch = sys::cusolverStatus_t::CUSOLVER_STATUS_ARCH_MISMATCH as _,
147    /// Memory or resource mapping failed.
148    MappingError = sys::cusolverStatus_t::CUSOLVER_STATUS_MAPPING_ERROR as _,
149    /// Kernel execution failed.
150    ExecutionFailed = sys::cusolverStatus_t::CUSOLVER_STATUS_EXECUTION_FAILED as _,
151    /// An internal cuSOLVER error occurred.
152    InternalError = sys::cusolverStatus_t::CUSOLVER_STATUS_INTERNAL_ERROR as _,
153    /// The matrix type is not supported by the operation.
154    MatrixTypeNotSupported = sys::cusolverStatus_t::CUSOLVER_STATUS_MATRIX_TYPE_NOT_SUPPORTED as _,
155    /// The requested operation is not supported.
156    NotSupported = sys::cusolverStatus_t::CUSOLVER_STATUS_NOT_SUPPORTED as _,
157    /// A zero pivot was encountered.
158    ZeroPivot = sys::cusolverStatus_t::CUSOLVER_STATUS_ZERO_PIVOT as _,
159    /// The cuSOLVER license is invalid.
160    InvalidLicense = sys::cusolverStatus_t::CUSOLVER_STATUS_INVALID_LICENSE as _,
161    /// IRS parameters were not initialized.
162    IrsParamsNotInitialized =
163        sys::cusolverStatus_t::CUSOLVER_STATUS_IRS_PARAMS_NOT_INITIALIZED as _,
164    /// IRS parameters are invalid.
165    IrsParamsInvalid = sys::cusolverStatus_t::CUSOLVER_STATUS_IRS_PARAMS_INVALID as _,
166    /// IRS precision parameters are invalid.
167    IrsParamsInvalidPrec = sys::cusolverStatus_t::CUSOLVER_STATUS_IRS_PARAMS_INVALID_PREC as _,
168    /// IRS refinement parameters are invalid.
169    IrsParamsInvalidRefine = sys::cusolverStatus_t::CUSOLVER_STATUS_IRS_PARAMS_INVALID_REFINE as _,
170    /// IRS max-iteration parameters are invalid.
171    IrsParamsInvalidMaxIter =
172        sys::cusolverStatus_t::CUSOLVER_STATUS_IRS_PARAMS_INVALID_MAXITER as _,
173    /// An internal IRS error occurred.
174    IrsInternalError = sys::cusolverStatus_t::CUSOLVER_STATUS_IRS_INTERNAL_ERROR as _,
175    /// The requested IRS configuration is not supported.
176    IrsNotSupported = sys::cusolverStatus_t::CUSOLVER_STATUS_IRS_NOT_SUPPORTED as _,
177    /// IRS configuration values are out of range.
178    IrsOutOfRange = sys::cusolverStatus_t::CUSOLVER_STATUS_IRS_OUT_OF_RANGE as _,
179    /// GMRES refinement does not support the requested number of right-hand sides.
180    IrsNrhsNotSupportedForRefineGmres =
181        sys::cusolverStatus_t::CUSOLVER_STATUS_IRS_NRHS_NOT_SUPPORTED_FOR_REFINE_GMRES as _,
182    /// IRS info structures were not initialized.
183    IrsInfosNotInitialized = sys::cusolverStatus_t::CUSOLVER_STATUS_IRS_INFOS_NOT_INITIALIZED as _,
184    /// IRS info structures were not destroyed before reuse.
185    IrsInfosNotDestroyed = sys::cusolverStatus_t::CUSOLVER_STATUS_IRS_INFOS_NOT_DESTROYED as _,
186    /// The IRS system matrix is singular.
187    IrsMatrixSingular = sys::cusolverStatus_t::CUSOLVER_STATUS_IRS_MATRIX_SINGULAR as _,
188    /// The provided workspace is invalid.
189    InvalidWorkspace = sys::cusolverStatus_t::CUSOLVER_STATUS_INVALID_WORKSPACE as _,
190}
191
192impl_enum_conversion!(sys::cusolverStatus_t, Status);
193
194impl Status {
195    pub const fn description(self) -> &'static str {
196        match self {
197            Self::Success => "success",
198            Self::NotInitialized => "library not initialized",
199            Self::AllocFailed => "allocation failed",
200            Self::InvalidValue => "invalid value",
201            Self::ArchMismatch => "architecture mismatch",
202            Self::MappingError => "mapping error",
203            Self::ExecutionFailed => "execution failed",
204            Self::InternalError => "internal error",
205            Self::MatrixTypeNotSupported => "matrix type not supported",
206            Self::NotSupported => "not supported",
207            Self::ZeroPivot => "zero pivot",
208            Self::InvalidLicense => "invalid license",
209            Self::IrsParamsNotInitialized => "irs params not initialized",
210            Self::IrsParamsInvalid => "irs params invalid",
211            Self::IrsParamsInvalidPrec => "irs params invalid precision",
212            Self::IrsParamsInvalidRefine => "irs params invalid refinement",
213            Self::IrsParamsInvalidMaxIter => "irs params invalid maxiter",
214            Self::IrsInternalError => "irs internal error",
215            Self::IrsNotSupported => "irs not supported",
216            Self::IrsOutOfRange => "irs out of range",
217            Self::IrsNrhsNotSupportedForRefineGmres => "irs nrhs not supported for refine gmres",
218            Self::IrsInfosNotInitialized => "irs infos not initialized",
219            Self::IrsInfosNotDestroyed => "irs infos not destroyed",
220            Self::IrsMatrixSingular => "irs matrix singular",
221            Self::InvalidWorkspace => "invalid workspace",
222        }
223    }
224}
225
226impl Display for Status {
227    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
228        match self {
229            Self::Success => write!(f, "CUSOLVER_STATUS_SUCCESS"),
230            Self::NotInitialized => write!(f, "CUSOLVER_STATUS_NOT_INITIALIZED"),
231            Self::AllocFailed => write!(f, "CUSOLVER_STATUS_ALLOC_FAILED"),
232            Self::InvalidValue => write!(f, "CUSOLVER_STATUS_INVALID_VALUE"),
233            Self::ArchMismatch => write!(f, "CUSOLVER_STATUS_ARCH_MISMATCH"),
234            Self::MappingError => write!(f, "CUSOLVER_STATUS_MAPPING_ERROR"),
235            Self::ExecutionFailed => write!(f, "CUSOLVER_STATUS_EXECUTION_FAILED"),
236            Self::InternalError => write!(f, "CUSOLVER_STATUS_INTERNAL_ERROR"),
237            Self::MatrixTypeNotSupported => {
238                write!(f, "CUSOLVER_STATUS_MATRIX_TYPE_NOT_SUPPORTED")
239            }
240            Self::NotSupported => write!(f, "CUSOLVER_STATUS_NOT_SUPPORTED"),
241            Self::ZeroPivot => write!(f, "CUSOLVER_STATUS_ZERO_PIVOT"),
242            Self::InvalidLicense => write!(f, "CUSOLVER_STATUS_INVALID_LICENSE"),
243            Self::IrsParamsNotInitialized => {
244                write!(f, "CUSOLVER_STATUS_IRS_PARAMS_NOT_INITIALIZED")
245            }
246            Self::IrsParamsInvalid => write!(f, "CUSOLVER_STATUS_IRS_PARAMS_INVALID"),
247            Self::IrsParamsInvalidPrec => write!(f, "CUSOLVER_STATUS_IRS_PARAMS_INVALID_PREC"),
248            Self::IrsParamsInvalidRefine => {
249                write!(f, "CUSOLVER_STATUS_IRS_PARAMS_INVALID_REFINE")
250            }
251            Self::IrsParamsInvalidMaxIter => {
252                write!(f, "CUSOLVER_STATUS_IRS_PARAMS_INVALID_MAXITER")
253            }
254            Self::IrsInternalError => write!(f, "CUSOLVER_STATUS_IRS_INTERNAL_ERROR"),
255            Self::IrsNotSupported => write!(f, "CUSOLVER_STATUS_IRS_NOT_SUPPORTED"),
256            Self::IrsOutOfRange => write!(f, "CUSOLVER_STATUS_IRS_OUT_OF_RANGE"),
257            Self::IrsNrhsNotSupportedForRefineGmres => {
258                write!(f, "CUSOLVER_STATUS_IRS_NRHS_NOT_SUPPORTED_FOR_REFINE_GMRES")
259            }
260            Self::IrsInfosNotInitialized => {
261                write!(f, "CUSOLVER_STATUS_IRS_INFOS_NOT_INITIALIZED")
262            }
263            Self::IrsInfosNotDestroyed => write!(f, "CUSOLVER_STATUS_IRS_INFOS_NOT_DESTROYED"),
264            Self::IrsMatrixSingular => write!(f, "CUSOLVER_STATUS_IRS_MATRIX_SINGULAR"),
265            Self::InvalidWorkspace => write!(f, "CUSOLVER_STATUS_INVALID_WORKSPACE"),
266        }
267    }
268}