ruvector_math/
error.rs

1//! Error types for ruvector-math
2
3use thiserror::Error;
4
5/// Result type alias for ruvector-math operations
6pub type Result<T> = std::result::Result<T, MathError>;
7
8/// Errors that can occur in mathematical operations
9#[derive(Error, Debug, Clone, PartialEq)]
10pub enum MathError {
11    /// Dimension mismatch between inputs
12    #[error("Dimension mismatch: expected {expected}, got {got}")]
13    DimensionMismatch {
14        /// Expected dimension
15        expected: usize,
16        /// Actual dimension received
17        got: usize,
18    },
19
20    /// Empty input where non-empty was required
21    #[error("Empty input: {context}")]
22    EmptyInput {
23        /// Context describing what was empty
24        context: String,
25    },
26
27    /// Numerical instability detected
28    #[error("Numerical instability: {message}")]
29    NumericalInstability {
30        /// Description of the instability
31        message: String,
32    },
33
34    /// Convergence failure in iterative algorithm
35    #[error("Convergence failed after {iterations} iterations (residual: {residual:.2e})")]
36    ConvergenceFailure {
37        /// Number of iterations attempted
38        iterations: usize,
39        /// Final residual/error value
40        residual: f64,
41    },
42
43    /// Invalid parameter value
44    #[error("Invalid parameter '{name}': {reason}")]
45    InvalidParameter {
46        /// Parameter name
47        name: String,
48        /// Reason why it's invalid
49        reason: String,
50    },
51
52    /// Point not on manifold
53    #[error("Point not on manifold: {message}")]
54    NotOnManifold {
55        /// Description of the constraint violation
56        message: String,
57    },
58
59    /// Singular matrix encountered
60    #[error("Singular matrix encountered: {context}")]
61    SingularMatrix {
62        /// Context where singularity occurred
63        context: String,
64    },
65
66    /// Curvature constraint violated
67    #[error("Curvature constraint violated: {message}")]
68    CurvatureViolation {
69        /// Description of the violation
70        message: String,
71    },
72}
73
74impl MathError {
75    /// Create a dimension mismatch error
76    pub fn dimension_mismatch(expected: usize, got: usize) -> Self {
77        Self::DimensionMismatch { expected, got }
78    }
79
80    /// Create an empty input error
81    pub fn empty_input(context: impl Into<String>) -> Self {
82        Self::EmptyInput {
83            context: context.into(),
84        }
85    }
86
87    /// Create a numerical instability error
88    pub fn numerical_instability(message: impl Into<String>) -> Self {
89        Self::NumericalInstability {
90            message: message.into(),
91        }
92    }
93
94    /// Create a convergence failure error
95    pub fn convergence_failure(iterations: usize, residual: f64) -> Self {
96        Self::ConvergenceFailure {
97            iterations,
98            residual,
99        }
100    }
101
102    /// Create an invalid parameter error
103    pub fn invalid_parameter(name: impl Into<String>, reason: impl Into<String>) -> Self {
104        Self::InvalidParameter {
105            name: name.into(),
106            reason: reason.into(),
107        }
108    }
109
110    /// Create a not on manifold error
111    pub fn not_on_manifold(message: impl Into<String>) -> Self {
112        Self::NotOnManifold {
113            message: message.into(),
114        }
115    }
116
117    /// Create a singular matrix error
118    pub fn singular_matrix(context: impl Into<String>) -> Self {
119        Self::SingularMatrix {
120            context: context.into(),
121        }
122    }
123
124    /// Create a curvature violation error
125    pub fn curvature_violation(message: impl Into<String>) -> Self {
126        Self::CurvatureViolation {
127            message: message.into(),
128        }
129    }
130}
131
132#[cfg(test)]
133mod tests {
134    use super::*;
135
136    #[test]
137    fn test_error_display() {
138        let err = MathError::dimension_mismatch(128, 64);
139        assert!(err.to_string().contains("128"));
140        assert!(err.to_string().contains("64"));
141    }
142
143    #[test]
144    fn test_convergence_error() {
145        let err = MathError::convergence_failure(100, 1e-3);
146        assert!(err.to_string().contains("100"));
147    }
148}