use crate::structure::matrix::{matrix, Matrix, Shape};
use crate::traits::fp::FPVector;
use crate::traits::matrix::MatrixTrait;
use crate::util::non_macro::zeros_shape;
use std::ops::{Add, Div, Mul, Sub};
pub trait VecOps: Sized + FPVector
where
Self::Scalar: Copy
+ Clone
+ Add<Self::Scalar, Output = Self::Scalar>
+ Sub<Self::Scalar, Output = Self::Scalar>
+ Mul<Self::Scalar, Output = Self::Scalar>
+ Div<Self::Scalar, Output = Self::Scalar>,
{
fn add_v(&self, v: &Self) -> Self {
self.zip_with(|x, y| x + y, v)
}
fn sub_v(&self, v: &Self) -> Self {
self.zip_with(|x, y| x - y, v)
}
fn mul_v(&self, v: &Self) -> Self {
self.zip_with(|x, y| x * y, v)
}
fn div_v(&self, v: &Self) -> Self {
self.zip_with(|x, y| x / y, v)
}
fn add_s(&self, s: Self::Scalar) -> Self {
self.fmap(|x| x + s)
}
fn sub_s(&self, s: Self::Scalar) -> Self {
self.fmap(|x| x - s)
}
fn mul_s(&self, s: Self::Scalar) -> Self {
self.fmap(|x| x * s)
}
fn div_s(&self, s: Self::Scalar) -> Self {
self.fmap(|x| x / s)
}
}
pub trait Scalable {
type Vec;
fn reshape(&self, size: (usize, usize), shape: Shape) -> Matrix;
fn add_col(&self, v: &Self::Vec) -> Matrix;
fn add_row(&self, v: &Self::Vec) -> Matrix;
}
pub trait ScalableMut {
type Vec;
fn reshape_mut(&mut self, size: (usize, usize), shape: Shape);
fn add_col_mut(&mut self, v: &Self::Vec);
fn add_row_mut(&mut self, v: &Self::Vec);
}
pub trait ConvToMat {
fn to_col(&self) -> Matrix;
fn to_row(&self) -> Matrix;
}
impl VecOps for Vec<f64> {}
impl Scalable for Vec<f64> {
type Vec = Self;
fn reshape(&self, (r, c): (usize, usize), shape: Shape) -> Matrix {
assert_eq!(self.len(), r * c);
let mut m = zeros_shape(r, c, shape);
m.data = self[..].to_vec();
m
}
fn add_col(&self, v: &Self::Vec) -> Matrix {
assert_eq!(self.len(), v.len());
let mut x = self[..].to_vec();
x.extend_from_slice(&v[..]);
x.reshape((self.len(), 2), Shape::Col)
}
fn add_row(&self, v: &Self::Vec) -> Matrix {
assert_eq!(self.len(), v.len());
let mut x = self[..].to_vec();
x.extend_from_slice(&v[..]);
x.reshape((2, self.len()), Shape::Row)
}
}
impl Scalable for Matrix {
type Vec = Vec<f64>;
fn reshape(&self, (r, c): (usize, usize), shape: Shape) -> Matrix {
assert_eq!(self.row * self.col, r * c);
let mut m = zeros_shape(r, c, shape);
m.data = self.data[..].to_vec();
m
}
fn add_col(&self, v: &Self::Vec) -> Matrix {
assert_eq!(self.row, v.len());
match self.shape {
Shape::Col => {
let mut m = self.clone();
m.data.extend_from_slice(&v[..]);
m.col += 1;
m
}
Shape::Row => {
let mut m = self.change_shape();
m.data.extend_from_slice(&v[..]);
m.col += 1;
m
}
}
}
fn add_row(&self, v: &Self::Vec) -> Matrix {
assert_eq!(self.col, v.len());
match self.shape {
Shape::Row => {
let mut m = self.clone();
m.data.extend_from_slice(&v[..]);
m.row += 1;
m
}
Shape::Col => {
let mut m = self.change_shape();
m.data.extend_from_slice(&v[..]);
m.row += 1;
m
}
}
}
}
impl ScalableMut for Matrix {
type Vec = Vec<f64>;
fn reshape_mut(&mut self, (r, c): (usize, usize), shape: Shape) {
assert_eq!(self.row * self.col, r * c);
self.row = r;
self.col = c;
self.shape = shape;
}
fn add_col_mut(&mut self, v: &Self::Vec) {
assert_eq!(self.row, v.len());
match self.shape {
Shape::Col => {
self.data.extend_from_slice(&v[..]);
self.col += 1;
}
Shape::Row => {
self.change_shape_mut();
self.data.extend_from_slice(&v[..]);
self.col += 1;
}
}
}
fn add_row_mut(&mut self, v: &Self::Vec) {
assert_eq!(self.col, v.len());
match self.shape {
Shape::Row => {
self.data.extend_from_slice(&v[..]);
self.row += 1;
}
Shape::Col => {
self.change_shape_mut();
self.data.extend_from_slice(&v[..]);
self.row += 1;
}
}
}
}
impl ConvToMat for Vec<f64> {
fn to_col(&self) -> Matrix {
matrix(self.clone(), self.len(), 1, Shape::Col)
}
fn to_row(&self) -> Matrix {
matrix(self.clone(), 1, self.len(), Shape::Row)
}
}