diff options
author | Zhongheng Liu <z.liu@outlook.com.gr> | 2025-01-25 12:42:03 +0200 |
---|---|---|
committer | Zhongheng Liu <z.liu@outlook.com.gr> | 2025-01-25 12:42:03 +0200 |
commit | 11665819754fd82d09a5d560e703e2968aa5538c (patch) | |
tree | dacdb660f7c4ee308990ef4cb507a6612593d1cc | |
parent | 1fdf5e281b2e5963b6348b5d577a827c191785f9 (diff) | |
download | matrix-rs-11665819754fd82d09a5d560e703e2968aa5538c.tar.gz matrix-rs-11665819754fd82d09a5d560e703e2968aa5538c.tar.bz2 matrix-rs-11665819754fd82d09a5d560e703e2968aa5538c.zip |
feat: matrix math
mul: impl Mul for LHS: i32, RHS: Matrix
trait: trait MatrixMath definition for cofactor, minors, adjoint,
determinant
-rw-r--r-- | src/lib.rs | 7 | ||||
-rw-r--r-- | src/matrix.rs | 122 | ||||
-rw-r--r-- | src/tests/matrix_test_ops.rs | 2 |
3 files changed, 87 insertions, 44 deletions
@@ -9,7 +9,7 @@ //! //! Examples: //! ``` -//! use matrix::Matrix; +//! use matrix::{Matrix, MatrixMath}; //! use std::str::FromStr; //! let m = Matrix::from_str("1,2,3\n4,5,6\n7,8,9").expect("Expected this to work"); //! println!("Matrix string formatting:\n{}", m); @@ -24,8 +24,11 @@ pub mod error; #[cfg(test)] mod tests; -pub use matrix::Matrix; +pub use matrix::{Matrix, MatrixMath}; pub fn test() { println!("Testing code here"); + let m = Matrix::from(vec![1,2,3,4,5]); + m.transpose(); + m.determinant(); } diff --git a/src/matrix.rs b/src/matrix.rs index bd6b38f..04a01bf 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -11,13 +11,12 @@ //! ``` //! TODO:: Create matrix multiplication method +use crate::error::{MatrixSetValueError, ParseMatrixError}; use std::{ fmt::Display, ops::{Add, Mul, Sub}, str::FromStr, }; - -use crate::error::{MatrixSetValueError, ParseMatrixError}; #[derive(Debug, PartialEq, Eq)] pub struct Matrix { /// Number of rows in matrix. @@ -29,6 +28,71 @@ pub struct Matrix { /// Data stored in the matrix, you should not access this directly data: Vec<Vec<i32>>, } + +pub trait MatrixMath { + fn inverse(&self) -> Matrix { + (1 / (self.determinant())) * &self.adjoint() + } + /// Finds the matrix of cofactors for any N-by-N matrix + fn cofactor(&self) -> Matrix { + todo!(); + } + /// Finds the matrix of minors for any N-by-N matrix. + fn minor(&self) -> Matrix { + todo!(); + } + /// Finds the determinant of any N-by-N matrix. + fn determinant(&self) -> i32 { + todo!(); + } + /// Finds the transpose of any matrix. + fn transpose(&self) -> Matrix { + todo!(); + } + /// Finds the adjoint matrix (transpose of cofactors) for any N-by-N matrix. + fn adjoint(&self) -> Matrix { + self.cofactor().transpose() + } +} +impl MatrixMath for Matrix { + /// Evaluates any N-by-N matrix. + /// + /// This function panics if the matrix is not square! + fn determinant(&self) -> i32 { + if !self.is_square() { + panic!() + }; + if self.nrows == 2 && self.ncols == 2 { + return self.data[0][0] * self.data[1][1] - self.data[0][1] * self.data[1][0]; + } + let mut tmp = 0; + for (i, n) in self.data[0].iter().enumerate() { + let mult = if i % 2 == 0 { -*n } else { *n }; + let eval = self.splice(i).determinant(); + tmp += mult * eval; + } + tmp + } + + /// Evaluates the tranpose of the matrix. + /// + /// Each row becomes a column, each column becomes a row. + fn transpose(&self) -> Matrix { + let mut new_data = Vec::<Vec<i32>>::new(); + for i in 0..self.nrows { + let mut new_row = Vec::<i32>::new(); + for j in 0..self.ncols { + new_row.push(self.data[j][i]); + } + new_data.push(new_row); + } + Matrix { + nrows: self.ncols, + ncols: self.nrows, + data: new_data, + } + } +} impl Matrix { /// Matrix initialiser function. /// @@ -69,7 +133,7 @@ impl Matrix { pub fn is_square(&self) -> bool { self.nrows == self.ncols } - fn splice(&self, at_index: usize) -> Matrix { + pub fn splice(&self, at_index: usize) -> Matrix { let mut data: Vec<Vec<i32>> = Vec::new(); for i in 0..self.data.len() { if i == 0 { @@ -86,44 +150,6 @@ impl Matrix { } Matrix::new(data) } - - /// Evaluates any N-by-N matrix. - /// - /// This function panics if the matrix is not square! - pub fn determinant(&self) -> i32 { - if !self.is_square() { - panic!() - }; - if self.nrows == 2 && self.ncols == 2 { - return self.data[0][0] * self.data[1][1] - self.data[0][1] * self.data[1][0]; - } - let mut tmp = 0; - for (i, n) in self.data[0].iter().enumerate() { - let mult = if i % 2 == 0 { -*n } else { *n }; - let eval = self.splice(i).determinant(); - tmp += mult * eval; - } - tmp - } - - /// Evaluates the tranpose of the matrix. - /// - /// Each row becomes a column, each column becomes a row. - pub fn transpose(&self) -> Matrix { - let mut new_data = Vec::<Vec<i32>>::new(); - for i in 0..self.nrows { - let mut new_row = Vec::<i32>::new(); - for j in 0..self.ncols { - new_row.push(self.data[j][i]); - } - new_data.push(new_row); - } - Matrix { - nrows: self.ncols, - ncols: self.nrows, - data: new_data, - } - } } impl FromStr for Matrix { type Err = ParseMatrixError; @@ -192,6 +218,20 @@ impl<'a, 'b> Sub<&'b Matrix> for &'a Matrix { todo!() } } +impl<'a> Mul<&'a Matrix> for i32 { + type Output = Matrix; + fn mul(self, rhs: &'a Matrix) -> Self::Output { + let mut d: Vec<Vec<i32>> = Vec::new(); + for r in &rhs.data { + let mut nr: Vec<i32> = Vec::new(); + for v in r { + nr.push(self * v); + } + d.push(nr); + } + Matrix::new(d) + } +} impl<'a, 'b> Mul<&'b Matrix> for &'a Matrix { type Output = Matrix; fn mul(self, rhs: &'b Matrix) -> Self::Output { diff --git a/src/tests/matrix_test_ops.rs b/src/tests/matrix_test_ops.rs index fe8c40d..e207c3e 100644 --- a/src/tests/matrix_test_ops.rs +++ b/src/tests/matrix_test_ops.rs @@ -1,6 +1,6 @@ use std::str::FromStr; -use crate::{matrix::Matrix, error::ParseMatrixError}; +use crate::{error::ParseMatrixError, matrix::Matrix, MatrixMath}; #[test] pub fn test_matrix_add() -> Result<(), ParseMatrixError> { |