Skip to main content

physdes/
vector2.rs

1use core::ops::{Add, Div, Mul, Neg, Rem, Sub};
2use num_traits::{Num, Signed, Zero};
3
4/// A 2D vector with x and y components.
5///
6/// ```svgbob
7///        y
8///        ^
9///        |
10///        |
11///        *-----> x
12///       /|
13///      / | y_
14///     /  |
15///    /   |
16///   *----+-----> x
17///  (0,0) x_
18/// ```
19///
20/// # Examples
21///
22/// ```
23/// use physdes::vector2::Vector2;
24///
25/// let v = Vector2::new(3, 4);
26/// assert_eq!(v.x_, 3);
27/// assert_eq!(v.y_, 4);
28/// ```
29#[derive(PartialEq, Eq, Copy, Clone, Hash, Debug, Default)]
30// #[repr(C)]
31#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
32pub struct Vector2<T1, T2> {
33    /// x portion of the Vector2 object
34    pub x_: T1,
35    /// y portion of the Vector2 object
36    pub y_: T2,
37}
38
39impl<T1, T2> Vector2<T1, T2> {
40    /// Creates a new Vector2 with the given x and y values.
41    ///
42    /// # Example
43    ///
44    /// ```
45    /// use physdes::vector2::Vector2;
46    ///
47    /// assert_eq!(Vector2::new(1, 2), Vector2 { x_: 1, y_: 2 });
48    /// assert_eq!(Vector2::new(3, 4), Vector2 { x_: 3, y_: 4 });
49    /// ```
50    #[inline]
51    pub const fn new(x_: T1, y_: T2) -> Self {
52        Vector2 { x_, y_ }
53    }
54}
55
56impl<T1: Clone + Num> Vector2<T1, T1> {
57    /// Computes the dot product of two vectors.
58    ///
59    /// $$\vec{a} \cdot \vec{b} = a_x b_x + a_y b_y$$
60    ///
61    /// # Example
62    ///
63    /// ```
64    /// use physdes::vector2::Vector2;
65    ///
66    /// assert_eq!(Vector2::new(1, 2).dot(&Vector2::new(3, 4)), 11);
67    /// assert_eq!(Vector2::new(3, 4).dot(&Vector2::new(1, 2)), 11);
68    /// ```
69    #[inline]
70    pub fn dot(&self, other: &Self) -> T1 {
71        self.x_.clone() * other.x_.clone() + self.y_.clone() * other.y_.clone()
72    }
73
74    /// Computes the cross product (2D scalar) of two vectors.
75    ///
76    /// $$\vec{a} \times \vec{b} = a_x b_y - a_y b_x$$
77    ///
78    /// # Example
79    ///
80    /// ```
81    /// use physdes::vector2::Vector2;
82    ///
83    /// assert_eq!(Vector2::new(1, 2).cross(&Vector2::new(3, 4)), -2);
84    /// assert_eq!(Vector2::new(3, 4).cross(&Vector2::new(1, 2)), 2);
85    /// ```
86    #[inline]
87    pub fn cross(&self, other: &Self) -> T1 {
88        self.x_.clone() * other.y_.clone() - self.y_.clone() * other.x_.clone()
89    }
90
91    // #[inline]
92    // pub fn norm_sqr(&self) -> T {
93    //     self.dot(self)
94    // }
95
96    /// Multiplies the vector by a scalar factor.
97    ///
98    /// $$\vec{v}' = \vec{v} \times f = (v_x \cdot f,\; v_y \cdot f)$$
99    ///
100    /// # Example
101    ///
102    /// ```
103    /// use physdes::vector2::Vector2;
104    ///
105    /// assert_eq!(Vector2::new(1, 2).scale(3), Vector2::new(3, 6));
106    /// assert_eq!(Vector2::new(3, 4).scale(2), Vector2::new(6, 8));
107    /// ```
108    #[inline]
109    pub fn scale(&self, factor: T1) -> Self {
110        Self::new(self.x_.clone() * factor.clone(), self.y_.clone() * factor)
111    }
112
113    /// Divides the vector by a scalar factor.
114    ///
115    /// $$\vec{v}' = \vec{v} / f = (v_x / f,\; v_y / f)$$
116    ///
117    /// # Example
118    ///
119    /// ```
120    /// use physdes::vector2::Vector2;
121    ///
122    /// assert_eq!(Vector2::new(3, 6).unscale(3), Vector2::new(1, 2));
123    /// assert_eq!(Vector2::new(6, 8).unscale(2), Vector2::new(3, 4));
124    /// ```
125    #[inline]
126    pub fn unscale(&self, factor: T1) -> Self {
127        Self::new(self.x_.clone() / factor.clone(), self.y_.clone() / factor)
128    }
129}
130
131impl<T1: Clone + Signed> Vector2<T1, T1> {
132    /// Computes the L1 norm (Manhattan distance from origin): `|x_| + |y_|`.
133    ///
134    /// $$\|\vec{v}\|_1 = |v_x| + |v_y|$$
135    ///
136    /// [Manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry
137    ///
138    /// # Example
139    ///
140    /// ```
141    /// use physdes::vector2::Vector2;
142    ///
143    /// assert_eq!(Vector2::new(1, 2).l1_norm(), 3);
144    /// assert_eq!(Vector2::new(3, 4).l1_norm(), 7);
145    /// ```
146    #[inline]
147    pub fn l1_norm(&self) -> T1 {
148        self.x_.abs() + self.y_.abs()
149    }
150}
151
152impl<T1: Clone + PartialOrd> Vector2<T1, T1> {
153    /// Computes the Chebyshev (infinity) norm: `max(x_, y_)`.
154    ///
155    /// $$\|\vec{v}\|_\infty = \max(v_x, v_y)$$
156    ///
157    /// Assumes non-negative coordinate values (does not take absolute values internally).
158    ///
159    /// # Example
160    ///
161    /// ```
162    /// use physdes::vector2::Vector2;
163    ///
164    /// assert_eq!(Vector2::new(1, 2).norm_inf(), 2);
165    /// assert_eq!(Vector2::new(3, 4).norm_inf(), 4);
166    /// ```
167    #[inline]
168    pub fn norm_inf(&self) -> T1 {
169        if self.x_ > self.y_ {
170            self.x_.clone()
171        } else {
172            self.y_.clone()
173        }
174    }
175}
176
177// (a, b) + (c, d) == (a + c), (b + d)
178impl<T1: Clone + Num, T2: Clone + Num> Add<Vector2<T1, T2>> for Vector2<T1, T2> {
179    type Output = Self;
180
181    /// Adds two vectors component-wise.
182    ///
183    /// $$\vec{a} + \vec{b} = (a_x + b_x,\; a_y + b_y)$$
184    ///
185    /// # Example
186    ///
187    /// ```
188    /// use physdes::vector2::Vector2;
189    ///
190    /// assert_eq!(Vector2::new(1, 2) + Vector2::new(3, 4), Vector2::new(4, 6));
191    /// ```
192    #[inline]
193    fn add(self, other: Self) -> Self::Output {
194        Self::Output::new(self.x_ + other.x_, self.y_ + other.y_)
195    }
196}
197
198// (a, b) - (c, d) == (a - c), (b - d)
199impl<T1: Clone + Num, T2: Clone + Num> Sub<Vector2<T1, T2>> for Vector2<T1, T2> {
200    type Output = Self;
201
202    /// Subtracts two vectors component-wise.
203    ///
204    /// $$\vec{a} - \vec{b} = (a_x - b_x,\; a_y - b_y)$$
205    ///
206    /// # Example
207    ///
208    /// ```
209    /// use physdes::vector2::Vector2;
210    ///
211    /// assert_eq!(Vector2::new(1, 2) - Vector2::new(3, 4), Vector2::new(-2, -2));
212    /// ```
213    #[inline]
214    fn sub(self, other: Self) -> Self::Output {
215        Self::Output::new(self.x_ - other.x_, self.y_ - other.y_)
216    }
217}
218
219// Op Assign
220
221mod opassign {
222    use core::ops::{AddAssign, DivAssign, MulAssign, SubAssign};
223
224    use num_traits::NumAssign;
225
226    use crate::Vector2;
227
228    impl<T1: Clone + NumAssign, T2: Clone + NumAssign> AddAssign for Vector2<T1, T2> {
229        /// Adds another vector to this one component-wise.
230        ///
231        /// $$\vec{a} \mathrel{+}= \vec{b} \implies (a_x + b_x,\; a_y + b_y)$$
232        ///
233        /// # Example
234        ///
235        /// ```
236        /// use physdes::vector2::Vector2;
237        /// use std::ops::AddAssign;
238        ///
239        /// let mut v = Vector2::new(1, 2);
240        /// let v2 = Vector2::new(3, 4);
241        /// v.add_assign(v2);
242        /// assert_eq!(v, Vector2::new(4, 6));
243        /// ```
244        fn add_assign(&mut self, other: Self) {
245            self.x_ += other.x_;
246            self.y_ += other.y_;
247        }
248    }
249
250    impl<T1: Clone + NumAssign, T2: Clone + NumAssign> SubAssign for Vector2<T1, T2> {
251        /// Subtracts another vector from this one component-wise.
252        ///
253        /// $$\vec{a} \mathrel{-}= \vec{b} \implies (a_x - b_x,\; a_y - b_y)$$
254        ///
255        /// # Example
256        ///
257        /// ```
258        /// use physdes::vector2::Vector2;
259        /// use std::ops::SubAssign;
260        /// let mut v = Vector2::new(1, 2);
261        /// let v2 = Vector2::new(3, 4);
262        /// v.sub_assign(v2);
263        /// assert_eq!(v, Vector2::new(-2, -2));
264        /// ```
265        fn sub_assign(&mut self, other: Self) {
266            self.x_ -= other.x_;
267            self.y_ -= other.y_;
268        }
269    }
270
271    impl<T1: Clone + NumAssign> MulAssign<T1> for Vector2<T1, T1> {
272        /// Multiplies each component of the vector by a scalar.
273        ///
274        /// $$\vec{v} \mathrel{*}= s \implies (v_x \cdot s,\; v_y \cdot s)$$
275        ///
276        /// # Example
277        ///
278        /// ```
279        /// use physdes::vector2::Vector2;
280        /// use std::ops::MulAssign;
281        ///
282        /// let mut v = Vector2::new(1, 2);
283        /// v.mul_assign(3);
284        /// assert_eq!(v, Vector2::new(3, 6));
285        /// ```
286        fn mul_assign(&mut self, other: T1) {
287            self.x_ *= other.clone();
288            self.y_ *= other;
289        }
290    }
291
292    impl<T1: Clone + NumAssign> DivAssign<T1> for Vector2<T1, T1> {
293        /// Divides each component of the vector by a scalar.
294        ///
295        /// $$\vec{v} \mathrel{/}= s \implies (v_x / s,\; v_y / s)$$
296        ///
297        /// # Example
298        ///
299        /// ```
300        /// use physdes::vector2::Vector2;
301        /// use std::ops::DivAssign;
302        ///
303        /// let mut v = Vector2::new(3, 6);
304        /// v.div_assign(3);
305        /// assert_eq!(v, Vector2::new(1, 2));
306        /// ```
307        fn div_assign(&mut self, other: T1) {
308            self.x_ /= other.clone();
309            self.y_ /= other;
310        }
311    }
312
313    macro_rules! forward_op_assign1 {
314        (impl $imp:ident, $method:ident) => {
315            impl<'a, T1: Clone + NumAssign, T2: Clone + NumAssign> $imp<&'a Vector2<T1, T2>>
316                for Vector2<T1, T2>
317            {
318                #[inline]
319                fn $method(&mut self, other: &Self) {
320                    self.$method(other.clone())
321                }
322            }
323        };
324    }
325
326    macro_rules! forward_op_assign2 {
327        (impl $imp:ident, $method:ident) => {
328            impl<'a, T1: Clone + NumAssign> $imp<&'a T1> for Vector2<T1, T1> {
329                #[inline]
330                fn $method(&mut self, other: &T1) {
331                    self.$method(other.clone())
332                }
333            }
334        };
335    }
336
337    forward_op_assign1!(impl AddAssign, add_assign);
338    forward_op_assign1!(impl SubAssign, sub_assign);
339    forward_op_assign2!(impl MulAssign, mul_assign);
340    forward_op_assign2!(impl DivAssign, div_assign);
341}
342
343impl<T1: Clone + Num + Neg<Output = T1>, T2: Clone + Num + Neg<Output = T2>> Neg
344    for Vector2<T1, T2>
345{
346    type Output = Self;
347
348    /// Negates both components of the vector.
349    ///
350    /// $$-\vec{v} = (-v_x,\; -v_y)$$
351    ///
352    /// # Example
353    ///
354    /// ```
355    /// use physdes::vector2::Vector2;
356    ///
357    /// let v = Vector2::new(1, 2);
358    /// assert_eq!(-v, Vector2::new(-1, -2));
359    /// ```
360    #[inline]
361    fn neg(self) -> Self::Output {
362        Self::Output::new(-self.x_, -self.y_)
363    }
364}
365
366impl<T1: Clone + Num + Neg<Output = T1>, T2: Clone + Num + Neg<Output = T2>> Neg
367    for &Vector2<T1, T2>
368{
369    type Output = Vector2<T1, T2>;
370
371    /// Negates both components of a borrowed vector.
372    ///
373    /// $$-\vec{v} = (-v_x,\; -v_y)$$
374    #[inline]
375    fn neg(self) -> Self::Output {
376        -self.clone()
377    }
378}
379
380macro_rules! scalar_arithmetic {
381    (@forward $imp:ident::$method:ident for $($scalar:ident),*) => (
382        impl<'a, T1: Clone + Num> $imp<&'a T1> for Vector2<T1, T1> {
383            type Output = Vector2<T1, T1>;
384
385            #[inline]
386            fn $method(self, other: &T1) -> Self::Output {
387                self.$method(other.clone())
388            }
389        }
390        impl<'a, T1: Clone + Num> $imp<T1> for &'a Vector2<T1, T1> {
391            type Output = Vector2<T1, T1>;
392
393            #[inline]
394            fn $method(self, other: T1) -> Self::Output {
395                self.clone().$method(other)
396            }
397        }
398        impl<'a, 'b, T1: Clone + Num> $imp<&'a T1> for &'b Vector2<T1, T1> {
399            type Output = Vector2<T1, T1>;
400
401            #[inline]
402            fn $method(self, other: &T1) -> Self::Output {
403                self.clone().$method(other.clone())
404            }
405        }
406        $(
407            impl<'a> $imp<&'a Vector2<$scalar, $scalar>> for $scalar {
408                type Output = Vector2<$scalar, $scalar>;
409
410                #[inline]
411                fn $method(self, other: &Vector2<$scalar, $scalar>) -> Vector2<$scalar, $scalar> {
412                    self.$method(other.clone())
413                }
414            }
415            impl<'a> $imp<Vector2<$scalar, $scalar>> for &'a $scalar {
416                type Output = Vector2<$scalar, $scalar>;
417
418                #[inline]
419                fn $method(self, other: Vector2<$scalar, $scalar>) -> Vector2<$scalar, $scalar> {
420                    self.clone().$method(other)
421                }
422            }
423            impl<'a, 'b> $imp<&'a Vector2<$scalar, $scalar>> for &'b $scalar {
424                type Output = Vector2<$scalar, $scalar>;
425
426                #[inline]
427                fn $method(self, other: &Vector2<$scalar, $scalar>) -> Vector2<$scalar, $scalar> {
428                    self.clone().$method(other.clone())
429                }
430            }
431        )*
432    );
433    ($($scalar:ident),*) => (
434        scalar_arithmetic!(@forward Mul::mul for $($scalar),*);
435        // scalar_arithmetic!(@forward Div::div for $($scalar),*);
436        // scalar_arithmetic!(@forward Rem::rem for $($scalar),*);
437
438        $(
439            impl Mul<Vector2<$scalar, $scalar>> for $scalar {
440                type Output = Vector2<$scalar, $scalar>;
441
442                #[inline]
443                fn mul(self, other: Vector2<$scalar, $scalar>) -> Self::Output {
444                    Self::Output::new(self * other.x_, self * other.y_)
445                }
446            }
447
448        )*
449    );
450}
451
452impl<T1: Clone + Num> Mul<T1> for Vector2<T1, T1> {
453    type Output = Vector2<T1, T1>;
454
455    /// Scalar multiplication: $\vec{v} \cdot s = (v_x \cdot s,\; v_y \cdot s)$
456    #[inline]
457    fn mul(self, other: T1) -> Self::Output {
458        Self::Output::new(self.x_ * other.clone(), self.y_ * other)
459    }
460}
461
462impl<T1: Clone + Num> Div<T1> for Vector2<T1, T1> {
463    type Output = Self;
464
465    /// Scalar division: $\vec{v} / s = (v_x / s,\; v_y / s)$
466    #[inline]
467    fn div(self, other: T1) -> Self::Output {
468        Self::Output::new(self.x_ / other.clone(), self.y_ / other)
469    }
470}
471
472impl<T1: Clone + Num> Rem<T1> for Vector2<T1, T1> {
473    type Output = Vector2<T1, T1>;
474
475    /// Scalar remainder: $\vec{v} \bmod s = (v_x \bmod s,\; v_y \bmod s)$
476    #[inline]
477    fn rem(self, other: T1) -> Self::Output {
478        Self::Output::new(self.x_ % other.clone(), self.y_ % other)
479    }
480}
481
482scalar_arithmetic!(usize, u8, u16, u32, u64, u128, isize, i8, i16, i32, i64, i128, f32, f64);
483
484// constants
485impl<T1: Clone + Num + Add, T2: Clone + Num + Add> Zero for Vector2<T1, T2> {
486    /// Zero vector: $\vec{0} = (0, 0)$
487    #[inline]
488    fn zero() -> Self {
489        Self::new(Zero::zero(), Zero::zero())
490    }
491
492    #[inline]
493    fn is_zero(&self) -> bool {
494        self.x_.is_zero() && self.y_.is_zero()
495    }
496
497    #[inline]
498    fn set_zero(&mut self) {
499        self.x_.set_zero();
500        self.y_.set_zero();
501    }
502}
503
504#[cfg(test)]
505mod test {
506    #![allow(non_upper_case_globals)]
507
508    use super::Vector2;
509    use core::f64;
510    use num_traits::Zero;
511    use std::hash;
512
513    fn hash<T: hash::Hash>(item: &T) -> u64 {
514        use std::collections::hash_map::RandomState;
515        use std::hash::{BuildHasher, Hasher};
516        let mut hasher = <RandomState as BuildHasher>::Hasher::new();
517        item.hash(&mut hasher);
518        hasher.finish()
519    }
520
521    pub const _0_0v: Vector2<f64, f64> = Vector2 { x_: 0.0, y_: 0.0 };
522    pub const _1_0v: Vector2<f64, f64> = Vector2 { x_: 1.0, y_: 0.0 };
523    pub const _1_1v: Vector2<f64, f64> = Vector2 { x_: 1.0, y_: 1.0 };
524    pub const _0_1v: Vector2<f64, f64> = Vector2 { x_: 0.0, y_: 1.0 };
525    pub const _neg1_1v: Vector2<f64, f64> = Vector2 { x_: -1.0, y_: 1.0 };
526    pub const _05_05v: Vector2<f64, f64> = Vector2 { x_: 0.5, y_: 0.5 };
527    pub const all_consts: [Vector2<f64, f64>; 5] = [_0_0v, _1_0v, _1_1v, _neg1_1v, _05_05v];
528    pub const _4_2v: Vector2<f64, f64> = Vector2 { x_: 4.0, y_: 2.0 };
529
530    pub const _0_0vv: Vector2<Vector2<f64, f64>, Vector2<f64, f64>> = Vector2 {
531        x_: _0_0v,
532        y_: _0_0v,
533    };
534
535    // vector of vectors
536    pub const _0_0_0_0vv: Vector2<Vector2<f64, f64>, Vector2<f64, f64>> = Vector2 {
537        x_: _0_0v,
538        y_: _0_0v,
539    };
540    pub const _1_0_0_0vv: Vector2<Vector2<f64, f64>, Vector2<f64, f64>> = Vector2 {
541        x_: _1_0v,
542        y_: _0_0v,
543    };
544    pub const _1_1_0_0vv: Vector2<Vector2<f64, f64>, Vector2<f64, f64>> = Vector2 {
545        x_: _1_1v,
546        y_: _0_0v,
547    };
548    pub const _0_1_0_0vv: Vector2<Vector2<f64, f64>, Vector2<f64, f64>> = Vector2 {
549        x_: _0_1v,
550        y_: _0_0v,
551    };
552    pub const _neg1_1_0_0vv: Vector2<Vector2<f64, f64>, Vector2<f64, f64>> = Vector2 {
553        x_: _neg1_1v,
554        y_: _0_0v,
555    };
556    pub const _05_05_0_0vv: Vector2<Vector2<f64, f64>, Vector2<f64, f64>> = Vector2 {
557        x_: _05_05v,
558        y_: _0_0v,
559    };
560    pub const _0_0_1_0vv: Vector2<Vector2<f64, f64>, Vector2<f64, f64>> = Vector2 {
561        x_: _0_0v,
562        y_: _1_0v,
563    };
564    pub const _1_0_1_0vv: Vector2<Vector2<f64, f64>, Vector2<f64, f64>> = Vector2 {
565        x_: _1_0v,
566        y_: _1_0v,
567    };
568    pub const _1_1_1_0vv: Vector2<Vector2<f64, f64>, Vector2<f64, f64>> = Vector2 {
569        x_: _1_1v,
570        y_: _1_0v,
571    };
572    pub const _0_1_1_0vv: Vector2<Vector2<f64, f64>, Vector2<f64, f64>> = Vector2 {
573        x_: _0_1v,
574        y_: _1_0v,
575    };
576    pub const _neg1_1_1_0vv: Vector2<Vector2<f64, f64>, Vector2<f64, f64>> = Vector2 {
577        x_: _neg1_1v,
578        y_: _1_0v,
579    };
580    pub const _05_05_1_0vv: Vector2<Vector2<f64, f64>, Vector2<f64, f64>> = Vector2 {
581        x_: _05_05v,
582        y_: _1_0v,
583    };
584    pub const _0_0_0_1vv: Vector2<Vector2<f64, f64>, Vector2<f64, f64>> = Vector2 {
585        x_: _0_0v,
586        y_: _0_1v,
587    };
588    pub const _1_0_0_1vv: Vector2<Vector2<f64, f64>, Vector2<f64, f64>> = Vector2 {
589        x_: _1_0v,
590        y_: _0_1v,
591    };
592    pub const _1_1_0_1vv: Vector2<Vector2<f64, f64>, Vector2<f64, f64>> = Vector2 {
593        x_: _1_1v,
594        y_: _0_1v,
595    };
596    pub const _0_1_0_1vv: Vector2<Vector2<f64, f64>, Vector2<f64, f64>> = Vector2 {
597        x_: _0_1v,
598        y_: _0_1v,
599    };
600    pub const _neg1_1_0_1vv: Vector2<Vector2<f64, f64>, Vector2<f64, f64>> = Vector2 {
601        x_: _neg1_1v,
602        y_: _0_1v,
603    };
604    pub const _05_05_0_1vv: Vector2<Vector2<f64, f64>, Vector2<f64, f64>> = Vector2 {
605        x_: _05_05v,
606        y_: _0_1v,
607    };
608
609    #[test]
610    fn test_consts() {
611        // check our constants are what Vector2::new creates
612        fn test(vec: Vector2<f64, f64>, x_val: f64, y_val: f64) {
613            assert_eq!(vec, Vector2::new(x_val, y_val));
614        }
615        test(_0_0v, 0.0, 0.0);
616        test(_1_0v, 1.0, 0.0);
617        test(_1_1v, 1.0, 1.0);
618        test(_neg1_1v, -1.0, 1.0);
619        test(_05_05v, 0.5, 0.5);
620        assert_eq!(_0_0v, Zero::zero());
621    }
622
623    #[test]
624    fn test_scale_unscale() {
625        assert_eq!(_05_05v.scale(2.0), _1_1v);
626        assert_eq!(_1_1v.unscale(2.0), _05_05v);
627        for &c in all_consts.iter() {
628            assert_eq!(c.scale(2.0).unscale(2.0), c);
629        }
630    }
631
632    #[test]
633    fn test_hash() {
634        let vec_a = Vector2::new(0i32, 0i32);
635        let vec_b = Vector2::new(1i32, 0i32);
636        let vec_c = Vector2::new(0i32, 1i32);
637        assert!(hash(&vec_a) != hash(&vec_b));
638        assert!(hash(&vec_b) != hash(&vec_c));
639        assert!(hash(&vec_c) != hash(&vec_a));
640    }
641
642    #[test]
643    fn test_zero() {
644        assert_eq!(_0_0v, Vector2::zero());
645    }
646
647    #[test]
648    fn test_is_zero() {
649        assert!(Vector2::<i32, i32>::zero().is_zero());
650        assert!(!_1_1v.is_zero());
651    }
652
653    #[test]
654    fn test_set_zero() {
655        let mut v = _1_1v;
656        v.set_zero();
657        assert!(v.is_zero());
658    }
659
660    #[test]
661    fn test_neg() {
662        assert_eq!(-(-_1_1v), _1_1v);
663    }
664
665    #[test]
666    fn test_scalar_arithmetic() {
667        assert_eq!(_1_1v * 0.5, _05_05v);
668        assert_eq!(_1_1v / 2.0, _05_05v);
669        assert_eq!(_4_2v % 2.0, _0_0v);
670        assert_eq!(0.5 * _1_1v, _05_05v);
671    }
672
673    #[test]
674    fn test_scalar_arithmetic_ref() {
675        assert_eq!(_1_1v * 0.5, _05_05v);
676        assert_eq!(0.5 * _1_1v, _05_05v);
677    }
678
679    #[test]
680    fn test_dot() {
681        assert_eq!(_1_1v.dot(&_1_1v), 2.0);
682        assert_eq!(_1_1v.dot(&_neg1_1v), 0.0);
683        assert_eq!(_1_1v.dot(&_0_1v), 1.0);
684    }
685
686    #[test]
687    fn test_cross() {
688        assert_eq!(_1_1v.cross(&_1_1v), 0.0);
689        assert_eq!(_1_1v.cross(&_neg1_1v), 2.0);
690        assert_eq!(_1_1v.cross(&_0_1v), 1.0);
691    }
692
693    // #[test]
694    // fn test_norm_sqr() {
695    //     assert_eq!(_1_1v.norm_sqr(), 2.0);
696    //     assert_eq!(_0_1v.norm_sqr(), 1.0);
697    //     assert_eq!(_neg1_1v.norm_sqr(), 2.0);
698    //     assert_eq!(_05_05v.norm_sqr(), 0.5);
699    //     assert_eq!(_1_0v.norm_sqr(), 1.0);
700    //     assert_eq!(_0_0v.norm_sqr(), 0.0);
701    //     assert_eq!(_4_2v.norm_sqr(), 20.0);
702    // }
703
704    #[test]
705    fn test_l1_norm() {
706        assert_eq!(_1_1v.l1_norm(), 2.0);
707        assert_eq!(_0_1v.l1_norm(), 1.0);
708        assert_eq!(_neg1_1v.l1_norm(), 2.0);
709        assert_eq!(_05_05v.l1_norm(), 1.0);
710        assert_eq!(_1_0v.l1_norm(), 1.0);
711        assert_eq!(_0_0v.l1_norm(), 0.0);
712        assert_eq!(_4_2v.l1_norm(), 6.0);
713    }
714
715    #[test]
716    fn test_norm_inf() {
717        assert_eq!(_1_1v.norm_inf(), 1.0);
718        assert_eq!(_0_1v.norm_inf(), 1.0);
719        assert_eq!(_neg1_1v.norm_inf(), 1.0);
720        assert_eq!(_05_05v.norm_inf(), 0.5);
721        assert_eq!(_1_0v.norm_inf(), 1.0);
722        assert_eq!(_0_0v.norm_inf(), 0.0);
723        assert_eq!(_4_2v.norm_inf(), 4.0);
724    }
725
726    #[test]
727    fn test_add_assign() {
728        let mut vec_a = _0_1v;
729        vec_a += _1_0v;
730        assert_eq!(vec_a, _1_1v);
731    }
732
733    #[test]
734    fn test_sub_assign() {
735        let mut vec_a = _1_1v;
736        vec_a -= _1_1v;
737        assert_eq!(vec_a, _0_0v);
738    }
739
740    #[test]
741    fn test_mul_assign() {
742        let mut vec_a = _05_05v;
743        vec_a *= 2.0;
744        assert_eq!(vec_a, _1_1v);
745    }
746
747    #[test]
748    fn test_div_assign() {
749        let mut vec_a = _1_1v;
750        vec_a /= 2.0;
751        assert_eq!(vec_a, _05_05v);
752    }
753
754    #[test]
755    fn test_rem() {
756        assert_eq!(_4_2v % 3.0, Vector2::new(1.0, 2.0));
757    }
758
759    #[test]
760    fn test_sub_more() {
761        assert_eq!(_1_1v - _0_1v, _1_0v);
762        assert_eq!(_0_1v - _1_0v, Vector2::new(-1.0, 1.0));
763    }
764
765    #[test]
766    fn test_add_more() {
767        assert_eq!(_1_0v + _0_1v, _1_1v);
768    }
769
770    #[test]
771    fn test_mul_more() {
772        assert_eq!(_1_1v * 2.0, Vector2::new(2.0, 2.0));
773    }
774
775    #[test]
776    fn test_dot_more_cases() {
777        assert_eq!(_0_0v.dot(&_1_1v), 0.0);
778        assert_eq!(_1_1v.dot(&_0_0v), 0.0);
779        assert_eq!(_neg1_1v.dot(&_1_1v), 0.0);
780    }
781
782    #[test]
783    fn test_cross_more_cases() {
784        assert_eq!(_0_0v.cross(&_1_1v), 0.0);
785        assert_eq!(_1_1v.cross(&_0_0v), 0.0);
786        assert_eq!(_neg1_1v.cross(&_1_1v), -2.0);
787    }
788
789    #[test]
790    fn test_l1_norm_more_cases() {
791        assert_eq!(_0_0v.l1_norm(), 0.0);
792        assert_eq!(_neg1_1v.l1_norm(), 2.0);
793    }
794
795    #[test]
796    fn test_norm_inf_more_cases() {
797        assert_eq!(_0_0v.norm_inf(), 0.0);
798        assert_eq!(_neg1_1v.norm_inf(), 1.0);
799    }
800
801    #[test]
802    fn test_scalar_arithmetic_more_cases() {
803        assert_eq!(_0_0v * 2.0, _0_0v);
804        assert_eq!(_1_1v * 0.0, _0_0v);
805        assert_eq!(_1_1v * 1.0, _1_1v);
806        assert_eq!(_1_1v * -1.0, -_1_1v);
807    }
808
809    #[test]
810    fn test_consts_vv() {
811        // check our constants are what Vector2::new creates
812        fn test(
813            vec: Vector2<Vector2<f64, f64>, Vector2<f64, f64>>,
814            w_val: f64,
815            x_val: f64,
816            y_val: f64,
817            z_val: f64,
818        ) {
819            assert_eq!(
820                vec,
821                Vector2::new(Vector2::new(w_val, x_val), Vector2::new(y_val, z_val))
822            );
823        }
824
825        test(_0_0vv, 0.0, 0.0, 0.0, 0.0);
826        test(_0_0_0_0vv, 0.0, 0.0, 0.0, 0.0);
827        test(_1_0_0_0vv, 1.0, 0.0, 0.0, 0.0);
828        test(_1_1_0_0vv, 1.0, 1.0, 0.0, 0.0);
829        test(_0_1_0_0vv, 0.0, 1.0, 0.0, 0.0);
830        test(_neg1_1_0_0vv, -1.0, 1.0, 0.0, 0.0);
831        test(_05_05_0_0vv, 0.5, 0.5, 0.0, 0.0);
832        test(_0_0_1_0vv, 0.0, 0.0, 1.0, 0.0);
833        test(_1_0_1_0vv, 1.0, 0.0, 1.0, 0.0);
834        test(_1_1_1_0vv, 1.0, 1.0, 1.0, 0.0);
835        test(_0_1_1_0vv, 0.0, 1.0, 1.0, 0.0);
836        test(_neg1_1_1_0vv, -1.0, 1.0, 1.0, 0.0);
837        test(_05_05_1_0vv, 0.5, 0.5, 1.0, 0.0);
838    }
839
840    // #[test]
841    // fn test_scale_unscale_vv() {
842    //     assert_eq!(_05_05_0_0vv.scale(2.0), _1_1_0_0vv);
843    //     assert_eq!(_1_1_0_0vv.unscale(2.0), _05_05_0_0vv);
844    //     for &c in all_consts_vv.iter() {
845    //         assert_eq!(c.scale(2.0).unscale(2.0), c);
846    //     }
847    // }
848
849    #[test]
850    #[allow(clippy::op_ref, clippy::clone_on_copy)]
851    fn test_mul_ref_scalar() {
852        let v = Vector2::new(3, 4);
853        let s = 2i32;
854
855        assert_eq!(v.clone() * &s, Vector2::new(6, 8));
856        assert_eq!(&v * s, Vector2::new(6, 8));
857        assert_eq!(&v * &s, Vector2::new(6, 8));
858    }
859
860    #[test]
861    #[allow(clippy::op_ref, clippy::clone_on_copy)]
862    fn test_scalar_mul_vec_ref() {
863        let v = Vector2::new(3, 4);
864        let s = 2i32;
865
866        assert_eq!(s * &v, Vector2::new(6, 8));
867        assert_eq!(&s * v.clone(), Vector2::new(6, 8));
868        assert_eq!(&s * &v, Vector2::new(6, 8));
869    }
870}
871
872#[test]
873fn test_neg_ref() {
874    let v = &Vector2::new(1, 2);
875    let neg_v = -v;
876    assert_eq!(neg_v, Vector2::new(-1, -2));
877}
878
879#[test]
880fn test_ref_add_assign_ref() {
881    let mut v1 = Vector2::new(1.0, 2.0);
882    let v2 = &Vector2::new(3.0, 4.0);
883    v1 += v2;
884    assert_eq!(v1, Vector2::new(4.0, 6.0));
885}
886
887#[test]
888fn test_ref_sub_assign_ref() {
889    let mut v1 = Vector2::new(5.0, 7.0);
890    let v2 = &Vector2::new(2.0, 3.0);
891    v1 -= v2;
892    assert_eq!(v1, Vector2::new(3.0, 4.0));
893}
894
895#[test]
896fn test_ref_mul_assign_ref() {
897    let mut v = Vector2::new(2.0, 3.0);
898    let scalar = &2.0;
899    v *= scalar;
900    assert_eq!(v, Vector2::new(4.0, 6.0));
901}
902
903#[test]
904fn test_ref_div_assign_ref() {
905    let mut v = Vector2::new(6.0, 8.0);
906    let scalar = &2.0;
907    v /= scalar;
908    assert_eq!(v, Vector2::new(3.0, 4.0));
909}
910
911#[test]
912fn test_mul_integer_types() {
913    let v = Vector2::new(2i32, 3i32);
914    assert_eq!(v * 2i32, Vector2::new(4, 6));
915
916    let v2 = Vector2::new(2u8, 3u8);
917    assert_eq!(v2 * 2u8, Vector2::new(4, 6));
918}
919
920#[test]
921fn test_neg_edge_cases() {
922    let v_zero = Vector2::new(0.0, 0.0);
923    assert_eq!(-v_zero, Vector2::new(-0.0, -0.0));
924
925    let v_neg = Vector2::new(-1.0, -2.0);
926    assert_eq!(-v_neg, Vector2::new(1.0, 2.0));
927}
928
929#[test]
930fn test_scalar_mul_i32_ref() {
931    let v = Vector2::new(2i32, 3i32);
932    let result = v * 2i32;
933    assert_eq!(result, Vector2::new(4, 6));
934}