use crate::algebra::linear::mat::Matrix;
use crate::algebra::linear::scalar::Scalar;
use fructose::operators::{ClosedAdd, ClosedMul, ClosedSub};
use fructose::properties::helpers::identity::{One, Two};
use std::ops::{Index, IndexMut};
pub type Point<T, const N: usize> = Vector<T, { N }>;
pub type Vector<T, const N: usize> = Matrix<T, { N }, 1>;
pub type RowVector<T, const N: usize> = Matrix<T, 1, { N }>;
impl<T: Scalar + Copy + ClosedMul + ClosedAdd, const N: usize> Vector<T, { N }> {
#[inline]
pub fn dot(&self, other: Self) -> T {
let mut sum = <T>::default();
for i in 0..N {
sum += self[i] * other[i];
}
sum
}
#[inline]
pub fn reverse(&mut self) {
self.data[0].reverse()
}
#[inline]
pub fn reversed(&self) -> Self {
let mut vec = *self;
vec.reverse();
vec
}
}
impl<T: Scalar + One, const N: usize> Vector<T, { N }> {
#[inline]
pub fn unit(n: usize) -> Self {
let mut data = [<T>::default(); N];
data[n] = <T>::one();
Self { data: [data] }
}
}
impl<T: Scalar + Two + ClosedMul + ClosedAdd + ClosedSub, const N: usize> Vector<T, { N }> {
#[inline]
pub fn reflect(&mut self, normal: Self) {
*self -= normal * <T>::two() * self.dot(normal);
}
}
impl<T, const N: usize> From<[T; N]> for Vector<T, { N }> {
fn from(rhs: [T; N]) -> Self {
Point::new([rhs])
}
}
impl<T> From<(T, T)> for Point<T, 2> {
fn from(rhs: (T, T)) -> Self {
Point::new([[rhs.0, rhs.1]])
}
}
impl<T> From<(T, T, T)> for Point<T, 3> {
fn from(rhs: (T, T, T)) -> Self {
Point::new([[rhs.0, rhs.1, rhs.2]])
}
}
impl<T> From<(T, T, T, T)> for Point<T, 4> {
fn from(rhs: (T, T, T, T)) -> Self {
Point::new([[rhs.0, rhs.1, rhs.2, rhs.3]])
}
}
impl<T, const N: usize> Index<usize> for Vector<T, { N }> {
type Output = T;
fn index(&self, index: usize) -> &Self::Output {
&self.data[0][index]
}
}
impl<T, const N: usize> IndexMut<usize> for Vector<T, { N }> {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
&mut self.data[0][index]
}
}