ultraviolet/vec/
vec4.rs

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