physdes/
vector2.rs

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