mirror of
https://github.com/SinTan1729/matrix-basic.git
synced 2024-12-26 05:48:36 -06:00
new: Added error enum to streamline throwing errors
This commit is contained in:
parent
55ac044c39
commit
4ce9554e1f
2 changed files with 46 additions and 15 deletions
29
src/errors.rs
Normal file
29
src/errors.rs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
use std::{
|
||||||
|
error::Error,
|
||||||
|
fmt::{self, Display, Formatter},
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Error type for using in this crate. Mostly to reduce writing
|
||||||
|
/// error description every time.
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum MatrixError {
|
||||||
|
/// Provided matrix isn't square.
|
||||||
|
NotSquare,
|
||||||
|
/// provided matrix is singular.
|
||||||
|
Singular,
|
||||||
|
/// Provided array has unequal rows.
|
||||||
|
UnequalRows,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for MatrixError {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let out = match *self {
|
||||||
|
Self::NotSquare => "provided matrix isn't square",
|
||||||
|
Self::Singular => "provided matrix is singular",
|
||||||
|
Self::UnequalRows => "provided array has unequal rows",
|
||||||
|
};
|
||||||
|
write!(f, "{out}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error for MatrixError {}
|
32
src/lib.rs
32
src/lib.rs
|
@ -8,6 +8,7 @@
|
||||||
//!
|
//!
|
||||||
//! Sayantan Santra (2023)
|
//! Sayantan Santra (2023)
|
||||||
|
|
||||||
|
use errors::MatrixError;
|
||||||
use num::{
|
use num::{
|
||||||
traits::{One, Zero},
|
traits::{One, Zero},
|
||||||
Integer,
|
Integer,
|
||||||
|
@ -18,6 +19,7 @@ use std::{
|
||||||
result::Result,
|
result::Result,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub mod errors;
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
/// Trait a type must satisfy to be element of a matrix. This is
|
/// Trait a type must satisfy to be element of a matrix. This is
|
||||||
|
@ -62,7 +64,7 @@ impl<T: ToMatrix> Matrix<T> {
|
||||||
/// will create the following matrix:
|
/// will create the following matrix:
|
||||||
/// ⌈1, 2, 3⌉
|
/// ⌈1, 2, 3⌉
|
||||||
/// ⌊4, 5, 6⌋
|
/// ⌊4, 5, 6⌋
|
||||||
pub fn from(entries: Vec<Vec<T>>) -> Result<Matrix<T>, &'static str> {
|
pub fn from(entries: Vec<Vec<T>>) -> Result<Matrix<T>, MatrixError> {
|
||||||
let mut equal_rows = true;
|
let mut equal_rows = true;
|
||||||
let row_len = entries[0].len();
|
let row_len = entries[0].len();
|
||||||
for row in &entries {
|
for row in &entries {
|
||||||
|
@ -74,7 +76,7 @@ impl<T: ToMatrix> Matrix<T> {
|
||||||
if equal_rows {
|
if equal_rows {
|
||||||
Ok(Matrix { entries })
|
Ok(Matrix { entries })
|
||||||
} else {
|
} else {
|
||||||
Err("Unequal rows.")
|
Err(MatrixError::UnequalRows)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,7 +154,7 @@ impl<T: ToMatrix> Matrix<T> {
|
||||||
/// let m = Matrix::from(vec![vec![1, 2], vec![3, 4]]).unwrap();
|
/// let m = Matrix::from(vec![vec![1, 2], vec![3, 4]]).unwrap();
|
||||||
/// assert_eq!(m.det(), Ok(-2));
|
/// assert_eq!(m.det(), Ok(-2));
|
||||||
/// ```
|
/// ```
|
||||||
pub fn det(&self) -> Result<T, &'static str> {
|
pub fn det(&self) -> Result<T, MatrixError> {
|
||||||
if self.is_square() {
|
if self.is_square() {
|
||||||
// It's a recursive algorithm using minors.
|
// It's a recursive algorithm using minors.
|
||||||
// TODO: Implement a faster algorithm.
|
// TODO: Implement a faster algorithm.
|
||||||
|
@ -173,7 +175,7 @@ impl<T: ToMatrix> Matrix<T> {
|
||||||
};
|
};
|
||||||
Ok(out)
|
Ok(out)
|
||||||
} else {
|
} else {
|
||||||
Err("Provided matrix isn't square.")
|
Err(MatrixError::NotSquare)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,7 +189,7 @@ impl<T: ToMatrix> Matrix<T> {
|
||||||
/// let m = Matrix::from(vec![vec![1.0, 2.0], vec![3.0, 4.0]]).unwrap();
|
/// let m = Matrix::from(vec![vec![1.0, 2.0], vec![3.0, 4.0]]).unwrap();
|
||||||
/// assert_eq!(m.det_in_field(), Ok(-2.0));
|
/// assert_eq!(m.det_in_field(), Ok(-2.0));
|
||||||
/// ```
|
/// ```
|
||||||
pub fn det_in_field(&self) -> Result<T, &'static str>
|
pub fn det_in_field(&self) -> Result<T, MatrixError>
|
||||||
where
|
where
|
||||||
T: One,
|
T: One,
|
||||||
T: PartialEq,
|
T: PartialEq,
|
||||||
|
@ -227,7 +229,7 @@ impl<T: ToMatrix> Matrix<T> {
|
||||||
}
|
}
|
||||||
Ok(multiplier)
|
Ok(multiplier)
|
||||||
} else {
|
} else {
|
||||||
Err("Provided matrix isn't square.")
|
Err(MatrixError::NotSquare)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -351,7 +353,7 @@ impl<T: ToMatrix> Matrix<T> {
|
||||||
/// let m = Matrix::from(vec![vec![1, 2], vec![3, 4]]).unwrap();
|
/// let m = Matrix::from(vec![vec![1, 2], vec![3, 4]]).unwrap();
|
||||||
/// assert_eq!(m.trace(), Ok(5));
|
/// assert_eq!(m.trace(), Ok(5));
|
||||||
/// ```
|
/// ```
|
||||||
pub fn trace(self) -> Result<T, &'static str> {
|
pub fn trace(self) -> Result<T, MatrixError> {
|
||||||
if self.is_square() {
|
if self.is_square() {
|
||||||
let mut out = self.entries[0][0];
|
let mut out = self.entries[0][0];
|
||||||
for i in 1..self.height() {
|
for i in 1..self.height() {
|
||||||
|
@ -359,7 +361,7 @@ impl<T: ToMatrix> Matrix<T> {
|
||||||
}
|
}
|
||||||
Ok(out)
|
Ok(out)
|
||||||
} else {
|
} else {
|
||||||
Err("Provided matrix isn't square.")
|
Err(MatrixError::NotSquare)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -408,7 +410,7 @@ impl<T: ToMatrix> Matrix<T> {
|
||||||
/// let n = Matrix::from(vec![vec![-2.0, 1.0], vec![1.5, -0.5]]).unwrap();
|
/// let n = Matrix::from(vec![vec![-2.0, 1.0], vec![1.5, -0.5]]).unwrap();
|
||||||
/// assert_eq!(m.inverse(), Ok(n));
|
/// assert_eq!(m.inverse(), Ok(n));
|
||||||
/// ```
|
/// ```
|
||||||
pub fn inverse(&self) -> Result<Self, &'static str>
|
pub fn inverse(&self) -> Result<Self, MatrixError>
|
||||||
where
|
where
|
||||||
T: Div<Output = T>,
|
T: Div<Output = T>,
|
||||||
T: One,
|
T: One,
|
||||||
|
@ -436,7 +438,7 @@ impl<T: ToMatrix> Matrix<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if zero_column {
|
if zero_column {
|
||||||
return Err("Provided matrix is singular.");
|
return Err(MatrixError::Singular);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for j in (i + 1)..h {
|
for j in (i + 1)..h {
|
||||||
|
@ -454,7 +456,7 @@ impl<T: ToMatrix> Matrix<T> {
|
||||||
// Then we reduce the rows
|
// Then we reduce the rows
|
||||||
for i in 0..h {
|
for i in 0..h {
|
||||||
if rows[i][i] == T::zero() {
|
if rows[i][i] == T::zero() {
|
||||||
return Err("Provided matrix is singular.");
|
return Err(MatrixError::Singular);
|
||||||
}
|
}
|
||||||
let divisor = rows[i][i];
|
let divisor = rows[i][i];
|
||||||
for entry in rows[i].iter_mut().skip(i) {
|
for entry in rows[i].iter_mut().skip(i) {
|
||||||
|
@ -477,7 +479,7 @@ impl<T: ToMatrix> Matrix<T> {
|
||||||
|
|
||||||
Ok(Matrix { entries: out })
|
Ok(Matrix { entries: out })
|
||||||
} else {
|
} else {
|
||||||
Err("Provided matrix isn't square.")
|
Err(MatrixError::NotSquare)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -496,7 +498,7 @@ impl<T: Mul<Output = T> + ToMatrix> Mul for Matrix<T> {
|
||||||
fn mul(self, other: Self) -> Self::Output {
|
fn mul(self, other: Self) -> Self::Output {
|
||||||
let width = self.width();
|
let width = self.width();
|
||||||
if width != other.height() {
|
if width != other.height() {
|
||||||
panic!("Row length of first matrix must be same as column length of second matrix.");
|
panic!("row length of first matrix != column length of second matrix");
|
||||||
} else {
|
} else {
|
||||||
let mut out = Vec::new();
|
let mut out = Vec::new();
|
||||||
for row in self.rows() {
|
for row in self.rows() {
|
||||||
|
@ -527,7 +529,7 @@ impl<T: Mul<Output = T> + ToMatrix> Add for Matrix<T> {
|
||||||
}
|
}
|
||||||
Matrix { entries: out }
|
Matrix { entries: out }
|
||||||
} else {
|
} else {
|
||||||
panic!("Both matrices must be of same dimensions.");
|
panic!("provided matrices have different dimensions");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -551,7 +553,7 @@ impl<T: ToMatrix> Sub for Matrix<T> {
|
||||||
if self.height() == other.height() && self.width() == other.width() {
|
if self.height() == other.height() && self.width() == other.width() {
|
||||||
self + -other
|
self + -other
|
||||||
} else {
|
} else {
|
||||||
panic!("Both matrices must be of same dimensions.");
|
panic!("provided matrices have different dimensions");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue