#![forbid(unsafe_code)]
#![doc = include_str!("../README.md")]
use core::fmt;
use use_matrix::Matrix2;
use use_vector::Vector2;
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum LinearError {
SingularMatrix { determinant: f64 },
}
impl fmt::Display for LinearError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::SingularMatrix { determinant } => {
write!(
formatter,
"matrix is singular with determinant {determinant}"
)
},
}
}
}
impl std::error::Error for LinearError {}
pub fn solve_2x2(matrix: Matrix2, rhs: Vector2) -> Result<Vector2, LinearError> {
let determinant = matrix.determinant();
matrix
.inverse()
.map(|inverse| inverse * rhs)
.ok_or(LinearError::SingularMatrix { determinant })
}
pub mod prelude;
#[cfg(test)]
mod tests {
use super::{LinearError, solve_2x2};
use use_matrix::Matrix2;
use use_vector::Vector2;
#[test]
fn solves_nonsingular_systems_and_rejects_unusable_ones() {
let matrix = Matrix2::new(2.0, 1.0, 5.0, 3.0);
let rhs = Vector2::new(1.0, 2.0);
let solution = solve_2x2(matrix, rhs).expect("system should solve");
assert_eq!(solution, Vector2::new(1.0, -1.0));
assert_eq!(matrix * solution, rhs);
assert_eq!(
solve_2x2(Matrix2::new(1.0, 2.0, 2.0, 4.0), Vector2::new(1.0, 2.0)),
Err(LinearError::SingularMatrix { determinant: 0.0 })
);
assert!(matches!(
solve_2x2(
Matrix2::new(f64::INFINITY, 0.0, 0.0, 1.0),
Vector2::new(1.0, 2.0)
),
Err(LinearError::SingularMatrix { determinant }) if !determinant.is_finite()
));
}
}