veccentric/
vecc.rs

1//! Generic vector with two components.
2
3use std::{cmp::Ord, ops::*};
4
5/// Generic vector with two components.
6///
7/// It implements multiple operators (for each combination of owned and borrowed
8/// args), namely addition, subtraction, element-wise multiplication,
9/// element-wise division and multiplication & division by a number. (Note that
10/// you can only multiply and divide in the following order: `vector op number`,
11/// since it is not possible to implement a foreign trait on `T`.)
12///
13/// This crate exports a specific version of [`Vecc`](crate::vecc::Vecc) with
14/// [`f64`](f64) components — [`Fecc`](crate::fecc::Fecc). It implements
15/// additional methods and is heavily inspired by [`p5.Vector`](https://p5js.org/reference/#/p5.Vector).
16///
17/// # Examples
18///
19/// Basic arithmetic.
20///
21/// ```
22/// use veccentric::Vecc;
23///
24/// let a = Vecc::new(3_i32, 4);
25/// let b = a * 5; // (15, 20)
26/// let c = Vecc::new(-10, -8);
27/// let d = b - c; // (5, 12)
28/// let e = -d; // (-5, -12)
29/// ```
30///
31/// Shorthand construction using [`From`](std::convert::From).
32///
33/// ```
34/// use veccentric::Vecc;
35///
36/// let a: Vecc<i32> = (10, 5).into();
37/// ```
38///
39/// Using [`Fecc`](crate::fecc::Fecc)'s extended API.
40///
41/// ```
42/// # use float_cmp::assert_approx_eq;
43/// # use std::f64::consts::PI;
44/// use veccentric::Fecc;
45///
46/// let a: Fecc = (3.0, 4.0).into();
47/// let b = a / 0.2; // (15.0, 20.0)
48/// let c = b.limit(20.0); // (12.0, 16.0)
49/// let d = c.rotate(PI); // (-12.0, -16.0)
50/// let e = d.turn(0.0); // (20.0, 0.0)
51///
52/// assert_approx_eq!(f64, e.mag(), 20.0);
53/// ```
54#[derive(Copy, Clone, Eq, PartialEq, Default, Hash, Debug)]
55pub struct Vecc<T> {
56    #[allow(missing_docs)]
57    pub x: T,
58
59    #[allow(missing_docs)]
60    pub y: T,
61}
62
63impl<T> Vecc<T> {
64    /// Constructs a new vector.
65    ///
66    /// # Examples
67    ///
68    /// ```
69    /// use veccentric::Vecc;
70    ///
71    /// let a: Vecc<i32> = Vecc::new(10, 0);
72    /// ```
73    ///
74    /// You can also construct it from a tuple:
75    ///
76    /// ```
77    /// use veccentric::Vecc;
78    ///
79    /// let a: Vecc<i32> = (10, 0).into();
80    /// ```
81    pub fn new(x: T, y: T) -> Self {
82        Self { x, y }
83    }
84
85    /// Takes a dot product of the vector with another.
86    ///
87    /// # Examples
88    ///
89    /// ```
90    /// use veccentric::Vecc;
91    ///
92    /// let a: Vecc<i32> = Vecc::new(10, 0);
93    /// let b: Vecc<i32> = Vecc::new(5, 0);
94    ///
95    /// assert_eq!(a.dot(b), 50);
96    /// ```
97    pub fn dot(self, rhs: Vecc<T>) -> T
98    where
99        T: Add<Output = T> + Mul<Output = T> + Copy,
100    {
101        self.x * rhs.x + self.y * rhs.y
102    }
103
104    /// Takes the cross-product (a scalar) of the vector with another.
105    ///
106    /// # Examples
107    ///
108    /// ```
109    /// use veccentric::Vecc;
110    ///
111    /// let a: Vecc<i32> = Vecc::new(10, 0);
112    /// let b: Vecc<i32> = Vecc::new(0, -10);
113    ///
114    /// assert_eq!(a.cross(b), -100);
115    /// ```
116    pub fn cross(self, rhs: Vecc<T>) -> T
117    where
118        T: Sub<Output = T> + Mul<Output = T> + Copy,
119    {
120        self.x * rhs.y - self.y * rhs.x
121    }
122}
123
124/// Advanced Rust-magic. This trait is needed to implement `min` and `max` for
125/// `Fecc`, otherwise it conflicts with `Vecc<T>`'s implementation. Big thanks to [u/fisgoda](https://www.reddit.com/user/figsoda/) ([link to Reddit post](https://www.reddit.com/r/rust/comments/paw1lm/implementation_of_from_for_generic_struct/)).
126pub auto trait Notf64 {}
127impl !Notf64 for f64 {}
128
129impl<T> Vecc<T>
130where
131    T: Ord + Notf64,
132{
133    /// Performs element-wise [`min`](std::cmp::Ord::min).
134    ///
135    /// # Examples
136    ///
137    /// ```
138    /// use veccentric::Vecc;
139    ///
140    /// let a: Vecc<i32> = Vecc::new(-100, 100);
141    /// let b: Vecc<i32> = Vecc::new(0, 0);
142    /// let min = a.min(b);
143    ///
144    /// assert_eq!(min.x, -100);
145    /// assert_eq!(min.y, 0);
146    /// ```
147    pub fn min(self, rhs: Vecc<T>) -> Vecc<T> {
148        Self {
149            x: self.x.min(rhs.x),
150            y: self.y.min(rhs.y),
151        }
152    }
153
154    /// Performs element-wise [`max`](std::cmp::Ord::max).
155    ///
156    /// # Examples
157    ///
158    /// ```
159    /// use veccentric::Vecc;
160    ///
161    /// let a: Vecc<i32> = Vecc::new(-100, 100);
162    /// let b: Vecc<i32> = Vecc::new(0, 0);
163    /// let max = a.max(b);
164    ///
165    /// assert_eq!(max.x, 0);
166    /// assert_eq!(max.y, 100);
167    /// ```
168    pub fn max(self, rhs: Vecc<T>) -> Vecc<T> {
169        Self {
170            x: self.x.max(rhs.x),
171            y: self.y.max(rhs.y),
172        }
173    }
174
175    /// Performs element-wise [`clamp`](std::cmp::Ord::clamp).
176    ///
177    /// # Examples
178    ///
179    /// ```
180    /// use veccentric::Vecc;
181    ///
182    /// let a: Vecc<i32> = Vecc::new(-100, 100);
183    /// let min: Vecc<i32> = Vecc::new(0, 10);
184    /// let max: Vecc<i32> = Vecc::new(0, 10);
185    /// let clamped = a.clamp(min, max);
186    ///
187    /// assert_eq!(clamped.x, 0);
188    /// assert_eq!(clamped.y, 10);
189    /// ```
190    pub fn clamp(self, min: Vecc<T>, max: Vecc<T>) -> Vecc<T> {
191        Self {
192            x: self.x.clamp(min.x, max.x),
193            y: self.y.clamp(min.y, max.y),
194        }
195    }
196}
197
198impl<T> From<(T, T)> for Vecc<T> {
199    /// Constructs a new vector from a tuple.
200    ///
201    /// # Examples
202    ///
203    /// ```
204    /// use veccentric::Vecc;
205    ///
206    /// let a: Vecc<i32> = (10, 0).into();
207    /// ```
208    fn from((x, y): (T, T)) -> Self {
209        Self { x, y }
210    }
211}
212
213#[allow(clippy::from_over_into)]
214impl<T> Into<(T, T)> for Vecc<T> {
215    fn into(self) -> (T, T) {
216        (self.x, self.y)
217    }
218}
219
220/// Advanced Rust-magic. This trait is needed to implement `From<Vecc<U>> for
221/// `Vecc<T>`, otherwise it conflicts with core's implementation of `From<T> for T` (when `U == T`). Big thanks to [u/fisgoda](https://www.reddit.com/user/figsoda/) ([link to Reddit post](https://www.reddit.com/r/rust/comments/paw1lm/implementation_of_from_for_generic_struct/)).
222pub auto trait Different {}
223
224impl<T> !Different for (T, T) {}
225
226impl<T, U> From<Vecc<U>> for Vecc<T>
227where
228    T: From<U>,
229    (T, U): Different,
230{
231    fn from(other: Vecc<U>) -> Vecc<T> {
232        Vecc {
233            x: From::from(other.x),
234            y: From::from(other.y),
235        }
236    }
237}
238
239// Unary operators.
240
241// Neg.
242
243// Owned.
244impl<T, U> Neg for Vecc<T>
245where
246    T: Neg<Output = U>,
247{
248    type Output = Vecc<U>;
249
250    fn neg(self) -> Self::Output {
251        Vecc {
252            x: self.x.neg(),
253            y: self.y.neg(),
254        }
255    }
256}
257
258// Borrowed.
259impl<T, U> Neg for &Vecc<T>
260where
261    T: Neg<Output = U> + Copy,
262{
263    type Output = Vecc<U>;
264
265    fn neg(self) -> Self::Output {
266        Vecc {
267            x: self.x.neg(),
268            y: self.y.neg(),
269        }
270    }
271}
272
273// Not.
274
275// Owned.
276impl<T, U> Not for Vecc<T>
277where
278    T: Not<Output = U>,
279{
280    type Output = Vecc<U>;
281
282    fn not(self) -> Self::Output {
283        Vecc {
284            x: self.x.not(),
285            y: self.y.not(),
286        }
287    }
288}
289
290// Borrowed.
291impl<T, U> Not for &Vecc<T>
292where
293    T: Not<Output = U> + Copy,
294{
295    type Output = Vecc<U>;
296
297    fn not(self) -> Self::Output {
298        Vecc {
299            x: self.x.not(),
300            y: self.y.not(),
301        }
302    }
303}
304
305// Binary operators.
306
307// Add.
308
309// Owned & owned.
310impl<T> Add<Vecc<T>> for Vecc<T>
311where
312    T: Add<Output = T>,
313{
314    type Output = Vecc<T>;
315
316    fn add(self, rhs: Vecc<T>) -> Self::Output {
317        Vecc {
318            x: self.x.add(rhs.x),
319            y: self.y.add(rhs.y),
320        }
321    }
322}
323
324// Owned & borrowed.
325impl<T> Add<&Vecc<T>> for Vecc<T>
326where
327    T: Add<Output = T> + Copy,
328{
329    type Output = Vecc<T>;
330
331    fn add(self, rhs: &Vecc<T>) -> Self::Output {
332        Vecc {
333            x: self.x.add(rhs.x),
334            y: self.y.add(rhs.y),
335        }
336    }
337}
338
339// Borrowed & owned.
340impl<T> Add<Vecc<T>> for &Vecc<T>
341where
342    T: Add<Output = T> + Copy,
343{
344    type Output = Vecc<T>;
345
346    fn add(self, rhs: Vecc<T>) -> Self::Output {
347        Vecc {
348            x: self.x.add(rhs.x),
349            y: self.y.add(rhs.y),
350        }
351    }
352}
353
354// Borrowed & borrowed.
355impl<T> Add<&Vecc<T>> for &Vecc<T>
356where
357    T: Add<Output = T> + Copy,
358{
359    type Output = Vecc<T>;
360
361    fn add(self, rhs: &Vecc<T>) -> Self::Output {
362        Vecc {
363            x: self.x.add(rhs.x),
364            y: self.y.add(rhs.y),
365        }
366    }
367}
368
369// Sub.
370
371// Owned & owned.
372impl<T> Sub<Vecc<T>> for Vecc<T>
373where
374    T: Sub<Output = T>,
375{
376    type Output = Vecc<T>;
377
378    fn sub(self, rhs: Vecc<T>) -> Self::Output {
379        Vecc {
380            x: self.x.sub(rhs.x),
381            y: self.y.sub(rhs.y),
382        }
383    }
384}
385
386// Owned & borrowed.
387impl<T> Sub<&Vecc<T>> for Vecc<T>
388where
389    T: Sub<Output = T> + Copy,
390{
391    type Output = Vecc<T>;
392
393    fn sub(self, rhs: &Vecc<T>) -> Self::Output {
394        Vecc {
395            x: self.x.sub(rhs.x),
396            y: self.y.sub(rhs.y),
397        }
398    }
399}
400
401// Borrowed & owned.
402impl<T> Sub<Vecc<T>> for &Vecc<T>
403where
404    T: Sub<Output = T> + Copy,
405{
406    type Output = Vecc<T>;
407
408    fn sub(self, rhs: Vecc<T>) -> Self::Output {
409        Vecc {
410            x: self.x.sub(rhs.x),
411            y: self.y.sub(rhs.y),
412        }
413    }
414}
415
416// Borrowed & borrowed.
417impl<T> Sub<&Vecc<T>> for &Vecc<T>
418where
419    T: Sub<Output = T> + Copy,
420{
421    type Output = Vecc<T>;
422
423    fn sub(self, rhs: &Vecc<T>) -> Self::Output {
424        Vecc {
425            x: self.x.sub(rhs.x),
426            y: self.y.sub(rhs.y),
427        }
428    }
429}
430
431// Mul with T.
432
433// Owned & owned.
434impl<T> Mul<T> for Vecc<T>
435where
436    T: Mul<Output = T> + Copy,
437{
438    type Output = Vecc<T>;
439
440    fn mul(self, rhs: T) -> Self::Output {
441        Vecc {
442            x: self.x.mul(rhs),
443            y: self.y.mul(rhs),
444        }
445    }
446}
447
448// Owned & borrowed.
449impl<T> Mul<&T> for Vecc<T>
450where
451    T: Mul<Output = T> + Copy,
452{
453    type Output = Vecc<T>;
454
455    fn mul(self, rhs: &T) -> Self::Output {
456        Vecc {
457            x: self.x.mul(*rhs),
458            y: self.y.mul(*rhs),
459        }
460    }
461}
462
463// Borrowed & owned.
464impl<T> Mul<T> for &Vecc<T>
465where
466    T: Mul<Output = T> + Copy,
467{
468    type Output = Vecc<T>;
469
470    fn mul(self, rhs: T) -> Self::Output {
471        Vecc {
472            x: self.x.mul(rhs),
473            y: self.y.mul(rhs),
474        }
475    }
476}
477
478// Borrowed & borrowed.
479impl<T> Mul<&T> for &Vecc<T>
480where
481    T: Mul<Output = T> + Copy,
482{
483    type Output = Vecc<T>;
484
485    fn mul(self, rhs: &T) -> Self::Output {
486        Vecc {
487            x: self.x.mul(*rhs),
488            y: self.y.mul(*rhs),
489        }
490    }
491}
492
493// Div with T.
494
495// Owned & owned.
496impl<T> Div<T> for Vecc<T>
497where
498    T: Div<Output = T> + Copy,
499{
500    type Output = Vecc<T>;
501
502    fn div(self, rhs: T) -> Self::Output {
503        Vecc {
504            x: self.x.div(rhs),
505            y: self.y.div(rhs),
506        }
507    }
508}
509
510// Owned & borrowed.
511impl<T> Div<&T> for Vecc<T>
512where
513    T: Div<Output = T> + Copy,
514{
515    type Output = Vecc<T>;
516
517    fn div(self, rhs: &T) -> Self::Output {
518        Vecc {
519            x: self.x.div(*rhs),
520            y: self.y.div(*rhs),
521        }
522    }
523}
524
525// Borrowed & owned.
526impl<T> Div<T> for &Vecc<T>
527where
528    T: Div<Output = T> + Copy,
529{
530    type Output = Vecc<T>;
531
532    fn div(self, rhs: T) -> Self::Output {
533        Vecc {
534            x: self.x.div(rhs),
535            y: self.y.div(rhs),
536        }
537    }
538}
539
540// Borrowed & borrowed.
541impl<T> Div<&T> for &Vecc<T>
542where
543    T: Div<Output = T> + Copy,
544{
545    type Output = Vecc<T>;
546
547    fn div(self, rhs: &T) -> Self::Output {
548        Vecc {
549            x: self.x.div(*rhs),
550            y: self.y.div(*rhs),
551        }
552    }
553}
554
555// Rem.
556
557// Owned & owned.
558impl<T> Rem<Vecc<T>> for Vecc<T>
559where
560    T: Rem<Output = T> + Notf64,
561{
562    type Output = Vecc<T>;
563
564    fn rem(self, rhs: Vecc<T>) -> Self::Output {
565        Vecc {
566            x: self.x.rem(rhs.x),
567            y: self.y.rem(rhs.y),
568        }
569    }
570}
571
572// Owned & borrowed.
573impl<T> Rem<&Vecc<T>> for Vecc<T>
574where
575    T: Rem<Output = T> + Copy + Notf64,
576{
577    type Output = Vecc<T>;
578
579    fn rem(self, rhs: &Vecc<T>) -> Self::Output {
580        Vecc {
581            x: self.x.rem(rhs.x),
582            y: self.y.rem(rhs.y),
583        }
584    }
585}
586
587// Borrowed & owned.
588impl<T> Rem<Vecc<T>> for &Vecc<T>
589where
590    T: Rem<Output = T> + Copy + Notf64,
591{
592    type Output = Vecc<T>;
593
594    fn rem(self, rhs: Vecc<T>) -> Self::Output {
595        Vecc {
596            x: self.x.rem(rhs.x),
597            y: self.y.rem(rhs.y),
598        }
599    }
600}
601
602// Borrowed & borrowed.
603impl<T> Rem<&Vecc<T>> for &Vecc<T>
604where
605    T: Rem<Output = T> + Copy + Notf64,
606{
607    type Output = Vecc<T>;
608
609    fn rem(self, rhs: &Vecc<T>) -> Self::Output {
610        Vecc {
611            x: self.x.rem(rhs.x),
612            y: self.y.rem(rhs.y),
613        }
614    }
615}
616
617// Rem with T.
618
619// Owned & owned.
620impl<T> Rem<T> for Vecc<T>
621where
622    T: Rem<Output = T> + Copy + Notf64,
623{
624    type Output = Vecc<T>;
625
626    fn rem(self, rhs: T) -> Self::Output {
627        Vecc {
628            x: self.x.rem(rhs),
629            y: self.y.rem(rhs),
630        }
631    }
632}
633
634// Owned & borrowed.
635impl<T> Rem<&T> for Vecc<T>
636where
637    T: Rem<Output = T> + Copy + Notf64,
638{
639    type Output = Vecc<T>;
640
641    fn rem(self, rhs: &T) -> Self::Output {
642        Vecc {
643            x: self.x.rem(*rhs),
644            y: self.y.rem(*rhs),
645        }
646    }
647}
648
649// Borrowed & owned.
650impl<T> Rem<T> for &Vecc<T>
651where
652    T: Rem<Output = T> + Copy + Notf64,
653{
654    type Output = Vecc<T>;
655
656    fn rem(self, rhs: T) -> Self::Output {
657        Vecc {
658            x: self.x.rem(rhs),
659            y: self.y.rem(rhs),
660        }
661    }
662}
663
664// Borrowed & borrowed.
665impl<T> Rem<&T> for &Vecc<T>
666where
667    T: Rem<Output = T> + Copy + Notf64,
668{
669    type Output = Vecc<T>;
670
671    fn rem(self, rhs: &T) -> Self::Output {
672        Vecc {
673            x: self.x.rem(*rhs),
674            y: self.y.rem(*rhs),
675        }
676    }
677}
678
679// *Assign.
680
681// AddAssign.
682
683// Owned.
684impl<T> AddAssign<Vecc<T>> for Vecc<T>
685where
686    T: AddAssign<T>,
687{
688    fn add_assign(&mut self, other: Vecc<T>) {
689        self.x.add_assign(other.x);
690        self.y.add_assign(other.y);
691    }
692}
693
694// Borrowed.
695impl<T> AddAssign<&Vecc<T>> for Vecc<T>
696where
697    T: AddAssign<T> + Copy,
698{
699    fn add_assign(&mut self, other: &Vecc<T>) {
700        self.x.add_assign(other.x);
701        self.y.add_assign(other.y);
702    }
703}
704
705// SubAssign.
706
707// Owned.
708impl<T> SubAssign<Vecc<T>> for Vecc<T>
709where
710    T: SubAssign<T>,
711{
712    fn sub_assign(&mut self, rhs: Vecc<T>) {
713        self.x.sub_assign(rhs.x);
714        self.y.sub_assign(rhs.y);
715    }
716}
717
718// Borrowed.
719impl<T> SubAssign<&Vecc<T>> for Vecc<T>
720where
721    T: SubAssign<T> + Copy,
722{
723    fn sub_assign(&mut self, rhs: &Vecc<T>) {
724        self.x.sub_assign(rhs.x);
725        self.y.sub_assign(rhs.y);
726    }
727}
728
729// MulAssign with T.
730
731// Owned.
732impl<T> MulAssign<T> for Vecc<T>
733where
734    T: MulAssign<T> + Copy,
735{
736    fn mul_assign(&mut self, rhs: T) {
737        self.x.mul_assign(rhs);
738        self.y.mul_assign(rhs);
739    }
740}
741
742// Borrowed.
743impl<T> MulAssign<&T> for Vecc<T>
744where
745    T: MulAssign<T> + Copy,
746{
747    fn mul_assign(&mut self, rhs: &T) {
748        self.x.mul_assign(*rhs);
749        self.y.mul_assign(*rhs);
750    }
751}
752
753// DivAssign with T.
754
755// Owned.
756impl<T> DivAssign<T> for Vecc<T>
757where
758    T: DivAssign<T> + Copy,
759{
760    fn div_assign(&mut self, rhs: T) {
761        self.x.div_assign(rhs);
762        self.y.div_assign(rhs);
763    }
764}
765
766// Borrowed.
767impl<T> DivAssign<&T> for Vecc<T>
768where
769    T: DivAssign<T> + Copy,
770{
771    fn div_assign(&mut self, rhs: &T) {
772        self.x.div_assign(*rhs);
773        self.y.div_assign(*rhs);
774    }
775}
776
777// RemAssign.
778
779// Owned.
780impl<T> RemAssign<Vecc<T>> for Vecc<T>
781where
782    T: RemAssign<T> + Notf64,
783{
784    fn rem_assign(&mut self, rhs: Vecc<T>) {
785        self.x.rem_assign(rhs.x);
786        self.y.rem_assign(rhs.y);
787    }
788}
789
790// Borrowed.
791impl<T> RemAssign<&Vecc<T>> for Vecc<T>
792where
793    T: RemAssign<T> + Copy + Notf64,
794{
795    fn rem_assign(&mut self, rhs: &Vecc<T>) {
796        self.x.rem_assign(rhs.x);
797        self.y.rem_assign(rhs.y);
798    }
799}
800
801// RemAssign with T.
802
803// Owned.
804impl<T> RemAssign<T> for Vecc<T>
805where
806    T: RemAssign<T> + Copy + Notf64,
807{
808    fn rem_assign(&mut self, rhs: T) {
809        self.x.rem_assign(rhs);
810        self.y.rem_assign(rhs);
811    }
812}
813
814// Borrowed.
815impl<T> RemAssign<&T> for Vecc<T>
816where
817    T: RemAssign<T> + Copy + Notf64,
818{
819    fn rem_assign(&mut self, rhs: &T) {
820        self.x.rem_assign(*rhs);
821        self.y.rem_assign(*rhs);
822    }
823}