From 49b174460415674204ed387bce5ae1f292071e08 Mon Sep 17 00:00:00 2001 From: Jon Janzen Date: Fri, 2 Apr 2021 16:33:31 -0600 Subject: [PATCH] went back to vec submatrixes and determinant can be used in the same method now --- matrix/src/lib.rs | 143 ++++++++++++++++++---------------------------- 1 file changed, 57 insertions(+), 86 deletions(-) diff --git a/matrix/src/lib.rs b/matrix/src/lib.rs index 7e28e5c..7e8bd48 100644 --- a/matrix/src/lib.rs +++ b/matrix/src/lib.rs @@ -1,6 +1,3 @@ -#![feature(const_generics)] -#![feature(const_evaluatable_checked)] -#![allow(incomplete_features)] #[macro_use] extern crate approx; @@ -9,28 +6,40 @@ use structs::Tuple; use std::ops::Index; #[derive(Debug)] -pub struct Matrix { - matrix: [[f32; W]; H], +pub struct Matrix { + matrix: Vec>, } -impl Matrix { +impl Matrix { - pub fn default() -> Self { + pub fn default(width: usize, height: usize) -> Self { Matrix { - matrix: [[0f32; W]; H], + matrix: vec![vec![0.0f32; width]; height], } } - pub fn from_array(matrix: [[f32; W]; H]) -> Matrix { + pub fn from_array(array: [[f32; W]; H]) -> Matrix { + let mut matrix: Vec> = Vec::with_capacity(H); + for r in array.iter() { + let mut row: Vec = Vec::with_capacity(W); + for v in r.iter() { + row.push(*v); + } + matrix.push(row); + } Matrix { matrix, } } - pub fn identity() -> Matrix { - // I can't figure out how to assign a 2d array to matrix inside the generic - // so I instead create the new and then assign 1.0 to the necessary values - let mut m = Self::default(); + pub fn from_vec(matrix: Vec>) -> Matrix { + Matrix { + matrix, + } + } + + pub fn identity(size: usize) -> Matrix { + let mut m = Self::default(size, size); for i in 0..m.matrix.len() { m.matrix[i][i] = 1.0; } @@ -47,63 +56,25 @@ impl Matrix { } } - pub fn determinant(&self) -> f32 where - [(); H - 1]: , - [(); W - 1]: , - { - if W == 2 { + pub fn determinant(&self) -> f32 { + if self.matrix[0].len() == 2 { self.matrix[0][0] * self.matrix[1][1] - self.matrix[0][1] * self.matrix[1][0] } else { let mut sum = 0.0; - for (col, val) in self.matrix[0].iter().enumerate().take(W) { + for (col, val) in self.matrix[0].iter().enumerate().take(self.matrix[0].len()) { sum += val * self.cofactor(0, col); } sum } } - fn zero_skip(&self, val: usize) -> usize { - if val == 0 { - 1 - } else { - 0 - } - } - - fn bound_skip(&self, val: usize, bound: usize) -> usize { - if val < bound { - bound - } else { - bound - 1 - } - } - - pub fn minor(&self, row: usize, col: usize) -> f32 where - [(); H - 1]: , - [(); W - 1]: , - [(); H - 1]: , - [(); W - 1]: , - { + pub fn minor(&self, row: usize, col: usize) -> f32 { let m = self.sub_matrix(row, col); let det = m.determinant(); det - // let t = self.zero_skip(row); - // let b = self.bound_skip(row, H - 1); - // let l = self.zero_skip(col); - // let r = self.bound_skip(col, W - 1); - - // let tl = self.matrix[t][l]; - // let br = self.matrix[b][r]; - // let tr = self.matrix[t][r]; - // let bl = self.matrix[b][l]; - - // tl * br - tr * bl } - pub fn cofactor(&self, row: usize, col: usize) -> f32 where - [(); H - 1]: , - [(); W - 1]: , - { + pub fn cofactor(&self, row: usize, col: usize) -> f32 { let minor = self.minor(row, col); if (row + col) & 0x1 == 0 { minor @@ -112,33 +83,30 @@ impl Matrix { } } - pub fn sub_matrix(&self, skip_row: usize, skip_col: usize) -> Matrix<{H - 1}, {W - 1}> + pub fn sub_matrix(&self, skip_row: usize, skip_col: usize) -> Matrix { - let mut idx_row: usize = 0; - - let mut arr = [[0f32; W - 1]; H - 1]; - for (i, row) in self.matrix.iter().enumerate().take(H) { + let mut m = Vec::>::with_capacity(self.matrix.len() - 1); + for (i, row) in self.matrix.iter().enumerate().take(self.matrix.len()) { if i == skip_row { continue; } - let mut idx_col: usize = 0; - for (j, col) in row.iter().enumerate().take(W) { + let mut r = Vec::::with_capacity(row.len() - 1); + for (j, col) in row.iter().enumerate().take(row.len()) { if j == skip_col { continue; } - arr[idx_row][idx_col] = *col; - idx_col += 1; + r.push(*col); } - idx_row += 1; + m.push(r); } - Matrix::from_array(arr) + Matrix::from_vec(m) } } -impl Index for Matrix { - type Output = [f32; W]; +impl Index for Matrix { + type Output = Vec; fn index(&self, index: usize) -> &Self::Output { &self.matrix[index] } } -impl PartialEq for Matrix { +impl PartialEq for Matrix { fn eq(&self, _rhs: &Self) -> bool { if self.matrix.len() != _rhs.matrix.len() { return false; @@ -158,10 +126,10 @@ impl PartialEq for Matrix { } } -impl Matrix { - fn calc_val_for_mul(&self, row: usize, rhs: &Matrix, col: usize) -> f32 { +impl Matrix { + fn calc_val_for_mul(&self, row: usize, rhs: &Matrix, col: usize) -> f32 { let mut sum = 0.0; - for i in 0..W { + for i in 0..self.matrix.len() { sum += self.matrix[row][i] * rhs.matrix[i][col]; } sum @@ -175,22 +143,25 @@ impl Matrix { } } -impl std::ops::Mul> for Matrix { - type Output = Matrix; +impl std::ops::Mul for Matrix { + type Output = Matrix; - fn mul(self, _rhs: Matrix) -> Matrix { - let mut result = [[0f32; W]; H]; - for (row, val) in result.iter_mut().enumerate().take(H) { - for (col, v) in val.iter_mut().enumerate().take(W) { - *v = self.calc_val_for_mul(row, &_rhs, col); + fn mul(self, _rhs: Matrix) -> Matrix { + let mut result: Vec> = Vec::with_capacity(self.matrix.len()); + for row in 0..self.matrix.len() { + let width = self.matrix[row].len(); + let mut new_col = Vec::with_capacity(width); + for col in 0..width { + new_col.push( self.calc_val_for_mul(row, &_rhs, col)); } + result.push(new_col); } - Matrix::from_array(result) + Matrix::from_vec(result) } } -impl std::ops::Mul for Matrix { +impl std::ops::Mul for Matrix { type Output = Tuple; fn mul(self, _rhs: Tuple) -> Tuple { @@ -373,7 +344,7 @@ mod tests { [4.0, 8.0, 16.0, 32.0,] ]); - assert_eq!(matrix * Matrix::identity(), expected); + assert_eq!(matrix * Matrix::identity(4), expected); } #[test] @@ -381,7 +352,7 @@ mod tests { let t = Tuple::new(1.0, 2.0, 3.0, 4.0); let expected = Tuple::new(1.0, 2.0, 3.0, 4.0); - assert_eq!(Matrix::<4, 4>::identity() * t, expected); + assert_eq!(Matrix::identity(4) * t, expected); } #[test] @@ -405,9 +376,9 @@ mod tests { #[test] fn transpose_identity() { - let mut m = Matrix::identity(); + let mut m = Matrix::identity(4); m.transpose(); - assert_eq!(m, Matrix::<4, 4>::identity()); + assert_eq!(m, Matrix::identity(4)); } #[test]