vector2d/lib.rs
1//! # vector2d
2//! A simple and convenient 2D vector library without excessive use of external
3//! dependencies. If other vector crates are swiss-army knives, vector2d is a
4//! spoon; safe, intuitive, and convenient. As an added bonus, you won't run
5//! into any excursions with the law using this library thanks to the awfully
6//! permissive Unlicense.
7//!
8//! The only type in this crate is [`Vector2D`], which is highly generic;
9//! shifting functionality depending upon the traits implemented by its internal
10//! components' types.
11//!
12//! [`Vector2D`]: struct.Vector2D.html
13//!
14//! # Example
15//! ```
16//! use vector2d::Vector2D;
17//!
18//! // Vectors have fields X and Y, these can be of any type
19//! let v1: Vector2D<i32> = Vector2D { x: 10, y: 5 };
20//!
21//! // Alternatively you can use new(..) to condense instantiation
22//! let v2: Vector2D<f64> = Vector2D::new(13.0, 11.5);
23//!
24//! // There are two ways to cast between Vector2Ds, depending on the source
25//! // and target types.
26//! //
27//! // If the target type has a implementation of From<SourceType>, then you
28//! // can either use source.into_vec2d() or Vector2D::from_vec2d(source).
29//! assert_eq!(Vector2D::new(10.0, 5.0), v1.into_vec2d());
30//! assert_eq!(Vector2D::new(10.0, 5.0), Vector2D::from_vec2d(v1));
31//!
32//! // If there is no From or Into implementation, then you're out of luck
33//! // unless you are using specific primitives, such as i32 and f64. In
34//! // this case you can use specialised functions, as shown below:
35//! assert_eq!(Vector2D::new(13, 11), v2.as_i32s());
36//!
37//! // The full list of interoperable primitives is as follows:
38//! // - i32, i64, isize
39//! // - u32, u64, usize
40//! // - f32, f64
41//!
42//! // As primitives generally implement From/Into for lossless casts,
43//! // an as_Ts() function is not available for those types, and
44//! // from(..)/into() should be favoured.
45//! //
46//! // Casts between signed and unsigned primitives will perform bounds
47//! // checking, so casting the vector (-10.0, 2.0) to a Vector2D<u32> will
48//! // result in the vector (0, 2).
49//!
50//! // For types with an Add and Mul implementation, the functions dot() and
51//! // length_squared() are available. For access to length(), normalise(),
52//! // or angle() however, you must be using either Vector2D<f32> or
53//! // Vector2D<f64>.
54//! let _v1_len_sq = v1.length_squared();
55//! let v2_len = v2.length();
56//! let v2_dir = v2.normalise();
57//!
58//! // Assuming the operator traits are implemented for the types involved,
59//! // you can add and subtract Vector2Ds from one-another, as well as
60//! // multiply and divide them with scalar values.
61//! assert_eq!(v2, v2_dir * v2_len);
62//! assert_eq!(Vector2D::new(23.0, 16.5), v2 + v1.into_vec2d()) ;
63//!
64//! // If you feel the need to multiply or divide individual components of
65//! // vectors with the same type, you can use mul_components(...) or
66//! // div_components(...) provided that their types can be multiplied or
67//! // divided.
68//!
69//! // For any Vector2D<T>, there is an implementation of
70//! // From<(T, T)> and From<[T; 2]>
71//! let v4: Vector2D<f64> = Vector2D::new(1.5, 2.3);
72//! assert_eq!(v4, (1.5, 2.3).into());
73//! assert_eq!(v4, [1.5, 2.3].into());
74//!
75//! // Additionally, there is an Into<(T, T)> implementation for any types
76//! // that the vector components have their own Into implementations for
77//! assert_eq!((1.5, 2.3), v4.into());
78//!
79//! // If you want the normal of a vector you can just call normal()
80//! let v5 = Vector2D::new(-10.0, -2.3);
81//! assert_eq!(Vector2D::new(2.3, -10.0), v5.normal());
82//!
83//! // You can get a vector consisting of only the horizontal or vertical
84//! // component of a vector by calling horizontal() or vertical()
85//! // respectively
86//! let v6 = Vector2D::new(12.3, 83.2);
87//! assert_eq!(Vector2D::new(12.3, 0.0), v6.horizontal());
88//! assert_eq!(Vector2D::new(0.0, 83.2), v6.vertical());
89//! ```
90
91#[cfg(test)]
92mod test;
93
94use std::cmp::Ordering;
95use std::ops::{
96 Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign,
97};
98
99/// Convenience macro for implementing funcs like `as_i32s` concisely
100macro_rules! fn_simple_as {
101 ($func:ident, $type:ty) => {
102 pub fn $func(&self) -> Vector2D<$type> {
103 Vector2D {
104 x: self.x as $type,
105 y: self.y as $type,
106 }
107 }
108 };
109}
110
111/// Convenience macro for implementing funcs like `as_u32s` concisely, while appropriately setting
112/// a lower bound (e.g. 0.0) for the source value before the conversion is performed
113macro_rules! fn_lower_bounded_as {
114 ($func:ident, $dst_type:ty, $lower_bound:expr) => {
115 pub fn $func(&self) -> Vector2D<$dst_type> {
116 Vector2D {
117 x: self.x.max($lower_bound) as $dst_type,
118 y: self.y.max($lower_bound) as $dst_type,
119 }
120 }
121 };
122}
123
124/// Convenience macro for implementing funcs like `as i32s` concisely, while appropriately setting
125/// bounds (e.g. from i32::MIN to i32::MAX) for the source value before the conversion is
126/// performed
127macro_rules! fn_bounded_as {
128 ($func:ident, $dst_type:ty, $lower_bound:expr, $upper_bound:expr) => {
129 pub fn $func(&self) -> Vector2D<$dst_type> {
130 Vector2D {
131 x: self.x.min($upper_bound).max($lower_bound) as $dst_type,
132 y: self.y.min($upper_bound).max($lower_bound) as $dst_type,
133 }
134 }
135 };
136}
137
138/// A 2D vector, containing an `x` and a `y` component. While many types can be
139/// used for a `Vector2D`'s components, the traits they implement determine
140/// what functions are available.
141///
142/// Provided that the components implement the necessary traits, `Vector2D`s
143/// can be added to or subtracted from one-another, and they can be mulitplied
144/// and divided by scalar values.
145///
146/// There are generally two options for converting between `Vector2D` types. If
147/// the internal components' type has an implementation of `Into` that targets
148/// the desired type, then [`into_vec2d()`] can be called from the source object,
149/// or [`from_vec2d(..)`] can be called and the source object can be provided.
150///
151/// If no `Into` implementation exists, then the only option is to use one of the
152/// flavours of casting with `as`. These are in the form `as_types()`, and are only
153/// implemented for specific types of components. An example usage would look like
154/// this:
155/// ```
156/// use vector2d::Vector2D;
157/// let f64_vector: Vector2D<f64> = Vector2D::new(10.3, 11.1);
158/// let i32_vector: Vector2D<i32> = f64_vector.as_i32s();
159/// assert_eq!(Vector2D::new(10, 11), i32_vector);
160/// ```
161///
162/// Implementations of `as_types()` are only available when an implementation of
163/// [`into_vec2d()`] is unavailable. This is to seperate between the lossless casting
164/// of primitives with `into()` and `from(..)`, and the lossy casting between
165/// primitives of varying detail.
166///
167/// Casts from signed types to unsigned types have a small additional check that
168/// ensures a lower bound of 0 on the signed value, to reduce the chances of
169/// experiencing undefined behaviour. This means that a `Vector2D<f64>` with a
170/// value of `(-10.3, 11.1)` would become `(0, 11)` when cast to a `Vector2D<u32>`
171/// with [`as_u32s()`].
172///
173/// The current list of interoperable types that can be cast with the `as` family of
174/// functions is as follows:
175/// - `i32`
176/// - `i64`,
177/// - `isize`
178/// - `u32`
179/// - `u64`
180/// - `usize`
181/// - `f32`
182/// - `f64`
183///
184/// [`into_vec2d()`]: struct.Vector2D.html#method.into_vec2d
185/// [`from_vec2d(..)`]: struct.Vector2D.html#method.from_vec2d
186/// [`as_u32s()`]: struct.Vector2D.html#method.as_u32s-1
187#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
188pub struct Vector2D<T> {
189 pub x: T,
190 pub y: T,
191}
192
193impl<T: Copy + Clone> Vector2D<T> {
194 /// Create a new `Vector2D` with the provided components.
195 pub const fn new(x: T, y: T) -> Self {
196 Self { x, y }
197 }
198
199 /// Convert a `Vector2` of type `U` to one of type `T`. Available only when
200 /// type T has implemented `From<U>`.
201 ///
202 /// # Example
203 /// ```
204 /// use vector2d::Vector2D;
205 /// let i32_vector: Vector2D<i32> = Vector2D::new(25, 8);
206 /// let f64_vector: Vector2D<f64> = Vector2D::from_vec2d(i32_vector);
207 /// assert_eq!(Vector2D::new(25.0, 8.0), f64_vector);
208 /// ```
209 pub fn from_vec2d<U: Into<T> + Copy + Clone>(src: Vector2D<U>) -> Vector2D<T> {
210 Vector2D {
211 x: src.x.into(),
212 y: src.y.into(),
213 }
214 }
215
216 /// Convert a `Vector2` of type `T` to one of type `U`. Available only when
217 /// type T has implemented `Into<U>`.
218 ///
219 /// # Example
220 /// ```
221 /// use vector2d::Vector2D;
222 /// let i32_vector: Vector2D<i32> = Vector2D::new(25, 8);
223 /// let i32_vector: Vector2D<i32> = Vector2D::new(25, 8);
224 /// let f64_vector: Vector2D<f64> = i32_vector.into_vec2d();
225 /// assert_eq!(Vector2D::new(25.0, 8.0), f64_vector);
226 /// ```
227 pub fn into_vec2d<U: From<T>>(self) -> Vector2D<U> {
228 Vector2D {
229 x: self.x.into(),
230 y: self.y.into(),
231 }
232 }
233}
234
235impl<T> Default for Vector2D<T>
236where
237 T: Default,
238{
239 fn default() -> Self {
240 Self {
241 x: T::default(),
242 y: T::default(),
243 }
244 }
245}
246
247impl<T: Default> Vector2D<T> {
248 /// Returns a vector with only the horizontal component of the current one
249 ///
250 /// # Example
251 /// ```
252 /// use vector2d::Vector2D;
253 /// let v = Vector2D::new(10, 20);
254 /// assert_eq!(Vector2D::new(10, 0), v.horizontal());
255 /// ```
256 pub fn horizontal(self) -> Self {
257 Self {
258 x: self.x,
259 y: Default::default(),
260 }
261 }
262
263 /// Returns a vector with only the vertical component of the current one
264 ///
265 /// # Example
266 /// ```
267 /// use vector2d::Vector2D;
268 /// let v = Vector2D::new(10, 20);
269 /// assert_eq!(Vector2D::new(0, 20), v.vertical());
270 pub fn vertical(self) -> Self {
271 Self {
272 x: Default::default(),
273 y: self.y,
274 }
275 }
276}
277
278impl<T> Vector2D<T>
279where
280 T: Mul<T, Output = T> + Copy + Clone,
281{
282 /// Returns a new vector with components equal to each of the current vector's
283 /// components multiplied by the corresponding component of the provided vector
284 ///
285 /// # Example
286 /// ```
287 /// use vector2d::Vector2D;
288 /// let v1 = Vector2D::new(11.0, -2.5);
289 /// let v2 = Vector2D::new(0.5, -2.0);
290 /// assert_eq!(Vector2D::new(5.5, 5.0), v1.mul_components(v2));
291 /// ```
292 pub fn mul_components(self, other: Self) -> Self {
293 Self {
294 x: self.x * other.x,
295 y: self.y * other.y,
296 }
297 }
298}
299
300impl<T> Vector2D<T>
301where
302 T: Div<T, Output = T> + Copy + Clone,
303{
304 /// Returns a new vector with components equal to each of the current vector's
305 /// components divided by the corresponding component of the provided vector
306 ///
307 /// # Example
308 /// ```
309 /// use vector2d::Vector2D;
310 /// let v1 = Vector2D::new(11.0, -2.5);
311 /// let v2 = Vector2D::new(0.5, -2.0);
312 /// assert_eq!(Vector2D::new(22.0, 1.25), v1.div_components(v2));
313 /// ```
314 pub fn div_components(self, other: Self) -> Self {
315 Self {
316 x: self.x / other.x,
317 y: self.y / other.y,
318 }
319 }
320}
321
322impl<T, U> Neg for Vector2D<T>
323where
324 T: Neg<Output = U> + Copy + Clone,
325{
326 type Output = Vector2D<U>;
327 fn neg(self) -> Self::Output {
328 Self::Output {
329 x: -self.x,
330 y: -self.y,
331 }
332 }
333}
334
335impl<T> Vector2D<T>
336where
337 T: Neg<Output = T> + Copy + Clone,
338{
339 /// Returns a vector perpendicular to the current one.
340 ///
341 /// # Example
342 /// ```
343 /// use vector2d::Vector2D;
344 /// let v = Vector2D::new(21.3, -98.1);
345 /// assert_eq!(Vector2D::new(98.1, 21.3), v.normal());
346 /// ```
347 pub fn normal(self) -> Self {
348 Self {
349 x: -self.y,
350 y: self.x,
351 }
352 }
353}
354
355impl<T, U, V> Vector2D<T>
356where
357 T: Mul<T, Output = U> + Copy + Clone,
358 U: Add<U, Output = V> + Copy + Clone,
359{
360 /// Get the scalar/dot product of the two `Vector2D`.
361 pub fn dot(v1: Self, v2: Self) -> V {
362 v1.x * v2.x + v1.y * v2.y
363 }
364
365 /// Get the squared length of a `Vector2D`. This is more performant than using
366 /// `length()` -- which is only available for `Vector2D<f32>` and `Vector2D<f64>`
367 /// -- as it does not perform any square root operation.
368 pub fn length_squared(self) -> V {
369 self.x * self.x + self.y * self.y
370 }
371}
372
373impl<T> Vector2D<T>
374where
375 T: Sub<T, Output = T> + Mul<T, Output = T> + Add<T, Output = T> + Copy + Clone,
376{
377 /// Linearly interpolates between two vectors
378 pub fn lerp(start: Self, end: Self, progress: T) -> Self {
379 start + ((end - start) * progress)
380 }
381}
382
383// From/Into Implementations
384
385impl<T, U> From<Vector2D<T>> for (U, U)
386where
387 U: From<T> + Copy + Clone,
388{
389 fn from(src: Vector2D<T>) -> (U, U) {
390 (U::from(src.x), U::from(src.y))
391 }
392}
393
394impl<T, U> From<(U, U)> for Vector2D<T>
395where
396 T: From<U>,
397 U: Copy + Clone,
398{
399 fn from(src: (U, U)) -> Vector2D<T> {
400 Vector2D {
401 x: src.0.into(),
402 y: src.1.into(),
403 }
404 }
405}
406
407impl<T, U> From<[U; 2]> for Vector2D<T>
408where
409 T: From<U>,
410 U: Copy + Clone,
411{
412 fn from(src: [U; 2]) -> Vector2D<T> {
413 Vector2D {
414 x: src[0].into(),
415 y: src[1].into(),
416 }
417 }
418}
419
420impl<T> Index<usize> for Vector2D<T> {
421 type Output = T;
422
423 /// Only possible for `idx` in {0, 1} - panics otherwise
424 fn index(&self, idx: usize) -> &Self::Output {
425 match idx {
426 0 => &self.x,
427 1 => &self.y,
428 _ => panic!("Index '{}' was out of range for Vector2D", idx),
429 }
430 }
431}
432
433impl<T> IndexMut<usize> for Vector2D<T> {
434 /// Only possible for `idx` in {0, 1} - panics otherwise
435 fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
436 match idx {
437 0 => &mut self.x,
438 1 => &mut self.y,
439 _ => panic!("Index '{}' was out of range for Vector2D", idx),
440 }
441 }
442}
443
444// Specific Primitive Implementations
445
446impl Vector2D<f32> {
447 /// Get the length of the vector. If possible, favour `length_squared()` over
448 /// this function, as it is more performant.
449 pub fn length(self) -> f32 {
450 f32::sqrt(self.length_squared())
451 }
452
453 /// Get a new vector with the same direction as this vector, but with a length
454 /// of 1.0. If the the length of the vector is 0, then the original vector is
455 /// returned.
456 pub fn normalise(self) -> Self {
457 let len = self.length();
458 if len == 0.0 {
459 self
460 } else {
461 self / len
462 }
463 }
464
465 /// Get the vector's direction in radians.
466 pub fn angle(self) -> f32 {
467 self.y.atan2(self.x)
468 }
469
470 fn_simple_as!(as_i32s, i32);
471 fn_simple_as!(as_i64s, i64);
472 fn_simple_as!(as_isizes, isize);
473 fn_lower_bounded_as!(as_u32s, u32, 0.0);
474 fn_lower_bounded_as!(as_u64s, u64, 0.0);
475 fn_lower_bounded_as!(as_usizes, usize, 0.0);
476}
477
478impl Vector2D<f64> {
479 /// Get the length of the vector. If possible, favour `length_squared()` over
480 /// this function, as it is more performant.
481 pub fn length(self) -> f64 {
482 f64::sqrt(self.length_squared())
483 }
484
485 /// Get a new vector with the same direction as this vector, but with a length
486 /// of 1.0. If the the length of the vector is 0, then the original vector is
487 /// returned.
488 pub fn normalise(self) -> Self {
489 let len = self.length();
490 if len == 0.0 {
491 self
492 } else {
493 self / len
494 }
495 }
496
497 /// Get the vector's direction in radians.
498 pub fn angle(self) -> f64 {
499 self.y.atan2(self.x)
500 }
501
502 fn_simple_as!(as_i32s, i32);
503 fn_simple_as!(as_i64s, i64);
504 fn_simple_as!(as_isize, isize);
505 fn_simple_as!(as_f32, f32);
506 fn_lower_bounded_as!(as_u32s, u32, 0.0);
507 fn_lower_bounded_as!(as_u64s, u64, 0.0);
508 fn_lower_bounded_as!(as_usizes, usize, 0.0);
509}
510
511impl Vector2D<i32> {
512 fn_simple_as!(as_isizes, isize);
513 fn_simple_as!(as_f32s, f32);
514 fn_simple_as!(as_f64s, f64);
515 fn_lower_bounded_as!(as_u32s, u32, 0);
516 fn_lower_bounded_as!(as_u64s, u64, 0);
517 fn_lower_bounded_as!(as_usizes, usize, 0);
518}
519
520impl Vector2D<i64> {
521 fn_bounded_as!(as_i32s, i32, i32::MIN.into(), i32::MAX.into());
522 fn_simple_as!(as_i64s, isize);
523 fn_simple_as!(as_f32s, f32);
524 fn_simple_as!(as_f64s, f64);
525 fn_lower_bounded_as!(as_u32s, u32, 0);
526 fn_lower_bounded_as!(as_u64s, u64, 0);
527 fn_lower_bounded_as!(as_usizes, usize, 0);
528}
529
530impl Vector2D<isize> {
531 fn_simple_as!(as_i32s, i32);
532 fn_simple_as!(as_i64s, i64);
533 fn_simple_as!(as_f32s, f32);
534 fn_simple_as!(as_f64s, f64);
535 fn_lower_bounded_as!(as_u32s, u32, 0);
536 fn_lower_bounded_as!(as_u64s, u64, 0);
537 fn_lower_bounded_as!(as_usizes, usize, 0);
538}
539
540impl Vector2D<u32> {
541 fn_bounded_as!(as_i32s, i32, 0, i32::MAX as u32);
542 fn_simple_as!(as_i64s, i64);
543 fn_simple_as!(as_isizes, isize);
544 fn_simple_as!(as_f32s, f32);
545 fn_simple_as!(as_f64s, f64);
546 fn_simple_as!(as_usizes, usize);
547}
548
549impl Vector2D<u64> {
550 fn_bounded_as!(as_i32s, i32, 0, i32::MAX as u64);
551 fn_bounded_as!(as_i64s, i64, 0, i64::MAX as u64);
552 fn_simple_as!(as_isizes, isize);
553 fn_simple_as!(as_f32s, f32);
554 fn_simple_as!(as_f64s, f64);
555 fn_simple_as!(as_u32s, u32);
556 fn_simple_as!(as_usizes, usize);
557}
558
559impl Vector2D<usize> {
560 fn_simple_as!(as_i32s, i32);
561 fn_simple_as!(as_i64s, i64);
562 fn_bounded_as!(as_isizes, isize, 0, isize::MAX as usize);
563 fn_simple_as!(as_f32s, f32);
564 fn_simple_as!(as_f64s, f64);
565 fn_simple_as!(as_u32s, u32);
566 fn_simple_as!(as_u64s, u64);
567}
568
569/// Blanket impls for `min_each`, `max_each`, and `clamp_each`
570impl<T> Vector2D<T>
571where
572 T: PartialOrd + Copy + Clone,
573{
574 // PartialOrd types don't get max, min, or clamp functions so we write our own. When comparison
575 // is impossible, we just return the first arg, as v1 this is the pre-existing value inside our
576 // vector and keeping it intact in such cases is somewhat reasonable enough.
577
578 fn min_t(v1: T, v2: T) -> T {
579 match v1.partial_cmp(&v2) {
580 None => v1,
581 Some(Ordering::Less) => v1,
582 Some(_) => v2,
583 }
584 }
585
586 fn max_t(v1: T, v2: T) -> T {
587 match v1.partial_cmp(&v2) {
588 None => v1,
589 Some(Ordering::Greater) => v1,
590 Some(_) => v2,
591 }
592 }
593
594 fn clamp_t(v: T, min: T, max: T) -> T {
595 Self::max_t(Self::min_t(v, max), min)
596 }
597
598 /// Compares each component against the provided value, and returns a new vector with the lower
599 /// value in each component
600 pub fn min_each(self, value: T) -> Self {
601 Self {
602 x: Self::min_t(self.x, value),
603 y: Self::min_t(self.y, value),
604 }
605 }
606
607 /// Compares each component against the provided value, and returns a new vector with the higher
608 /// value in each component
609 pub fn max_each(self, value: T) -> Self {
610 Self {
611 x: Self::max_t(self.x, value),
612 y: Self::max_t(self.y, value),
613 }
614 }
615
616 /// Returns a new vector where each component has the values of the source vector clamped within
617 /// the provided bounds
618 pub fn clamp_each(self, min: T, max: T) -> Self {
619 Self {
620 x: Self::clamp_t(self.x, min, max),
621 y: Self::clamp_t(self.y, min, max),
622 }
623 }
624}
625
626// Ops Implementations
627
628impl<T, O> Add<Vector2D<T>> for Vector2D<T>
629where
630 T: Add<T, Output = O> + Copy + Clone,
631{
632 type Output = Vector2D<O>;
633 fn add(self, rhs: Vector2D<T>) -> Self::Output {
634 Vector2D {
635 x: self.x + rhs.x,
636 y: self.y + rhs.y,
637 }
638 }
639}
640
641impl<T, O> Add<&Vector2D<T>> for &Vector2D<T>
642where
643 T: Add<T, Output = O> + Copy + Clone,
644{
645 type Output = Vector2D<O>;
646 fn add(self, rhs: &Vector2D<T>) -> Self::Output {
647 Vector2D {
648 x: self.x + rhs.x,
649 y: self.y + rhs.y,
650 }
651 }
652}
653
654impl<T> AddAssign<Vector2D<T>> for Vector2D<T>
655where
656 T: Add<T, Output = T> + Copy + Clone,
657{
658 fn add_assign(&mut self, rhs: Vector2D<T>) {
659 self.x = self.x + rhs.x;
660 self.y = self.y + rhs.y;
661 }
662}
663
664impl<T, O> Sub<Vector2D<T>> for Vector2D<T>
665where
666 T: Sub<T, Output = O> + Copy + Clone,
667{
668 type Output = Vector2D<O>;
669 fn sub(self, rhs: Vector2D<T>) -> Self::Output {
670 Vector2D {
671 x: self.x - rhs.x,
672 y: self.y - rhs.y,
673 }
674 }
675}
676
677impl<T, O> Sub<&Vector2D<T>> for &Vector2D<T>
678where
679 T: Sub<T, Output = O> + Copy + Clone,
680{
681 type Output = Vector2D<O>;
682 fn sub(self, rhs: &Vector2D<T>) -> Self::Output {
683 Vector2D {
684 x: self.x - rhs.x,
685 y: self.y - rhs.y,
686 }
687 }
688}
689
690impl<T> SubAssign<Vector2D<T>> for Vector2D<T>
691where
692 T: Sub<T, Output = T> + Copy + Clone,
693{
694 fn sub_assign(&mut self, rhs: Vector2D<T>) {
695 self.x = self.x - rhs.x;
696 self.y = self.y - rhs.y;
697 }
698}
699
700impl<T, O> Mul<T> for Vector2D<T>
701where
702 T: Mul<T, Output = O> + Copy + Clone,
703{
704 type Output = Vector2D<O>;
705 fn mul(self, rhs: T) -> Self::Output {
706 Vector2D {
707 x: self.x * rhs,
708 y: self.y * rhs,
709 }
710 }
711}
712
713impl<T, O> Mul<T> for &Vector2D<T>
714where
715 T: Mul<T, Output = O> + Copy + Clone,
716{
717 type Output = Vector2D<O>;
718 fn mul(self, rhs: T) -> Self::Output {
719 Self::Output {
720 x: self.x * rhs,
721 y: self.y * rhs,
722 }
723 }
724}
725
726impl<T> MulAssign<T> for Vector2D<T>
727where
728 T: Mul<T, Output = T> + Copy + Clone,
729{
730 fn mul_assign(&mut self, rhs: T) {
731 self.x = self.x * rhs;
732 self.y = self.y * rhs;
733 }
734}
735
736impl<T, O> Div<T> for Vector2D<T>
737where
738 T: Div<T, Output = O> + Copy + Clone,
739{
740 type Output = Vector2D<O>;
741 fn div(self, rhs: T) -> Self::Output {
742 Self::Output {
743 x: self.x / rhs,
744 y: self.y / rhs,
745 }
746 }
747}
748
749impl<T, O> Div<T> for &Vector2D<T>
750where
751 T: Div<T, Output = O> + Copy + Clone,
752{
753 type Output = Vector2D<O>;
754 fn div(self, rhs: T) -> Self::Output {
755 Self::Output {
756 x: self.x / rhs,
757 y: self.y / rhs,
758 }
759 }
760}
761
762impl<T> DivAssign<T> for Vector2D<T>
763where
764 T: Div<T, Output = T> + Copy + Clone,
765{
766 fn div_assign(&mut self, rhs: T) {
767 self.x = self.x / rhs;
768 self.y = self.y / rhs;
769 }
770}