1use crate::vval::VVal;
9use std::ops::{Neg, Add, Sub, Div, Mul};
10
11
12#[derive(Debug, Copy, Clone, PartialEq)]
15pub enum NVec<N: NVecNum> {
16 Vec2(N, N),
17 Vec3(N, N, N),
18 Vec4(N, N, N, N),
19}
20
21#[derive(Clone, Copy, Debug, Ord, PartialOrd, Eq, PartialEq)]
23pub enum NVecDim {
24 Two = 2,
25 Three = 3,
26 Four = 4,
27}
28
29#[allow(clippy::len_without_is_empty)]
30impl NVecDim {
31 pub fn len(self) -> usize {
33 match self {
34 NVecDim::Two => 2,
35 NVecDim::Three => 3,
36 NVecDim::Four => 4,
37 }
38 }
39}
40
41use NVec::*;
51
52pub trait NVecNum: Sized + Copy + Clone + PartialEq {
54 fn sign() -> char;
56
57 fn from_vval(v: &VVal) -> Self;
58 fn into_vval(self) -> VVal;
59
60 fn into_f64(self) -> f64;
61 fn from_f64(f: f64) -> Self;
62
63 fn into_f32(self) -> f32;
64 fn from_f32(f: f32) -> Self;
65
66 fn into_i64(self) -> i64;
67 fn from_i64(i: i64) -> Self;
68
69 fn into_i32(self) -> i32;
70 fn from_i32(i: i32) -> Self;
71
72 fn zero() -> Self;
74
75 fn add(self, o: Self) -> Self;
76 fn sub(self, o: Self) -> Self;
77 fn mul(self, o: Self) -> Self;
78 fn div(self, o: Self) -> Self;
79
80 fn from_ivec(ivec: NVec<i64>) -> NVec<Self>;
81 fn into_fvec(s: NVec<Self>) -> NVec<f64>;
82 fn from_fvec(fvec: NVec<f64>) -> NVec<Self>;
83 fn from_fvec_round(fvec: NVec<f64>) -> NVec<Self>;
84}
85
86impl NVecNum for i64 {
87 #[inline]
88 fn sign() -> char { 'i' }
89
90 #[inline]
91 fn from_vval(v: &VVal) -> Self { v.i() }
92 #[inline]
93 fn into_vval(self) -> VVal { VVal::Int(self) }
94
95 #[inline]
96 fn into_f64(self) -> f64 { self as f64 }
97 #[inline]
98 fn from_f64(f: f64) -> Self { f as i64 }
99
100 #[inline]
101 fn into_f32(self) -> f32 { self as f32 }
102 #[inline]
103 fn from_f32(f: f32) -> Self { f as i64 }
104
105 #[inline]
106 fn into_i64(self) -> i64 { self }
107 #[inline]
108 fn from_i64(i: i64) -> Self { i }
109
110 #[inline]
111 fn into_i32(self) -> i32 { self as i32 }
112 #[inline]
113 fn from_i32(i: i32) -> Self { i as i64 }
114
115 #[inline]
116 fn zero() -> Self { 0 }
117
118 #[inline]
119 fn add(self, o: Self) -> Self { self + o }
120 #[inline]
121 fn sub(self, o: Self) -> Self { self - o }
122 #[inline]
123 fn mul(self, o: Self) -> Self { self * o }
124 #[inline]
125 fn div(self, o: Self) -> Self { self / o }
126
127 #[inline]
128 fn from_ivec(i: NVec<i64>) -> NVec<Self> { i }
129 #[inline]
130 fn into_fvec(i: NVec<Self>) -> NVec<f64> { NVec::from_vval_tpl(i.into_vval_tpl()).unwrap() }
131 #[inline]
132 fn from_fvec(f: NVec<f64>) -> NVec<Self> { NVec::from_vval_tpl(f.into_vval_tpl()).unwrap() }
133 #[inline]
134 #[allow(clippy::many_single_char_names)]
135 fn from_fvec_round(f: NVec<f64>) -> NVec<Self> {
136 let (x, y, z, w) = f.into_tpl();
137 NVec::from_tpl((
138 x.round() as i64,
139 y.round() as i64,
140 z.map(|z| z.round() as i64),
141 w.map(|w| w.round() as i64)
142 )).unwrap()
143 }
144}
145
146impl NVecNum for f64 {
147 #[inline]
148 fn sign() -> char { 'f' }
149
150 #[inline]
151 fn from_vval(v: &VVal) -> Self { v.f() }
152 #[inline]
153 fn into_vval(self) -> VVal { VVal::Flt(self) }
154
155 #[inline]
156 fn into_f64(self) -> f64 { self }
157 #[inline]
158 fn from_f64(f: f64) -> Self { f }
159
160 #[inline]
161 fn into_f32(self) -> f32 { self as f32 }
162 #[inline]
163 fn from_f32(f: f32) -> Self { f as f64 }
164
165 #[inline]
166 fn into_i64(self) -> i64 { self as i64 }
167 #[inline]
168 fn from_i64(f: i64) -> Self { f as f64 }
169
170 #[inline]
171 fn into_i32(self) -> i32 { self as i32 }
172 #[inline]
173 fn from_i32(f: i32) -> Self { f as f64 }
174
175 #[inline]
176 fn zero() -> Self { 0.0 }
177
178 #[inline]
179 fn add(self, o: Self) -> Self { self + o }
180 #[inline]
181 fn sub(self, o: Self) -> Self { self - o }
182 #[inline]
183 fn mul(self, o: Self) -> Self { self * o }
184 #[inline]
185 fn div(self, o: Self) -> Self { self / o }
186
187 #[inline]
188 fn from_ivec(i: NVec<i64>) -> NVec<Self> { NVec::from_vval_tpl(i.into_vval_tpl()).unwrap() }
189 #[inline]
190 fn into_fvec(f: NVec<Self>) -> NVec<f64> { f }
191 #[inline]
192 fn from_fvec(f: NVec<f64>) -> NVec<Self> { f }
193 #[inline]
194 fn from_fvec_round(f: NVec<f64>) -> NVec<Self> { f }
195}
196
197impl AsRef<VVal> for VVal {
198 fn as_ref(&self) -> &Self {
199 self
200 }
201}
202
203impl<N: NVecNum> NVec<N> {
204 #[inline]
206 pub fn x(&self) -> VVal {
207 self.x_raw().into_vval()
208 }
209
210 #[inline]
212 pub fn x_raw(&self) -> N {
213 match self {
214 Vec2(x, _) => *x,
215 Vec3(x, _, _) => *x,
216 Vec4(x, _, _, _) => *x,
217 }
218 }
219
220 #[inline]
222 pub fn y(&self) -> VVal {
223 self.y_raw().into_vval()
224 }
225
226 #[inline]
228 pub fn y_raw(&self) -> N {
229 match self {
230 Vec2(_, y) => *y,
231 Vec3(_, y, _) => *y,
232 Vec4(_, y, _, _) => *y,
233 }
234 }
235
236 #[inline]
238 pub fn z(&self) -> Option<VVal> {
239 self.z_raw().map(|v| v.into_vval())
240 }
241
242 #[inline]
244 pub fn z_raw(&self) -> Option<N> {
245 match self {
246 Vec2(_, _) => None,
247 Vec3(_, _, z) => Some(*z),
248 Vec4(_, _, z, _) => Some(*z),
249 }
250 }
251
252 #[inline]
254 pub fn w(&self) -> Option<VVal> {
255 self.w_raw().map(|v| v.into_vval())
256 }
257
258 #[inline]
260 pub fn w_raw(&self) -> Option<N> {
261 match self {
262 Vec2(_, _) => None,
263 Vec3(_, _, _) => None,
264 Vec4(_, _, _, w) => Some(*w),
265 }
266 }
267
268 #[inline]
270 pub fn dims(&self) -> NVecDim {
271 match self {
272 Vec2(_, _) => NVecDim::Two,
273 Vec3(_, _, _) => NVecDim::Three,
274 Vec4(_, _, _, _) => NVecDim::Four,
275 }
276 }
277
278 #[inline]
281 pub fn into_tpl(self) -> (N, N, Option<N>, Option<N>) {
282 match self {
283 Vec2(x, y) => (x, y, None , None),
284 Vec3(x, y, z) => (x, y, Some(z), None),
285 Vec4(x, y, z, w) => (x, y, Some(z), Some(w)),
286 }
287 }
288
289 #[inline]
290 pub fn into_zero_tpl(self) -> (N, N, N, N) {
293 let zero = N::zero();
294 match self {
295 Vec2(x, y) => (x, y, zero, zero),
296 Vec3(x, y, z) => (x, y, z, zero),
297 Vec4(x, y, z, w) => (x, y, z, w),
298 }
299 }
300
301 #[inline]
304 pub fn into_vval_tpl(self) -> (VVal, VVal, Option<VVal>, Option<VVal>) {
305 match self {
306 Vec2(x, y) => (x.into_vval(), y.into_vval(), None , None),
307 Vec3(x, y, z) => (x.into_vval(), y.into_vval(), Some(z.into_vval()), None),
308 Vec4(x, y, z, w) => (x.into_vval(), y.into_vval(), Some(z.into_vval()), Some(w.into_vval())),
309 }
310 }
311
312 #[inline]
314 pub fn from_tpl(tpl: (N, N, Option<N>, Option<N>)) -> Option<Self> {
315 Some(match tpl {
316 (x, y, None , None) => Vec2(x, y),
317 (x, y, Some(z), None) => Vec3(x, y, z),
318 (x, y, Some(z), Some(w)) => Vec4(x, y, z, w),
319 _ => return None
320 })
321 }
322
323 #[inline]
325 pub fn from_vval_tpl<W: AsRef<VVal>>((x, y, z, w): (W, W, Option<W>, Option<W>)) -> Option<Self> {
326 Some(match (x.as_ref(), y.as_ref(), z, w) {
327 (x, y, None , None) =>
328 Vec2(N::from_vval(x), N::from_vval(y)),
329 (x, y, Some(z), None) =>
330 Vec3(N::from_vval(x), N::from_vval(y), N::from_vval(z.as_ref())),
331 (x, y, Some(z), Some(w)) =>
332 Vec4(N::from_vval(x), N::from_vval(y), N::from_vval(z.as_ref()), N::from_vval(w.as_ref())),
333 _ => return None
334 })
335 }
336
337 #[inline]
339 pub fn s(&self) -> String {
340 match self.into_vval_tpl() {
341 (x, y, None, None) => format!("${}({},{})", N::sign(), x.s(), y.s()),
342 (x, y, Some(z), None) => format!("${}({},{},{})", N::sign(), x.s(), y.s(), z.s()),
343 (x, y, Some(z), Some(w)) => format!("${}({},{},{},{})", N::sign(), x.s(), y.s(), z.s(), w.s()),
344 _ => unreachable!()
345 }
346 }
347
348 #[inline]
349 pub fn vec2(self) -> Self {
351 match self {
352 Vec2(_, _) => self,
353 Vec3(x, y, _) => Vec2(x, y),
354 Vec4(x, y, _, _) => Vec2(x, y),
355 }
356 }
357
358 #[inline]
359 pub fn vec3(self) -> Self {
362 match self {
363 Vec2(x, y) => Vec3(x, y, N::zero()),
364 Vec3(_, _, _) => self,
365 Vec4(x, y, z, _) => Vec3(x, y, z),
366 }
367 }
368
369 #[inline]
372 pub fn vec4(self) -> Self {
373 let o = N::zero();
374 match self {
375 Vec2(x, y) => Vec4(x, y, o, o),
376 Vec3(x, y, z) => Vec4(x, y, z, o),
377 Vec4(_, _, _, _) => self,
378 }
379 }
380
381 #[inline]
384 pub fn mag2(&self) -> f64 {
385 match self {
386 Vec2(x, y) =>
387 x.into_f64().powi(2) + y.into_f64().powi(2),
388 Vec3(x, y, z) =>
389 x.into_f64().powi(2) + y.into_f64().powi(2) + z.into_f64().powi(2),
390 Vec4(x, y, z, w) =>
391 x.into_f64().powi(2) + y.into_f64().powi(2) + z.into_f64().powi(2) + w.into_f64().powi(2),
392 }
393 }
394
395 #[inline]
399 pub fn mag(&self) -> f64 {
400 self.mag2().sqrt()
401 }
402
403 #[inline]
405 pub fn norm(self) -> Self {
406 let m = N::from_f64(self.mag());
407 if m == N::zero() {
408 self
409 } else {
410 self / m
411 }
412 }
413
414 #[inline]
416 pub fn dot(self, o: NVec<N>) -> N {
417 let max_dims = self.dims().max(o.dims());
418 let (lx, ly, lz, lw) = self.into_zero_tpl();
419 let (rx, ry, rz, rw) = o.into_zero_tpl();
420
421 match max_dims {
422 NVecDim::Two => lx.mul(rx).add(ly.mul(ry)),
423 NVecDim::Three => lx.mul(rx).add(ly.mul(ry)).add(lz.mul(rz)),
424 NVecDim::Four => lx.mul(rx).add(ly.mul(ry)).add(lz.mul(rz)).add(lw.mul(rw)),
425 }
426 }
427
428 #[inline]
430 pub fn cross(self, o: NVec<N>) -> Self {
431 let a = self.into_zero_tpl();
432 let b = o.into_zero_tpl();
433
434 Vec3(
435 a.1.mul(b.2).sub(a.2.mul(b.1)),
436 a.2.mul(b.0).sub(a.0.mul(b.2)),
437 a.0.mul(b.1).sub(a.1.mul(b.0)),
438 )
439 }
440
441 #[inline]
444 pub fn lerp(self, o: NVec<N>, t: f64) -> Self {
445 N::from_fvec_round(
446 (N::into_fvec(self) * (1.0 - t))
447 + (N::into_fvec(o) * t)
448 )
449 }
450
451 pub fn vec2rad(self) -> f64 {
453 N::into_f64(self.y_raw()).atan2(N::into_f64(self.x_raw()))
454 }
455
456 pub fn rad2vec(f: f64) -> Self {
458 let (y, x) = f.sin_cos();
459 N::from_fvec(Vec2(x, y))
460 }
461
462 #[inline]
463 pub fn slerp(self, o: NVec<N>, t: f64) -> Self {
470 let (p0, p1) = {
471 let (p0, p1) = (N::into_fvec(self), N::into_fvec(o));
472 if (p0 + p1).mag2() == 0.0 {
474 ((p0 + Vec2(1e-5, 1e-5)).norm(), p1)
475 } else {
476 (p0, p1)
477 }
478 };
479 let omega = p0.dot(p1).acos();
480 let sin_omega = omega.sin();
481 N::from_fvec_round(
482 (p0 * (((1.0 - t) * omega).sin() / sin_omega))
483 + (p1 * ((t * omega).sin() / sin_omega))
484 )
485 }
486}
487
488#[cfg(feature = "mint")]
489macro_rules! mint_vec_to_from { ( $( $ty:ident : $to:ident -> $from:ident ; )* ) => { $(
490impl<N: NVecNum> From<mint::Vector2<$ty>> for NVec<N> {
491 fn from(o: mint::Vector2<$ty>) -> Self {
492 Vec2(N::$from(o.x), N::$from(o.y))
493 }
494}
495impl<N: NVecNum> From<mint::Vector3<$ty>> for NVec<N> {
496 fn from(o: mint::Vector3<$ty>) -> Self {
497 Vec3(N::$from(o.x), N::$from(o.y), N::$from(o.z))
498 }
499}
500impl<N: NVecNum> From<mint::Vector4<$ty>> for NVec<N> {
501 fn from(o: mint::Vector4<$ty>) -> Self {
502 Vec4(N::$from(o.x), N::$from(o.y), N::$from(o.z), N::$from(o.w))
503 }
504}
505
506impl<N: NVecNum> Into<mint::Vector2<$ty>> for NVec<N> {
507 fn into(self) -> mint::Vector2<$ty> {
508 let (x, y, _, _) = self.into_zero_tpl();
509 mint::Vector2 { x: N::$to(x), y: N::$to(y) }
510 }
511}
512impl<N: NVecNum> Into<mint::Vector3<$ty>> for NVec<N> {
513 fn into(self) -> mint::Vector3<$ty> {
514 let (x, y, z, _) = self.into_zero_tpl();
515 mint::Vector3 { x: N::$to(x), y: N::$to(y), z: N::$to(z) }
516 }
517}
518impl<N: NVecNum> Into<mint::Vector4<$ty>> for NVec<N> {
519 fn into(self) -> mint::Vector4<$ty> {
520 let (x, y, z, w) = self.into_zero_tpl();
521 mint::Vector4 { x: N::$to(x), y: N::$to(y), z: N::$to(z), w: N::$to(w) }
522 }
523}
524)* } }
525
526#[cfg(feature = "mint")]
527mint_vec_to_from! {
528 f64 : into_f64 -> from_f64;
529 f32 : into_f32 -> from_f32;
530 i64 : into_i64 -> from_i64;
531 i32 : into_i32 -> from_i32;
532}
533
534impl<N: NVecNum> Neg for NVec<N> {
535 type Output = NVec<N>;
536
537 fn neg(self) -> Self::Output {
538 self * N::from_f64(-1.0)
539 }
540}
541
542macro_rules! euler_binop { ( $( $trait:ident | $fn:ident ; )* ) => { $(
543 impl<N: NVecNum> $trait for NVec<N> {
544 type Output = Self;
545
546 #[inline]
547 fn $fn(self, o: NVec<N>) -> NVec<N> {
548 let max_dims = self.dims().max(o.dims());
549 let (lx, ly, lz, lw) = self.into_zero_tpl();
550 let (rx, ry, rz, rw) = o.into_zero_tpl();
551
552 match max_dims {
553 NVecDim::Two => Vec2(lx.$fn(rx), ly.$fn(ry)),
554 NVecDim::Three => Vec3(lx.$fn(rx), ly.$fn(ry), lz.$fn(rz)),
555 NVecDim::Four => Vec4(lx.$fn(rx), ly.$fn(ry), lz.$fn(rz), lw.$fn(rw)),
556 }
557 }
558 }
559)* } }
560euler_binop! {
561 Add | add;
562 Sub | sub;
563}
564
565macro_rules! scalar_binop { ( $( $trait:ident | $fn:ident ; )* ) => { $(
566 impl<N: NVecNum> $trait<N> for NVec<N> {
567 type Output = Self;
568
569 #[inline]
570 fn $fn(self, o: N) -> NVec<N> {
571 match self {
572 Vec2(x, y) => Vec2(x.$fn(o), y.$fn(o)),
573 Vec3(x, y, z) => Vec3(x.$fn(o), y.$fn(o), z.$fn(o)),
574 Vec4(x, y, z, w) => Vec4(x.$fn(o), y.$fn(o), z.$fn(o), w.$fn(o)),
575 }
576 }
577 }
578)* } }
579scalar_binop! {
580 Mul | mul;
581 Div | div;
582}