1#![allow(clippy::missing_errors_doc, clippy::many_single_char_names)]
4
5use std::fmt;
6
7use nabled_core::errors::{IntoNabledError, NabledError, ShapeError};
8
9pub mod dare;
10pub mod gramian;
11pub mod lqr;
12pub mod observer;
13pub mod pole;
14
15#[derive(Debug, Clone, PartialEq)]
16pub enum ControlError {
17 EmptyMatrix,
18 DimensionMismatch,
19 InvalidInput(String),
20 ConvergenceFailed,
21 SingularSystem,
22}
23
24impl fmt::Display for ControlError {
25 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26 match self {
27 ControlError::EmptyMatrix => write!(f, "matrix cannot be empty"),
28 ControlError::DimensionMismatch => write!(f, "input dimensions are incompatible"),
29 ControlError::InvalidInput(message) => write!(f, "invalid input: {message}"),
30 ControlError::ConvergenceFailed => write!(f, "control iteration did not converge"),
31 ControlError::SingularSystem => write!(f, "singular control system"),
32 }
33 }
34}
35
36impl std::error::Error for ControlError {}
37
38impl IntoNabledError for ControlError {
39 fn into_nabled_error(self) -> NabledError {
40 match self {
41 ControlError::EmptyMatrix => NabledError::Shape(ShapeError::EmptyInput),
42 ControlError::DimensionMismatch => NabledError::Shape(ShapeError::DimensionMismatch),
43 ControlError::InvalidInput(message) => NabledError::InvalidInput(message),
44 ControlError::ConvergenceFailed => NabledError::ConvergenceFailed,
45 ControlError::SingularSystem => NabledError::SingularMatrix,
46 }
47 }
48}
49
50#[cfg(test)]
51mod tests {
52 use nabled_core::errors::{IntoNabledError, NabledError, ShapeError};
53
54 use super::*;
55
56 #[test]
57 fn control_errors_display_and_map_to_shared_taxonomy() {
58 assert_eq!(ControlError::EmptyMatrix.to_string(), "matrix cannot be empty");
59 assert_eq!(
60 ControlError::DimensionMismatch.to_string(),
61 "input dimensions are incompatible"
62 );
63 assert_eq!(
64 ControlError::InvalidInput("bad poles".to_string()).to_string(),
65 "invalid input: bad poles"
66 );
67 assert_eq!(
68 ControlError::ConvergenceFailed.to_string(),
69 "control iteration did not converge"
70 );
71 assert_eq!(ControlError::SingularSystem.to_string(), "singular control system");
72
73 assert!(matches!(
74 ControlError::EmptyMatrix.into_nabled_error(),
75 NabledError::Shape(ShapeError::EmptyInput)
76 ));
77 assert!(matches!(
78 ControlError::DimensionMismatch.into_nabled_error(),
79 NabledError::Shape(ShapeError::DimensionMismatch)
80 ));
81 assert!(matches!(
82 ControlError::InvalidInput("x".to_string()).into_nabled_error(),
83 NabledError::InvalidInput(_)
84 ));
85 assert!(matches!(
86 ControlError::ConvergenceFailed.into_nabled_error(),
87 NabledError::ConvergenceFailed
88 ));
89 assert!(matches!(
90 ControlError::SingularSystem.into_nabled_error(),
91 NabledError::SingularMatrix
92 ));
93 }
94}