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 $(#[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[inline]
314 pub fn as_slice(&self) -> &[$t] {
315 unsafe {
318 std::slice::from_raw_parts(self as *const $n as *const $t, 3)
319 }
320 }
321
322 #[inline]
324 pub fn as_mut_slice(&mut self) -> &mut [$t] {
325 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 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 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 #[inline]
358 pub const fn as_ptr(&self) -> *const $t {
359 self as *const $n as *const $t
360 }
361
362 #[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 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
591macro_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
639macro_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 #[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);