use std::fmt;
#[derive(Debug, Clone, PartialEq)]
pub enum SolveError {
Singular,
NotPositiveDefinite,
NoConvergence { iters: usize, residual: f64 },
DimensionMismatch { expected: usize, got: usize },
InvalidArgument(&'static str),
}
impl fmt::Display for SolveError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
SolveError::Singular => write!(f, "matrix is singular or pivot below threshold"),
SolveError::NotPositiveDefinite => write!(f, "matrix is not positive definite"),
SolveError::NoConvergence { iters, residual } => {
write!(f, "no convergence after {iters} iterations (residual {residual:e})")
}
SolveError::DimensionMismatch { expected, got } => {
write!(f, "dimension mismatch: expected {expected}, got {got}")
}
SolveError::InvalidArgument(msg) => write!(f, "invalid argument: {msg}"),
}
}
}
impl std::error::Error for SolveError {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_display_variants() {
assert!(SolveError::Singular.to_string().contains("singular"));
assert!(SolveError::NotPositiveDefinite.to_string().contains("positive definite"));
let nc = SolveError::NoConvergence { iters: 5, residual: 1e-3 };
assert!(nc.to_string().contains('5'));
let dm = SolveError::DimensionMismatch { expected: 3, got: 4 };
assert!(dm.to_string().contains('3') && dm.to_string().contains('4'));
assert!(SolveError::InvalidArgument("x").to_string().contains('x'));
}
#[test]
fn test_eq_clone() {
let e = SolveError::DimensionMismatch { expected: 2, got: 1 };
assert_eq!(e.clone(), e);
assert_ne!(e, SolveError::Singular);
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum GeomError {
Degenerate(&'static str),
NotManifold,
Empty,
InvalidArgument(&'static str),
}
impl fmt::Display for GeomError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
GeomError::Degenerate(msg) => write!(f, "degenerate geometry: {msg}"),
GeomError::NotManifold => write!(f, "mesh is not manifold"),
GeomError::Empty => write!(f, "empty input"),
GeomError::InvalidArgument(msg) => write!(f, "invalid argument: {msg}"),
}
}
}
impl std::error::Error for GeomError {}
#[cfg(test)]
mod geom_tests {
use super::*;
#[test]
fn test_geom_error_display() {
assert!(GeomError::Degenerate("x").to_string().contains('x'));
assert!(GeomError::NotManifold.to_string().contains("manifold"));
assert!(GeomError::Empty.to_string().contains("empty"));
assert!(GeomError::InvalidArgument("y").to_string().contains('y'));
assert_eq!(GeomError::Empty.clone(), GeomError::Empty);
}
}