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")]
15use 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<T> {
30    /// x portion of the Vector2 object
31    pub x_: T,
32    /// y portion of the Vector2 object
33    pub y_: T,
34}
35
36impl<T> Vector2<T> {
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_: T, y_: T) -> Self {
60        Vector2 { x_, y_ }
61    }
62}
63
64impl<T: Clone + Num> Vector2<T> {
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) -> T {
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    /// Returns:
97    ///
98    /// The cross product of two vectors is being returned.
99    /// Returns the cross product
100    ///
101    /// # Example
102    ///
103    /// ```
104    /// use physdes::vector2::Vector2;
105    ///
106    /// assert_eq!(Vector2::new(1, 2).cross(&Vector2::new(3, 4)), -2);
107    /// assert_eq!(Vector2::new(3, 4).cross(&Vector2::new(1, 2)), 2);
108    /// ```
109    #[inline]
110    pub fn cross(&self, other: &Self) -> T {
111        self.x_.clone() * other.y_.clone() - self.y_.clone() * other.x_.clone()
112    }
113
114    /// The `norm_sqr` function calculates the square of the norm of a vector.
115    ///
116    /// Returns:
117    ///
118    /// The `norm_sqr` function returns the squared norm of the object on which it is called.
119    ///
120    /// # Example
121    ///
122    /// ```
123    /// use physdes::vector2::Vector2;
124    ///
125    /// assert_eq!(Vector2::new(1, 2).norm_sqr(), 5);
126    /// assert_eq!(Vector2::new(3, 4).norm_sqr(), 25);
127    /// ```
128    #[inline]
129    pub fn norm_sqr(&self) -> T {
130        self.dot(self)
131    }
132
133    /// The `scale` function multiplies the vector by a scalar value.
134    ///
135    /// Arguments:
136    ///
137    /// * `t`: The parameter `t` is a scalar value that will be used to multiply each component of
138    /// `self`.
139    ///
140    /// Returns:
141    ///
142    /// The `scale` method returns a new instance of the same type as `self`.
143    /// Multiplies `self` by the scalar `t`.
144    ///
145    /// # Example
146    ///
147    /// ```
148    /// use physdes::vector2::Vector2;
149    ///
150    /// assert_eq!(Vector2::new(1, 2).scale(3), Vector2::new(3, 6));
151    /// assert_eq!(Vector2::new(3, 4).scale(2), Vector2::new(6, 8));
152    /// ```
153    #[inline]
154    pub fn scale(&self, t: T) -> Self {
155        Self::new(self.x_.clone() * t.clone(), self.y_.clone() * t)
156    }
157
158    /// The `unscale` function divides the coordinates of a vector by a scalar value.
159    ///
160    /// Arguments:
161    ///
162    /// * `t`: The parameter `t` is a scalar value that is used to divide the `self` object. It is of
163    /// type `T`, which is a generic type parameter. The division operation is performed on the `x_` and
164    /// `y_` fields of the `self` object.
165    ///
166    /// Returns:
167    ///
168    /// The `unscale` method returns a new instance of the same type as `self`.
169    /// Divides `self` by the scalar `t`.
170    ///
171    /// # Example
172    ///
173    /// ```
174    /// use physdes::vector2::Vector2;
175    ///
176    /// assert_eq!(Vector2::new(3, 6).unscale(3), Vector2::new(1, 2));
177    /// assert_eq!(Vector2::new(6, 8).unscale(2), Vector2::new(3, 4));
178    /// ```
179    #[inline]
180    pub fn unscale(&self, t: T) -> Self {
181        Self::new(self.x_.clone() / t.clone(), self.y_.clone() / t)
182    }
183}
184
185impl<T: Clone + Signed> Vector2<T> {
186    /// The `l1_norm` function calculates the Manhattan distance from the origin.
187    ///
188    /// [Manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry
189    ///
190    /// Returns:
191    ///
192    /// The L1 norm, which is the Manhattan distance from the origin.
193    /// Returns the L1 norm `|x_| + |y_|` -- the [Manhattan distance] from the origin.
194    ///
195    /// # Example
196    ///
197    /// ```
198    /// use physdes::vector2::Vector2;
199    ///
200    /// assert_eq!(Vector2::new(1, 2).l1_norm(), 3);
201    /// assert_eq!(Vector2::new(3, 4).l1_norm(), 7);
202    /// ```
203    #[inline]
204    pub fn l1_norm(&self) -> T {
205        self.x_.abs() + self.y_.abs()
206    }
207}
208
209impl<T: Clone + PartialOrd> Vector2<T> {
210    /// The `norm_inf` function returns the maximum absolute value between `x_` and `y_`.
211    ///
212    /// Returns:
213    ///
214    /// The `norm_inf` function returns the maximum value between `|x_|` and `|y_|`.
215    /// Returns the infinity norm `max(|x_| + |y_|)`
216    ///
217    /// # Example
218    ///
219    /// ```
220    /// use physdes::vector2::Vector2;
221    ///
222    /// assert_eq!(Vector2::new(1, 2).norm_inf(), 2);
223    /// assert_eq!(Vector2::new(3, 4).norm_inf(), 4);
224    /// ```
225    #[inline]
226    pub fn norm_inf(&self) -> T {
227        if self.x_ > self.y_ {
228            self.x_.clone()
229        } else {
230            self.y_.clone()
231        }
232    }
233}
234
235macro_rules! forward_xf_xf_binop {
236    (impl $imp:ident, $method:ident) => {
237        impl<'a, 'b, T: Clone + Num> $imp<&'b Vector2<T>> for &'a Vector2<T> {
238            type Output = Vector2<T>;
239
240            /// The function clones the input arguments and calls the specified method on them.
241            ///
242            /// Arguments:
243            ///
244            /// * `other`: A reference to another Vector2 object of the same type as self.
245            #[inline]
246            fn $method(self, other: &Vector2<T>) -> Self::Output {
247                self.clone().$method(other.clone())
248            }
249        }
250    };
251}
252
253macro_rules! forward_xf_val_binop {
254    (impl $imp:ident, $method:ident) => {
255        impl<'a, T: Clone + Num> $imp<Vector2<T>> for &'a Vector2<T> {
256            type Output = Vector2<T>;
257
258            #[inline]
259            fn $method(self, other: Vector2<T>) -> Self::Output {
260                self.clone().$method(other)
261            }
262        }
263    };
264}
265
266macro_rules! forward_val_xf_binop {
267    (impl $imp:ident, $method:ident) => {
268        impl<'a, T: Clone + Num> $imp<&'a Vector2<T>> for Vector2<T> {
269            type Output = Vector2<T>;
270
271            #[inline]
272            fn $method(self, other: &Vector2<T>) -> Self::Output {
273                self.$method(other.clone())
274            }
275        }
276    };
277}
278
279macro_rules! forward_all_binop {
280    (impl $imp:ident, $method:ident) => {
281        forward_xf_xf_binop!(impl $imp, $method);
282        forward_xf_val_binop!(impl $imp, $method);
283        forward_val_xf_binop!(impl $imp, $method);
284    };
285}
286
287// arithmetic
288forward_all_binop!(impl Add, add);
289
290// (a, b) + (c, d) == (a + c), (b + d)
291impl<T: Clone + Num> Add<Vector2<T>> for Vector2<T> {
292    type Output = Self;
293
294    /// The function `add` takes two values of the same type and returns their sum.
295    ///
296    /// Arguments:
297    ///
298    /// * `other`: The `other` parameter is of the same type as `self` and represents the other object
299    /// that you want to add to `self`.
300    ///
301    /// # Example
302    ///
303    /// ```
304    /// use physdes::vector2::Vector2;
305    /// use std::ops::Add;
306    ///
307    /// assert_eq!(Vector2::new(1, 2).add(Vector2::new(3, 4)), Vector2::new(4, 6));
308    /// assert_eq!(Vector2::new(3, 4).add(Vector2::new(1, 2)), Vector2::new(4, 6));
309    /// ```
310    #[inline]
311    fn add(self, other: Self) -> Self::Output {
312        Self::Output::new(self.x_ + other.x_, self.y_ + other.y_)
313    }
314}
315
316forward_all_binop!(impl Sub, sub);
317
318// (a, b) - (c, d) == (a - c), (b - d)
319impl<T: Clone + Num> Sub<Vector2<T>> for Vector2<T> {
320    type Output = Self;
321
322    /// The function subtracts the coordinates of two points and returns a new point.
323    ///
324    /// Arguments:
325    ///
326    /// * `other`: The `other` parameter is of the same type as `self` and represents the other value
327    /// that you want to subtract from `self`.
328    ///
329    /// # Example
330    ///
331    /// ```
332    /// use physdes::vector2::Vector2;
333    /// use std::ops::Sub;
334    ///
335    /// assert_eq!(Vector2::new(1, 2).sub(Vector2::new(3, 4)), Vector2::new(-2, -2));
336    /// assert_eq!(Vector2::new(3, 4).sub(Vector2::new(1, 2)), Vector2::new(2, 2));
337    /// ```
338    #[inline]
339    fn sub(self, other: Self) -> Self::Output {
340        Self::Output::new(self.x_ - other.x_, self.y_ - other.y_)
341    }
342}
343
344// Op Assign
345
346mod opassign {
347    use core::ops::{AddAssign, DivAssign, MulAssign, SubAssign};
348
349    use num_traits::NumAssign;
350
351    use crate::Vector2;
352
353    impl<T: Clone + NumAssign> AddAssign for Vector2<T> {
354        /// The function `add_assign` adds the values of `other.x_` and `other.y_` to `self.x_` and
355        /// `self.y_` respectively.
356        ///
357        /// Arguments:
358        ///
359        /// * `other`: The "other" parameter is of type Self, which means it is a reference to another
360        /// instance of the same struct or class that the method is defined in. In this case, it
361        /// represents another instance of the struct or class that has the same fields or properties as
362        /// self.
363        ///
364        /// # Example
365        ///
366        /// ```
367        /// use physdes::vector2::Vector2;
368        /// use std::ops::AddAssign;
369        ///
370        /// let mut v = Vector2::new(1, 2);
371        /// let v2 = Vector2::new(3, 4);
372        /// v.add_assign(v2);
373        /// assert_eq!(v, Vector2::new(4, 6));
374        /// ```
375        fn add_assign(&mut self, other: Self) {
376            self.x_ += other.x_;
377            self.y_ += other.y_;
378        }
379    }
380
381    impl<T: Clone + NumAssign> SubAssign for Vector2<T> {
382        /// The function subtracts the values of another object from the values of the current object.
383        ///
384        /// Arguments:
385        ///
386        /// * `other`: The parameter "other" is of type Self, which means it is a reference to another
387        /// instance of the same struct or class that the method is defined in. In this case, it is a
388        /// reference to another instance of the struct or class that has the same fields as self (x_
389        /// and y
390        ///
391        /// # Example
392        ///
393        /// ```
394        /// use physdes::vector2::Vector2;
395        /// use std::ops::SubAssign;
396        /// let mut v = Vector2::new(1, 2);
397        /// let v2 = Vector2::new(3, 4);
398        /// v.sub_assign(v2);
399        /// assert_eq!(v, Vector2::new(-2, -2));
400        /// ```
401        fn sub_assign(&mut self, other: Self) {
402            self.x_ -= other.x_;
403            self.y_ -= other.y_;
404        }
405    }
406
407    impl<T: Clone + NumAssign> MulAssign<T> for Vector2<T> {
408        /// The function multiplies the values of self.x_ and self.y_ by the value of other.
409        ///
410        /// Arguments:
411        ///
412        /// * `other`: The parameter `other` is of type `T`, which means it can be any type that
413        /// implements the `Clone` trait.
414        ///
415        /// # Example
416        ///
417        /// ```
418        /// use physdes::vector2::Vector2;
419        /// use std::ops::MulAssign;
420        ///
421        /// let mut v = Vector2::new(1, 2);
422        /// v.mul_assign(3);
423        /// assert_eq!(v, Vector2::new(3, 6));
424        /// ```
425        fn mul_assign(&mut self, other: T) {
426            self.x_ *= other.clone();
427            self.y_ *= other;
428        }
429    }
430
431    impl<T: Clone + NumAssign> DivAssign<T> for Vector2<T> {
432        /// The function divides the values of self.x_ and self.y_ by the value of other.
433        ///
434        /// Arguments:
435        ///
436        /// * `other`: The parameter `other` is of type `T`, which means it can be any type that
437        /// implements the `Clone` trait.
438        ///
439        /// # Example
440        ///
441        /// ```
442        /// use physdes::vector2::Vector2;
443        /// use std::ops::DivAssign;
444        ///
445        /// let mut v = Vector2::new(3, 6);
446        /// v.div_assign(3);
447        /// assert_eq!(v, Vector2::new(1, 2));
448        /// ```
449        fn div_assign(&mut self, other: T) {
450            self.x_ /= other.clone();
451            self.y_ /= other;
452        }
453    }
454
455    macro_rules! forward_op_assign1 {
456        (impl $imp:ident, $method:ident) => {
457            impl<'a, T: Clone + NumAssign> $imp<&'a Vector2<T>> for Vector2<T> {
458                #[inline]
459                fn $method(&mut self, other: &Self) {
460                    self.$method(other.clone())
461                }
462            }
463        };
464    }
465
466    macro_rules! forward_op_assign2 {
467        (impl $imp:ident, $method:ident) => {
468            impl<'a, T: Clone + NumAssign> $imp<&'a T> for Vector2<T> {
469                #[inline]
470                fn $method(&mut self, other: &T) {
471                    self.$method(other.clone())
472                }
473            }
474        };
475    }
476
477    forward_op_assign1!(impl AddAssign, add_assign);
478    forward_op_assign1!(impl SubAssign, sub_assign);
479    forward_op_assign2!(impl MulAssign, mul_assign);
480    forward_op_assign2!(impl DivAssign, div_assign);
481}
482
483impl<T: Clone + Num + Neg<Output = T>> Neg for Vector2<T> {
484    type Output = Self;
485
486    /// The `neg` function returns a new instance of the same type with the negated values of `x_` and
487    /// `y_`.
488    ///
489    /// # Example
490    ///
491    /// ```
492    /// use physdes::vector2::Vector2;
493    /// use std::ops::Neg;
494    ///
495    /// let v = Vector2::new(1, 2);
496    /// assert_eq!(-v, Vector2::new(-1, -2));
497    /// ```
498    #[inline]
499    fn neg(self) -> Self::Output {
500        Self::Output::new(-self.x_, -self.y_)
501    }
502}
503
504impl<'a, T: Clone + Num + Neg<Output = T>> Neg for &'a Vector2<T> {
505    type Output = Vector2<T>;
506
507    #[inline]
508    fn neg(self) -> Self::Output {
509        -self.clone()
510    }
511}
512
513macro_rules! scalar_arithmetic {
514    (@forward $imp:ident::$method:ident for $($scalar:ident),*) => (
515        impl<'a, T: Clone + Num> $imp<&'a T> for Vector2<T> {
516            type Output = Vector2<T>;
517
518            #[inline]
519            fn $method(self, other: &T) -> Self::Output {
520                self.$method(other.clone())
521            }
522        }
523        impl<'a, T: Clone + Num> $imp<T> for &'a Vector2<T> {
524            type Output = Vector2<T>;
525
526            #[inline]
527            fn $method(self, other: T) -> Self::Output {
528                self.clone().$method(other)
529            }
530        }
531        impl<'a, 'b, T: Clone + Num> $imp<&'a T> for &'b Vector2<T> {
532            type Output = Vector2<T>;
533
534            #[inline]
535            fn $method(self, other: &T) -> Self::Output {
536                self.clone().$method(other.clone())
537            }
538        }
539        $(
540            impl<'a> $imp<&'a Vector2<$scalar>> for $scalar {
541                type Output = Vector2<$scalar>;
542
543                #[inline]
544                fn $method(self, other: &Vector2<$scalar>) -> Vector2<$scalar> {
545                    self.$method(other.clone())
546                }
547            }
548            impl<'a> $imp<Vector2<$scalar>> for &'a $scalar {
549                type Output = Vector2<$scalar>;
550
551                #[inline]
552                fn $method(self, other: Vector2<$scalar>) -> Vector2<$scalar> {
553                    self.clone().$method(other)
554                }
555            }
556            impl<'a, 'b> $imp<&'a Vector2<$scalar>> for &'b $scalar {
557                type Output = Vector2<$scalar>;
558
559                #[inline]
560                fn $method(self, other: &Vector2<$scalar>) -> Vector2<$scalar> {
561                    self.clone().$method(other.clone())
562                }
563            }
564        )*
565    );
566    ($($scalar:ident),*) => (
567        scalar_arithmetic!(@forward Mul::mul for $($scalar),*);
568        // scalar_arithmetic!(@forward Div::div for $($scalar),*);
569        // scalar_arithmetic!(@forward Rem::rem for $($scalar),*);
570
571        $(
572            impl Mul<Vector2<$scalar>> for $scalar {
573                type Output = Vector2<$scalar>;
574
575                #[inline]
576                fn mul(self, other: Vector2<$scalar>) -> Self::Output {
577                    Self::Output::new(self * other.x_, self * other.y_)
578                }
579            }
580
581        )*
582    );
583}
584
585impl<T: Clone + Num> Mul<T> for Vector2<T> {
586    type Output = Vector2<T>;
587
588    #[inline]
589    fn mul(self, other: T) -> Self::Output {
590        Self::Output::new(self.x_ * other.clone(), self.y_ * other)
591    }
592}
593
594impl<T: Clone + Num> Div<T> for Vector2<T> {
595    type Output = Self;
596
597    #[inline]
598    fn div(self, other: T) -> Self::Output {
599        Self::Output::new(self.x_ / other.clone(), self.y_ / other)
600    }
601}
602
603impl<T: Clone + Num> Rem<T> for Vector2<T> {
604    type Output = Vector2<T>;
605
606    #[inline]
607    fn rem(self, other: T) -> Self::Output {
608        Self::Output::new(self.x_ % other.clone(), self.y_ % other)
609    }
610}
611
612scalar_arithmetic!(usize, u8, u16, u32, u64, u128, isize, i8, i16, i32, i64, i128, f32, f64);
613
614// constants
615impl<T: Clone + Num> Zero for Vector2<T> {
616    #[inline]
617    fn zero() -> Self {
618        Self::new(Zero::zero(), Zero::zero())
619    }
620
621    #[inline]
622    fn is_zero(&self) -> bool {
623        self.x_.is_zero() && self.y_.is_zero()
624    }
625
626    #[inline]
627    fn set_zero(&mut self) {
628        self.x_.set_zero();
629        self.y_.set_zero();
630    }
631}
632
633#[cfg(test)]
634fn hash<T: hash::Hash>(x: &T) -> u64 {
635    use std::collections::hash_map::RandomState;
636    use std::hash::{BuildHasher, Hasher};
637    let mut hasher = <RandomState as BuildHasher>::Hasher::new();
638    x.hash(&mut hasher);
639    hasher.finish()
640}
641
642#[cfg(test)]
643mod test {
644    #![allow(non_upper_case_globals)]
645
646    use super::{hash, Vector2};
647    use core::f64;
648    use num_traits::Zero;
649
650    pub const _0_0v: Vector2<f64> = Vector2 { x_: 0.0, y_: 0.0 };
651    pub const _1_0v: Vector2<f64> = Vector2 { x_: 1.0, y_: 0.0 };
652    pub const _1_1v: Vector2<f64> = Vector2 { x_: 1.0, y_: 1.0 };
653    pub const _0_1v: Vector2<f64> = Vector2 { x_: 0.0, y_: 1.0 };
654    pub const _neg1_1v: Vector2<f64> = Vector2 { x_: -1.0, y_: 1.0 };
655    pub const _05_05v: Vector2<f64> = Vector2 { x_: 0.5, y_: 0.5 };
656    pub const all_consts: [Vector2<f64>; 5] = [_0_0v, _1_0v, _1_1v, _neg1_1v, _05_05v];
657    pub const _4_2v: Vector2<f64> = Vector2 { x_: 4.0, y_: 2.0 };
658
659    #[test]
660    fn test_consts() {
661        // check our constants are what Vector2::new creates
662        fn test(c: Vector2<f64>, r: f64, i: f64) {
663            assert_eq!(c, Vector2::new(r, i));
664        }
665        test(_0_0v, 0.0, 0.0);
666        test(_1_0v, 1.0, 0.0);
667        test(_1_1v, 1.0, 1.0);
668        test(_neg1_1v, -1.0, 1.0);
669        test(_05_05v, 0.5, 0.5);
670        assert_eq!(_0_0v, Zero::zero());
671    }
672
673    #[test]
674    fn test_scale_unscale() {
675        assert_eq!(_05_05v.scale(2.0), _1_1v);
676        assert_eq!(_1_1v.unscale(2.0), _05_05v);
677        for &c in all_consts.iter() {
678            assert_eq!(c.scale(2.0).unscale(2.0), c);
679        }
680    }
681
682    #[test]
683    fn test_hash() {
684        let a = Vector2::new(0i32, 0i32);
685        let b = Vector2::new(1i32, 0i32);
686        let c = Vector2::new(0i32, 1i32);
687        assert!(hash(&a) != hash(&b));
688        assert!(hash(&b) != hash(&c));
689        assert!(hash(&c) != hash(&a));
690    }
691}