Compare commits
2 commits
17e0edb3ca
...
182f73db27
Author | SHA1 | Date | |
---|---|---|---|
182f73db27 | |||
7dfef8b718 |
5 changed files with 114 additions and 43 deletions
|
@ -1 +1,2 @@
|
|||
pub mod num;
|
||||
pub mod matrix;
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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
40
src/num.rs
Normal 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
35
src/num/bigint.rs
Normal 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 {
|
||||
|
||||
}
|
Loading…
Reference in a new issue