ultraviolet/vec/
vec2.rs

1use std::ops::*;
2
3use crate::util::EqualsEps;
4use crate::*;
5
6macro_rules! vec2s {
7    ($(($n:ident, $bn:ident, $rn:ident, $v3t:ident, $v4t:ident) => $t:ident),+) => {
8        $(
9        /// A set of two coordinates which may be interpreted as a vector or point in 2d space.
10        ///
11        /// Generally this distinction between a point and vector is more of a pain than it is worth
12        /// to distinguish on a type level, however when converting to and from homogeneous
13        /// coordinates it is quite important.
14        #[derive(Clone, Copy, Debug, Default, PartialEq)]
15        #[repr(C)]
16        pub struct $n {
17            pub x: $t,
18            pub y: $t,
19        }
20
21        impl $n {
22            #[inline]
23            pub const fn new(x: $t, y: $t) -> Self {
24                $n { x, y }
25            }
26
27            #[inline]
28            pub const fn broadcast(val: $t) -> Self {
29                Self::new(val, val)
30            }
31
32            #[inline]
33            pub fn unit_x() -> Self {
34                $n{ x: $t::splat(1.0), y: $t::splat(0.0) }
35            }
36
37            #[inline]
38            pub fn unit_y() -> Self {
39                $n{ x: $t::splat(0.0), y: $t::splat(1.0) }
40            }
41
42            /// Create a homogeneous 2d *point* from this vector interpreted as a point,
43            /// meaning the homogeneous component will start with a value of 1.0.
44            #[inline]
45            pub fn into_homogeneous_point(self) -> $v3t {
46                $v3t { x: self.x, y: self.y, z: $t::splat(1.0) }
47            }
48
49            /// Create a homogeneous 2d *vector* from this vector,
50            /// meaning the homogeneous component will always have a value of 0.0.
51            #[inline]
52            pub fn into_homogeneous_vector(self) -> $v3t {
53                $v3t { x: self.x, y: self.y, z: $t::splat(0.0) }
54            }
55
56            /// Create a 2d point from a homogeneous 2d *point*, performing
57            /// division by the homogeneous component. This should not be used
58            /// for homogeneous 2d *vectors*, which will have 0 as their
59            /// homogeneous component.
60            #[inline]
61            pub fn from_homogeneous_point(v: $v3t) -> Self {
62                Self { x: v.x / v.z, y: v.y / v.z }
63            }
64
65            /// Create a 2d vector from homogeneous 2d *vector*, which simply
66            /// discards the homogeneous component.
67            #[inline]
68            pub fn from_homogeneous_vector(v: $v3t) -> Self {
69                v.into()
70            }
71
72            #[inline]
73            pub fn dot(&self, other: $n) -> $t {
74                (self.x * other.x) + (self.y * other.y)
75            }
76
77            /// The wedge (aka exterior) product of two vectors.
78            ///
79            /// Note: Sometimes called "cross" product in 2D.
80            /// Such a product is not well defined in 2 dimensions
81            /// and is really just shorthand notation for a hacky operation that
82            /// extends the vectors into 3 dimensions, takes the cross product,
83            /// then returns only the resulting Z component as a pseudoscalar value.
84            /// This value is will have the same value as
85            /// the resulting bivector of the wedge product in 2d (a 2d
86            /// bivector is also a kind of pseudoscalar value), so you may use
87            /// this product to calculate the same value.
88            ///
89            /// This operation results in a bivector, which represents
90            /// the plane parallel to the two vectors, and which has a
91            /// 'oriented area' equal to the parallelogram created by extending
92            /// the two vectors, oriented such that the positive direction is the
93            /// one which would move `self` closer to `other`.
94            #[inline]
95            pub fn wedge(&self, other: $n) -> $bn {
96                $bn::new((self.x * other.y) - (other.x * self.y))
97            }
98
99            /// The geometric product of this and another vector, which
100            /// is defined as the sum of the dot product and the wedge product.
101            ///
102            /// This operation results in a 'rotor', named as such as it may define
103            /// a rotation. The rotor which results from the geometric product
104            /// will rotate in the plane parallel to the two vectors, by twice the angle between
105            /// them and in the opposite direction (i.e. it will rotate in the direction that would
106            /// bring `other` towards `self`, and rotate in that direction by twice the angle between them).
107            #[inline]
108            pub fn geom(&self, other: $n) -> $rn {
109                $rn::new(self.dot(other), self.wedge(other))
110            }
111
112            #[inline]
113            pub fn rotate_by(&mut self, rotor: $rn) {
114                rotor.rotate_vec(self);
115            }
116
117            #[inline]
118            pub fn rotated_by(mut self, rotor: $rn) -> Self {
119                rotor.rotate_vec(&mut self);
120                self
121            }
122
123            #[inline]
124            pub fn reflected(&self, normal: $n) -> Self {
125                *self - ($t::splat(2.0) * self.dot(normal) * normal)
126            }
127
128            #[inline]
129            pub fn mag_sq(&self) -> $t {
130                (self.x * self.x) + (self.y * self.y)
131            }
132
133            #[inline]
134            pub fn mag(&self) -> $t {
135                self.mag_sq().sqrt()
136            }
137
138            #[inline]
139            pub fn normalize(&mut self) {
140                let r_mag = $t::splat(1.0) /self.mag();
141                self.x *= r_mag;
142                self.y *= r_mag;
143            }
144
145            #[inline]
146            #[must_use = "Did you mean to use `.normalize()` to normalize `self` in place?"]
147            pub fn normalized(&self) -> Self {
148                let mut r = self.clone();
149                r.normalize();
150                r
151            }
152
153            #[inline]
154            pub fn mul_add(&self, mul: $n, add: $n) -> Self {
155                $n::new(
156                    self.x.mul_add(mul.x, add.x),
157                    self.y.mul_add(mul.y, add.y),
158                )
159            }
160
161            #[inline]
162            pub fn abs(&self) -> Self {
163                Self::new(self.x.abs(), self.y.abs())
164            }
165
166            #[inline]
167            pub fn clamp(&mut self, min: Self, max: Self) {
168                self.x = self.x.max(min.x).min(max.x);
169                self.y = self.y.max(min.y).min(max.y);
170            }
171
172            #[inline]
173            pub fn clamped(mut self, min: Self, max: Self) -> Self {
174                self.clamp(min, max);
175                self
176            }
177
178            #[inline]
179            pub fn map<F>(&self, mut f: F) -> Self
180                where F: FnMut($t) -> $t
181            {
182                $n::new(
183                    f(self.x),
184                    f(self.y),
185                )
186            }
187
188            #[inline]
189            pub fn apply<F>(&mut self, mut f: F)
190                where F: FnMut($t) -> $t
191            {
192                self.x = f(self.x);
193                self.y = f(self.y);
194            }
195
196            #[inline]
197            pub fn max_by_component(mut self, other: Self) -> Self {
198                self.x = self.x.max(other.x);
199                self.y = self.y.max(other.y);
200                self
201            }
202
203            #[inline]
204            pub fn min_by_component(mut self, other: Self) -> Self {
205                self.x = self.x.min(other.x);
206                self.y = self.y.min(other.y);
207                self
208            }
209
210            #[inline]
211            pub fn component_max(&self) -> $t {
212                self.x.max(self.y)
213            }
214
215            #[inline]
216            pub fn component_min(&self) -> $t {
217                self.x.min(self.y)
218            }
219
220            #[inline]
221            pub fn zero() -> Self {
222                Self::broadcast($t::splat(0.0))
223            }
224
225            #[inline]
226            pub fn one() -> Self {
227                Self::broadcast($t::splat(1.0))
228            }
229
230            #[inline]
231            pub fn xyz(&self) -> $v3t {
232                $v3t::new(self.x, self.y, $t::splat(0.0))
233            }
234
235            #[inline]
236            pub fn xyzw(&self) -> $v4t {
237                $v4t::new(self.x, self.y, $t::splat(0.0), $t::splat(0.0))
238            }
239
240            /// Get the [`core::alloc::Layout`] of `Self`
241            #[inline]
242            pub fn layout() -> alloc::alloc::Layout {
243                alloc::alloc::Layout::from_size_align(std::mem::size_of::<Self>(), std::mem::align_of::<$t>()).unwrap()
244            }
245
246            /// Interpret `self` as a statically-sized array of its base numeric type
247            #[inline]
248            pub fn as_array(&self) -> &[$t; 2] {
249                let ptr = self as *const $n as *const [$t; 2];
250                unsafe { &*ptr }
251            }
252
253            /// Interpret `self` as a statically-sized array of its base numeric type
254            #[inline]
255            pub fn as_mut_array(&mut self) -> &mut [$t; 2] {
256                let ptr = self as *mut $n as *mut [$t; 2];
257                unsafe { &mut *ptr }
258            }
259
260            /// Interpret `self` as a slice of its base numeric type
261            #[inline]
262            pub fn as_slice(&self) -> &[$t] {
263                // This is safe because we are statically bounding our slices to the size of these
264                // vectors
265                unsafe {
266                    std::slice::from_raw_parts(self as *const $n as *const $t, 2)
267                }
268            }
269
270            /// Interpret `self` as a slice of its base numeric type
271            #[inline]
272            pub fn as_mut_slice(&mut self) -> &mut [$t] {
273                // This is safe because we are statically bounding our slices to the size of these
274                // vectors
275                unsafe {
276                    std::slice::from_raw_parts_mut(self as *mut $n as *mut $t, 2)
277                }
278            }
279
280            #[inline]
281            pub fn as_byte_slice(&self) -> &[u8] {
282                // This is safe because we are statically bounding our slices to the size of these
283                // vectors
284                unsafe {
285                    std::slice::from_raw_parts(self as *const $n as *const u8, 2 * std::mem::size_of::<$t>())
286                }
287            }
288
289            #[inline]
290            pub fn as_mut_byte_slice(&mut self) -> &mut [u8] {
291                // This is safe because we are statically bounding our slices to the size of these
292                // vectors
293                unsafe {
294                    std::slice::from_raw_parts_mut(self as *mut $n as *mut u8, 2 * std::mem::size_of::<$t>())
295                }
296            }
297
298            /// Returns a constant unsafe pointer to the underlying data in the underlying type.
299            /// This function is safe because all types here are repr(C) and can be represented
300            /// as their underlying type.
301            ///
302            /// # Safety
303            ///
304            /// It is up to the caller to correctly use this pointer and its bounds.
305            #[inline]
306            pub const fn as_ptr(&self) -> *const $t {
307                self as *const $n as *const $t
308            }
309
310            /// Returns a mutable unsafe pointer to the underlying data in the underlying type.
311            /// This function is safe because all types here are repr(C) and can be represented
312            /// as their underlying type.
313            ///
314            /// # Safety
315            ///
316            /// It is up to the caller to correctly use this pointer and its bounds.
317            #[inline]
318            pub fn as_mut_ptr(&mut self) -> *mut $t {
319                self as *mut $n as *mut $t
320            }
321        }
322
323        impl From<$n> for [$t; 2] {
324            #[inline]
325            fn from(v: $n) -> Self {
326                [v.x, v.y]
327            }
328        }
329
330        impl From<[$t; 2]> for $n {
331            #[inline]
332            fn from(comps: [$t; 2]) -> Self {
333                Self::new(comps[0], comps[1])
334            }
335        }
336
337        impl From<&[$t; 2]> for $n {
338            #[inline]
339            fn from(comps: &[$t; 2]) -> Self {
340                Self::from(*comps)
341            }
342        }
343
344        impl From<&mut [$t; 2]> for $n {
345            #[inline]
346            fn from(comps: &mut [$t; 2]) -> Self {
347                Self::from(*comps)
348            }
349        }
350
351        impl From<($t, $t)> for $n {
352            #[inline]
353            fn from(comps: ($t, $t)) -> Self {
354                Self::new(comps.0, comps.1)
355            }
356        }
357
358        impl From<&($t, $t)> for $n {
359            #[inline]
360            fn from(comps: &($t, $t)) -> Self {
361                Self::from(*comps)
362            }
363        }
364
365        impl From<$n> for ($t, $t) {
366            #[inline]
367            fn from(v: $n) -> Self {
368                (v.x, v.y)
369            }
370        }
371
372        impl EqualsEps for $n {
373            fn eq_eps(self, other: Self) -> bool {
374                self.x.eq_eps(other.x) && self.y.eq_eps(other.y)
375            }
376        }
377
378        impl Add for $n {
379            type Output = Self;
380            #[inline]
381            fn add(self, rhs: $n) -> Self {
382                $n::new(self.x + rhs.x, self.y + rhs.y)
383            }
384        }
385
386        impl AddAssign for $n {
387            #[inline]
388            fn add_assign(&mut self, rhs: $n) {
389                self.x += rhs.x;
390                self.y += rhs.y;
391            }
392        }
393
394        impl Sub for $n {
395            type Output = Self;
396            #[inline]
397            fn sub(self, rhs: $n) -> Self {
398                $n::new(self.x - rhs.x, self.y - rhs.y)
399            }
400        }
401
402        impl SubAssign for $n {
403            #[inline]
404            fn sub_assign(&mut self, rhs: $n) {
405                self.x -= rhs.x;
406                self.y -= rhs.y;
407            }
408        }
409
410        impl Mul for $n {
411            type Output = Self;
412            #[inline]
413            fn mul(self, rhs: $n) -> Self {
414                $n::new(self.x * rhs.x, self.y * rhs.y)
415            }
416        }
417
418        impl Mul<$n> for $t {
419            type Output = $n;
420            #[inline]
421            fn mul(self, rhs: $n) -> $n {
422                $n::new(self * rhs.x, self * rhs.y)
423            }
424        }
425
426        impl Mul<$t> for $n {
427            type Output = $n;
428            #[inline]
429            fn mul(self, rhs: $t) -> $n {
430                $n::new(self.x * rhs, self.y * rhs)
431            }
432        }
433
434        impl MulAssign for $n {
435            #[inline]
436            fn mul_assign(&mut self, rhs: $n) {
437                self.x *= rhs.x;
438                self.y *= rhs.y;
439            }
440        }
441
442        impl MulAssign<$t> for $n {
443            #[inline]
444            fn mul_assign(&mut self, rhs: $t) {
445                self.x *= rhs;
446                self.y *= rhs;
447            }
448        }
449
450        impl Div for $n {
451            type Output = Self;
452            #[inline]
453            fn div(self, rhs: $n) -> Self {
454                $n::new(self.x / rhs.x, self.y / rhs.y)
455            }
456        }
457
458        impl Div<$t> for $n {
459            type Output = $n;
460            #[inline]
461            fn div(self, rhs: $t) -> $n {
462                $n::new(self.x / rhs, self.y / rhs)
463            }
464        }
465
466        impl DivAssign for $n {
467            #[inline]
468            fn div_assign(&mut self, rhs: $n) {
469                self.x /= rhs.x;
470                self.y /= rhs.y;
471            }
472        }
473
474        impl DivAssign<$t> for $n {
475            #[inline]
476            fn div_assign(&mut self, rhs: $t) {
477                self.x /= rhs;
478                self.y /= rhs;
479            }
480        }
481
482        impl Neg for $n {
483            type Output = $n;
484            #[inline]
485            fn neg(self) -> $n {
486                self * $t::splat(-1.0)
487            }
488        }
489
490        impl Index<usize> for $n {
491            type Output = $t;
492
493            fn index(&self, index: usize) -> &Self::Output {
494                match index {
495                    0 => &self.x,
496                    1 => &self.y,
497                    _ => panic!("Invalid for vector of type: {}", std::any::type_name::<$n>()),
498                }
499            }
500        }
501
502        impl IndexMut<usize> for $n {
503            fn index_mut(&mut self, index: usize) -> &mut Self::Output {
504                match index {
505                    0 => &mut self.x,
506                    1 => &mut self.y,
507                    _ => panic!("Invalid for vector of type: {}", std::any::type_name::<$n>()),
508                }
509            }
510        }
511
512        impl std::iter::Sum<$n> for $n {
513            fn sum<I>(iter: I) -> Self where I: Iterator<Item = Self> {
514                // Kahan summation algorithm
515                // https://en.wikipedia.org/wiki/Kahan_summation_algorithm
516                let mut sum = $n::zero();
517                let mut c = $n::zero();
518                for v in iter {
519                    let y = v - c;
520                    let t = sum + y;
521                    c = (t - sum) - y;
522                    sum = t;
523                }
524                sum
525            }
526        }
527        )+
528    };
529}
530
531// SCALAR VEC2 IMPLS
532
533macro_rules! impl_scalar_vec2s {
534    ($(($vt:ident, $v3t:ident) => $t:ident),+) => {
535        $(impl $vt {
536            #[inline]
537            pub fn refract(&mut self, normal: Self, eta: $t) {
538                *self = self.refracted(normal, eta);
539            }
540
541            #[inline]
542            pub fn refracted(&self, normal: Self, eta: $t) -> Self {
543                let n = normal;
544                let i = *self;
545                let ndi = n.dot(i);
546                let k = 1.0 - eta * eta * (1.0 - ndi * ndi);
547                if k < 0.0 {
548                    Self::zero()
549                } else {
550                    i * eta - (eta * ndi + k.sqrt()) * n
551                }
552            }
553        }
554
555        impl From<$v3t> for $vt {
556            #[inline]
557            fn from(vec: $v3t) -> Self {
558                Self { x: vec.x, y: vec.y }
559            }
560        })+
561    };
562}
563
564// WIDE VEC2 IMPLS
565
566macro_rules! impl_wide_vec2s {
567    ($($vt:ident => $tt:ident, $t:ident, $maskt:ident, $nonwidet:ident, $v3t:ident),+) => {
568        $(impl $vt {
569            #[inline]
570            pub fn new_splat(x: $tt, y: $tt) -> Self {
571                Self {
572                    x: $t::splat(x),
573                    y: $t::splat(y),
574                }
575            }
576
577            #[inline]
578            pub fn splat(vec: $nonwidet) -> Self {
579                Self {
580                    x: $t::splat(vec.x),
581                    y: $t::splat(vec.y),
582                }
583            }
584
585            /// Blend two vectors together lanewise using `mask` as a mask.
586            ///
587            /// This is essentially a bitwise blend operation, such that any point where
588            /// there is a 1 bit in `mask`, the output will put the bit from `tru`, while
589            /// where there is a 0 bit in `mask`, the output will put the bit from `fals`
590            #[inline]
591            pub fn blend(mask: $maskt, tru: Self, fals: Self) -> Self {
592                Self {
593                    x: mask.blend(tru.x, fals.x),
594                    y: mask.blend(tru.y, fals.y),
595                }
596            }
597
598            #[inline]
599            pub fn refract(&mut self, normal: Self, eta: $t) {
600                *self = self.refracted(normal, eta);
601            }
602
603            #[inline]
604            pub fn refracted(&self, normal: Self, eta: $t) -> Self {
605                let n = normal;
606                let i = *self;
607                let one = $t::splat(1.0);
608                let ndi = n.dot(i);
609
610                let k = one - eta * eta * (one - ndi * ndi);
611                let mask = k.cmp_lt($t::splat(0.0));
612
613                let out = i * eta - (eta * ndi + k.sqrt()) * n;
614
615                Self::blend(mask, Self::zero(), out)
616            }
617        }
618
619        impl From<$nonwidet> for $vt {
620            #[inline]
621            fn from(vec: $nonwidet) -> Self {
622                Self::splat(vec)
623            }
624        }
625
626        impl From<$v3t> for $vt {
627            #[inline]
628            fn from(vec: $v3t) -> Self {
629                Self { x: vec.x, y: vec.y }
630            }
631        })+
632    }
633}
634
635impl From<Vec2x4> for [Vec2; 4] {
636    #[inline]
637    fn from(v: Vec2x4) -> Self {
638        let xs: [f32; 4] = v.x.into();
639        let ys: [f32; 4] = v.y.into();
640        [
641            Vec2::new(xs[0], ys[0]),
642            Vec2::new(xs[1], ys[1]),
643            Vec2::new(xs[2], ys[2]),
644            Vec2::new(xs[3], ys[3]),
645        ]
646    }
647}
648
649impl From<[Vec2; 4]> for Vec2x4 {
650    #[inline]
651    fn from(vecs: [Vec2; 4]) -> Self {
652        Self {
653            x: f32x4::from([vecs[0].x, vecs[1].x, vecs[2].x, vecs[3].x]),
654            y: f32x4::from([vecs[0].y, vecs[1].y, vecs[2].y, vecs[3].y]),
655        }
656    }
657}
658
659impl From<Vec2x8> for [Vec2; 8] {
660    #[inline]
661    fn from(v: Vec2x8) -> Self {
662        let xs: [f32; 8] = v.x.into();
663        let ys: [f32; 8] = v.y.into();
664        [
665            Vec2::new(xs[0], ys[0]),
666            Vec2::new(xs[1], ys[1]),
667            Vec2::new(xs[2], ys[2]),
668            Vec2::new(xs[3], ys[3]),
669            Vec2::new(xs[4], ys[4]),
670            Vec2::new(xs[5], ys[5]),
671            Vec2::new(xs[6], ys[6]),
672            Vec2::new(xs[7], ys[7]),
673        ]
674    }
675}
676
677impl From<[Vec2; 8]> for Vec2x8 {
678    #[inline]
679    fn from(vecs: [Vec2; 8]) -> Self {
680        Self {
681            x: f32x8::from([
682                vecs[0].x, vecs[1].x, vecs[2].x, vecs[3].x, vecs[4].x, vecs[5].x, vecs[6].x,
683                vecs[7].x,
684            ]),
685            y: f32x8::from([
686                vecs[0].y, vecs[1].y, vecs[2].y, vecs[3].y, vecs[4].y, vecs[5].y, vecs[6].y,
687                vecs[7].y,
688            ]),
689        }
690    }
691}
692
693#[cfg(feature = "f64")]
694impl From<DVec2x2> for [DVec2; 2] {
695    #[inline]
696    fn from(v: DVec2x2) -> Self {
697        let xs: [f64; 2] = v.x.into();
698        let ys: [f64; 2] = v.y.into();
699        [DVec2::new(xs[0], ys[0]), DVec2::new(xs[1], ys[1])]
700    }
701}
702
703#[cfg(feature = "f64")]
704impl From<[DVec2; 2]> for DVec2x2 {
705    #[inline]
706    fn from(vecs: [DVec2; 2]) -> Self {
707        Self {
708            x: f64x2::from([vecs[0].x, vecs[1].x]),
709            y: f64x2::from([vecs[0].y, vecs[1].y]),
710        }
711    }
712}
713
714#[cfg(feature = "f64")]
715impl From<DVec2x4> for [DVec2; 4] {
716    #[inline]
717    fn from(v: DVec2x4) -> Self {
718        let xs: [f64; 4] = v.x.into();
719        let ys: [f64; 4] = v.y.into();
720        [
721            DVec2::new(xs[0], ys[0]),
722            DVec2::new(xs[1], ys[1]),
723            DVec2::new(xs[2], ys[2]),
724            DVec2::new(xs[3], ys[3]),
725        ]
726    }
727}
728
729#[cfg(feature = "f64")]
730impl From<[DVec2; 4]> for DVec2x4 {
731    #[inline]
732    fn from(vecs: [DVec2; 4]) -> Self {
733        Self {
734            x: f64x4::from([vecs[0].x, vecs[1].x, vecs[2].x, vecs[3].x]),
735            y: f64x4::from([vecs[0].y, vecs[1].y, vecs[2].y, vecs[3].y]),
736        }
737    }
738}
739
740vec2s!(
741    (Vec2, Bivec2, Rotor2, Vec3, Vec4) => f32,
742    (Vec2x4, Bivec2x4, Rotor2x4, Vec3x4, Vec4x4) => f32x4,
743    (Vec2x8, Bivec2x8, Rotor2x8, Vec3x8, Vec4x8) => f32x8
744);
745
746#[cfg(feature = "f64")]
747vec2s!(
748    (DVec2, DBivec2, DRotor2, DVec3, DVec4) => f64,
749    (DVec2x2, DBivec2x2, DRotor2x2, DVec3x2, DVec4x2) => f64x2,
750    (DVec2x4, DBivec2x4, DRotor2x4, DVec3x4, DVec4x4) => f64x4
751);
752
753impl_scalar_vec2s!(
754    (Vec2, Vec3) => f32
755);
756
757#[cfg(feature = "f64")]
758impl_scalar_vec2s!(
759    (DVec2, DVec3) => f64
760);
761
762impl_wide_vec2s!(
763    Vec2x4 => f32, f32x4, m32x4, Vec2, Vec3x4,
764    Vec2x8 => f32, f32x8, m32x8, Vec2, Vec3x8
765);
766
767#[cfg(feature = "f64")]
768impl_wide_vec2s!(
769    DVec2x2 => f64, f64x2, m64x2, DVec2, DVec3x2,
770    DVec2x4 => f64, f64x4, m64x4, DVec2, DVec3x4
771);