Matrix can now be of size 1x1, can take minor of 2x2 matrix, minor tests modifications

This commit is contained in:
Egor 2024-05-26 23:52:09 +03:00
parent 17e0edb3ca
commit 7dfef8b718
2 changed files with 38 additions and 43 deletions

View file

@ -14,13 +14,16 @@ pub struct Matrix<T: Num> {
impl<T: Num + Clone> Matrix<T> { impl<T: Num + Clone> Matrix<T> {
pub fn new_filled(val: T, width: usize, height: usize) -> Self { pub fn new_filled(val: T, width: usize, height: usize) -> Self {
if width == 0 {
panic!("Matrix width must be greater than 0, but got {}", width)
}
if height == 0 {
panic!("Matrix height must be greater than 0, but got {}", width)
}
let Some(size) = width.checked_mul(height) let Some(size) = width.checked_mul(height)
else { else {
panic!("Total matrix size for width {} and height {} exceeds usize limit", width, height) 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]); let data = Box::new(vec![val; size]);
Self { width, data } Self { width, data }
} }
@ -48,15 +51,14 @@ impl<T: Num + Clone> Matrix<T> {
impl<T: Num> Matrix<T> { impl<T: Num> Matrix<T> {
pub fn new(mut data: Vec<T>, width: usize) -> Self { pub fn new(mut data: Vec<T>, width: usize) -> Self {
if width <= 0 { if width == 0 {
panic!("Matrix width must be greater than 0, but got {}", width) panic!("Matrix width must be greater than 0, but got {}", width)
} }
let height = data.len() / width; if data.len() < width {
let size = width * height; panic!("Data vector must be greater than or equal to width, but got length {} for width {}", data.len(), width)
if size < 2 {
panic!("Total matrix size must be greater than 1, but got {}", size)
} }
data.truncate(size); let odd_elements = data.len() % width;
data.truncate(data.len() - odd_elements);
Self { width, data: Box::new(data) } Self { width, data: Box::new(data) }
} }
@ -100,23 +102,23 @@ impl<T: Num> Matrix<T> {
} }
pub fn remove_row(&mut self, i: usize) { pub fn remove_row(&mut self, i: usize) {
if self.height() <= 2 { if self.height() == 1 {
panic!("Unable to remove row of a matrix with height {}", self.height()); panic!("Unable to remove row of a matrix with height 1");
} }
let row_start = i * self.width; let row_start = i * self.width;
self.data.drain(row_start..row_start+self.width); self.data.drain(row_start..row_start+self.width);
} }
pub fn remove_last_row(&mut self) { pub fn remove_last_row(&mut self) {
if self.height() <= 2 { if self.height() == 1 {
panic!("Unable to remove row of a matrix with height {}", self.height()); panic!("Unable to remove row of a matrix with height 1");
} }
self.data.truncate(self.data.len() - self.width); self.data.truncate(self.data.len() - self.width);
} }
pub fn remove_column(&mut self, j: usize) { pub fn remove_column(&mut self, j: usize) {
if self.width <= 2 { if self.width == 1 {
panic!("Unable to remove column of a matrix with height {}", self.width); panic!("Unable to remove column of a matrix with width 1");
} }
for i in 0..self.height() { for i in 0..self.height() {
let remove_at = i * (self.width - 1) + j; let remove_at = i * (self.width - 1) + j;
@ -178,9 +180,15 @@ mod tests {
} }
#[test] #[test]
#[should_panic(expected = "size must be greater")] #[should_panic(expected = "width must be greater than 0")]
fn size_too_small() { fn width_zero() {
Matrix::<i32>::new_zeroes(1, 1); Matrix::<i32>::new_zeroes(0, 1);
}
#[test]
#[should_panic(expected = "height must be greater than 0")]
fn height_zero() {
Matrix::<i32>::new_zeroes(1, 0);
} }
#[test] #[test]
@ -310,18 +318,17 @@ mod tests {
#[should_panic(expected = "Unable to remove")] #[should_panic(expected = "Unable to remove")]
fn remove_row_wrong_height() { fn remove_row_wrong_height() {
matrix![2; matrix![2;
1, 2, 1, 2
3, 4 ].remove_row(0);
].remove_row(1);
} }
#[test] #[test]
#[should_panic(expected = "Unable to remove")] #[should_panic(expected = "Unable to remove")]
fn remove_column_wrong_height() { fn remove_column_wrong_height() {
matrix![2; matrix![1;
1, 2, 1,
3, 4 3
].remove_column(1); ].remove_column(0);
} }
#[test] #[test]

View file

@ -4,15 +4,12 @@ use num::Num;
impl<T: Num + Clone> Matrix<T> { impl<T: Num + Clone> Matrix<T> {
pub fn minor(&self, row_index: usize, column_index: usize) -> Self { pub fn minor(&self, row_index: usize, column_index: usize) -> Self {
if self.width < 2 { if self.width == 1 {
panic!("Matrix width must be greater than 1 to form its minor, but got {}", self.width) panic!("Unable to take minor of a matrix with width 1")
} }
let height = self.height(); let height = self.height();
if height < 2 { if height == 1 {
panic!("Matrix height must be greater than 1 to form its minor, but got {}", height) panic!("Unable to take minor of a matrix with height 1")
}
if self.width == 2 && height == 2 {
panic!("Unable to form minor of a 2x2 matrix");
} }
let minor_width = self.width - 1; let minor_width = self.width - 1;
let mut minor_data = Box::new(Vec::with_capacity(minor_width * (height - 1))); let mut minor_data = Box::new(Vec::with_capacity(minor_width * (height - 1)));
@ -62,22 +59,13 @@ mod tests {
} }
#[test] #[test]
#[should_panic(expected = "minor of a 2x2 matrix")] #[should_panic(expected = "Unable to take minor of a matrix with width 1")]
fn minor_2x2_panic() {
matrix![2;
1, 2,
3, 4
].minor(0, 0);
}
#[test]
#[should_panic(expected = "width must be greater")]
fn minor_1xn_panic() { fn minor_1xn_panic() {
matrix![1; 1, 2, 3, 4].minor(0, 0); matrix![1; 1, 2, 3, 4].minor(0, 0);
} }
#[test] #[test]
#[should_panic(expected = "height must be greater")] #[should_panic(expected = "Unable to take minor of a matrix with height 1")]
fn minor_nx1_panic() { fn minor_nx1_panic() {
matrix![4; 1, 2, 3, 4].minor(0, 0); matrix![4; 1, 2, 3, 4].minor(0, 0);
} }