1pub mod corrector;
11pub mod loss_functions;
12pub mod noise;
13pub mod problem;
14pub mod residual_block;
15pub mod variable;
16
17use slotmap::new_key_type;
18use thiserror::Error;
19
20new_key_type! {
21 pub struct VarKey;
23 pub struct FactorKey;
25}
26
27#[derive(Debug, Clone, Error)]
29pub enum CoreError {
30 #[error("Residual block error: {0}")]
32 ResidualBlock(String),
33
34 #[error("Variable error: {0}")]
36 Variable(String),
37
38 #[error("Factor linearization failed: {0}")]
40 FactorLinearization(String),
41
42 #[error("Symbolic structure error: {0}")]
44 SymbolicStructure(String),
45
46 #[error("Parallel computation error: {0}")]
48 ParallelComputation(String),
49
50 #[error("Dimension mismatch: {0}")]
52 DimensionMismatch(String),
53
54 #[error("Invalid constraint: {0}")]
56 InvalidConstraint(String),
57
58 #[error("Loss function error: {0}")]
60 LossFunction(String),
61
62 #[error("Invalid input: {0}")]
64 InvalidInput(String),
65}
66
67pub type CoreResult<T> = Result<T, CoreError>;
69
70impl From<crate::linearizer::LinearizerError> for CoreError {
71 fn from(err: crate::linearizer::LinearizerError) -> Self {
72 match err {
73 crate::linearizer::LinearizerError::SymbolicStructure(msg) => {
74 CoreError::SymbolicStructure(msg)
75 }
76 crate::linearizer::LinearizerError::ParallelComputation(msg) => {
77 CoreError::ParallelComputation(msg)
78 }
79 crate::linearizer::LinearizerError::Variable(msg) => CoreError::Variable(msg),
80 crate::linearizer::LinearizerError::FactorLinearization(msg) => {
81 CoreError::FactorLinearization(msg)
82 }
83 crate::linearizer::LinearizerError::InvalidInput(msg) => CoreError::InvalidInput(msg),
84 }
85 }
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91 use crate::error::ErrorLogging;
92
93 #[test]
98 fn test_core_error_residual_block_display() {
99 let e = CoreError::ResidualBlock("bad block".into());
100 assert!(e.to_string().contains("bad block"));
101 }
102
103 #[test]
104 fn test_core_error_variable_display() {
105 let e = CoreError::Variable("bad var".into());
106 assert!(e.to_string().contains("bad var"));
107 }
108
109 #[test]
110 fn test_core_error_factor_linearization_display() {
111 let e = CoreError::FactorLinearization("jacobian fail".into());
112 assert!(e.to_string().contains("jacobian fail"));
113 }
114
115 #[test]
116 fn test_core_error_symbolic_structure_display() {
117 let e = CoreError::SymbolicStructure("sparse error".into());
118 assert!(e.to_string().contains("sparse error"));
119 }
120
121 #[test]
122 fn test_core_error_parallel_computation_display() {
123 let e = CoreError::ParallelComputation("thread panic".into());
124 assert!(e.to_string().contains("thread panic"));
125 }
126
127 #[test]
128 fn test_core_error_dimension_mismatch_display() {
129 let e = CoreError::DimensionMismatch("3 vs 6".into());
130 assert!(e.to_string().contains("3 vs 6"));
131 }
132
133 #[test]
134 fn test_core_error_invalid_constraint_display() {
135 let e = CoreError::InvalidConstraint("out of bounds".into());
136 assert!(e.to_string().contains("out of bounds"));
137 }
138
139 #[test]
140 fn test_core_error_loss_function_display() {
141 let e = CoreError::LossFunction("huber weight".into());
142 assert!(e.to_string().contains("huber weight"));
143 }
144
145 #[test]
146 fn test_core_error_invalid_input_display() {
147 let e = CoreError::InvalidInput("null pointer".into());
148 assert!(e.to_string().contains("null pointer"));
149 }
150
151 #[test]
156 fn test_core_error_log_returns_self() {
157 let e = CoreError::InvalidInput("test_log".into());
158 let returned = e.log();
159 assert!(returned.to_string().contains("test_log"));
160 }
161
162 #[test]
163 fn test_core_error_log_with_source_returns_self() {
164 let e = CoreError::DimensionMismatch("mismatch".into());
165 let source = std::io::Error::other("source error");
166 let returned = e.log_with_source(source);
167 assert!(returned.to_string().contains("mismatch"));
168 }
169
170 #[test]
175 fn test_core_result_ok() {
176 let r: CoreResult<i32> = Ok(42);
177 assert!(matches!(r, Ok(42)));
178 }
179
180 #[test]
181 fn test_core_result_err() {
182 let r: CoreResult<i32> = Err(CoreError::InvalidInput("oops".into()));
183 assert!(r.is_err());
184 }
185}