Changed generic type T of matrix to only accept Num + Clone
Derived some traits for Matrix Added panic when forming minor of a 2x2 matrix Added row iteration and indexed (i, j) element iteration Added more tests to Matrix
This commit is contained in:
parent
883df942ea
commit
25c1f55254
2 changed files with 159 additions and 18 deletions
|
@ -2,12 +2,13 @@ use std::ops::{Index, IndexMut};
|
|||
|
||||
use num::Num;
|
||||
|
||||
pub struct Matrix<T: Num> {
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
pub struct Matrix<T: Num + Clone> {
|
||||
width: usize,
|
||||
data: Box<Vec<T>>
|
||||
}
|
||||
|
||||
impl<T: Num + Copy> Matrix<T> {
|
||||
impl<T: Num + Clone> Matrix<T> {
|
||||
pub fn new_filled(val: T, width: usize, height: usize) -> Self {
|
||||
let Some(size) = width.checked_mul(height)
|
||||
else {
|
||||
|
@ -23,9 +24,7 @@ impl<T: Num + Copy> Matrix<T> {
|
|||
pub fn new_zeroes(width: usize, height: usize) -> Self {
|
||||
Self::new_filled(T::zero(), width, height)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Num> Matrix<T> {
|
||||
pub fn new(mut data: Vec<T>, width: usize) -> Self {
|
||||
if width <= 0 {
|
||||
panic!("Matrix width must be greater than 0, but got {}", width)
|
||||
|
@ -63,12 +62,14 @@ impl<T: Num> Matrix<T> {
|
|||
if height < 2 {
|
||||
panic!("Matrix height must be greater than 1 to form its minor, but got {}", height)
|
||||
}
|
||||
if self.width == 2 && height == 2 {
|
||||
panic!("Unable to form minor of a 2x2 matrix");
|
||||
}
|
||||
let minor_width = self.width - 1;
|
||||
let mut minor_data = Vec::with_capacity(minor_width * (height - 1));
|
||||
for i in 0..row_index {
|
||||
if i == row_index { continue; }
|
||||
let row = &self[i];
|
||||
todo!()
|
||||
for (i, j, e) in self.iter_indexed() {
|
||||
if i == row_index || j == column_index { continue; }
|
||||
minor_data.push(e.clone());
|
||||
}
|
||||
Self { width: minor_width, data: Box::new(minor_data) }
|
||||
}
|
||||
|
@ -77,16 +78,80 @@ impl<T: Num> Matrix<T> {
|
|||
self.data.into_iter()
|
||||
}
|
||||
|
||||
pub fn into_iter_indexed(self) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn into_iter_rows(self) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> std::slice::Iter<T> {
|
||||
self.data.iter()
|
||||
}
|
||||
|
||||
pub fn iter_indexed<'a>(&'a self) -> IterIndexed<'a, T> {
|
||||
IterIndexed { i: 0, j: 0, width: self.width, matrix_iter: self.iter() }
|
||||
}
|
||||
|
||||
pub fn iter_rows(&self) -> std::slice::Chunks<T> {
|
||||
self.data.chunks(self.width)
|
||||
}
|
||||
|
||||
pub fn iter_mut(&mut self) -> std::slice::IterMut<T> {
|
||||
self.data.iter_mut()
|
||||
}
|
||||
|
||||
pub fn iter_indexed_mut<'a>(&'a mut self) -> IterIndexedMut<'a, T> {
|
||||
IterIndexedMut { i: 0, j: 0, width: self.width, matrix_iter_mut: self.iter_mut() }
|
||||
}
|
||||
|
||||
pub fn iter_mut_rows(&mut self) -> std::slice::ChunksMut<T> {
|
||||
self.data.chunks_mut(self.width)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Num> Index<usize> for Matrix<T> {
|
||||
pub struct IterIndexed<'a, T: Num + Clone> {
|
||||
i: usize, j: usize, width: usize,
|
||||
matrix_iter: std::slice::Iter<'a, T>
|
||||
}
|
||||
|
||||
pub struct IterIndexedMut<'a, T: Num + Clone> {
|
||||
i: usize, j: usize, width: usize,
|
||||
matrix_iter_mut: std::slice::IterMut<'a, T>
|
||||
}
|
||||
|
||||
impl<'a, T: Num + Clone> Iterator for IterIndexed<'a, T> {
|
||||
type Item = (usize, usize, &'a T);
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.matrix_iter.next().map(|e| {
|
||||
let next = (self.i, self.j, e);
|
||||
self.j += 1;
|
||||
if self.j >= self.width {
|
||||
self.i += 1;
|
||||
self.j = 0;
|
||||
}
|
||||
next
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Num + Clone> Iterator for IterIndexedMut<'a, T> {
|
||||
type Item = (usize, usize, &'a mut T);
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.matrix_iter_mut.next().map(|e| {
|
||||
let next = (self.i, self.j, e);
|
||||
self.j += 1;
|
||||
if self.j >= self.width {
|
||||
self.i += 1;
|
||||
self.j = 0;
|
||||
}
|
||||
next
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Num + Clone> Index<usize> for Matrix<T> {
|
||||
type Output = [T];
|
||||
fn index(&self, index: usize) -> &Self::Output {
|
||||
let row_start = index * self.width;
|
||||
|
@ -94,26 +159,27 @@ impl<T: Num> Index<usize> for Matrix<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Num> IndexMut<usize> for Matrix<T> {
|
||||
impl<T: Num + Clone> IndexMut<usize> for Matrix<T> {
|
||||
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<T: Num> Index<(usize, usize)> for Matrix<T> {
|
||||
impl<T: Num + Clone> Index<(usize, usize)> for Matrix<T> {
|
||||
type Output = T;
|
||||
fn index(&self, index: (usize, usize)) -> &Self::Output {
|
||||
&self.data[index.0 * self.width + index.1]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Num> IndexMut<(usize, usize)> for Matrix<T> {
|
||||
impl<T: Num + Clone> IndexMut<(usize, usize)> for Matrix<T> {
|
||||
fn index_mut(&mut self, index: (usize, usize)) -> &mut Self::Output {
|
||||
&mut self.data[index.0 * self.width + index.1]
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! matrix {
|
||||
[ $w:expr; $( $x:expr ),+ ] => {
|
||||
Matrix::new(vec![$( $x, )+], $w)
|
||||
|
@ -128,7 +194,6 @@ mod tests {
|
|||
#[should_panic]
|
||||
fn size_too_big() {
|
||||
Matrix::<i32>::new_zeroes(usize::MAX, 2);
|
||||
let a = vec![0].into_iter();
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -138,7 +203,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn new_test() {
|
||||
fn new() {
|
||||
let matrix = matrix![3;
|
||||
1, 2, 3,
|
||||
4, 5, 6,
|
||||
|
@ -147,4 +212,81 @@ mod tests {
|
|||
assert_eq!(matrix.width(), 3);
|
||||
assert_eq!(matrix.height(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn index() {
|
||||
let mut matrix = matrix![3;
|
||||
1, 2, 3,
|
||||
4, 5, 6,
|
||||
7, 8, 9
|
||||
];
|
||||
assert_eq!(matrix[(0, 0)], 1);
|
||||
assert_eq!(matrix[(1, 2)], 6);
|
||||
assert_eq!(matrix[(2, 2)], 9);
|
||||
matrix[(1, 2)] = 10;
|
||||
assert_eq!(matrix[(1, 2)], 10);
|
||||
|
||||
assert_eq!(matrix[0][0], 1);
|
||||
assert_eq!(matrix[2][1], 8);
|
||||
assert_eq!(matrix[2][2], 9);
|
||||
matrix[2][1] = 0;
|
||||
assert_eq!(matrix[2][1], 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iter() {
|
||||
let data = vec![1,2,3,4,5,6,7,8,9];
|
||||
let mut matrix = Matrix::new(data.clone(), 3);
|
||||
for (i, e) in matrix.iter().enumerate() {
|
||||
assert_eq!(data[i], *e);
|
||||
}
|
||||
for (i, e) in matrix.iter_mut().enumerate() {
|
||||
*e += 2;
|
||||
assert_eq!(data[i] + 2, *e);
|
||||
}
|
||||
for (i, e) in matrix.into_iter().enumerate() {
|
||||
assert_eq!(data[i] + 2, e);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn minor() {
|
||||
let matrix = matrix![4;
|
||||
1, 2, 3, 4,
|
||||
5, 6, 7, 8,
|
||||
9, 10, 11, 12
|
||||
];
|
||||
assert_eq!(matrix.minor(0, 0), matrix![3;
|
||||
6, 7, 8,
|
||||
10, 11, 12
|
||||
]);
|
||||
assert_eq!(matrix.minor(1, 2), matrix![3;
|
||||
1, 2, 4,
|
||||
9, 10, 12
|
||||
]);
|
||||
assert_eq!(matrix.minor(0, 0).minor(0, 0), matrix![2;
|
||||
11, 12
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn minor_2x2_panic() {
|
||||
matrix![2;
|
||||
1, 2,
|
||||
3, 4
|
||||
].minor(0, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn minor_1xn_panic() {
|
||||
matrix![1; 1, 2, 3, 4].minor(0, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn minor_nx1_panic() {
|
||||
matrix![4; 1, 2, 3, 4].minor(0, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use num::Num;
|
||||
use super::matrix::Matrix;
|
||||
|
||||
pub struct SquareMatrix<T: Num> {
|
||||
pub struct SquareMatrix<T: Num + Clone> {
|
||||
matrix: Matrix<T>
|
||||
}
|
||||
|
||||
impl<T: Num + Copy> SquareMatrix<T> {
|
||||
impl<T: Num + Clone> SquareMatrix<T> {
|
||||
pub fn new_filled(val: T, order: usize) -> Self {
|
||||
let size = check_size(order);
|
||||
let data = vec![val; size];
|
||||
|
@ -17,9 +17,7 @@ impl<T: Num + Copy> SquareMatrix<T> {
|
|||
pub fn new_zeroes(order: usize) -> Self {
|
||||
Self::new_filled(T::zero(), order)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Num> SquareMatrix<T> {
|
||||
pub fn new(mut data: Vec<T>, order: usize) -> Self {
|
||||
let size = check_size(order);
|
||||
data.truncate(size);
|
||||
|
@ -44,6 +42,7 @@ fn check_size(order: usize) -> usize {
|
|||
return size;
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! sq_matrix {
|
||||
[ $o:expr; $( $x:expr ),+ ] => {
|
||||
SquareMatrix::new(vec![$( $x, )+], $o)
|
||||
|
|
Loading…
Reference in a new issue