use std::{
fmt::{Debug, Display},
hash::Hash,
iter::Sum,
ops::{Add, AddAssign, Div, DivAssign, Mul, Neg, Rem, RemAssign, Sub, SubAssign},
};
use num_traits::{real::Real, Num, NumCast, Signed, ToPrimitive};
#[derive(Clone)]
pub struct Vector<T, const N: usize> {
components: [T; N],
}
#[macro_export]
macro_rules! vector {
($($x:expr),*) => {
$crate::Vector::new([$($x),*])
};
}
impl<T, const N: usize> Vector<T, N> {
pub fn new(components: [T; N]) -> Self {
Self { components }
}
pub fn zero() -> Self
where
T: Num + Copy,
{
Self {
components: [T::zero(); N],
}
}
pub fn as_slice(&self) -> &[T] {
&self.components
}
}
impl<T: Copy, const N: usize> Vector<T, N> {
pub fn num_cast<K: Num + Copy + NumCast>(&self) -> Option<Vector<K, N>>
where
T: ToPrimitive,
{
let mut components = [K::zero(); N];
for (i, e) in self.components.iter().enumerate() {
components[i] = K::from(*e)?;
}
Some(Vector { components })
}
pub fn try_cast<K: Num + Copy + TryFrom<T>>(
&self,
) -> Result<Vector<K, N>, <K as TryFrom<T>>::Error> {
let mut components = [K::zero(); N];
for (i, e) in self.components.iter().enumerate() {
components[i] = K::try_from(*e)?;
}
Ok(Vector { components })
}
pub fn cast<K: Num + Copy + From<T>>(&self) -> Vector<K, N> {
let mut components = [K::zero(); N];
for (i, e) in self.components.iter().enumerate() {
components[i] = K::from(*e);
}
Vector { components }
}
}
impl<T: Default + Copy, const N: usize> Default for Vector<T, N> {
fn default() -> Self {
Self {
components: [T::default(); N],
}
}
}
impl<T: Num + Copy, const N: usize> Vector<T, N> {
pub fn hadamard_product(&self, other: &Self) -> Self {
let mut components = [T::zero(); N];
for (i, e) in components.iter_mut().enumerate() {
*e = self.components[i] * other.components[i];
}
Self { components }
}
}
impl<T: Num + Copy + Ord, const N: usize> Vector<T, N> {
pub fn min(&self, other: &Self) -> Self {
let mut components = [T::zero(); N];
for (i, e) in components.iter_mut().enumerate() {
*e = self.components[i].min(other.components[i]);
}
Self { components }
}
pub fn max(&self, other: &Self) -> Self {
let mut components = [T::zero(); N];
for (i, e) in components.iter_mut().enumerate() {
*e = self.components[i].max(other.components[i]);
}
Self { components }
}
pub fn min_component(&self) -> T {
self.components.iter().min().copied().unwrap()
}
pub fn max_component(&self) -> T {
self.components.iter().max().copied().unwrap()
}
}
impl<T: Num + Copy + Signed, const N: usize> Vector<T, N> {
pub fn opposite(&self) -> Self {
let mut components = [T::zero(); N];
for (i, e) in components.iter_mut().enumerate() {
*e = -self.components[i];
}
Self { components }
}
pub fn signum(&self) -> Self {
let mut components = [T::zero(); N];
for (i, e) in components.iter_mut().enumerate() {
*e = self.components[i].signum();
}
Self { components }
}
pub fn manhattan_distance(&self, other: &Self) -> T {
let mut out = T::zero();
for (&a, &b) in self.components.iter().zip(other.components.iter()) {
out = out + (a - b).abs();
}
out
}
}
impl<T: Num + Copy + Sum, const N: usize> Vector<T, N> {
pub fn sum(&self) -> T {
let mut acc = T::zero();
for i in self.components {
acc = acc + i;
}
acc
}
pub fn magnitude_squared(&self) -> T {
self.components.into_iter().map(|x| x * x).sum()
}
pub fn dot(&self, other: &Self) -> T {
self.components
.iter()
.zip(other.components.iter())
.map(|(a, b)| *a * *b)
.sum()
}
}
impl<T: Num + Copy + Sum + Real, const N: usize> Vector<T, N> {
pub fn magnitude(&self) -> T {
self.magnitude_squared().sqrt()
}
pub fn normalize(&self) -> Self {
*self / self.magnitude()
}
pub fn distance(&self, other: &Self) -> T {
(*self - *other).magnitude()
}
}
impl<T: Num + Signed + Copy, const N: usize> Vector<T, N> {
pub fn abs(&self) -> Self {
let mut components = [T::zero(); N];
for (i, e) in components.iter_mut().enumerate() {
*e = self.components[i].abs();
}
Self { components }
}
}
impl<T: Num + Copy + Display, const N: usize> Debug for Vector<T, N> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let components = self.components.map(|x| x.to_string()).join(", ");
f.write_fmt(format_args!("({})", components))
}
}
impl<T: Num + Copy, const N: usize> Copy for Vector<T, N> {}
impl<T: Num + Copy, const N: usize> Eq for Vector<T, N> {}
impl<T: Num + Copy, const N: usize> FromIterator<T> for Vector<T, N> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
let mut components = [T::zero(); N];
for (i, item) in iter.into_iter().take(N).enumerate() {
components[i] = item;
}
Self { components }
}
}
macro_rules! bin_op {
($trait:tt, $func:ident) => {
impl<T: Num + Copy, const N: usize> $trait for Vector<T, N> {
type Output = Self;
fn $func(self, other: Self) -> Self::Output {
let mut components = [T::zero(); N];
for (i, e) in components.iter_mut().enumerate() {
*e = self.components[i].$func(other.components[i]);
}
Self { components }
}
}
impl<T: Num + Copy, const N: usize> $trait<T> for Vector<T, N> {
type Output = Self;
fn $func(self, other: T) -> Self::Output {
let mut components = [T::zero(); N];
for (i, e) in components.iter_mut().enumerate() {
*e = self.components[i].$func(other);
}
Self { components }
}
}
};
}
bin_op!(Add, add);
bin_op!(Sub, sub);
bin_op!(Div, div);
bin_op!(Rem, rem);
macro_rules! assign_op {
($trait:tt, $func:ident, $op:ident) => {
impl<T: Num + Copy, const N: usize> $trait for Vector<T, N> {
fn $func(&mut self, rhs: Self) {
for (i, e) in self.components.iter_mut().enumerate() {
*e = e.$op(rhs.components[i]);
}
}
}
};
}
assign_op!(AddAssign, add_assign, add);
assign_op!(SubAssign, sub_assign, sub);
assign_op!(DivAssign, div_assign, div);
assign_op!(RemAssign, rem_assign, rem);
impl<T: Num + Copy, const N: usize> Neg for Vector<T, N> {
type Output = Self;
fn neg(self) -> Self::Output {
let mut components = [T::zero(); N];
for (i, e) in components.iter_mut().enumerate() {
*e = T::zero() - self.components[i];
}
Self { components }
}
}
impl<T: Num + Copy, const N: usize> PartialEq for Vector<T, N> {
fn eq(&self, other: &Self) -> bool {
self.components
.iter()
.zip(other.components.iter())
.all(|(a, b)| a == b)
}
}
impl<T: Num + Copy + Send + Sync, const N: usize> Mul<T> for Vector<T, N> {
type Output = Self;
fn mul(self, rhs: T) -> Self::Output {
let mut components = [T::zero(); N];
for (i, e) in components.iter_mut().enumerate() {
*e = self.components[i] * rhs;
}
Self { components }
}
}
impl<T: Hash, const N: usize> Hash for Vector<T, N> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.components.hash(state);
}
}
impl<T: Copy> Vector<T, 2> {
#[inline(always)]
pub fn x(&self) -> T {
self.components[0]
}
#[inline(always)]
pub fn y(&self) -> T {
self.components[1]
}
}
impl<T: Copy> Vector<T, 3> {
#[inline(always)]
pub fn x(&self) -> T {
self.components[0]
}
#[inline(always)]
pub fn y(&self) -> T {
self.components[1]
}
#[inline(always)]
pub fn z(&self) -> T {
self.components[2]
}
}