Compare commits

...

2 commits

5 changed files with 114 additions and 43 deletions

View file

@ -1 +1,2 @@
pub mod num;
pub mod matrix;

View file

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

View file

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

40
src/num.rs Normal file
View file

@ -0,0 +1,40 @@
mod bigint;
use std::ops::*;
pub trait Signed: Neg {}
pub trait NumOps<Rhs = Self>: Sized + Add<Rhs> + Sub<Rhs> + Mul<Rhs> + Div<Rhs> {}
pub trait NumAssignOps<Rhs = Self>: AddAssign<Rhs> + SubAssign<Rhs> + MulAssign<Rhs> + DivAssign<Rhs> {}
pub trait Num: PartialEq + Default + NumOps + NumAssignOps {}
macro_rules! impl_num {
($t:ty) => {
impl NumOps for $t {}
impl NumAssignOps for $t {}
impl Num for $t {}
};
}
macro_rules! impl_sign_num {
($t:ty) => {
impl_num!($t);
impl Signed for $t {}
};
}
impl_num!(u8);
impl_num!(u16);
impl_num!(u32);
impl_num!(u64);
impl_num!(u128);
impl_num!(usize);
impl_sign_num!(i8);
impl_sign_num!(i16);
impl_sign_num!(i32);
impl_sign_num!(i64);
impl_sign_num!(i128);
impl_sign_num!(isize);
impl_sign_num!(f32);
impl_sign_num!(f64);

35
src/num/bigint.rs Normal file
View file

@ -0,0 +1,35 @@
pub struct BigInt {
negative: bool,
num: BigUInt
}
pub struct BigUInt {
data: Vec<u64>
}
impl BigUInt {
pub fn new() -> Self {
Self::new_from(0)
}
pub fn new_from(num: u64) -> Self {
Self { data: vec![num] }
}
}
impl BigInt {
pub fn new() -> Self {
Self { negative: false, num: BigUInt::new() }
}
pub fn new_from(num: i64) -> Self {
let (negative, num) = if num < 0 { (true, -num as u64) }
else { (false, num as u64) };
Self { negative, num: BigUInt::new_from(num) }
}
}
#[cfg(test)]
mod tests {
}