Skip to main content

scivex_core/
error.rs

1use core::fmt;
2
3/// All errors returned by `scivex-core`.
4///
5/// # Examples
6///
7/// ```
8/// use scivex_core::error::CoreError;
9/// let e = CoreError::SingularMatrix;
10/// assert_eq!(format!("{e}"), "singular matrix");
11/// ```
12#[cfg_attr(
13    feature = "serde-support",
14    derive(serde::Serialize, serde::Deserialize)
15)]
16#[derive(Debug, Clone, PartialEq, Eq)]
17#[non_exhaustive]
18pub enum CoreError {
19    /// Operand shapes do not match the required layout.
20    DimensionMismatch {
21        expected: Vec<usize>,
22        got: Vec<usize>,
23    },
24
25    /// A shape or stride specification is invalid.
26    InvalidShape {
27        shape: Vec<usize>,
28        reason: &'static str,
29    },
30
31    /// An axis index is out of bounds for the tensor's rank.
32    AxisOutOfBounds { axis: usize, ndim: usize },
33
34    /// A flat or multi-dimensional index is out of bounds.
35    IndexOutOfBounds {
36        index: Vec<usize>,
37        shape: Vec<usize>,
38    },
39
40    /// Matrix is singular and cannot be inverted / decomposed.
41    SingularMatrix,
42
43    /// The operation is not supported for the given input.
44    InvalidArgument { reason: &'static str },
45
46    /// Shapes cannot be broadcast together.
47    BroadcastError {
48        shape_a: Vec<usize>,
49        shape_b: Vec<usize>,
50    },
51}
52
53impl fmt::Display for CoreError {
54    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55        match self {
56            Self::DimensionMismatch { expected, got } => {
57                write!(f, "dimension mismatch: expected {expected:?}, got {got:?}")
58            }
59            Self::InvalidShape { shape, reason } => {
60                write!(f, "invalid shape {shape:?}: {reason}")
61            }
62            Self::AxisOutOfBounds { axis, ndim } => {
63                write!(
64                    f,
65                    "axis {axis} out of bounds for tensor with {ndim} dimensions"
66                )
67            }
68            Self::IndexOutOfBounds { index, shape } => {
69                write!(f, "index {index:?} out of bounds for shape {shape:?}")
70            }
71            Self::SingularMatrix => write!(f, "singular matrix"),
72            Self::InvalidArgument { reason } => write!(f, "invalid argument: {reason}"),
73            Self::BroadcastError { shape_a, shape_b } => {
74                write!(f, "cannot broadcast shapes {shape_a:?} and {shape_b:?}")
75            }
76        }
77    }
78}
79
80impl std::error::Error for CoreError {}
81
82/// Convenience alias used throughout `scivex-core`.
83///
84/// # Examples
85///
86/// ```
87/// use scivex_core::error::{CoreError, Result};
88/// fn check(ok: bool) -> Result<i32> {
89///     if ok { Ok(42) } else { Err(CoreError::SingularMatrix) }
90/// }
91/// assert_eq!(check(true).unwrap(), 42);
92/// assert!(check(false).is_err());
93/// ```
94pub type Result<T> = std::result::Result<T, CoreError>;