ginger/
vector2.rs

1// #![no_std]
2use core::ops::{Add, Div, Mul, Neg, Rem, Sub};
3use num_traits::{Num, Signed, Zero};
4
5/// The `Vector2` struct represents a 2-dimensional vector with elements of type `T`.
6///
7/// Properties:
8///
9/// * `x_`: The `x_` property represents the first element of the `Vector2` object. It is of type `T`,
10/// which means it can be any type that is specified when creating an instance of `Vector2`.
11/// * `y_`: The `y_` property is the second element of the `Vector2` object. It represents the
12/// y-coordinate of a 2D vector.
13///
14/// # Examples:
15///
16/// ```
17/// use ginger::vector2::Vector2;
18///
19/// assert_eq!(Vector2::new(3, 4), Vector2 { x_: 3, y_: 4});
20/// ```
21#[derive(PartialEq, Eq, Copy, Clone, Hash, Debug, Default)]
22pub struct Vector2<T> {
23    /// The first element of the vector2 object
24    pub x_: T,
25    /// The second element of the vector2 object
26    pub y_: T,
27}
28
29impl<T> Vector2<T> {
30    /// Creates a new [`Vector2<T>`].
31    ///
32    /// The `new` function creates a new `Vector2` instance with the given `x` and `y` values.
33    ///
34    /// Arguments:
35    ///
36    /// * `x_`: The parameter `x_` represents the x-coordinate of the vector. It is of type `T`, which means
37    /// it can be any type that implements the necessary operations for vector calculations (e.g., addition,
38    /// subtraction, multiplication).
39    /// * `y_`: The `y_` parameter represents the y-coordinate of the vector.
40    ///
41    /// Returns:
42    ///
43    /// The `new` function returns a new instance of the `Vector2<T>` struct.
44    ///
45    /// # Examples
46    ///
47    /// ```
48    /// use ginger::vector2::Vector2;
49    ///
50    /// assert_eq!(Vector2::new(3, 4), Vector2 { x_: 3, y_: 4});
51    /// ```
52    #[inline]
53    pub const fn new(x_: T, y_: T) -> Self {
54        Vector2 { x_, y_ }
55    }
56}
57
58impl<T: Clone + Num> Vector2<T> {
59    /// The `dot` function calculates the dot product of two vectors.
60    ///
61    /// Arguments:
62    ///
63    /// * `other`: The `other` parameter is a reference to another `Vector2` object that we want to
64    /// calculate the dot product with.
65    ///
66    /// Returns:
67    ///
68    /// The dot product of two vectors is being returned.
69    ///
70    /// # Examples
71    ///
72    /// ```
73    /// use ginger::vector2::Vector2;
74    ///
75    /// let vector2 = &Vector2::new(3, 4);
76    /// let other = &Vector2::new(5, 6);
77    /// assert_eq!(vector2.dot(other), 15 + 24);
78    /// assert_eq!(vector2.dot(&vector2), 9 + 16);
79    /// ```
80    #[inline]
81    pub fn dot(&self, other: &Self) -> T {
82        self.x_.clone() * other.x_.clone() + self.y_.clone() * other.y_.clone()
83    }
84
85    /// The `cross` function calculates the cross product of two vectors.
86    ///
87    /// Arguments:
88    ///
89    /// * `other`: The `other` parameter is a reference to another `Vector2` object that we want to
90    /// calculate the cross product with.
91    ///
92    /// Returns:
93    ///
94    /// The cross product of two vectors is being returned.
95    ///
96    /// # Examples
97    ///
98    /// ```
99    /// use ginger::vector2::Vector2;
100    ///
101    /// let vector2 = &Vector2::new(3, 4);
102    /// let other = &Vector2::new(5, 6);
103    /// assert_eq!(vector2.cross(other), 18 - 20);
104    /// assert_eq!(vector2.cross(&vector2), 0);
105    /// ```
106    #[inline]
107    pub fn cross(&self, other: &Self) -> T {
108        self.x_.clone() * other.y_.clone() - self.y_.clone() * other.x_.clone()
109    }
110
111    /// Returns the norm sqr of this [`Vector2<T>`].
112    ///
113    /// The `norm_sqr` function calculates the squared norm of a `Vector2` object.
114    ///
115    /// Returns:
116    ///
117    /// The `norm_sqr` function returns the squared norm of the `Vector2<T>`.
118    ///
119    /// # Examples
120    ///
121    /// ```
122    /// use ginger::vector2::Vector2;
123    ///
124    /// let vector2 = &Vector2::new(3, 4);
125    /// assert_eq!(vector2.norm_sqr(), 9 + 16);
126    /// ```
127    #[inline]
128    pub fn norm_sqr(&self) -> T {
129        self.dot(self)
130    }
131
132    /// The `scale` function multiplies the x and y components of a `Vector2` object by a given scalar
133    /// value.
134    ///
135    /// Arguments:
136    ///
137    /// * `alpha`: The parameter `alpha` represents the scaling factor that will be applied to the vector.
138    ///
139    /// Returns:
140    ///
141    /// The `scale` method returns a new `Vector2` object.
142    ///
143    /// # Examples
144    ///
145    /// ```
146    /// use ginger::vector2::Vector2;
147    ///
148    /// let vector2 = &Vector2::new(3.0, 4.0);
149    /// assert_eq!(vector2.scale(10.0), Vector2::new(30.0, 40.0));
150    /// assert_eq!(vector2.scale(0.5), Vector2::new(1.5, 2.0));
151    /// ```
152    #[inline]
153    pub fn scale(&self, alpha: T) -> Self {
154        Self::new(self.x_.clone() * alpha.clone(), self.y_.clone() * alpha)
155    }
156
157    /// The `unscale` function divides the x and y components of a `Vector2` by a given value.
158    ///
159    /// Arguments:
160    ///
161    /// * `alpha`: The `alpha` parameter is a value of type `T` that is used to divide the `x_` and `y_`
162    /// values of the `Vector2` object.
163    ///
164    /// Returns:
165    ///
166    /// The `unscale` method returns a new `Vector2` object.
167    ///
168    /// # Examples
169    ///
170    /// ```
171    /// use ginger::vector2::Vector2;
172    ///
173    /// let vector2 = &Vector2::new(30, 40);
174    /// assert_eq!(vector2.unscale(10), Vector2::new(3, 4));
175    /// ```
176    #[inline]
177    pub fn unscale(&self, alpha: T) -> Self {
178        Self::new(self.x_.clone() / alpha.clone(), self.y_.clone() / alpha)
179    }
180}
181
182impl<T: Clone + Signed> Vector2<T> {
183    /// The `l1_norm` function calculates the Manhattan distance from the origin for a 2D vector.
184    ///
185    /// [Manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry
186    ///
187    /// Returns:
188    ///
189    /// The function `l1_norm` returns the L1 norm of a `Vector2` object, which is the sum of the absolute
190    /// values of its `x_` and `y_` components.
191    ///
192    /// # Examples
193    ///
194    /// ```
195    /// use ginger::vector2::Vector2;
196    ///
197    /// let vector2 = &Vector2::new(3, -4);
198    /// assert_eq!(vector2.l1_norm(), 7);
199    /// ```
200    #[inline]
201    pub fn l1_norm(&self) -> T {
202        self.x_.abs() + self.y_.abs()
203    }
204}
205
206impl<T: Clone + PartialOrd> Vector2<T> {
207    /// The `norm_inf` function returns the maximum absolute value of the two elements in a `Vector2`
208    /// object.
209    ///
210    /// Returns:
211    ///
212    /// The `norm_inf` function returns the maximum value between `self.x_` and `self.y_`.
213    ///
214    /// # Examples
215    ///
216    /// ```
217    /// use ginger::vector2::Vector2;
218    ///
219    /// let vector2 = &Vector2::new(3, -4);
220    /// assert_eq!(vector2.norm_inf(), 3);
221    /// ```
222    #[inline]
223    pub fn norm_inf(&self) -> T {
224        if self.x_ > self.y_ {
225            self.x_.clone()
226        } else {
227            self.y_.clone()
228        }
229    }
230}
231
232macro_rules! forward_xf_xf_binop {
233    (impl $imp:ident, $method:ident) => {
234        impl<'a, 'b, T: Clone + Num> $imp<&'b Vector2<T>> for &'a Vector2<T> {
235            type Output = Vector2<T>;
236
237            #[inline]
238            fn $method(self, other: &Vector2<T>) -> Self::Output {
239                self.clone().$method(other.clone())
240            }
241        }
242    };
243}
244
245macro_rules! forward_xf_val_binop {
246    (impl $imp:ident, $method:ident) => {
247        impl<'a, T: Clone + Num> $imp<Vector2<T>> for &'a Vector2<T> {
248            type Output = Vector2<T>;
249
250            #[inline]
251            fn $method(self, other: Vector2<T>) -> Self::Output {
252                self.clone().$method(other)
253            }
254        }
255    };
256}
257
258macro_rules! forward_val_xf_binop {
259    (impl $imp:ident, $method:ident) => {
260        impl<'a, T: Clone + Num> $imp<&'a Vector2<T>> for Vector2<T> {
261            type Output = Vector2<T>;
262
263            #[inline]
264            fn $method(self, other: &Vector2<T>) -> Self::Output {
265                self.$method(other.clone())
266            }
267        }
268    };
269}
270
271macro_rules! forward_all_binop {
272    (impl $imp:ident, $method:ident) => {
273        forward_xf_xf_binop!(impl $imp, $method);
274        forward_xf_val_binop!(impl $imp, $method);
275        forward_val_xf_binop!(impl $imp, $method);
276    };
277}
278
279// arithmetic
280forward_all_binop!(impl Add, add);
281
282// (a, b) + (c, d) == (a + c), (b + d)
283impl<T: Clone + Num> Add<Vector2<T>> for Vector2<T> {
284    type Output = Self;
285
286    #[inline]
287    fn add(self, other: Self) -> Self::Output {
288        Self::Output::new(self.x_ + other.x_, self.y_ + other.y_)
289    }
290}
291
292forward_all_binop!(impl Sub, sub);
293
294// (a, b) - (c, d) == (a - c), (b - d)
295impl<T: Clone + Num> Sub<Vector2<T>> for Vector2<T> {
296    type Output = Self;
297
298    #[inline]
299    fn sub(self, other: Self) -> Self::Output {
300        Self::Output::new(self.x_ - other.x_, self.y_ - other.y_)
301    }
302}
303
304// Op Assign
305
306mod opassign {
307    use core::ops::{AddAssign, DivAssign, MulAssign, SubAssign};
308
309    use num_traits::NumAssign;
310
311    use crate::Vector2;
312
313    impl<T: Clone + NumAssign> AddAssign for Vector2<T> {
314        fn add_assign(&mut self, other: Self) {
315            self.x_ += other.x_;
316            self.y_ += other.y_;
317        }
318    }
319
320    impl<T: Clone + NumAssign> SubAssign for Vector2<T> {
321        fn sub_assign(&mut self, other: Self) {
322            self.x_ -= other.x_;
323            self.y_ -= other.y_;
324        }
325    }
326
327    impl<T: Clone + NumAssign> MulAssign<T> for Vector2<T> {
328        fn mul_assign(&mut self, other: T) {
329            self.x_ *= other.clone();
330            self.y_ *= other;
331        }
332    }
333
334    impl<T: Clone + NumAssign> DivAssign<T> for Vector2<T> {
335        fn div_assign(&mut self, other: T) {
336            self.x_ /= other.clone();
337            self.y_ /= other;
338        }
339    }
340
341    macro_rules! forward_op_assign1 {
342        (impl $imp:ident, $method:ident) => {
343            impl<'a, T: Clone + NumAssign> $imp<&'a Vector2<T>> for Vector2<T> {
344                #[inline]
345                fn $method(&mut self, other: &Self) {
346                    self.$method(other.clone())
347                }
348            }
349        };
350    }
351
352    macro_rules! forward_op_assign2 {
353        (impl $imp:ident, $method:ident) => {
354            impl<'a, T: Clone + NumAssign> $imp<&'a T> for Vector2<T> {
355                #[inline]
356                fn $method(&mut self, other: &T) {
357                    self.$method(other.clone())
358                }
359            }
360        };
361    }
362
363    forward_op_assign1!(impl AddAssign, add_assign);
364    forward_op_assign1!(impl SubAssign, sub_assign);
365    forward_op_assign2!(impl MulAssign, mul_assign);
366    forward_op_assign2!(impl DivAssign, div_assign);
367}
368
369impl<T: Clone + Num + Neg<Output = T>> Neg for Vector2<T> {
370    type Output = Self;
371
372    #[inline]
373    fn neg(self) -> Self::Output {
374        Self::Output::new(-self.x_, -self.y_)
375    }
376}
377
378impl<'a, T: Clone + Num + Neg<Output = T>> Neg for &'a Vector2<T> {
379    type Output = Vector2<T>;
380
381    #[inline]
382    fn neg(self) -> Self::Output {
383        -self.clone()
384    }
385}
386
387macro_rules! scalar_arithmetic {
388    (@forward $imp:ident::$method:ident for $($scalar:ident),*) => (
389        impl<'a, T: Clone + Num> $imp<&'a T> for Vector2<T> {
390            type Output = Vector2<T>;
391
392            #[inline]
393            fn $method(self, other: &T) -> Self::Output {
394                self.$method(other.clone())
395            }
396        }
397        impl<'a, T: Clone + Num> $imp<T> for &'a Vector2<T> {
398            type Output = Vector2<T>;
399
400            #[inline]
401            fn $method(self, other: T) -> Self::Output {
402                self.clone().$method(other)
403            }
404        }
405        impl<'a, 'b, T: Clone + Num> $imp<&'a T> for &'b Vector2<T> {
406            type Output = Vector2<T>;
407
408            #[inline]
409            fn $method(self, other: &T) -> Self::Output {
410                self.clone().$method(other.clone())
411            }
412        }
413        $(
414            impl<'a> $imp<&'a Vector2<$scalar>> for $scalar {
415                type Output = Vector2<$scalar>;
416
417                #[inline]
418                fn $method(self, other: &Vector2<$scalar>) -> Vector2<$scalar> {
419                    self.$method(other.clone())
420                }
421            }
422            impl<'a> $imp<Vector2<$scalar>> for &'a $scalar {
423                type Output = Vector2<$scalar>;
424
425                #[inline]
426                fn $method(self, other: Vector2<$scalar>) -> Vector2<$scalar> {
427                    self.clone().$method(other)
428                }
429            }
430            impl<'a, 'b> $imp<&'a Vector2<$scalar>> for &'b $scalar {
431                type Output = Vector2<$scalar>;
432
433                #[inline]
434                fn $method(self, other: &Vector2<$scalar>) -> Vector2<$scalar> {
435                    self.clone().$method(other.clone())
436                }
437            }
438        )*
439    );
440    ($($scalar:ident),*) => (
441        scalar_arithmetic!(@forward Mul::mul for $($scalar),*);
442        // scalar_arithmetic!(@forward Div::div for $($scalar),*);
443        // scalar_arithmetic!(@forward Rem::rem for $($scalar),*);
444
445        $(
446            impl Mul<Vector2<$scalar>> for $scalar {
447                type Output = Vector2<$scalar>;
448
449                #[inline]
450                fn mul(self, other: Vector2<$scalar>) -> Self::Output {
451                    Self::Output::new(self * other.x_, self * other.y_)
452                }
453            }
454
455        )*
456    );
457}
458
459impl<T: Clone + Num> Mul<T> for Vector2<T> {
460    type Output = Vector2<T>;
461
462    #[inline]
463    fn mul(self, other: T) -> Self::Output {
464        Self::Output::new(self.x_ * other.clone(), self.y_ * other)
465    }
466}
467
468impl<T: Clone + Num> Div<T> for Vector2<T> {
469    type Output = Self;
470
471    #[inline]
472    fn div(self, other: T) -> Self::Output {
473        Self::Output::new(self.x_ / other.clone(), self.y_ / other)
474    }
475}
476
477impl<T: Clone + Num> Rem<T> for Vector2<T> {
478    type Output = Vector2<T>;
479
480    #[inline]
481    fn rem(self, other: T) -> Self::Output {
482        Self::Output::new(self.x_ % other.clone(), self.y_ % other)
483    }
484}
485
486scalar_arithmetic!(usize, u8, u16, u32, u64, u128, isize, i8, i16, i32, i64, i128, f32, f64);
487
488// constants
489impl<T: Clone + Num> Zero for Vector2<T> {
490    #[inline]
491    fn zero() -> Self {
492        Self::new(Zero::zero(), Zero::zero())
493    }
494
495    #[inline]
496    fn is_zero(&self) -> bool {
497        self.x_.is_zero() && self.y_.is_zero()
498    }
499
500    #[inline]
501    fn set_zero(&mut self) {
502        self.x_.set_zero();
503        self.y_.set_zero();
504    }
505}
506
507// #[cfg(test)]
508// fn hash<T: hash::Hash>(x: &T) -> u64 {
509//     use std::collections::hash_map::RandomState;
510//     use std::hash::{BuildHasher, Hasher};
511//     let mut hasher = <RandomState as BuildHasher>::Hasher::new();
512//     x.hash(&mut hasher);
513//     hasher.finish()
514// }
515
516#[cfg(test)]
517mod test {
518    #![allow(non_upper_case_globals)]
519
520    // use super::{hash, Vector2};
521    use super::Vector2;
522    use core::f64;
523    use num_traits::Zero;
524
525    pub const _0_0v: Vector2<f64> = Vector2 { x_: 0.0, y_: 0.0 };
526    pub const _1_0v: Vector2<f64> = Vector2 { x_: 1.0, y_: 0.0 };
527    pub const _1_1v: Vector2<f64> = Vector2 { x_: 1.0, y_: 1.0 };
528    pub const _0_1v: Vector2<f64> = Vector2 { x_: 0.0, y_: 1.0 };
529    pub const _neg1_1v: Vector2<f64> = Vector2 { x_: -1.0, y_: 1.0 };
530    pub const _05_05v: Vector2<f64> = Vector2 { x_: 0.5, y_: 0.5 };
531    pub const all_consts: [Vector2<f64>; 5] = [_0_0v, _1_0v, _1_1v, _neg1_1v, _05_05v];
532    pub const _4_2v: Vector2<f64> = Vector2 { x_: 4.0, y_: 2.0 };
533
534    #[test]
535    fn test_consts() {
536        // check our constants are what Vector2::new creates
537        fn test(c: Vector2<f64>, r: f64, i: f64) {
538            assert_eq!(c, Vector2::new(r, i));
539        }
540        test(_0_0v, 0.0, 0.0);
541        test(_1_0v, 1.0, 0.0);
542        test(_1_1v, 1.0, 1.0);
543        test(_neg1_1v, -1.0, 1.0);
544        test(_05_05v, 0.5, 0.5);
545        assert_eq!(_0_0v, Zero::zero());
546    }
547
548    #[test]
549    fn test_scale_unscale() {
550        assert_eq!(_05_05v.scale(2.0), _1_1v);
551        assert_eq!(_1_1v.unscale(2.0), _05_05v);
552        for &c in all_consts.iter() {
553            assert_eq!(c.scale(2.0).unscale(2.0), c);
554        }
555    }
556
557    // #[test]
558    // fn test_hash() {
559    //     let a = Vector2::new(0i32, 0i32);
560    //     let b = Vector2::new(1i32, 0i32);
561    //     let c = Vector2::new(0i32, 1i32);
562    //     assert!(hash(&a) != hash(&b));
563    //     assert!(hash(&b) != hash(&c));
564    //     assert!(hash(&c) != hash(&a));
565    // }
566}