Skip to main content

vita_core/tensor/
vector.rs

1use core::iter::Sum;
2use core::ops::{
3    Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign,
4};
5
6use crate::Scalar;
7
8/// A vector of three components `x`, `y`, and `z`.
9pub struct Vector3<T> {
10    /// The first component.
11    pub x: T,
12    /// The second component.
13    pub y: T,
14    /// The third component.
15    pub z: T,
16}
17
18impl<T: ::core::marker::Copy> ::core::marker::Copy for Vector3<T> {}
19
20impl<T: ::core::clone::Clone> ::core::clone::Clone for Vector3<T> {
21    #[inline]
22    fn clone(&self) -> Self {
23        Self {
24            x: self.x.clone(),
25            y: self.y.clone(),
26            z: self.z.clone(),
27        }
28    }
29}
30
31impl<T: ::core::fmt::Debug> ::core::fmt::Debug for Vector3<T> {
32    fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
33        f.debug_struct("Vector3")
34            .field("x", &self.x)
35            .field("y", &self.y)
36            .field("z", &self.z)
37            .finish()
38    }
39}
40
41impl<T: ::core::cmp::PartialEq> ::core::cmp::PartialEq for Vector3<T> {
42    #[inline]
43    fn eq(&self, other: &Self) -> bool {
44        self.x == other.x && self.y == other.y && self.z == other.z
45    }
46}
47
48impl<T> Vector3<T> {
49    /// Constructs a vector from its three components.
50    #[inline]
51    pub const fn new(x: T, y: T, z: T) -> Self {
52        Self { x, y, z }
53    }
54
55    /// Constructs a vector from an array `[x, y, z]`.
56    #[inline]
57    pub fn from_array(array: [T; 3]) -> Self {
58        let [x, y, z] = array;
59        Self { x, y, z }
60    }
61
62    /// Returns the components as an array `[x, y, z]`.
63    #[inline]
64    pub fn to_array(self) -> [T; 3] {
65        [self.x, self.y, self.z]
66    }
67
68    /// Returns a copy of `self` with the `x` component replaced.
69    #[inline]
70    pub fn with_x(self, x: T) -> Self {
71        Self {
72            x,
73            y: self.y,
74            z: self.z,
75        }
76    }
77
78    /// Returns a copy of `self` with the `y` component replaced.
79    #[inline]
80    pub fn with_y(self, y: T) -> Self {
81        Self {
82            x: self.x,
83            y,
84            z: self.z,
85        }
86    }
87
88    /// Returns a copy of `self` with the `z` component replaced.
89    #[inline]
90    pub fn with_z(self, z: T) -> Self {
91        Self {
92            x: self.x,
93            y: self.y,
94            z,
95        }
96    }
97
98    /// Applies `f` to every component, returning the resulting vector.
99    #[inline]
100    pub fn map<U, F: FnMut(T) -> U>(self, mut f: F) -> Vector3<U> {
101        Vector3 {
102            x: f(self.x),
103            y: f(self.y),
104            z: f(self.z),
105        }
106    }
107
108    /// Combines `self` and `rhs` component-wise through `f`.
109    #[inline]
110    pub fn zip_map<U, R, F: FnMut(T, U) -> R>(self, rhs: Vector3<U>, mut f: F) -> Vector3<R> {
111        Vector3 {
112            x: f(self.x, rhs.x),
113            y: f(self.y, rhs.y),
114            z: f(self.z, rhs.z),
115        }
116    }
117}
118
119impl<T: Copy> Vector3<T> {
120    /// Constructs a vector with all three components set to `value`.
121    #[inline]
122    pub const fn splat(value: T) -> Self {
123        Self {
124            x: value,
125            y: value,
126            z: value,
127        }
128    }
129
130    /// Constructs a vector from the first three elements of a slice.
131    ///
132    /// # Panics
133    ///
134    /// Panics if `slice` has fewer than three elements.
135    #[inline]
136    pub fn from_slice(slice: &[T]) -> Self {
137        Self {
138            x: slice[0],
139            y: slice[1],
140            z: slice[2],
141        }
142    }
143}
144
145impl<T> Index<usize> for Vector3<T> {
146    type Output = T;
147
148    /// Returns the component at `index`, where `0`, `1`, and `2` map to `x`,
149    /// `y`, and `z`.
150    ///
151    /// # Panics
152    ///
153    /// Panics if `index` is greater than `2`.
154    #[inline]
155    fn index(&self, index: usize) -> &T {
156        match index {
157            0 => &self.x,
158            1 => &self.y,
159            2 => &self.z,
160            _ => panic!("index out of bounds: Vector3 has 3 components but the index is {index}"),
161        }
162    }
163}
164
165impl<T> IndexMut<usize> for Vector3<T> {
166    /// Returns the component at `index`, where `0`, `1`, and `2` map to `x`,
167    /// `y`, and `z`.
168    ///
169    /// # Panics
170    ///
171    /// Panics if `index` is greater than `2`.
172    #[inline]
173    fn index_mut(&mut self, index: usize) -> &mut T {
174        match index {
175            0 => &mut self.x,
176            1 => &mut self.y,
177            2 => &mut self.z,
178            _ => panic!("index out of bounds: Vector3 has 3 components but the index is {index}"),
179        }
180    }
181}
182
183impl<T: Default> Default for Vector3<T> {
184    /// Returns the zero vector.
185    #[inline]
186    fn default() -> Self {
187        Self {
188            x: T::default(),
189            y: T::default(),
190            z: T::default(),
191        }
192    }
193}
194
195impl<T: Neg<Output = T>> Neg for Vector3<T> {
196    type Output = Self;
197    /// Returns the component-wise negation of `self`.
198    #[inline]
199    fn neg(self) -> Self {
200        Self::new(-self.x, -self.y, -self.z)
201    }
202}
203
204impl<T: Add<Output = T>> Add for Vector3<T> {
205    type Output = Self;
206    /// Returns the component-wise sum of `self` and `rhs`.
207    #[inline]
208    fn add(self, rhs: Self) -> Self {
209        Self::new(self.x + rhs.x, self.y + rhs.y, self.z + rhs.z)
210    }
211}
212
213impl<T: AddAssign> AddAssign for Vector3<T> {
214    #[inline]
215    fn add_assign(&mut self, rhs: Self) {
216        self.x += rhs.x;
217        self.y += rhs.y;
218        self.z += rhs.z;
219    }
220}
221
222impl<T: Sub<Output = T>> Sub for Vector3<T> {
223    type Output = Self;
224    /// Returns the component-wise difference of `self` and `rhs`.
225    #[inline]
226    fn sub(self, rhs: Self) -> Self {
227        Self::new(self.x - rhs.x, self.y - rhs.y, self.z - rhs.z)
228    }
229}
230
231impl<T: SubAssign> SubAssign for Vector3<T> {
232    #[inline]
233    fn sub_assign(&mut self, rhs: Self) {
234        self.x -= rhs.x;
235        self.y -= rhs.y;
236        self.z -= rhs.z;
237    }
238}
239
240impl<T, S: Scalar> Mul<S> for Vector3<T>
241where
242    T: Mul<S, Output = T>,
243{
244    type Output = Self;
245    /// Scales every component by the scalar `rhs`, preserving the element's unit.
246    #[inline]
247    fn mul(self, rhs: S) -> Self {
248        Self::new(self.x * rhs, self.y * rhs, self.z * rhs)
249    }
250}
251
252impl<T, S: Scalar> MulAssign<S> for Vector3<T>
253where
254    T: MulAssign<S>,
255{
256    #[inline]
257    fn mul_assign(&mut self, rhs: S) {
258        self.x *= rhs;
259        self.y *= rhs;
260        self.z *= rhs;
261    }
262}
263
264impl<T, S: Scalar> Div<S> for Vector3<T>
265where
266    T: Div<S, Output = T>,
267{
268    type Output = Self;
269    /// Divides every component by the scalar `rhs`, preserving the element's unit.
270    #[inline]
271    fn div(self, rhs: S) -> Self {
272        Self::new(self.x / rhs, self.y / rhs, self.z / rhs)
273    }
274}
275
276impl<T, S: Scalar> DivAssign<S> for Vector3<T>
277where
278    T: DivAssign<S>,
279{
280    #[inline]
281    fn div_assign(&mut self, rhs: S) {
282        self.x /= rhs;
283        self.y /= rhs;
284        self.z /= rhs;
285    }
286}
287
288impl<T: Add<Output = T> + Default + Copy> Sum for Vector3<T> {
289    #[inline]
290    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
291        iter.fold(Self::default(), |acc, v| acc + v)
292    }
293}
294
295impl<'a, T: Add<Output = T> + Default + Copy> Sum<&'a Vector3<T>> for Vector3<T> {
296    #[inline]
297    fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
298        iter.copied().fold(Self::default(), |acc, v| acc + v)
299    }
300}
301
302impl<T: Add<Output = T>> Vector3<T> {
303    /// Returns the sum of the three components, `x + y + z`.
304    #[inline]
305    pub fn element_sum(self) -> T {
306        self.x + self.y + self.z
307    }
308}
309
310impl<T: Add<Output = T> + Sub<Output = T> + Copy> Vector3<T> {
311    /// Linearly interpolates from `self` toward `rhs` by the factor `t`.
312    ///
313    /// `t == 0` yields `self`, `t == 1` yields `rhs`.
314    #[inline]
315    pub fn lerp<S: Scalar>(self, rhs: Self, t: S) -> Self
316    where
317        T: Mul<S, Output = T>,
318    {
319        self + (rhs - self) * t
320    }
321}
322
323impl<V: Scalar> Vector3<V> {
324    /// The zero vector, `(0, 0, 0)`.
325    pub const ZERO: Self = Self::new(V::ZERO, V::ZERO, V::ZERO);
326
327    /// The vector with every component set to one, `(1, 1, 1)`.
328    pub const ONE: Self = Self::new(V::ONE, V::ONE, V::ONE);
329
330    /// The unit vector along the `x` axis, `(1, 0, 0)`.
331    pub const X: Self = Self::new(V::ONE, V::ZERO, V::ZERO);
332
333    /// The unit vector along the `y` axis, `(0, 1, 0)`.
334    pub const Y: Self = Self::new(V::ZERO, V::ONE, V::ZERO);
335
336    /// The unit vector along the `z` axis, `(0, 0, 1)`.
337    pub const Z: Self = Self::new(V::ZERO, V::ZERO, V::ONE);
338
339    /// Returns the dot product `self · rhs`.
340    #[inline]
341    pub fn dot(self, rhs: Self) -> V {
342        self.x * rhs.x + self.y * rhs.y + self.z * rhs.z
343    }
344
345    /// Returns the cross product `self × rhs`.
346    #[inline]
347    pub fn cross(self, rhs: Self) -> Self {
348        Self::new(
349            self.y * rhs.z - self.z * rhs.y,
350            self.z * rhs.x - self.x * rhs.z,
351            self.x * rhs.y - self.y * rhs.x,
352        )
353    }
354
355    /// Returns the squared Euclidean norm `self · self`.
356    ///
357    /// Cheaper than [`norm`][Self::norm] and sufficient whenever only relative
358    /// magnitudes are compared.
359    #[inline]
360    pub fn norm_squared(self) -> V {
361        self.dot(self)
362    }
363
364    /// Returns the Euclidean norm (length) of the vector.
365    #[inline]
366    pub fn norm(self) -> V {
367        self.norm_squared().sqrt()
368    }
369
370    /// Returns `self` rescaled to unit length.
371    ///
372    /// Yields a non-finite vector when the norm is zero or non-finite; use
373    /// [`try_normalize`][Self::try_normalize] or
374    /// [`normalize_or_zero`][Self::normalize_or_zero] to handle those cases.
375    #[inline]
376    pub fn normalize(self) -> Self {
377        self / self.norm()
378    }
379
380    /// Returns `self` rescaled to unit length, or `None` if the result would
381    /// not be finite (e.g. for the zero vector).
382    #[inline]
383    pub fn try_normalize(self) -> Option<Self> {
384        let norm = self.norm();
385        if norm.is_finite() && norm > V::ZERO {
386            Some(self / norm)
387        } else {
388            None
389        }
390    }
391
392    /// Returns `self` rescaled to unit length, or the zero vector if the
393    /// result would not be finite.
394    #[inline]
395    pub fn normalize_or_zero(self) -> Self {
396        self.try_normalize().unwrap_or(Self::ZERO)
397    }
398
399    /// Returns `true` if the vector is of unit length within a small
400    /// tolerance (`2.0e-4`).
401    #[inline]
402    pub fn is_normalized(self) -> bool {
403        (self.norm_squared() - V::ONE).abs() <= V::from_f64(2.0e-4)
404    }
405
406    /// Returns the unsigned angle between `self` and `rhs`, in radians within
407    /// `[0, π]`.
408    ///
409    /// The computation is numerically stable across the whole range, including
410    /// near-parallel and near-antiparallel inputs.
411    #[inline]
412    pub fn angle_between(self, rhs: Self) -> V {
413        self.cross(rhs).norm().atan2(self.dot(rhs))
414    }
415
416    /// Returns the vector projection of `self` onto `onto`.
417    #[inline]
418    pub fn project_onto(self, onto: Self) -> Self {
419        onto * (self.dot(onto) / onto.norm_squared())
420    }
421
422    /// Returns the component of `self` orthogonal to `from`.
423    #[inline]
424    pub fn reject_from(self, from: Self) -> Self {
425        self - self.project_onto(from)
426    }
427
428    /// Reflects `self` across the plane through the origin with unit normal
429    /// `normal`.
430    #[inline]
431    pub fn reflect(self, normal: Self) -> Self {
432        self - normal * (self.dot(normal) * (V::ONE + V::ONE))
433    }
434
435    /// Returns the component-wise reciprocal `(1/x, 1/y, 1/z)`.
436    #[inline]
437    pub fn recip(self) -> Self {
438        Self::new(self.x.recip(), self.y.recip(), self.z.recip())
439    }
440
441    /// Returns the product of the three components, `x * y * z`.
442    #[inline]
443    pub fn element_product(self) -> V {
444        self.x * self.y * self.z
445    }
446
447    /// Returns the component-wise absolute value.
448    #[inline]
449    pub fn abs(self) -> Self {
450        Self::new(self.x.abs(), self.y.abs(), self.z.abs())
451    }
452
453    /// Returns the component-wise minimum of `self` and `rhs`.
454    #[inline]
455    pub fn min(self, rhs: Self) -> Self {
456        Self::new(self.x.min(rhs.x), self.y.min(rhs.y), self.z.min(rhs.z))
457    }
458
459    /// Returns the component-wise maximum of `self` and `rhs`.
460    #[inline]
461    pub fn max(self, rhs: Self) -> Self {
462        Self::new(self.x.max(rhs.x), self.y.max(rhs.y), self.z.max(rhs.z))
463    }
464
465    /// Restricts every component to the interval `[min, max]`.
466    ///
467    /// # Panics
468    ///
469    /// Panics if any component of `min` exceeds the corresponding component of
470    /// `max`.
471    #[inline]
472    pub fn clamp(self, min: Self, max: Self) -> Self {
473        Self::new(
474            self.x.clamp(min.x, max.x),
475            self.y.clamp(min.y, max.y),
476            self.z.clamp(min.z, max.z),
477        )
478    }
479
480    /// Returns the smallest of the three components.
481    #[inline]
482    pub fn min_element(self) -> V {
483        self.x.min(self.y).min(self.z)
484    }
485
486    /// Returns the largest of the three components.
487    #[inline]
488    pub fn max_element(self) -> V {
489        self.x.max(self.y).max(self.z)
490    }
491
492    /// Returns the component-wise floor.
493    #[inline]
494    pub fn floor(self) -> Self {
495        Self::new(self.x.floor(), self.y.floor(), self.z.floor())
496    }
497
498    /// Returns the component-wise ceiling.
499    #[inline]
500    pub fn ceil(self) -> Self {
501        Self::new(self.x.ceil(), self.y.ceil(), self.z.ceil())
502    }
503
504    /// Returns the component-wise nearest integer, rounding halves away from
505    /// zero.
506    #[inline]
507    pub fn round(self) -> Self {
508        Self::new(self.x.round(), self.y.round(), self.z.round())
509    }
510
511    /// Returns the component-wise nearest integer, rounding halves to even.
512    #[inline]
513    pub fn round_ties_even(self) -> Self {
514        Self::new(
515            self.x.round_ties_even(),
516            self.y.round_ties_even(),
517            self.z.round_ties_even(),
518        )
519    }
520
521    /// Returns the component-wise truncation toward zero.
522    #[inline]
523    pub fn trunc(self) -> Self {
524        Self::new(self.x.trunc(), self.y.trunc(), self.z.trunc())
525    }
526
527    /// Returns the component-wise fractional part.
528    #[inline]
529    pub fn fract(self) -> Self {
530        Self::new(self.x.fract(), self.y.fract(), self.z.fract())
531    }
532
533    /// Returns a vector with the magnitudes of `self` and the component-wise
534    /// signs of `sign`.
535    #[inline]
536    pub fn copysign(self, sign: Self) -> Self {
537        Self::new(
538            self.x.copysign(sign.x),
539            self.y.copysign(sign.y),
540            self.z.copysign(sign.z),
541        )
542    }
543
544    /// Returns the component-wise sign, each `1`, `-1`, or `NaN`.
545    #[inline]
546    pub fn signum(self) -> Self {
547        Self::new(self.x.signum(), self.y.signum(), self.z.signum())
548    }
549
550    /// Returns the component-wise least nonnegative remainder against `rhs`.
551    #[inline]
552    pub fn rem_euclid(self, rhs: Self) -> Self {
553        Self::new(
554            self.x.rem_euclid(rhs.x),
555            self.y.rem_euclid(rhs.y),
556            self.z.rem_euclid(rhs.z),
557        )
558    }
559
560    /// Returns `true` if every component is finite.
561    #[inline]
562    pub fn is_finite(self) -> bool {
563        self.x.is_finite() && self.y.is_finite() && self.z.is_finite()
564    }
565
566    /// Returns `true` if any component is positive or negative infinity.
567    #[inline]
568    pub fn is_infinite(self) -> bool {
569        self.x.is_infinite() || self.y.is_infinite() || self.z.is_infinite()
570    }
571
572    /// Returns `true` if any component is `NaN`.
573    #[inline]
574    pub fn is_nan(self) -> bool {
575        self.x.is_nan() || self.y.is_nan() || self.z.is_nan()
576    }
577}
578
579#[cfg(test)]
580mod tests {
581    use super::*;
582    use core::f64::consts::FRAC_PI_2;
583    use core::iter;
584
585    #[test]
586    fn new() {
587        let v = Vector3::new(1.0, 2.0, 3.0);
588        assert_eq!((v.x, v.y, v.z), (1.0, 2.0, 3.0));
589    }
590
591    #[test]
592    fn from_array() {
593        assert_eq!(
594            Vector3::from_array([1.0, 2.0, 3.0]),
595            Vector3::new(1.0, 2.0, 3.0)
596        );
597    }
598
599    #[test]
600    fn to_array() {
601        assert_eq!(Vector3::new(1.0, 2.0, 3.0).to_array(), [1.0, 2.0, 3.0]);
602    }
603
604    #[test]
605    fn splat() {
606        assert_eq!(Vector3::splat(5.0), Vector3::new(5.0, 5.0, 5.0));
607    }
608
609    #[test]
610    fn from_slice() {
611        assert_eq!(
612            Vector3::from_slice(&[1.0, 2.0, 3.0, 4.0]),
613            Vector3::new(1.0, 2.0, 3.0)
614        );
615    }
616
617    #[test]
618    #[should_panic]
619    fn from_slice_panics_when_too_short() {
620        Vector3::<f64>::from_slice(&[1.0, 2.0]);
621    }
622
623    #[test]
624    fn with_x() {
625        assert_eq!(
626            Vector3::new(1.0, 2.0, 3.0).with_x(9.0),
627            Vector3::new(9.0, 2.0, 3.0)
628        );
629    }
630
631    #[test]
632    fn with_y() {
633        assert_eq!(
634            Vector3::new(1.0, 2.0, 3.0).with_y(9.0),
635            Vector3::new(1.0, 9.0, 3.0)
636        );
637    }
638
639    #[test]
640    fn with_z() {
641        assert_eq!(
642            Vector3::new(1.0, 2.0, 3.0).with_z(9.0),
643            Vector3::new(1.0, 2.0, 9.0)
644        );
645    }
646
647    #[test]
648    fn map() {
649        assert_eq!(
650            Vector3::new(1.0, 2.0, 3.0).map(|c| c * 2.0),
651            Vector3::new(2.0, 4.0, 6.0)
652        );
653    }
654
655    #[test]
656    fn zip_map() {
657        assert_eq!(
658            Vector3::new(1.0, 2.0, 3.0).zip_map(Vector3::new(4.0, 5.0, 6.0), |a, b| a + b),
659            Vector3::new(5.0, 7.0, 9.0)
660        );
661    }
662
663    #[test]
664    fn default_is_zero() {
665        assert_eq!(Vector3::<f64>::default(), Vector3::new(0.0, 0.0, 0.0));
666    }
667
668    #[test]
669    fn copy_and_clone() {
670        let a = Vector3::new(1.0, 2.0, 3.0);
671        let b = a;
672        let c = ::core::clone::Clone::clone(&a);
673        assert_eq!(a, b);
674        assert_eq!(a, c);
675    }
676
677    #[test]
678    fn eq() {
679        let a = Vector3::new(1.0, 2.0, 3.0);
680        assert_eq!(a, Vector3::new(1.0, 2.0, 3.0));
681        assert_ne!(a, Vector3::new(1.0, 2.0, 4.0));
682    }
683
684    #[test]
685    fn debug() {
686        assert_eq!(
687            format!("{:?}", Vector3::new(1.0, 2.0, 3.0)),
688            "Vector3 { x: 1.0, y: 2.0, z: 3.0 }"
689        );
690    }
691
692    #[test]
693    fn index() {
694        let v = Vector3::new(1.0, 2.0, 3.0);
695        assert_eq!((v[0], v[1], v[2]), (1.0, 2.0, 3.0));
696    }
697
698    #[test]
699    fn index_mut() {
700        let mut v = Vector3::new(1.0, 2.0, 3.0);
701        v[1] = 9.0;
702        assert_eq!(v.y, 9.0);
703    }
704
705    #[test]
706    #[should_panic]
707    fn index_panics_when_out_of_bounds() {
708        let _ = Vector3::new(1.0, 2.0, 3.0)[3];
709    }
710
711    #[test]
712    #[should_panic]
713    fn index_mut_panics_when_out_of_bounds() {
714        Vector3::new(1.0, 2.0, 3.0)[3] = 0.0;
715    }
716
717    #[test]
718    fn constants() {
719        assert_eq!(Vector3::<f64>::ZERO, Vector3::new(0.0, 0.0, 0.0));
720        assert_eq!(Vector3::<f64>::ONE, Vector3::new(1.0, 1.0, 1.0));
721        assert_eq!(Vector3::<f64>::X, Vector3::new(1.0, 0.0, 0.0));
722        assert_eq!(Vector3::<f64>::Y, Vector3::new(0.0, 1.0, 0.0));
723        assert_eq!(Vector3::<f64>::Z, Vector3::new(0.0, 0.0, 1.0));
724    }
725
726    #[test]
727    fn neg() {
728        assert_eq!(-Vector3::new(1.0, -2.0, 3.0), Vector3::new(-1.0, 2.0, -3.0));
729    }
730
731    #[test]
732    fn add() {
733        assert_eq!(
734            Vector3::new(1.0, 2.0, 3.0) + Vector3::new(4.0, 5.0, 6.0),
735            Vector3::new(5.0, 7.0, 9.0)
736        );
737    }
738
739    #[test]
740    fn add_assign() {
741        let mut v = Vector3::new(1.0, 2.0, 3.0);
742        v += Vector3::new(4.0, 5.0, 6.0);
743        assert_eq!(v, Vector3::new(5.0, 7.0, 9.0));
744    }
745
746    #[test]
747    fn sub() {
748        assert_eq!(
749            Vector3::new(4.0, 5.0, 6.0) - Vector3::new(1.0, 2.0, 3.0),
750            Vector3::new(3.0, 3.0, 3.0)
751        );
752    }
753
754    #[test]
755    fn sub_assign() {
756        let mut v = Vector3::new(4.0, 5.0, 6.0);
757        v -= Vector3::new(1.0, 2.0, 3.0);
758        assert_eq!(v, Vector3::new(3.0, 3.0, 3.0));
759    }
760
761    #[test]
762    fn mul_scalar() {
763        assert_eq!(
764            Vector3::new(1.0, 2.0, 3.0) * 2.0,
765            Vector3::new(2.0, 4.0, 6.0)
766        );
767    }
768
769    #[test]
770    fn mul_assign_scalar() {
771        let mut v = Vector3::new(1.0, 2.0, 3.0);
772        v *= 2.0;
773        assert_eq!(v, Vector3::new(2.0, 4.0, 6.0));
774    }
775
776    #[test]
777    fn div_scalar() {
778        assert_eq!(
779            Vector3::new(2.0, 4.0, 6.0) / 2.0,
780            Vector3::new(1.0, 2.0, 3.0)
781        );
782    }
783
784    #[test]
785    fn div_assign_scalar() {
786        let mut v = Vector3::new(2.0, 4.0, 6.0);
787        v /= 2.0;
788        assert_eq!(v, Vector3::new(1.0, 2.0, 3.0));
789    }
790
791    #[test]
792    fn sum_owned() {
793        let v = [
794            Vector3::new(1.0, 1.0, 1.0),
795            Vector3::new(2.0, 2.0, 2.0),
796            Vector3::new(3.0, 3.0, 3.0),
797        ];
798        let total: Vector3<f64> = v.iter().copied().sum();
799        assert_eq!(total, Vector3::new(6.0, 6.0, 6.0));
800    }
801
802    #[test]
803    fn sum_borrowed() {
804        let v = [
805            Vector3::new(1.0, 1.0, 1.0),
806            Vector3::new(2.0, 2.0, 2.0),
807            Vector3::new(3.0, 3.0, 3.0),
808        ];
809        let total: Vector3<f64> = v.iter().sum();
810        assert_eq!(total, Vector3::new(6.0, 6.0, 6.0));
811    }
812
813    #[test]
814    fn sum_empty() {
815        let total: Vector3<f64> = iter::empty::<Vector3<f64>>().sum();
816        assert_eq!(total, Vector3::new(0.0, 0.0, 0.0));
817    }
818
819    #[test]
820    fn element_sum() {
821        assert_eq!(Vector3::new(1.0, 2.0, 3.0).element_sum(), 6.0);
822    }
823
824    #[test]
825    fn element_product() {
826        assert_eq!(Vector3::new(2.0, 3.0, 4.0).element_product(), 24.0);
827    }
828
829    #[test]
830    fn lerp() {
831        assert_eq!(
832            Vector3::new(0.0, 0.0, 0.0).lerp(Vector3::new(2.0, 4.0, 6.0), 0.5),
833            Vector3::new(1.0, 2.0, 3.0)
834        );
835    }
836
837    #[test]
838    fn dot() {
839        assert_eq!(
840            Vector3::new(1.0, 2.0, 3.0).dot(Vector3::new(4.0, 5.0, 6.0)),
841            32.0
842        );
843    }
844
845    #[test]
846    fn cross() {
847        assert_eq!(Vector3::<f64>::X.cross(Vector3::Y), Vector3::Z);
848        assert_eq!(
849            Vector3::new(1.0, 2.0, 3.0).cross(Vector3::new(4.0, 5.0, 6.0)),
850            Vector3::new(-3.0, 6.0, -3.0)
851        );
852    }
853
854    #[test]
855    fn norm_squared() {
856        assert_eq!(Vector3::new(1.0, 2.0, 2.0).norm_squared(), 9.0);
857    }
858
859    #[test]
860    fn norm() {
861        assert_eq!(Vector3::new(3.0, 4.0, 0.0).norm(), 5.0);
862    }
863
864    #[test]
865    fn normalize() {
866        let n = Vector3::new(3.0, 4.0, 0.0).normalize();
867        assert!((n - Vector3::new(0.6, 0.8, 0.0)).norm() < 1e-12);
868    }
869
870    #[test]
871    fn try_normalize() {
872        let n = Vector3::new(3.0, 4.0, 0.0).try_normalize().unwrap();
873        assert!((n - Vector3::new(0.6, 0.8, 0.0)).norm() < 1e-12);
874    }
875
876    #[test]
877    fn try_normalize_zero_is_none() {
878        assert_eq!(Vector3::<f64>::ZERO.try_normalize(), None);
879    }
880
881    #[test]
882    fn normalize_or_zero() {
883        let n = Vector3::new(3.0, 4.0, 0.0).normalize_or_zero();
884        assert!((n - Vector3::new(0.6, 0.8, 0.0)).norm() < 1e-12);
885    }
886
887    #[test]
888    fn normalize_or_zero_zero_is_zero() {
889        assert_eq!(Vector3::<f64>::ZERO.normalize_or_zero(), Vector3::ZERO);
890    }
891
892    #[test]
893    fn is_normalized() {
894        assert!(Vector3::<f64>::X.is_normalized());
895        assert!(!Vector3::new(2.0, 0.0, 0.0).is_normalized());
896    }
897
898    #[test]
899    fn angle_between() {
900        assert!((Vector3::<f64>::X.angle_between(Vector3::Y) - FRAC_PI_2).abs() < 1e-12);
901        assert!(Vector3::<f64>::X.angle_between(Vector3::X).abs() < 1e-12);
902    }
903
904    #[test]
905    fn project_onto() {
906        assert_eq!(
907            Vector3::new(2.0, 3.0, 0.0).project_onto(Vector3::X),
908            Vector3::new(2.0, 0.0, 0.0)
909        );
910    }
911
912    #[test]
913    fn reject_from() {
914        assert_eq!(
915            Vector3::new(2.0, 3.0, 0.0).reject_from(Vector3::X),
916            Vector3::new(0.0, 3.0, 0.0)
917        );
918    }
919
920    #[test]
921    fn reflect() {
922        assert_eq!(
923            Vector3::new(1.0, -1.0, 0.0).reflect(Vector3::Y),
924            Vector3::new(1.0, 1.0, 0.0)
925        );
926    }
927
928    #[test]
929    fn recip() {
930        assert_eq!(
931            Vector3::new(2.0, 4.0, 8.0).recip(),
932            Vector3::new(0.5, 0.25, 0.125)
933        );
934    }
935
936    #[test]
937    fn abs() {
938        assert_eq!(
939            Vector3::new(-1.0, 2.0, -3.0).abs(),
940            Vector3::new(1.0, 2.0, 3.0)
941        );
942    }
943
944    #[test]
945    fn min() {
946        assert_eq!(
947            Vector3::new(1.0, 5.0, 3.0).min(Vector3::new(4.0, 2.0, 6.0)),
948            Vector3::new(1.0, 2.0, 3.0)
949        );
950    }
951
952    #[test]
953    fn max() {
954        assert_eq!(
955            Vector3::new(1.0, 5.0, 3.0).max(Vector3::new(4.0, 2.0, 6.0)),
956            Vector3::new(4.0, 5.0, 6.0)
957        );
958    }
959
960    #[test]
961    fn clamp() {
962        assert_eq!(
963            Vector3::new(5.0, -1.0, 2.0).clamp(Vector3::splat(0.0), Vector3::splat(3.0)),
964            Vector3::new(3.0, 0.0, 2.0)
965        );
966    }
967
968    #[test]
969    #[should_panic]
970    fn clamp_panics_when_min_gt_max() {
971        Vector3::new(1.0, 1.0, 1.0).clamp(Vector3::splat(3.0), Vector3::splat(0.0));
972    }
973
974    #[test]
975    fn min_element() {
976        assert_eq!(Vector3::new(3.0, 1.0, 2.0).min_element(), 1.0);
977    }
978
979    #[test]
980    fn max_element() {
981        assert_eq!(Vector3::new(3.0, 1.0, 2.0).max_element(), 3.0);
982    }
983
984    #[test]
985    fn floor() {
986        assert_eq!(
987            Vector3::new(1.7, -1.2, 2.0).floor(),
988            Vector3::new(1.0, -2.0, 2.0)
989        );
990    }
991
992    #[test]
993    fn ceil() {
994        assert_eq!(
995            Vector3::new(1.2, -1.7, 2.0).ceil(),
996            Vector3::new(2.0, -1.0, 2.0)
997        );
998    }
999
1000    #[test]
1001    fn round() {
1002        assert_eq!(
1003            Vector3::new(1.5, -1.5, 2.4).round(),
1004            Vector3::new(2.0, -2.0, 2.0)
1005        );
1006    }
1007
1008    #[test]
1009    fn round_ties_even() {
1010        assert_eq!(
1011            Vector3::new(1.5, 2.5, -1.5).round_ties_even(),
1012            Vector3::new(2.0, 2.0, -2.0)
1013        );
1014    }
1015
1016    #[test]
1017    fn trunc() {
1018        assert_eq!(
1019            Vector3::new(1.7, -1.7, 2.0).trunc(),
1020            Vector3::new(1.0, -1.0, 2.0)
1021        );
1022    }
1023
1024    #[test]
1025    fn fract() {
1026        assert_eq!(
1027            Vector3::new(2.5, -1.25, 0.0).fract(),
1028            Vector3::new(0.5, -0.25, 0.0)
1029        );
1030    }
1031
1032    #[test]
1033    fn copysign() {
1034        assert_eq!(
1035            Vector3::new(3.0, -4.0, 5.0).copysign(Vector3::new(-1.0, 1.0, -1.0)),
1036            Vector3::new(-3.0, 4.0, -5.0)
1037        );
1038    }
1039
1040    #[test]
1041    fn signum() {
1042        assert_eq!(
1043            Vector3::new(3.0, -2.0, 5.0).signum(),
1044            Vector3::new(1.0, -1.0, 1.0)
1045        );
1046    }
1047
1048    #[test]
1049    fn rem_euclid() {
1050        assert_eq!(
1051            Vector3::new(-7.0, 7.0, 8.0).rem_euclid(Vector3::splat(3.0)),
1052            Vector3::new(2.0, 1.0, 2.0)
1053        );
1054    }
1055
1056    #[test]
1057    fn is_finite() {
1058        assert!(Vector3::new(1.0, 2.0, 3.0).is_finite());
1059        assert!(!Vector3::new(1.0, f64::INFINITY, 3.0).is_finite());
1060    }
1061
1062    #[test]
1063    fn is_infinite() {
1064        assert!(Vector3::new(1.0, f64::INFINITY, 3.0).is_infinite());
1065        assert!(!Vector3::new(1.0, 2.0, 3.0).is_infinite());
1066    }
1067
1068    #[test]
1069    fn is_nan() {
1070        assert!(Vector3::new(1.0, f64::NAN, 3.0).is_nan());
1071        assert!(!Vector3::new(1.0, 2.0, 3.0).is_nan());
1072    }
1073
1074    #[test]
1075    fn f32_normalize() {
1076        let n = Vector3::<f32>::new(3.0, 4.0, 0.0).normalize();
1077        assert!((n - Vector3::new(0.6, 0.8, 0.0)).norm() < 1e-6);
1078    }
1079}