use crate::libs::cs::model::{Cs, Dim};
use crate::libs::tolerance;
use std::ops::{Add, Sub, Mul, Div, Neg};
use std::array;
pub mod d2;
pub mod d3;
impl<const N: usize> Cs<N> where Cs<N>: Dim {
#[rustfmt::skip] #[inline]
pub fn sub(&self, other: &Self) -> Self {
Cs(array::from_fn(|i| self.0[i] - other.0[i]))
}
#[rustfmt::skip] #[inline]
pub fn add(&self, other: &Self) -> Self {
Cs(array::from_fn(|i| self.0[i] + other.0[i]))
}
#[rustfmt::skip] #[inline]
pub fn dot(&self, other: &Self) -> f64 {
let mut sum = 0.0;
for i in 0..N { sum += self.0[i] * other.0[i]; }
sum
}
#[rustfmt::skip] #[inline]
pub fn r_sq(&self) -> f64 { self.dot(self) }
#[rustfmt::skip] #[inline]
pub fn r(&self) -> f64 { self.r_sq().sqrt() }
#[rustfmt::skip] #[inline]
pub fn normalize_r_projection(&self) -> Self {
let radius = self.r();
if tolerance::is_zero(radius) {
Cs([0.0; N])
} else {
Cs(array::from_fn(|i| self.0[i] / radius))
}
}
#[rustfmt::skip] #[inline]
pub fn angle_between(&self, other: &Self) -> f64 {
let r1 = self.r();
let r2 = other.r();
if tolerance::is_zero(r1) || tolerance::is_zero(r2) {
0.0
} else {
(self.dot(other) / (r1 * r2)).clamp(-1.0, 1.0).acos()
}
}
}
impl<const N: usize> Add for Cs<N> where Cs<N>: Dim {
type Output = Cs<N>;
#[inline]
fn add(self, rhs: Self) -> Self::Output {
Cs(array::from_fn(|i| self.0[i] + rhs.0[i]))
}
}
impl<const N: usize> Sub for Cs<N> where Cs<N>: Dim {
type Output = Cs<N>;
#[inline]
fn sub(self, rhs: Self) -> Self::Output {
Cs(array::from_fn(|i| self.0[i] - rhs.0[i]))
}
}
impl<const N: usize> Neg for Cs<N> where Cs<N>: Dim {
type Output = Cs<N>;
#[inline]
fn neg(self) -> Self::Output {
Cs(array::from_fn(|i| -self.0[i]))
}
}
impl<const N: usize> Mul<f64> for Cs<N> where Cs<N>: Dim {
type Output = Cs<N>;
#[inline]
fn mul(self, rhs: f64) -> Self::Output {
Cs(array::from_fn(|i| self.0[i] * rhs))
}
}
impl<const N: usize> Mul<Cs<N>> for f64 where Cs<N>: Dim {
type Output = Cs<N>;
#[inline]
fn mul(self, rhs: Cs<N>) -> Self::Output {
rhs * self }
}
impl<const N: usize> Div<f64> for Cs<N> where Cs<N>: Dim {
type Output = Cs<N>;
#[inline]
fn div(self, rhs: f64) -> Self::Output {
Cs(array::from_fn(|i| self.0[i] / rhs))
}
}