1use std::{
2 array,
3 ops::{Add, Div, Index, Mul, Neg, Sub},
4};
5
6use culit::culit;
7
8use crate::{
9 Vect,
10 op_wrapper::Sc,
11 ops::Dot,
12 ops::{AngleTo, Cross, ProjRej},
13 traits::Field,
14};
15
16#[derive(Copy, Clone, PartialEq, Eq, Hash)]
17pub struct Nrml<const N: usize, S: Field>([S; N]);
18
19impl<S: Field, const N: usize> Nrml<N, S> {
20 pub const unsafe fn new_unchecked(array: [S; N]) -> Nrml<N, S> {
30 Nrml(array)
31 }
32
33 #[culit]
34 pub const fn axis(i: usize) -> Self {
35 let mut v = [0S; N];
36 v[i] = 1S;
37 Self(v)
38 }
39}
40
41impl<const N: usize> Nrml<N, f32> {
42 pub fn to_f64(self) -> Nrml<N, f64> {
43 Nrml(self.0.map(|x| x as _))
44 }
45}
46
47impl<const N: usize> Nrml<N, f64> {
48 pub fn to_f32(self) -> Nrml<N, f32> {
49 Nrml(self.0.map(|x| x as _))
50 }
51}
52
53impl<S: Field, const N: usize> From<Nrml<N, S>> for Vect<N, S> {
54 fn from(value: Nrml<N, S>) -> Self {
55 Vect(value.0)
56 }
57}
58
59impl<S: Field, const N: usize> Index<usize> for Nrml<N, S> {
60 type Output = S;
61
62 fn index(&self, i: usize) -> &Self::Output {
63 &self.0[i]
64 }
65}
66
67impl<S: Field, const N: usize> Nrml<N, S> {
68 pub fn array(self) -> [S; N] {
69 self.0
70 }
71}
72
73impl<S: Field, const N: usize> Add for Nrml<N, S> {
74 type Output = Vect<N, S>;
75
76 fn add(self, rhs: Self) -> Self::Output {
77 Vect::from_fn(|i| self[i].add(rhs[i]))
78 }
79}
80
81impl<S: Field, const N: usize> Add<Vect<N, S>> for Nrml<N, S> {
82 type Output = Vect<N, S>;
83
84 fn add(self, rhs: Vect<N, S>) -> Self::Output {
85 Vect::from_fn(|i| self[i].add(rhs[i]))
86 }
87}
88
89impl<S: Field, const N: usize> Add<Nrml<N, S>> for Vect<N, S> {
90 type Output = Vect<N, S>;
91
92 fn add(self, rhs: Nrml<N, S>) -> Self::Output {
93 Vect::from_fn(|i| self[i].add(rhs[i]))
94 }
95}
96
97impl<S: Field, const N: usize> Sub for Nrml<N, S> {
98 type Output = Vect<N, S>;
99
100 fn sub(self, rhs: Self) -> Self::Output {
101 Vect::from_fn(|i| self[i].sub(rhs[i]))
102 }
103}
104
105impl<S: Field, const N: usize> Sub<Vect<N, S>> for Nrml<N, S> {
106 type Output = Vect<N, S>;
107
108 fn sub(self, rhs: Vect<N, S>) -> Self::Output {
109 Vect::from_fn(|i| self[i].sub(rhs[i]))
110 }
111}
112
113impl<S: Field, const N: usize> Sub<Nrml<N, S>> for Vect<N, S> {
114 type Output = Vect<N, S>;
115
116 fn sub(self, rhs: Nrml<N, S>) -> Self::Output {
117 Vect::from_fn(|i| self[i].sub(rhs[i]))
118 }
119}
120
121impl<S: Field, const N: usize> Neg for Nrml<N, S> {
122 type Output = Self;
123
124 fn neg(self) -> Self::Output {
125 Self(array::from_fn(|i| self[i].neg()))
126 }
127}
128
129impl<S: Field, const N: usize> Mul<S> for Nrml<N, S> {
130 type Output = Vect<N, S>;
131
132 fn mul(self, rhs: S) -> Self::Output {
133 Vect::from_fn(|i| self[i].mul(rhs))
134 }
135}
136
137impl<S: Field, const N: usize> Div<S> for Nrml<N, S> {
138 type Output = Vect<N, S>;
139
140 fn div(self, rhs: S) -> Self::Output {
141 Vect::from_fn(|i| self[i].div(rhs))
142 }
143}
144
145impl<S: Field, const N: usize> Dot<Self> for Nrml<N, S> {
146 #[culit]
147 fn dot(self, other: Self) -> S {
148 let dot = (0..N)
149 .map(|i| self[i].mul(other[i]))
150 .fold(S::ZERO, |c, n| c.add(n));
151 if dot > S::ONE {
152 S::ONE
153 } else if Sc(dot) < -1Sc {
154 (-1Sc).0
155 } else {
156 dot
157 }
158 }
159
160 type Output = S;
161}
162
163impl<S: Field, const N: usize> Dot<Vect<N, S>> for Nrml<N, S> {
164 fn dot(self, other: Vect<N, S>) -> S {
165 Vect::from(self).dot(other)
166 }
167
168 type Output = S;
169}
170
171impl<S: Field, const N: usize> Dot<Nrml<N, S>> for Vect<N, S> {
172 fn dot(self, other: Nrml<N, S>) -> S {
173 self.dot(Vect::from(other))
174 }
175
176 type Output = S;
177}
178
179impl<S: Field, const N: usize> Cross for Nrml<N, S>
180where
181 Vect<N, S>: Cross,
182{
183 type Output = <Vect<N, S> as Cross>::Output;
184
185 fn cross(self, other: Self) -> Self::Output {
186 Vect::from(self).cross(Vect::from(other))
187 }
188}
189
190impl<S: Field, const N: usize> Cross<Vect<N, S>> for Nrml<N, S>
191where
192 Vect<N, S>: Cross,
193{
194 type Output = <Vect<N, S> as Cross>::Output;
195
196 fn cross(self, other: Vect<N, S>) -> Self::Output {
197 Vect::from(self).cross(other)
198 }
199}
200
201impl<S: Field, const N: usize> Cross<Nrml<N, S>> for Vect<N, S>
202where
203 Self: Cross,
204{
205 type Output = <Self as Cross>::Output;
206
207 fn cross(self, other: Nrml<N, S>) -> Self::Output {
208 self.cross(Vect::from(other))
209 }
210}
211
212impl<S: Field, const N: usize> AngleTo for Nrml<N, S> {
213 type Output = S;
214
215 fn angle_to(self, other: Self) -> Self::Output {
216 self.dot(other).acos()
217 }
218}
219
220impl<S: Field, const N: usize> AngleTo<Option<Self>> for Nrml<N, S> {
221 type Output = S;
222
223 fn angle_to(self, other: Option<Self>) -> Self::Output {
224 match other {
225 Some(other) => self.angle_to(other),
226 None => S::ZERO,
227 }
228 }
229}
230
231impl<S: Field, const N: usize> AngleTo<Nrml<N, S>> for Option<Nrml<N, S>> {
232 type Output = S;
233
234 fn angle_to(self, other: Nrml<N, S>) -> Self::Output {
235 match self {
236 Some(s) => s.angle_to(other),
237 None => S::ZERO,
238 }
239 }
240}
241
242impl<S: Field, const N: usize> AngleTo for Option<Nrml<N, S>> {
243 type Output = S;
244
245 fn angle_to(self, other: Self) -> Self::Output {
246 match (self, other) {
247 (Some(a), Some(b)) => a.angle_to(b),
248 _ => S::ZERO,
249 }
250 }
251}
252
253impl<S: Field, const N: usize> ProjRej<Nrml<N, S>> for Nrml<N, S> {
254 type Output = Vect<N, S>;
255
256 fn proj(self, axis: Nrml<N, S>) -> Vect<N, S> {
257 axis * self.dot(axis)
258 }
259
260 fn rej(self, axis: Nrml<N, S>) -> Vect<N, S> {
261 self - self.proj(axis)
262 }
263
264 fn proj_rej(self, axis: Nrml<N, S>) -> (Vect<N, S>, Vect<N, S>) {
265 let proj = self.proj(axis);
266 (proj, self - proj)
267 }
268}
269
270impl<S: Field, const N: usize> ProjRej<Option<Nrml<N, S>>> for Nrml<N, S> {
271 type Output = Vect<N, S>;
272
273 fn proj(self, axis: Option<Nrml<N, S>>) -> Self::Output {
274 match axis {
275 Some(axis) => self.proj(axis),
276 None => Vect::ZERO,
277 }
278 }
279
280 fn rej(self, axis: Option<Nrml<N, S>>) -> Self::Output {
281 self - self.proj(axis)
282 }
283
284 fn proj_rej(self, axis: Option<Nrml<N, S>>) -> (Self::Output, Self::Output) {
285 let proj = self.proj(axis);
286 (proj, self - proj)
287 }
288}
289impl<S: Field> Nrml<1, S> {
290 pub fn x(self) -> S {
291 self[0]
292 }
293}
294
295impl<S: Field> Nrml<2, S> {
296 pub fn x(self) -> S {
297 self[0]
298 }
299
300 pub fn y(self) -> S {
301 self[1]
302 }
303}
304
305impl<S: Field> Nrml<3, S> {
306 pub fn x(self) -> S {
307 self[0]
308 }
309
310 pub fn y(self) -> S {
311 self[1]
312 }
313
314 pub fn z(self) -> S {
315 self[2]
316 }
317}
318
319impl<S: Field> Nrml<4, S> {
320 pub fn x(self) -> S {
321 self[0]
322 }
323
324 pub fn y(self) -> S {
325 self[1]
326 }
327
328 pub fn z(self) -> S {
329 self[2]
330 }
331
332 pub fn w(self) -> S {
333 self[3]
334 }
335}