diff --git a/features/src/lib.rs b/features/src/lib.rs index 4ed24fc..d2f8153 100644 --- a/features/src/lib.rs +++ b/features/src/lib.rs @@ -8,6 +8,13 @@ pub mod canvas; pub mod matrix; pub mod transformations; +#[macro_export] +macro_rules! num_traits_cast { + ($tt:expr) => { + num_traits::cast($tt).unwrap() + }; +} + #[cfg(test)] mod tests { #[test] diff --git a/features/src/matrix.rs b/features/src/matrix.rs index 500e95b..9a09632 100644 --- a/features/src/matrix.rs +++ b/features/src/matrix.rs @@ -1,4 +1,7 @@ use crate::structs::Tuple; +use crate::num_traits_cast; + +use num_traits::NumCast; use std::ops::{Index, IndexMut}; @@ -15,12 +18,13 @@ impl Matrix { } } - pub fn from_array(array: [[f32; W]; H]) -> Matrix { + pub fn from_array(array: [[T; W]; H]) -> Matrix + where T: NumCast + Copy { 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); + row.push(num_traits_cast!(*v)); } matrix.push(row); } @@ -29,9 +33,19 @@ impl Matrix { } } - pub fn from_vec(matrix: Vec>) -> Matrix { + pub fn from_vec(matrix: Vec>) -> Matrix + where T: NumCast + Copy { + let mut matrix_f32 : Vec> = Vec::with_capacity(matrix.len()); + for r in matrix.iter() { + let mut row: Vec = Vec::with_capacity(r.len()); + for v in r.iter() { + row.push(num_traits_cast!(*v)); + } + matrix_f32.push(row); + } + Matrix { - matrix, + matrix: matrix_f32, } } @@ -261,8 +275,8 @@ mod tests { #[test] fn matrix_2x2() { let m = [ - [-3.0, 5.0,], - [1.0, 2.0,], + [-3, 5,], + [1, 2,], ]; let matrix = Matrix::from_array(m); assert_eq!(-3.0, matrix[0][0]); @@ -274,9 +288,9 @@ mod tests { #[test] fn matrix_3x3() { let m = [ - [-3.0, 5.0, 0.0], - [1.0, -2.0, -7.0], - [0.0, 1.0, 1.0], + [-3, 5, 0], + [1, -2, -7], + [0, 1, 1], ]; let matrix = Matrix::from_array(m); @@ -288,18 +302,18 @@ mod tests { #[test] fn matrix_equality_a() { let a = [ - [1.0, 2.0, 3.0, 4.0], - [5.0, 6.0, 7.0, 8.0], - [9.0, 8.0, 7.0, 6.0], - [5.0, 4.0, 3.0, 2.0], + [1, 2, 3, 4], + [5, 6, 7, 8], + [9, 8, 7, 6], + [5, 4, 3, 2], ]; let m_a = Matrix::from_array(a); let b = [ - [1.0, 2.0, 3.0, 4.0], - [5.0, 6.0, 7.0, 8.0], - [9.0, 8.0, 7.0, 6.0], - [5.0, 4.0, 3.0, 2.0], + [1, 2, 3, 4], + [5, 6, 7, 8], + [9, 8, 7, 6], + [5, 4, 3, 2], ]; let m_b = Matrix::from_array(b); @@ -310,18 +324,18 @@ mod tests { #[test] fn matrix_equality_b() { let a = [ - [1.0, 2.0, 3.0, 4.0], - [5.0, 6.0, 7.0, 8.0], - [9.0, 8.0, 7.0, 6.0], - [5.0, 4.0, 3.0, 2.0], + [1, 2, 3, 4], + [5, 6, 7, 8], + [9, 8, 7, 6], + [5, 4, 3, 2], ]; let m_a = Matrix::from_array(a); let b = [ - [2.0, 3.0, 4.0, 5.0], - [6.0, 7.0, 8.0, 9.0], - [8.0, 7.0, 6.0, 5.0], - [4.0, 3.0, 2.0, 1.0], + [2, 3, 4, 5], + [6, 7, 8, 9], + [8, 7, 6, 5], + [4, 3, 2, 1], ]; let m_b = Matrix::from_array(b); @@ -332,23 +346,23 @@ mod tests { #[test] fn multiply() { let matrix_a = Matrix::from_array([ - [1.0, 2.0, 3.0, 4.0,], - [5.0, 6.0, 7.0, 8.0,], - [9.0, 8.0, 7.0, 6.0,], - [5.0, 4.0, 3.0, 2.0,], + [1, 2, 3, 4,], + [5, 6, 7, 8,], + [9, 8, 7, 6,], + [5, 4, 3, 2,], ]); let matrix_b = Matrix::from_array([ - [-2.0, 1.0, 2.0, 3.0,], - [3.0, 2.0, 1.0, -1.0,], - [4.0, 3.0, 6.0, 5.0,], - [1.0, 2.0, 7.0, 8.0,], + [-2, 1, 2, 3,], + [3, 2, 1, -1,], + [4, 3, 6, 5,], + [1, 2, 7, 8,], ]); let expected = Matrix::from_array([ - [20.0, 22.0, 50.0, 48.0], - [44.0, 54.0, 114.0, 108.0], - [40.0, 58.0, 110.0, 102.0,], - [16.0, 26.0, 46.0, 42.0], + [20, 22, 50, 48], + [44, 54, 114, 108], + [40, 58, 110, 102,], + [16, 26, 46, 42], ]); assert_eq!(&matrix_a * &matrix_b, expected); @@ -357,14 +371,14 @@ mod tests { #[test] fn multiply_by_tuple() { let matrix = Matrix::from_array([ - [1.0, 2.0, 3.0, 4.0], - [2.0, 4.0, 4.0, 2.0], - [8.0, 6.0, 4.0, 1.0], - [0.0, 0.0, 0.0, 1.0], + [1, 2, 3, 4], + [2, 4, 4, 2], + [8, 6, 4, 1], + [0, 0, 0, 1], ]); - let tuple = Tuple::new(1.0, 2.0, 3.0, 1.0); - let expected = Tuple::new(18.0, 24.0, 33.0, 1.0); + let tuple = Tuple::new(1, 2, 3, 1); + let expected = Tuple::new(18, 24, 33, 1); assert_eq!(&matrix * &tuple, expected); } @@ -373,14 +387,14 @@ mod tests { #[test] fn multiply_by_tuple_reverse() { let matrix = Matrix::from_array([ - [1.0, 2.0, 3.0, 4.0], - [2.0, 4.0, 4.0, 2.0], - [8.0, 6.0, 4.0, 1.0], - [0.0, 0.0, 0.0, 1.0], + [1, 2, 3, 4], + [2, 4, 4, 2], + [8, 6, 4, 1], + [0, 0, 0, 1], ]); - let tuple = Tuple::new(1.0, 2.0, 3.0, 1.0); - let expected = Tuple::new(18.0, 24.0, 33.0, 1.0); + let tuple = Tuple::new(1, 2, 3, 1); + let expected = Tuple::new(18, 24, 33, 1); assert_eq!(&tuple * &matrix, expected); } @@ -388,17 +402,17 @@ mod tests { #[test] fn matrix_by_identity() { let matrix = Matrix::from_array([ - [0.0, 1.0, 2.0, 4.0,], - [1.0, 2.0, 4.0, 8.0,], - [2.0, 4.0, 8.0, 16.0], - [4.0, 8.0, 16.0, 32.0,] + [0, 1, 2, 4,], + [1, 2, 4, 8,], + [2, 4, 8, 16], + [4, 8, 16, 32,] ]); let expected = Matrix::from_array([ - [0.0, 1.0, 2.0, 4.0,], - [1.0, 2.0, 4.0, 8.0,], - [2.0, 4.0, 8.0, 16.0], - [4.0, 8.0, 16.0, 32.0,] + [0, 1, 2, 4,], + [1, 2, 4, 8,], + [2, 4, 8, 16], + [4, 8, 16, 32,] ]); assert_eq!(&matrix * &Matrix::identity(4), expected); @@ -406,8 +420,8 @@ mod tests { #[test] fn tuple_by_identity() { - 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 t = Tuple::new(1, 2, 3, 4); + let expected = Tuple::new(1, 2, 3, 4); assert_eq!(&Matrix::identity(4) * &t, expected); } @@ -415,17 +429,17 @@ mod tests { #[test] fn transposition() { let mut m = Matrix::from_array([ - [0.0, 9.0, 3.0, 0.0], - [9.0, 8.0, 0.0, 8.0], - [1.0, 8.0, 5.0, 3.0], - [0.0, 0.0, 5.0, 8.0], + [0, 9, 3, 0], + [9, 8, 0, 8], + [1, 8, 5, 3], + [0, 0, 5, 8], ]); let expected = Matrix::from_array([ - [0.0, 9.0, 1.0, 0.0], - [9.0, 8.0, 8.0, 0.0], - [3.0, 0.0, 5.0, 5.0], - [0.0, 8.0, 3.0, 8.0], + [0, 9, 1, 0], + [9, 8, 8, 0], + [3, 0, 5, 5], + [0, 8, 3, 8], ]); m.transpose(); assert_eq!(m, expected); @@ -441,8 +455,8 @@ mod tests { #[test] fn determinant_2x2() { let m = Matrix::from_array([ - [1.0, 5.0], - [-3.0, 2.0], + [1, 5], + [-3, 2], ]); assert_eq!(17.0, m.determinant()); @@ -451,14 +465,14 @@ mod tests { #[test] fn submatrix_3x3() { let start = Matrix::from_array([ - [1.0, 5.0, 0.0], - [-3.0, 2.0, 7.0], - [0.0, 6.0, -3.0], + [1, 5, 0], + [-3, 2, 7], + [0, 6, -3], ]); let expected = Matrix::from_array([ - [-3.0, 2.0], - [0.0, 6.0], + [-3, 2], + [0, 6], ]); assert_eq!(expected, start.sub_matrix(0, 2)); @@ -467,15 +481,15 @@ mod tests { #[test] fn submatrix_4x4() { let start = Matrix::from_array([ - [-6.0, 1.0, 1.0, 6.0], - [-8.0, 5.0, 8.0, 6.0], - [-1.0, 0.0, 8.0, 2.0], - [-7.0, 1.0, -1.0, 1.0], + [-6, 1, 1, 6], + [-8, 5, 8, 6], + [-1, 0, 8, 2], + [-7, 1, -1, 1], ]); let expected = Matrix::from_array([ - [-6.0, 1.0, 6.0], - [-8.0, 8.0, 6.0], - [-7.0, -1.0, 1.0], + [-6, 1, 6], + [-8, 8, 6], + [-7, -1, 1], ]); assert_eq!(expected, start.sub_matrix(2, 1)); @@ -484,9 +498,9 @@ mod tests { #[test] fn minor_3x3() { let m = Matrix::from_array([ - [3.0, 5.0, 0.0], - [2.0, -1.0, -7.0], - [6.0, -1.0, 5.0], + [3, 5, 0], + [2, -1, -7], + [6, -1, 5], ]); let s = m.sub_matrix(1, 0); @@ -498,9 +512,9 @@ mod tests { #[test] fn cofactor_3x3() { let m = Matrix::from_array([ - [3.0, 5.0, 0.0], - [2.0, -1.0, -7.0], - [6.0, -1.0, 5.0], + [3, 5, 0], + [2, -1, -7], + [6, -1, 5], ]); assert_eq!(-12.0, m.minor(0, 0)); assert_eq!(-12.0, m.cofactor(0, 0)); @@ -511,9 +525,9 @@ mod tests { #[test] fn determinant_3x3() { let m = Matrix::from_array([ - [1.0, 2.0, 6.0], - [-5.0, 8.0, -4.0], - [2.0, 6.0, 4.0], + [1, 2, 6], + [-5, 8, -4], + [2, 6, 4], ]); assert_eq!(56.0, m.cofactor(0, 0)); assert_eq!(12.0, m.cofactor(0, 1)); @@ -524,10 +538,10 @@ mod tests { #[test] fn determinant_4x4() { let m = Matrix::from_array([ - [-2.0, -8.0, 3.0, 5.0], - [-3.0, 1.0, 7.0, 3.0], - [1.0, 2.0, -9.0, 6.0], - [-6.0, 7.0, 7.0, -9.0], + [-2, -8, 3, 5], + [-3, 1, 7, 3], + [1, 2, -9, 6], + [-6, 7, 7, -9], ]); assert_eq!(690.0, m.cofactor(0, 0)); assert_eq!(447.0, m.cofactor(0, 1)); @@ -539,10 +553,10 @@ mod tests { #[test] fn can_invert_invertable() { let m = Matrix::from_array([ - [6.0, 4.0, 4.0, 4.0], - [5.0, 5.0, 7.0, 6.0], - [4.0, -9.0, 3.0, -7.0], - [9.0, 1.0, 7.0, -6.0], + [6, 4, 4, 4], + [5, 5, 7, 6], + [4, -9, 3, -7], + [9, 1, 7, -6], ]); assert_eq!(-2120.0, m.determinant()); @@ -552,10 +566,10 @@ mod tests { #[test] fn can_invert_not_invertable() { let m = Matrix::from_array([ - [-4.0, 2.0, -2.0, -3.0], - [9.0, 6.0, 2.0, 6.0], - [0.0, -5.0, 1.0, -5.0], - [0.0, 0.0, 0.0, 0.0], + [-4, 2, -2, -3], + [9, 6, 2, 6], + [0, -5, 1, -5], + [0, 0, 0, 0], ]); assert_eq!(0.0, m.determinant()); @@ -583,11 +597,11 @@ mod tests { #[test] fn inverse() { - let m = Matrix::from_array([ - [-5.0, 2.0, 6.0, -8.0], - [1.0, -5.0, 1.0, 8.0], - [7.0, 7.0, -6.0, -7.0], - [1.0, -3.0, 7.0, 4.0], + let m = Matrix::from_array::([ + [-5, 2, 6, -8], + [1, -5, 1, 8], + [7, 7, -6, -7], + [1, -3, 7, 4], ]); let b = m.inverse(); @@ -597,7 +611,7 @@ mod tests { assert_eq!(105.0, m.cofactor(3, 2)); assert_eq!(105.0/532.0, b[2][3]); - let expected = Matrix::from_array([ + let expected = Matrix::from_array::([ [0.21805, 0.45113, 0.24060, -0.04511], [-0.80827, -1.45677, -0.44361, 0.52068], [-0.07895, -0.22368, -0.05263, 0.19737], @@ -610,10 +624,10 @@ mod tests { #[test] fn inverse_2() { let m = Matrix::from_array([ - [8.0, -5.0, 9.0, 2.0], - [7.0, 5.0, 6.0, 1.0], - [-6.0, 0.0, 9.0, 6.0], - [-3.0, 0.0, -9.0, -4.0], + [8, -5, 9, 2], + [7, 5, 6, 1], + [-6, 0, 9, 6], + [-3, 0, -9, -4], ]).inverse(); let expected = Matrix::from_array([ @@ -629,10 +643,10 @@ mod tests { #[test] fn inverse_3() { let m = Matrix::from_array([ - [9.0, 3.0, 0.0, 9.0], - [-5.0, -2.0, -6.0, -3.0], - [-4.0, 9.0, 6.0, 4.0], - [-7.0, 6.0, 6.0, 2.0], + [9, 3, 0, 9], + [-5, -2, -6, -3], + [-4, 9, 6, 4], + [-7, 6, 6, 2], ]).inverse(); let expected = Matrix::from_array([ @@ -648,25 +662,25 @@ mod tests { #[test] fn multiply_by_inverse() { let a = Matrix::from_array([ - [3.0, -9.0, 7.0, 3.0], - [3.0, -8.0, 2.0, -9.0], - [-4.0, 4.0, 4.0, 1.0], - [-6.0, 5.0, -1.0, 1.0], + [3, -9, 7, 3], + [3, -8, 2, -9], + [-4, 4, 4, 1], + [-6, 5, -1, 1], ]); let b = Matrix::from_array([ - [8.0, 2.0, 2.0, 2.0], - [3.0, -1.0, 7.0, 0.0], - [7.0, 0.0, 5.0, 4.0], - [6.0, -2.0, 0.0, 5.0], + [8, 2, 2, 2], + [3, -1, 7, 0], + [7, 0, 5, 4], + [6, -2, 0, 5], ]); let c = &a * &b; let r = &c * &b.inverse(); let expected = Matrix::from_array([ - [3.0, -9.0, 7.0, 3.0], - [3.0, -8.0, 2.0, -9.0], - [-4.0, 4.0, 4.0, 1.0], - [-6.0, 5.0, -1.0, 1.0], + [3, -9, 7, 3], + [3, -8, 2, -9], + [-4, 4, 4, 1], + [-6, 5, -1, 1], ]); assert_matrix_eq(&r, &expected, 0.00001); } diff --git a/features/src/structs.rs b/features/src/structs.rs index 849d8ac..a98038d 100644 --- a/features/src/structs.rs +++ b/features/src/structs.rs @@ -1,8 +1,9 @@ +use crate::num_traits_cast; + use std::fmt; use std::ops; use num_traits::NumCast; -use num_traits::cast; #[derive(Debug, Copy, Clone)] pub struct Tuple { @@ -12,12 +13,6 @@ pub struct Tuple { w: f32, } -macro_rules! num_traits_cast { - ($tt:ident) => { - cast($tt).unwrap() - }; -} - impl Tuple { pub fn new(x: X, y: Y, z: Z, w: W) -> Tuple where X: NumCast,