use std::ops::Add;
use std::ops::{Mul, AddAssign};
use crate::vector::Vector;
#[allow(dead_code)]
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Matrix<T>
{
rows : usize,
cols : usize,
matrix : Vec<Vec<T>>
}
#[allow(dead_code)]
impl<T> Matrix<T>
where
T: Copy
{
pub fn into_vector(self) -> Vector<T> {
if self.rows == 1 {
let mut params = vec![];
for param in &self.matrix[0] {
params.push(*param)
}
return Vector::from(params)
}
else if self.cols == 1 {
let mut params: Vec<T> = vec![];
for row in self.matrix {
params.push(row[0])
}
return Vector::from(params);
}
else {
panic!("Cannot convert matrix because neither rows nor columns are 1")
}
}
}
impl<T> From<Vec<Vec<T>>> for Matrix<T> {
fn from(params: Vec<Vec<T>>) -> Self {
let rows = params.len();
let cols = params[0].len();
for row in 1..rows {
if params[row].len() != cols {
panic!("Input 2D Vec does not have same length for all rows")
}
}
Matrix {
rows : params.len(),
cols : params[0].len(),
matrix : params
}
}
}
impl<T> Mul<&Vector<T>> for &Matrix<T>
where
T: Copy + AddAssign + Mul<Output = T> + Default
{
type Output = Vector<T>;
fn mul(self, rhs: &Vector<T>) -> Self::Output {
if rhs.len() != self.cols {
panic!("The matrix column count must be equal to the vector parameter count.")
};
let mut params = vec![];
let vector_ptr = rhs.list().as_ptr();
for row in &self.matrix {
let mut param = T::default();
let row_ptr = row.as_ptr();
for i in 0..self.cols {
unsafe {
param += *row_ptr.add(i) * *vector_ptr.add(i)
}
}
params.push(param)
}
Vector::from(params)
}
}
impl<T> Mul for &Matrix<T>
where
T: Copy + AddAssign + Mul<Output = T> + Default
{
type Output = Matrix<T>;
fn mul(self, rhs: Self) -> Self::Output {
if self.cols != rhs.rows {
panic!("The left matrix row count is not equal to the right matrix column count.")
}
let mut params: Vec<Vec<T>> = vec![vec![]; self.rows];
for out_row_index in 0..self.rows {
for out_col_index in 0..rhs.cols {
let mut param = T::default();
for index in 0..self.cols {
let lhs_row_ptr = self.matrix[out_row_index].as_ptr();
let lhs_value: T;
unsafe {
lhs_value = *lhs_row_ptr.add(index)
}
let rhs_row_ptr = rhs.matrix[index].as_ptr();
let rhs_value: T;
unsafe {
rhs_value = *rhs_row_ptr.add(out_col_index)
}
param += lhs_value * rhs_value
}
params[out_row_index].push(param)
}
}
Matrix::from(params)
}
}
impl<T> Add for &Matrix<T>
where
T: Add<Output = T> + Copy
{
type Output = Matrix<T>;
fn add(self, rhs: Self) -> Self::Output {
if self.rows != rhs.rows || self.cols != rhs.cols {
panic!("Differently sized matrices cannot be added together.")
}
let mut params = vec![vec![]; self.rows];
for row_idx in 0..self.rows {
for col_idx in 0..self.cols {
params[row_idx].push(self.matrix[row_idx][col_idx] + rhs.matrix[row_idx][col_idx])
}
}
Matrix::from(params)
}
}