ultraviolet/vec/
vec3.rs

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