1use thiserror::Error;
4
5pub type Result<T> = std::result::Result<T, MathError>;
7
8#[derive(Error, Debug, Clone, PartialEq)]
10pub enum MathError {
11 #[error("Dimension mismatch: expected {expected}, got {got}")]
13 DimensionMismatch {
14 expected: usize,
16 got: usize,
18 },
19
20 #[error("Empty input: {context}")]
22 EmptyInput {
23 context: String,
25 },
26
27 #[error("Numerical instability: {message}")]
29 NumericalInstability {
30 message: String,
32 },
33
34 #[error("Convergence failed after {iterations} iterations (residual: {residual:.2e})")]
36 ConvergenceFailure {
37 iterations: usize,
39 residual: f64,
41 },
42
43 #[error("Invalid parameter '{name}': {reason}")]
45 InvalidParameter {
46 name: String,
48 reason: String,
50 },
51
52 #[error("Point not on manifold: {message}")]
54 NotOnManifold {
55 message: String,
57 },
58
59 #[error("Singular matrix encountered: {context}")]
61 SingularMatrix {
62 context: String,
64 },
65
66 #[error("Curvature constraint violated: {message}")]
68 CurvatureViolation {
69 message: String,
71 },
72}
73
74impl MathError {
75 pub fn dimension_mismatch(expected: usize, got: usize) -> Self {
77 Self::DimensionMismatch { expected, got }
78 }
79
80 pub fn empty_input(context: impl Into<String>) -> Self {
82 Self::EmptyInput {
83 context: context.into(),
84 }
85 }
86
87 pub fn numerical_instability(message: impl Into<String>) -> Self {
89 Self::NumericalInstability {
90 message: message.into(),
91 }
92 }
93
94 pub fn convergence_failure(iterations: usize, residual: f64) -> Self {
96 Self::ConvergenceFailure {
97 iterations,
98 residual,
99 }
100 }
101
102 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 pub fn not_on_manifold(message: impl Into<String>) -> Self {
112 Self::NotOnManifold {
113 message: message.into(),
114 }
115 }
116
117 pub fn singular_matrix(context: impl Into<String>) -> Self {
119 Self::SingularMatrix {
120 context: context.into(),
121 }
122 }
123
124 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}