went back to vec

submatrixes and determinant can be used in the same method now
This commit is contained in:
Jon Janzen
2021-04-02 16:33:31 -06:00
parent 75f882f860
commit 49b1744604

View File

@@ -1,6 +1,3 @@
#![feature(const_generics)]
#![feature(const_evaluatable_checked)]
#![allow(incomplete_features)]
#[macro_use] #[macro_use]
extern crate approx; extern crate approx;
@@ -9,28 +6,40 @@ use structs::Tuple;
use std::ops::Index; use std::ops::Index;
#[derive(Debug)] #[derive(Debug)]
pub struct Matrix<const H: usize, const W: usize> { pub struct Matrix {
matrix: [[f32; W]; H], matrix: Vec<Vec<f32>>,
} }
impl<const H: usize, const W: usize> Matrix<H, W> { impl Matrix {
pub fn default() -> Self { pub fn default(width: usize, height: usize) -> Self {
Matrix { Matrix {
matrix: [[0f32; W]; H], matrix: vec![vec![0.0f32; width]; height],
} }
} }
pub fn from_array(matrix: [[f32; W]; H]) -> Matrix<H, W> { pub fn from_array<const H: usize, const W: usize>(array: [[f32; W]; H]) -> Matrix {
let mut matrix: Vec<Vec<f32>> = Vec::with_capacity(H);
for r in array.iter() {
let mut row: Vec<f32> = Vec::with_capacity(W);
for v in r.iter() {
row.push(*v);
}
matrix.push(row);
}
Matrix { Matrix {
matrix, matrix,
} }
} }
pub fn identity() -> Matrix<H, W> { pub fn from_vec(matrix: Vec<Vec<f32>>) -> Matrix {
// I can't figure out how to assign a 2d array to matrix inside the generic Matrix {
// so I instead create the new and then assign 1.0 to the necessary values matrix,
let mut m = Self::default(); }
}
pub fn identity(size: usize) -> Matrix {
let mut m = Self::default(size, size);
for i in 0..m.matrix.len() { for i in 0..m.matrix.len() {
m.matrix[i][i] = 1.0; m.matrix[i][i] = 1.0;
} }
@@ -47,63 +56,25 @@ impl<const H: usize, const W: usize> Matrix<H, W> {
} }
} }
pub fn determinant(&self) -> f32 where pub fn determinant(&self) -> f32 {
[(); H - 1]: , if self.matrix[0].len() == 2 {
[(); W - 1]: ,
{
if W == 2 {
self.matrix[0][0] * self.matrix[1][1] - self.matrix[0][1] * self.matrix[1][0] self.matrix[0][0] * self.matrix[1][1] - self.matrix[0][1] * self.matrix[1][0]
} else { } else {
let mut sum = 0.0; 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 += val * self.cofactor(0, col);
} }
sum sum
} }
} }
fn zero_skip(&self, val: usize) -> usize { pub fn minor(&self, row: usize, col: usize) -> f32 {
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]: ,
{
let m = self.sub_matrix(row, col); let m = self.sub_matrix(row, col);
let det = m.determinant(); let det = m.determinant();
det 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 pub fn cofactor(&self, row: usize, col: usize) -> f32 {
[(); H - 1]: ,
[(); W - 1]: ,
{
let minor = self.minor(row, col); let minor = self.minor(row, col);
if (row + col) & 0x1 == 0 { if (row + col) & 0x1 == 0 {
minor minor
@@ -112,33 +83,30 @@ impl<const H: usize, const W: usize> Matrix<H, W> {
} }
} }
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 m = Vec::<Vec<f32>>::with_capacity(self.matrix.len() - 1);
for (i, row) in self.matrix.iter().enumerate().take(self.matrix.len()) {
let mut arr = [[0f32; W - 1]; H - 1];
for (i, row) in self.matrix.iter().enumerate().take(H) {
if i == skip_row { continue; } if i == skip_row { continue; }
let mut idx_col: usize = 0; let mut r = Vec::<f32>::with_capacity(row.len() - 1);
for (j, col) in row.iter().enumerate().take(W) { for (j, col) in row.iter().enumerate().take(row.len()) {
if j == skip_col { continue; } if j == skip_col { continue; }
arr[idx_row][idx_col] = *col; r.push(*col);
idx_col += 1;
} }
idx_row += 1; m.push(r);
} }
Matrix::from_array(arr) Matrix::from_vec(m)
} }
} }
impl<const H: usize, const W: usize> Index<usize> for Matrix<H, W> { impl Index<usize> for Matrix {
type Output = [f32; W]; type Output = Vec<f32>;
fn index(&self, index: usize) -> &Self::Output { fn index(&self, index: usize) -> &Self::Output {
&self.matrix[index] &self.matrix[index]
} }
} }
impl<const H: usize, const W: usize> PartialEq for Matrix<H, W> { impl PartialEq for Matrix {
fn eq(&self, _rhs: &Self) -> bool { fn eq(&self, _rhs: &Self) -> bool {
if self.matrix.len() != _rhs.matrix.len() { if self.matrix.len() != _rhs.matrix.len() {
return false; return false;
@@ -158,10 +126,10 @@ impl<const H: usize, const W: usize> PartialEq for Matrix<H, W> {
} }
} }
impl<const H: usize, const W: usize> Matrix<H, W> { impl Matrix {
fn calc_val_for_mul(&self, row: usize, rhs: &Matrix<H, W>, col: usize) -> f32 { fn calc_val_for_mul(&self, row: usize, rhs: &Matrix, col: usize) -> f32 {
let mut sum = 0.0; 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 += self.matrix[row][i] * rhs.matrix[i][col];
} }
sum sum
@@ -175,22 +143,25 @@ impl<const H: usize, const W: usize> Matrix<H, W> {
} }
} }
impl<const H: usize, const W: usize> std::ops::Mul<Matrix<H, W>> for Matrix<H, W> { impl std::ops::Mul<Matrix> for Matrix {
type Output = Matrix<H, W>; type Output = Matrix;
fn mul(self, _rhs: Matrix<H, W>) -> Matrix<H, W> { fn mul(self, _rhs: Matrix) -> Matrix {
let mut result = [[0f32; W]; H]; let mut result: Vec<Vec<f32>> = Vec::with_capacity(self.matrix.len());
for (row, val) in result.iter_mut().enumerate().take(H) { for row in 0..self.matrix.len() {
for (col, v) in val.iter_mut().enumerate().take(W) { let width = self.matrix[row].len();
*v = self.calc_val_for_mul(row, &_rhs, col); 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<const H: usize, const W: usize> std::ops::Mul<Tuple> for Matrix<H, W> { impl std::ops::Mul<Tuple> for Matrix {
type Output = Tuple; type Output = Tuple;
fn mul(self, _rhs: Tuple) -> Tuple { fn mul(self, _rhs: Tuple) -> Tuple {
@@ -373,7 +344,7 @@ mod tests {
[4.0, 8.0, 16.0, 32.0,] [4.0, 8.0, 16.0, 32.0,]
]); ]);
assert_eq!(matrix * Matrix::identity(), expected); assert_eq!(matrix * Matrix::identity(4), expected);
} }
#[test] #[test]
@@ -381,7 +352,7 @@ mod tests {
let t = Tuple::new(1.0, 2.0, 3.0, 4.0); let t = Tuple::new(1.0, 2.0, 3.0, 4.0);
let expected = 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] #[test]
@@ -405,9 +376,9 @@ mod tests {
#[test] #[test]
fn transpose_identity() { fn transpose_identity() {
let mut m = Matrix::identity(); let mut m = Matrix::identity(4);
m.transpose(); m.transpose();
assert_eq!(m, Matrix::<4, 4>::identity()); assert_eq!(m, Matrix::identity(4));
} }
#[test] #[test]