1use core::array;
6use core::fmt::{Debug, Formatter};
7use core::iter::Sum;
8use core::marker::PhantomData;
9use core::ops::{Add, Div, Index, IndexMut, Mul, Neg, Sub};
10use core::ops::{AddAssign, DivAssign, MulAssign, SubAssign};
11
12use crate::math::approx::ApproxEq;
13use crate::math::float::f32;
14use crate::math::space::{Affine, Linear, Proj4, Real};
15
16#[repr(transparent)]
33pub struct Vector<Repr, Space = ()>(pub Repr, PhantomData<Space>);
34
35pub type Vec2<Basis = ()> = Vector<[f32; 2], Real<2, Basis>>;
37pub type Vec3<Basis = ()> = Vector<[f32; 3], Real<3, Basis>>;
39pub type ProjVec4 = Vector<[f32; 4], Proj4>;
41
42pub type Vec2i<Basis = ()> = Vector<[i32; 2], Real<2, Basis>>;
44pub type Vec3i<Basis = ()> = Vector<[i32; 3], Real<3, Basis>>;
46
47pub type Vec2u<Basis = ()> = Vector<[u32; 2], Real<2, Basis>>;
49pub const fn vec2<Sc, B>(x: Sc, y: Sc) -> Vector<[Sc; 2], Real<2, B>> {
57 Vector([x, y], PhantomData)
58}
59
60pub const fn vec3<Sc, B>(x: Sc, y: Sc, z: Sc) -> Vector<[Sc; 3], Real<3, B>> {
62 Vector([x, y, z], PhantomData)
63}
64
65#[inline]
76pub fn splat<Sp, Sc: Clone, const DIM: usize>(s: Sc) -> Vector<[Sc; DIM], Sp> {
77 s.into()
78}
79
80impl<R, Sp> Vector<R, Sp> {
85 #[inline]
87 pub const fn new(repr: R) -> Self {
88 Self(repr, PhantomData)
89 }
90
91 #[inline]
99 pub fn to<S>(self) -> Vector<R, S> {
100 Vector::new(self.0)
101 }
102}
103
104impl<Sp, const N: usize> Vector<[f32; N], Sp> {
106 #[cfg(feature = "fp")]
108 #[inline]
109 pub fn len(&self) -> f32 {
110 super::float::f32::sqrt(self.dot(self))
111 }
112
113 #[inline]
127 #[must_use]
128 pub fn normalize(&self) -> Self {
129 use super::float::f32;
130 #[cfg(feature = "std")]
131 use super::float::RecipSqrt;
132
133 let len_sqr = self.len_sqr();
134 debug_assert_ne!(len_sqr, 0.0, "cannot normalize a zero-length vector");
135 *self * f32::recip_sqrt(len_sqr)
136 }
137
138 #[must_use]
151 pub fn clamp(&self, min: &Self, max: &Self) -> Self {
152 array::from_fn(|i| self[i].clamp(min[i], max[i])).into()
153 }
154}
155
156impl<Sc, Sp, const N: usize> Vector<[Sc; N], Sp>
157where
158 Self: Linear<Scalar = Sc>,
159 Sc: Linear<Scalar = Sc> + Copy,
160{
161 #[inline]
166 pub fn len_sqr(&self) -> Sc {
167 self.dot(self)
168 }
169
170 #[inline]
172 pub fn dot(&self, other: &Self) -> Sc {
173 self.0
174 .iter()
175 .zip(&other.0)
176 .map(|(a, b)| a.mul(*b))
177 .fold(Sc::zero(), |acc, x| acc.add(&x))
178 }
179
180 #[must_use]
183 pub fn scalar_project(&self, other: &Self) -> Sc
184 where
185 Sc: Div<Sc, Output = Sc>,
186 {
187 self.dot(other) / other.dot(other)
188 }
189 #[must_use]
203 pub fn vector_project(&self, other: &Self) -> Self
204 where
205 Sc: Div<Sc, Output = Sc>,
206 {
207 other.mul(self.scalar_project(other))
208 }
209
210 #[inline]
213 #[must_use]
214 pub fn map<T>(self, mut f: impl FnMut(Sc) -> T) -> Vector<[T; N], Sp> {
215 array::from_fn(|i| f(self[i])).into()
216 }
217}
218
219impl<R, Sc, B> Vector<R, Real<2, B>>
220where
221 R: Index<usize, Output = Sc>,
222 Sc: Copy,
223{
224 #[inline]
226 pub fn x(&self) -> Sc {
227 self.0[0]
228 }
229 #[inline]
231 pub fn y(&self) -> Sc {
232 self.0[1]
233 }
234}
235
236impl<R, Sc, B> Vector<R, Real<3, B>>
237where
238 R: Index<usize, Output = Sc>,
239 Sc: Copy,
240{
241 #[inline]
243 pub fn x(&self) -> Sc {
244 self.0[0]
245 }
246 #[inline]
248 pub fn y(&self) -> Sc {
249 self.0[1]
250 }
251 #[inline]
253 pub fn z(&self) -> Sc {
254 self.0[2]
255 }
256
257 pub fn cross(&self, other: &Self) -> Self
281 where
282 Sc: Linear<Scalar = Sc>,
283 [Sc; 3]: Into<Self>,
284 {
285 let (s, o) = (self, other);
286 [
287 s.y().mul(o.z()).sub(&s.z().mul(o.y())),
288 s.z().mul(o.x()).sub(&s.x().mul(o.z())),
289 s.x().mul(o.y()).sub(&s.y().mul(o.x())),
290 ]
291 .into()
292 }
293}
294
295impl<R, Sc> Vector<R, Proj4>
296where
297 R: Index<usize, Output = Sc>,
298 Sc: Copy,
299{
300 #[inline]
302 pub fn x(&self) -> Sc {
303 self.0[0]
304 }
305 #[inline]
307 pub fn y(&self) -> Sc {
308 self.0[1]
309 }
310 #[inline]
312 pub fn z(&self) -> Sc {
313 self.0[2]
314 }
315 #[inline]
317 pub fn w(&self) -> Sc {
318 self.0[3]
319 }
320}
321
322impl<Sc, Sp, const DIM: usize> Affine for Vector<[Sc; DIM], Sp>
327where
328 Sc: Affine,
329 Sc::Diff: Linear<Scalar = Sc::Diff> + Copy,
330{
331 type Space = Sp;
332 type Diff = Vector<[Sc::Diff; DIM], Sp>;
333
334 const DIM: usize = DIM;
336
337 #[inline]
338 fn add(&self, other: &Self::Diff) -> Self {
339 array::from_fn(|i| self.0[i].add(&other.0[i])).into()
341 }
342 #[inline]
343 fn sub(&self, other: &Self) -> Self::Diff {
344 array::from_fn(|i| self.0[i].sub(&other.0[i])).into()
345 }
346}
347
348impl<Sc, Sp, const DIM: usize> Linear for Vector<[Sc; DIM], Sp>
349where
350 Self: Affine<Diff = Self>,
351 Sc: Linear<Scalar = Sc> + Copy,
352{
353 type Scalar = Sc;
354
355 #[inline]
357 fn zero() -> Self {
358 [Sc::zero(); DIM].into()
359 }
360 #[inline]
361 fn neg(&self) -> Self {
362 array::from_fn(|i| self.0[i].neg()).into()
363 }
364 #[inline]
365 fn mul(&self, scalar: Self::Scalar) -> Self {
366 array::from_fn(|i| self.0[i].mul(scalar)).into()
367 }
368}
369
370impl<Sc: ApproxEq, Sp, const N: usize> ApproxEq<Self, Sc>
371 for Vector<[Sc; N], Sp>
372{
373 fn approx_eq_eps(&self, other: &Self, eps: &Sc) -> bool {
374 self.0.approx_eq_eps(&other.0, eps)
375 }
376 fn relative_epsilon() -> Sc {
377 Sc::relative_epsilon()
378 }
379}
380
381impl<R: Copy, S> Copy for Vector<R, S> {}
389
390impl<R: Clone, S> Clone for Vector<R, S> {
391 fn clone(&self) -> Self {
392 Self(self.0.clone(), PhantomData)
393 }
394}
395
396impl<R: Default, S> Default for Vector<R, S> {
397 fn default() -> Self {
398 Self(R::default(), PhantomData)
399 }
400}
401
402impl<R: Eq, S> Eq for Vector<R, S> {}
403
404impl<R: PartialEq, S> PartialEq for Vector<R, S> {
405 fn eq(&self, other: &Self) -> bool {
406 self.0 == other.0
407 }
408}
409
410impl<const DIM: usize, B> Debug for Real<DIM, B>
411where
412 B: Debug + Default,
413{
414 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
415 const DIMS: [char; 3] = ['ยฒ', 'ยณ', 'โด'];
416 let b = B::default();
417 if let Some(dim) = DIMS.get(DIM - 2) {
418 write!(f, "โ{dim}<{b:?}>")
419 } else {
420 write!(f, "โ^{DIM}<{b:?}>")
421 }
422 }
423}
424
425impl<R: Debug, Sp: Debug + Default> Debug for Vector<R, Sp> {
426 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
427 write!(f, "Vec<{:?}>", Sp::default())?;
428 Debug::fmt(&self.0, f)
429 }
430}
431
432impl<R, Sp> From<R> for Vector<R, Sp> {
433 #[inline]
434 fn from(els: R) -> Self {
435 Self(els, PhantomData)
436 }
437}
438
439impl<Sp, Sc: Clone, const DIM: usize> From<Sc> for Vector<[Sc; DIM], Sp> {
440 #[inline]
444 fn from(scalar: Sc) -> Self {
445 array::from_fn(|_| scalar.clone()).into()
446 }
447}
448
449impl<R, Sp> Index<usize> for Vector<R, Sp>
450where
451 Self: Affine,
452 R: Index<usize>,
453{
454 type Output = R::Output;
455
456 #[inline]
462 fn index(&self, i: usize) -> &Self::Output {
463 assert!(i < Self::DIM, "index {i} out of bounds ({})", Self::DIM);
464 &self.0[i]
465 }
466}
467
468impl<R, Sp> IndexMut<usize> for Vector<R, Sp>
469where
470 Self: Affine,
471 R: IndexMut<usize>,
472{
473 #[inline]
479 fn index_mut(&mut self, i: usize) -> &mut Self::Output {
480 assert!(i < Self::DIM, "index {i} out of bounds ({})", Self::DIM);
481 &mut self.0[i]
482 }
483}
484
485impl<R, Sp> Sum for Vector<R, Sp>
486where
487 Self: Linear,
488{
489 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
490 iter.fold(Self::zero(), |acc, v| Affine::add(&acc, &v))
491 }
492}
493
494macro_rules! impl_op {
500 ($trait:ident :: $method:ident, $rhs:ty, $op:tt) => {
501 impl_op!($trait::$method, $rhs, $op, bound=Linear);
502 };
503 ($trait:ident :: $method:ident, $rhs:ty, $op:tt, bound=$bnd:path) => {
504 impl<R, Sp> $trait<$rhs> for Vector<R, Sp>
505 where
506 Self: $bnd,
507 {
508 type Output = Self;
509 #[inline]
511 fn $method(mut self, rhs: $rhs) -> Self {
512 self $op rhs; self
513 }
514 }
515 };
516}
517
518impl<R, Sp> AddAssign<<Self as Affine>::Diff> for Vector<R, Sp>
520where
521 Self: Affine,
522{
523 #[inline]
524 fn add_assign(&mut self, rhs: <Self as Affine>::Diff) {
525 *self = Affine::add(&*self, &rhs);
526 }
527}
528impl_op!(Add::add, <Self as Affine>::Diff, +=, bound=Affine);
530
531impl<R, Sp> SubAssign<<Self as Affine>::Diff> for Vector<R, Sp>
533where
534 Self: Affine,
535{
536 #[inline]
537 fn sub_assign(&mut self, rhs: <Self as Affine>::Diff) {
538 *self = Affine::add(&*self, &rhs.neg());
539 }
540}
541
542impl_op!(Sub::sub, <Self as Affine>::Diff, -=, bound=Affine);
544
545impl<R, Sp> MulAssign<<Self as Linear>::Scalar> for Vector<R, Sp>
547where
548 Self: Linear,
549{
550 #[inline]
551 fn mul_assign(&mut self, rhs: <Self as Linear>::Scalar) {
552 *self = Linear::mul(&*self, rhs);
553 }
554}
555impl_op!(Mul::mul, <Self as Linear>::Scalar, *=);
557
558impl<R, Sp> DivAssign<f32> for Vector<R, Sp>
560where
561 Self: Linear<Scalar = f32>,
562{
563 #[inline]
564 fn div_assign(&mut self, rhs: f32) {
565 debug_assert!(f32::abs(rhs) > 1e-7);
566 *self = Linear::mul(&*self, rhs.recip());
567 }
568}
569
570impl_op!(Div::div, f32, /=, bound=Linear<Scalar = f32>);
572
573impl<R, Sp> Neg for Vector<R, Sp>
575where
576 Self: Linear,
577{
578 type Output = Self;
579
580 #[inline]
581 fn neg(self) -> Self::Output {
582 <Self as Linear>::neg(&self)
583 }
584}
585
586impl<R, Sp> Mul<Vector<R, Sp>> for f32
587where
588 Vector<R, Sp>: Linear<Scalar = f32>,
589{
590 type Output = Vector<R, Sp>;
591
592 #[inline]
593 fn mul(self, rhs: Vector<R, Sp>) -> Self::Output {
594 rhs * self
595 }
596}
597impl<R, Sp> Mul<Vector<R, Sp>> for i32
598where
599 Vector<R, Sp>: Linear<Scalar = i32>,
600{
601 type Output = Vector<R, Sp>;
602
603 #[inline]
604 fn mul(self, rhs: Vector<R, Sp>) -> Self::Output {
605 rhs * self
606 }
607}
608impl<R, Sp> Mul<Vector<R, Sp>> for u32
609where
610 Vector<R, Sp>: Linear<Scalar = u32>,
611{
612 type Output = Vector<R, Sp>;
613
614 #[inline]
615 fn mul(self, rhs: Vector<R, Sp>) -> Self::Output {
616 rhs * self
617 }
618}
619
620#[cfg(test)]
625mod tests {
626 use core::f32::consts::*;
627
628 use crate::assert_approx_eq;
629
630 use super::*;
631
632 pub const fn vec2<S>(x: S, y: S) -> Vector<[S; 2], Real<2>> {
633 super::vec2(x, y)
634 }
635 pub const fn vec3<S>(x: S, y: S, z: S) -> Vector<[S; 3], Real<3>> {
636 super::vec3(x, y, z)
637 }
638 pub const fn vec4<S>(x: S, y: S, z: S, w: S) -> Vector<[S; 4], Real<4>> {
639 Vector::new([x, y, z, w])
640 }
641
642 mod f32 {
643 use super::*;
644
645 #[cfg(feature = "fp")]
646 #[test]
647 fn length() {
648 assert_approx_eq!(vec2(1.0, 1.0).len(), SQRT_2);
649 assert_approx_eq!(vec2(-3.0, 4.0).len(), 5.0);
650 assert_approx_eq!(vec3(1.0, -2.0, 3.0).len(), 14.0f32.sqrt());
651 }
652
653 #[test]
654 fn length_squared() {
655 assert_eq!(vec2(1.0, 1.0).len_sqr(), 2.0);
656 assert_eq!(vec2(-4.0, 3.0).len_sqr(), 25.0);
657 assert_eq!(vec3(1.0, -2.0, 3.0).len_sqr(), 14.0);
658 }
659
660 #[test]
661 fn normalize() {
662 assert_approx_eq!(vec2(3.0, 4.0).normalize(), vec2(0.6, 0.8));
663
664 let sqrt_14 = 14.0f32.sqrt();
665 assert_approx_eq!(
666 vec3(1.0, 2.0, 3.0).normalize(),
667 vec3(1.0 / sqrt_14, 2.0 / sqrt_14, 3.0 / sqrt_14)
668 );
669 }
670
671 #[test]
672 fn vector_addition() {
673 assert_eq!(vec2(1.0, 2.0) + vec2(-2.0, 1.0), vec2(-1.0, 3.0));
674 assert_eq!(
675 vec3(1.0, 2.0, 0.0) + vec3(-2.0, 1.0, -1.0),
676 vec3(-1.0, 3.0, -1.0)
677 );
678 }
679
680 #[test]
681 fn scalar_multiplication() {
682 assert_eq!(vec2(1.0, -2.0) * 0.0, vec2(0.0, 0.0));
683 assert_eq!(vec3(1.0, -2.0, 3.0) * 3.0, vec3(3.0, -6.0, 9.0));
684 assert_eq!(3.0 * vec3(1.0, -2.0, 3.0), vec3(3.0, -6.0, 9.0));
685 assert_eq!(
686 vec4(1.0, -2.0, 0.0, -3.0) * 3.0,
687 vec4(3.0, -6.0, 0.0, -9.0)
688 );
689 assert_eq!(
690 3.0 * vec4(1.0, -2.0, 0.0, -3.0),
691 vec4(3.0, -6.0, 0.0, -9.0)
692 );
693 }
694
695 #[test]
696 fn scalar_division() {
697 assert_eq!(vec2(1.0, -2.0) / 1.0, vec2(1.0, -2.0));
698 assert_eq!(vec3(3.0, -6.0, 9.0) / 3.0, vec3(1.0, -2.0, 3.0));
699 assert_eq!(
700 vec4(3.0, -6.0, 0.0, -9.0) / 3.0,
701 vec4(1.0, -2.0, 0.0, -3.0)
702 );
703 }
704
705 #[test]
706 fn dot_product() {
707 assert_eq!(vec2(1.0, -2.0).dot(&vec2(2.0, 3.0)), -4.0);
708 assert_eq!(vec3(1.0, -2.0, 3.0).dot(&vec3(2.0, 3.0, -1.0)), -7.0);
709 }
710
711 #[test]
712 fn indexing() {
713 let mut v = vec2(1.0, 2.0);
714 assert_eq!(v[1], 2.0);
715 v[0] = 3.0;
716 assert_eq!(v.0, [3.0, 2.0]);
717
718 let mut v = vec3(1.0, 2.0, 3.0);
719 assert_eq!(v[1], 2.0);
720 v[2] = 4.0;
721 assert_eq!(v.0, [1.0, 2.0, 4.0]);
722 }
723
724 #[test]
725 fn from_array() {
726 assert_eq!(Vec2::from([1.0, -2.0]), vec2(1.0, -2.0));
727 assert_eq!(Vec3::from([1.0, -2.0, 4.0]), vec3(1.0, -2.0, 4.0));
728 assert_eq!(
729 Vector::from([1.0, -2.0, 4.0, -3.0]),
730 vec4(1.0, -2.0, 4.0, -3.0)
731 );
732 }
733 }
734
735 mod i32 {
736 use super::*;
737
738 #[test]
739 fn vector_addition() {
740 assert_eq!(vec2(1, 2) + vec2(-2, 1), vec2(-1, 3));
741 assert_eq!(vec3(1, 2, 0) + vec3(-2, 1, -1), vec3(-1, 3, -1));
742 }
743
744 #[test]
745 fn vector_subtraction() {
746 assert_eq!(vec2(1, 2) - vec2(-2, 3), vec2(3, -1));
747 assert_eq!(vec3(1, 2, 0) - vec3(-2, 1, 2), vec3(3, 1, -2));
748 }
749
750 #[test]
751 #[allow(clippy::erasing_op)]
752 fn scalar_multiplication() {
753 assert_eq!(vec2(1, -2) * 0, vec2(0, 0));
754
755 assert_eq!(vec3(1, -2, 3) * 3, vec3(3, -6, 9));
756 assert_eq!(3 * vec3(1, -2, 3), vec3(3, -6, 9));
757
758 assert_eq!(vec4(1, -2, 0, -3) * 3, vec4(3, -6, 0, -9));
759 assert_eq!(3 * vec4(1, -2, 0, -3), vec4(3, -6, 0, -9));
760 }
761
762 #[test]
763 fn dot_product() {
764 assert_eq!(vec2(1, -2).dot(&vec2(2, 3)), -4);
765 assert_eq!(vec3(1, -2, 3).dot(&vec3(2, 3, -1)), -7);
766 }
767
768 #[test]
769 fn indexing() {
770 let mut v = vec2(1, 2);
771 assert_eq!(v[1], 2);
772 v[0] = 3;
773 assert_eq!(v.0, [3, 2]);
774
775 let mut v = vec3(1, 2, 3);
776 assert_eq!(v[1], 2);
777 v[2] = 4;
778 assert_eq!(v.0, [1, 2, 4]);
779 }
780
781 #[test]
782 fn from_array() {
783 assert_eq!(Vec2i::from([1, -2]), vec2(1, -2));
784 assert_eq!(Vec3i::from([1, -2, 3]), vec3(1, -2, 3));
785 }
786 }
787
788 mod u32 {
789 use super::*;
790
791 #[test]
792 fn vector_addition() {
793 assert_eq!(vec2(1_u32, 2) + vec2(1_i32, -2), vec2(2_u32, 0));
794 assert_eq!(
795 vec3(1_u32, 2, 3) + vec3(-1_i32, 1, 0),
796 vec3(0_u32, 3, 3)
797 );
798 }
799
800 #[test]
801 fn vector_subtraction() {
802 assert_eq!(vec2(3_u32, 2) - vec2(3_i32, -1), vec2(0_u32, 3));
803 assert_eq!(
804 vec3(2_u32, 1, 3) - vec3(1_i32, -1, 0),
805 vec3(1_u32, 2, 3)
806 );
807 }
808
809 #[test]
810 fn indexing() {
811 let mut v = vec2(1u32, 2);
812 assert_eq!(v[1], 2);
813 v[0] = 3;
814 assert_eq!(v.0, [3, 2]);
815 }
816
817 #[test]
818 fn from_array() {
819 assert_eq!(Vec2u::from([1, 2]), vec2(1, 2));
820 }
821 }
822
823 #[test]
824 fn cross_product() {
825 assert_eq!(
826 vec3(1.0, 0.0, 0.0).cross(&vec3(0.0, 1.0, 0.0)),
827 vec3(0.0, 0.0, 1.0)
828 );
829 assert_eq!(
830 vec3(0.0, 0.0, 1.0).cross(&vec3(0.0, 1.0, 0.0)),
831 vec3(-1.0, 0.0, 0.0)
832 );
833 }
834
835 #[test]
836 fn iterator_sum() {
837 let vs = [vec2(-1.0, 2.0), vec2(0.0, 2.0), vec2(3.0, -1.0)];
838 assert_eq!(vs.into_iter().sum::<Vec2>(), vec2(2.0, 3.0));
839 }
840
841 #[test]
842 fn approx_equal_pass() {
843 assert_approx_eq!(vec2(1.0, -10.0), vec2(1.01, -9.9), eps = 0.011);
844 }
845 #[test]
846 #[should_panic]
847 fn approx_equal_fail() {
848 let eps = 2.0 * f32::relative_epsilon();
849 assert_approx_eq!(vec2(1.0, -10.0), vec2(1.0 + eps, -10.0 - eps));
850 }
851
852 #[test]
855 fn debug() {
856 assert_eq!(
857 alloc::format!("{:?}", vec2(1.0, -E)),
858 "Vec<โยฒ<()>>[1.0, -2.7182817]"
859 );
860 assert_eq!(
861 alloc::format!("{:?}", vec3(1.0, -2.0, 3.0)),
862 "Vec<โยณ<()>>[1.0, -2.0, 3.0]"
863 );
864 assert_eq!(
865 alloc::format!("{:?}", vec4(1.0, -2.0, PI, -4.0)),
866 "Vec<โโด<()>>[1.0, -2.0, 3.1415927, -4.0]"
867 );
868 }
869}