use crate::mat::{Matrix, Vector};
use num_traits::identities::{One, Zero};
use std::ops::{Add, AddAssign, Div, Index, IndexMut, Mul, Neg, Sub, SubAssign};
impl<T> Add for &Matrix<T>
where
T: Add<Output = T> + Zero + One + Clone + Copy,
{
type Output = Matrix<T>;
fn add(self, rhs: &Matrix<T>) -> Self::Output {
if self.dims != rhs.dims {
panic!("Dimensions of matrices do not match.");
} else {
let mut res = Matrix::new(self.dims.get_rows(), self.dims.get_cols(), T::zero());
for i in 0..self.matrix.len() {
res.matrix[i] = self.matrix[i] + rhs.matrix[i];
}
res
}
}
}
impl<T> AddAssign<&Matrix<T>> for Matrix<T>
where
T: Add<Output = T> + Zero + One + Clone + Copy,
{
fn add_assign(&mut self, mat: &Matrix<T>) {
let m = &self.clone() + mat;
self.matrix = m.matrix;
}
}
impl<T> Sub for &Matrix<T>
where
T: Sub<Output = T> + One + Zero + Clone + Copy,
{
type Output = Matrix<T>;
fn sub(self, rhs: &Matrix<T>) -> Self::Output {
let ref a = rhs * (T::zero() - T::one());
self + a
}
}
impl<T> SubAssign<&Matrix<T>> for Matrix<T>
where
T: Sub<Output = T> + Zero + One + Copy + Clone,
{
fn sub_assign(&mut self, mat: &Matrix<T>) {
let m = &self.clone() - mat;
self.matrix = m.matrix;
}
}
impl<T> Neg for &Matrix<T>
where
T: Neg + One + Zero + Copy,
Vec<T>: std::iter::FromIterator<<T as std::ops::Neg>::Output>,
{
type Output = Matrix<T>;
fn neg(self) -> Self::Output {
Matrix::from_vec(
self.dims.get_rows(),
self.dims.get_cols(),
self.matrix.iter().map(|&x| -x).collect(),
)
}
}
impl<T> Mul for &Matrix<T>
where
T: Zero + One + Clone + Copy,
{
type Output = Matrix<T>;
fn mul(self, rhs: &Matrix<T>) -> Self::Output {
let a = self.clone();
let b = rhs.clone();
if a.dims.get_cols() != b.dims.get_rows() {
panic!("Dimensions of matrices should be 'm x n' and 'n x k'");
} else {
let mut res: Matrix<T> = Matrix::new(a.dims.get_rows(), b.dims.get_cols(), T::zero());
for i in 0..a.dims.get_rows() {
for j in 0..b.dims.get_cols() {
let mut sum = T::zero();
for k in 0..a.dims.get_cols() {
sum = sum
+ a.matrix[i * a.dims.get_cols() + k]
* b.matrix[k * b.dims.get_cols() + j];
}
res.matrix[i * res.dims.get_cols() + j] = sum;
}
}
res
}
}
}
impl<T> Mul<&Vector<T>> for &Matrix<T>
where
T: One + Zero + Copy + Clone,
{
type Output = Vector<T>;
fn mul(self, vec: &Vector<T>) -> Self::Output {
let v = vec.clone();
let mat_v: Matrix<T> = v.into();
let res = self * &mat_v;
res.into()
}
}
impl<T> Mul<T> for &Matrix<T>
where
T: Mul<Output = T> + Copy,
{
type Output = Matrix<T>;
fn mul(self, scalar: T) -> Self::Output {
let mut res_mat = self.clone();
for i in 0..res_mat.matrix.len() {
res_mat.matrix[i] = res_mat.matrix[i] * scalar;
}
res_mat
}
}
impl<T> Div<T> for &Matrix<T>
where
T: Div<Output = T> + Zero + One + PartialEq + Copy,
{
type Output = Matrix<T>;
fn div(self, scalar: T) -> Self::Output {
if scalar == T::zero() {
panic!("Cannot divide by zero.");
}
self * (T::one() / scalar)
}
}
impl<T> Index<usize> for Matrix<T> {
type Output = [T];
fn index(&self, idx: usize) -> &Self::Output {
if idx >= self.dims.get_rows() {
panic!("Unreachable index: {}", idx);
}
&self.matrix[idx * self.dims.get_cols()..idx * self.dims.get_cols() + self.dims.get_cols()]
}
}
impl<T> IndexMut<usize> for Matrix<T> {
fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
if idx >= self.dims.get_rows() {
panic!("Unreachable index: {}", idx);
}
&mut self.matrix
[idx * self.dims.get_cols()..idx * self.dims.get_cols() + self.dims.get_cols()]
}
}