diff --git a/Cargo.toml b/Cargo.toml index ae2d5a2..45cfda3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,4 +1,4 @@ [workspace] -members = ["matrix", "matrix_graphics"] +members = ["matrix", "matrix_graphics", "lin_sys"] default-members = ["matrix_graphics"] resolver = "2" diff --git a/lin_sys/Cargo.toml b/lin_sys/Cargo.toml new file mode 100644 index 0000000..5e83e9e --- /dev/null +++ b/lin_sys/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "lin_sys" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +matrix = {version = "0.2.0", path = "../matrix"} +smurf = "0.2.0" \ No newline at end of file diff --git a/lin_sys/src/main.rs b/lin_sys/src/main.rs new file mode 100644 index 0000000..083b182 --- /dev/null +++ b/lin_sys/src/main.rs @@ -0,0 +1,6 @@ +use matrix; +use smurf; + +fn main() { + println!("Inp") +} diff --git a/matrix/Cargo.toml b/matrix/Cargo.toml index 087fea8..09dbcac 100644 --- a/matrix/Cargo.toml +++ b/matrix/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "matrix" -version = "0.1.2" +version = "0.2.0" edition = "2021" license = "MIT" diff --git a/matrix/src/lib.rs b/matrix/src/lib.rs index 8dc26af..e568477 100644 --- a/matrix/src/lib.rs +++ b/matrix/src/lib.rs @@ -1,13 +1,110 @@ -use std::ops::{Add, AddAssign, Mul}; +#![recursion_limit = "32768"] use rand::{thread_rng, Rng}; +use std::cmp::Ord; +use std::ops::{Add, AddAssign, Mul, Neg}; -pub(crate) type Matrix = Vec>; +#[derive(Debug)] +pub struct Matrix< + T: Mul + + Copy + + AddAssign + + From + + PartialEq + + Add + + PartialOrd + + Ord + + Copy + + Neg, +>(Vec>); -fn check_valid(a: &Matrix) -> bool { - let len = a[0].len(); +impl< + T: Mul + + Copy + + AddAssign + + From + + PartialEq + + Add + + PartialOrd + + Ord + + Copy + + Neg, + > Matrix +{ + fn len(&self) -> usize { + self.0.len() + } - for i in a { + fn push(&mut self, element: Vec) { + self.0.push(element) + } + + fn new() -> Matrix { + Matrix(Vec::new()) + } + + pub fn dot(&self, other: &Matrix) -> Option> { + if !(check_valid(self) && check_valid(other)) { + return None; + } + + if self.0[0].len() != other.0.len() { + return None; + } + + let m = self.0[0].len(); + let mut c: Matrix = Matrix::new(); + + for i in 0..self.len() { + c.push(vec![]); + for j in 0..other.0[0].len() { + let mut s: T = 0_u8.into(); + for r in 0..m { + s += self.0[i][r] * other.0[r][j]; + } + c.0[i].push(s as T); + } + } + + Some(c) + } +} + +impl< + T: Mul + + Copy + + AddAssign + + From + + PartialEq + + Add + + PartialOrd + + Ord + + Copy + + Neg, + > PartialEq for Matrix +{ + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } +} + +fn check_valid< + T: Mul + + Copy + + AddAssign + + From + + PartialEq + + Add + + PartialOrd + + Ord + + Copy + + Neg, +>( + a: &Matrix, +) -> bool { + let len = a.0[0].len(); + + for i in &a.0 { if i.len() != len { return false; } @@ -16,7 +113,21 @@ fn check_valid(a: &Matrix) -> bool { true } -pub fn sum + Copy>(a: &Matrix, b: &Matrix) -> Option> { +pub fn sum< + T: Mul + + Copy + + AddAssign + + From + + PartialEq + + Add + + PartialOrd + + Ord + + Copy + + Neg, +>( + a: &Matrix, + b: &Matrix, +) -> Option> { if !(check_valid(a) && check_valid(b)) { return None; } @@ -25,80 +136,114 @@ pub fn sum + Copy>(a: &Matrix, b: &Matrix) -> Option = Vec::new(); + let mut c: Matrix = Matrix::new(); for i in 0..a.len() { c.push(vec![]); - for j in 0..a[0].len() { - c[i].push(a[i][j] + b[i][j]); + for j in 0..a.0[0].len() { + c.0[i].push(a.0[i][j] + b.0[i][j]); } } Some(c) } -pub fn mul + Copy + AddAssign + From>( - a: &Matrix, - b: &Matrix, -) -> Option> { - if !(check_valid(a) && check_valid(b)) { - return None; - } - - if a[0].len() != b.len() { - return None; - } - - let m = a[0].len(); - let mut c: Matrix = Vec::new(); - - for i in 0..a.len() { - c.push(vec![]); - for j in 0..b[0].len() { - let mut s: T = 0_u8.into(); - for r in 0..m { - s += a[i][r] * b[r][j]; - } - c[i].push(s as T); +fn get_minor< + T: Mul + + Copy + + AddAssign + + From + + PartialEq + + Add + + PartialOrd + + Ord + + Copy + + Neg, +>( + base: &&Matrix, + mi: &usize, + mj: &usize, +) -> Matrix { + let mut minor: Matrix = Matrix::new(); + let mut offset: usize = 0; + for i in 0..base.len() { + if i == *mi { + offset += 1; + continue; } - } - - Some(c) -} - -pub fn det + Copy + Add>(a: &Matrix) -> Option> { - if ! check_valid(a) { - return None; - } - if a[0].len() != a.len() { - return None; - } - let j = 0; - for i in 1..n { - let _pre_minor: Matrix = vec![&a[0..i], &a[i+1..]]; - let mut pre_minor: Metrix = vec![vec![]]; - for m in _pre_minor { - if m == j { + minor.push(vec![]); + for j in 0..base.0[0].len() { + if j == *mj { continue; } - pre_minor[m].push + minor.0[i - offset].push(base.0[i][j]) } - let minor = det(&pre_minor); - } + minor +} + +pub fn det< + T: Mul + + Copy + + AddAssign + + From + + PartialEq + + Add + + PartialOrd + + Ord + + Copy + + Neg, +>( + a: &Matrix, +) -> Option { + if !check_valid(a) { + return None; + } + if a.0[0].len() != a.0.len() { + return None; + } + if a.0[0].len() == 1 { + return Some(a.0[0][0]); + } + let j = 1; + let mut determinant: T = 0.into(); + for i in 0..a.len() { + let minor: T = det(&get_minor(&a, &i, &j)).unwrap(); + determinant += if (i + 1) % 2 == 1 { + -Into::::into(1i8) + } else { + Into::::into(1i8) + } * a.0[i][1] + * minor; + } + Some(determinant) } #[allow(dead_code)] -fn gen_matrix>(i: usize, j: usize) -> Option> { +fn gen_matrix< + T: Mul + + Copy + + AddAssign + + From + + PartialEq + + Add + + PartialOrd + + Ord + + Copy + + Neg, +>( + i: usize, + j: usize, +) -> Option> { if !(i > 0 && j > 0) { return None; } let mut rng = thread_rng(); - let mut m: Matrix = Vec::new(); + let mut m: Matrix = Matrix::new(); for a in 0..i { m.push(vec![]); for _ in 0..j { - m[a].push(T::from(rng.gen_range(0..100))); + m.0[a].push(T::from(rng.gen_range(0..100))); } } Some(m) @@ -114,14 +259,17 @@ mod test { fn basic_sum() { let a = vec![vec![1., 2.], vec![3., 4.]]; let b = vec![vec![5., 6.], vec![7., 8.]]; - assert_eq!(sum(&a, &b).unwrap(), vec![vec![6., 8.], vec![10., 12.]]) + assert_eq!(sum(&Matrix(a), &Matrix(b)).unwrap(), Matrix(vec![vec![6., 8.], vec![10., 12.]])) } #[test] fn basic_mul() { let a = vec![vec![3., -1., 2.], vec![4., 2., 0.], vec![-5., 6., 1.]]; let b = vec![vec![8., 1.], vec![7., 2.], vec![2., -3.]]; - assert_eq!(mul(&a, &b).unwrap(), vec![vec![21., -5.], vec![46., 8.], vec![4., 4.]]) + assert_eq!( + mul(&Matrix(a), &Matrix(b)).unwrap(), + Matrix(vec![vec![21., -5.], vec![46., 8.], vec![4., 4.]]) + ) } #[test] @@ -134,13 +282,13 @@ mod test { } #[test] - #[ignore] + #[should_panic] fn mv_mul() { let a: Matrix = gen_matrix(10, 1).unwrap(); let b: Matrix = gen_matrix(1, 10).unwrap(); let ab = mul(&a, &b); let ba = mul(&b, &a); - if ab != None && ba != None { + if ab.is_some() && ba.is_some() { assert_eq!(ab.unwrap(), ba.unwrap()) } else { assert!(false) @@ -171,4 +319,34 @@ mod test { let c: Matrix = gen_matrix(s3, s4).unwrap(); assert_eq!(mul(&mul(&a, &b).unwrap(), &c).unwrap(), mul(&a, &mul(&b, &c).unwrap()).unwrap()) } + + #[test] + fn basic_det_1() { + let matrix: Matrix = Matrix(vec![vec![1, -2, -2], vec![5, 1, 3], vec![8, 0, 4]]); + assert_eq!(det(&matrix).unwrap(), 12i32) + } + #[test] + fn basic_det_2() { + let matrix: Matrix = + Matrix(vec![vec![1, 0, 0, 0], vec![0, 3, 0, 0], vec![0, 0, 1, 0], vec![0, 0, 0, 1]]); + assert_eq!(det(&matrix).unwrap(), 3i32) + } + #[test] + fn basic_det_3() { + let matrix: Matrix = + Matrix(vec![vec![0, 0, 0, 1], vec![0, 1, 0, 0], vec![0, 0, 1, 0], vec![1, 0, 0, 0]]); + assert_eq!(det(&matrix).unwrap(), -1i32) + } + #[test] + fn basic_det_4() { + let matrix: Matrix = + Matrix(vec![vec![1, 0, 0, 7], vec![0, 1, 0, 0], vec![0, 0, 1, 0], vec![0, 0, 0, 1]]); + assert_eq!(det(&matrix).unwrap(), 1i32) + } + #[test] + fn basic_det_5() { + let matrix: Matrix = + Matrix(vec![vec![3, 0, 2, -1], vec![1, 2, 0, -2], vec![4, 0, 6, -3], vec![5, 0, 2, 0]]); + assert_eq!(det(&matrix).unwrap(), 20i32) + } } diff --git a/matrix_graphics/Cargo.toml b/matrix_graphics/Cargo.toml index b6a3e47..3578ee3 100644 --- a/matrix_graphics/Cargo.toml +++ b/matrix_graphics/Cargo.toml @@ -11,7 +11,7 @@ default = ["optimize"] [dependencies] env_logger = "0.10.0" log = "0.4.17" -matrix = { version = "0.1.2", path = "../matrix" } +matrix = { version = "0.2.0", path = "../matrix" } pixels = "0.11.0" winit = "0.28.2" winit_input_helper = "0.14.0"