use crate::{scalar, FloatOps, Matrix};
use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Rem, RemAssign, Sub, SubAssign};
use num::{traits::NumAssign, One, Zero};
impl<T: Copy + NumAssign, const R: usize, const C: usize> Zero for Matrix<T, R, C> {
#[inline]
fn zero() -> Self {
Self::default()
}
fn is_zero(&self) -> bool {
let zero_ele = T::zero();
for c in 0..C {
for r in 0..R {
if self.0[c][r] != zero_ele {
return false;
}
}
}
true
}
}
impl<T: Copy + NumAssign, const R: usize, const C: usize> Matrix<T, R, C> {
pub fn mul_assign<const N: usize>(&mut self, lhs: Matrix<T, R, N>, rhs: Matrix<T, N, C>) {
for c in 0..C {
for r in 0..R {
let mut sum = T::zero();
for n in 0..N {
sum += lhs[(r, n)] * rhs[(n, c)];
}
self[(r, c)] = sum;
}
}
}
}
impl<T: Copy + NumAssign, const R: usize, const C: usize> AddAssign for Matrix<T, R, C> {
fn add_assign(&mut self, rhs: Matrix<T, R, C>) {
for c in 0..C {
for r in 0..R {
self.0[c][r] += rhs.0[c][r];
}
}
}
}
impl<T: Copy + NumAssign, const R: usize, const C: usize> SubAssign for Matrix<T, R, C> {
fn sub_assign(&mut self, rhs: Matrix<T, R, C>) {
for c in 0..C {
for r in 0..R {
self.0[c][r] -= rhs.0[c][r];
}
}
}
}
impl<T: Copy + NumAssign, const R: usize, const C: usize> Add for Matrix<T, R, C> {
type Output = Matrix<T, R, C>;
#[inline]
fn add(self, rhs: Matrix<T, R, C>) -> Self::Output {
let mut result = self;
result += rhs;
result
}
}
impl<T: Copy + NumAssign, const R: usize, const C: usize> Sub for Matrix<T, R, C> {
type Output = Matrix<T, R, C>;
#[inline]
fn sub(self, rhs: Matrix<T, R, C>) -> Self::Output {
let mut result = self;
result -= rhs;
result
}
}
impl<T: Copy + NumAssign, const R: usize, const N: usize, const C: usize> Mul<Matrix<T, N, C>>
for Matrix<T, R, N>
{
type Output = Matrix<T, R, C>;
#[inline]
fn mul(self, rhs: Matrix<T, N, C>) -> Self::Output {
let mut result = Self::Output::default();
result.mul_assign(self, rhs);
result
}
}
impl<T: Copy + NumAssign, const R: usize, const C: usize> MulAssign<T> for Matrix<T, R, C> {
fn mul_assign(&mut self, rhs: T) {
for c in 0..C {
for r in 0..R {
self.0[c][r] *= rhs;
}
}
}
}
impl<T: Copy + NumAssign, const R: usize, const C: usize> DivAssign<T> for Matrix<T, R, C> {
fn div_assign(&mut self, rhs: T) {
for c in 0..C {
for r in 0..R {
self.0[c][r] /= rhs;
}
}
}
}
impl<T: Copy + NumAssign, const R: usize, const C: usize> RemAssign<T> for Matrix<T, R, C> {
fn rem_assign(&mut self, rhs: T) {
for c in 0..C {
for r in 0..R {
self.0[c][r] %= rhs;
}
}
}
}
impl<T: Copy + NumAssign, const R: usize, const C: usize> Mul<T> for Matrix<T, R, C> {
type Output = Matrix<T, R, C>;
#[inline]
fn mul(self, rhs: T) -> Self::Output {
let mut result = self;
result *= rhs;
result
}
}
impl<T: Copy + NumAssign, const R: usize, const C: usize> Div<T> for Matrix<T, R, C> {
type Output = Matrix<T, R, C>;
#[inline]
fn div(self, rhs: T) -> Self::Output {
let mut result = self;
result /= rhs;
result
}
}
impl<T: Copy + NumAssign, const R: usize, const C: usize> Rem<T> for Matrix<T, R, C> {
type Output = Matrix<T, R, C>;
#[inline]
fn rem(self, rhs: T) -> Self::Output {
let mut result = self;
result %= rhs;
result
}
}
impl<T: Copy + NumAssign, const N: usize> One for Matrix<T, N, N> {
#[inline]
fn one() -> Self {
Self::identity()
}
}
impl<T: Copy + NumAssign, const N: usize> MulAssign for Matrix<T, N, N> {
#[inline]
fn mul_assign(&mut self, rhs: Matrix<T, N, N>) {
self.mul_assign(self.clone(), rhs);
}
}
impl<T: Copy + NumAssign, const N: usize> Matrix<T, N, N> {
pub fn transpose(&mut self) {
for c in 0..N {
for r in (c + 1)..N {
let mrc = self.0[c][r];
self.0[c][r] = self.0[r][c];
self.0[r][c] = mrc;
}
}
}
#[inline]
pub fn transposed(&self) -> Self {
let mut m = *self;
m.transpose();
m
}
}
impl<T: Copy + NumAssign, const N: usize> Matrix<T, N, 1> {
pub fn dot(&self, rhs: Self) -> T {
let mut result = T::zero();
for i in 0..N {
result += self.0[0][i] * rhs.0[0][i];
}
result
}
#[inline]
pub fn sqr_len(&self) -> T {
self.dot(*self)
}
pub fn lerp(&self, rhs: Self, t: T) -> Self {
let mut result = Self::default();
for i in 0..N {
result.0[0][i] = scalar::lerp(self.0[0][i], rhs.0[0][i], t);
}
result
}
}
impl<T: Copy + FloatOps + NumAssign, const N: usize> Matrix<T, N, 1> {
#[inline]
pub fn len(&self) -> T {
self.dot(*self).sqrt()
}
pub fn normalize(&mut self) -> bool {
let len = self.len();
if len != T::zero() {
*self /= len;
true
} else {
false
}
}
#[inline]
pub fn normalized(&self) -> Option<Self> {
let mut v = *self;
if v.normalize() {
Some(v)
} else {
None
}
}
}