Skip to main content

circulant_rs/
error.rs

1// @module: crate::error
2// @status: stable
3// @owner: code_expert
4// @feature: none
5// @depends: [thiserror]
6// @tests: [unit]
7
8//! Error types for circulant-rs operations.
9
10use thiserror::Error;
11
12/// Errors that can occur during circulant matrix operations.
13#[derive(Error, Debug, Clone, PartialEq)]
14pub enum CirculantError {
15    /// The generator vector is empty.
16    #[error("generator vector cannot be empty")]
17    EmptyGenerator,
18
19    /// Dimension mismatch between matrix and vector.
20    #[error("dimension mismatch: expected {expected}, got {got}")]
21    DimensionMismatch {
22        /// Expected dimension.
23        expected: usize,
24        /// Actual dimension.
25        got: usize,
26    },
27
28    /// Invalid size for FFT (must be positive).
29    #[error("invalid FFT size: {0}")]
30    InvalidFftSize(usize),
31
32    /// Block structure is invalid.
33    #[error("invalid block structure: {0}")]
34    InvalidBlockStructure(String),
35
36    /// Quantum state is not normalized.
37    #[error("quantum state not normalized: norm squared = {0}")]
38    NotNormalized(String),
39
40    /// Invalid coin dimension.
41    #[error("invalid coin dimension: expected {expected}, got {got}")]
42    InvalidCoinDimension {
43        /// Expected coin dimension.
44        expected: usize,
45        /// Actual coin dimension.
46        got: usize,
47    },
48
49    /// Position out of bounds.
50    #[error("position {position} out of bounds for size {size}")]
51    PositionOutOfBounds {
52        /// The invalid position.
53        position: usize,
54        /// The valid size.
55        size: usize,
56    },
57
58    /// Invalid kernel dimensions.
59    #[error("invalid kernel: {0}")]
60    InvalidKernel(String),
61
62    /// Image dimension mismatch.
63    #[error("image dimensions {got:?} incompatible with filter {expected:?}")]
64    ImageDimensionMismatch {
65        /// Expected dimensions.
66        expected: (usize, usize),
67        /// Actual dimensions.
68        got: (usize, usize),
69    },
70
71    /// Hamiltonian is not Hermitian.
72    #[error("Hamiltonian must be Hermitian")]
73    NotHermitian,
74
75    /// Time parameter invalid.
76    #[error("invalid time parameter: {0}")]
77    InvalidTime(String),
78
79    /// Visualization error.
80    #[error("visualization error: {0}")]
81    VisualizationError(String),
82
83    /// Invalid walk parameters.
84    #[error("invalid walk parameters: {0}")]
85    InvalidWalkParameters(String),
86
87    /// Invalid tensor shape.
88    #[error("invalid tensor shape: expected {expected:?}, got {got:?}")]
89    InvalidTensorShape {
90        /// Expected shape.
91        expected: Vec<usize>,
92        /// Actual shape.
93        got: Vec<usize>,
94    },
95
96    /// Invalid tensor dimension.
97    #[error("invalid tensor dimension: expected {expected}, got {got}")]
98    InvalidTensorDimension {
99        /// Expected dimension count.
100        expected: usize,
101        /// Actual dimension count.
102        got: usize,
103    },
104
105    /// Reshape operation failed.
106    #[error("reshape failed: {0}")]
107    ReshapeFailed(String),
108}
109
110/// A specialized Result type for circulant operations.
111pub type Result<T> = std::result::Result<T, CirculantError>;
112
113#[cfg(test)]
114mod tests {
115    use super::*;
116
117    #[test]
118    fn test_error_display_messages() {
119        let err = CirculantError::EmptyGenerator;
120        assert_eq!(err.to_string(), "generator vector cannot be empty");
121
122        let err = CirculantError::DimensionMismatch {
123            expected: 4,
124            got: 3,
125        };
126        assert_eq!(err.to_string(), "dimension mismatch: expected 4, got 3");
127
128        let err = CirculantError::InvalidFftSize(0);
129        assert_eq!(err.to_string(), "invalid FFT size: 0");
130
131        let err = CirculantError::InvalidBlockStructure("non-square blocks".to_string());
132        assert_eq!(
133            err.to_string(),
134            "invalid block structure: non-square blocks"
135        );
136
137        let err = CirculantError::NotNormalized("1.5".to_string());
138        assert_eq!(
139            err.to_string(),
140            "quantum state not normalized: norm squared = 1.5"
141        );
142
143        let err = CirculantError::InvalidCoinDimension {
144            expected: 2,
145            got: 3,
146        };
147        assert_eq!(err.to_string(), "invalid coin dimension: expected 2, got 3");
148
149        let err = CirculantError::PositionOutOfBounds {
150            position: 10,
151            size: 5,
152        };
153        assert_eq!(err.to_string(), "position 10 out of bounds for size 5");
154
155        let err = CirculantError::InvalidKernel("kernel must be odd-sized".to_string());
156        assert_eq!(err.to_string(), "invalid kernel: kernel must be odd-sized");
157
158        let err = CirculantError::ImageDimensionMismatch {
159            expected: (64, 64),
160            got: (32, 32),
161        };
162        assert_eq!(
163            err.to_string(),
164            "image dimensions (32, 32) incompatible with filter (64, 64)"
165        );
166
167        let err = CirculantError::NotHermitian;
168        assert_eq!(err.to_string(), "Hamiltonian must be Hermitian");
169
170        let err = CirculantError::InvalidTime("time must be non-negative".to_string());
171        assert_eq!(
172            err.to_string(),
173            "invalid time parameter: time must be non-negative"
174        );
175
176        let err = CirculantError::VisualizationError("failed to create plot".to_string());
177        assert_eq!(
178            err.to_string(),
179            "visualization error: failed to create plot"
180        );
181
182        let err = CirculantError::InvalidWalkParameters("positions must be positive".to_string());
183        assert_eq!(
184            err.to_string(),
185            "invalid walk parameters: positions must be positive"
186        );
187    }
188
189    #[test]
190    fn test_error_equality() {
191        let err1 = CirculantError::EmptyGenerator;
192        let err2 = CirculantError::EmptyGenerator;
193        assert_eq!(err1, err2);
194
195        let err3 = CirculantError::DimensionMismatch {
196            expected: 4,
197            got: 3,
198        };
199        let err4 = CirculantError::DimensionMismatch {
200            expected: 4,
201            got: 3,
202        };
203        assert_eq!(err3, err4);
204    }
205}