From 1c4b7dfff358b0d61f82ba6e3d68a8bcea0e30b2 Mon Sep 17 00:00:00 2001 From: erius Date: Sat, 11 May 2024 14:12:26 +0300 Subject: [PATCH] Added SquareMatrix struct, started implemeting some methods for Matrix --- src/math/matrix.rs | 63 ----------------- src/math/matrix/matrix.rs | 130 +++++++++++++++++++++++++++++++++++ src/math/matrix/mod.rs | 2 + src/math/matrix/sq_matrix.rs | 54 +++++++++++++++ 4 files changed, 186 insertions(+), 63 deletions(-) delete mode 100644 src/math/matrix.rs create mode 100644 src/math/matrix/matrix.rs create mode 100644 src/math/matrix/mod.rs create mode 100644 src/math/matrix/sq_matrix.rs diff --git a/src/math/matrix.rs b/src/math/matrix.rs deleted file mode 100644 index bb9fad9..0000000 --- a/src/math/matrix.rs +++ /dev/null @@ -1,63 +0,0 @@ -use num::{Integer, Num}; - -pub struct Matrix { - width: usize, height: usize, - data: Box> -} - -impl Matrix { - pub fn new(width: usize, data: Vec) -> Self { - if width == 0 { - panic!("Matrix width must not be 0") - } - let (height, append_zeroes) = data.len().div_rem(&width); - let mut matrix = Self { width, height, data: Box::new(data) }; - if append_zeroes == 0 { return matrix; } - matrix.height += 1; - for _ in 0..append_zeroes { - matrix.data.push(T::zero()); - } - return matrix; - } - - pub fn new_filled(val: T, width: usize, height: usize) -> Self { - let Some(size) = width.checked_mul(height) - else { - panic!("Total matrix size for width {} and height {} exceeds usize limit", width, height) - }; - if size < 2 { - panic!("Total matrix size must be greater than 1, but got {}", size) - } - let data = Box::new(vec![val; size]); - Self { width, height, data } - } - - pub fn new_zeroes(width: usize, height: usize) -> Self { - Self::new_filled(T::zero(), width, height) - } - - pub fn width(&self) -> usize { - self.width - } - - pub fn height(&self) -> usize { - self.height - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - #[should_panic] - fn size_too_big() { - Matrix::::new_zeroes(usize::MAX, 2); - } - - #[test] - #[should_panic] - fn size_too_small() { - Matrix::::new_zeroes(1, 1); - } -} diff --git a/src/math/matrix/matrix.rs b/src/math/matrix/matrix.rs new file mode 100644 index 0000000..5ba39a8 --- /dev/null +++ b/src/math/matrix/matrix.rs @@ -0,0 +1,130 @@ +use std::ops::{Index, IndexMut}; + +use num::Num; + +pub struct Matrix { + pub(super) width: usize, + pub(super) data: Box> +} + +impl Matrix { + pub fn new(mut data: Vec, width: usize) -> Self { + if width <= 0 { + panic!("Matrix width must be greater than 0, but got {}", width) + } + let height = data.len() / width; + let size = width * height; + if size < 2 { + panic!("Total matrix size must be greater than 1, but got {}", size) + } + data.truncate(size); + Self { width, data: Box::new(data) } + } + + pub fn new_filled(val: T, width: usize, height: usize) -> Self { + let Some(size) = width.checked_mul(height) + else { + panic!("Total matrix size for width {} and height {} exceeds usize limit", width, height) + }; + if size < 2 { + panic!("Total matrix size must be greater than 1, but got {}", size) + } + let data = Box::new(vec![val; size]); + Self { width, data } + } + + pub fn new_zeroes(width: usize, height: usize) -> Self { + Self::new_filled(T::zero(), width, height) + } + + pub fn width(&self) -> usize { + self.width + } + + pub fn height(&self) -> usize { + self.data.len() / self.width + } + + pub fn minor(&self, row_index: usize, column_index: usize) -> Self { + if self.width < 2 { + panic!("Matrix width must be greater than 1 to form its minor, but got {}", self.width) + } + let height = self.height(); + if height < 2 { + panic!("Matrix height must be greater than 1 to form its minor, but got {}", height) + } + let minor_width = self.width - 1; + let minor_size = minor_width * (height - 1); + if minor_size < 2 { + panic!("Minor total size must be greater than 2, but got {}", minor_size) + } + let mut minor_data = Vec::with_capacity(minor_size); + for i in 0..row_index { + let row = &self[i]; + todo!() + } + Self { width: minor_width, data: Box::new(minor_data) } + } +} + +impl Index for Matrix { + type Output = [T]; + fn index(&self, index: usize) -> &Self::Output { + let row_start = index * self.width; + &self.data[row_start..row_start + self.width] + } +} + +impl IndexMut for Matrix { + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + let row_start = index * self.width; + &mut self.data[row_start..row_start + self.width] + } +} + +impl Index<(usize, usize)> for Matrix { + type Output = T; + fn index(&self, index: (usize, usize)) -> &Self::Output { + &self.data[index.0 * self.width + index.1] + } +} + +impl IndexMut<(usize, usize)> for Matrix { + fn index_mut(&mut self, index: (usize, usize)) -> &mut Self::Output { + &mut self.data[index.0 * self.width + index.1] + } +} + +macro_rules! matrix { + [ $w:expr; $( $x:expr ),+ ] => { + Matrix::new(vec![$( $x, )+], $w) + }; +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + #[should_panic] + fn size_too_big() { + Matrix::::new_zeroes(usize::MAX, 2); + } + + #[test] + #[should_panic] + fn size_too_small() { + Matrix::::new_zeroes(1, 1); + } + + #[test] + fn new_test() { + let matrix = matrix![3; + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, 10 + ]; + assert_eq!(matrix.width(), 3); + assert_eq!(matrix.height(), 3); + } +} diff --git a/src/math/matrix/mod.rs b/src/math/matrix/mod.rs new file mode 100644 index 0000000..74ad4bc --- /dev/null +++ b/src/math/matrix/mod.rs @@ -0,0 +1,2 @@ +pub mod matrix; +pub mod sq_matrix; \ No newline at end of file diff --git a/src/math/matrix/sq_matrix.rs b/src/math/matrix/sq_matrix.rs new file mode 100644 index 0000000..f3677bd --- /dev/null +++ b/src/math/matrix/sq_matrix.rs @@ -0,0 +1,54 @@ +use num::Num; +use super::matrix::Matrix; + +pub struct SquareMatrix { + matrix: Matrix +} + +impl SquareMatrix { + pub fn new(mut data: Vec, order: usize) -> Self { + let size = Self::check_size(order); + data.truncate(size); + Self { + matrix: Matrix { + width: order, + data: Box::new(data) + } + } + } + + pub fn new_filled(val: T, order: usize) -> Self { + let size = Self::check_size(order); + let data = Box::new(vec![val; size]); + Self { + matrix: Matrix { + width: order, data + } + } + } + + pub fn new_zeroes(order: usize) -> Self { + Self::new_filled(T::zero(), order) + } + + fn check_size(order: usize) -> usize { + if order < 2 { + panic!("Square matrix must have at least order of 2, but got {}", order) + } + let Some(size) = order.checked_mul(order) + else { + panic!("Total matrix size for order {} exceeds usize limit", order) + }; + return size; + } + + pub fn order(&self) -> usize { + self.matrix.width + } +} + +macro_rules! sq_matrix { + [ $o:expr; $( $x:expr ),+ ] => { + SquareMatrix::new(vec![$( $x, )+], $o) + }; +}