use std::{
array,
ops::{Add, Div, Mul, Neg, Sub},
};
use crate::libs::{
cs::{
abstracts::{AbstractArithmeticCsGeneric, AbstractMathCsGeneric},
model::Cs,
types::Dim,
},
tolerance,
};
pub mod d2;
pub mod d3;
impl<const N: usize> AbstractMathCsGeneric for Cs<N>
where Cs<N>: Dim
{
#[rustfmt::skip] #[inline]
fn sub(&self, other: &Self) -> Self {
Cs(array::from_fn(|i| self.0[i] - other.0[i]))
}
#[rustfmt::skip] #[inline]
fn add(&self, other: &Self) -> Self {
Cs(array::from_fn(|i| self.0[i] + other.0[i]))
}
#[rustfmt::skip] #[inline]
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]
fn r_sq(&self) -> f64 { self.dot(self) }
#[rustfmt::skip] #[inline]
fn r(&self) -> f64 { self.r_sq().sqrt() }
#[rustfmt::skip] #[inline]
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]
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 {
AbstractMathCsGeneric::add(&self, &rhs)
}
}
impl<const N: usize> Sub for Cs<N>
where Cs<N>: Dim
{
type Output = Cs<N>;
#[inline]
fn sub(self, rhs: Self) -> Self::Output {
AbstractMathCsGeneric::sub(&self, &rhs)
}
}
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))
}
}
impl<const N: usize> AbstractArithmeticCsGeneric for Cs<N>
where Cs<N>: Dim
{
#[inline]
fn add_cs(&self, rhs: &Self) -> Self { AbstractMathCsGeneric::add(self, rhs) }
#[inline]
fn sub_cs(&self, rhs: &Self) -> Self { AbstractMathCsGeneric::sub(self, rhs) }
#[inline]
fn neg_cs(&self) -> Self { -*self }
#[inline]
fn mul_scalar(&self, rhs: f64) -> Self { *self * rhs }
#[inline]
fn div_scalar(&self, rhs: f64) -> Self { *self / rhs }
}