retrofire_core/math/
vec.rs

1//! Real and projective vectors.
2//!
3//! TODO
4
5use core::{
6    array,
7    fmt::{Debug, Formatter},
8    iter::Sum,
9    marker::PhantomData as Pd,
10    ops::{Add, Div, Index, IndexMut, Mul, Neg, Sub},
11    ops::{AddAssign, DivAssign, MulAssign, SubAssign},
12};
13
14use crate::math::{
15    Affine, ApproxEq, Linear, Point,
16    space::{Proj3, Real},
17    vary::ZDiv,
18};
19
20//
21// Types
22//
23
24/// A generic vector type. Represents an element of a vector space or a module,
25/// a generalization of a vector space where the scalars can be integers
26/// (technically, the scalar type can be any *ring*-like type).
27///
28/// # Type parameters
29/// * `Repr`: Representation of the scalar components of the vector,
30///   for example an array or a SIMD vector.
31/// * `Space`: The space that the vector is an element of. A tag type used to
32///   prevent mixing up vectors of different spaces and bases.
33///
34/// # Examples
35/// TODO examples
36#[repr(transparent)]
37pub struct Vector<Repr, Space = ()>(pub Repr, Pd<Space>);
38
39/// A 2-vector with `f32` components.
40pub type Vec2<Basis = ()> = Vector<[f32; 2], Real<2, Basis>>;
41/// A 3-vector with `f32` components.
42pub type Vec3<Basis = ()> = Vector<[f32; 3], Real<3, Basis>>;
43/// A `f32` 4-vector in the projective 3-space over ℝ, aka P<sub>3</sub>(ℝ).
44pub type ProjVec3 = Vector<[f32; 4], Proj3>;
45
46//pub type HomVec2<B> = Vector<[f32; 3], Hom<2, B>>;
47//pub type HomVec3<B> = Vector<[f32; 4], Hom<3, B>>;
48
49/// A 2-vector with `i32` components.
50pub type Vec2i<Basis = ()> = Vector<[i32; 2], Real<2, Basis>>;
51/// A 3-vector with `i32` components.
52pub type Vec3i<Basis = ()> = Vector<[i32; 3], Real<3, Basis>>;
53
54//
55// Free functions
56//
57
58/// Returns a real 2-vector with components `x` and `y`.
59pub const fn vec2<Sc, B>(x: Sc, y: Sc) -> Vector<[Sc; 2], Real<2, B>> {
60    Vector([x, y], Pd)
61}
62
63/// Returns a real 3-vector with components `x`, `y`, and `z`.
64pub const fn vec3<Sc, B>(x: Sc, y: Sc, z: Sc) -> Vector<[Sc; 3], Real<3, B>> {
65    Vector([x, y, z], Pd)
66}
67
68/// Returns a vector with all components equal to a scalar.
69///
70/// This operation is also called "broadcast".
71///
72/// # Examples
73/// ```
74/// use retrofire_core::math::{vec3, Vec3, splat};
75/// let v: Vec3 = splat(1.23);
76/// assert_eq!(v, vec3(1.23, 1.23, 1.23));
77#[inline]
78pub fn splat<Sp, Sc: Clone, const DIM: usize>(s: Sc) -> Vector<[Sc; DIM], Sp> {
79    array::from_fn(|_| s.clone()).into() // Use array::repeat once stable
80}
81
82//
83// Inherent impls
84//
85
86impl<R, Sp> Vector<R, Sp> {
87    /// Returns a new vector with representation `repr`.
88    #[inline]
89    pub const fn new(repr: R) -> Self {
90        Self(repr, Pd)
91    }
92
93    /// Returns a vector with value equal to `self` but in space `S`.
94    ///
95    /// This method can be used to coerce a vector from one space
96    /// to another in order to make types match. One use case is
97    /// to cast a "generic" vector returned by one of the constructor
98    /// functions to a more specific space.
99    // TODO Cannot be const (yet?) due to E0493 :(
100    #[inline]
101    pub fn to<S>(self) -> Vector<R, S> {
102        Vector::new(self.0)
103    }
104
105    /// Returns the affine point equivalent to `self`.
106    // TODO Cannot be const (yet?) due to E0493 :(
107    #[inline]
108    pub fn to_pt(self) -> Point<R, Sp> {
109        Point::new(self.0)
110    }
111}
112
113// TODO Many of these functions could be more generic
114impl<Sp, const N: usize> Vector<[f32; N], Sp> {
115    /// Returns the length (magnitude) of `self`.
116    #[cfg(feature = "fp")]
117    #[inline]
118    pub fn len(&self) -> f32 {
119        super::float::f32::sqrt(self.dot(self))
120    }
121
122    /// Returns `self` normalized to unit length.
123    ///
124    /// # Examples
125    /// ```
126    /// use retrofire_core::assert_approx_eq;
127    /// use retrofire_core::math::{vec2, Vec2};
128    ///
129    /// let normalized: Vec2 = vec2(3.0, 4.0).normalize();
130    /// assert_approx_eq!(normalized, vec2(0.6, 0.8), eps=1e-2);
131    /// assert_approx_eq!(normalized.len_sqr(), 1.0, eps=1e-2);
132    /// ```
133    ///
134    /// # Panics
135    /// Panics in dev mode if `self` is a zero vector.
136    #[inline]
137    #[must_use]
138    pub fn normalize(&self) -> Self {
139        #[cfg(feature = "std")]
140        use super::float::RecipSqrt;
141        use super::float::f32;
142        let len_sqr = self.len_sqr();
143        assert!(
144            len_sqr.is_finite() && !len_sqr.approx_eq_eps(&0.0, &1e-12),
145            "cannot normalize a near-zero or non-finite vector: {:?}",
146            self.0
147        );
148        *self * f32::recip_sqrt(len_sqr)
149    }
150
151    /// Returns `self` clamped component-wise to the given range.
152    ///
153    /// In other words, for each component `self[i]`, the result `r` has
154    /// `r[i]` equal to `self[i].clamp(min[i], max[i])`.
155    ///
156    /// # Examples
157    /// ```
158    /// use retrofire_core::math::vec::{vec3, Vec3, splat};
159    /// let v: Vec3 = vec3(0.5, 1.5, -2.0);
160    ///
161    /// // Clamp to the unit cube
162    /// let clamped = v.clamp(&splat(-1.0), &splat(1.0));
163    /// assert_eq!(clamped, vec3(0.5, 1.0, -1.0));
164    // TODO f32 and f64 have inherent clamp methods because they're not Ord.
165    //      A generic clamp for Sc: Ord would conflict with this one. There is
166    //      currently no clean way to support both floats and impl Ord types.
167    //      However, VecXi and VecXu should have their own inherent impls.
168    #[must_use]
169    pub fn clamp(&self, min: &Self, max: &Self) -> Self {
170        array::from_fn(|i| self[i].clamp(min[i], max[i])).into()
171    }
172
173    /// Returns `true` if every component of `self` is finite,
174    /// `false` otherwise.
175    ///
176    /// See [`f32::is_finite()`].
177    pub fn is_finite(&self) -> bool {
178        self.0.iter().all(|c| c.is_finite())
179    }
180}
181
182impl<Sc, Sp, const N: usize> Vector<[Sc; N], Sp>
183where
184    Self: Linear<Scalar = Sc>,
185    Sc: Linear<Scalar = Sc> + Copy,
186{
187    /// Returns the length of `self`, squared.
188    ///
189    /// This avoids taking the square root in cases it's not needed and works with scalars for
190    /// which a square root is not defined.
191    #[inline]
192    pub fn len_sqr(&self) -> Sc {
193        self.dot(self)
194    }
195
196    /// Returns the dot product of `self` and `other`.
197    #[inline]
198    pub fn dot(&self, other: &Self) -> Sc {
199        self.0
200            .iter()
201            .zip(&other.0)
202            .map(|(a, b)| a.mul(*b))
203            .fold(Sc::zero(), |acc, x| acc.add(&x))
204    }
205
206    /// Returns the scalar projection of `self` onto `other`
207    /// (the length of the component of `self` parallel to `other`).
208    #[must_use]
209    pub fn scalar_project(&self, other: &Self) -> Sc
210    where
211        Sc: Div<Sc, Output = Sc>,
212    {
213        self.dot(other) / other.dot(other)
214    }
215    /// Returns the vector projection of `self` onto `other`
216    /// (the vector component of `self` parallel to `other`).
217    /// ```text
218    ///            self
219    ///            ^
220    ///           /.
221    ///         /  .
222    ///       /    .
223    ///     /      .
224    ///   /       _.
225    ///  +-------'->-----> other
226    ///         result
227    /// ```
228    #[must_use]
229    pub fn vector_project(&self, other: &Self) -> Self
230    where
231        Sc: Div<Sc, Output = Sc>,
232    {
233        other.mul(self.scalar_project(other))
234    }
235
236    /// Reflects `self` across a line.
237    ///
238    /// # Examples
239    /// ```
240    /// use retrofire_core::math::{Vec3, vec3};
241    ///
242    /// let axis: Vec3 = vec3(1.0, 1.0, 0.0);
243    /// let v = vec3(3.0, 2.0, -1.0);
244    ///
245    /// assert_eq!(v.reflect(axis), vec3(2.0, 3.0, 1.0));
246    /// ```
247    pub fn reflect(self, other: Self) -> Self
248    where
249        Sc: Div<Sc, Output = Sc>,
250    {
251        let proj_on_other = self.vector_project(&other);
252        proj_on_other + proj_on_other - self
253    }
254}
255
256impl<Sc: Copy, Sp, const N: usize> Vector<[Sc; N], Sp> {
257    /// Returns a vector of the same dimension as `self` by applying `f`
258    /// component-wise.
259    ///
260    /// # Examples
261    /// ```
262    /// use retrofire_core::math::{Vec3i, vec3};
263    ///
264    /// let v: Vec3i = vec3(1, 2, 3);
265    /// assert_eq!(v.map(|x| x as f32 + 0.5), vec3(1.5, 2.5, 3.5));
266    /// ```
267    #[inline]
268    #[must_use]
269    pub fn map<T>(self, mut f: impl FnMut(Sc) -> T) -> Vector<[T; N], Sp> {
270        array::from_fn(|i| f(self.0[i])).into()
271    }
272    /// Returns a vector of the same dimension as `self` by applying `f`
273    /// component-wise to `self` and `other`.
274    ///
275    /// # Examples
276    /// ```
277    /// use retrofire_core::math::vec3;
278    ///
279    /// let a = vec3::<f32, ()>(1.0, 2.0, 3.0);
280    /// let b = vec3(4, 3, 2);
281    /// assert_eq!(a.zip_map(b, |x, exp| x.powi(exp)), vec3(1.0, 8.0, 9.0));
282    /// ```
283    #[inline]
284    #[must_use]
285    pub fn zip_map<T: Copy, U>(
286        self,
287        other: Vector<[T; N], Sp>,
288        mut f: impl FnMut(Sc, T) -> U,
289    ) -> Vector<[U; N], Sp> {
290        array::from_fn(|i| f(self.0[i], other.0[i])).into()
291    }
292}
293
294impl<R, Sc, B> Vector<R, Real<2, B>>
295where
296    R: Index<usize, Output = Sc>,
297    Sc: Copy,
298{
299    /// Returns the x component of `self`.
300    #[inline]
301    pub fn x(&self) -> Sc {
302        self.0[0]
303    }
304    /// Returns the y component of `self`.
305    #[inline]
306    pub fn y(&self) -> Sc {
307        self.0[1]
308    }
309}
310
311// TODO Make more general - requires a "Scalar::one()" method
312impl<B> Vec2<B> {
313    /// Unit vector codirectional with the positive x-axis.
314    pub const X: Self = vec2(1.0, 0.0);
315
316    /// Unit vector codirectional with the positive y-axis.
317    pub const Y: Self = vec2(0.0, 1.0);
318
319    /// Converts `self` into a `Vec3`, with z set to 0.
320    pub fn to_vec3(self) -> Vec3<B> {
321        vec3(self.x(), self.y(), 0.0)
322    }
323
324    /// Returns `self` rotated 90° counter-clockwise.
325    ///
326    /// # Examples
327    /// ```
328    /// use retrofire_core::math::Vec2;
329    ///
330    /// assert_eq!(<Vec2>::X.perp(), Vec2::Y);
331    /// assert_eq!(<Vec2>::Y.perp(), -Vec2::X);
332    /// ```
333    #[inline]
334    pub fn perp(self) -> Self {
335        vec2(-self.y(), self.x())
336    }
337
338    /// Returns the "perpendicular dot product" of `self` and `other`.
339    ///
340    /// This operation is also called the "2D cross product". Like its 3D analog,
341    /// it satisfies the following identity:
342    ///
343    /// **a**<sup>⟂</sup> · **b** = |**a**| |**b**| sin *θ*,
344    ///
345    /// where *θ* is the (signed) angle between **a** and **b**. In particular,
346    /// the result is zero if **a** and **b** are parallel (or either is zero),
347    /// positive if the angle from **a** to **b** is positive, and negative if
348    /// the angle is negative:
349    ///
350    /// ```text
351    ///       ^ b               ^ a
352    ///      /           ^ b   /        ^ a
353    ///     ^ a           \   /          \
354    ///    /               \ /            \
355    ///   O                 O              O-----> b
356    ///
357    ///  a⟂·b = 0        a⟂·b > 0       a⟂·b < 0
358    /// ```
359    ///
360    /// # Examples
361    /// ```
362    /// use retrofire_core::math::{vec2, Vec2};
363    /// let v: Vec2 = vec2(2.0, 1.0);
364    ///
365    /// assert_eq!(v.perp_dot(3.0 * v),  0.0, "v and 3*v are parallel");
366    /// assert_eq!(v.perp_dot(-v),       0.0, "v and -v are parallel");
367    /// assert!   (v.perp_dot(Vec2::X) < 0.0, "X is clockwise from v");
368    /// assert!   (v.perp_dot(Vec2::Y) > 0.0, "Y is counter-clockwise from v");
369    /// ```
370    #[inline]
371    pub fn perp_dot(self, other: Self) -> f32 {
372        self.perp().dot(&other)
373    }
374}
375
376impl<R, Sc, B> Vector<R, Real<3, B>>
377where
378    R: Index<usize, Output = Sc>,
379    Sc: Copy,
380{
381    /// Returns the x component of `self`.
382    #[inline]
383    pub fn x(&self) -> Sc {
384        self.0[0]
385    }
386    /// Returns the y component of `self`.
387    #[inline]
388    pub fn y(&self) -> Sc {
389        self.0[1]
390    }
391    /// Returns the z component of `self`.
392    #[inline]
393    pub fn z(&self) -> Sc {
394        self.0[2]
395    }
396
397    /// Returns the cross product of `self` with `other`.
398    ///
399    /// The result is a vector orthogonal with both input vectors, its length
400    /// proportional to the area of the parallelogram formed by the vectors.
401    /// Specifically, the length is given by the identity:
402    ///
403    /// ```text
404    ///     |𝗮 × 𝗯| = |𝗮| |𝗯| sin 𝜽
405    /// ```
406    ///
407    /// where |·| denotes the length of a vector and 𝜽 equals the angle
408    /// between 𝗮 and 𝗯. Specifically, the result has unit length if 𝗮 and 𝗯
409    /// are orthogonal and |𝗮| = |𝗯| = 1. The cross product can be used to
410    /// produce an *orthonormal basis* from any two non-parallel non-zero
411    /// 3-vectors.
412    ///
413    /// ```text
414    ///        ^
415    ///     r  |
416    ///     e  |
417    ///     s  |    other
418    ///     u  |     ^ - - - - - - - +
419    ///     l  |   /               /
420    ///     t  | /               /
421    ///        +--------------- > self
422    /// ```
423    pub fn cross(&self, other: &Self) -> Self
424    where
425        Sc: Linear<Scalar = Sc>,
426        [Sc; 3]: Into<Self>,
427    {
428        let (s, o) = (self, other);
429        [
430            s.y().mul(o.z()).sub(&s.z().mul(o.y())),
431            s.z().mul(o.x()).sub(&s.x().mul(o.z())),
432            s.x().mul(o.y()).sub(&s.y().mul(o.x())),
433        ]
434        .into()
435    }
436}
437
438// TODO Make more general - requires a "Scalar::one()" method
439impl<B> Vec3<B> {
440    /// Unit vector codirectional with the positive x-axis.
441    pub const X: Self = vec3(1.0, 0.0, 0.0);
442
443    /// Unit vector codirectional with the positive y-axis.
444    pub const Y: Self = vec3(0.0, 1.0, 0.0);
445
446    /// Unit vector codirectional with the positive z-axis.
447    pub const Z: Self = vec3(0.0, 0.0, 1.0);
448}
449
450impl<R, Sc> Vector<R, Proj3>
451where
452    R: Index<usize, Output = Sc>,
453    Sc: Copy,
454{
455    /// Returns the x component of `self`.
456    #[inline]
457    pub fn x(&self) -> Sc {
458        self.0[0]
459    }
460    /// Returns the y component of `self`.
461    #[inline]
462    pub fn y(&self) -> Sc {
463        self.0[1]
464    }
465    /// Returns the z component of `self`.
466    #[inline]
467    pub fn z(&self) -> Sc {
468        self.0[2]
469    }
470    /// Returns the w component of `self`.
471    #[inline]
472    pub fn w(&self) -> Sc {
473        self.0[3]
474    }
475}
476
477//
478// Local trait impls
479//
480
481impl<Sc, Sp, const DIM: usize> Affine for Vector<[Sc; DIM], Sp>
482where
483    Sc: Linear<Scalar = Sc> + Copy,
484{
485    type Space = Sp;
486    type Diff = Self;
487
488    /// The dimension (number of components) of `Self`.
489    const DIM: usize = DIM;
490
491    #[inline]
492    fn add(&self, other: &Self) -> Self {
493        // TODO Profile performance of array::from_fn
494        Self(array::from_fn(|i| self.0[i].add(&other.0[i])), Pd)
495    }
496    #[inline]
497    fn sub(&self, other: &Self) -> Self {
498        Self(array::from_fn(|i| self.0[i].sub(&other.0[i])), Pd)
499    }
500}
501
502impl<Sc, Sp, const DIM: usize> Linear for Vector<[Sc; DIM], Sp>
503where
504    Sc: Linear<Scalar = Sc> + Copy,
505{
506    type Scalar = Sc;
507
508    /// Returns a vector with all-zero components, also called a zero vector.
509    #[inline]
510    fn zero() -> Self {
511        Self([Sc::zero(); DIM], Pd)
512    }
513    #[inline]
514    fn mul(&self, scalar: Sc) -> Self {
515        self.map(|c| c.mul(scalar))
516    }
517}
518
519impl<Sc, Sp, const N: usize> ZDiv for Vector<[Sc; N], Sp>
520where
521    Sc: ZDiv + Copy,
522{
523    fn z_div(self, z: f32) -> Self {
524        self.map(|c| c.z_div(z))
525    }
526}
527
528impl<Sc: ApproxEq, Sp, const N: usize> ApproxEq<Self, Sc>
529    for Vector<[Sc; N], Sp>
530{
531    fn approx_eq_eps(&self, other: &Self, eps: &Sc) -> bool {
532        self.0.approx_eq_eps(&other.0, eps)
533    }
534    fn relative_epsilon() -> Sc {
535        Sc::relative_epsilon()
536    }
537}
538
539//
540// Foreign trait impls
541//
542
543// Manual impls of Copy, Clone, Default, Eq, and PartialEq
544// to avoid superfluous where S: Trait bound
545
546impl<R: Copy, S> Copy for Vector<R, S> {}
547
548impl<R: Clone, S> Clone for Vector<R, S> {
549    fn clone(&self) -> Self {
550        Self(self.0.clone(), Pd)
551    }
552}
553
554impl<R: Default, B, const DIM: usize> Default for Vector<R, Real<DIM, B>> {
555    fn default() -> Self {
556        Self(R::default(), Pd)
557    }
558}
559
560impl<R: Eq, S> Eq for Vector<R, S> {}
561
562impl<R: PartialEq, S> PartialEq for Vector<R, S> {
563    fn eq(&self, other: &Self) -> bool {
564        self.0 == other.0
565    }
566}
567
568impl<R: Debug, Sp: Debug + Default> Debug for Vector<R, Sp> {
569    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
570        write!(f, "Vec<{:?}>", Sp::default())?;
571        Debug::fmt(&self.0, f)
572    }
573}
574
575impl<R, Sp> From<R> for Vector<R, Sp> {
576    #[inline]
577    fn from(repr: R) -> Self {
578        Self(repr, Pd)
579    }
580}
581
582impl<Sp, Sc: Clone, const DIM: usize> From<Sc> for Vector<[Sc; DIM], Sp> {
583    /// Returns a vector with all components equal to `scalar`.
584    ///
585    /// This operation is also called "splat" or "broadcast".
586    #[inline]
587    fn from(scalar: Sc) -> Self {
588        splat(scalar)
589    }
590}
591/*
592impl<B> From<Vec2<B>> for HomVec2<B> {
593    fn from(v: Vec2<B>) -> Self {
594        let [x, y] = v.0;
595        [x, y, 0.0].into()
596    }
597}
598impl<B> From<Vec3<B>> for HomVec3<B> {
599    fn from(v: Vec3<B>) -> Self {
600        let [x, y, z] = v.0;
601        [x, y, z, 0.0].into()
602    }
603}
604*/
605impl<R, Sp> Index<usize> for Vector<R, Sp>
606where
607    Self: Affine,
608    R: Index<usize>,
609{
610    type Output = R::Output;
611
612    /// Returns the component of `self` with index `i`.
613    ///
614    /// # Panics
615    /// If `i >= Self::DIM`.
616    /// Note that `Self::DIM` can be less than the number of elements in `R`.
617    #[inline]
618    fn index(&self, i: usize) -> &Self::Output {
619        assert!(i < Self::DIM, "index {i} out of bounds ({})", Self::DIM);
620        &self.0[i]
621    }
622}
623
624impl<R, Sp> IndexMut<usize> for Vector<R, Sp>
625where
626    Self: Affine,
627    R: IndexMut<usize>,
628{
629    /// Returns a mutable reference to the component of `self` with index `i`.
630    ///
631    /// # Panics
632    /// If `i >= Self::DIM`.
633    /// Note that `Self::DIM` can be less than the number of elements in `R`.
634    #[inline]
635    fn index_mut(&mut self, i: usize) -> &mut Self::Output {
636        assert!(i < Self::DIM, "index {i} out of bounds ({})", Self::DIM);
637        &mut self.0[i]
638    }
639}
640
641impl<R, Sp> Sum for Vector<R, Sp>
642where
643    Self: Linear,
644{
645    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
646        iter.fold(Self::zero(), |acc, v| Affine::add(&acc, &v))
647    }
648}
649
650//
651// Arithmetic traits
652//
653
654/// The vector += vector operator.
655impl<R, Sp> AddAssign<<Self as Affine>::Diff> for Vector<R, Sp>
656where
657    Self: Affine,
658{
659    #[inline]
660    fn add_assign(&mut self, rhs: <Self as Affine>::Diff) {
661        *self = Affine::add(&*self, &rhs);
662    }
663}
664
665/// The vector -= vector operator.
666impl<R, Sp> SubAssign<<Self as Affine>::Diff> for Vector<R, Sp>
667where
668    Self: Affine,
669{
670    #[inline]
671    fn sub_assign(&mut self, rhs: <Self as Affine>::Diff) {
672        *self = Affine::add(&*self, &rhs.neg());
673    }
674}
675
676// The vector *= scalar operator.
677impl<R, Sp> MulAssign<<Self as Linear>::Scalar> for Vector<R, Sp>
678where
679    Self: Linear,
680{
681    #[inline]
682    fn mul_assign(&mut self, rhs: <Self as Linear>::Scalar) {
683        *self = Linear::mul(&*self, rhs);
684    }
685}
686
687// The vector /= scalar operator.
688impl<R, Sp> DivAssign<f32> for Vector<R, Sp>
689where
690    Self: Linear<Scalar = f32>,
691{
692    #[inline]
693    fn div_assign(&mut self, rhs: f32) {
694        debug_assert!(!rhs.approx_eq(&0.0), "divisor {rhs} < epsilon");
695        *self = Linear::mul(&*self, rhs.recip());
696    }
697}
698
699/// The vector negation operator.
700impl<R, Sp> Neg for Vector<R, Sp>
701where
702    Self: Linear,
703{
704    type Output = Self;
705
706    #[inline]
707    fn neg(self) -> Self::Output {
708        <Self as Linear>::neg(&self)
709    }
710}
711
712impl<R, Sp> Mul<Vector<R, Sp>> for f32
713where
714    Vector<R, Sp>: Linear<Scalar = f32>,
715{
716    type Output = Vector<R, Sp>;
717
718    #[inline]
719    fn mul(self, rhs: Vector<R, Sp>) -> Self::Output {
720        rhs * self
721    }
722}
723impl<R, Sp> Mul<Vector<R, Sp>> for i32
724where
725    Vector<R, Sp>: Linear<Scalar = i32>,
726{
727    type Output = Vector<R, Sp>;
728
729    #[inline]
730    fn mul(self, rhs: Vector<R, Sp>) -> Self::Output {
731        rhs * self
732    }
733}
734impl<R, Sp> Mul<Vector<R, Sp>> for u32
735where
736    Vector<R, Sp>: Linear<Scalar = u32>,
737{
738    type Output = Vector<R, Sp>;
739
740    #[inline]
741    fn mul(self, rhs: Vector<R, Sp>) -> Self::Output {
742        rhs * self
743    }
744}
745
746// The vector + vector operator.
747impl_op!(Add::add, Vector, <Self as Affine>::Diff, +=, bound=Affine);
748// The vector - vector operator.
749impl_op!(Sub::sub, Vector, <Self as Affine>::Diff, -=, bound=Affine);
750// The vector * scalar operator.
751impl_op!(Mul::mul, Vector, <Self as Linear>::Scalar, *=);
752// The vector / scalar operator.
753impl_op!(Div::div, Vector, f32, /=, bound=Linear<Scalar = f32>);
754
755//
756// Unit tests
757//
758
759#[cfg(test)]
760mod tests {
761    use core::f32::consts::*;
762
763    use crate::assert_approx_eq;
764
765    use super::*;
766
767    pub const fn vec2<S>(x: S, y: S) -> Vector<[S; 2], Real<2>> {
768        super::vec2(x, y)
769    }
770    pub const fn vec3<S>(x: S, y: S, z: S) -> Vector<[S; 3], Real<3>> {
771        super::vec3(x, y, z)
772    }
773    pub const fn vec4<S>(x: S, y: S, z: S, w: S) -> Vector<[S; 4], Real<4>> {
774        Vector::new([x, y, z, w])
775    }
776
777    mod f32 {
778        use super::*;
779
780        #[cfg(feature = "fp")]
781        #[test]
782        fn length() {
783            assert_approx_eq!(vec2(1.0, 1.0).len(), SQRT_2);
784            assert_approx_eq!(vec2(-3.0, 4.0).len(), 5.0);
785            assert_approx_eq!(vec3(1.0, -2.0, 3.0).len(), 14.0f32.sqrt());
786        }
787
788        #[test]
789        fn length_squared() {
790            assert_eq!(vec2(1.0, 1.0).len_sqr(), 2.0);
791            assert_eq!(vec2(-4.0, 3.0).len_sqr(), 25.0);
792            assert_eq!(vec3(1.0, -2.0, 3.0).len_sqr(), 14.0);
793        }
794
795        #[test]
796        fn normalize() {
797            assert_approx_eq!(vec2(3.0, 4.0).normalize(), vec2(0.6, 0.8));
798
799            let sqrt_14 = 14.0f32.sqrt();
800            assert_approx_eq!(
801                vec3(1.0, 2.0, 3.0).normalize(),
802                vec3(1.0 / sqrt_14, 2.0 / sqrt_14, 3.0 / sqrt_14)
803            );
804        }
805
806        #[test]
807        fn vector_addition() {
808            assert_eq!(vec2(1.0, 2.0) + vec2(-2.0, 1.0), vec2(-1.0, 3.0));
809            assert_eq!(
810                vec3(1.0, 2.0, 0.0) + vec3(-2.0, 1.0, -1.0),
811                vec3(-1.0, 3.0, -1.0)
812            );
813        }
814
815        #[test]
816        fn scalar_multiplication() {
817            assert_eq!(vec2(1.0, -2.0) * 0.0, vec2(0.0, 0.0));
818            assert_eq!(vec3(1.0, -2.0, 3.0) * 3.0, vec3(3.0, -6.0, 9.0));
819            assert_eq!(3.0 * vec3(1.0, -2.0, 3.0), vec3(3.0, -6.0, 9.0));
820            assert_eq!(
821                vec4(1.0, -2.0, 0.0, -3.0) * 3.0,
822                vec4(3.0, -6.0, 0.0, -9.0)
823            );
824            assert_eq!(
825                3.0 * vec4(1.0, -2.0, 0.0, -3.0),
826                vec4(3.0, -6.0, 0.0, -9.0)
827            );
828        }
829
830        #[test]
831        fn scalar_division() {
832            assert_eq!(vec2(1.0, -2.0) / 1.0, vec2(1.0, -2.0));
833            assert_eq!(vec3(3.0, -6.0, 9.0) / 3.0, vec3(1.0, -2.0, 3.0));
834            assert_eq!(
835                vec4(3.0, -6.0, 0.0, -9.0) / 3.0,
836                vec4(1.0, -2.0, 0.0, -3.0)
837            );
838        }
839
840        #[test]
841        fn dot_product() {
842            assert_eq!(vec2(1.0, -2.0).dot(&vec2(2.0, 3.0)), -4.0);
843            assert_eq!(vec3(1.0, -2.0, 3.0).dot(&vec3(2.0, 3.0, -1.0)), -7.0);
844        }
845
846        #[test]
847        fn indexing() {
848            let mut v = vec2(1.0, 2.0);
849            assert_eq!(v[1], 2.0);
850            v[0] = 3.0;
851            assert_eq!(v.0, [3.0, 2.0]);
852
853            let mut v = vec3(1.0, 2.0, 3.0);
854            assert_eq!(v[1], 2.0);
855            v[2] = 4.0;
856            assert_eq!(v.0, [1.0, 2.0, 4.0]);
857        }
858
859        #[test]
860        fn from_array() {
861            assert_eq!(Vec2::from([1.0, -2.0]), vec2(1.0, -2.0));
862            assert_eq!(Vec3::from([1.0, -2.0, 4.0]), vec3(1.0, -2.0, 4.0));
863            assert_eq!(
864                Vector::from([1.0, -2.0, 4.0, -3.0]),
865                vec4(1.0, -2.0, 4.0, -3.0)
866            );
867        }
868
869        #[test]
870        fn perp() {
871            assert_eq!(Vec2::<()>::zero().perp(), Vec2::zero());
872            assert_eq!(Vec2::<()>::X.perp(), Vec2::Y);
873            assert_eq!(vec2(-0.2, -1.5).perp(), vec2(1.5, -0.2));
874        }
875
876        #[test]
877        fn perp_dot() {
878            const X: Vec2 = Vec2::X;
879            const Y: Vec2 = Vec2::Y;
880
881            assert_eq!(X.perp_dot(X), 0.0);
882            assert_eq!(X.perp_dot(Y), 1.0);
883            assert_eq!((2.0 * Y).perp_dot(3.0 * X), -6.0);
884        }
885    }
886
887    mod i32 {
888        use super::*;
889
890        #[test]
891        fn vector_addition() {
892            assert_eq!(vec2(1, 2) + vec2(-2, 1), vec2(-1, 3));
893            assert_eq!(vec3(1, 2, 0) + vec3(-2, 1, -1), vec3(-1, 3, -1));
894        }
895
896        #[test]
897        fn vector_subtraction() {
898            assert_eq!(vec2(1, 2) - vec2(-2, 3), vec2(3, -1));
899            assert_eq!(vec3(1, 2, 0) - vec3(-2, 1, 2), vec3(3, 1, -2));
900        }
901
902        #[test]
903        #[allow(clippy::erasing_op)]
904        fn scalar_multiplication() {
905            assert_eq!(vec2(1, -2) * 0, vec2(0, 0));
906
907            assert_eq!(vec3(1, -2, 3) * 3, vec3(3, -6, 9));
908            assert_eq!(3 * vec3(1, -2, 3), vec3(3, -6, 9));
909
910            assert_eq!(vec4(1, -2, 0, -3) * 3, vec4(3, -6, 0, -9));
911            assert_eq!(3 * vec4(1, -2, 0, -3), vec4(3, -6, 0, -9));
912        }
913
914        #[test]
915        fn dot_product() {
916            assert_eq!(vec2(1, -2).dot(&vec2(2, 3)), -4);
917            assert_eq!(vec3(1, -2, 3).dot(&vec3(2, 3, -1)), -7);
918        }
919
920        #[test]
921        fn indexing() {
922            let mut v = vec2(1, 2);
923            assert_eq!(v[1], 2);
924            v[0] = 3;
925            assert_eq!(v.0, [3, 2]);
926
927            let mut v = vec3(1, 2, 3);
928            assert_eq!(v[1], 2);
929            v[2] = 4;
930            assert_eq!(v.0, [1, 2, 4]);
931        }
932
933        #[test]
934        fn from_array() {
935            assert_eq!(Vec2i::from([1, -2]), vec2(1, -2));
936            assert_eq!(Vec3i::from([1, -2, 3]), vec3(1, -2, 3));
937        }
938    }
939
940    const X: Vec3 = Vec3::X;
941    const Y: Vec3 = Vec3::Y;
942    const Z: Vec3 = Vec3::Z;
943
944    #[test]
945    fn cross_product_basis_vectors() {
946        assert_eq!(X.cross(&Y), Z);
947        assert_eq!(Y.cross(&X), -Z);
948
949        assert_eq!(Y.cross(&Z), X);
950        assert_eq!(Z.cross(&Y), -X);
951
952        assert_eq!(Z.cross(&X), Y);
953        assert_eq!(X.cross(&Z), -Y);
954    }
955
956    #[test]
957    fn cross_product_parallelogram_area() {
958        let a = 3.0 * Y;
959        let b = 2.0 * X - Y;
960        assert_eq!(a.cross(&b).len_sqr(), 6.0 * 6.0);
961    }
962
963    #[test]
964    fn iterator_sum() {
965        let vs = [vec2(-1.0, 2.0), vec2(0.0, 2.0), vec2(3.0, -1.0)];
966        assert_eq!(vs.into_iter().sum::<Vec2>(), vec2(2.0, 3.0));
967    }
968
969    #[test]
970    fn approx_equal_pass() {
971        assert_approx_eq!(vec2(1.0, -10.0), vec2(1.01, -9.9), eps = 0.011);
972    }
973    #[test]
974    #[should_panic]
975    fn approx_equal_fail() {
976        let eps = 2.0 * f32::relative_epsilon();
977        assert_approx_eq!(vec2(1.0, -10.0), vec2(1.0 + eps, -10.0 - eps));
978    }
979
980    // TODO Tests for projections
981
982    #[test]
983    fn debug() {
984        assert_eq!(
985            alloc::format!("{:?}", vec2(1.0, -E)),
986            "Vec<ℝ²<()>>[1.0, -2.7182817]"
987        );
988        assert_eq!(
989            alloc::format!("{:?}", vec3(1.0, -2.0, 3.0)),
990            "Vec<ℝ³<()>>[1.0, -2.0, 3.0]"
991        );
992        assert_eq!(
993            alloc::format!("{:?}", vec4(1.0, -2.0, PI, -4.0)),
994            "Vec<ℝ⁴<()>>[1.0, -2.0, 3.1415927, -4.0]"
995        );
996    }
997}