Identity and Determinant traits

master
Andrew Cassidy 2 years ago
parent 2829c52487
commit 53b1f5fdfa

@ -7,4 +7,5 @@ edition = "2021"
[dependencies]
generic_parameterize = "0.1.0"
itertools = "0.10.5"
num-traits = "0.2.15"

@ -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<T, const N: usize> = Matrix<T, N, 1>;
pub trait MatrixDepth {
const DEPTH: usize = 1;
}
pub trait Dot<R> {
type Output;
#[must_use]
@ -53,6 +57,17 @@ pub trait MMul<R> {
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<T: Copy, const M: usize, const N: usize> Matrix<T, M, N> {
/// Generate a new matrix from a 2D Array
@ -360,6 +375,7 @@ where
}
}
//Matrix Multiplication
impl<T: Copy, R: Copy, const M: usize, const N: usize, const P: usize> MMul<Matrix<R, N, P>>
for Matrix<T, M, N>
where
@ -381,6 +397,44 @@ where
}
}
// Identity
impl<T: Copy + Zero + One, const M: usize> Identity for Matrix<T, M, M> {
fn identity() -> Self {
let mut result = Self::zero();
for i in 0..M {
result[(i, i)] = T::one();
}
return result;
}
}
// Determinant
impl<T: Copy, const M: usize> Determinant for Matrix<T, M, M>
where
for<'a> T: Product<T> + Sum<T> + 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::<T>() * sign
};
// Now sum up all steps
zip(column_permutations, signs).map(summand).sum()
}
}
// Index
impl<I, T, const M: usize, const N: usize> Index<I> for Matrix<T, M, N>
where

@ -1,22 +0,0 @@
use num_traits::Pow;
pub trait Dot<RHS> {
type Output;
fn dot(&self, other: &RHS) -> <Self as Dot<RHS>>::Output;
}
pub trait Cross<RHS> {
type Output;
fn cross(&self, other: &RHS) -> <Self as Cross<RHS>>::Output;
}
pub trait Mult<RHS> {
type Output;
fn mult(&self, other: &RHS) -> <Self as Mult<RHS>>::Output;
}
pub trait Magnitude<T: Pow<f32>> {
fn sqrmag(&self) -> T;
fn mag(&self) -> <T as Pow<f32>>::Output;
fn norm(&self) -> Self;
}
Loading…
Cancel
Save