Skip to main content

oxicuda_sparse/
error.rs

1//! Error types for OxiCUDA Sparse operations.
2//!
3//! Provides [`SparseError`] covering all failure modes for GPU-accelerated
4//! sparse matrix routines -- format validation, dimension mismatches, PTX
5//! generation, and underlying CUDA / BLAS errors.
6
7use oxicuda_blas::BlasError;
8use oxicuda_driver::CudaError;
9use oxicuda_ptx::PtxGenError;
10use thiserror::Error;
11
12/// Sparse-specific error type.
13///
14/// Every fallible sparse operation returns [`SparseResult<T>`] which uses this
15/// enum as its error variant.
16#[derive(Debug, Error)]
17pub enum SparseError {
18    /// A CUDA driver call failed.
19    #[error("CUDA driver error: {0}")]
20    Cuda(#[from] CudaError),
21
22    /// A BLAS operation failed.
23    #[error("BLAS error: {0}")]
24    Blas(#[from] BlasError),
25
26    /// PTX kernel generation failed.
27    #[error("PTX generation error: {0}")]
28    PtxGeneration(String),
29
30    /// The sparse matrix format is invalid (e.g. mismatched array lengths).
31    #[error("invalid sparse format: {0}")]
32    InvalidFormat(String),
33
34    /// Matrix dimensions are incompatible for the requested operation.
35    #[error("dimension mismatch: {0}")]
36    DimensionMismatch(String),
37
38    /// The number of non-zeros is zero, which is invalid for this operation.
39    #[error("matrix has zero non-zeros")]
40    ZeroNnz,
41
42    /// The matrix is singular and cannot be factored or solved.
43    #[error("singular matrix detected")]
44    SingularMatrix,
45
46    /// An iterative algorithm failed to converge within the iteration limit.
47    #[error("convergence failure: {0}")]
48    ConvergenceFailure(String),
49
50    /// An internal logic error (should not happen in correct code).
51    #[error("internal error: {0}")]
52    InternalError(String),
53
54    /// A function argument is invalid.
55    #[error("invalid argument: {0}")]
56    InvalidArgument(String),
57
58    /// An I/O operation failed (e.g. PTX cache).
59    #[error("I/O error: {0}")]
60    Io(#[from] std::io::Error),
61}
62
63impl From<PtxGenError> for SparseError {
64    fn from(err: PtxGenError) -> Self {
65        Self::PtxGeneration(err.to_string())
66    }
67}
68
69/// Convenience alias used throughout the sparse crate.
70pub type SparseResult<T> = Result<T, SparseError>;
71
72#[cfg(test)]
73mod tests {
74    use super::*;
75
76    #[test]
77    fn display_zero_nnz() {
78        let err = SparseError::ZeroNnz;
79        assert!(err.to_string().contains("zero non-zeros"));
80    }
81
82    #[test]
83    fn display_dimension_mismatch() {
84        let err = SparseError::DimensionMismatch("A.cols != B.rows".to_string());
85        assert!(err.to_string().contains("A.cols != B.rows"));
86    }
87
88    #[test]
89    fn from_cuda_error() {
90        let cuda_err = CudaError::NotInitialized;
91        let sparse_err: SparseError = cuda_err.into();
92        assert!(matches!(sparse_err, SparseError::Cuda(_)));
93    }
94}