1use std::{
4 array,
5 ops::{Add, Div, Mul, Neg, Sub},
6};
7
8use crate::libs::{
9 cs::{
10 abstracts::{AbstractArithmeticCsGeneric, AbstractMathCsGeneric},
11 model::Cs,
12 types::Dim,
13 },
14 tolerance,
15};
16
17pub mod d2;
19pub mod d3;
21
22impl<const N: usize> AbstractMathCsGeneric for Cs<N>
23where Cs<N>: Dim
24{
25 #[rustfmt::skip] #[inline]
28 fn sub(&self, other: &Self) -> Self {
29 Cs(array::from_fn(|i| self.0[i] - other.0[i]))
30 }
31
32 #[rustfmt::skip] #[inline]
35 fn add(&self, other: &Self) -> Self {
36 Cs(array::from_fn(|i| self.0[i] + other.0[i]))
37 }
38
39 #[rustfmt::skip] #[inline]
42 fn dot(&self, other: &Self) -> f64 {
43 let mut sum = 0.0;
44 for i in 0..N { sum += self.0[i] * other.0[i]; }
45 sum
46 }
47
48 #[rustfmt::skip] #[inline]
51 fn r_sq(&self) -> f64 { self.dot(self) }
52
53 #[rustfmt::skip] #[inline]
56 fn r(&self) -> f64 { self.r_sq().sqrt() }
57
58 #[rustfmt::skip] #[inline]
61 fn normalize_r_projection(&self) -> Self {
62 let radius = self.r();
63 if tolerance::is_zero(radius) {
64 Cs([0.0; N])
65 } else {
66 Cs(array::from_fn(|i| self.0[i] / radius))
67 }
68 }
69
70 #[rustfmt::skip] #[inline]
73 fn angle_between(&self, other: &Self) -> f64 {
74 let r1 = self.r();
75 let r2 = other.r();
76 if tolerance::is_zero(r1) || tolerance::is_zero(r2) {
77 0.0
78 } else {
79 (self.dot(other) / (r1 * r2)).clamp(-1.0, 1.0).acos()
80 }
81 }
82}
83
84impl<const N: usize> Add for Cs<N>
91where Cs<N>: Dim
92{
93 type Output = Cs<N>;
94 #[inline]
95 fn add(self, rhs: Self) -> Self::Output {
96 AbstractMathCsGeneric::add(&self, &rhs)
98 }
99}
100
101impl<const N: usize> Sub for Cs<N>
104where Cs<N>: Dim
105{
106 type Output = Cs<N>;
107 #[inline]
108 fn sub(self, rhs: Self) -> Self::Output {
109 AbstractMathCsGeneric::sub(&self, &rhs)
111 }
112}
113
114impl<const N: usize> Neg for Cs<N>
117where Cs<N>: Dim
118{
119 type Output = Cs<N>;
120 #[inline]
121 fn neg(self) -> Self::Output {
122 Cs(array::from_fn(|i| -self.0[i]))
123 }
125}
126
127impl<const N: usize> Mul<f64> for Cs<N>
130where Cs<N>: Dim
131{
132 type Output = Cs<N>;
133 #[inline]
134 fn mul(self, rhs: f64) -> Self::Output {
135 Cs(array::from_fn(|i| self.0[i] * rhs))
136 }
138}
139
140impl<const N: usize> Mul<Cs<N>> for f64
143where Cs<N>: Dim
144{
145 type Output = Cs<N>;
146 #[inline]
147 fn mul(self, rhs: Cs<N>) -> Self::Output { rhs * self }
148}
149
150impl<const N: usize> Div<f64> for Cs<N>
153where Cs<N>: Dim
154{
155 type Output = Cs<N>;
156 #[inline]
157 fn div(self, rhs: f64) -> Self::Output {
158 Cs(array::from_fn(|i| self.0[i] / rhs))
162 }
164}
165impl<const N: usize> AbstractArithmeticCsGeneric for Cs<N>
170where Cs<N>: Dim
171{
172 #[inline]
173 fn add_cs(&self, rhs: &Self) -> Self { AbstractMathCsGeneric::add(self, rhs) }
174 #[inline]
175 fn sub_cs(&self, rhs: &Self) -> Self { AbstractMathCsGeneric::sub(self, rhs) }
176 #[inline]
177 fn neg_cs(&self) -> Self { -*self }
178 #[inline]
179 fn mul_scalar(&self, rhs: f64) -> Self { *self * rhs }
180 #[inline]
181 fn div_scalar(&self, rhs: f64) -> Self { *self / rhs }
182}