use std::{ops::*, convert::TryInto};
use super::general::NumTools;
const INV_DIM: &str = "Error: Dimensions did not match.";
#[derive(Clone, Debug)]
pub struct MathVector<const C: usize, T> {
values: [T; C],
length: Option<f64>,
}
impl<T: Copy +
NumTools<T> +
From<f64> +
Mul<Output = T>, const C: usize> MathVector<C, T>
where
f64: From<T> {
#[must_use]
pub fn new(values: [T; C]) -> MathVector<C, T> {
MathVector { values: values.try_into().unwrap(),
length: None }
}
#[inline]
#[must_use]
pub fn new_with_dimension() -> MathVector<C, T> {
MathVector { values: [0.0.into(); C],
length: None }
}
#[inline]
#[must_use]
pub fn dimension(&self) -> usize {
self.values.len()
}
#[inline]
#[must_use]
pub fn length(&mut self) -> f64 {
match self.length {
None => { let mut len: f64 = 0.0;
self.values.iter().for_each(|x| len.inc_by(f64::from(*x).square()));
len = len.sqrt();
self.length = Some(len);
len
}
Some(len) => { len }
}
}
#[inline]
#[must_use]
pub fn get_values(&self) -> &[T] {
&self.values
}
pub fn set_values(&mut self, vals: [T; C]) {
match vals.len() == self.dimension() {
true => { self.values = vals;
self.length = None; }
false => { panic!("{}", INV_DIM); }
}
}
#[inline]
pub fn normalise(&mut self) {
*self = scalar_mul(T::from(self.length().recip()), self);
self.length = Some(1.0);
}
}
impl<T: Copy +
super::general::NumTools<T> +
From<f64> + Into<f64> +
Mul<Output = T> +
Add<Output = T>, const C: usize>
Add for MathVector<C, T>
where
f64: From<T> {
type Output = Self;
fn add(self, other: Self) -> MathVector<C, T> {
match self.dimension() == other.dimension() {
true => {
let mut vals = [0.0.into(); C];
for i in 0..self.dimension() {
vals[i] = self.values[i] + other.values[i];
}
MathVector { values: vals,
length: None }
}
false => { panic!("{}", INV_DIM) }
}
}
}
impl<T: Copy +
super::general::NumTools<T> +
From<f64> +
Into<f64> +
Mul<Output = T> +
Sub<Output = T>, const C: usize>
Sub for MathVector<C, T>
where
f64: From<T> {
type Output = Self;
fn sub(self, other: Self) -> MathVector<C, T> {
match self.dimension() == other.dimension() {
true => {
let mut vals = [0.0.into(); C];
for i in 0..self.dimension() {
vals[i] = self.values[i] - other.values[i];
}
MathVector { values: vals,
length: None }
}
false => { panic!("{}", INV_DIM) }
}
}
}
#[inline]
#[must_use = "This returns the result of the operation, without modifying the original."]
pub fn scalar_mul<T: Copy +
super::general::NumTools<T> +
From<f64> +
Mul<Output = T>, const C: usize>
(scalar: T, other: &MathVector<C, T>) -> MathVector<C, T>
where
f64: From<T> {
let mut vals = [0.0.into(); C];
for x in other.values.iter().enumerate() {
vals[x.0] = *x.1 * scalar;
}
MathVector { values: vals,
length: None }
}
impl<T: Copy +
super::general::NumTools<T> +
Into<f64> +
std::fmt::Display + From<f64> +
Mul<Output = T>, const C: usize>
std::fmt::Display for MathVector<C, T>
where
f64: From<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut finstring: String = String::from("( ");
for i in 0..self.dimension() {
finstring.push_str(&(self.values[i].to_string() + "; "));
}
finstring.drain(finstring.len()-2..finstring.len());
write!(f, "{} )", finstring)
}
}
impl<T: PartialEq, const C: usize> PartialEq for MathVector<C, T> {
fn eq(&self, other: &Self) -> bool {
self.values == other.values
}
}