diff --git a/Cargo.toml b/Cargo.toml index 65df4db..7dfcc5c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,4 +7,5 @@ edition = "2021" [dependencies] generic_parameterize = "0.1.0" +itertools = "0.10.5" num-traits = "0.2.15" diff --git a/src/matrix.rs b/src/matrix.rs index b12013c..11aa394 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -1,10 +1,10 @@ use crate::impl_matrix_op; use crate::index::Index2D; +use itertools::Itertools; use num_traits::{Num, One, Zero}; use std::fmt::Debug; use std::iter::{zip, Flatten, Product, Sum}; -use std::ops::{AddAssign, Deref, DerefMut, Index, IndexMut, Mul, MulAssign, Neg, Sub}; - +use std::ops::{Add, AddAssign, Deref, DerefMut, Index, IndexMut, Mul, MulAssign, Neg, Sub}; /// A Scalar that a [Matrix] can be made up of. /// /// This trait has no associated functions and can be implemented on any type that is [Default] and @@ -34,6 +34,10 @@ where /// An alias for a [Matrix] with a single column pub type Vector = Matrix; +pub trait MatrixDepth { + const DEPTH: usize = 1; +} + pub trait Dot { type Output; #[must_use] @@ -53,6 +57,17 @@ pub trait MMul { fn mmul(&self, rhs: &R) -> Self::Output; } +pub trait Identity { + #[must_use] + fn identity() -> Self; +} + +pub trait Determinant { + type Output; + #[must_use] + fn determinant(&self) -> Self::Output; +} + // Simple access functions that only require T be copyable impl Matrix { /// Generate a new matrix from a 2D Array @@ -360,6 +375,7 @@ where } } +//Matrix Multiplication impl MMul> for Matrix where @@ -381,6 +397,44 @@ where } } +// Identity +impl Identity for Matrix { + fn identity() -> Self { + let mut result = Self::zero(); + for i in 0..M { + result[(i, i)] = T::one(); + } + return result; + } +} + +// Determinant +impl Determinant for Matrix +where + for<'a> T: Product + Sum + Mul<&'a i32, Output = T>, +{ + type Output = T; + + fn determinant(&self) -> Self::Output { + // Leibniz formula + + // alternating 1,-1,1,-1... + let signs = [1, -1].iter().cycle(); + // all permutations of 0..M + let column_permutations = (0..M).permutations(M); + + // Calculating the determinant is done by summing up M steps, + // each with a different permutation of columns and alternating sign + // Each step involves a product of the components being operated on + let summand = |(columns, sign)| -> T { + zip(0..M, columns).map(|(r, c)| self[(r, c)]).product::() * sign + }; + + // Now sum up all steps + zip(column_permutations, signs).map(summand).sum() + } +} + // Index impl Index for Matrix where diff --git a/src/matrix_traits.rs b/src/matrix_traits.rs deleted file mode 100644 index fb42659..0000000 --- a/src/matrix_traits.rs +++ /dev/null @@ -1,22 +0,0 @@ -use num_traits::Pow; - -pub trait Dot { - type Output; - fn dot(&self, other: &RHS) -> >::Output; -} - -pub trait Cross { - type Output; - fn cross(&self, other: &RHS) -> >::Output; -} - -pub trait Mult { - type Output; - fn mult(&self, other: &RHS) -> >::Output; -} - -pub trait Magnitude> { - fn sqrmag(&self) -> T; - fn mag(&self) -> >::Output; - fn norm(&self) -> Self; -}