euclid/
vector.rs

1// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution.
3//
4// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7// option. This file may not be copied, modified, or distributed
8// except according to those terms.
9
10use super::UnknownUnit;
11use approxeq::ApproxEq;
12use length::Length;
13#[cfg(feature = "mint")]
14use mint;
15use point::{TypedPoint2D, TypedPoint3D, point2, point3};
16use size::{TypedSize2D, size2};
17use scale::TypedScale;
18use transform2d::TypedTransform2D;
19use transform3d::TypedTransform3D;
20use trig::Trig;
21use Angle;
22use num::*;
23use num_traits::{Float, NumCast, Signed};
24use core::fmt;
25use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
26use core::marker::PhantomData;
27
28/// A 2d Vector tagged with a unit.
29#[derive(EuclidMatrix)]
30#[repr(C)]
31pub struct TypedVector2D<T, U> {
32    pub x: T,
33    pub y: T,
34    #[doc(hidden)]
35    pub _unit: PhantomData<U>,
36}
37
38mint_vec!(TypedVector2D[x, y] = Vector2);
39
40/// Default 2d vector type with no unit.
41///
42/// `Vector2D` provides the same methods as `TypedVector2D`.
43pub type Vector2D<T> = TypedVector2D<T, UnknownUnit>;
44
45impl<T: Copy + Zero, U> TypedVector2D<T, U> {
46    /// Constructor, setting all components to zero.
47    #[inline]
48    pub fn zero() -> Self {
49        TypedVector2D::new(Zero::zero(), Zero::zero())
50    }
51
52    /// Convert into a 3d vector.
53    #[inline]
54    pub fn to_3d(&self) -> TypedVector3D<T, U> {
55        vec3(self.x, self.y, Zero::zero())
56    }
57}
58
59impl<T: fmt::Debug, U> fmt::Debug for TypedVector2D<T, U> {
60    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
61        write!(f, "({:?},{:?})", self.x, self.y)
62    }
63}
64
65impl<T: fmt::Display, U> fmt::Display for TypedVector2D<T, U> {
66    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
67        write!(formatter, "({},{})", self.x, self.y)
68    }
69}
70
71impl<T: Default, U> Default for TypedVector2D<T, U> {
72    fn default() -> Self {
73        TypedVector2D::new(Default::default(), Default::default())
74    }
75}
76
77impl<T, U> TypedVector2D<T, U> {
78    /// Constructor taking scalar values directly.
79    #[inline]
80    pub fn new(x: T, y: T) -> Self {
81        TypedVector2D {
82            x,
83            y,
84            _unit: PhantomData,
85        }
86    }
87}
88
89impl<T: Copy, U> TypedVector2D<T, U> {
90    /// Constructor taking properly typed Lengths instead of scalar values.
91    #[inline]
92    pub fn from_lengths(x: Length<T, U>, y: Length<T, U>) -> Self {
93        vec2(x.0, y.0)
94    }
95
96    /// Create a 3d vector from this one, using the specified z value.
97    #[inline]
98    pub fn extend(&self, z: T) -> TypedVector3D<T, U> {
99        vec3(self.x, self.y, z)
100    }
101
102    /// Cast this vector into a point.
103    ///
104    /// Equivalent to adding this vector to the origin.
105    #[inline]
106    pub fn to_point(&self) -> TypedPoint2D<T, U> {
107        point2(self.x, self.y)
108    }
109
110    /// Swap x and y.
111    #[inline]
112    pub fn yx(&self) -> Self {
113        vec2(self.y, self.x)
114    }
115
116    /// Cast this vector into a size.
117    #[inline]
118    pub fn to_size(&self) -> TypedSize2D<T, U> {
119        size2(self.x, self.y)
120    }
121
122    /// Returns self.x as a Length carrying the unit.
123    #[inline]
124    pub fn x_typed(&self) -> Length<T, U> {
125        Length::new(self.x)
126    }
127
128    /// Returns self.y as a Length carrying the unit.
129    #[inline]
130    pub fn y_typed(&self) -> Length<T, U> {
131        Length::new(self.y)
132    }
133
134    /// Drop the units, preserving only the numeric value.
135    #[inline]
136    pub fn to_untyped(&self) -> Vector2D<T> {
137        vec2(self.x, self.y)
138    }
139
140    /// Tag a unit-less value with units.
141    #[inline]
142    pub fn from_untyped(p: &Vector2D<T>) -> Self {
143        vec2(p.x, p.y)
144    }
145
146    /// Cast the unit
147    #[inline]
148    pub fn cast_unit<V>(&self) -> TypedVector2D<T, V> {
149        vec2(self.x, self.y)
150    }
151
152    #[inline]
153    pub fn to_array(&self) -> [T; 2] {
154        [self.x, self.y]
155    }
156
157    #[inline]
158    pub fn to_tuple(&self) -> (T, T) {
159        (self.x, self.y)
160    }
161}
162
163impl<T, U> TypedVector2D<T, U>
164where
165    T: Copy
166        + Clone
167        + Add<T, Output = T>
168        + Mul<T, Output = T>
169        + Div<T, Output = T>
170        + Sub<T, Output = T>
171        + Trig
172        + PartialOrd
173        + One
174        + Zero {
175    #[inline]
176    pub fn to_transform(&self) -> TypedTransform2D<T, U, U> {
177        TypedTransform2D::create_translation(self.x, self.y)
178    }
179}
180
181impl<T, U> TypedVector2D<T, U>
182where
183    T: Trig + Copy + Sub<T, Output = T>,
184{
185    /// Returns the angle between this vector and the x axis between -PI and PI.
186    pub fn angle_from_x_axis(&self) -> Angle<T> {
187        Angle::radians(Trig::fast_atan2(self.y, self.x))
188    }
189}
190
191impl<T, U> TypedVector2D<T, U>
192where
193    T: Copy + Mul<T, Output = T> + Add<T, Output = T> + Sub<T, Output = T>,
194{
195    /// Dot product.
196    #[inline]
197    pub fn dot(self, other: Self) -> T {
198        self.x * other.x + self.y * other.y
199    }
200
201    /// Returns the norm of the cross product [self.x, self.y, 0] x [other.x, other.y, 0]..
202    #[inline]
203    pub fn cross(self, other: Self) -> T {
204        self.x * other.y - self.y * other.x
205    }
206
207    #[inline]
208    pub fn normalize(self) -> Self
209    where
210        T: Float,
211    {
212        self / self.length()
213    }
214
215    /// Return the normalized vector even if the length is larger than the max value of Float.
216    #[inline]
217    pub fn robust_normalize(self) -> Self
218    where
219        T: Float,
220    {
221        let length = self.length();
222        if length.is_infinite() {
223            let scaled = self / T::max_value();
224            scaled / scaled.length()
225        } else {
226            self / length
227        }
228    }
229
230    #[inline]
231    pub fn square_length(&self) -> T {
232        self.x * self.x + self.y * self.y
233    }
234
235    #[inline]
236    pub fn length(&self) -> T
237    where
238        T: Float,
239    {
240        self.square_length().sqrt()
241    }
242}
243
244impl<T, U> TypedVector2D<T, U>
245where
246    T: Copy + One + Add<Output = T> + Sub<Output = T> + Mul<Output = T>,
247{
248    /// Linearly interpolate between this vector and another vector.
249    ///
250    /// `t` is expected to be between zero and one.
251    #[inline]
252    pub fn lerp(&self, other: Self, t: T) -> Self {
253        let one_t = T::one() - t;
254        (*self) * one_t + other * t
255    }
256}
257
258impl<T: Copy + Add<T, Output = T>, U> Add for TypedVector2D<T, U> {
259    type Output = Self;
260    fn add(self, other: Self) -> Self {
261        TypedVector2D::new(self.x + other.x, self.y + other.y)
262    }
263}
264
265impl<T: Copy + Add<T, Output = T>, U> AddAssign for TypedVector2D<T, U> {
266    #[inline]
267    fn add_assign(&mut self, other: Self) {
268        *self = *self + other
269    }
270}
271
272impl<T: Copy + Sub<T, Output = T>, U> SubAssign<TypedVector2D<T, U>> for TypedVector2D<T, U> {
273    #[inline]
274    fn sub_assign(&mut self, other: Self) {
275        *self = *self - other
276    }
277}
278
279impl<T: Copy + Sub<T, Output = T>, U> Sub for TypedVector2D<T, U> {
280    type Output = Self;
281    #[inline]
282    fn sub(self, other: Self) -> Self {
283        vec2(self.x - other.x, self.y - other.y)
284    }
285}
286
287impl<T: Copy + Neg<Output = T>, U> Neg for TypedVector2D<T, U> {
288    type Output = Self;
289    #[inline]
290    fn neg(self) -> Self {
291        vec2(-self.x, -self.y)
292    }
293}
294
295impl<T: Float, U> TypedVector2D<T, U> {
296    #[inline]
297    pub fn min(self, other: Self) -> Self {
298        vec2(self.x.min(other.x), self.y.min(other.y))
299    }
300
301    #[inline]
302    pub fn max(self, other: Self) -> Self {
303        vec2(self.x.max(other.x), self.y.max(other.y))
304    }
305
306    #[inline]
307    pub fn clamp(&self, start: Self, end: Self) -> Self {
308        self.max(start).min(end)
309    }
310}
311
312impl<T: Copy + Mul<T, Output = T>, U> Mul<T> for TypedVector2D<T, U> {
313    type Output = Self;
314    #[inline]
315    fn mul(self, scale: T) -> Self {
316        vec2(self.x * scale, self.y * scale)
317    }
318}
319
320impl<T: Copy + Div<T, Output = T>, U> Div<T> for TypedVector2D<T, U> {
321    type Output = Self;
322    #[inline]
323    fn div(self, scale: T) -> Self {
324        vec2(self.x / scale, self.y / scale)
325    }
326}
327
328impl<T: Copy + Mul<T, Output = T>, U> MulAssign<T> for TypedVector2D<T, U> {
329    #[inline]
330    fn mul_assign(&mut self, scale: T) {
331        *self = *self * scale
332    }
333}
334
335impl<T: Copy + Div<T, Output = T>, U> DivAssign<T> for TypedVector2D<T, U> {
336    #[inline]
337    fn div_assign(&mut self, scale: T) {
338        *self = *self / scale
339    }
340}
341
342impl<T: Copy + Mul<T, Output = T>, U1, U2> Mul<TypedScale<T, U1, U2>> for TypedVector2D<T, U1> {
343    type Output = TypedVector2D<T, U2>;
344    #[inline]
345    fn mul(self, scale: TypedScale<T, U1, U2>) -> Self::Output {
346        vec2(self.x * scale.get(), self.y * scale.get())
347    }
348}
349
350impl<T: Copy + Div<T, Output = T>, U1, U2> Div<TypedScale<T, U1, U2>> for TypedVector2D<T, U2> {
351    type Output = TypedVector2D<T, U1>;
352    #[inline]
353    fn div(self, scale: TypedScale<T, U1, U2>) -> Self::Output {
354        vec2(self.x / scale.get(), self.y / scale.get())
355    }
356}
357
358impl<T: Round, U> TypedVector2D<T, U> {
359    /// Rounds each component to the nearest integer value.
360    ///
361    /// This behavior is preserved for negative values (unlike the basic cast).
362    /// For example `{ -0.1, -0.8 }.round() == { 0.0, -1.0 }`.
363    #[inline]
364    #[cfg_attr(feature = "unstable", must_use)]
365    pub fn round(&self) -> Self {
366        vec2(self.x.round(), self.y.round())
367    }
368}
369
370impl<T: Ceil, U> TypedVector2D<T, U> {
371    /// Rounds each component to the smallest integer equal or greater than the original value.
372    ///
373    /// This behavior is preserved for negative values (unlike the basic cast).
374    /// For example `{ -0.1, -0.8 }.ceil() == { 0.0, 0.0 }`.
375    #[inline]
376    #[cfg_attr(feature = "unstable", must_use)]
377    pub fn ceil(&self) -> Self {
378        vec2(self.x.ceil(), self.y.ceil())
379    }
380}
381
382impl<T: Floor, U> TypedVector2D<T, U> {
383    /// Rounds each component to the biggest integer equal or lower than the original value.
384    ///
385    /// This behavior is preserved for negative values (unlike the basic cast).
386    /// For example `{ -0.1, -0.8 }.floor() == { -1.0, -1.0 }`.
387    #[inline]
388    #[cfg_attr(feature = "unstable", must_use)]
389    pub fn floor(&self) -> Self {
390        vec2(self.x.floor(), self.y.floor())
391    }
392}
393
394impl<T: NumCast + Copy, U> TypedVector2D<T, U> {
395    /// Cast from one numeric representation to another, preserving the units.
396    ///
397    /// When casting from floating vector to integer coordinates, the decimals are truncated
398    /// as one would expect from a simple cast, but this behavior does not always make sense
399    /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
400    #[inline]
401    pub fn cast<NewT: NumCast + Copy>(&self) -> TypedVector2D<NewT, U> {
402        self.try_cast().unwrap()
403    }
404
405    /// Fallible cast from one numeric representation to another, preserving the units.
406    ///
407    /// When casting from floating vector to integer coordinates, the decimals are truncated
408    /// as one would expect from a simple cast, but this behavior does not always make sense
409    /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
410    #[inline]
411    pub fn try_cast<NewT: NumCast + Copy>(&self) -> Option<TypedVector2D<NewT, U>> {
412        match (NumCast::from(self.x), NumCast::from(self.y)) {
413            (Some(x), Some(y)) => Some(TypedVector2D::new(x, y)),
414            _ => None,
415        }
416    }
417
418    // Convenience functions for common casts
419
420    /// Cast into an `f32` vector.
421    #[inline]
422    pub fn to_f32(&self) -> TypedVector2D<f32, U> {
423        self.cast()
424    }
425
426    /// Cast into an `f64` vector.
427    #[inline]
428    pub fn to_f64(&self) -> TypedVector2D<f64, U> {
429        self.cast()
430    }
431
432    /// Cast into an `usize` vector, truncating decimals if any.
433    ///
434    /// When casting from floating vector vectors, it is worth considering whether
435    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
436    /// the desired conversion behavior.
437    #[inline]
438    pub fn to_usize(&self) -> TypedVector2D<usize, U> {
439        self.cast()
440    }
441
442    /// Cast into an `u32` vector, truncating decimals if any.
443    ///
444    /// When casting from floating vector vectors, it is worth considering whether
445    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
446    /// the desired conversion behavior.
447    #[inline]
448    pub fn to_u32(&self) -> TypedVector2D<u32, U> {
449        self.cast()
450    }
451
452    /// Cast into an i32 vector, truncating decimals if any.
453    ///
454    /// When casting from floating vector vectors, it is worth considering whether
455    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
456    /// the desired conversion behavior.
457    #[inline]
458    pub fn to_i32(&self) -> TypedVector2D<i32, U> {
459        self.cast()
460    }
461
462    /// Cast into an i64 vector, truncating decimals if any.
463    ///
464    /// When casting from floating vector vectors, it is worth considering whether
465    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
466    /// the desired conversion behavior.
467    #[inline]
468    pub fn to_i64(&self) -> TypedVector2D<i64, U> {
469        self.cast()
470    }
471}
472
473impl<T: Copy + ApproxEq<T>, U> ApproxEq<TypedVector2D<T, U>> for TypedVector2D<T, U> {
474    #[inline]
475    fn approx_epsilon() -> Self {
476        vec2(T::approx_epsilon(), T::approx_epsilon())
477    }
478
479    #[inline]
480    fn approx_eq(&self, other: &Self) -> bool {
481        self.x.approx_eq(&other.x) && self.y.approx_eq(&other.y)
482    }
483
484    #[inline]
485    fn approx_eq_eps(&self, other: &Self, eps: &Self) -> bool {
486        self.x.approx_eq_eps(&other.x, &eps.x) && self.y.approx_eq_eps(&other.y, &eps.y)
487    }
488}
489
490impl<T: Copy, U> Into<[T; 2]> for TypedVector2D<T, U> {
491    fn into(self) -> [T; 2] {
492        self.to_array()
493    }
494}
495
496impl<T: Copy, U> From<[T; 2]> for TypedVector2D<T, U> {
497    fn from(array: [T; 2]) -> Self {
498        vec2(array[0], array[1])
499    }
500}
501
502impl<T: Copy, U> Into<(T, T)> for TypedVector2D<T, U> {
503    fn into(self) -> (T, T) {
504        self.to_tuple()
505    }
506}
507
508impl<T: Copy, U> From<(T, T)> for TypedVector2D<T, U> {
509    fn from(tuple: (T, T)) -> Self {
510        vec2(tuple.0, tuple.1)
511    }
512}
513
514impl<T, U> TypedVector2D<T, U>
515where
516    T: Signed,
517{
518    pub fn abs(&self) -> Self {
519        vec2(self.x.abs(), self.y.abs())
520    }
521}
522
523/// A 3d Vector tagged with a unit.
524#[derive(EuclidMatrix)]
525#[repr(C)]
526pub struct TypedVector3D<T, U> {
527    pub x: T,
528    pub y: T,
529    pub z: T,
530    #[doc(hidden)]
531    pub _unit: PhantomData<U>,
532}
533
534mint_vec!(TypedVector3D[x, y, z] = Vector3);
535
536/// Default 3d vector type with no unit.
537///
538/// `Vector3D` provides the same methods as `TypedVector3D`.
539pub type Vector3D<T> = TypedVector3D<T, UnknownUnit>;
540
541impl<T: Copy + Zero, U> TypedVector3D<T, U> {
542    /// Constructor, setting all components to zero.
543    #[inline]
544    pub fn zero() -> Self {
545        vec3(Zero::zero(), Zero::zero(), Zero::zero())
546    }
547
548    #[inline]
549    pub fn to_array_4d(&self) -> [T; 4] {
550        [self.x, self.y, self.z, Zero::zero()]
551    }
552
553    #[inline]
554    pub fn to_tuple_4d(&self) -> (T, T, T, T) {
555        (self.x, self.y, self.z, Zero::zero())
556    }
557}
558
559impl<T: fmt::Debug, U> fmt::Debug for TypedVector3D<T, U> {
560    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
561        write!(f, "({:?},{:?},{:?})", self.x, self.y, self.z)
562    }
563}
564
565impl<T: fmt::Display, U> fmt::Display for TypedVector3D<T, U> {
566    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
567        write!(f, "({},{},{})", self.x, self.y, self.z)
568    }
569}
570
571impl<T: Default, U> Default for TypedVector3D<T, U> {
572    fn default() -> Self {
573        TypedVector3D::new(Default::default(), Default::default(), Default::default())
574    }
575}
576
577impl<T, U> TypedVector3D<T, U> {
578    /// Constructor taking scalar values directly.
579    #[inline]
580    pub fn new(x: T, y: T, z: T) -> Self {
581        TypedVector3D {
582            x,
583            y,
584            z,
585            _unit: PhantomData,
586        }
587    }
588}
589
590impl<T: Copy, U> TypedVector3D<T, U> {
591    /// Constructor taking properly typed Lengths instead of scalar values.
592    #[inline]
593    pub fn from_lengths(x: Length<T, U>, y: Length<T, U>, z: Length<T, U>) -> TypedVector3D<T, U> {
594        vec3(x.0, y.0, z.0)
595    }
596
597    /// Cast this vector into a point.
598    ///
599    /// Equivalent to adding this vector to the origin.
600    #[inline]
601    pub fn to_point(&self) -> TypedPoint3D<T, U> {
602        point3(self.x, self.y, self.z)
603    }
604
605    /// Returns a 2d vector using this vector's x and y coordinates
606    #[inline]
607    pub fn xy(&self) -> TypedVector2D<T, U> {
608        vec2(self.x, self.y)
609    }
610
611    /// Returns a 2d vector using this vector's x and z coordinates
612    #[inline]
613    pub fn xz(&self) -> TypedVector2D<T, U> {
614        vec2(self.x, self.z)
615    }
616
617    /// Returns a 2d vector using this vector's x and z coordinates
618    #[inline]
619    pub fn yz(&self) -> TypedVector2D<T, U> {
620        vec2(self.y, self.z)
621    }
622
623    /// Returns self.x as a Length carrying the unit.
624    #[inline]
625    pub fn x_typed(&self) -> Length<T, U> {
626        Length::new(self.x)
627    }
628
629    /// Returns self.y as a Length carrying the unit.
630    #[inline]
631    pub fn y_typed(&self) -> Length<T, U> {
632        Length::new(self.y)
633    }
634
635    /// Returns self.z as a Length carrying the unit.
636    #[inline]
637    pub fn z_typed(&self) -> Length<T, U> {
638        Length::new(self.z)
639    }
640
641    #[inline]
642    pub fn to_array(&self) -> [T; 3] {
643        [self.x, self.y, self.z]
644    }
645
646    #[inline]
647    pub fn to_tuple(&self) -> (T, T, T) {
648        (self.x, self.y, self.z)
649    }
650
651    /// Drop the units, preserving only the numeric value.
652    #[inline]
653    pub fn to_untyped(&self) -> Vector3D<T> {
654        vec3(self.x, self.y, self.z)
655    }
656
657    /// Tag a unitless value with units.
658    #[inline]
659    pub fn from_untyped(p: &Vector3D<T>) -> Self {
660        vec3(p.x, p.y, p.z)
661    }
662
663    /// Convert into a 2d vector.
664    #[inline]
665    pub fn to_2d(&self) -> TypedVector2D<T, U> {
666        self.xy()
667    }
668}
669
670impl<T, U> TypedVector3D<T, U>
671where
672    T: Copy
673        + Clone
674        + Add<T, Output = T>
675        + Mul<T, Output = T>
676        + Div<T, Output = T>
677        + Sub<T, Output = T>
678        + Trig
679        + PartialOrd
680        + One
681        + Zero
682        + Neg<Output = T> {
683    #[inline]
684    pub fn to_transform(&self) -> TypedTransform3D<T, U, U> {
685        TypedTransform3D::create_translation(self.x, self.y, self.z)
686    }
687}
688
689impl<T: Mul<T, Output = T> + Add<T, Output = T> + Sub<T, Output = T> + Copy, U>
690    TypedVector3D<T, U> {
691    // Dot product.
692    #[inline]
693    pub fn dot(self, other: Self) -> T {
694        self.x * other.x + self.y * other.y + self.z * other.z
695    }
696
697    // Cross product.
698    #[inline]
699    pub fn cross(self, other: Self) -> Self {
700        vec3(
701            self.y * other.z - self.z * other.y,
702            self.z * other.x - self.x * other.z,
703            self.x * other.y - self.y * other.x,
704        )
705    }
706
707    #[inline]
708    pub fn normalize(self) -> Self
709    where
710        T: Float,
711    {
712        self / self.length()
713    }
714
715    /// Return the normalized vector even if the length is larger than the max value of Float.
716    #[inline]
717    pub fn robust_normalize(self) -> Self
718    where
719        T: Float,
720    {
721        let length = self.length();
722        if length.is_infinite() {
723            let scaled = self / T::max_value();
724            scaled / scaled.length()
725        } else {
726            self / length
727        }
728    }
729
730    #[inline]
731    pub fn square_length(&self) -> T {
732        self.x * self.x + self.y * self.y + self.z * self.z
733    }
734
735    #[inline]
736    pub fn length(&self) -> T
737    where
738        T: Float,
739    {
740        self.square_length().sqrt()
741    }
742}
743
744impl<T, U> TypedVector3D<T, U>
745where
746    T: Copy + One + Add<Output = T> + Sub<Output = T> + Mul<Output = T>,
747{
748    /// Linearly interpolate between this vector and another vector.
749    ///
750    /// `t` is expected to be between zero and one.
751    #[inline]
752    pub fn lerp(&self, other: Self, t: T) -> Self {
753        let one_t = T::one() - t;
754        (*self) * one_t + other * t
755    }
756}
757
758impl<T: Copy + Add<T, Output = T>, U> Add for TypedVector3D<T, U> {
759    type Output = Self;
760    #[inline]
761    fn add(self, other: Self) -> Self {
762        vec3(self.x + other.x, self.y + other.y, self.z + other.z)
763    }
764}
765
766impl<T: Copy + Sub<T, Output = T>, U> Sub for TypedVector3D<T, U> {
767    type Output = Self;
768    #[inline]
769    fn sub(self, other: Self) -> Self {
770        vec3(self.x - other.x, self.y - other.y, self.z - other.z)
771    }
772}
773
774impl<T: Copy + Add<T, Output = T>, U> AddAssign for TypedVector3D<T, U> {
775    #[inline]
776    fn add_assign(&mut self, other: Self) {
777        *self = *self + other
778    }
779}
780
781impl<T: Copy + Sub<T, Output = T>, U> SubAssign<TypedVector3D<T, U>> for TypedVector3D<T, U> {
782    #[inline]
783    fn sub_assign(&mut self, other: Self) {
784        *self = *self - other
785    }
786}
787
788impl<T: Copy + Neg<Output = T>, U> Neg for TypedVector3D<T, U> {
789    type Output = Self;
790    #[inline]
791    fn neg(self) -> Self {
792        vec3(-self.x, -self.y, -self.z)
793    }
794}
795
796impl<T: Copy + Mul<T, Output = T>, U> Mul<T> for TypedVector3D<T, U> {
797    type Output = Self;
798    #[inline]
799    fn mul(self, scale: T) -> Self {
800        Self::new(self.x * scale, self.y * scale, self.z * scale)
801    }
802}
803
804impl<T: Copy + Div<T, Output = T>, U> Div<T> for TypedVector3D<T, U> {
805    type Output = Self;
806    #[inline]
807    fn div(self, scale: T) -> Self {
808        Self::new(self.x / scale, self.y / scale, self.z / scale)
809    }
810}
811
812impl<T: Copy + Mul<T, Output = T>, U> MulAssign<T> for TypedVector3D<T, U> {
813    #[inline]
814    fn mul_assign(&mut self, scale: T) {
815        *self = *self * scale
816    }
817}
818
819impl<T: Copy + Div<T, Output = T>, U> DivAssign<T> for TypedVector3D<T, U> {
820    #[inline]
821    fn div_assign(&mut self, scale: T) {
822        *self = *self / scale
823    }
824}
825
826impl<T: Float, U> TypedVector3D<T, U> {
827    #[inline]
828    pub fn min(self, other: Self) -> Self {
829        vec3(
830            self.x.min(other.x),
831            self.y.min(other.y),
832            self.z.min(other.z),
833        )
834    }
835
836    #[inline]
837    pub fn max(self, other: Self) -> Self {
838        vec3(
839            self.x.max(other.x),
840            self.y.max(other.y),
841            self.z.max(other.z),
842        )
843    }
844
845    #[inline]
846    pub fn clamp(&self, start: Self, end: Self) -> Self {
847        self.max(start).min(end)
848    }
849}
850
851impl<T: Copy + Mul<T, Output = T>, U1, U2> Mul<TypedScale<T, U1, U2>> for TypedVector3D<T, U1> {
852    type Output = TypedVector3D<T, U2>;
853    #[inline]
854    fn mul(self, scale: TypedScale<T, U1, U2>) -> Self::Output {
855        vec3(self.x * scale.get(), self.y * scale.get(), self.z * scale.get())
856    }
857}
858
859impl<T: Copy + Div<T, Output = T>, U1, U2> Div<TypedScale<T, U1, U2>> for TypedVector3D<T, U2> {
860    type Output = TypedVector3D<T, U1>;
861    #[inline]
862    fn div(self, scale: TypedScale<T, U1, U2>) -> Self::Output {
863        vec3(self.x / scale.get(), self.y / scale.get(), self.z / scale.get())
864    }
865}
866
867impl<T: Round, U> TypedVector3D<T, U> {
868    /// Rounds each component to the nearest integer value.
869    ///
870    /// This behavior is preserved for negative values (unlike the basic cast).
871    #[inline]
872    #[cfg_attr(feature = "unstable", must_use)]
873    pub fn round(&self) -> Self {
874        vec3(self.x.round(), self.y.round(), self.z.round())
875    }
876}
877
878impl<T: Ceil, U> TypedVector3D<T, U> {
879    /// Rounds each component to the smallest integer equal or greater than the original value.
880    ///
881    /// This behavior is preserved for negative values (unlike the basic cast).
882    #[inline]
883    #[cfg_attr(feature = "unstable", must_use)]
884    pub fn ceil(&self) -> Self {
885        vec3(self.x.ceil(), self.y.ceil(), self.z.ceil())
886    }
887}
888
889impl<T: Floor, U> TypedVector3D<T, U> {
890    /// Rounds each component to the biggest integer equal or lower than the original value.
891    ///
892    /// This behavior is preserved for negative values (unlike the basic cast).
893    #[inline]
894    #[cfg_attr(feature = "unstable", must_use)]
895    pub fn floor(&self) -> Self {
896        vec3(self.x.floor(), self.y.floor(), self.z.floor())
897    }
898}
899
900impl<T: NumCast + Copy, U> TypedVector3D<T, U> {
901    /// Cast from one numeric representation to another, preserving the units.
902    ///
903    /// When casting from floating vector to integer coordinates, the decimals are truncated
904    /// as one would expect from a simple cast, but this behavior does not always make sense
905    /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
906    #[inline]
907    pub fn cast<NewT: NumCast + Copy>(&self) -> TypedVector3D<NewT, U> {
908        self.try_cast().unwrap()
909    }
910
911    /// Fallible cast from one numeric representation to another, preserving the units.
912    ///
913    /// When casting from floating vector to integer coordinates, the decimals are truncated
914    /// as one would expect from a simple cast, but this behavior does not always make sense
915    /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
916    #[inline]
917    pub fn try_cast<NewT: NumCast + Copy>(&self) -> Option<TypedVector3D<NewT, U>> {
918        match (
919            NumCast::from(self.x),
920            NumCast::from(self.y),
921            NumCast::from(self.z),
922        ) {
923            (Some(x), Some(y), Some(z)) => Some(vec3(x, y, z)),
924            _ => None,
925        }
926    }
927
928    // Convenience functions for common casts
929
930    /// Cast into an `f32` vector.
931    #[inline]
932    pub fn to_f32(&self) -> TypedVector3D<f32, U> {
933        self.cast()
934    }
935
936    /// Cast into an `f64` vector.
937    #[inline]
938    pub fn to_f64(&self) -> TypedVector3D<f64, U> {
939        self.cast()
940    }
941
942    /// Cast into an `usize` vector, truncating decimals if any.
943    ///
944    /// When casting from floating vector vectors, it is worth considering whether
945    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
946    /// the desired conversion behavior.
947    #[inline]
948    pub fn to_usize(&self) -> TypedVector3D<usize, U> {
949        self.cast()
950    }
951
952    /// Cast into an `u32` vector, truncating decimals if any.
953    ///
954    /// When casting from floating vector vectors, it is worth considering whether
955    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
956    /// the desired conversion behavior.
957    #[inline]
958    pub fn to_u32(&self) -> TypedVector3D<u32, U> {
959        self.cast()
960    }
961
962    /// Cast into an `i32` vector, truncating decimals if any.
963    ///
964    /// When casting from floating vector vectors, it is worth considering whether
965    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
966    /// the desired conversion behavior.
967    #[inline]
968    pub fn to_i32(&self) -> TypedVector3D<i32, U> {
969        self.cast()
970    }
971
972    /// Cast into an `i64` vector, truncating decimals if any.
973    ///
974    /// When casting from floating vector vectors, it is worth considering whether
975    /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
976    /// the desired conversion behavior.
977    #[inline]
978    pub fn to_i64(&self) -> TypedVector3D<i64, U> {
979        self.cast()
980    }
981}
982
983impl<T: Copy + ApproxEq<T>, U> ApproxEq<TypedVector3D<T, U>> for TypedVector3D<T, U> {
984    #[inline]
985    fn approx_epsilon() -> Self {
986        vec3(
987            T::approx_epsilon(),
988            T::approx_epsilon(),
989            T::approx_epsilon(),
990        )
991    }
992
993    #[inline]
994    fn approx_eq(&self, other: &Self) -> bool {
995        self.x.approx_eq(&other.x) && self.y.approx_eq(&other.y) && self.z.approx_eq(&other.z)
996    }
997
998    #[inline]
999    fn approx_eq_eps(&self, other: &Self, eps: &Self) -> bool {
1000        self.x.approx_eq_eps(&other.x, &eps.x) && self.y.approx_eq_eps(&other.y, &eps.y)
1001            && self.z.approx_eq_eps(&other.z, &eps.z)
1002    }
1003}
1004
1005impl<T: Copy, U> Into<[T; 3]> for TypedVector3D<T, U> {
1006    fn into(self) -> [T; 3] {
1007        self.to_array()
1008    }
1009}
1010
1011impl<T: Copy, U> From<[T; 3]> for TypedVector3D<T, U> {
1012    fn from(array: [T; 3]) -> Self {
1013        vec3(array[0], array[1], array[2])
1014    }
1015}
1016
1017impl<T: Copy, U> Into<(T, T, T)> for TypedVector3D<T, U> {
1018    fn into(self) -> (T, T, T) {
1019        self.to_tuple()
1020    }
1021}
1022
1023impl<T: Copy, U> From<(T, T, T)> for TypedVector3D<T, U> {
1024    fn from(tuple: (T, T, T)) -> Self {
1025        vec3(tuple.0, tuple.1, tuple.2)
1026    }
1027}
1028
1029impl<T, U> TypedVector3D<T, U>
1030where
1031    T: Signed,
1032{
1033    pub fn abs(&self) -> Self {
1034        vec3(self.x.abs(), self.y.abs(), self.z.abs())
1035    }
1036}
1037
1038#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
1039pub struct BoolVector2D {
1040    pub x: bool,
1041    pub y: bool,
1042}
1043
1044#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
1045pub struct BoolVector3D {
1046    pub x: bool,
1047    pub y: bool,
1048    pub z: bool,
1049}
1050
1051impl BoolVector2D {
1052    #[inline]
1053    pub fn all(&self) -> bool {
1054        self.x && self.y
1055    }
1056
1057    #[inline]
1058    pub fn any(&self) -> bool {
1059        self.x || self.y
1060    }
1061
1062    #[inline]
1063    pub fn none(&self) -> bool {
1064        !self.any()
1065    }
1066
1067    #[inline]
1068    pub fn and(&self, other: Self) -> Self {
1069        BoolVector2D {
1070            x: self.x && other.x,
1071            y: self.y && other.y,
1072        }
1073    }
1074
1075    #[inline]
1076    pub fn or(&self, other: Self) -> Self {
1077        BoolVector2D {
1078            x: self.x || other.x,
1079            y: self.y || other.y,
1080        }
1081    }
1082
1083    #[inline]
1084    pub fn not(&self) -> Self {
1085        BoolVector2D {
1086            x: !self.x,
1087            y: !self.y,
1088        }
1089    }
1090
1091    #[inline]
1092    pub fn select_point<T: Copy, U>(&self, a: &TypedPoint2D<T, U>, b: &TypedPoint2D<T, U>) -> TypedPoint2D<T, U> {
1093        point2(
1094            if self.x { a.x } else { b.x },
1095            if self.y { a.y } else { b.y },
1096        )
1097    }
1098
1099    #[inline]
1100    pub fn select_vector<T: Copy, U>(&self, a: &TypedVector2D<T, U>, b: &TypedVector2D<T, U>) -> TypedVector2D<T, U> {
1101        vec2(
1102            if self.x { a.x } else { b.x },
1103            if self.y { a.y } else { b.y },
1104        )
1105    }
1106
1107    #[inline]
1108    pub fn select_size<T: Copy, U>(&self, a: &TypedSize2D<T, U>, b: &TypedSize2D<T, U>) -> TypedSize2D<T, U> {
1109        size2(
1110            if self.x { a.width } else { b.width },
1111            if self.y { a.height } else { b.height },
1112        )
1113    }
1114}
1115
1116impl BoolVector3D {
1117    #[inline]
1118    pub fn all(&self) -> bool {
1119        self.x && self.y && self.z
1120    }
1121
1122    #[inline]
1123    pub fn any(&self) -> bool {
1124        self.x || self.y || self.z
1125    }
1126
1127    #[inline]
1128    pub fn none(&self) -> bool {
1129        !self.any()
1130    }
1131
1132    #[inline]
1133    pub fn and(&self, other: Self) -> Self {
1134        BoolVector3D {
1135            x: self.x && other.x,
1136            y: self.y && other.y,
1137            z: self.z && other.z,
1138        }
1139    }
1140
1141    #[inline]
1142    pub fn or(&self, other: Self) -> Self {
1143        BoolVector3D {
1144            x: self.x || other.x,
1145            y: self.y || other.y,
1146            z: self.z || other.z,
1147        }
1148    }
1149
1150    #[inline]
1151    pub fn not(&self) -> Self {
1152        BoolVector3D {
1153            x: !self.x,
1154            y: !self.y,
1155            z: !self.z,
1156        }
1157    }
1158
1159
1160    #[inline]
1161    pub fn select_point<T: Copy, U>(&self, a: &TypedPoint3D<T, U>, b: &TypedPoint3D<T, U>) -> TypedPoint3D<T, U> {
1162        point3(
1163            if self.x { a.x } else { b.x },
1164            if self.y { a.y } else { b.y },
1165            if self.z { a.z } else { b.z },
1166        )
1167    }
1168
1169    #[inline]
1170    pub fn select_vector<T: Copy, U>(&self, a: &TypedVector3D<T, U>, b: &TypedVector3D<T, U>) -> TypedVector3D<T, U> {
1171        vec3(
1172            if self.x { a.x } else { b.x },
1173            if self.y { a.y } else { b.y },
1174            if self.z { a.z } else { b.z },
1175        )
1176    }
1177
1178    #[inline]
1179    pub fn xy(&self) -> BoolVector2D {
1180        BoolVector2D {
1181            x: self.x,
1182            y: self.y,
1183        }
1184    }
1185
1186    #[inline]
1187    pub fn xz(&self) -> BoolVector2D {
1188        BoolVector2D {
1189            x: self.x,
1190            y: self.z,
1191        }
1192    }
1193
1194    #[inline]
1195    pub fn yz(&self) -> BoolVector2D {
1196        BoolVector2D {
1197            x: self.y,
1198            y: self.z,
1199        }
1200    }
1201}
1202
1203impl<T: PartialOrd, U> TypedVector2D<T, U> {
1204    pub fn greater_than(&self, other: &Self) -> BoolVector2D {
1205        BoolVector2D {
1206            x: self.x > other.x,
1207            y: self.y > other.y,
1208        }
1209    }
1210
1211    pub fn lower_than(&self, other: &Self) -> BoolVector2D {
1212        BoolVector2D {
1213            x: self.x < other.x,
1214            y: self.y < other.y,
1215        }
1216    }
1217}
1218
1219
1220impl<T: PartialEq, U> TypedVector2D<T, U> {
1221    pub fn equal(&self, other: &Self) -> BoolVector2D {
1222        BoolVector2D {
1223            x: self.x == other.x,
1224            y: self.y == other.y,
1225        }
1226    }
1227
1228    pub fn not_equal(&self, other: &Self) -> BoolVector2D {
1229        BoolVector2D {
1230            x: self.x != other.x,
1231            y: self.y != other.y,
1232        }
1233    }
1234}
1235
1236impl<T: PartialOrd, U> TypedVector3D<T, U> {
1237    pub fn greater_than(&self, other: &Self) -> BoolVector3D {
1238        BoolVector3D {
1239            x: self.x > other.x,
1240            y: self.y > other.y,
1241            z: self.z > other.z,
1242        }
1243    }
1244
1245    pub fn lower_than(&self, other: &Self) -> BoolVector3D {
1246        BoolVector3D {
1247            x: self.x < other.x,
1248            y: self.y < other.y,
1249            z: self.z < other.z,
1250        }
1251    }
1252}
1253
1254
1255impl<T: PartialEq, U> TypedVector3D<T, U> {
1256    pub fn equal(&self, other: &Self) -> BoolVector3D {
1257        BoolVector3D {
1258            x: self.x == other.x,
1259            y: self.y == other.y,
1260            z: self.z == other.z,
1261        }
1262    }
1263
1264    pub fn not_equal(&self, other: &Self) -> BoolVector3D {
1265        BoolVector3D {
1266            x: self.x != other.x,
1267            y: self.y != other.y,
1268            z: self.z != other.z,
1269        }
1270    }
1271}
1272
1273/// Convenience constructor.
1274#[inline]
1275pub fn vec2<T, U>(x: T, y: T) -> TypedVector2D<T, U> {
1276    TypedVector2D::new(x, y)
1277}
1278
1279/// Convenience constructor.
1280#[inline]
1281pub fn vec3<T, U>(x: T, y: T, z: T) -> TypedVector3D<T, U> {
1282    TypedVector3D::new(x, y, z)
1283}
1284
1285#[inline]
1286pub fn bvec2(x: bool, y: bool) -> BoolVector2D {
1287    BoolVector2D { x, y }
1288}
1289
1290#[inline]
1291pub fn bvec3(x: bool, y: bool, z: bool) -> BoolVector3D {
1292    BoolVector3D { x, y, z }
1293}
1294
1295
1296#[cfg(test)]
1297mod vector2d {
1298    use super::{Vector2D, vec2};
1299    #[cfg(feature = "mint")]
1300    use mint;
1301    type Vec2 = Vector2D<f32>;
1302
1303    #[test]
1304    pub fn test_scalar_mul() {
1305        let p1: Vec2 = vec2(3.0, 5.0);
1306
1307        let result = p1 * 5.0;
1308
1309        assert_eq!(result, Vector2D::new(15.0, 25.0));
1310    }
1311
1312    #[test]
1313    pub fn test_dot() {
1314        let p1: Vec2 = vec2(2.0, 7.0);
1315        let p2: Vec2 = vec2(13.0, 11.0);
1316        assert_eq!(p1.dot(p2), 103.0);
1317    }
1318
1319    #[test]
1320    pub fn test_cross() {
1321        let p1: Vec2 = vec2(4.0, 7.0);
1322        let p2: Vec2 = vec2(13.0, 8.0);
1323        let r = p1.cross(p2);
1324        assert_eq!(r, -59.0);
1325    }
1326
1327    #[test]
1328    pub fn test_normalize() {
1329        let p0: Vec2 = Vec2::zero();
1330        let p1: Vec2 = vec2(4.0, 0.0);
1331        let p2: Vec2 = vec2(3.0, -4.0);
1332        assert!(p0.normalize().x.is_nan() && p0.normalize().y.is_nan());
1333        assert_eq!(p1.normalize(), vec2(1.0, 0.0));
1334        assert_eq!(p2.normalize(), vec2(0.6, -0.8));
1335
1336        let p3: Vec2 = vec2(::std::f32::MAX, ::std::f32::MAX);
1337        assert_ne!(p3.normalize(), vec2(1.0 / 2.0f32.sqrt(), 1.0 / 2.0f32.sqrt()));
1338        assert_eq!(p3.robust_normalize(), vec2(1.0 / 2.0f32.sqrt(), 1.0 / 2.0f32.sqrt()));
1339    }
1340
1341    #[test]
1342    pub fn test_min() {
1343        let p1: Vec2 = vec2(1.0, 3.0);
1344        let p2: Vec2 = vec2(2.0, 2.0);
1345
1346        let result = p1.min(p2);
1347
1348        assert_eq!(result, vec2(1.0, 2.0));
1349    }
1350
1351    #[test]
1352    pub fn test_max() {
1353        let p1: Vec2 = vec2(1.0, 3.0);
1354        let p2: Vec2 = vec2(2.0, 2.0);
1355
1356        let result = p1.max(p2);
1357
1358        assert_eq!(result, vec2(2.0, 3.0));
1359    }
1360    #[test]
1361    pub fn test_angle_from_x_axis() {
1362        use core::f32::consts::FRAC_PI_2;
1363        use approxeq::ApproxEq;
1364
1365        let right: Vec2 = vec2(10.0, 0.0);
1366        let down: Vec2 = vec2(0.0, 4.0);
1367        let up: Vec2 = vec2(0.0, -1.0);
1368
1369        assert!(right.angle_from_x_axis().get().approx_eq(&0.0));
1370        assert!(down.angle_from_x_axis().get().approx_eq(&FRAC_PI_2));
1371        assert!(up.angle_from_x_axis().get().approx_eq(&-FRAC_PI_2));
1372    }
1373
1374    #[cfg(feature = "mint")]
1375    #[test]
1376    pub fn test_mint() {
1377        let v1 = Vec2::new(1.0, 3.0);
1378        let vm: mint::Vector2<_> = v1.into();
1379        let v2 = Vec2::from(vm);
1380
1381        assert_eq!(v1, v2);
1382    }
1383}
1384
1385#[cfg(test)]
1386mod typedvector2d {
1387    use super::{TypedVector2D, Vector2D, vec2};
1388    use scale::TypedScale;
1389
1390    pub enum Mm {}
1391    pub enum Cm {}
1392
1393    pub type Vector2DMm<T> = TypedVector2D<T, Mm>;
1394    pub type Vector2DCm<T> = TypedVector2D<T, Cm>;
1395
1396    #[test]
1397    pub fn test_add() {
1398        let p1 = Vector2DMm::new(1.0, 2.0);
1399        let p2 = Vector2DMm::new(3.0, 4.0);
1400
1401        let result = p1 + p2;
1402
1403        assert_eq!(result, vec2(4.0, 6.0));
1404    }
1405
1406    #[test]
1407    pub fn test_add_assign() {
1408        let mut p1 = Vector2DMm::new(1.0, 2.0);
1409        p1 += vec2(3.0, 4.0);
1410
1411        assert_eq!(p1, vec2(4.0, 6.0));
1412    }
1413
1414    #[test]
1415    pub fn test_scalar_mul() {
1416        let p1 = Vector2DMm::new(1.0, 2.0);
1417        let cm_per_mm = TypedScale::<f32, Mm, Cm>::new(0.1);
1418
1419        let result: Vector2DCm<f32> = p1 * cm_per_mm;
1420
1421        assert_eq!(result, vec2(0.1, 0.2));
1422    }
1423
1424    #[test]
1425    pub fn test_swizzling() {
1426        let p: Vector2D<i32> = vec2(1, 2);
1427        assert_eq!(p.yx(), vec2(2, 1));
1428    }
1429}
1430
1431#[cfg(test)]
1432mod vector3d {
1433    #[cfg(feature = "mint")]
1434    use mint;
1435    use super::{TypedVector3D, Vector3D, vec2, vec3};
1436    use scale::TypedScale;
1437
1438    type Vec3 = Vector3D<f32>;
1439
1440    #[test]
1441    pub fn test_dot() {
1442        let p1: Vec3 = vec3(7.0, 21.0, 32.0);
1443        let p2: Vec3 = vec3(43.0, 5.0, 16.0);
1444        assert_eq!(p1.dot(p2), 918.0);
1445    }
1446
1447    #[test]
1448    pub fn test_cross() {
1449        let p1: Vec3 = vec3(4.0, 7.0, 9.0);
1450        let p2: Vec3 = vec3(13.0, 8.0, 3.0);
1451        let p3 = p1.cross(p2);
1452        assert_eq!(p3, vec3(-51.0, 105.0, -59.0));
1453    }
1454
1455    #[test]
1456    pub fn test_normalize() {
1457        let p0: Vec3 = Vec3::zero();
1458        let p1: Vec3 = vec3(0.0, -6.0, 0.0);
1459        let p2: Vec3 = vec3(1.0, 2.0, -2.0);
1460        assert!(
1461            p0.normalize().x.is_nan() && p0.normalize().y.is_nan() && p0.normalize().z.is_nan()
1462        );
1463        assert_eq!(p1.normalize(), vec3(0.0, -1.0, 0.0));
1464        assert_eq!(p2.normalize(), vec3(1.0 / 3.0, 2.0 / 3.0, -2.0 / 3.0));
1465
1466        let p3: Vec3 = vec3(::std::f32::MAX, ::std::f32::MAX, 0.0);
1467        assert_ne!(p3.normalize(), vec3(1.0 / 2.0f32.sqrt(), 1.0 / 2.0f32.sqrt(), 0.0));
1468        assert_eq!(p3.robust_normalize(), vec3(1.0 / 2.0f32.sqrt(), 1.0 / 2.0f32.sqrt(), 0.0));
1469    }
1470
1471    #[test]
1472    pub fn test_min() {
1473        let p1: Vec3 = vec3(1.0, 3.0, 5.0);
1474        let p2: Vec3 = vec3(2.0, 2.0, -1.0);
1475
1476        let result = p1.min(p2);
1477
1478        assert_eq!(result, vec3(1.0, 2.0, -1.0));
1479    }
1480
1481    #[test]
1482    pub fn test_max() {
1483        let p1: Vec3 = vec3(1.0, 3.0, 5.0);
1484        let p2: Vec3 = vec3(2.0, 2.0, -1.0);
1485
1486        let result = p1.max(p2);
1487
1488        assert_eq!(result, vec3(2.0, 3.0, 5.0));
1489    }
1490
1491    #[test]
1492    pub fn test_clamp() {
1493        let p1: Vec3 = vec3(1.0, -1.0, 5.0);
1494        let p2: Vec3 = vec3(2.0, 5.0, 10.0);
1495        let p3: Vec3 = vec3(-1.0, 2.0, 20.0);
1496
1497        let result = p3.clamp(p1, p2);
1498
1499        assert_eq!(result, vec3(1.0, 2.0, 10.0));
1500    }
1501
1502    #[test]
1503    pub fn test_scalar_mul() {
1504        enum Mm {}
1505        enum Cm {}
1506
1507        let p1 = TypedVector3D::<f32, Mm>::new(1.0, 2.0, 3.0);
1508        let cm_per_mm = TypedScale::<f32, Mm, Cm>::new(0.1);
1509
1510        let result: TypedVector3D<f32, Cm> = p1 * cm_per_mm;
1511
1512        assert_eq!(result, vec3(0.1, 0.2, 0.3));
1513    }
1514
1515    #[test]
1516    pub fn test_swizzling() {
1517        let p: Vector3D<i32> = vec3(1, 2, 3);
1518        assert_eq!(p.xy(), vec2(1, 2));
1519        assert_eq!(p.xz(), vec2(1, 3));
1520        assert_eq!(p.yz(), vec2(2, 3));
1521    }
1522
1523    #[cfg(feature = "mint")]
1524    #[test]
1525    pub fn test_mint() {
1526        let v1 = Vec3::new(1.0, 3.0, 5.0);
1527        let vm: mint::Vector3<_> = v1.into();
1528        let v2 = Vec3::from(vm);
1529
1530        assert_eq!(v1, v2);
1531    }
1532}
1533
1534#[cfg(test)]
1535mod bool_vector {
1536    use super::*;
1537    type Vec2 = Vector2D<f32>;
1538    type Vec3 = Vector3D<f32>;
1539
1540    #[test]
1541    fn test_bvec2() {
1542
1543        assert_eq!(
1544            Vec2::new(1.0, 2.0).greater_than(&Vec2::new(2.0, 1.0)),
1545            bvec2(false, true),
1546        );
1547
1548        assert_eq!(
1549            Vec2::new(1.0, 2.0).lower_than(&Vec2::new(2.0, 1.0)),
1550            bvec2(true, false),
1551        );
1552
1553        assert_eq!(
1554            Vec2::new(1.0, 2.0).equal(&Vec2::new(1.0, 3.0)),
1555            bvec2(true, false),
1556        );
1557
1558        assert_eq!(
1559            Vec2::new(1.0, 2.0).not_equal(&Vec2::new(1.0, 3.0)),
1560            bvec2(false, true),
1561        );
1562
1563        assert!(bvec2(true, true).any());
1564        assert!(bvec2(false, true).any());
1565        assert!(bvec2(true, false).any());
1566        assert!(!bvec2(false, false).any());
1567        assert!(bvec2(false, false).none());
1568        assert!(bvec2(true, true).all());
1569        assert!(!bvec2(false, true).all());
1570        assert!(!bvec2(true, false).all());
1571        assert!(!bvec2(false, false).all());
1572
1573        assert_eq!(bvec2(true, false).not(), bvec2(false, true));
1574        assert_eq!(bvec2(true, false).and(bvec2(true, true)), bvec2(true, false));
1575        assert_eq!(bvec2(true, false).or(bvec2(true, true)), bvec2(true, true));
1576
1577        assert_eq!(
1578            bvec2(true, false).select_vector(&Vec2::new(1.0, 2.0), &Vec2::new(3.0, 4.0)),
1579            Vec2::new(1.0, 4.0),
1580        );
1581    }
1582
1583    #[test]
1584    fn test_bvec3() {
1585
1586        assert_eq!(
1587            Vec3::new(1.0, 2.0, 3.0).greater_than(&Vec3::new(3.0, 2.0, 1.0)),
1588            bvec3(false, false, true),
1589        );
1590
1591        assert_eq!(
1592            Vec3::new(1.0, 2.0, 3.0).lower_than(&Vec3::new(3.0, 2.0, 1.0)),
1593            bvec3(true, false, false),
1594        );
1595
1596        assert_eq!(
1597            Vec3::new(1.0, 2.0, 3.0).equal(&Vec3::new(3.0, 2.0, 1.0)),
1598            bvec3(false, true, false),
1599        );
1600
1601        assert_eq!(
1602            Vec3::new(1.0, 2.0, 3.0).not_equal(&Vec3::new(3.0, 2.0, 1.0)),
1603            bvec3(true, false, true),
1604        );
1605
1606        assert!(bvec3(true, true, false).any());
1607        assert!(bvec3(false, true, false).any());
1608        assert!(bvec3(true, false, false).any());
1609        assert!(!bvec3(false, false, false).any());
1610        assert!(bvec3(false, false, false).none());
1611        assert!(bvec3(true, true, true).all());
1612        assert!(!bvec3(false, true, false).all());
1613        assert!(!bvec3(true, false, false).all());
1614        assert!(!bvec3(false, false, false).all());
1615
1616        assert_eq!(bvec3(true, false, true).not(), bvec3(false, true, false));
1617        assert_eq!(bvec3(true, false, true).and(bvec3(true, true, false)), bvec3(true, false, false));
1618        assert_eq!(bvec3(true, false, false).or(bvec3(true, true, false)), bvec3(true, true, false));
1619
1620        assert_eq!(
1621            bvec3(true, false, true).select_vector(&Vec3::new(1.0, 2.0, 3.0), &Vec3::new(4.0, 5.0, 6.0)),
1622            Vec3::new(1.0, 5.0, 3.0),
1623        );
1624    }
1625
1626}