diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..b8b6439 --- /dev/null +++ b/src/error.rs @@ -0,0 +1,48 @@ +use std::fmt; + +use crate::{matrix::MatrixError, properties::PropertiesError, solvers::SolverError}; + +#[derive(Debug)] +pub enum CEAError { + Matrix(MatrixError), + Solver(SolverError), + Properties(PropertiesError), +} + +impl fmt::Display for CEAError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + CEAError::Matrix(e) => write!(f, "matrix error: {}", e), + CEAError::Solver(e) => write!(f, "solver error: {}", e), + CEAError::Properties(e) => write!(f, "properties error: {}", e), + } + } +} + +impl std::error::Error for CEAError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + CEAError::Matrix(e) => Some(e), + CEAError::Solver(e) => Some(e), + CEAError::Properties(e) => Some(e), + } + } +} + +impl From for CEAError { + fn from(e: MatrixError) -> Self { + CEAError::Matrix(e) + } +} + +impl From for CEAError { + fn from(e: SolverError) -> Self { + CEAError::Solver(e) + } +} + +impl From for CEAError { + fn from(e: PropertiesError) -> Self { + CEAError::Properties(e) + } +} diff --git a/src/lib.rs b/src/lib.rs index 95cdfcf..3c96114 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,9 @@ pub mod consts; +pub mod error; pub mod matrix; pub mod mixtures; pub mod properties; +pub mod solvers; #[macro_export] macro_rules! assert_delta { diff --git a/src/matrix.rs b/src/matrix.rs index 8d39ff5..5763240 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -65,10 +65,13 @@ impl fmt::Display for MatrixError { } } +impl std::error::Error for MatrixError {} + fn make_index_error(i: usize, j: usize, m: &Matrix) -> MatrixError { MatrixError::IndexError(i, j, m.m, m.n) } +#[derive(Clone)] pub struct Matrix { data: Vec, m: usize, @@ -153,6 +156,21 @@ impl Matrix { } Ok(c) } + + pub fn shape(&self) -> (usize, usize) { + (self.m, self.n) + } + + pub fn swap_rows(&mut self, i: usize, j: usize) { + if i == j { + return; + } + for col in 0..self.n { + let first_index = self.index(i, col); + let second_index = self.index(j, col); + self.data.swap(first_index, second_index); + } + } } impl Display for Matrix { @@ -259,4 +277,28 @@ mod test { assert_eq!(*atranspose.get(3, 1).unwrap(), 8); assert_eq!(*atranspose.get(3, 2).unwrap(), 12); } + + #[test] + fn test_swap_rows() { + let mut m = Matrix::from_vec(3, 3, vec![1, 2, 3, 4, 5, 6, 7, 8, 9]).unwrap(); + + // Swap rows 0 and 2 + m.swap_rows(0, 2); + assert_eq!(*m.get(0, 0).unwrap(), 7); + assert_eq!(*m.get(0, 1).unwrap(), 8); + assert_eq!(*m.get(0, 2).unwrap(), 9); + assert_eq!(*m.get(2, 0).unwrap(), 1); + assert_eq!(*m.get(2, 1).unwrap(), 2); + assert_eq!(*m.get(2, 2).unwrap(), 3); + // Row 1 unchanged + assert_eq!(*m.get(1, 0).unwrap(), 4); + assert_eq!(*m.get(1, 1).unwrap(), 5); + assert_eq!(*m.get(1, 2).unwrap(), 6); + + // Swapping a row with itself is a no-op + m.swap_rows(1, 1); + assert_eq!(*m.get(1, 0).unwrap(), 4); + assert_eq!(*m.get(1, 1).unwrap(), 5); + assert_eq!(*m.get(1, 2).unwrap(), 6); + } }