geometric_algebra/
epga2d.rs

1#![allow(clippy::assign_op_pattern)]
2use crate::{simd::*, *};
3use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
4
5#[derive(Clone, Copy)]
6struct MultiVectorGroups {
7    /// 1, e12, e1, e2
8    g0: Simd32x4,
9    /// e0, e012, e01, -e02
10    g1: Simd32x4,
11}
12
13#[derive(Clone, Copy)]
14pub union MultiVector {
15    groups: MultiVectorGroups,
16    /// 1, e12, e1, e2, e0, e012, e01, -e02
17    elements: [f32; 8],
18}
19
20impl MultiVector {
21    #[allow(clippy::too_many_arguments)]
22    pub const fn new(scalar: f32, e12: f32, e1: f32, e2: f32, e0: f32, e012: f32, e01: f32, _e02: f32) -> Self {
23        Self { elements: [scalar, e12, e1, e2, e0, e012, e01, _e02] }
24    }
25    pub const fn from_groups(g0: Simd32x4, g1: Simd32x4) -> Self {
26        Self { groups: MultiVectorGroups { g0, g1 } }
27    }
28    #[inline(always)]
29    pub fn group0(&self) -> Simd32x4 {
30        unsafe { self.groups.g0 }
31    }
32    #[inline(always)]
33    pub fn group0_mut(&mut self) -> &mut Simd32x4 {
34        unsafe { &mut self.groups.g0 }
35    }
36    #[inline(always)]
37    pub fn group1(&self) -> Simd32x4 {
38        unsafe { self.groups.g1 }
39    }
40    #[inline(always)]
41    pub fn group1_mut(&mut self) -> &mut Simd32x4 {
42        unsafe { &mut self.groups.g1 }
43    }
44}
45
46const MULTIVECTOR_INDEX_REMAP: [usize; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
47
48impl std::ops::Index<usize> for MultiVector {
49    type Output = f32;
50
51    fn index(&self, index: usize) -> &Self::Output {
52        unsafe { &self.elements[MULTIVECTOR_INDEX_REMAP[index]] }
53    }
54}
55
56impl std::ops::IndexMut<usize> for MultiVector {
57    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
58        unsafe { &mut self.elements[MULTIVECTOR_INDEX_REMAP[index]] }
59    }
60}
61
62impl std::convert::From<MultiVector> for [f32; 8] {
63    fn from(vector: MultiVector) -> Self {
64        unsafe { [vector.elements[0], vector.elements[1], vector.elements[2], vector.elements[3], vector.elements[4], vector.elements[5], vector.elements[6], vector.elements[7]] }
65    }
66}
67
68impl std::convert::From<[f32; 8]> for MultiVector {
69    fn from(array: [f32; 8]) -> Self {
70        Self { elements: [array[0], array[1], array[2], array[3], array[4], array[5], array[6], array[7]] }
71    }
72}
73
74impl std::fmt::Debug for MultiVector {
75    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
76        formatter
77            .debug_struct("MultiVector")
78            .field("1", &self[0])
79            .field("e12", &self[1])
80            .field("e1", &self[2])
81            .field("e2", &self[3])
82            .field("e0", &self[4])
83            .field("e012", &self[5])
84            .field("e01", &self[6])
85            .field("-e02", &self[7])
86            .finish()
87    }
88}
89
90#[derive(Clone, Copy)]
91struct RotorGroups {
92    /// 1, e12
93    g0: Simd32x2,
94}
95
96#[derive(Clone, Copy)]
97pub union Rotor {
98    groups: RotorGroups,
99    /// 1, e12, 0, 0
100    elements: [f32; 4],
101}
102
103impl Rotor {
104    #[allow(clippy::too_many_arguments)]
105    pub const fn new(scalar: f32, e12: f32) -> Self {
106        Self { elements: [scalar, e12, 0.0, 0.0] }
107    }
108    pub const fn from_groups(g0: Simd32x2) -> Self {
109        Self { groups: RotorGroups { g0 } }
110    }
111    #[inline(always)]
112    pub fn group0(&self) -> Simd32x2 {
113        unsafe { self.groups.g0 }
114    }
115    #[inline(always)]
116    pub fn group0_mut(&mut self) -> &mut Simd32x2 {
117        unsafe { &mut self.groups.g0 }
118    }
119}
120
121const ROTOR_INDEX_REMAP: [usize; 2] = [0, 1];
122
123impl std::ops::Index<usize> for Rotor {
124    type Output = f32;
125
126    fn index(&self, index: usize) -> &Self::Output {
127        unsafe { &self.elements[ROTOR_INDEX_REMAP[index]] }
128    }
129}
130
131impl std::ops::IndexMut<usize> for Rotor {
132    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
133        unsafe { &mut self.elements[ROTOR_INDEX_REMAP[index]] }
134    }
135}
136
137impl std::convert::From<Rotor> for [f32; 2] {
138    fn from(vector: Rotor) -> Self {
139        unsafe { [vector.elements[0], vector.elements[1]] }
140    }
141}
142
143impl std::convert::From<[f32; 2]> for Rotor {
144    fn from(array: [f32; 2]) -> Self {
145        Self { elements: [array[0], array[1], 0.0, 0.0] }
146    }
147}
148
149impl std::fmt::Debug for Rotor {
150    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
151        formatter
152            .debug_struct("Rotor")
153            .field("1", &self[0])
154            .field("e12", &self[1])
155            .finish()
156    }
157}
158
159#[derive(Clone, Copy)]
160struct PointGroups {
161    /// e12, e01, -e02
162    g0: Simd32x3,
163}
164
165#[derive(Clone, Copy)]
166pub union Point {
167    groups: PointGroups,
168    /// e12, e01, -e02, 0
169    elements: [f32; 4],
170}
171
172impl Point {
173    #[allow(clippy::too_many_arguments)]
174    pub const fn new(e12: f32, e01: f32, _e02: f32) -> Self {
175        Self { elements: [e12, e01, _e02, 0.0] }
176    }
177    pub const fn from_groups(g0: Simd32x3) -> Self {
178        Self { groups: PointGroups { g0 } }
179    }
180    #[inline(always)]
181    pub fn group0(&self) -> Simd32x3 {
182        unsafe { self.groups.g0 }
183    }
184    #[inline(always)]
185    pub fn group0_mut(&mut self) -> &mut Simd32x3 {
186        unsafe { &mut self.groups.g0 }
187    }
188}
189
190const POINT_INDEX_REMAP: [usize; 3] = [0, 1, 2];
191
192impl std::ops::Index<usize> for Point {
193    type Output = f32;
194
195    fn index(&self, index: usize) -> &Self::Output {
196        unsafe { &self.elements[POINT_INDEX_REMAP[index]] }
197    }
198}
199
200impl std::ops::IndexMut<usize> for Point {
201    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
202        unsafe { &mut self.elements[POINT_INDEX_REMAP[index]] }
203    }
204}
205
206impl std::convert::From<Point> for [f32; 3] {
207    fn from(vector: Point) -> Self {
208        unsafe { [vector.elements[0], vector.elements[1], vector.elements[2]] }
209    }
210}
211
212impl std::convert::From<[f32; 3]> for Point {
213    fn from(array: [f32; 3]) -> Self {
214        Self { elements: [array[0], array[1], array[2], 0.0] }
215    }
216}
217
218impl std::fmt::Debug for Point {
219    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
220        formatter
221            .debug_struct("Point")
222            .field("e12", &self[0])
223            .field("e01", &self[1])
224            .field("-e02", &self[2])
225            .finish()
226    }
227}
228
229#[derive(Clone, Copy)]
230struct IdealPointGroups {
231    /// e01, -e02
232    g0: Simd32x2,
233}
234
235#[derive(Clone, Copy)]
236pub union IdealPoint {
237    groups: IdealPointGroups,
238    /// e01, -e02, 0, 0
239    elements: [f32; 4],
240}
241
242impl IdealPoint {
243    #[allow(clippy::too_many_arguments)]
244    pub const fn new(e01: f32, _e02: f32) -> Self {
245        Self { elements: [e01, _e02, 0.0, 0.0] }
246    }
247    pub const fn from_groups(g0: Simd32x2) -> Self {
248        Self { groups: IdealPointGroups { g0 } }
249    }
250    #[inline(always)]
251    pub fn group0(&self) -> Simd32x2 {
252        unsafe { self.groups.g0 }
253    }
254    #[inline(always)]
255    pub fn group0_mut(&mut self) -> &mut Simd32x2 {
256        unsafe { &mut self.groups.g0 }
257    }
258}
259
260const IDEALPOINT_INDEX_REMAP: [usize; 2] = [0, 1];
261
262impl std::ops::Index<usize> for IdealPoint {
263    type Output = f32;
264
265    fn index(&self, index: usize) -> &Self::Output {
266        unsafe { &self.elements[IDEALPOINT_INDEX_REMAP[index]] }
267    }
268}
269
270impl std::ops::IndexMut<usize> for IdealPoint {
271    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
272        unsafe { &mut self.elements[IDEALPOINT_INDEX_REMAP[index]] }
273    }
274}
275
276impl std::convert::From<IdealPoint> for [f32; 2] {
277    fn from(vector: IdealPoint) -> Self {
278        unsafe { [vector.elements[0], vector.elements[1]] }
279    }
280}
281
282impl std::convert::From<[f32; 2]> for IdealPoint {
283    fn from(array: [f32; 2]) -> Self {
284        Self { elements: [array[0], array[1], 0.0, 0.0] }
285    }
286}
287
288impl std::fmt::Debug for IdealPoint {
289    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
290        formatter
291            .debug_struct("IdealPoint")
292            .field("e01", &self[0])
293            .field("-e02", &self[1])
294            .finish()
295    }
296}
297
298#[derive(Clone, Copy)]
299struct PlaneGroups {
300    /// e0, e2, e1
301    g0: Simd32x3,
302}
303
304#[derive(Clone, Copy)]
305pub union Plane {
306    groups: PlaneGroups,
307    /// e0, e2, e1, 0
308    elements: [f32; 4],
309}
310
311impl Plane {
312    #[allow(clippy::too_many_arguments)]
313    pub const fn new(e0: f32, e2: f32, e1: f32) -> Self {
314        Self { elements: [e0, e2, e1, 0.0] }
315    }
316    pub const fn from_groups(g0: Simd32x3) -> Self {
317        Self { groups: PlaneGroups { g0 } }
318    }
319    #[inline(always)]
320    pub fn group0(&self) -> Simd32x3 {
321        unsafe { self.groups.g0 }
322    }
323    #[inline(always)]
324    pub fn group0_mut(&mut self) -> &mut Simd32x3 {
325        unsafe { &mut self.groups.g0 }
326    }
327}
328
329const PLANE_INDEX_REMAP: [usize; 3] = [0, 1, 2];
330
331impl std::ops::Index<usize> for Plane {
332    type Output = f32;
333
334    fn index(&self, index: usize) -> &Self::Output {
335        unsafe { &self.elements[PLANE_INDEX_REMAP[index]] }
336    }
337}
338
339impl std::ops::IndexMut<usize> for Plane {
340    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
341        unsafe { &mut self.elements[PLANE_INDEX_REMAP[index]] }
342    }
343}
344
345impl std::convert::From<Plane> for [f32; 3] {
346    fn from(vector: Plane) -> Self {
347        unsafe { [vector.elements[0], vector.elements[1], vector.elements[2]] }
348    }
349}
350
351impl std::convert::From<[f32; 3]> for Plane {
352    fn from(array: [f32; 3]) -> Self {
353        Self { elements: [array[0], array[1], array[2], 0.0] }
354    }
355}
356
357impl std::fmt::Debug for Plane {
358    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
359        formatter
360            .debug_struct("Plane")
361            .field("e0", &self[0])
362            .field("e2", &self[1])
363            .field("e1", &self[2])
364            .finish()
365    }
366}
367
368#[derive(Clone, Copy)]
369struct TranslatorGroups {
370    /// 1, e01, -e02
371    g0: Simd32x3,
372}
373
374#[derive(Clone, Copy)]
375pub union Translator {
376    groups: TranslatorGroups,
377    /// 1, e01, -e02, 0
378    elements: [f32; 4],
379}
380
381impl Translator {
382    #[allow(clippy::too_many_arguments)]
383    pub const fn new(scalar: f32, e01: f32, _e02: f32) -> Self {
384        Self { elements: [scalar, e01, _e02, 0.0] }
385    }
386    pub const fn from_groups(g0: Simd32x3) -> Self {
387        Self { groups: TranslatorGroups { g0 } }
388    }
389    #[inline(always)]
390    pub fn group0(&self) -> Simd32x3 {
391        unsafe { self.groups.g0 }
392    }
393    #[inline(always)]
394    pub fn group0_mut(&mut self) -> &mut Simd32x3 {
395        unsafe { &mut self.groups.g0 }
396    }
397}
398
399const TRANSLATOR_INDEX_REMAP: [usize; 3] = [0, 1, 2];
400
401impl std::ops::Index<usize> for Translator {
402    type Output = f32;
403
404    fn index(&self, index: usize) -> &Self::Output {
405        unsafe { &self.elements[TRANSLATOR_INDEX_REMAP[index]] }
406    }
407}
408
409impl std::ops::IndexMut<usize> for Translator {
410    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
411        unsafe { &mut self.elements[TRANSLATOR_INDEX_REMAP[index]] }
412    }
413}
414
415impl std::convert::From<Translator> for [f32; 3] {
416    fn from(vector: Translator) -> Self {
417        unsafe { [vector.elements[0], vector.elements[1], vector.elements[2]] }
418    }
419}
420
421impl std::convert::From<[f32; 3]> for Translator {
422    fn from(array: [f32; 3]) -> Self {
423        Self { elements: [array[0], array[1], array[2], 0.0] }
424    }
425}
426
427impl std::fmt::Debug for Translator {
428    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
429        formatter
430            .debug_struct("Translator")
431            .field("1", &self[0])
432            .field("e01", &self[1])
433            .field("-e02", &self[2])
434            .finish()
435    }
436}
437
438#[derive(Clone, Copy)]
439struct MotorGroups {
440    /// 1, e12, e01, -e02
441    g0: Simd32x4,
442}
443
444#[derive(Clone, Copy)]
445pub union Motor {
446    groups: MotorGroups,
447    /// 1, e12, e01, -e02
448    elements: [f32; 4],
449}
450
451impl Motor {
452    #[allow(clippy::too_many_arguments)]
453    pub const fn new(scalar: f32, e12: f32, e01: f32, _e02: f32) -> Self {
454        Self { elements: [scalar, e12, e01, _e02] }
455    }
456    pub const fn from_groups(g0: Simd32x4) -> Self {
457        Self { groups: MotorGroups { g0 } }
458    }
459    #[inline(always)]
460    pub fn group0(&self) -> Simd32x4 {
461        unsafe { self.groups.g0 }
462    }
463    #[inline(always)]
464    pub fn group0_mut(&mut self) -> &mut Simd32x4 {
465        unsafe { &mut self.groups.g0 }
466    }
467}
468
469const MOTOR_INDEX_REMAP: [usize; 4] = [0, 1, 2, 3];
470
471impl std::ops::Index<usize> for Motor {
472    type Output = f32;
473
474    fn index(&self, index: usize) -> &Self::Output {
475        unsafe { &self.elements[MOTOR_INDEX_REMAP[index]] }
476    }
477}
478
479impl std::ops::IndexMut<usize> for Motor {
480    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
481        unsafe { &mut self.elements[MOTOR_INDEX_REMAP[index]] }
482    }
483}
484
485impl std::convert::From<Motor> for [f32; 4] {
486    fn from(vector: Motor) -> Self {
487        unsafe { [vector.elements[0], vector.elements[1], vector.elements[2], vector.elements[3]] }
488    }
489}
490
491impl std::convert::From<[f32; 4]> for Motor {
492    fn from(array: [f32; 4]) -> Self {
493        Self { elements: [array[0], array[1], array[2], array[3]] }
494    }
495}
496
497impl std::fmt::Debug for Motor {
498    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
499        formatter
500            .debug_struct("Motor")
501            .field("1", &self[0])
502            .field("e12", &self[1])
503            .field("e01", &self[2])
504            .field("-e02", &self[3])
505            .finish()
506    }
507}
508
509#[derive(Clone, Copy)]
510struct MotorDualGroups {
511    /// e012, e0, e2, e1
512    g0: Simd32x4,
513}
514
515#[derive(Clone, Copy)]
516pub union MotorDual {
517    groups: MotorDualGroups,
518    /// e012, e0, e2, e1
519    elements: [f32; 4],
520}
521
522impl MotorDual {
523    #[allow(clippy::too_many_arguments)]
524    pub const fn new(e012: f32, e0: f32, e2: f32, e1: f32) -> Self {
525        Self { elements: [e012, e0, e2, e1] }
526    }
527    pub const fn from_groups(g0: Simd32x4) -> Self {
528        Self { groups: MotorDualGroups { g0 } }
529    }
530    #[inline(always)]
531    pub fn group0(&self) -> Simd32x4 {
532        unsafe { self.groups.g0 }
533    }
534    #[inline(always)]
535    pub fn group0_mut(&mut self) -> &mut Simd32x4 {
536        unsafe { &mut self.groups.g0 }
537    }
538}
539
540const MOTORDUAL_INDEX_REMAP: [usize; 4] = [0, 1, 2, 3];
541
542impl std::ops::Index<usize> for MotorDual {
543    type Output = f32;
544
545    fn index(&self, index: usize) -> &Self::Output {
546        unsafe { &self.elements[MOTORDUAL_INDEX_REMAP[index]] }
547    }
548}
549
550impl std::ops::IndexMut<usize> for MotorDual {
551    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
552        unsafe { &mut self.elements[MOTORDUAL_INDEX_REMAP[index]] }
553    }
554}
555
556impl std::convert::From<MotorDual> for [f32; 4] {
557    fn from(vector: MotorDual) -> Self {
558        unsafe { [vector.elements[0], vector.elements[1], vector.elements[2], vector.elements[3]] }
559    }
560}
561
562impl std::convert::From<[f32; 4]> for MotorDual {
563    fn from(array: [f32; 4]) -> Self {
564        Self { elements: [array[0], array[1], array[2], array[3]] }
565    }
566}
567
568impl std::fmt::Debug for MotorDual {
569    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
570        formatter
571            .debug_struct("MotorDual")
572            .field("e012", &self[0])
573            .field("e0", &self[1])
574            .field("e2", &self[2])
575            .field("e1", &self[3])
576            .finish()
577    }
578}
579
580impl Add<MultiVector> for f32 {
581    type Output = MultiVector;
582
583    fn add(self, other: MultiVector) -> MultiVector {
584        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + other.group0(), g1: other.group1() } }
585    }
586}
587
588impl Sub<MultiVector> for f32 {
589    type Output = MultiVector;
590
591    fn sub(self, other: MultiVector) -> MultiVector {
592        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) - other.group0(), g1: Simd32x4::from(0.0) - other.group1() } }
593    }
594}
595
596impl GeometricProduct<MultiVector> for f32 {
597    type Output = MultiVector;
598
599    fn geometric_product(self, other: MultiVector) -> MultiVector {
600        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self) * other.group0(), g1: Simd32x4::from(self) * other.group1() } }
601    }
602}
603
604impl RegressiveProduct<MultiVector> for f32 {
605    type Output = f32;
606
607    fn regressive_product(self, other: MultiVector) -> f32 {
608        self * other.group1()[1]
609    }
610}
611
612impl OuterProduct<MultiVector> for f32 {
613    type Output = MultiVector;
614
615    fn outer_product(self, other: MultiVector) -> MultiVector {
616        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self) * other.group0(), g1: Simd32x4::from(self) * other.group1() } }
617    }
618}
619
620impl InnerProduct<MultiVector> for f32 {
621    type Output = MultiVector;
622
623    fn inner_product(self, other: MultiVector) -> MultiVector {
624        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self) * other.group0(), g1: Simd32x4::from(self) * other.group1() } }
625    }
626}
627
628impl LeftContraction<MultiVector> for f32 {
629    type Output = MultiVector;
630
631    fn left_contraction(self, other: MultiVector) -> MultiVector {
632        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self) * other.group0(), g1: Simd32x4::from(self) * other.group1() } }
633    }
634}
635
636impl RightContraction<MultiVector> for f32 {
637    type Output = f32;
638
639    fn right_contraction(self, other: MultiVector) -> f32 {
640        self * other.group0()[0]
641    }
642}
643
644impl ScalarProduct<MultiVector> for f32 {
645    type Output = f32;
646
647    fn scalar_product(self, other: MultiVector) -> f32 {
648        self * other.group0()[0]
649    }
650}
651
652impl Add<Rotor> for f32 {
653    type Output = Rotor;
654
655    fn add(self, other: Rotor) -> Rotor {
656        Rotor { groups: RotorGroups { g0: Simd32x2::from(self) * Simd32x2::from([1.0, 0.0]) + other.group0() } }
657    }
658}
659
660impl Sub<Rotor> for f32 {
661    type Output = Rotor;
662
663    fn sub(self, other: Rotor) -> Rotor {
664        Rotor { groups: RotorGroups { g0: Simd32x2::from(self) * Simd32x2::from([1.0, 0.0]) - other.group0() } }
665    }
666}
667
668impl GeometricProduct<Rotor> for f32 {
669    type Output = Rotor;
670
671    fn geometric_product(self, other: Rotor) -> Rotor {
672        Rotor { groups: RotorGroups { g0: Simd32x2::from(self) * other.group0() } }
673    }
674}
675
676impl OuterProduct<Rotor> for f32 {
677    type Output = Rotor;
678
679    fn outer_product(self, other: Rotor) -> Rotor {
680        Rotor { groups: RotorGroups { g0: Simd32x2::from(self) * other.group0() } }
681    }
682}
683
684impl InnerProduct<Rotor> for f32 {
685    type Output = Rotor;
686
687    fn inner_product(self, other: Rotor) -> Rotor {
688        Rotor { groups: RotorGroups { g0: Simd32x2::from(self) * other.group0() } }
689    }
690}
691
692impl LeftContraction<Rotor> for f32 {
693    type Output = Rotor;
694
695    fn left_contraction(self, other: Rotor) -> Rotor {
696        Rotor { groups: RotorGroups { g0: Simd32x2::from(self) * other.group0() } }
697    }
698}
699
700impl RightContraction<Rotor> for f32 {
701    type Output = f32;
702
703    fn right_contraction(self, other: Rotor) -> f32 {
704        self * other.group0()[0]
705    }
706}
707
708impl ScalarProduct<Rotor> for f32 {
709    type Output = f32;
710
711    fn scalar_product(self, other: Rotor) -> f32 {
712        self * other.group0()[0]
713    }
714}
715
716impl Add<Point> for f32 {
717    type Output = Motor;
718
719    fn add(self, other: Point) -> Motor {
720        Motor { groups: MotorGroups { g0: Simd32x4::from(self) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
721    }
722}
723
724impl Sub<Point> for f32 {
725    type Output = Motor;
726
727    fn sub(self, other: Point) -> Motor {
728        Motor { groups: MotorGroups { g0: Simd32x4::from(self) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) - Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
729    }
730}
731
732impl GeometricProduct<Point> for f32 {
733    type Output = Point;
734
735    fn geometric_product(self, other: Point) -> Point {
736        Point { groups: PointGroups { g0: Simd32x3::from(self) * other.group0() } }
737    }
738}
739
740impl OuterProduct<Point> for f32 {
741    type Output = Point;
742
743    fn outer_product(self, other: Point) -> Point {
744        Point { groups: PointGroups { g0: Simd32x3::from(self) * other.group0() } }
745    }
746}
747
748impl InnerProduct<Point> for f32 {
749    type Output = Point;
750
751    fn inner_product(self, other: Point) -> Point {
752        Point { groups: PointGroups { g0: Simd32x3::from(self) * other.group0() } }
753    }
754}
755
756impl LeftContraction<Point> for f32 {
757    type Output = Point;
758
759    fn left_contraction(self, other: Point) -> Point {
760        Point { groups: PointGroups { g0: Simd32x3::from(self) * other.group0() } }
761    }
762}
763
764impl Add<IdealPoint> for f32 {
765    type Output = Translator;
766
767    fn add(self, other: IdealPoint) -> Translator {
768        Translator { groups: TranslatorGroups { g0: Simd32x3::from(self) * Simd32x3::from([1.0, 0.0, 0.0]) + Simd32x3::from([other.group0()[0], other.group0()[0], other.group0()[1]]) * Simd32x3::from([0.0, 1.0, 1.0]) } }
769    }
770}
771
772impl Sub<IdealPoint> for f32 {
773    type Output = Translator;
774
775    fn sub(self, other: IdealPoint) -> Translator {
776        Translator { groups: TranslatorGroups { g0: Simd32x3::from(self) * Simd32x3::from([1.0, 0.0, 0.0]) - Simd32x3::from([other.group0()[0], other.group0()[0], other.group0()[1]]) * Simd32x3::from([0.0, 1.0, 1.0]) } }
777    }
778}
779
780impl GeometricProduct<IdealPoint> for f32 {
781    type Output = IdealPoint;
782
783    fn geometric_product(self, other: IdealPoint) -> IdealPoint {
784        IdealPoint { groups: IdealPointGroups { g0: Simd32x2::from(self) * other.group0() } }
785    }
786}
787
788impl OuterProduct<IdealPoint> for f32 {
789    type Output = IdealPoint;
790
791    fn outer_product(self, other: IdealPoint) -> IdealPoint {
792        IdealPoint { groups: IdealPointGroups { g0: Simd32x2::from(self) * other.group0() } }
793    }
794}
795
796impl InnerProduct<IdealPoint> for f32 {
797    type Output = IdealPoint;
798
799    fn inner_product(self, other: IdealPoint) -> IdealPoint {
800        IdealPoint { groups: IdealPointGroups { g0: Simd32x2::from(self) * other.group0() } }
801    }
802}
803
804impl LeftContraction<IdealPoint> for f32 {
805    type Output = IdealPoint;
806
807    fn left_contraction(self, other: IdealPoint) -> IdealPoint {
808        IdealPoint { groups: IdealPointGroups { g0: Simd32x2::from(self) * other.group0() } }
809    }
810}
811
812impl GeometricProduct<Plane> for f32 {
813    type Output = Plane;
814
815    fn geometric_product(self, other: Plane) -> Plane {
816        Plane { groups: PlaneGroups { g0: Simd32x3::from(self) * other.group0() } }
817    }
818}
819
820impl OuterProduct<Plane> for f32 {
821    type Output = Plane;
822
823    fn outer_product(self, other: Plane) -> Plane {
824        Plane { groups: PlaneGroups { g0: Simd32x3::from(self) * other.group0() } }
825    }
826}
827
828impl InnerProduct<Plane> for f32 {
829    type Output = Plane;
830
831    fn inner_product(self, other: Plane) -> Plane {
832        Plane { groups: PlaneGroups { g0: Simd32x3::from(self) * other.group0() } }
833    }
834}
835
836impl LeftContraction<Plane> for f32 {
837    type Output = Plane;
838
839    fn left_contraction(self, other: Plane) -> Plane {
840        Plane { groups: PlaneGroups { g0: Simd32x3::from(self) * other.group0() } }
841    }
842}
843
844impl Add<Translator> for f32 {
845    type Output = Translator;
846
847    fn add(self, other: Translator) -> Translator {
848        Translator { groups: TranslatorGroups { g0: Simd32x3::from(self) * Simd32x3::from([1.0, 0.0, 0.0]) + other.group0() } }
849    }
850}
851
852impl Sub<Translator> for f32 {
853    type Output = Translator;
854
855    fn sub(self, other: Translator) -> Translator {
856        Translator { groups: TranslatorGroups { g0: Simd32x3::from(self) * Simd32x3::from([1.0, 0.0, 0.0]) - other.group0() } }
857    }
858}
859
860impl GeometricProduct<Translator> for f32 {
861    type Output = Translator;
862
863    fn geometric_product(self, other: Translator) -> Translator {
864        Translator { groups: TranslatorGroups { g0: Simd32x3::from(self) * other.group0() } }
865    }
866}
867
868impl OuterProduct<Translator> for f32 {
869    type Output = Translator;
870
871    fn outer_product(self, other: Translator) -> Translator {
872        Translator { groups: TranslatorGroups { g0: Simd32x3::from(self) * other.group0() } }
873    }
874}
875
876impl InnerProduct<Translator> for f32 {
877    type Output = Translator;
878
879    fn inner_product(self, other: Translator) -> Translator {
880        Translator { groups: TranslatorGroups { g0: Simd32x3::from(self) * other.group0() } }
881    }
882}
883
884impl LeftContraction<Translator> for f32 {
885    type Output = Translator;
886
887    fn left_contraction(self, other: Translator) -> Translator {
888        Translator { groups: TranslatorGroups { g0: Simd32x3::from(self) * other.group0() } }
889    }
890}
891
892impl RightContraction<Translator> for f32 {
893    type Output = f32;
894
895    fn right_contraction(self, other: Translator) -> f32 {
896        self * other.group0()[0]
897    }
898}
899
900impl ScalarProduct<Translator> for f32 {
901    type Output = f32;
902
903    fn scalar_product(self, other: Translator) -> f32 {
904        self * other.group0()[0]
905    }
906}
907
908impl Add<Motor> for f32 {
909    type Output = Motor;
910
911    fn add(self, other: Motor) -> Motor {
912        Motor { groups: MotorGroups { g0: Simd32x4::from(self) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + other.group0() } }
913    }
914}
915
916impl Sub<Motor> for f32 {
917    type Output = Motor;
918
919    fn sub(self, other: Motor) -> Motor {
920        Motor { groups: MotorGroups { g0: Simd32x4::from(self) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) - other.group0() } }
921    }
922}
923
924impl GeometricProduct<Motor> for f32 {
925    type Output = Motor;
926
927    fn geometric_product(self, other: Motor) -> Motor {
928        Motor { groups: MotorGroups { g0: Simd32x4::from(self) * other.group0() } }
929    }
930}
931
932impl OuterProduct<Motor> for f32 {
933    type Output = Motor;
934
935    fn outer_product(self, other: Motor) -> Motor {
936        Motor { groups: MotorGroups { g0: Simd32x4::from(self) * other.group0() } }
937    }
938}
939
940impl InnerProduct<Motor> for f32 {
941    type Output = Motor;
942
943    fn inner_product(self, other: Motor) -> Motor {
944        Motor { groups: MotorGroups { g0: Simd32x4::from(self) * other.group0() } }
945    }
946}
947
948impl LeftContraction<Motor> for f32 {
949    type Output = Motor;
950
951    fn left_contraction(self, other: Motor) -> Motor {
952        Motor { groups: MotorGroups { g0: Simd32x4::from(self) * other.group0() } }
953    }
954}
955
956impl RightContraction<Motor> for f32 {
957    type Output = f32;
958
959    fn right_contraction(self, other: Motor) -> f32 {
960        self * other.group0()[0]
961    }
962}
963
964impl ScalarProduct<Motor> for f32 {
965    type Output = f32;
966
967    fn scalar_product(self, other: Motor) -> f32 {
968        self * other.group0()[0]
969    }
970}
971
972impl GeometricProduct<MotorDual> for f32 {
973    type Output = MotorDual;
974
975    fn geometric_product(self, other: MotorDual) -> MotorDual {
976        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self) * other.group0() } }
977    }
978}
979
980impl RegressiveProduct<MotorDual> for f32 {
981    type Output = f32;
982
983    fn regressive_product(self, other: MotorDual) -> f32 {
984        self * other.group0()[0]
985    }
986}
987
988impl OuterProduct<MotorDual> for f32 {
989    type Output = MotorDual;
990
991    fn outer_product(self, other: MotorDual) -> MotorDual {
992        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self) * other.group0() } }
993    }
994}
995
996impl InnerProduct<MotorDual> for f32 {
997    type Output = MotorDual;
998
999    fn inner_product(self, other: MotorDual) -> MotorDual {
1000        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self) * other.group0() } }
1001    }
1002}
1003
1004impl LeftContraction<MotorDual> for f32 {
1005    type Output = MotorDual;
1006
1007    fn left_contraction(self, other: MotorDual) -> MotorDual {
1008        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self) * other.group0() } }
1009    }
1010}
1011
1012impl Zero for MultiVector {
1013    fn zero() -> Self {
1014        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(0.0), g1: Simd32x4::from(0.0) } }
1015    }
1016}
1017
1018impl One for MultiVector {
1019    fn one() -> Self {
1020        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from([1.0, 0.0, 0.0, 0.0]), g1: Simd32x4::from(0.0) } }
1021    }
1022}
1023
1024impl Neg for MultiVector {
1025    type Output = MultiVector;
1026
1027    fn neg(self) -> MultiVector {
1028        MultiVector { groups: MultiVectorGroups { g0: self.group0() * Simd32x4::from(-1.0), g1: self.group1() * Simd32x4::from(-1.0) } }
1029    }
1030}
1031
1032impl Automorphism for MultiVector {
1033    type Output = MultiVector;
1034
1035    fn automorphism(self) -> MultiVector {
1036        MultiVector { groups: MultiVectorGroups { g0: self.group0() * Simd32x4::from([1.0, 1.0, -1.0, -1.0]), g1: self.group1() * Simd32x4::from([-1.0, -1.0, 1.0, 1.0]) } }
1037    }
1038}
1039
1040impl Reversal for MultiVector {
1041    type Output = MultiVector;
1042
1043    fn reversal(self) -> MultiVector {
1044        MultiVector { groups: MultiVectorGroups { g0: self.group0() * Simd32x4::from([1.0, -1.0, 1.0, 1.0]), g1: self.group1() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) } }
1045    }
1046}
1047
1048impl Conjugation for MultiVector {
1049    type Output = MultiVector;
1050
1051    fn conjugation(self) -> MultiVector {
1052        MultiVector { groups: MultiVectorGroups { g0: self.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]), g1: self.group1() * Simd32x4::from([-1.0, 1.0, -1.0, -1.0]) } }
1053    }
1054}
1055
1056impl Dual for MultiVector {
1057    type Output = MultiVector;
1058
1059    fn dual(self) -> MultiVector {
1060        MultiVector { groups: MultiVectorGroups { g0: swizzle!(self.group1(), 1, 0, 3, 2), g1: swizzle!(self.group0(), 1, 0, 3, 2) } }
1061    }
1062}
1063
1064impl Into<f32> for MultiVector {
1065    fn into(self) -> f32 {
1066        self.group0()[0]
1067    }
1068}
1069
1070impl Add<f32> for MultiVector {
1071    type Output = MultiVector;
1072
1073    fn add(self, other: f32) -> MultiVector {
1074        MultiVector { groups: MultiVectorGroups { g0: self.group0() + Simd32x4::from(other) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]), g1: self.group1() } }
1075    }
1076}
1077
1078impl AddAssign<f32> for MultiVector {
1079    fn add_assign(&mut self, other: f32) {
1080        *self = (*self).add(other);
1081    }
1082}
1083
1084impl Sub<f32> for MultiVector {
1085    type Output = MultiVector;
1086
1087    fn sub(self, other: f32) -> MultiVector {
1088        MultiVector { groups: MultiVectorGroups { g0: self.group0() - Simd32x4::from(other) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]), g1: self.group1() } }
1089    }
1090}
1091
1092impl SubAssign<f32> for MultiVector {
1093    fn sub_assign(&mut self, other: f32) {
1094        *self = (*self).sub(other);
1095    }
1096}
1097
1098impl GeometricProduct<f32> for MultiVector {
1099    type Output = MultiVector;
1100
1101    fn geometric_product(self, other: f32) -> MultiVector {
1102        MultiVector { groups: MultiVectorGroups { g0: self.group0() * Simd32x4::from(other), g1: self.group1() * Simd32x4::from(other) } }
1103    }
1104}
1105
1106impl RegressiveProduct<f32> for MultiVector {
1107    type Output = f32;
1108
1109    fn regressive_product(self, other: f32) -> f32 {
1110        self.group1()[1] * other
1111    }
1112}
1113
1114impl OuterProduct<f32> for MultiVector {
1115    type Output = MultiVector;
1116
1117    fn outer_product(self, other: f32) -> MultiVector {
1118        MultiVector { groups: MultiVectorGroups { g0: self.group0() * Simd32x4::from(other), g1: self.group1() * Simd32x4::from(other) } }
1119    }
1120}
1121
1122impl InnerProduct<f32> for MultiVector {
1123    type Output = MultiVector;
1124
1125    fn inner_product(self, other: f32) -> MultiVector {
1126        MultiVector { groups: MultiVectorGroups { g0: self.group0() * Simd32x4::from(other), g1: self.group1() * Simd32x4::from(other) } }
1127    }
1128}
1129
1130impl LeftContraction<f32> for MultiVector {
1131    type Output = f32;
1132
1133    fn left_contraction(self, other: f32) -> f32 {
1134        self.group0()[0] * other
1135    }
1136}
1137
1138impl RightContraction<f32> for MultiVector {
1139    type Output = MultiVector;
1140
1141    fn right_contraction(self, other: f32) -> MultiVector {
1142        MultiVector { groups: MultiVectorGroups { g0: self.group0() * Simd32x4::from(other), g1: self.group1() * Simd32x4::from(other) } }
1143    }
1144}
1145
1146impl ScalarProduct<f32> for MultiVector {
1147    type Output = f32;
1148
1149    fn scalar_product(self, other: f32) -> f32 {
1150        self.group0()[0] * other
1151    }
1152}
1153
1154impl Add<MultiVector> for MultiVector {
1155    type Output = MultiVector;
1156
1157    fn add(self, other: MultiVector) -> MultiVector {
1158        MultiVector { groups: MultiVectorGroups { g0: self.group0() + other.group0(), g1: self.group1() + other.group1() } }
1159    }
1160}
1161
1162impl AddAssign<MultiVector> for MultiVector {
1163    fn add_assign(&mut self, other: MultiVector) {
1164        *self = (*self).add(other);
1165    }
1166}
1167
1168impl Sub<MultiVector> for MultiVector {
1169    type Output = MultiVector;
1170
1171    fn sub(self, other: MultiVector) -> MultiVector {
1172        MultiVector { groups: MultiVectorGroups { g0: self.group0() - other.group0(), g1: self.group1() - other.group1() } }
1173    }
1174}
1175
1176impl SubAssign<MultiVector> for MultiVector {
1177    fn sub_assign(&mut self, other: MultiVector) {
1178        *self = (*self).sub(other);
1179    }
1180}
1181
1182impl Mul<MultiVector> for MultiVector {
1183    type Output = MultiVector;
1184
1185    fn mul(self, other: MultiVector) -> MultiVector {
1186        MultiVector { groups: MultiVectorGroups { g0: self.group0() * other.group0(), g1: self.group1() * other.group1() } }
1187    }
1188}
1189
1190impl MulAssign<MultiVector> for MultiVector {
1191    fn mul_assign(&mut self, other: MultiVector) {
1192        *self = (*self).mul(other);
1193    }
1194}
1195
1196impl Div<MultiVector> for MultiVector {
1197    type Output = MultiVector;
1198
1199    fn div(self, other: MultiVector) -> MultiVector {
1200        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[1], self.group0()[2], self.group0()[3]]) * Simd32x4::from([1.0, 1.0, 1.0, 1.0]) / Simd32x4::from([other.group0()[0], other.group0()[1], other.group0()[2], other.group0()[3]]) * Simd32x4::from([1.0, 1.0, 1.0, 1.0]), g1: Simd32x4::from([self.group1()[0], self.group1()[1], self.group1()[2], self.group1()[3]]) * Simd32x4::from([1.0, 1.0, 1.0, 1.0]) / Simd32x4::from([other.group1()[0], other.group1()[1], other.group1()[2], other.group1()[3]]) * Simd32x4::from([1.0, 1.0, 1.0, 1.0]) } }
1201    }
1202}
1203
1204impl DivAssign<MultiVector> for MultiVector {
1205    fn div_assign(&mut self, other: MultiVector) {
1206        *self = (*self).div(other);
1207    }
1208}
1209
1210impl GeometricProduct<MultiVector> for MultiVector {
1211    type Output = MultiVector;
1212
1213    fn geometric_product(self, other: MultiVector) -> MultiVector {
1214        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 3, 0, 1) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([1.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group1()[0]) * other.group1() * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[1]) * swizzle!(other.group1(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, -1.0, -1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group1(), 2, 3, 0, 1) * Simd32x4::from([-1.0, 1.0, -1.0, -1.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group1(), 3, 2, 1, 0) * Simd32x4::from([-1.0, -1.0, -1.0, 1.0]), g1: Simd32x4::from(self.group0()[0]) * other.group1() + Simd32x4::from(self.group0()[1]) * swizzle!(other.group1(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group1(), 2, 3, 0, 1) * Simd32x4::from([-1.0, 1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group1(), 3, 2, 1, 0) + Simd32x4::from(self.group1()[0]) * other.group0() * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[1]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group0(), 2, 3, 0, 1) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) } }
1215    }
1216}
1217
1218impl RegressiveProduct<MultiVector> for MultiVector {
1219    type Output = MultiVector;
1220
1221    fn regressive_product(self, other: MultiVector) -> MultiVector {
1222        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[1]) * other.group1() * Simd32x4::from([1.0, 1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group1(), 3, 3, 1, 3) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group1(), 2, 2, 2, 1) * Simd32x4::from([1.0, 0.0, 0.0, 1.0]) + Simd32x4::from(self.group1()[0]) * Simd32x4::from(other.group0()[1]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[1]) * other.group0() + Simd32x4::from(self.group1()[2]) * swizzle!(other.group0(), 3, 3, 1, 3) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group0(), 2, 2, 2, 1) * Simd32x4::from([1.0, 0.0, 0.0, -1.0]) + Simd32x4::from(self.group0()[0]) * swizzle!(other.group1(), 1, 0, 0, 0) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]), g1: Simd32x4::from(self.group1()[1]) * other.group1() + Simd32x4::from(self.group1()[2]) * swizzle!(other.group1(), 3, 3, 1, 3) * Simd32x4::from([-1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group1(), 2, 2, 2, 1) * Simd32x4::from([1.0, 0.0, 0.0, 1.0]) + Simd32x4::from(self.group1()[0]) * swizzle!(other.group1(), 1, 0, 0, 0) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
1223    }
1224}
1225
1226impl OuterProduct<MultiVector> for MultiVector {
1227    type Output = MultiVector;
1228
1229    fn outer_product(self, other: MultiVector) -> MultiVector {
1230        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 3, 3, 0, 3) * Simd32x4::from([0.0, 1.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 2, 2, 2, 0) * Simd32x4::from([0.0, -1.0, 0.0, 1.0]) + swizzle!(self.group0(), 0, 1, 0, 0) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 0.0, 0.0]), g1: Simd32x4::from(self.group0()[0]) * other.group1() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group1(), 3, 3, 0, 3) * Simd32x4::from([0.0, 1.0, -1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group1(), 2, 2, 2, 0) * Simd32x4::from([0.0, 1.0, 0.0, 1.0]) + Simd32x4::from(self.group1()[0]) * other.group0() * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[1]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group0(), 3, 3, 0, 3) * Simd32x4::from([0.0, 1.0, 1.0, 0.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group0(), 2, 2, 2, 0) * Simd32x4::from([0.0, 1.0, 0.0, 1.0]) + swizzle!(self.group0(), 0, 1, 0, 0) * Simd32x4::from(other.group1()[0]) * Simd32x4::from([0.0, 1.0, 0.0, 0.0]) } }
1231    }
1232}
1233
1234impl InnerProduct<MultiVector> for MultiVector {
1235    type Output = MultiVector;
1236
1237    fn inner_product(self, other: MultiVector) -> MultiVector {
1238        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 3, 1, 0) * Simd32x4::from([1.0, 0.0, -1.0, 1.0]) + Simd32x4::from(self.group1()[0]) * other.group1() * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[1]) * swizzle!(other.group1(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, -1.0, -1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group1(), 2, 2, 0, 1) * Simd32x4::from([-1.0, 0.0, -1.0, -1.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group1(), 3, 3, 1, 0) * Simd32x4::from([-1.0, 0.0, -1.0, 1.0]) + swizzle!(self.group0(), 2, 0, 2, 2) * swizzle!(other.group0(), 2, 0, 0, 1) * Simd32x4::from([1.0, 0.0, 1.0, 1.0]), g1: Simd32x4::from(self.group0()[0]) * other.group1() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group1(), 2, 2, 2, 1) * Simd32x4::from([-1.0, 0.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group1(), 3, 3, 1, 3) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group1()[0]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[1]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 1.0]) + swizzle!(self.group0(), 1, 0, 0, 0) * swizzle!(other.group1(), 1, 0, 0, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) } }
1239    }
1240}
1241
1242impl LeftContraction<MultiVector> for MultiVector {
1243    type Output = MultiVector;
1244
1245    fn left_contraction(self, other: MultiVector) -> MultiVector {
1246        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 2, 1) * Simd32x4::from([1.0, 0.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 3, 1, 3) * Simd32x4::from([1.0, 0.0, -1.0, 0.0]) + Simd32x4::from(self.group1()[0]) * other.group1() * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[1]) * Simd32x4::from(other.group1()[1]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group1(), 2, 2, 2, 1) * Simd32x4::from([-1.0, 0.0, 0.0, -1.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group1(), 3, 3, 1, 3) * Simd32x4::from([-1.0, 0.0, -1.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0, 0) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]), g1: Simd32x4::from(self.group0()[0]) * other.group1() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group1(), 2, 2, 2, 1) * Simd32x4::from([-1.0, 0.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group1(), 3, 3, 1, 3) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0, 0) * swizzle!(other.group1(), 1, 0, 0, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) } }
1247    }
1248}
1249
1250impl RightContraction<MultiVector> for MultiVector {
1251    type Output = MultiVector;
1252
1253    fn right_contraction(self, other: MultiVector) -> MultiVector {
1254        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, 1.0]) + Simd32x4::from(self.group1()[0]) * Simd32x4::from(other.group1()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[1]) * swizzle!(other.group1(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, -1.0, -1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group1(), 2, 2, 0, 2) * Simd32x4::from([-1.0, 0.0, -1.0, 0.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group1(), 3, 3, 3, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]), g1: Simd32x4::from(self.group1()[1]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 1.0]) + Simd32x4::from(self.group1()[0]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
1255    }
1256}
1257
1258impl ScalarProduct<MultiVector> for MultiVector {
1259    type Output = f32;
1260
1261    fn scalar_product(self, other: MultiVector) -> f32 {
1262        self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group0()[1] + self.group0()[2] * other.group0()[2] + self.group0()[3] * other.group0()[3] + self.group1()[0] * other.group1()[0] - self.group1()[1] * other.group1()[1] - self.group1()[2] * other.group1()[2] - self.group1()[3] * other.group1()[3]
1263    }
1264}
1265
1266impl Into<Rotor> for MultiVector {
1267    fn into(self) -> Rotor {
1268        Rotor { groups: RotorGroups { g0: Simd32x2::from([self.group0()[0], self.group0()[1]]) } }
1269    }
1270}
1271
1272impl Add<Rotor> for MultiVector {
1273    type Output = MultiVector;
1274
1275    fn add(self, other: Rotor) -> MultiVector {
1276        MultiVector { groups: MultiVectorGroups { g0: self.group0() + Simd32x4::from([other.group0()[0], other.group0()[1], other.group0()[0], other.group0()[0]]) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]), g1: self.group1() } }
1277    }
1278}
1279
1280impl AddAssign<Rotor> for MultiVector {
1281    fn add_assign(&mut self, other: Rotor) {
1282        *self = (*self).add(other);
1283    }
1284}
1285
1286impl Sub<Rotor> for MultiVector {
1287    type Output = MultiVector;
1288
1289    fn sub(self, other: Rotor) -> MultiVector {
1290        MultiVector { groups: MultiVectorGroups { g0: self.group0() - Simd32x4::from([other.group0()[0], other.group0()[1], other.group0()[0], other.group0()[0]]) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]), g1: self.group1() } }
1291    }
1292}
1293
1294impl SubAssign<Rotor> for MultiVector {
1295    fn sub_assign(&mut self, other: Rotor) {
1296        *self = (*self).sub(other);
1297    }
1298}
1299
1300impl GeometricProduct<Rotor> for MultiVector {
1301    type Output = MultiVector;
1302
1303    fn geometric_product(self, other: Rotor) -> MultiVector {
1304        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[1], other.group0()[0], other.group0()[1], other.group0()[1]]) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[1], other.group0()[1], other.group0()[1], other.group0()[0]]) * Simd32x4::from([0.0, 0.0, -1.0, 1.0]) + swizzle!(self.group0(), 0, 0, 2, 2) * Simd32x4::from([other.group0()[0], other.group0()[1], other.group0()[0], other.group0()[1]]), g1: Simd32x4::from(self.group1()[1]) * Simd32x4::from([other.group0()[1], other.group0()[0], other.group0()[1], other.group0()[1]]) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from([other.group0()[1], other.group0()[1], other.group0()[1], other.group0()[0]]) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) + swizzle!(self.group1(), 0, 0, 2, 2) * Simd32x4::from([other.group0()[0], other.group0()[1], other.group0()[0], other.group0()[1]]) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) } }
1305    }
1306}
1307
1308impl OuterProduct<Rotor> for MultiVector {
1309    type Output = MultiVector;
1310
1311    fn outer_product(self, other: Rotor) -> MultiVector {
1312        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 0.0, 0.0]) + swizzle!(self.group0(), 0, 0, 2, 3) * Simd32x4::from([other.group0()[0], other.group0()[1], other.group0()[0], other.group0()[0]]), g1: Simd32x4::from(self.group1()[1]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 0.0, 0.0]) + swizzle!(self.group1(), 0, 0, 2, 3) * Simd32x4::from([other.group0()[0], other.group0()[1], other.group0()[0], other.group0()[0]]) } }
1313    }
1314}
1315
1316impl InnerProduct<Rotor> for MultiVector {
1317    type Output = MultiVector;
1318
1319    fn inner_product(self, other: Rotor) -> MultiVector {
1320        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[1], other.group0()[0], other.group0()[1], other.group0()[1]]) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[1], other.group0()[1], other.group0()[1], other.group0()[0]]) * Simd32x4::from([0.0, 0.0, -1.0, 1.0]) + swizzle!(self.group0(), 0, 0, 2, 2) * Simd32x4::from([other.group0()[0], other.group0()[1], other.group0()[0], other.group0()[1]]), g1: Simd32x4::from(self.group1()[1]) * Simd32x4::from([other.group0()[1], other.group0()[0], other.group0()[1], other.group0()[1]]) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]) + swizzle!(self.group1(), 0, 0, 2, 3) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 1.0, 1.0]) } }
1321    }
1322}
1323
1324impl RightContraction<Rotor> for MultiVector {
1325    type Output = MultiVector;
1326
1327    fn right_contraction(self, other: Rotor) -> MultiVector {
1328        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[1], other.group0()[0], other.group0()[1], other.group0()[1]]) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]) + swizzle!(self.group0(), 0, 0, 2, 3) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 1.0, 1.0]), g1: Simd32x4::from(self.group1()[1]) * Simd32x4::from([other.group0()[1], other.group0()[0], other.group0()[1], other.group0()[1]]) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]) + swizzle!(self.group1(), 0, 0, 2, 3) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 1.0, 1.0]) } }
1329    }
1330}
1331
1332impl ScalarProduct<Rotor> for MultiVector {
1333    type Output = f32;
1334
1335    fn scalar_product(self, other: Rotor) -> f32 {
1336        self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group0()[1]
1337    }
1338}
1339
1340impl Into<Point> for MultiVector {
1341    fn into(self) -> Point {
1342        Point { groups: PointGroups { g0: Simd32x3::from([self.group0()[1], self.group1()[2], self.group1()[3]]) } }
1343    }
1344}
1345
1346impl Add<Point> for MultiVector {
1347    type Output = MultiVector;
1348
1349    fn add(self, other: Point) -> MultiVector {
1350        MultiVector { groups: MultiVectorGroups { g0: self.group0() + Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 0.0, 0.0]), g1: self.group1() + Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) } }
1351    }
1352}
1353
1354impl AddAssign<Point> for MultiVector {
1355    fn add_assign(&mut self, other: Point) {
1356        *self = (*self).add(other);
1357    }
1358}
1359
1360impl Sub<Point> for MultiVector {
1361    type Output = MultiVector;
1362
1363    fn sub(self, other: Point) -> MultiVector {
1364        MultiVector { groups: MultiVectorGroups { g0: self.group0() - Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 0.0, 0.0]), g1: self.group1() - Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) } }
1365    }
1366}
1367
1368impl SubAssign<Point> for MultiVector {
1369    fn sub_assign(&mut self, other: Point) {
1370        *self = (*self).sub(other);
1371    }
1372}
1373
1374impl GeometricProduct<Point> for MultiVector {
1375    type Output = MultiVector;
1376
1377    fn geometric_product(self, other: Point) -> MultiVector {
1378        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group1()[0]) * Simd32x4::from([other.group0()[1], other.group0()[1], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[1]) * Simd32x4::from([other.group0()[2], other.group0()[2], other.group0()[2], other.group0()[1]]) * Simd32x4::from([0.0, 0.0, -1.0, -1.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from([other.group0()[1], other.group0()[2], other.group0()[1], other.group0()[1]]) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from([other.group0()[2], other.group0()[1], other.group0()[2], other.group0()[2]]) * Simd32x4::from([-1.0, -1.0, 0.0, 0.0]) + swizzle!(self.group0(), 1, 0, 3, 2) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([-1.0, 1.0, -1.0, 1.0]), g1: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[2], other.group0()[2], other.group0()[2], other.group0()[1]]) * Simd32x4::from([0.0, 0.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[2], other.group0()[1], other.group0()[2], other.group0()[2]]) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[0]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[1]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, 0.0, -1.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, 1.0, 0.0]) + swizzle!(self.group0(), 2, 2, 0, 0) * Simd32x4::from([other.group0()[1], other.group0()[2], other.group0()[1], other.group0()[2]]) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) } }
1379    }
1380}
1381
1382impl ScalarProduct<Point> for MultiVector {
1383    type Output = f32;
1384
1385    fn scalar_product(self, other: Point) -> f32 {
1386        0.0 - self.group0()[1] * other.group0()[0] - self.group1()[2] * other.group0()[1] - self.group1()[3] * other.group0()[2]
1387    }
1388}
1389
1390impl Into<IdealPoint> for MultiVector {
1391    fn into(self) -> IdealPoint {
1392        IdealPoint { groups: IdealPointGroups { g0: Simd32x2::from([self.group1()[2], self.group1()[3]]) } }
1393    }
1394}
1395
1396impl Add<IdealPoint> for MultiVector {
1397    type Output = MultiVector;
1398
1399    fn add(self, other: IdealPoint) -> MultiVector {
1400        MultiVector { groups: MultiVectorGroups { g0: self.group0(), g1: self.group1() + Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[0], other.group0()[1]]) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) } }
1401    }
1402}
1403
1404impl AddAssign<IdealPoint> for MultiVector {
1405    fn add_assign(&mut self, other: IdealPoint) {
1406        *self = (*self).add(other);
1407    }
1408}
1409
1410impl Sub<IdealPoint> for MultiVector {
1411    type Output = MultiVector;
1412
1413    fn sub(self, other: IdealPoint) -> MultiVector {
1414        MultiVector { groups: MultiVectorGroups { g0: self.group0(), g1: self.group1() - Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[0], other.group0()[1]]) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) } }
1415    }
1416}
1417
1418impl SubAssign<IdealPoint> for MultiVector {
1419    fn sub_assign(&mut self, other: IdealPoint) {
1420        *self = (*self).sub(other);
1421    }
1422}
1423
1424impl GeometricProduct<IdealPoint> for MultiVector {
1425    type Output = MultiVector;
1426
1427    fn geometric_product(self, other: IdealPoint) -> MultiVector {
1428        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group1()[1]) * Simd32x4::from([other.group0()[1], other.group0()[1], other.group0()[1], other.group0()[0]]) * Simd32x4::from([0.0, 0.0, -1.0, -1.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from([other.group0()[1], other.group0()[0], other.group0()[1], other.group0()[1]]) * Simd32x4::from([-1.0, -1.0, 0.0, 0.0]) + swizzle!(self.group1(), 2, 2, 0, 0) * Simd32x4::from([other.group0()[0], other.group0()[1], other.group0()[0], other.group0()[1]]) * Simd32x4::from([-1.0, 1.0, 1.0, -1.0]), g1: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[1], other.group0()[1], other.group0()[1], other.group0()[0]]) * Simd32x4::from([0.0, 0.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[1], other.group0()[0], other.group0()[1], other.group0()[1]]) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + swizzle!(self.group0(), 2, 2, 0, 0) * Simd32x4::from([other.group0()[0], other.group0()[1], other.group0()[0], other.group0()[1]]) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) } }
1429    }
1430}
1431
1432impl ScalarProduct<IdealPoint> for MultiVector {
1433    type Output = f32;
1434
1435    fn scalar_product(self, other: IdealPoint) -> f32 {
1436        0.0 - self.group1()[2] * other.group0()[0] - self.group1()[3] * other.group0()[1]
1437    }
1438}
1439
1440impl Into<Plane> for MultiVector {
1441    fn into(self) -> Plane {
1442        Plane { groups: PlaneGroups { g0: Simd32x3::from([self.group1()[0], self.group0()[3], self.group0()[2]]) } }
1443    }
1444}
1445
1446impl Add<Plane> for MultiVector {
1447    type Output = MultiVector;
1448
1449    fn add(self, other: Plane) -> MultiVector {
1450        MultiVector { groups: MultiVectorGroups { g0: self.group0() + Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[2], other.group0()[1]]) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]), g1: self.group1() + Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
1451    }
1452}
1453
1454impl AddAssign<Plane> for MultiVector {
1455    fn add_assign(&mut self, other: Plane) {
1456        *self = (*self).add(other);
1457    }
1458}
1459
1460impl Sub<Plane> for MultiVector {
1461    type Output = MultiVector;
1462
1463    fn sub(self, other: Plane) -> MultiVector {
1464        MultiVector { groups: MultiVectorGroups { g0: self.group0() - Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[2], other.group0()[1]]) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]), g1: self.group1() - Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
1465    }
1466}
1467
1468impl SubAssign<Plane> for MultiVector {
1469    fn sub_assign(&mut self, other: Plane) {
1470        *self = (*self).sub(other);
1471    }
1472}
1473
1474impl GeometricProduct<Plane> for MultiVector {
1475    type Output = MultiVector;
1476
1477    fn geometric_product(self, other: Plane) -> MultiVector {
1478        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[1], other.group0()[1], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[1], other.group0()[2], other.group0()[1], other.group0()[1]]) * Simd32x4::from([1.0, -1.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[0]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[1]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, -1.0, 0.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, 0.0, 1.0]) + swizzle!(self.group0(), 2, 2, 0, 0) * Simd32x4::from([other.group0()[2], other.group0()[1], other.group0()[2], other.group0()[1]]), g1: Simd32x4::from(self.group1()[0]) * Simd32x4::from([other.group0()[2], other.group0()[2], other.group0()[2], other.group0()[1]]) * Simd32x4::from([0.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[1]) * Simd32x4::from([other.group0()[1], other.group0()[1], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from([other.group0()[2], other.group0()[1], other.group0()[2], other.group0()[2]]) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from([other.group0()[1], other.group0()[2], other.group0()[1], other.group0()[1]]) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]) + self.group0() * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 1.0, -1.0, 1.0]) } }
1479    }
1480}
1481
1482impl ScalarProduct<Plane> for MultiVector {
1483    type Output = f32;
1484
1485    fn scalar_product(self, other: Plane) -> f32 {
1486        self.group0()[2] * other.group0()[2] + self.group0()[3] * other.group0()[1] + self.group1()[0] * other.group0()[0]
1487    }
1488}
1489
1490impl Into<Translator> for MultiVector {
1491    fn into(self) -> Translator {
1492        Translator { groups: TranslatorGroups { g0: Simd32x3::from([self.group0()[0], self.group1()[2], self.group1()[3]]) } }
1493    }
1494}
1495
1496impl Add<Translator> for MultiVector {
1497    type Output = MultiVector;
1498
1499    fn add(self, other: Translator) -> MultiVector {
1500        MultiVector { groups: MultiVectorGroups { g0: self.group0() + Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]), g1: self.group1() + Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) } }
1501    }
1502}
1503
1504impl AddAssign<Translator> for MultiVector {
1505    fn add_assign(&mut self, other: Translator) {
1506        *self = (*self).add(other);
1507    }
1508}
1509
1510impl Sub<Translator> for MultiVector {
1511    type Output = MultiVector;
1512
1513    fn sub(self, other: Translator) -> MultiVector {
1514        MultiVector { groups: MultiVectorGroups { g0: self.group0() - Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]), g1: self.group1() - Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) } }
1515    }
1516}
1517
1518impl SubAssign<Translator> for MultiVector {
1519    fn sub_assign(&mut self, other: Translator) {
1520        *self = (*self).sub(other);
1521    }
1522}
1523
1524impl GeometricProduct<Translator> for MultiVector {
1525    type Output = MultiVector;
1526
1527    fn geometric_product(self, other: Translator) -> MultiVector {
1528        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group1()[0]) * Simd32x4::from([other.group0()[1], other.group0()[1], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[1]) * Simd32x4::from([other.group0()[2], other.group0()[2], other.group0()[2], other.group0()[1]]) * Simd32x4::from([0.0, 0.0, -1.0, -1.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from([other.group0()[1], other.group0()[2], other.group0()[1], other.group0()[1]]) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from([other.group0()[2], other.group0()[1], other.group0()[2], other.group0()[2]]) * Simd32x4::from([-1.0, -1.0, 0.0, 0.0]) + self.group0() * Simd32x4::from(other.group0()[0]), g1: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[2], other.group0()[2], other.group0()[2], other.group0()[1]]) * Simd32x4::from([0.0, 0.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[2], other.group0()[1], other.group0()[2], other.group0()[2]]) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[0]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[1]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, 0.0, 1.0]) + swizzle!(self.group0(), 2, 2, 0, 0) * Simd32x4::from([other.group0()[1], other.group0()[2], other.group0()[1], other.group0()[2]]) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) } }
1529    }
1530}
1531
1532impl OuterProduct<Translator> for MultiVector {
1533    type Output = MultiVector;
1534
1535    fn outer_product(self, other: Translator) -> MultiVector {
1536        MultiVector { groups: MultiVectorGroups { g0: self.group0() * Simd32x4::from(other.group0()[0]), g1: Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group0()[1]) * Simd32x4::from([0.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[1]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, 0.0, 1.0]) + Simd32x4::from([self.group1()[0], self.group0()[2], self.group0()[0], self.group0()[0]]) * Simd32x4::from([other.group0()[0], other.group0()[2], other.group0()[1], other.group0()[2]]) } }
1537    }
1538}
1539
1540impl InnerProduct<Translator> for MultiVector {
1541    type Output = MultiVector;
1542
1543    fn inner_product(self, other: Translator) -> MultiVector {
1544        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group1()[0]) * Simd32x4::from([other.group0()[1], other.group0()[1], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[1]) * Simd32x4::from([other.group0()[2], other.group0()[2], other.group0()[2], other.group0()[1]]) * Simd32x4::from([0.0, 0.0, -1.0, -1.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from(other.group0()[1]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from(other.group0()[2]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + self.group0() * Simd32x4::from(other.group0()[0]), g1: Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group0()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[0]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, 0.0, 1.0]) + Simd32x4::from([self.group0()[2], self.group1()[1], self.group0()[0], self.group0()[0]]) * Simd32x4::from([other.group0()[1], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) } }
1545    }
1546}
1547
1548impl RightContraction<Translator> for MultiVector {
1549    type Output = MultiVector;
1550
1551    fn right_contraction(self, other: Translator) -> MultiVector {
1552        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group1()[1]) * Simd32x4::from([other.group0()[2], other.group0()[2], other.group0()[2], other.group0()[1]]) * Simd32x4::from([0.0, 0.0, -1.0, -1.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from(other.group0()[1]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from(other.group0()[2]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + self.group0() * Simd32x4::from(other.group0()[0]), g1: self.group1() * Simd32x4::from(other.group0()[0]) } }
1553    }
1554}
1555
1556impl ScalarProduct<Translator> for MultiVector {
1557    type Output = f32;
1558
1559    fn scalar_product(self, other: Translator) -> f32 {
1560        self.group0()[0] * other.group0()[0] - self.group1()[2] * other.group0()[1] - self.group1()[3] * other.group0()[2]
1561    }
1562}
1563
1564impl Into<Motor> for MultiVector {
1565    fn into(self) -> Motor {
1566        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[1], self.group1()[2], self.group1()[3]]) } }
1567    }
1568}
1569
1570impl Add<Motor> for MultiVector {
1571    type Output = MultiVector;
1572
1573    fn add(self, other: Motor) -> MultiVector {
1574        MultiVector { groups: MultiVectorGroups { g0: self.group0() + swizzle!(other.group0(), 0, 1, 0, 0) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]), g1: self.group1() + swizzle!(other.group0(), 0, 0, 2, 3) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) } }
1575    }
1576}
1577
1578impl AddAssign<Motor> for MultiVector {
1579    fn add_assign(&mut self, other: Motor) {
1580        *self = (*self).add(other);
1581    }
1582}
1583
1584impl Sub<Motor> for MultiVector {
1585    type Output = MultiVector;
1586
1587    fn sub(self, other: Motor) -> MultiVector {
1588        MultiVector { groups: MultiVectorGroups { g0: self.group0() - swizzle!(other.group0(), 0, 1, 0, 0) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]), g1: self.group1() - swizzle!(other.group0(), 0, 0, 2, 3) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) } }
1589    }
1590}
1591
1592impl SubAssign<Motor> for MultiVector {
1593    fn sub_assign(&mut self, other: Motor) {
1594        *self = (*self).sub(other);
1595    }
1596}
1597
1598impl GeometricProduct<Motor> for MultiVector {
1599    type Output = MultiVector;
1600
1601    fn geometric_product(self, other: Motor) -> MultiVector {
1602        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0, 1, 1) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 1, 1, 1, 0) * Simd32x4::from([0.0, 0.0, -1.0, 1.0]) + Simd32x4::from(self.group1()[0]) * swizzle!(other.group0(), 2, 2, 2, 3) * Simd32x4::from([0.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[1]) * swizzle!(other.group0(), 3, 3, 3, 2) * Simd32x4::from([0.0, 0.0, -1.0, -1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group0(), 2, 3, 2, 2) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group0(), 3, 2, 3, 3) * Simd32x4::from([-1.0, -1.0, 0.0, 0.0]) + swizzle!(self.group0(), 0, 0, 2, 2) * swizzle!(other.group0(), 0, 1, 0, 1), g1: Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 3, 3, 3, 2) * Simd32x4::from([0.0, 0.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 2, 3, 3) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[0]) * swizzle!(other.group0(), 0, 1, 0, 0) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[1]) * swizzle!(other.group0(), 1, 0, 1, 1) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group0(), 0, 0, 0, 1) * Simd32x4::from([0.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group0(), 1, 1, 1, 0) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) + swizzle!(self.group0(), 2, 2, 0, 0) * swizzle!(other.group0(), 2, 3, 2, 3) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) } }
1603    }
1604}
1605
1606impl OuterProduct<Motor> for MultiVector {
1607    type Output = MultiVector;
1608
1609    fn outer_product(self, other: Motor) -> MultiVector {
1610        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 0.0, 0.0]) + swizzle!(self.group0(), 0, 0, 2, 3) * swizzle!(other.group0(), 0, 1, 0, 0), g1: Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group0()[2]) * Simd32x4::from([0.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[0]) * swizzle!(other.group0(), 0, 1, 0, 0) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[1]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, 0.0, 1.0]) + swizzle!(self.group0(), 0, 2, 0, 0) * swizzle!(other.group0(), 0, 3, 2, 3) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
1611    }
1612}
1613
1614impl InnerProduct<Motor> for MultiVector {
1615    type Output = MultiVector;
1616
1617    fn inner_product(self, other: Motor) -> MultiVector {
1618        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0, 1, 1) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 1, 1, 1, 0) * Simd32x4::from([0.0, 0.0, -1.0, 1.0]) + Simd32x4::from(self.group1()[0]) * swizzle!(other.group0(), 2, 2, 2, 3) * Simd32x4::from([0.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[1]) * swizzle!(other.group0(), 3, 3, 3, 2) * Simd32x4::from([0.0, 0.0, -1.0, -1.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from(other.group0()[2]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from(other.group0()[3]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + swizzle!(self.group0(), 0, 0, 2, 2) * swizzle!(other.group0(), 0, 1, 0, 1), g1: Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group0()[3]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[0]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[1]) * swizzle!(other.group0(), 1, 0, 1, 1) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, 0.0, 1.0]) + swizzle!(self.group0(), 2, 0, 0, 0) * swizzle!(other.group0(), 2, 0, 2, 3) * Simd32x4::from([-1.0, 0.0, 1.0, 1.0]) } }
1619    }
1620}
1621
1622impl RightContraction<Motor> for MultiVector {
1623    type Output = MultiVector;
1624
1625    fn right_contraction(self, other: Motor) -> MultiVector {
1626        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0, 1, 1) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[1]) * swizzle!(other.group0(), 3, 3, 3, 2) * Simd32x4::from([0.0, 0.0, -1.0, -1.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from(other.group0()[2]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from(other.group0()[3]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + swizzle!(self.group0(), 0, 0, 2, 3) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 1.0, 1.0]), g1: Simd32x4::from(self.group1()[1]) * swizzle!(other.group0(), 1, 0, 1, 1) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]) + swizzle!(self.group1(), 0, 0, 2, 3) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 1.0, 1.0]) } }
1627    }
1628}
1629
1630impl ScalarProduct<Motor> for MultiVector {
1631    type Output = f32;
1632
1633    fn scalar_product(self, other: Motor) -> f32 {
1634        self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group0()[1] - self.group1()[2] * other.group0()[2] - self.group1()[3] * other.group0()[3]
1635    }
1636}
1637
1638impl Into<MotorDual> for MultiVector {
1639    fn into(self) -> MotorDual {
1640        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from([self.group1()[1], self.group1()[0], self.group0()[3], self.group0()[2]]) } }
1641    }
1642}
1643
1644impl Add<MotorDual> for MultiVector {
1645    type Output = MultiVector;
1646
1647    fn add(self, other: MotorDual) -> MultiVector {
1648        MultiVector { groups: MultiVectorGroups { g0: self.group0() + swizzle!(other.group0(), 0, 0, 3, 2) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]), g1: self.group1() + swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) } }
1649    }
1650}
1651
1652impl AddAssign<MotorDual> for MultiVector {
1653    fn add_assign(&mut self, other: MotorDual) {
1654        *self = (*self).add(other);
1655    }
1656}
1657
1658impl Sub<MotorDual> for MultiVector {
1659    type Output = MultiVector;
1660
1661    fn sub(self, other: MotorDual) -> MultiVector {
1662        MultiVector { groups: MultiVectorGroups { g0: self.group0() - swizzle!(other.group0(), 0, 0, 3, 2) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]), g1: self.group1() - swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) } }
1663    }
1664}
1665
1666impl SubAssign<MotorDual> for MultiVector {
1667    fn sub_assign(&mut self, other: MotorDual) {
1668        *self = (*self).sub(other);
1669    }
1670}
1671
1672impl GeometricProduct<MotorDual> for MultiVector {
1673    type Output = MultiVector;
1674
1675    fn geometric_product(self, other: MotorDual) -> MultiVector {
1676        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 2, 2, 2, 3) * Simd32x4::from([0.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 2, 3, 2, 2) * Simd32x4::from([1.0, -1.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[0]) * swizzle!(other.group0(), 1, 0, 1, 1) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[1]) * swizzle!(other.group0(), 0, 1, 0, 0) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group0(), 1, 1, 1, 0) * Simd32x4::from([0.0, 0.0, -1.0, -1.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group0(), 0, 0, 0, 1) * Simd32x4::from([0.0, 0.0, -1.0, 1.0]) + swizzle!(self.group0(), 2, 2, 0, 0) * swizzle!(other.group0(), 3, 2, 3, 2), g1: Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 0, 1, 0, 0) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 0, 0, 0, 1) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) + Simd32x4::from(self.group1()[0]) * swizzle!(other.group0(), 3, 3, 3, 2) * Simd32x4::from([0.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[1]) * swizzle!(other.group0(), 2, 2, 2, 3) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group0(), 3, 2, 3, 3) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group0(), 2, 3, 2, 2) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]) + swizzle!(self.group0(), 0, 0, 2, 2) * swizzle!(other.group0(), 1, 0, 1, 0) * Simd32x4::from([1.0, 1.0, -1.0, 1.0]) } }
1677    }
1678}
1679
1680impl RegressiveProduct<MotorDual> for MultiVector {
1681    type Output = MultiVector;
1682
1683    fn regressive_product(self, other: MotorDual) -> MultiVector {
1684        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0, 1, 1) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[1]) * swizzle!(other.group0(), 3, 3, 3, 2) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from(other.group0()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from(other.group0()[3]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + swizzle!(self.group0(), 0, 0, 2, 3) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 1.0, 1.0]), g1: Simd32x4::from(self.group1()[1]) * swizzle!(other.group0(), 1, 0, 1, 1) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + swizzle!(self.group1(), 0, 0, 2, 3) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 1.0, 1.0]) } }
1685    }
1686}
1687
1688impl InnerProduct<MotorDual> for MultiVector {
1689    type Output = MultiVector;
1690
1691    fn inner_product(self, other: MotorDual) -> MultiVector {
1692        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 2, 2, 2, 3) * Simd32x4::from([0.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group0()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[0]) * swizzle!(other.group0(), 1, 0, 1, 1) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[1]) * swizzle!(other.group0(), 0, 1, 0, 0) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group0(), 1, 1, 1, 0) * Simd32x4::from([0.0, 0.0, -1.0, -1.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group0(), 0, 0, 0, 1) * Simd32x4::from([0.0, 0.0, -1.0, 1.0]) + swizzle!(self.group0(), 2, 0, 0, 0) * swizzle!(other.group0(), 3, 0, 3, 2) * Simd32x4::from([1.0, 0.0, 1.0, 1.0]), g1: Simd32x4::from(self.group0()[1]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[1]) * swizzle!(other.group0(), 2, 2, 2, 3) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from(other.group0()[3]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from(other.group0()[2]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + swizzle!(self.group0(), 0, 0, 3, 2) * swizzle!(other.group0(), 1, 0, 0, 0) } }
1693    }
1694}
1695
1696impl LeftContraction<MotorDual> for MultiVector {
1697    type Output = MultiVector;
1698
1699    fn left_contraction(self, other: MotorDual) -> MultiVector {
1700        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group0()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[0]) * swizzle!(other.group0(), 1, 0, 1, 1) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[1]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, 0.0, -1.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, -1.0, 0.0]) + swizzle!(self.group0(), 2, 0, 0, 0) * swizzle!(other.group0(), 3, 0, 3, 2) * Simd32x4::from([1.0, 0.0, 1.0, 1.0]), g1: Simd32x4::from(self.group0()[1]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + swizzle!(self.group0(), 0, 0, 3, 2) * swizzle!(other.group0(), 1, 0, 0, 0) } }
1701    }
1702}
1703
1704impl ScalarProduct<MotorDual> for MultiVector {
1705    type Output = f32;
1706
1707    fn scalar_product(self, other: MotorDual) -> f32 {
1708        self.group0()[2] * other.group0()[3] + self.group0()[3] * other.group0()[2] + self.group1()[0] * other.group0()[1] - self.group1()[1] * other.group0()[0]
1709    }
1710}
1711
1712impl SquaredMagnitude for MultiVector {
1713    type Output = f32;
1714
1715    fn squared_magnitude(self) -> f32 {
1716        self.scalar_product(self.reversal())
1717    }
1718}
1719
1720impl Magnitude for MultiVector {
1721    type Output = f32;
1722
1723    fn magnitude(self) -> f32 {
1724        self.squared_magnitude().sqrt()
1725    }
1726}
1727
1728impl Mul<f32> for MultiVector {
1729    type Output = MultiVector;
1730
1731    fn mul(self, other: f32) -> MultiVector {
1732        self.geometric_product(other)
1733    }
1734}
1735
1736impl MulAssign<f32> for MultiVector {
1737    fn mul_assign(&mut self, other: f32) {
1738        *self = (*self).mul(other);
1739    }
1740}
1741
1742impl Signum for MultiVector {
1743    type Output = MultiVector;
1744
1745    fn signum(self) -> MultiVector {
1746        self.geometric_product(1.0 / self.magnitude())
1747    }
1748}
1749
1750impl Inverse for MultiVector {
1751    type Output = MultiVector;
1752
1753    fn inverse(self) -> MultiVector {
1754        self.reversal().geometric_product(1.0 / self.squared_magnitude())
1755    }
1756}
1757
1758impl Zero for Rotor {
1759    fn zero() -> Self {
1760        Rotor { groups: RotorGroups { g0: Simd32x2::from(0.0) } }
1761    }
1762}
1763
1764impl One for Rotor {
1765    fn one() -> Self {
1766        Rotor { groups: RotorGroups { g0: Simd32x2::from([1.0, 0.0]) } }
1767    }
1768}
1769
1770impl Neg for Rotor {
1771    type Output = Rotor;
1772
1773    fn neg(self) -> Rotor {
1774        Rotor { groups: RotorGroups { g0: self.group0() * Simd32x2::from(-1.0) } }
1775    }
1776}
1777
1778impl Automorphism for Rotor {
1779    type Output = Rotor;
1780
1781    fn automorphism(self) -> Rotor {
1782        Rotor { groups: RotorGroups { g0: self.group0() } }
1783    }
1784}
1785
1786impl Reversal for Rotor {
1787    type Output = Rotor;
1788
1789    fn reversal(self) -> Rotor {
1790        Rotor { groups: RotorGroups { g0: self.group0() * Simd32x2::from([1.0, -1.0]) } }
1791    }
1792}
1793
1794impl Conjugation for Rotor {
1795    type Output = Rotor;
1796
1797    fn conjugation(self) -> Rotor {
1798        Rotor { groups: RotorGroups { g0: self.group0() * Simd32x2::from([1.0, -1.0]) } }
1799    }
1800}
1801
1802impl Into<f32> for Rotor {
1803    fn into(self) -> f32 {
1804        self.group0()[0]
1805    }
1806}
1807
1808impl Add<f32> for Rotor {
1809    type Output = Rotor;
1810
1811    fn add(self, other: f32) -> Rotor {
1812        Rotor { groups: RotorGroups { g0: self.group0() + Simd32x2::from(other) * Simd32x2::from([1.0, 0.0]) } }
1813    }
1814}
1815
1816impl AddAssign<f32> for Rotor {
1817    fn add_assign(&mut self, other: f32) {
1818        *self = (*self).add(other);
1819    }
1820}
1821
1822impl Sub<f32> for Rotor {
1823    type Output = Rotor;
1824
1825    fn sub(self, other: f32) -> Rotor {
1826        Rotor { groups: RotorGroups { g0: self.group0() - Simd32x2::from(other) * Simd32x2::from([1.0, 0.0]) } }
1827    }
1828}
1829
1830impl SubAssign<f32> for Rotor {
1831    fn sub_assign(&mut self, other: f32) {
1832        *self = (*self).sub(other);
1833    }
1834}
1835
1836impl GeometricProduct<f32> for Rotor {
1837    type Output = Rotor;
1838
1839    fn geometric_product(self, other: f32) -> Rotor {
1840        Rotor { groups: RotorGroups { g0: self.group0() * Simd32x2::from(other) } }
1841    }
1842}
1843
1844impl OuterProduct<f32> for Rotor {
1845    type Output = Rotor;
1846
1847    fn outer_product(self, other: f32) -> Rotor {
1848        Rotor { groups: RotorGroups { g0: self.group0() * Simd32x2::from(other) } }
1849    }
1850}
1851
1852impl InnerProduct<f32> for Rotor {
1853    type Output = Rotor;
1854
1855    fn inner_product(self, other: f32) -> Rotor {
1856        Rotor { groups: RotorGroups { g0: self.group0() * Simd32x2::from(other) } }
1857    }
1858}
1859
1860impl LeftContraction<f32> for Rotor {
1861    type Output = f32;
1862
1863    fn left_contraction(self, other: f32) -> f32 {
1864        self.group0()[0] * other
1865    }
1866}
1867
1868impl RightContraction<f32> for Rotor {
1869    type Output = Rotor;
1870
1871    fn right_contraction(self, other: f32) -> Rotor {
1872        Rotor { groups: RotorGroups { g0: self.group0() * Simd32x2::from(other) } }
1873    }
1874}
1875
1876impl ScalarProduct<f32> for Rotor {
1877    type Output = f32;
1878
1879    fn scalar_product(self, other: f32) -> f32 {
1880        self.group0()[0] * other
1881    }
1882}
1883
1884impl Add<MultiVector> for Rotor {
1885    type Output = MultiVector;
1886
1887    fn add(self, other: MultiVector) -> MultiVector {
1888        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[1], self.group0()[0], self.group0()[0]]) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + other.group0(), g1: other.group1() } }
1889    }
1890}
1891
1892impl Sub<MultiVector> for Rotor {
1893    type Output = MultiVector;
1894
1895    fn sub(self, other: MultiVector) -> MultiVector {
1896        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[1], self.group0()[0], self.group0()[0]]) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) - other.group0(), g1: Simd32x4::from(0.0) - other.group1() } }
1897    }
1898}
1899
1900impl GeometricProduct<MultiVector> for Rotor {
1901    type Output = MultiVector;
1902
1903    fn geometric_product(self, other: MultiVector) -> MultiVector {
1904        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, 1.0, -1.0]), g1: Simd32x4::from(self.group0()[0]) * other.group1() + Simd32x4::from(self.group0()[1]) * swizzle!(other.group1(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, -1.0, 1.0]) } }
1905    }
1906}
1907
1908impl OuterProduct<MultiVector> for Rotor {
1909    type Output = MultiVector;
1910
1911    fn outer_product(self, other: MultiVector) -> MultiVector {
1912        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from([self.group0()[0], self.group0()[1], self.group0()[0], self.group0()[0]]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 0.0, 0.0]), g1: Simd32x4::from(self.group0()[0]) * other.group1() + Simd32x4::from([self.group0()[0], self.group0()[1], self.group0()[0], self.group0()[0]]) * Simd32x4::from(other.group1()[0]) * Simd32x4::from([0.0, 1.0, 0.0, 0.0]) } }
1913    }
1914}
1915
1916impl InnerProduct<MultiVector> for Rotor {
1917    type Output = MultiVector;
1918
1919    fn inner_product(self, other: MultiVector) -> MultiVector {
1920        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, 1.0, -1.0]), g1: Simd32x4::from(self.group0()[0]) * other.group1() + Simd32x4::from([self.group0()[1], self.group0()[0], self.group0()[0], self.group0()[0]]) * swizzle!(other.group1(), 1, 0, 0, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) } }
1921    }
1922}
1923
1924impl LeftContraction<MultiVector> for Rotor {
1925    type Output = MultiVector;
1926
1927    fn left_contraction(self, other: MultiVector) -> MultiVector {
1928        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from([self.group0()[1], self.group0()[0], self.group0()[0], self.group0()[0]]) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]), g1: Simd32x4::from(self.group0()[0]) * other.group1() + Simd32x4::from([self.group0()[1], self.group0()[0], self.group0()[0], self.group0()[0]]) * swizzle!(other.group1(), 1, 0, 0, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) } }
1929    }
1930}
1931
1932impl ScalarProduct<MultiVector> for Rotor {
1933    type Output = f32;
1934
1935    fn scalar_product(self, other: MultiVector) -> f32 {
1936        self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group0()[1]
1937    }
1938}
1939
1940impl Add<Rotor> for Rotor {
1941    type Output = Rotor;
1942
1943    fn add(self, other: Rotor) -> Rotor {
1944        Rotor { groups: RotorGroups { g0: self.group0() + other.group0() } }
1945    }
1946}
1947
1948impl AddAssign<Rotor> for Rotor {
1949    fn add_assign(&mut self, other: Rotor) {
1950        *self = (*self).add(other);
1951    }
1952}
1953
1954impl Sub<Rotor> for Rotor {
1955    type Output = Rotor;
1956
1957    fn sub(self, other: Rotor) -> Rotor {
1958        Rotor { groups: RotorGroups { g0: self.group0() - other.group0() } }
1959    }
1960}
1961
1962impl SubAssign<Rotor> for Rotor {
1963    fn sub_assign(&mut self, other: Rotor) {
1964        *self = (*self).sub(other);
1965    }
1966}
1967
1968impl Mul<Rotor> for Rotor {
1969    type Output = Rotor;
1970
1971    fn mul(self, other: Rotor) -> Rotor {
1972        Rotor { groups: RotorGroups { g0: self.group0() * other.group0() } }
1973    }
1974}
1975
1976impl MulAssign<Rotor> for Rotor {
1977    fn mul_assign(&mut self, other: Rotor) {
1978        *self = (*self).mul(other);
1979    }
1980}
1981
1982impl Div<Rotor> for Rotor {
1983    type Output = Rotor;
1984
1985    fn div(self, other: Rotor) -> Rotor {
1986        Rotor { groups: RotorGroups { g0: Simd32x2::from([self.group0()[0], self.group0()[1]]) * Simd32x2::from([1.0, 1.0]) / Simd32x2::from([other.group0()[0], other.group0()[1]]) * Simd32x2::from([1.0, 1.0]) } }
1987    }
1988}
1989
1990impl DivAssign<Rotor> for Rotor {
1991    fn div_assign(&mut self, other: Rotor) {
1992        *self = (*self).div(other);
1993    }
1994}
1995
1996impl GeometricProduct<Rotor> for Rotor {
1997    type Output = Rotor;
1998
1999    fn geometric_product(self, other: Rotor) -> Rotor {
2000        Rotor { groups: RotorGroups { g0: Simd32x2::from(self.group0()[0]) * other.group0() + Simd32x2::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0) * Simd32x2::from([-1.0, 1.0]) } }
2001    }
2002}
2003
2004impl OuterProduct<Rotor> for Rotor {
2005    type Output = Rotor;
2006
2007    fn outer_product(self, other: Rotor) -> Rotor {
2008        Rotor { groups: RotorGroups { g0: Simd32x2::from(self.group0()[0]) * other.group0() + self.group0() * Simd32x2::from(other.group0()[0]) * Simd32x2::from([0.0, 1.0]) } }
2009    }
2010}
2011
2012impl InnerProduct<Rotor> for Rotor {
2013    type Output = Rotor;
2014
2015    fn inner_product(self, other: Rotor) -> Rotor {
2016        Rotor { groups: RotorGroups { g0: Simd32x2::from(self.group0()[0]) * other.group0() + Simd32x2::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0) * Simd32x2::from([-1.0, 1.0]) } }
2017    }
2018}
2019
2020impl LeftContraction<Rotor> for Rotor {
2021    type Output = Rotor;
2022
2023    fn left_contraction(self, other: Rotor) -> Rotor {
2024        Rotor { groups: RotorGroups { g0: Simd32x2::from(self.group0()[0]) * other.group0() + swizzle!(self.group0(), 1, 0) * swizzle!(other.group0(), 1, 0) * Simd32x2::from([-1.0, 0.0]) } }
2025    }
2026}
2027
2028impl RightContraction<Rotor> for Rotor {
2029    type Output = Rotor;
2030
2031    fn right_contraction(self, other: Rotor) -> Rotor {
2032        Rotor { groups: RotorGroups { g0: Simd32x2::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0) * Simd32x2::from([-1.0, 1.0]) + Simd32x2::from(self.group0()[0]) * Simd32x2::from(other.group0()[0]) * Simd32x2::from([1.0, 0.0]) } }
2033    }
2034}
2035
2036impl ScalarProduct<Rotor> for Rotor {
2037    type Output = f32;
2038
2039    fn scalar_product(self, other: Rotor) -> f32 {
2040        self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group0()[1]
2041    }
2042}
2043
2044impl Add<Point> for Rotor {
2045    type Output = Motor;
2046
2047    fn add(self, other: Point) -> Motor {
2048        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[1], self.group0()[0], self.group0()[0]]) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
2049    }
2050}
2051
2052impl Sub<Point> for Rotor {
2053    type Output = Motor;
2054
2055    fn sub(self, other: Point) -> Motor {
2056        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[1], self.group0()[0], self.group0()[0]]) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) - Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
2057    }
2058}
2059
2060impl GeometricProduct<Point> for Rotor {
2061    type Output = Motor;
2062
2063    fn geometric_product(self, other: Point) -> Motor {
2064        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[2], other.group0()[1]]) * Simd32x4::from([-1.0, 0.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
2065    }
2066}
2067
2068impl OuterProduct<Point> for Rotor {
2069    type Output = Point;
2070
2071    fn outer_product(self, other: Point) -> Point {
2072        Point { groups: PointGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() } }
2073    }
2074}
2075
2076impl InnerProduct<Point> for Rotor {
2077    type Output = Motor;
2078
2079    fn inner_product(self, other: Point) -> Motor {
2080        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[1], self.group0()[0], self.group0()[0], self.group0()[0]]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) } }
2081    }
2082}
2083
2084impl LeftContraction<Point> for Rotor {
2085    type Output = Motor;
2086
2087    fn left_contraction(self, other: Point) -> Motor {
2088        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[1], self.group0()[0], self.group0()[0], self.group0()[0]]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) } }
2089    }
2090}
2091
2092impl RightContraction<Point> for Rotor {
2093    type Output = f32;
2094
2095    fn right_contraction(self, other: Point) -> f32 {
2096        0.0 - self.group0()[1] * other.group0()[0]
2097    }
2098}
2099
2100impl ScalarProduct<Point> for Rotor {
2101    type Output = f32;
2102
2103    fn scalar_product(self, other: Point) -> f32 {
2104        0.0 - self.group0()[1] * other.group0()[0]
2105    }
2106}
2107
2108impl Add<IdealPoint> for Rotor {
2109    type Output = Motor;
2110
2111    fn add(self, other: IdealPoint) -> Motor {
2112        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[1], self.group0()[0], self.group0()[0]]) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[0], other.group0()[1]]) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) } }
2113    }
2114}
2115
2116impl Sub<IdealPoint> for Rotor {
2117    type Output = Motor;
2118
2119    fn sub(self, other: IdealPoint) -> Motor {
2120        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[1], self.group0()[0], self.group0()[0]]) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) - Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[0], other.group0()[1]]) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) } }
2121    }
2122}
2123
2124impl GeometricProduct<IdealPoint> for Rotor {
2125    type Output = IdealPoint;
2126
2127    fn geometric_product(self, other: IdealPoint) -> IdealPoint {
2128        IdealPoint { groups: IdealPointGroups { g0: Simd32x2::from(self.group0()[0]) * other.group0() + Simd32x2::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0) * Simd32x2::from([-1.0, 1.0]) } }
2129    }
2130}
2131
2132impl OuterProduct<IdealPoint> for Rotor {
2133    type Output = IdealPoint;
2134
2135    fn outer_product(self, other: IdealPoint) -> IdealPoint {
2136        IdealPoint { groups: IdealPointGroups { g0: Simd32x2::from(self.group0()[0]) * other.group0() } }
2137    }
2138}
2139
2140impl InnerProduct<IdealPoint> for Rotor {
2141    type Output = IdealPoint;
2142
2143    fn inner_product(self, other: IdealPoint) -> IdealPoint {
2144        IdealPoint { groups: IdealPointGroups { g0: Simd32x2::from(self.group0()[0]) * other.group0() } }
2145    }
2146}
2147
2148impl LeftContraction<IdealPoint> for Rotor {
2149    type Output = IdealPoint;
2150
2151    fn left_contraction(self, other: IdealPoint) -> IdealPoint {
2152        IdealPoint { groups: IdealPointGroups { g0: Simd32x2::from(self.group0()[0]) * other.group0() } }
2153    }
2154}
2155
2156impl GeometricProduct<Plane> for Rotor {
2157    type Output = MotorDual;
2158
2159    fn geometric_product(self, other: Plane) -> MotorDual {
2160        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[2], other.group0()[1]]) * Simd32x4::from([1.0, 0.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
2161    }
2162}
2163
2164impl RegressiveProduct<Plane> for Rotor {
2165    type Output = f32;
2166
2167    fn regressive_product(self, other: Plane) -> f32 {
2168        self.group0()[1] * other.group0()[0]
2169    }
2170}
2171
2172impl OuterProduct<Plane> for Rotor {
2173    type Output = MotorDual;
2174
2175    fn outer_product(self, other: Plane) -> MotorDual {
2176        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from([self.group0()[1], self.group0()[0], self.group0()[0], self.group0()[0]]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) } }
2177    }
2178}
2179
2180impl InnerProduct<Plane> for Rotor {
2181    type Output = Plane;
2182
2183    fn inner_product(self, other: Plane) -> Plane {
2184        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() + Simd32x3::from([self.group0()[0], self.group0()[1], self.group0()[1]]) * swizzle!(other.group0(), 0, 2, 1) * Simd32x3::from([0.0, -1.0, 1.0]) } }
2185    }
2186}
2187
2188impl LeftContraction<Plane> for Rotor {
2189    type Output = Plane;
2190
2191    fn left_contraction(self, other: Plane) -> Plane {
2192        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() } }
2193    }
2194}
2195
2196impl Add<Translator> for Rotor {
2197    type Output = Motor;
2198
2199    fn add(self, other: Translator) -> Motor {
2200        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[1], self.group0()[0], self.group0()[0]]) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([1.0, 0.0, 1.0, 1.0]) } }
2201    }
2202}
2203
2204impl Sub<Translator> for Rotor {
2205    type Output = Motor;
2206
2207    fn sub(self, other: Translator) -> Motor {
2208        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[1], self.group0()[0], self.group0()[0]]) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) - Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([1.0, 0.0, 1.0, 1.0]) } }
2209    }
2210}
2211
2212impl GeometricProduct<Translator> for Rotor {
2213    type Output = Motor;
2214
2215    fn geometric_product(self, other: Translator) -> Motor {
2216        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[2], other.group0()[1]]) * Simd32x4::from([0.0, 1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([1.0, 0.0, 1.0, 1.0]) } }
2217    }
2218}
2219
2220impl OuterProduct<Translator> for Rotor {
2221    type Output = Motor;
2222
2223    fn outer_product(self, other: Translator) -> Motor {
2224        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[1], self.group0()[0], self.group0()[0]]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) } }
2225    }
2226}
2227
2228impl InnerProduct<Translator> for Rotor {
2229    type Output = Motor;
2230
2231    fn inner_product(self, other: Translator) -> Motor {
2232        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[1], self.group0()[0], self.group0()[0]]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) } }
2233    }
2234}
2235
2236impl LeftContraction<Translator> for Rotor {
2237    type Output = Translator;
2238
2239    fn left_contraction(self, other: Translator) -> Translator {
2240        Translator { groups: TranslatorGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() } }
2241    }
2242}
2243
2244impl RightContraction<Translator> for Rotor {
2245    type Output = Rotor;
2246
2247    fn right_contraction(self, other: Translator) -> Rotor {
2248        Rotor { groups: RotorGroups { g0: self.group0() * Simd32x2::from(other.group0()[0]) } }
2249    }
2250}
2251
2252impl ScalarProduct<Translator> for Rotor {
2253    type Output = f32;
2254
2255    fn scalar_product(self, other: Translator) -> f32 {
2256        self.group0()[0] * other.group0()[0]
2257    }
2258}
2259
2260impl Add<Motor> for Rotor {
2261    type Output = Motor;
2262
2263    fn add(self, other: Motor) -> Motor {
2264        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[1], self.group0()[0], self.group0()[0]]) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + other.group0() } }
2265    }
2266}
2267
2268impl Sub<Motor> for Rotor {
2269    type Output = Motor;
2270
2271    fn sub(self, other: Motor) -> Motor {
2272        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[1], self.group0()[0], self.group0()[0]]) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) - other.group0() } }
2273    }
2274}
2275
2276impl GeometricProduct<Motor> for Rotor {
2277    type Output = Motor;
2278
2279    fn geometric_product(self, other: Motor) -> Motor {
2280        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, -1.0, 1.0]) } }
2281    }
2282}
2283
2284impl OuterProduct<Motor> for Rotor {
2285    type Output = Motor;
2286
2287    fn outer_product(self, other: Motor) -> Motor {
2288        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from([self.group0()[0], self.group0()[1], self.group0()[0], self.group0()[0]]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 0.0, 0.0]) } }
2289    }
2290}
2291
2292impl InnerProduct<Motor> for Rotor {
2293    type Output = Motor;
2294
2295    fn inner_product(self, other: Motor) -> Motor {
2296        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from([self.group0()[1], self.group0()[1], self.group0()[0], self.group0()[0]]) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]) } }
2297    }
2298}
2299
2300impl LeftContraction<Motor> for Rotor {
2301    type Output = Motor;
2302
2303    fn left_contraction(self, other: Motor) -> Motor {
2304        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from([self.group0()[1], self.group0()[0], self.group0()[0], self.group0()[0]]) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) } }
2305    }
2306}
2307
2308impl RightContraction<Motor> for Rotor {
2309    type Output = Rotor;
2310
2311    fn right_contraction(self, other: Motor) -> Rotor {
2312        Rotor { groups: RotorGroups { g0: Simd32x2::from(self.group0()[1]) * Simd32x2::from([other.group0()[1], other.group0()[0]]) * Simd32x2::from([-1.0, 1.0]) + Simd32x2::from(self.group0()[0]) * Simd32x2::from(other.group0()[0]) * Simd32x2::from([1.0, 0.0]) } }
2313    }
2314}
2315
2316impl ScalarProduct<Motor> for Rotor {
2317    type Output = f32;
2318
2319    fn scalar_product(self, other: Motor) -> f32 {
2320        self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group0()[1]
2321    }
2322}
2323
2324impl GeometricProduct<MotorDual> for Rotor {
2325    type Output = MotorDual;
2326
2327    fn geometric_product(self, other: MotorDual) -> MotorDual {
2328        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([1.0, -1.0, -1.0, 1.0]) } }
2329    }
2330}
2331
2332impl RegressiveProduct<MotorDual> for Rotor {
2333    type Output = Rotor;
2334
2335    fn regressive_product(self, other: MotorDual) -> Rotor {
2336        Rotor { groups: RotorGroups { g0: Simd32x2::from(self.group0()[1]) * Simd32x2::from([other.group0()[1], other.group0()[0]]) + Simd32x2::from(self.group0()[0]) * Simd32x2::from(other.group0()[0]) * Simd32x2::from([1.0, 0.0]) } }
2337    }
2338}
2339
2340impl OuterProduct<MotorDual> for Rotor {
2341    type Output = MotorDual;
2342
2343    fn outer_product(self, other: MotorDual) -> MotorDual {
2344        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from([self.group0()[1], self.group0()[0], self.group0()[0], self.group0()[0]]) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
2345    }
2346}
2347
2348impl InnerProduct<MotorDual> for Rotor {
2349    type Output = MotorDual;
2350
2351    fn inner_product(self, other: MotorDual) -> MotorDual {
2352        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from([self.group0()[0], self.group0()[1], self.group0()[1], self.group0()[1]]) * swizzle!(other.group0(), 0, 0, 3, 2) * Simd32x4::from([0.0, -1.0, -1.0, 1.0]) } }
2353    }
2354}
2355
2356impl LeftContraction<MotorDual> for Rotor {
2357    type Output = MotorDual;
2358
2359    fn left_contraction(self, other: MotorDual) -> MotorDual {
2360        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from([self.group0()[0], self.group0()[1], self.group0()[0], self.group0()[0]]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, -1.0, 0.0, 0.0]) } }
2361    }
2362}
2363
2364impl SquaredMagnitude for Rotor {
2365    type Output = f32;
2366
2367    fn squared_magnitude(self) -> f32 {
2368        self.scalar_product(self.reversal())
2369    }
2370}
2371
2372impl Magnitude for Rotor {
2373    type Output = f32;
2374
2375    fn magnitude(self) -> f32 {
2376        self.squared_magnitude().sqrt()
2377    }
2378}
2379
2380impl Mul<f32> for Rotor {
2381    type Output = Rotor;
2382
2383    fn mul(self, other: f32) -> Rotor {
2384        self.geometric_product(other)
2385    }
2386}
2387
2388impl MulAssign<f32> for Rotor {
2389    fn mul_assign(&mut self, other: f32) {
2390        *self = (*self).mul(other);
2391    }
2392}
2393
2394impl Signum for Rotor {
2395    type Output = Rotor;
2396
2397    fn signum(self) -> Rotor {
2398        self.geometric_product(1.0 / self.magnitude())
2399    }
2400}
2401
2402impl Inverse for Rotor {
2403    type Output = Rotor;
2404
2405    fn inverse(self) -> Rotor {
2406        self.reversal().geometric_product(1.0 / self.squared_magnitude())
2407    }
2408}
2409
2410impl Zero for Point {
2411    fn zero() -> Self {
2412        Point { groups: PointGroups { g0: Simd32x3::from(0.0) } }
2413    }
2414}
2415
2416impl One for Point {
2417    fn one() -> Self {
2418        Point { groups: PointGroups { g0: Simd32x3::from(0.0) } }
2419    }
2420}
2421
2422impl Neg for Point {
2423    type Output = Point;
2424
2425    fn neg(self) -> Point {
2426        Point { groups: PointGroups { g0: self.group0() * Simd32x3::from(-1.0) } }
2427    }
2428}
2429
2430impl Automorphism for Point {
2431    type Output = Point;
2432
2433    fn automorphism(self) -> Point {
2434        Point { groups: PointGroups { g0: self.group0() } }
2435    }
2436}
2437
2438impl Reversal for Point {
2439    type Output = Point;
2440
2441    fn reversal(self) -> Point {
2442        Point { groups: PointGroups { g0: self.group0() * Simd32x3::from(-1.0) } }
2443    }
2444}
2445
2446impl Conjugation for Point {
2447    type Output = Point;
2448
2449    fn conjugation(self) -> Point {
2450        Point { groups: PointGroups { g0: self.group0() * Simd32x3::from(-1.0) } }
2451    }
2452}
2453
2454impl Dual for Point {
2455    type Output = Plane;
2456
2457    fn dual(self) -> Plane {
2458        Plane { groups: PlaneGroups { g0: self.group0() } }
2459    }
2460}
2461
2462impl Add<f32> for Point {
2463    type Output = Motor;
2464
2465    fn add(self, other: f32) -> Motor {
2466        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[1], self.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) + Simd32x4::from(other) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
2467    }
2468}
2469
2470impl Sub<f32> for Point {
2471    type Output = Motor;
2472
2473    fn sub(self, other: f32) -> Motor {
2474        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[1], self.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) - Simd32x4::from(other) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
2475    }
2476}
2477
2478impl GeometricProduct<f32> for Point {
2479    type Output = Point;
2480
2481    fn geometric_product(self, other: f32) -> Point {
2482        Point { groups: PointGroups { g0: self.group0() * Simd32x3::from(other) } }
2483    }
2484}
2485
2486impl OuterProduct<f32> for Point {
2487    type Output = Point;
2488
2489    fn outer_product(self, other: f32) -> Point {
2490        Point { groups: PointGroups { g0: self.group0() * Simd32x3::from(other) } }
2491    }
2492}
2493
2494impl InnerProduct<f32> for Point {
2495    type Output = Point;
2496
2497    fn inner_product(self, other: f32) -> Point {
2498        Point { groups: PointGroups { g0: self.group0() * Simd32x3::from(other) } }
2499    }
2500}
2501
2502impl RightContraction<f32> for Point {
2503    type Output = Point;
2504
2505    fn right_contraction(self, other: f32) -> Point {
2506        Point { groups: PointGroups { g0: self.group0() * Simd32x3::from(other) } }
2507    }
2508}
2509
2510impl Add<MultiVector> for Point {
2511    type Output = MultiVector;
2512
2513    fn add(self, other: MultiVector) -> MultiVector {
2514        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * Simd32x4::from([0.0, 1.0, 0.0, 0.0]) + other.group0(), g1: Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[1], self.group0()[2]]) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) + other.group1() } }
2515    }
2516}
2517
2518impl Sub<MultiVector> for Point {
2519    type Output = MultiVector;
2520
2521    fn sub(self, other: MultiVector) -> MultiVector {
2522        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * Simd32x4::from([0.0, 1.0, 0.0, 0.0]) - other.group0(), g1: Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[1], self.group0()[2]]) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) - other.group1() } }
2523    }
2524}
2525
2526impl GeometricProduct<MultiVector> for Point {
2527    type Output = MultiVector;
2528
2529    fn geometric_product(self, other: MultiVector) -> MultiVector {
2530        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[1]) * swizzle!(other.group1(), 2, 3, 0, 1) * Simd32x4::from([-1.0, 1.0, -1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group1(), 3, 2, 1, 0) * Simd32x4::from([-1.0, -1.0, -1.0, 1.0]), g1: Simd32x4::from(self.group0()[0]) * swizzle!(other.group1(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 2, 3, 0, 1) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) } }
2531    }
2532}
2533
2534impl ScalarProduct<MultiVector> for Point {
2535    type Output = f32;
2536
2537    fn scalar_product(self, other: MultiVector) -> f32 {
2538        0.0 - self.group0()[0] * other.group0()[1] - self.group0()[1] * other.group1()[2] - self.group0()[2] * other.group1()[3]
2539    }
2540}
2541
2542impl Add<Rotor> for Point {
2543    type Output = Motor;
2544
2545    fn add(self, other: Rotor) -> Motor {
2546        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[1], self.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) + Simd32x4::from([other.group0()[0], other.group0()[1], other.group0()[0], other.group0()[0]]) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) } }
2547    }
2548}
2549
2550impl Sub<Rotor> for Point {
2551    type Output = Motor;
2552
2553    fn sub(self, other: Rotor) -> Motor {
2554        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[1], self.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) - Simd32x4::from([other.group0()[0], other.group0()[1], other.group0()[0], other.group0()[0]]) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) } }
2555    }
2556}
2557
2558impl GeometricProduct<Rotor> for Point {
2559    type Output = Motor;
2560
2561    fn geometric_product(self, other: Rotor) -> Motor {
2562        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[1], other.group0()[1], other.group0()[1], other.group0()[0]]) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) + Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[1], self.group0()[1]]) * Simd32x4::from([other.group0()[1], other.group0()[0], other.group0()[0], other.group0()[1]]) * Simd32x4::from([-1.0, 1.0, 1.0, -1.0]) } }
2563    }
2564}
2565
2566impl OuterProduct<Rotor> for Point {
2567    type Output = Point;
2568
2569    fn outer_product(self, other: Rotor) -> Point {
2570        Point { groups: PointGroups { g0: self.group0() * Simd32x3::from(other.group0()[0]) } }
2571    }
2572}
2573
2574impl InnerProduct<Rotor> for Point {
2575    type Output = Motor;
2576
2577    fn inner_product(self, other: Rotor) -> Motor {
2578        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[1], self.group0()[2]]) * Simd32x4::from([other.group0()[1], other.group0()[0], other.group0()[0], other.group0()[0]]) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) } }
2579    }
2580}
2581
2582impl LeftContraction<Rotor> for Point {
2583    type Output = f32;
2584
2585    fn left_contraction(self, other: Rotor) -> f32 {
2586        0.0 - self.group0()[0] * other.group0()[1]
2587    }
2588}
2589
2590impl RightContraction<Rotor> for Point {
2591    type Output = Motor;
2592
2593    fn right_contraction(self, other: Rotor) -> Motor {
2594        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[1], self.group0()[2]]) * Simd32x4::from([other.group0()[1], other.group0()[0], other.group0()[0], other.group0()[0]]) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) } }
2595    }
2596}
2597
2598impl ScalarProduct<Rotor> for Point {
2599    type Output = f32;
2600
2601    fn scalar_product(self, other: Rotor) -> f32 {
2602        0.0 - self.group0()[0] * other.group0()[1]
2603    }
2604}
2605
2606impl Add<Point> for Point {
2607    type Output = Point;
2608
2609    fn add(self, other: Point) -> Point {
2610        Point { groups: PointGroups { g0: self.group0() + other.group0() } }
2611    }
2612}
2613
2614impl AddAssign<Point> for Point {
2615    fn add_assign(&mut self, other: Point) {
2616        *self = (*self).add(other);
2617    }
2618}
2619
2620impl Sub<Point> for Point {
2621    type Output = Point;
2622
2623    fn sub(self, other: Point) -> Point {
2624        Point { groups: PointGroups { g0: self.group0() - other.group0() } }
2625    }
2626}
2627
2628impl SubAssign<Point> for Point {
2629    fn sub_assign(&mut self, other: Point) {
2630        *self = (*self).sub(other);
2631    }
2632}
2633
2634impl Mul<Point> for Point {
2635    type Output = Point;
2636
2637    fn mul(self, other: Point) -> Point {
2638        Point { groups: PointGroups { g0: self.group0() * other.group0() } }
2639    }
2640}
2641
2642impl MulAssign<Point> for Point {
2643    fn mul_assign(&mut self, other: Point) {
2644        *self = (*self).mul(other);
2645    }
2646}
2647
2648impl Div<Point> for Point {
2649    type Output = Point;
2650
2651    fn div(self, other: Point) -> Point {
2652        Point { groups: PointGroups { g0: Simd32x3::from([self.group0()[0], self.group0()[1], self.group0()[2]]) * Simd32x3::from([1.0, 1.0, 1.0]) / Simd32x3::from([other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x3::from([1.0, 1.0, 1.0]) } }
2653    }
2654}
2655
2656impl DivAssign<Point> for Point {
2657    fn div_assign(&mut self, other: Point) {
2658        *self = (*self).div(other);
2659    }
2660}
2661
2662impl GeometricProduct<Point> for Point {
2663    type Output = Motor;
2664
2665    fn geometric_product(self, other: Point) -> Motor {
2666        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[1], other.group0()[2], other.group0()[1], other.group0()[0]]) * Simd32x4::from([-1.0, 1.0, 0.0, -1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[2], other.group0()[1], other.group0()[0], other.group0()[2]]) * Simd32x4::from([-1.0, -1.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[2], other.group0()[1]]) * Simd32x4::from([-1.0, 0.0, -1.0, 1.0]) } }
2667    }
2668}
2669
2670impl RegressiveProduct<Point> for Point {
2671    type Output = Plane;
2672
2673    fn regressive_product(self, other: Point) -> Plane {
2674        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[1]) * swizzle!(other.group0(), 2, 2, 0) * Simd32x3::from([-1.0, 0.0, 1.0]) + Simd32x3::from(self.group0()[2]) * swizzle!(other.group0(), 1, 0, 1) * Simd32x3::from([1.0, -1.0, 0.0]) + Simd32x3::from(self.group0()[0]) * swizzle!(other.group0(), 0, 2, 1) * Simd32x3::from([0.0, 1.0, -1.0]) } }
2675    }
2676}
2677
2678impl InnerProduct<Point> for Point {
2679    type Output = f32;
2680
2681    fn inner_product(self, other: Point) -> f32 {
2682        0.0 - self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group0()[1] - self.group0()[2] * other.group0()[2]
2683    }
2684}
2685
2686impl LeftContraction<Point> for Point {
2687    type Output = f32;
2688
2689    fn left_contraction(self, other: Point) -> f32 {
2690        0.0 - self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group0()[1] - self.group0()[2] * other.group0()[2]
2691    }
2692}
2693
2694impl RightContraction<Point> for Point {
2695    type Output = f32;
2696
2697    fn right_contraction(self, other: Point) -> f32 {
2698        0.0 - self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group0()[1] - self.group0()[2] * other.group0()[2]
2699    }
2700}
2701
2702impl ScalarProduct<Point> for Point {
2703    type Output = f32;
2704
2705    fn scalar_product(self, other: Point) -> f32 {
2706        0.0 - self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group0()[1] - self.group0()[2] * other.group0()[2]
2707    }
2708}
2709
2710impl Into<IdealPoint> for Point {
2711    fn into(self) -> IdealPoint {
2712        IdealPoint { groups: IdealPointGroups { g0: Simd32x2::from([self.group0()[1], self.group0()[2]]) } }
2713    }
2714}
2715
2716impl Add<IdealPoint> for Point {
2717    type Output = Point;
2718
2719    fn add(self, other: IdealPoint) -> Point {
2720        Point { groups: PointGroups { g0: self.group0() + Simd32x3::from([other.group0()[0], other.group0()[0], other.group0()[1]]) * Simd32x3::from([0.0, 1.0, 1.0]) } }
2721    }
2722}
2723
2724impl AddAssign<IdealPoint> for Point {
2725    fn add_assign(&mut self, other: IdealPoint) {
2726        *self = (*self).add(other);
2727    }
2728}
2729
2730impl Sub<IdealPoint> for Point {
2731    type Output = Point;
2732
2733    fn sub(self, other: IdealPoint) -> Point {
2734        Point { groups: PointGroups { g0: self.group0() - Simd32x3::from([other.group0()[0], other.group0()[0], other.group0()[1]]) * Simd32x3::from([0.0, 1.0, 1.0]) } }
2735    }
2736}
2737
2738impl SubAssign<IdealPoint> for Point {
2739    fn sub_assign(&mut self, other: IdealPoint) {
2740        *self = (*self).sub(other);
2741    }
2742}
2743
2744impl GeometricProduct<IdealPoint> for Point {
2745    type Output = Motor;
2746
2747    fn geometric_product(self, other: IdealPoint) -> Motor {
2748        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[1], other.group0()[0], other.group0()[1], other.group0()[1]]) * Simd32x4::from([-1.0, -1.0, 0.0, 0.0]) + Simd32x4::from([self.group0()[1], self.group0()[1], self.group0()[0], self.group0()[0]]) * Simd32x4::from([other.group0()[0], other.group0()[1], other.group0()[1], other.group0()[0]]) * Simd32x4::from([-1.0, 1.0, -1.0, 1.0]) } }
2749    }
2750}
2751
2752impl RegressiveProduct<IdealPoint> for Point {
2753    type Output = Plane;
2754
2755    fn regressive_product(self, other: IdealPoint) -> Plane {
2756        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[2]) * Simd32x3::from(other.group0()[0]) * Simd32x3::from([1.0, 0.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0) * Simd32x3::from([other.group0()[1], other.group0()[1], other.group0()[0]]) * Simd32x3::from([-1.0, 1.0, -1.0]) } }
2757    }
2758}
2759
2760impl InnerProduct<IdealPoint> for Point {
2761    type Output = f32;
2762
2763    fn inner_product(self, other: IdealPoint) -> f32 {
2764        0.0 - self.group0()[1] * other.group0()[0] - self.group0()[2] * other.group0()[1]
2765    }
2766}
2767
2768impl LeftContraction<IdealPoint> for Point {
2769    type Output = f32;
2770
2771    fn left_contraction(self, other: IdealPoint) -> f32 {
2772        0.0 - self.group0()[1] * other.group0()[0] - self.group0()[2] * other.group0()[1]
2773    }
2774}
2775
2776impl RightContraction<IdealPoint> for Point {
2777    type Output = f32;
2778
2779    fn right_contraction(self, other: IdealPoint) -> f32 {
2780        0.0 - self.group0()[1] * other.group0()[0] - self.group0()[2] * other.group0()[1]
2781    }
2782}
2783
2784impl ScalarProduct<IdealPoint> for Point {
2785    type Output = f32;
2786
2787    fn scalar_product(self, other: IdealPoint) -> f32 {
2788        0.0 - self.group0()[1] * other.group0()[0] - self.group0()[2] * other.group0()[1]
2789    }
2790}
2791
2792impl GeometricProduct<Plane> for Point {
2793    type Output = MotorDual;
2794
2795    fn geometric_product(self, other: Plane) -> MotorDual {
2796        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[1], other.group0()[2], other.group0()[1], other.group0()[0]]) * Simd32x4::from([1.0, 1.0, 0.0, -1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[2], other.group0()[1], other.group0()[0], other.group0()[2]]) * Simd32x4::from([1.0, -1.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[2], other.group0()[1]]) * Simd32x4::from([1.0, 0.0, -1.0, 1.0]) } }
2797    }
2798}
2799
2800impl RegressiveProduct<Plane> for Point {
2801    type Output = f32;
2802
2803    fn regressive_product(self, other: Plane) -> f32 {
2804        self.group0()[0] * other.group0()[0] + self.group0()[1] * other.group0()[1] + self.group0()[2] * other.group0()[2]
2805    }
2806}
2807
2808impl InnerProduct<Plane> for Point {
2809    type Output = Plane;
2810
2811    fn inner_product(self, other: Plane) -> Plane {
2812        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[1]) * swizzle!(other.group0(), 2, 2, 0) * Simd32x3::from([1.0, 0.0, -1.0]) + Simd32x3::from(self.group0()[2]) * swizzle!(other.group0(), 1, 0, 1) * Simd32x3::from([-1.0, 1.0, 0.0]) + Simd32x3::from(self.group0()[0]) * swizzle!(other.group0(), 0, 2, 1) * Simd32x3::from([0.0, -1.0, 1.0]) } }
2813    }
2814}
2815
2816impl RightContraction<Plane> for Point {
2817    type Output = Plane;
2818
2819    fn right_contraction(self, other: Plane) -> Plane {
2820        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[1]) * swizzle!(other.group0(), 2, 2, 0) * Simd32x3::from([1.0, 0.0, -1.0]) + Simd32x3::from(self.group0()[2]) * swizzle!(other.group0(), 1, 0, 1) * Simd32x3::from([-1.0, 1.0, 0.0]) + Simd32x3::from(self.group0()[0]) * swizzle!(other.group0(), 0, 2, 1) * Simd32x3::from([0.0, -1.0, 1.0]) } }
2821    }
2822}
2823
2824impl Add<Translator> for Point {
2825    type Output = Motor;
2826
2827    fn add(self, other: Translator) -> Motor {
2828        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[1], self.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) + Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([1.0, 0.0, 1.0, 1.0]) } }
2829    }
2830}
2831
2832impl Sub<Translator> for Point {
2833    type Output = Motor;
2834
2835    fn sub(self, other: Translator) -> Motor {
2836        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[1], self.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) - Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([1.0, 0.0, 1.0, 1.0]) } }
2837    }
2838}
2839
2840impl GeometricProduct<Translator> for Point {
2841    type Output = Motor;
2842
2843    fn geometric_product(self, other: Translator) -> Motor {
2844        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[1], other.group0()[2], other.group0()[0], other.group0()[1]]) * Simd32x4::from([-1.0, 1.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[2], other.group0()[1], other.group0()[2], other.group0()[0]]) * Simd32x4::from([-1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[2], other.group0()[1]]) * Simd32x4::from([0.0, 1.0, -1.0, 1.0]) } }
2845    }
2846}
2847
2848impl RegressiveProduct<Translator> for Point {
2849    type Output = Plane;
2850
2851    fn regressive_product(self, other: Translator) -> Plane {
2852        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[2]) * Simd32x3::from(other.group0()[1]) * Simd32x3::from([1.0, 0.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0) * swizzle!(other.group0(), 2, 2, 1) * Simd32x3::from([-1.0, 1.0, -1.0]) } }
2853    }
2854}
2855
2856impl OuterProduct<Translator> for Point {
2857    type Output = Point;
2858
2859    fn outer_product(self, other: Translator) -> Point {
2860        Point { groups: PointGroups { g0: self.group0() * Simd32x3::from(other.group0()[0]) } }
2861    }
2862}
2863
2864impl InnerProduct<Translator> for Point {
2865    type Output = Motor;
2866
2867    fn inner_product(self, other: Translator) -> Motor {
2868        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[2], other.group0()[2], other.group0()[2], other.group0()[0]]) * Simd32x4::from([-1.0, 0.0, 0.0, 1.0]) + Simd32x4::from([self.group0()[1], self.group0()[0], self.group0()[1], self.group0()[0]]) * Simd32x4::from([other.group0()[1], other.group0()[0], other.group0()[0], other.group0()[0]]) * Simd32x4::from([-1.0, 1.0, 1.0, 0.0]) } }
2869    }
2870}
2871
2872impl LeftContraction<Translator> for Point {
2873    type Output = f32;
2874
2875    fn left_contraction(self, other: Translator) -> f32 {
2876        0.0 - self.group0()[1] * other.group0()[1] - self.group0()[2] * other.group0()[2]
2877    }
2878}
2879
2880impl RightContraction<Translator> for Point {
2881    type Output = Motor;
2882
2883    fn right_contraction(self, other: Translator) -> Motor {
2884        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[2], other.group0()[2], other.group0()[2], other.group0()[0]]) * Simd32x4::from([-1.0, 0.0, 0.0, 1.0]) + Simd32x4::from([self.group0()[1], self.group0()[0], self.group0()[1], self.group0()[0]]) * Simd32x4::from([other.group0()[1], other.group0()[0], other.group0()[0], other.group0()[0]]) * Simd32x4::from([-1.0, 1.0, 1.0, 0.0]) } }
2885    }
2886}
2887
2888impl ScalarProduct<Translator> for Point {
2889    type Output = f32;
2890
2891    fn scalar_product(self, other: Translator) -> f32 {
2892        0.0 - self.group0()[1] * other.group0()[1] - self.group0()[2] * other.group0()[2]
2893    }
2894}
2895
2896impl Add<Motor> for Point {
2897    type Output = Motor;
2898
2899    fn add(self, other: Motor) -> Motor {
2900        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[1], self.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) + other.group0() } }
2901    }
2902}
2903
2904impl Sub<Motor> for Point {
2905    type Output = Motor;
2906
2907    fn sub(self, other: Motor) -> Motor {
2908        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[1], self.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) - other.group0() } }
2909    }
2910}
2911
2912impl GeometricProduct<Motor> for Point {
2913    type Output = Motor;
2914
2915    fn geometric_product(self, other: Motor) -> Motor {
2916        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 2, 3, 0, 1) * Simd32x4::from([-1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([-1.0, -1.0, 1.0, 1.0]) } }
2917    }
2918}
2919
2920impl RegressiveProduct<Motor> for Point {
2921    type Output = Plane;
2922
2923    fn regressive_product(self, other: Motor) -> Plane {
2924        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[1]) * Simd32x3::from([other.group0()[3], other.group0()[3], other.group0()[1]]) * Simd32x3::from([-1.0, 0.0, 1.0]) + Simd32x3::from(self.group0()[2]) * Simd32x3::from([other.group0()[2], other.group0()[1], other.group0()[2]]) * Simd32x3::from([1.0, -1.0, 0.0]) + Simd32x3::from(self.group0()[0]) * Simd32x3::from([other.group0()[0], other.group0()[3], other.group0()[2]]) * Simd32x3::from([0.0, 1.0, -1.0]) } }
2925    }
2926}
2927
2928impl OuterProduct<Motor> for Point {
2929    type Output = Point;
2930
2931    fn outer_product(self, other: Motor) -> Point {
2932        Point { groups: PointGroups { g0: self.group0() * Simd32x3::from(other.group0()[0]) } }
2933    }
2934}
2935
2936impl InnerProduct<Motor> for Point {
2937    type Output = Motor;
2938
2939    fn inner_product(self, other: Motor) -> Motor {
2940        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([-1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[0]) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]) } }
2941    }
2942}
2943
2944impl LeftContraction<Motor> for Point {
2945    type Output = f32;
2946
2947    fn left_contraction(self, other: Motor) -> f32 {
2948        0.0 - self.group0()[0] * other.group0()[1] - self.group0()[1] * other.group0()[2] - self.group0()[2] * other.group0()[3]
2949    }
2950}
2951
2952impl RightContraction<Motor> for Point {
2953    type Output = Motor;
2954
2955    fn right_contraction(self, other: Motor) -> Motor {
2956        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([-1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[0]) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]) } }
2957    }
2958}
2959
2960impl ScalarProduct<Motor> for Point {
2961    type Output = f32;
2962
2963    fn scalar_product(self, other: Motor) -> f32 {
2964        0.0 - self.group0()[0] * other.group0()[1] - self.group0()[1] * other.group0()[2] - self.group0()[2] * other.group0()[3]
2965    }
2966}
2967
2968impl GeometricProduct<MotorDual> for Point {
2969    type Output = MotorDual;
2970
2971    fn geometric_product(self, other: MotorDual) -> MotorDual {
2972        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[0]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([1.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 2, 3, 0, 1) * Simd32x4::from([1.0, 1.0, -1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) } }
2973    }
2974}
2975
2976impl RegressiveProduct<MotorDual> for Point {
2977    type Output = Motor;
2978
2979    fn regressive_product(self, other: MotorDual) -> Motor {
2980        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[0]) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) } }
2981    }
2982}
2983
2984impl InnerProduct<MotorDual> for Point {
2985    type Output = Plane;
2986
2987    fn inner_product(self, other: MotorDual) -> Plane {
2988        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[0]) * Simd32x3::from([other.group0()[0], other.group0()[3], other.group0()[2]]) * Simd32x3::from([-1.0, -1.0, 1.0]) + Simd32x3::from(self.group0()[1]) * Simd32x3::from([other.group0()[3], other.group0()[0], other.group0()[1]]) * Simd32x3::from([1.0, -1.0, -1.0]) + Simd32x3::from(self.group0()[2]) * Simd32x3::from([other.group0()[2], other.group0()[1], other.group0()[0]]) * Simd32x3::from([-1.0, 1.0, -1.0]) } }
2989    }
2990}
2991
2992impl LeftContraction<MotorDual> for Point {
2993    type Output = Plane;
2994
2995    fn left_contraction(self, other: MotorDual) -> Plane {
2996        Plane { groups: PlaneGroups { g0: self.group0() * Simd32x3::from(other.group0()[0]) * Simd32x3::from(-1.0) } }
2997    }
2998}
2999
3000impl RightContraction<MotorDual> for Point {
3001    type Output = Plane;
3002
3003    fn right_contraction(self, other: MotorDual) -> Plane {
3004        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[1]) * Simd32x3::from([other.group0()[3], other.group0()[3], other.group0()[1]]) * Simd32x3::from([1.0, 0.0, -1.0]) + Simd32x3::from(self.group0()[2]) * Simd32x3::from([other.group0()[2], other.group0()[1], other.group0()[2]]) * Simd32x3::from([-1.0, 1.0, 0.0]) + Simd32x3::from(self.group0()[0]) * Simd32x3::from([other.group0()[0], other.group0()[3], other.group0()[2]]) * Simd32x3::from([0.0, -1.0, 1.0]) } }
3005    }
3006}
3007
3008impl SquaredMagnitude for Point {
3009    type Output = f32;
3010
3011    fn squared_magnitude(self) -> f32 {
3012        self.scalar_product(self.reversal())
3013    }
3014}
3015
3016impl Magnitude for Point {
3017    type Output = f32;
3018
3019    fn magnitude(self) -> f32 {
3020        self.squared_magnitude().sqrt()
3021    }
3022}
3023
3024impl Mul<f32> for Point {
3025    type Output = Point;
3026
3027    fn mul(self, other: f32) -> Point {
3028        self.geometric_product(other)
3029    }
3030}
3031
3032impl MulAssign<f32> for Point {
3033    fn mul_assign(&mut self, other: f32) {
3034        *self = (*self).mul(other);
3035    }
3036}
3037
3038impl Signum for Point {
3039    type Output = Point;
3040
3041    fn signum(self) -> Point {
3042        self.geometric_product(1.0 / self.magnitude())
3043    }
3044}
3045
3046impl Inverse for Point {
3047    type Output = Point;
3048
3049    fn inverse(self) -> Point {
3050        self.reversal().geometric_product(1.0 / self.squared_magnitude())
3051    }
3052}
3053
3054impl Zero for IdealPoint {
3055    fn zero() -> Self {
3056        IdealPoint { groups: IdealPointGroups { g0: Simd32x2::from(0.0) } }
3057    }
3058}
3059
3060impl One for IdealPoint {
3061    fn one() -> Self {
3062        IdealPoint { groups: IdealPointGroups { g0: Simd32x2::from(0.0) } }
3063    }
3064}
3065
3066impl Neg for IdealPoint {
3067    type Output = IdealPoint;
3068
3069    fn neg(self) -> IdealPoint {
3070        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x2::from(-1.0) } }
3071    }
3072}
3073
3074impl Automorphism for IdealPoint {
3075    type Output = IdealPoint;
3076
3077    fn automorphism(self) -> IdealPoint {
3078        IdealPoint { groups: IdealPointGroups { g0: self.group0() } }
3079    }
3080}
3081
3082impl Reversal for IdealPoint {
3083    type Output = IdealPoint;
3084
3085    fn reversal(self) -> IdealPoint {
3086        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x2::from(-1.0) } }
3087    }
3088}
3089
3090impl Conjugation for IdealPoint {
3091    type Output = IdealPoint;
3092
3093    fn conjugation(self) -> IdealPoint {
3094        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x2::from(-1.0) } }
3095    }
3096}
3097
3098impl Add<f32> for IdealPoint {
3099    type Output = Translator;
3100
3101    fn add(self, other: f32) -> Translator {
3102        Translator { groups: TranslatorGroups { g0: Simd32x3::from([self.group0()[0], self.group0()[0], self.group0()[1]]) * Simd32x3::from([0.0, 1.0, 1.0]) + Simd32x3::from(other) * Simd32x3::from([1.0, 0.0, 0.0]) } }
3103    }
3104}
3105
3106impl Sub<f32> for IdealPoint {
3107    type Output = Translator;
3108
3109    fn sub(self, other: f32) -> Translator {
3110        Translator { groups: TranslatorGroups { g0: Simd32x3::from([self.group0()[0], self.group0()[0], self.group0()[1]]) * Simd32x3::from([0.0, 1.0, 1.0]) - Simd32x3::from(other) * Simd32x3::from([1.0, 0.0, 0.0]) } }
3111    }
3112}
3113
3114impl GeometricProduct<f32> for IdealPoint {
3115    type Output = IdealPoint;
3116
3117    fn geometric_product(self, other: f32) -> IdealPoint {
3118        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x2::from(other) } }
3119    }
3120}
3121
3122impl OuterProduct<f32> for IdealPoint {
3123    type Output = IdealPoint;
3124
3125    fn outer_product(self, other: f32) -> IdealPoint {
3126        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x2::from(other) } }
3127    }
3128}
3129
3130impl InnerProduct<f32> for IdealPoint {
3131    type Output = IdealPoint;
3132
3133    fn inner_product(self, other: f32) -> IdealPoint {
3134        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x2::from(other) } }
3135    }
3136}
3137
3138impl RightContraction<f32> for IdealPoint {
3139    type Output = IdealPoint;
3140
3141    fn right_contraction(self, other: f32) -> IdealPoint {
3142        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x2::from(other) } }
3143    }
3144}
3145
3146impl Add<MultiVector> for IdealPoint {
3147    type Output = MultiVector;
3148
3149    fn add(self, other: MultiVector) -> MultiVector {
3150        MultiVector { groups: MultiVectorGroups { g0: other.group0(), g1: Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[0], self.group0()[1]]) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) + other.group1() } }
3151    }
3152}
3153
3154impl Sub<MultiVector> for IdealPoint {
3155    type Output = MultiVector;
3156
3157    fn sub(self, other: MultiVector) -> MultiVector {
3158        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(0.0) - other.group0(), g1: Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[0], self.group0()[1]]) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) - other.group1() } }
3159    }
3160}
3161
3162impl GeometricProduct<MultiVector> for IdealPoint {
3163    type Output = MultiVector;
3164
3165    fn geometric_product(self, other: MultiVector) -> MultiVector {
3166        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * swizzle!(other.group1(), 2, 3, 0, 1) * Simd32x4::from([-1.0, 1.0, -1.0, -1.0]) + Simd32x4::from(self.group0()[1]) * swizzle!(other.group1(), 3, 2, 1, 0) * Simd32x4::from([-1.0, -1.0, -1.0, 1.0]), g1: Simd32x4::from(self.group0()[0]) * swizzle!(other.group0(), 2, 3, 0, 1) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) } }
3167    }
3168}
3169
3170impl ScalarProduct<MultiVector> for IdealPoint {
3171    type Output = f32;
3172
3173    fn scalar_product(self, other: MultiVector) -> f32 {
3174        0.0 - self.group0()[0] * other.group1()[2] - self.group0()[1] * other.group1()[3]
3175    }
3176}
3177
3178impl Add<Rotor> for IdealPoint {
3179    type Output = Motor;
3180
3181    fn add(self, other: Rotor) -> Motor {
3182        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[0], self.group0()[1]]) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) + Simd32x4::from([other.group0()[0], other.group0()[1], other.group0()[0], other.group0()[0]]) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) } }
3183    }
3184}
3185
3186impl Sub<Rotor> for IdealPoint {
3187    type Output = Motor;
3188
3189    fn sub(self, other: Rotor) -> Motor {
3190        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[0], self.group0()[1]]) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) - Simd32x4::from([other.group0()[0], other.group0()[1], other.group0()[0], other.group0()[0]]) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) } }
3191    }
3192}
3193
3194impl GeometricProduct<Rotor> for IdealPoint {
3195    type Output = IdealPoint;
3196
3197    fn geometric_product(self, other: Rotor) -> IdealPoint {
3198        IdealPoint { groups: IdealPointGroups { g0: Simd32x2::from(self.group0()[0]) * other.group0() * Simd32x2::from([1.0, -1.0]) + Simd32x2::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0) } }
3199    }
3200}
3201
3202impl OuterProduct<Rotor> for IdealPoint {
3203    type Output = IdealPoint;
3204
3205    fn outer_product(self, other: Rotor) -> IdealPoint {
3206        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x2::from(other.group0()[0]) } }
3207    }
3208}
3209
3210impl InnerProduct<Rotor> for IdealPoint {
3211    type Output = IdealPoint;
3212
3213    fn inner_product(self, other: Rotor) -> IdealPoint {
3214        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x2::from(other.group0()[0]) } }
3215    }
3216}
3217
3218impl RightContraction<Rotor> for IdealPoint {
3219    type Output = IdealPoint;
3220
3221    fn right_contraction(self, other: Rotor) -> IdealPoint {
3222        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x2::from(other.group0()[0]) } }
3223    }
3224}
3225
3226impl Add<Point> for IdealPoint {
3227    type Output = Point;
3228
3229    fn add(self, other: Point) -> Point {
3230        Point { groups: PointGroups { g0: Simd32x3::from([self.group0()[0], self.group0()[0], self.group0()[1]]) * Simd32x3::from([0.0, 1.0, 1.0]) + other.group0() } }
3231    }
3232}
3233
3234impl Sub<Point> for IdealPoint {
3235    type Output = Point;
3236
3237    fn sub(self, other: Point) -> Point {
3238        Point { groups: PointGroups { g0: Simd32x3::from([self.group0()[0], self.group0()[0], self.group0()[1]]) * Simd32x3::from([0.0, 1.0, 1.0]) - other.group0() } }
3239    }
3240}
3241
3242impl GeometricProduct<Point> for IdealPoint {
3243    type Output = Motor;
3244
3245    fn geometric_product(self, other: Point) -> Motor {
3246        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[2], other.group0()[1], other.group0()[0], other.group0()[2]]) * Simd32x4::from([-1.0, -1.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group0()[1], other.group0()[2], other.group0()[0], other.group0()[0]]) * Simd32x4::from([-1.0, 1.0, 0.0, -1.0]) } }
3247    }
3248}
3249
3250impl RegressiveProduct<Point> for IdealPoint {
3251    type Output = Plane;
3252
3253    fn regressive_product(self, other: Point) -> Plane {
3254        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0, 1) * Simd32x3::from([1.0, -1.0, 0.0]) + Simd32x3::from(self.group0()[0]) * swizzle!(other.group0(), 2, 0, 0) * Simd32x3::from([-1.0, 0.0, 1.0]) } }
3255    }
3256}
3257
3258impl InnerProduct<Point> for IdealPoint {
3259    type Output = f32;
3260
3261    fn inner_product(self, other: Point) -> f32 {
3262        0.0 - self.group0()[0] * other.group0()[1] - self.group0()[1] * other.group0()[2]
3263    }
3264}
3265
3266impl LeftContraction<Point> for IdealPoint {
3267    type Output = f32;
3268
3269    fn left_contraction(self, other: Point) -> f32 {
3270        0.0 - self.group0()[0] * other.group0()[1] - self.group0()[1] * other.group0()[2]
3271    }
3272}
3273
3274impl RightContraction<Point> for IdealPoint {
3275    type Output = f32;
3276
3277    fn right_contraction(self, other: Point) -> f32 {
3278        0.0 - self.group0()[0] * other.group0()[1] - self.group0()[1] * other.group0()[2]
3279    }
3280}
3281
3282impl ScalarProduct<Point> for IdealPoint {
3283    type Output = f32;
3284
3285    fn scalar_product(self, other: Point) -> f32 {
3286        0.0 - self.group0()[0] * other.group0()[1] - self.group0()[1] * other.group0()[2]
3287    }
3288}
3289
3290impl Add<IdealPoint> for IdealPoint {
3291    type Output = IdealPoint;
3292
3293    fn add(self, other: IdealPoint) -> IdealPoint {
3294        IdealPoint { groups: IdealPointGroups { g0: self.group0() + other.group0() } }
3295    }
3296}
3297
3298impl AddAssign<IdealPoint> for IdealPoint {
3299    fn add_assign(&mut self, other: IdealPoint) {
3300        *self = (*self).add(other);
3301    }
3302}
3303
3304impl Sub<IdealPoint> for IdealPoint {
3305    type Output = IdealPoint;
3306
3307    fn sub(self, other: IdealPoint) -> IdealPoint {
3308        IdealPoint { groups: IdealPointGroups { g0: self.group0() - other.group0() } }
3309    }
3310}
3311
3312impl SubAssign<IdealPoint> for IdealPoint {
3313    fn sub_assign(&mut self, other: IdealPoint) {
3314        *self = (*self).sub(other);
3315    }
3316}
3317
3318impl Mul<IdealPoint> for IdealPoint {
3319    type Output = IdealPoint;
3320
3321    fn mul(self, other: IdealPoint) -> IdealPoint {
3322        IdealPoint { groups: IdealPointGroups { g0: self.group0() * other.group0() } }
3323    }
3324}
3325
3326impl MulAssign<IdealPoint> for IdealPoint {
3327    fn mul_assign(&mut self, other: IdealPoint) {
3328        *self = (*self).mul(other);
3329    }
3330}
3331
3332impl Div<IdealPoint> for IdealPoint {
3333    type Output = IdealPoint;
3334
3335    fn div(self, other: IdealPoint) -> IdealPoint {
3336        IdealPoint { groups: IdealPointGroups { g0: Simd32x2::from([self.group0()[0], self.group0()[1]]) * Simd32x2::from([1.0, 1.0]) / Simd32x2::from([other.group0()[0], other.group0()[1]]) * Simd32x2::from([1.0, 1.0]) } }
3337    }
3338}
3339
3340impl DivAssign<IdealPoint> for IdealPoint {
3341    fn div_assign(&mut self, other: IdealPoint) {
3342        *self = (*self).div(other);
3343    }
3344}
3345
3346impl GeometricProduct<IdealPoint> for IdealPoint {
3347    type Output = Rotor;
3348
3349    fn geometric_product(self, other: IdealPoint) -> Rotor {
3350        Rotor { groups: RotorGroups { g0: Simd32x2::from(self.group0()[0]) * other.group0() * Simd32x2::from([-1.0, 1.0]) - Simd32x2::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0) } }
3351    }
3352}
3353
3354impl InnerProduct<IdealPoint> for IdealPoint {
3355    type Output = f32;
3356
3357    fn inner_product(self, other: IdealPoint) -> f32 {
3358        0.0 - self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group0()[1]
3359    }
3360}
3361
3362impl LeftContraction<IdealPoint> for IdealPoint {
3363    type Output = f32;
3364
3365    fn left_contraction(self, other: IdealPoint) -> f32 {
3366        0.0 - self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group0()[1]
3367    }
3368}
3369
3370impl RightContraction<IdealPoint> for IdealPoint {
3371    type Output = f32;
3372
3373    fn right_contraction(self, other: IdealPoint) -> f32 {
3374        0.0 - self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group0()[1]
3375    }
3376}
3377
3378impl ScalarProduct<IdealPoint> for IdealPoint {
3379    type Output = f32;
3380
3381    fn scalar_product(self, other: IdealPoint) -> f32 {
3382        0.0 - self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group0()[1]
3383    }
3384}
3385
3386impl GeometricProduct<Plane> for IdealPoint {
3387    type Output = MotorDual;
3388
3389    fn geometric_product(self, other: Plane) -> MotorDual {
3390        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[2], other.group0()[1], other.group0()[0], other.group0()[2]]) * Simd32x4::from([1.0, -1.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group0()[1], other.group0()[2], other.group0()[0], other.group0()[0]]) * Simd32x4::from([1.0, 1.0, 0.0, -1.0]) } }
3391    }
3392}
3393
3394impl RegressiveProduct<Plane> for IdealPoint {
3395    type Output = f32;
3396
3397    fn regressive_product(self, other: Plane) -> f32 {
3398        self.group0()[0] * other.group0()[1] + self.group0()[1] * other.group0()[2]
3399    }
3400}
3401
3402impl InnerProduct<Plane> for IdealPoint {
3403    type Output = Plane;
3404
3405    fn inner_product(self, other: Plane) -> Plane {
3406        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0, 1) * Simd32x3::from([-1.0, 1.0, 0.0]) + Simd32x3::from(self.group0()[0]) * swizzle!(other.group0(), 2, 0, 0) * Simd32x3::from([1.0, 0.0, -1.0]) } }
3407    }
3408}
3409
3410impl RightContraction<Plane> for IdealPoint {
3411    type Output = Plane;
3412
3413    fn right_contraction(self, other: Plane) -> Plane {
3414        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0, 1) * Simd32x3::from([-1.0, 1.0, 0.0]) + Simd32x3::from(self.group0()[0]) * swizzle!(other.group0(), 2, 0, 0) * Simd32x3::from([1.0, 0.0, -1.0]) } }
3415    }
3416}
3417
3418impl Add<Translator> for IdealPoint {
3419    type Output = Translator;
3420
3421    fn add(self, other: Translator) -> Translator {
3422        Translator { groups: TranslatorGroups { g0: Simd32x3::from([self.group0()[0], self.group0()[0], self.group0()[1]]) * Simd32x3::from([0.0, 1.0, 1.0]) + other.group0() } }
3423    }
3424}
3425
3426impl Sub<Translator> for IdealPoint {
3427    type Output = Translator;
3428
3429    fn sub(self, other: Translator) -> Translator {
3430        Translator { groups: TranslatorGroups { g0: Simd32x3::from([self.group0()[0], self.group0()[0], self.group0()[1]]) * Simd32x3::from([0.0, 1.0, 1.0]) - other.group0() } }
3431    }
3432}
3433
3434impl GeometricProduct<Translator> for IdealPoint {
3435    type Output = Motor;
3436
3437    fn geometric_product(self, other: Translator) -> Motor {
3438        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[2], other.group0()[1], other.group0()[2], other.group0()[0]]) * Simd32x4::from([-1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group0()[1], other.group0()[2], other.group0()[0], other.group0()[0]]) * Simd32x4::from([-1.0, 1.0, 1.0, 0.0]) } }
3439    }
3440}
3441
3442impl OuterProduct<Translator> for IdealPoint {
3443    type Output = IdealPoint;
3444
3445    fn outer_product(self, other: Translator) -> IdealPoint {
3446        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x2::from(other.group0()[0]) } }
3447    }
3448}
3449
3450impl InnerProduct<Translator> for IdealPoint {
3451    type Output = Translator;
3452
3453    fn inner_product(self, other: Translator) -> Translator {
3454        Translator { groups: TranslatorGroups { g0: Simd32x3::from(self.group0()[1]) * swizzle!(other.group0(), 2, 2, 0) * Simd32x3::from([-1.0, 0.0, 1.0]) + Simd32x3::from(self.group0()[0]) * swizzle!(other.group0(), 1, 0, 0) * Simd32x3::from([-1.0, 1.0, 0.0]) } }
3455    }
3456}
3457
3458impl LeftContraction<Translator> for IdealPoint {
3459    type Output = f32;
3460
3461    fn left_contraction(self, other: Translator) -> f32 {
3462        0.0 - self.group0()[0] * other.group0()[1] - self.group0()[1] * other.group0()[2]
3463    }
3464}
3465
3466impl RightContraction<Translator> for IdealPoint {
3467    type Output = Translator;
3468
3469    fn right_contraction(self, other: Translator) -> Translator {
3470        Translator { groups: TranslatorGroups { g0: Simd32x3::from(self.group0()[1]) * swizzle!(other.group0(), 2, 2, 0) * Simd32x3::from([-1.0, 0.0, 1.0]) + Simd32x3::from(self.group0()[0]) * swizzle!(other.group0(), 1, 0, 0) * Simd32x3::from([-1.0, 1.0, 0.0]) } }
3471    }
3472}
3473
3474impl ScalarProduct<Translator> for IdealPoint {
3475    type Output = f32;
3476
3477    fn scalar_product(self, other: Translator) -> f32 {
3478        0.0 - self.group0()[0] * other.group0()[1] - self.group0()[1] * other.group0()[2]
3479    }
3480}
3481
3482impl Add<Motor> for IdealPoint {
3483    type Output = Motor;
3484
3485    fn add(self, other: Motor) -> Motor {
3486        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[0], self.group0()[1]]) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) + other.group0() } }
3487    }
3488}
3489
3490impl Sub<Motor> for IdealPoint {
3491    type Output = Motor;
3492
3493    fn sub(self, other: Motor) -> Motor {
3494        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[0], self.group0()[1]]) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) - other.group0() } }
3495    }
3496}
3497
3498impl GeometricProduct<Motor> for IdealPoint {
3499    type Output = Motor;
3500
3501    fn geometric_product(self, other: Motor) -> Motor {
3502        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * swizzle!(other.group0(), 2, 3, 0, 1) * Simd32x4::from([-1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([-1.0, -1.0, 1.0, 1.0]) } }
3503    }
3504}
3505
3506impl RegressiveProduct<Motor> for IdealPoint {
3507    type Output = Plane;
3508
3509    fn regressive_product(self, other: Motor) -> Plane {
3510        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[1]) * Simd32x3::from([other.group0()[2], other.group0()[1], other.group0()[2]]) * Simd32x3::from([1.0, -1.0, 0.0]) + Simd32x3::from(self.group0()[0]) * Simd32x3::from([other.group0()[3], other.group0()[0], other.group0()[1]]) * Simd32x3::from([-1.0, 0.0, 1.0]) } }
3511    }
3512}
3513
3514impl OuterProduct<Motor> for IdealPoint {
3515    type Output = IdealPoint;
3516
3517    fn outer_product(self, other: Motor) -> IdealPoint {
3518        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x2::from(other.group0()[0]) } }
3519    }
3520}
3521
3522impl InnerProduct<Motor> for IdealPoint {
3523    type Output = Translator;
3524
3525    fn inner_product(self, other: Motor) -> Translator {
3526        Translator { groups: TranslatorGroups { g0: Simd32x3::from(self.group0()[1]) * Simd32x3::from([other.group0()[3], other.group0()[3], other.group0()[0]]) * Simd32x3::from([-1.0, 0.0, 1.0]) + Simd32x3::from(self.group0()[0]) * Simd32x3::from([other.group0()[2], other.group0()[0], other.group0()[0]]) * Simd32x3::from([-1.0, 1.0, 0.0]) } }
3527    }
3528}
3529
3530impl LeftContraction<Motor> for IdealPoint {
3531    type Output = f32;
3532
3533    fn left_contraction(self, other: Motor) -> f32 {
3534        0.0 - self.group0()[0] * other.group0()[2] - self.group0()[1] * other.group0()[3]
3535    }
3536}
3537
3538impl RightContraction<Motor> for IdealPoint {
3539    type Output = Translator;
3540
3541    fn right_contraction(self, other: Motor) -> Translator {
3542        Translator { groups: TranslatorGroups { g0: Simd32x3::from(self.group0()[1]) * Simd32x3::from([other.group0()[3], other.group0()[3], other.group0()[0]]) * Simd32x3::from([-1.0, 0.0, 1.0]) + Simd32x3::from(self.group0()[0]) * Simd32x3::from([other.group0()[2], other.group0()[0], other.group0()[0]]) * Simd32x3::from([-1.0, 1.0, 0.0]) } }
3543    }
3544}
3545
3546impl ScalarProduct<Motor> for IdealPoint {
3547    type Output = f32;
3548
3549    fn scalar_product(self, other: Motor) -> f32 {
3550        0.0 - self.group0()[0] * other.group0()[2] - self.group0()[1] * other.group0()[3]
3551    }
3552}
3553
3554impl GeometricProduct<MotorDual> for IdealPoint {
3555    type Output = MotorDual;
3556
3557    fn geometric_product(self, other: MotorDual) -> MotorDual {
3558        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[0]) * swizzle!(other.group0(), 2, 3, 0, 1) * Simd32x4::from([1.0, 1.0, -1.0, -1.0]) + Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) } }
3559    }
3560}
3561
3562impl RegressiveProduct<MotorDual> for IdealPoint {
3563    type Output = Translator;
3564
3565    fn regressive_product(self, other: MotorDual) -> Translator {
3566        Translator { groups: TranslatorGroups { g0: Simd32x3::from(self.group0()[1]) * Simd32x3::from([other.group0()[3], other.group0()[3], other.group0()[0]]) * Simd32x3::from([1.0, 0.0, 1.0]) + Simd32x3::from(self.group0()[0]) * Simd32x3::from([other.group0()[2], other.group0()[0], other.group0()[0]]) * Simd32x3::from([1.0, 1.0, 0.0]) } }
3567    }
3568}
3569
3570impl InnerProduct<MotorDual> for IdealPoint {
3571    type Output = Plane;
3572
3573    fn inner_product(self, other: MotorDual) -> Plane {
3574        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[0]) * Simd32x3::from([other.group0()[3], other.group0()[0], other.group0()[1]]) * Simd32x3::from([1.0, -1.0, -1.0]) + Simd32x3::from(self.group0()[1]) * Simd32x3::from([other.group0()[2], other.group0()[1], other.group0()[0]]) * Simd32x3::from([-1.0, 1.0, -1.0]) } }
3575    }
3576}
3577
3578impl RightContraction<MotorDual> for IdealPoint {
3579    type Output = Plane;
3580
3581    fn right_contraction(self, other: MotorDual) -> Plane {
3582        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[1]) * Simd32x3::from([other.group0()[2], other.group0()[1], other.group0()[2]]) * Simd32x3::from([-1.0, 1.0, 0.0]) + Simd32x3::from(self.group0()[0]) * Simd32x3::from([other.group0()[3], other.group0()[0], other.group0()[1]]) * Simd32x3::from([1.0, 0.0, -1.0]) } }
3583    }
3584}
3585
3586impl SquaredMagnitude for IdealPoint {
3587    type Output = f32;
3588
3589    fn squared_magnitude(self) -> f32 {
3590        self.scalar_product(self.reversal())
3591    }
3592}
3593
3594impl Magnitude for IdealPoint {
3595    type Output = f32;
3596
3597    fn magnitude(self) -> f32 {
3598        self.squared_magnitude().sqrt()
3599    }
3600}
3601
3602impl Mul<f32> for IdealPoint {
3603    type Output = IdealPoint;
3604
3605    fn mul(self, other: f32) -> IdealPoint {
3606        self.geometric_product(other)
3607    }
3608}
3609
3610impl MulAssign<f32> for IdealPoint {
3611    fn mul_assign(&mut self, other: f32) {
3612        *self = (*self).mul(other);
3613    }
3614}
3615
3616impl Signum for IdealPoint {
3617    type Output = IdealPoint;
3618
3619    fn signum(self) -> IdealPoint {
3620        self.geometric_product(1.0 / self.magnitude())
3621    }
3622}
3623
3624impl Inverse for IdealPoint {
3625    type Output = IdealPoint;
3626
3627    fn inverse(self) -> IdealPoint {
3628        self.reversal().geometric_product(1.0 / self.squared_magnitude())
3629    }
3630}
3631
3632impl Zero for Plane {
3633    fn zero() -> Self {
3634        Plane { groups: PlaneGroups { g0: Simd32x3::from(0.0) } }
3635    }
3636}
3637
3638impl One for Plane {
3639    fn one() -> Self {
3640        Plane { groups: PlaneGroups { g0: Simd32x3::from(0.0) } }
3641    }
3642}
3643
3644impl Neg for Plane {
3645    type Output = Plane;
3646
3647    fn neg(self) -> Plane {
3648        Plane { groups: PlaneGroups { g0: self.group0() * Simd32x3::from(-1.0) } }
3649    }
3650}
3651
3652impl Automorphism for Plane {
3653    type Output = Plane;
3654
3655    fn automorphism(self) -> Plane {
3656        Plane { groups: PlaneGroups { g0: self.group0() * Simd32x3::from(-1.0) } }
3657    }
3658}
3659
3660impl Reversal for Plane {
3661    type Output = Plane;
3662
3663    fn reversal(self) -> Plane {
3664        Plane { groups: PlaneGroups { g0: self.group0() } }
3665    }
3666}
3667
3668impl Conjugation for Plane {
3669    type Output = Plane;
3670
3671    fn conjugation(self) -> Plane {
3672        Plane { groups: PlaneGroups { g0: self.group0() * Simd32x3::from(-1.0) } }
3673    }
3674}
3675
3676impl Dual for Plane {
3677    type Output = Point;
3678
3679    fn dual(self) -> Point {
3680        Point { groups: PointGroups { g0: self.group0() } }
3681    }
3682}
3683
3684impl GeometricProduct<f32> for Plane {
3685    type Output = Plane;
3686
3687    fn geometric_product(self, other: f32) -> Plane {
3688        Plane { groups: PlaneGroups { g0: self.group0() * Simd32x3::from(other) } }
3689    }
3690}
3691
3692impl OuterProduct<f32> for Plane {
3693    type Output = Plane;
3694
3695    fn outer_product(self, other: f32) -> Plane {
3696        Plane { groups: PlaneGroups { g0: self.group0() * Simd32x3::from(other) } }
3697    }
3698}
3699
3700impl InnerProduct<f32> for Plane {
3701    type Output = Plane;
3702
3703    fn inner_product(self, other: f32) -> Plane {
3704        Plane { groups: PlaneGroups { g0: self.group0() * Simd32x3::from(other) } }
3705    }
3706}
3707
3708impl RightContraction<f32> for Plane {
3709    type Output = Plane;
3710
3711    fn right_contraction(self, other: f32) -> Plane {
3712        Plane { groups: PlaneGroups { g0: self.group0() * Simd32x3::from(other) } }
3713    }
3714}
3715
3716impl Add<MultiVector> for Plane {
3717    type Output = MultiVector;
3718
3719    fn add(self, other: MultiVector) -> MultiVector {
3720        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[2], self.group0()[1]]) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) + other.group0(), g1: Simd32x4::from(self.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + other.group1() } }
3721    }
3722}
3723
3724impl Sub<MultiVector> for Plane {
3725    type Output = MultiVector;
3726
3727    fn sub(self, other: MultiVector) -> MultiVector {
3728        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[2], self.group0()[1]]) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) - other.group0(), g1: Simd32x4::from(self.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) - other.group1() } }
3729    }
3730}
3731
3732impl GeometricProduct<MultiVector> for Plane {
3733    type Output = MultiVector;
3734
3735    fn geometric_product(self, other: MultiVector) -> MultiVector {
3736        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group1() * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([1.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 3, 0, 1), g1: Simd32x4::from(self.group0()[0]) * other.group0() * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[1]) * swizzle!(other.group1(), 3, 2, 1, 0) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group1(), 2, 3, 0, 1) * Simd32x4::from([-1.0, 1.0, -1.0, 1.0]) } }
3737    }
3738}
3739
3740impl ScalarProduct<MultiVector> for Plane {
3741    type Output = f32;
3742
3743    fn scalar_product(self, other: MultiVector) -> f32 {
3744        self.group0()[0] * other.group1()[0] + self.group0()[1] * other.group0()[3] + self.group0()[2] * other.group0()[2]
3745    }
3746}
3747
3748impl GeometricProduct<Rotor> for Plane {
3749    type Output = MotorDual;
3750
3751    fn geometric_product(self, other: Rotor) -> MotorDual {
3752        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[1], other.group0()[1], other.group0()[1], other.group0()[0]]) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) + Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[1], self.group0()[1]]) * Simd32x4::from([other.group0()[1], other.group0()[0], other.group0()[0], other.group0()[1]]) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) } }
3753    }
3754}
3755
3756impl RegressiveProduct<Rotor> for Plane {
3757    type Output = f32;
3758
3759    fn regressive_product(self, other: Rotor) -> f32 {
3760        self.group0()[0] * other.group0()[1]
3761    }
3762}
3763
3764impl OuterProduct<Rotor> for Plane {
3765    type Output = MotorDual;
3766
3767    fn outer_product(self, other: Rotor) -> MotorDual {
3768        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[1], self.group0()[2]]) * Simd32x4::from([other.group0()[1], other.group0()[0], other.group0()[0], other.group0()[0]]) } }
3769    }
3770}
3771
3772impl InnerProduct<Rotor> for Plane {
3773    type Output = Plane;
3774
3775    fn inner_product(self, other: Rotor) -> Plane {
3776        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[2]) * Simd32x3::from([other.group0()[1], other.group0()[1], other.group0()[0]]) * Simd32x3::from([0.0, 1.0, 1.0]) + swizzle!(self.group0(), 0, 1, 1) * Simd32x3::from([other.group0()[0], other.group0()[0], other.group0()[1]]) * Simd32x3::from([1.0, 1.0, -1.0]) } }
3777    }
3778}
3779
3780impl RightContraction<Rotor> for Plane {
3781    type Output = Plane;
3782
3783    fn right_contraction(self, other: Rotor) -> Plane {
3784        Plane { groups: PlaneGroups { g0: self.group0() * Simd32x3::from(other.group0()[0]) } }
3785    }
3786}
3787
3788impl GeometricProduct<Point> for Plane {
3789    type Output = MotorDual;
3790
3791    fn geometric_product(self, other: Point) -> MotorDual {
3792        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[1], other.group0()[2], other.group0()[1], other.group0()[0]]) * Simd32x4::from([1.0, 1.0, 0.0, -1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[2], other.group0()[1], other.group0()[0], other.group0()[2]]) * Simd32x4::from([1.0, -1.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[2], other.group0()[1]]) * Simd32x4::from([1.0, 0.0, -1.0, 1.0]) } }
3793    }
3794}
3795
3796impl RegressiveProduct<Point> for Plane {
3797    type Output = f32;
3798
3799    fn regressive_product(self, other: Point) -> f32 {
3800        self.group0()[0] * other.group0()[0] + self.group0()[1] * other.group0()[1] + self.group0()[2] * other.group0()[2]
3801    }
3802}
3803
3804impl InnerProduct<Point> for Plane {
3805    type Output = Plane;
3806
3807    fn inner_product(self, other: Point) -> Plane {
3808        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[1]) * swizzle!(other.group0(), 2, 2, 0) * Simd32x3::from([1.0, 0.0, -1.0]) + Simd32x3::from(self.group0()[2]) * swizzle!(other.group0(), 1, 0, 1) * Simd32x3::from([-1.0, 1.0, 0.0]) + Simd32x3::from(self.group0()[0]) * swizzle!(other.group0(), 0, 2, 1) * Simd32x3::from([0.0, -1.0, 1.0]) } }
3809    }
3810}
3811
3812impl LeftContraction<Point> for Plane {
3813    type Output = Plane;
3814
3815    fn left_contraction(self, other: Point) -> Plane {
3816        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[1]) * swizzle!(other.group0(), 2, 2, 0) * Simd32x3::from([1.0, 0.0, -1.0]) + Simd32x3::from(self.group0()[2]) * swizzle!(other.group0(), 1, 0, 1) * Simd32x3::from([-1.0, 1.0, 0.0]) + Simd32x3::from(self.group0()[0]) * swizzle!(other.group0(), 0, 2, 1) * Simd32x3::from([0.0, -1.0, 1.0]) } }
3817    }
3818}
3819
3820impl GeometricProduct<IdealPoint> for Plane {
3821    type Output = MotorDual;
3822
3823    fn geometric_product(self, other: IdealPoint) -> MotorDual {
3824        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[1], other.group0()[0], other.group0()[1], other.group0()[1]]) * Simd32x4::from([1.0, -1.0, 0.0, 0.0]) + Simd32x4::from([self.group0()[1], self.group0()[1], self.group0()[0], self.group0()[0]]) * Simd32x4::from([other.group0()[0], other.group0()[1], other.group0()[1], other.group0()[0]]) * Simd32x4::from([1.0, 1.0, -1.0, 1.0]) } }
3825    }
3826}
3827
3828impl RegressiveProduct<IdealPoint> for Plane {
3829    type Output = f32;
3830
3831    fn regressive_product(self, other: IdealPoint) -> f32 {
3832        self.group0()[1] * other.group0()[0] + self.group0()[2] * other.group0()[1]
3833    }
3834}
3835
3836impl InnerProduct<IdealPoint> for Plane {
3837    type Output = Plane;
3838
3839    fn inner_product(self, other: IdealPoint) -> Plane {
3840        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[2]) * Simd32x3::from(other.group0()[0]) * Simd32x3::from([-1.0, 0.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0) * Simd32x3::from([other.group0()[1], other.group0()[1], other.group0()[0]]) * Simd32x3::from([1.0, -1.0, 1.0]) } }
3841    }
3842}
3843
3844impl LeftContraction<IdealPoint> for Plane {
3845    type Output = Plane;
3846
3847    fn left_contraction(self, other: IdealPoint) -> Plane {
3848        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[2]) * Simd32x3::from(other.group0()[0]) * Simd32x3::from([-1.0, 0.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0) * Simd32x3::from([other.group0()[1], other.group0()[1], other.group0()[0]]) * Simd32x3::from([1.0, -1.0, 1.0]) } }
3849    }
3850}
3851
3852impl Add<Plane> for Plane {
3853    type Output = Plane;
3854
3855    fn add(self, other: Plane) -> Plane {
3856        Plane { groups: PlaneGroups { g0: self.group0() + other.group0() } }
3857    }
3858}
3859
3860impl AddAssign<Plane> for Plane {
3861    fn add_assign(&mut self, other: Plane) {
3862        *self = (*self).add(other);
3863    }
3864}
3865
3866impl Sub<Plane> for Plane {
3867    type Output = Plane;
3868
3869    fn sub(self, other: Plane) -> Plane {
3870        Plane { groups: PlaneGroups { g0: self.group0() - other.group0() } }
3871    }
3872}
3873
3874impl SubAssign<Plane> for Plane {
3875    fn sub_assign(&mut self, other: Plane) {
3876        *self = (*self).sub(other);
3877    }
3878}
3879
3880impl Mul<Plane> for Plane {
3881    type Output = Plane;
3882
3883    fn mul(self, other: Plane) -> Plane {
3884        Plane { groups: PlaneGroups { g0: self.group0() * other.group0() } }
3885    }
3886}
3887
3888impl MulAssign<Plane> for Plane {
3889    fn mul_assign(&mut self, other: Plane) {
3890        *self = (*self).mul(other);
3891    }
3892}
3893
3894impl Div<Plane> for Plane {
3895    type Output = Plane;
3896
3897    fn div(self, other: Plane) -> Plane {
3898        Plane { groups: PlaneGroups { g0: Simd32x3::from([self.group0()[0], self.group0()[1], self.group0()[2]]) * Simd32x3::from([1.0, 1.0, 1.0]) / Simd32x3::from([other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x3::from([1.0, 1.0, 1.0]) } }
3899    }
3900}
3901
3902impl DivAssign<Plane> for Plane {
3903    fn div_assign(&mut self, other: Plane) {
3904        *self = (*self).div(other);
3905    }
3906}
3907
3908impl GeometricProduct<Plane> for Plane {
3909    type Output = Motor;
3910
3911    fn geometric_product(self, other: Plane) -> Motor {
3912        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[1], other.group0()[2], other.group0()[1], other.group0()[0]]) * Simd32x4::from([1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[2], other.group0()[1], other.group0()[0], other.group0()[2]]) * Simd32x4::from([1.0, 1.0, -1.0, 0.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[2], other.group0()[1]]) * Simd32x4::from([1.0, 0.0, 1.0, -1.0]) } }
3913    }
3914}
3915
3916impl OuterProduct<Plane> for Plane {
3917    type Output = Point;
3918
3919    fn outer_product(self, other: Plane) -> Point {
3920        Point { groups: PointGroups { g0: Simd32x3::from(self.group0()[1]) * swizzle!(other.group0(), 2, 2, 0) * Simd32x3::from([-1.0, 0.0, 1.0]) + Simd32x3::from(self.group0()[2]) * swizzle!(other.group0(), 1, 0, 1) * Simd32x3::from([1.0, -1.0, 0.0]) + Simd32x3::from(self.group0()[0]) * swizzle!(other.group0(), 0, 2, 1) * Simd32x3::from([0.0, 1.0, -1.0]) } }
3921    }
3922}
3923
3924impl InnerProduct<Plane> for Plane {
3925    type Output = f32;
3926
3927    fn inner_product(self, other: Plane) -> f32 {
3928        self.group0()[0] * other.group0()[0] + self.group0()[1] * other.group0()[1] + self.group0()[2] * other.group0()[2]
3929    }
3930}
3931
3932impl LeftContraction<Plane> for Plane {
3933    type Output = f32;
3934
3935    fn left_contraction(self, other: Plane) -> f32 {
3936        self.group0()[0] * other.group0()[0] + self.group0()[1] * other.group0()[1] + self.group0()[2] * other.group0()[2]
3937    }
3938}
3939
3940impl RightContraction<Plane> for Plane {
3941    type Output = f32;
3942
3943    fn right_contraction(self, other: Plane) -> f32 {
3944        self.group0()[0] * other.group0()[0] + self.group0()[1] * other.group0()[1] + self.group0()[2] * other.group0()[2]
3945    }
3946}
3947
3948impl ScalarProduct<Plane> for Plane {
3949    type Output = f32;
3950
3951    fn scalar_product(self, other: Plane) -> f32 {
3952        self.group0()[0] * other.group0()[0] + self.group0()[1] * other.group0()[1] + self.group0()[2] * other.group0()[2]
3953    }
3954}
3955
3956impl GeometricProduct<Translator> for Plane {
3957    type Output = MotorDual;
3958
3959    fn geometric_product(self, other: Translator) -> MotorDual {
3960        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[1], other.group0()[2], other.group0()[0], other.group0()[1]]) * Simd32x4::from([1.0, 1.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[2], other.group0()[1], other.group0()[2], other.group0()[0]]) * Simd32x4::from([1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[2], other.group0()[1]]) * Simd32x4::from([0.0, 1.0, -1.0, 1.0]) } }
3961    }
3962}
3963
3964impl RegressiveProduct<Translator> for Plane {
3965    type Output = f32;
3966
3967    fn regressive_product(self, other: Translator) -> f32 {
3968        self.group0()[1] * other.group0()[1] + self.group0()[2] * other.group0()[2]
3969    }
3970}
3971
3972impl OuterProduct<Translator> for Plane {
3973    type Output = MotorDual;
3974
3975    fn outer_product(self, other: Translator) -> MotorDual {
3976        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[2], other.group0()[2], other.group0()[2], other.group0()[0]]) * Simd32x4::from([1.0, 0.0, 0.0, 1.0]) + Simd32x4::from([self.group0()[1], self.group0()[0], self.group0()[1], self.group0()[0]]) * Simd32x4::from([other.group0()[1], other.group0()[0], other.group0()[0], other.group0()[0]]) * Simd32x4::from([1.0, 1.0, 1.0, 0.0]) } }
3977    }
3978}
3979
3980impl InnerProduct<Translator> for Plane {
3981    type Output = Plane;
3982
3983    fn inner_product(self, other: Translator) -> Plane {
3984        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[0]) * swizzle!(other.group0(), 0, 2, 1) * Simd32x3::from([1.0, -1.0, 1.0]) + Simd32x3::from(self.group0()[2]) * swizzle!(other.group0(), 1, 1, 0) * Simd32x3::from([-1.0, 0.0, 1.0]) + swizzle!(self.group0(), 1, 1, 0) * swizzle!(other.group0(), 2, 0, 0) * Simd32x3::from([1.0, 1.0, 0.0]) } }
3985    }
3986}
3987
3988impl LeftContraction<Translator> for Plane {
3989    type Output = Plane;
3990
3991    fn left_contraction(self, other: Translator) -> Plane {
3992        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[2]) * Simd32x3::from(other.group0()[1]) * Simd32x3::from([-1.0, 0.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0) * swizzle!(other.group0(), 2, 2, 1) * Simd32x3::from([1.0, -1.0, 1.0]) } }
3993    }
3994}
3995
3996impl RightContraction<Translator> for Plane {
3997    type Output = Plane;
3998
3999    fn right_contraction(self, other: Translator) -> Plane {
4000        Plane { groups: PlaneGroups { g0: self.group0() * Simd32x3::from(other.group0()[0]) } }
4001    }
4002}
4003
4004impl GeometricProduct<Motor> for Plane {
4005    type Output = MotorDual;
4006
4007    fn geometric_product(self, other: Motor) -> MotorDual {
4008        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[0]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([1.0, 1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 2, 3, 0, 1) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([1.0, -1.0, 1.0, 1.0]) } }
4009    }
4010}
4011
4012impl RegressiveProduct<Motor> for Plane {
4013    type Output = f32;
4014
4015    fn regressive_product(self, other: Motor) -> f32 {
4016        self.group0()[0] * other.group0()[1] + self.group0()[1] * other.group0()[2] + self.group0()[2] * other.group0()[3]
4017    }
4018}
4019
4020impl OuterProduct<Motor> for Plane {
4021    type Output = MotorDual;
4022
4023    fn outer_product(self, other: Motor) -> MotorDual {
4024        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[0]) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) } }
4025    }
4026}
4027
4028impl InnerProduct<Motor> for Plane {
4029    type Output = Plane;
4030
4031    fn inner_product(self, other: Motor) -> Plane {
4032        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[0]) * Simd32x3::from([other.group0()[0], other.group0()[3], other.group0()[2]]) * Simd32x3::from([1.0, -1.0, 1.0]) + Simd32x3::from(self.group0()[1]) * Simd32x3::from([other.group0()[3], other.group0()[0], other.group0()[1]]) * Simd32x3::from([1.0, 1.0, -1.0]) + Simd32x3::from(self.group0()[2]) * Simd32x3::from([other.group0()[2], other.group0()[1], other.group0()[0]]) * Simd32x3::from([-1.0, 1.0, 1.0]) } }
4033    }
4034}
4035
4036impl LeftContraction<Motor> for Plane {
4037    type Output = Plane;
4038
4039    fn left_contraction(self, other: Motor) -> Plane {
4040        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[1]) * Simd32x3::from([other.group0()[3], other.group0()[3], other.group0()[1]]) * Simd32x3::from([1.0, 0.0, -1.0]) + Simd32x3::from(self.group0()[2]) * Simd32x3::from([other.group0()[2], other.group0()[1], other.group0()[2]]) * Simd32x3::from([-1.0, 1.0, 0.0]) + Simd32x3::from(self.group0()[0]) * Simd32x3::from([other.group0()[0], other.group0()[3], other.group0()[2]]) * Simd32x3::from([0.0, -1.0, 1.0]) } }
4041    }
4042}
4043
4044impl RightContraction<Motor> for Plane {
4045    type Output = Plane;
4046
4047    fn right_contraction(self, other: Motor) -> Plane {
4048        Plane { groups: PlaneGroups { g0: self.group0() * Simd32x3::from(other.group0()[0]) } }
4049    }
4050}
4051
4052impl Add<MotorDual> for Plane {
4053    type Output = MotorDual;
4054
4055    fn add(self, other: MotorDual) -> MotorDual {
4056        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[1], self.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) + other.group0() } }
4057    }
4058}
4059
4060impl Sub<MotorDual> for Plane {
4061    type Output = MotorDual;
4062
4063    fn sub(self, other: MotorDual) -> MotorDual {
4064        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[1], self.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) - other.group0() } }
4065    }
4066}
4067
4068impl GeometricProduct<MotorDual> for Plane {
4069    type Output = Motor;
4070
4071    fn geometric_product(self, other: MotorDual) -> Motor {
4072        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 2, 3, 0, 1) * Simd32x4::from([1.0, -1.0, 1.0, 1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([1.0, 1.0, -1.0, 1.0]) } }
4073    }
4074}
4075
4076impl RegressiveProduct<MotorDual> for Plane {
4077    type Output = Plane;
4078
4079    fn regressive_product(self, other: MotorDual) -> Plane {
4080        Plane { groups: PlaneGroups { g0: self.group0() * Simd32x3::from(other.group0()[0]) } }
4081    }
4082}
4083
4084impl OuterProduct<MotorDual> for Plane {
4085    type Output = Point;
4086
4087    fn outer_product(self, other: MotorDual) -> Point {
4088        Point { groups: PointGroups { g0: Simd32x3::from(self.group0()[1]) * Simd32x3::from([other.group0()[3], other.group0()[3], other.group0()[1]]) * Simd32x3::from([-1.0, 0.0, 1.0]) + Simd32x3::from(self.group0()[2]) * Simd32x3::from([other.group0()[2], other.group0()[1], other.group0()[2]]) * Simd32x3::from([1.0, -1.0, 0.0]) + Simd32x3::from(self.group0()[0]) * Simd32x3::from([other.group0()[0], other.group0()[3], other.group0()[2]]) * Simd32x3::from([0.0, 1.0, -1.0]) } }
4089    }
4090}
4091
4092impl InnerProduct<MotorDual> for Plane {
4093    type Output = Motor;
4094
4095    fn inner_product(self, other: MotorDual) -> Motor {
4096        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[0]) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) } }
4097    }
4098}
4099
4100impl LeftContraction<MotorDual> for Plane {
4101    type Output = Motor;
4102
4103    fn left_contraction(self, other: MotorDual) -> Motor {
4104        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[0]) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) } }
4105    }
4106}
4107
4108impl RightContraction<MotorDual> for Plane {
4109    type Output = f32;
4110
4111    fn right_contraction(self, other: MotorDual) -> f32 {
4112        self.group0()[0] * other.group0()[1] + self.group0()[1] * other.group0()[2] + self.group0()[2] * other.group0()[3]
4113    }
4114}
4115
4116impl ScalarProduct<MotorDual> for Plane {
4117    type Output = f32;
4118
4119    fn scalar_product(self, other: MotorDual) -> f32 {
4120        self.group0()[0] * other.group0()[1] + self.group0()[1] * other.group0()[2] + self.group0()[2] * other.group0()[3]
4121    }
4122}
4123
4124impl SquaredMagnitude for Plane {
4125    type Output = f32;
4126
4127    fn squared_magnitude(self) -> f32 {
4128        self.scalar_product(self.reversal())
4129    }
4130}
4131
4132impl Magnitude for Plane {
4133    type Output = f32;
4134
4135    fn magnitude(self) -> f32 {
4136        self.squared_magnitude().sqrt()
4137    }
4138}
4139
4140impl Mul<f32> for Plane {
4141    type Output = Plane;
4142
4143    fn mul(self, other: f32) -> Plane {
4144        self.geometric_product(other)
4145    }
4146}
4147
4148impl MulAssign<f32> for Plane {
4149    fn mul_assign(&mut self, other: f32) {
4150        *self = (*self).mul(other);
4151    }
4152}
4153
4154impl Signum for Plane {
4155    type Output = Plane;
4156
4157    fn signum(self) -> Plane {
4158        self.geometric_product(1.0 / self.magnitude())
4159    }
4160}
4161
4162impl Inverse for Plane {
4163    type Output = Plane;
4164
4165    fn inverse(self) -> Plane {
4166        self.reversal().geometric_product(1.0 / self.squared_magnitude())
4167    }
4168}
4169
4170impl Zero for Translator {
4171    fn zero() -> Self {
4172        Translator { groups: TranslatorGroups { g0: Simd32x3::from(0.0) } }
4173    }
4174}
4175
4176impl One for Translator {
4177    fn one() -> Self {
4178        Translator { groups: TranslatorGroups { g0: Simd32x3::from([1.0, 0.0, 0.0]) } }
4179    }
4180}
4181
4182impl Neg for Translator {
4183    type Output = Translator;
4184
4185    fn neg(self) -> Translator {
4186        Translator { groups: TranslatorGroups { g0: self.group0() * Simd32x3::from(-1.0) } }
4187    }
4188}
4189
4190impl Automorphism for Translator {
4191    type Output = Translator;
4192
4193    fn automorphism(self) -> Translator {
4194        Translator { groups: TranslatorGroups { g0: self.group0() } }
4195    }
4196}
4197
4198impl Reversal for Translator {
4199    type Output = Translator;
4200
4201    fn reversal(self) -> Translator {
4202        Translator { groups: TranslatorGroups { g0: self.group0() * Simd32x3::from([1.0, -1.0, -1.0]) } }
4203    }
4204}
4205
4206impl Conjugation for Translator {
4207    type Output = Translator;
4208
4209    fn conjugation(self) -> Translator {
4210        Translator { groups: TranslatorGroups { g0: self.group0() * Simd32x3::from([1.0, -1.0, -1.0]) } }
4211    }
4212}
4213
4214impl Into<f32> for Translator {
4215    fn into(self) -> f32 {
4216        self.group0()[0]
4217    }
4218}
4219
4220impl Add<f32> for Translator {
4221    type Output = Translator;
4222
4223    fn add(self, other: f32) -> Translator {
4224        Translator { groups: TranslatorGroups { g0: self.group0() + Simd32x3::from(other) * Simd32x3::from([1.0, 0.0, 0.0]) } }
4225    }
4226}
4227
4228impl AddAssign<f32> for Translator {
4229    fn add_assign(&mut self, other: f32) {
4230        *self = (*self).add(other);
4231    }
4232}
4233
4234impl Sub<f32> for Translator {
4235    type Output = Translator;
4236
4237    fn sub(self, other: f32) -> Translator {
4238        Translator { groups: TranslatorGroups { g0: self.group0() - Simd32x3::from(other) * Simd32x3::from([1.0, 0.0, 0.0]) } }
4239    }
4240}
4241
4242impl SubAssign<f32> for Translator {
4243    fn sub_assign(&mut self, other: f32) {
4244        *self = (*self).sub(other);
4245    }
4246}
4247
4248impl GeometricProduct<f32> for Translator {
4249    type Output = Translator;
4250
4251    fn geometric_product(self, other: f32) -> Translator {
4252        Translator { groups: TranslatorGroups { g0: self.group0() * Simd32x3::from(other) } }
4253    }
4254}
4255
4256impl OuterProduct<f32> for Translator {
4257    type Output = Translator;
4258
4259    fn outer_product(self, other: f32) -> Translator {
4260        Translator { groups: TranslatorGroups { g0: self.group0() * Simd32x3::from(other) } }
4261    }
4262}
4263
4264impl InnerProduct<f32> for Translator {
4265    type Output = Translator;
4266
4267    fn inner_product(self, other: f32) -> Translator {
4268        Translator { groups: TranslatorGroups { g0: self.group0() * Simd32x3::from(other) } }
4269    }
4270}
4271
4272impl LeftContraction<f32> for Translator {
4273    type Output = f32;
4274
4275    fn left_contraction(self, other: f32) -> f32 {
4276        self.group0()[0] * other
4277    }
4278}
4279
4280impl RightContraction<f32> for Translator {
4281    type Output = Translator;
4282
4283    fn right_contraction(self, other: f32) -> Translator {
4284        Translator { groups: TranslatorGroups { g0: self.group0() * Simd32x3::from(other) } }
4285    }
4286}
4287
4288impl ScalarProduct<f32> for Translator {
4289    type Output = f32;
4290
4291    fn scalar_product(self, other: f32) -> f32 {
4292        self.group0()[0] * other
4293    }
4294}
4295
4296impl Add<MultiVector> for Translator {
4297    type Output = MultiVector;
4298
4299    fn add(self, other: MultiVector) -> MultiVector {
4300        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + other.group0(), g1: Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[1], self.group0()[2]]) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) + other.group1() } }
4301    }
4302}
4303
4304impl Sub<MultiVector> for Translator {
4305    type Output = MultiVector;
4306
4307    fn sub(self, other: MultiVector) -> MultiVector {
4308        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) - other.group0(), g1: Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[1], self.group0()[2]]) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) - other.group1() } }
4309    }
4310}
4311
4312impl GeometricProduct<MultiVector> for Translator {
4313    type Output = MultiVector;
4314
4315    fn geometric_product(self, other: MultiVector) -> MultiVector {
4316        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[1]) * swizzle!(other.group1(), 2, 3, 0, 1) * Simd32x4::from([-1.0, 1.0, -1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group1(), 3, 2, 1, 0) * Simd32x4::from([-1.0, -1.0, -1.0, 1.0]), g1: Simd32x4::from(self.group0()[0]) * other.group1() + Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 2, 3, 0, 1) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) } }
4317    }
4318}
4319
4320impl OuterProduct<MultiVector> for Translator {
4321    type Output = MultiVector;
4322
4323    fn outer_product(self, other: MultiVector) -> MultiVector {
4324        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0(), g1: Simd32x4::from(self.group0()[0]) * other.group1() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 2, 0) * Simd32x4::from([0.0, 1.0, 0.0, 1.0]) + Simd32x4::from([self.group0()[0], self.group0()[1], self.group0()[1], self.group0()[0]]) * swizzle!(other.group0(), 0, 3, 0, 0) * Simd32x4::from([0.0, 1.0, 1.0, 0.0]) } }
4325    }
4326}
4327
4328impl InnerProduct<MultiVector> for Translator {
4329    type Output = MultiVector;
4330
4331    fn inner_product(self, other: MultiVector) -> MultiVector {
4332        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group1(), 3, 3, 1, 0) * Simd32x4::from([-1.0, 0.0, -1.0, 1.0]) + Simd32x4::from([self.group0()[1], self.group0()[0], self.group0()[1], self.group0()[1]]) * swizzle!(other.group1(), 2, 0, 0, 1) * Simd32x4::from([-1.0, 0.0, -1.0, -1.0]), g1: Simd32x4::from(self.group0()[0]) * other.group1() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 1.0]) + Simd32x4::from([self.group0()[1], self.group0()[0], self.group0()[1], self.group0()[0]]) * swizzle!(other.group0(), 2, 0, 0, 0) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) } }
4333    }
4334}
4335
4336impl LeftContraction<MultiVector> for Translator {
4337    type Output = MultiVector;
4338
4339    fn left_contraction(self, other: MultiVector) -> MultiVector {
4340        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group1(), 3, 3, 1, 3) * Simd32x4::from([-1.0, 0.0, -1.0, 0.0]) + Simd32x4::from([self.group0()[1], self.group0()[0], self.group0()[0], self.group0()[1]]) * swizzle!(other.group1(), 2, 0, 0, 1) * Simd32x4::from([-1.0, 0.0, 0.0, -1.0]), g1: Simd32x4::from(self.group0()[0]) * other.group1() } }
4341    }
4342}
4343
4344impl ScalarProduct<MultiVector> for Translator {
4345    type Output = f32;
4346
4347    fn scalar_product(self, other: MultiVector) -> f32 {
4348        self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group1()[2] - self.group0()[2] * other.group1()[3]
4349    }
4350}
4351
4352impl Add<Rotor> for Translator {
4353    type Output = Motor;
4354
4355    fn add(self, other: Rotor) -> Motor {
4356        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[1], self.group0()[2]]) * Simd32x4::from([1.0, 0.0, 1.0, 1.0]) + Simd32x4::from([other.group0()[0], other.group0()[1], other.group0()[0], other.group0()[0]]) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) } }
4357    }
4358}
4359
4360impl Sub<Rotor> for Translator {
4361    type Output = Motor;
4362
4363    fn sub(self, other: Rotor) -> Motor {
4364        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[1], self.group0()[2]]) * Simd32x4::from([1.0, 0.0, 1.0, 1.0]) - Simd32x4::from([other.group0()[0], other.group0()[1], other.group0()[0], other.group0()[0]]) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) } }
4365    }
4366}
4367
4368impl GeometricProduct<Rotor> for Translator {
4369    type Output = Motor;
4370
4371    fn geometric_product(self, other: Rotor) -> Motor {
4372        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[1], other.group0()[1], other.group0()[1], other.group0()[0]]) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) + Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[1], self.group0()[1]]) * Simd32x4::from([other.group0()[0], other.group0()[1], other.group0()[0], other.group0()[1]]) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) } }
4373    }
4374}
4375
4376impl OuterProduct<Rotor> for Translator {
4377    type Output = Motor;
4378
4379    fn outer_product(self, other: Rotor) -> Motor {
4380        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[1], self.group0()[2]]) * Simd32x4::from([other.group0()[0], other.group0()[1], other.group0()[0], other.group0()[0]]) } }
4381    }
4382}
4383
4384impl InnerProduct<Rotor> for Translator {
4385    type Output = Motor;
4386
4387    fn inner_product(self, other: Rotor) -> Motor {
4388        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[1], self.group0()[2]]) * Simd32x4::from([other.group0()[0], other.group0()[1], other.group0()[0], other.group0()[0]]) } }
4389    }
4390}
4391
4392impl LeftContraction<Rotor> for Translator {
4393    type Output = Rotor;
4394
4395    fn left_contraction(self, other: Rotor) -> Rotor {
4396        Rotor { groups: RotorGroups { g0: Simd32x2::from(self.group0()[0]) * other.group0() } }
4397    }
4398}
4399
4400impl RightContraction<Rotor> for Translator {
4401    type Output = Translator;
4402
4403    fn right_contraction(self, other: Rotor) -> Translator {
4404        Translator { groups: TranslatorGroups { g0: self.group0() * Simd32x3::from(other.group0()[0]) } }
4405    }
4406}
4407
4408impl ScalarProduct<Rotor> for Translator {
4409    type Output = f32;
4410
4411    fn scalar_product(self, other: Rotor) -> f32 {
4412        self.group0()[0] * other.group0()[0]
4413    }
4414}
4415
4416impl Add<Point> for Translator {
4417    type Output = Motor;
4418
4419    fn add(self, other: Point) -> Motor {
4420        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[1], self.group0()[2]]) * Simd32x4::from([1.0, 0.0, 1.0, 1.0]) + Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
4421    }
4422}
4423
4424impl Sub<Point> for Translator {
4425    type Output = Motor;
4426
4427    fn sub(self, other: Point) -> Motor {
4428        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[1], self.group0()[2]]) * Simd32x4::from([1.0, 0.0, 1.0, 1.0]) - Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
4429    }
4430}
4431
4432impl GeometricProduct<Point> for Translator {
4433    type Output = Motor;
4434
4435    fn geometric_product(self, other: Point) -> Motor {
4436        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[1], other.group0()[2], other.group0()[1], other.group0()[0]]) * Simd32x4::from([-1.0, 1.0, 0.0, -1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[2], other.group0()[1], other.group0()[0], other.group0()[2]]) * Simd32x4::from([-1.0, -1.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
4437    }
4438}
4439
4440impl RegressiveProduct<Point> for Translator {
4441    type Output = Plane;
4442
4443    fn regressive_product(self, other: Point) -> Plane {
4444        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[2]) * swizzle!(other.group0(), 1, 0, 1) * Simd32x3::from([1.0, -1.0, 0.0]) + swizzle!(self.group0(), 1, 0, 1) * swizzle!(other.group0(), 2, 0, 0) * Simd32x3::from([-1.0, 0.0, 1.0]) } }
4445    }
4446}
4447
4448impl OuterProduct<Point> for Translator {
4449    type Output = Point;
4450
4451    fn outer_product(self, other: Point) -> Point {
4452        Point { groups: PointGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() } }
4453    }
4454}
4455
4456impl InnerProduct<Point> for Translator {
4457    type Output = Motor;
4458
4459    fn inner_product(self, other: Point) -> Motor {
4460        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group0()[2]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + Simd32x4::from([self.group0()[1], self.group0()[0], self.group0()[0], self.group0()[0]]) * Simd32x4::from([other.group0()[1], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) } }
4461    }
4462}
4463
4464impl LeftContraction<Point> for Translator {
4465    type Output = Motor;
4466
4467    fn left_contraction(self, other: Point) -> Motor {
4468        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group0()[2]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + Simd32x4::from([self.group0()[1], self.group0()[0], self.group0()[0], self.group0()[0]]) * Simd32x4::from([other.group0()[1], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) } }
4469    }
4470}
4471
4472impl RightContraction<Point> for Translator {
4473    type Output = f32;
4474
4475    fn right_contraction(self, other: Point) -> f32 {
4476        0.0 - self.group0()[1] * other.group0()[1] - self.group0()[2] * other.group0()[2]
4477    }
4478}
4479
4480impl ScalarProduct<Point> for Translator {
4481    type Output = f32;
4482
4483    fn scalar_product(self, other: Point) -> f32 {
4484        0.0 - self.group0()[1] * other.group0()[1] - self.group0()[2] * other.group0()[2]
4485    }
4486}
4487
4488impl Into<IdealPoint> for Translator {
4489    fn into(self) -> IdealPoint {
4490        IdealPoint { groups: IdealPointGroups { g0: Simd32x2::from([self.group0()[1], self.group0()[2]]) } }
4491    }
4492}
4493
4494impl Add<IdealPoint> for Translator {
4495    type Output = Translator;
4496
4497    fn add(self, other: IdealPoint) -> Translator {
4498        Translator { groups: TranslatorGroups { g0: self.group0() + Simd32x3::from([other.group0()[0], other.group0()[0], other.group0()[1]]) * Simd32x3::from([0.0, 1.0, 1.0]) } }
4499    }
4500}
4501
4502impl AddAssign<IdealPoint> for Translator {
4503    fn add_assign(&mut self, other: IdealPoint) {
4504        *self = (*self).add(other);
4505    }
4506}
4507
4508impl Sub<IdealPoint> for Translator {
4509    type Output = Translator;
4510
4511    fn sub(self, other: IdealPoint) -> Translator {
4512        Translator { groups: TranslatorGroups { g0: self.group0() - Simd32x3::from([other.group0()[0], other.group0()[0], other.group0()[1]]) * Simd32x3::from([0.0, 1.0, 1.0]) } }
4513    }
4514}
4515
4516impl SubAssign<IdealPoint> for Translator {
4517    fn sub_assign(&mut self, other: IdealPoint) {
4518        *self = (*self).sub(other);
4519    }
4520}
4521
4522impl GeometricProduct<IdealPoint> for Translator {
4523    type Output = Motor;
4524
4525    fn geometric_product(self, other: IdealPoint) -> Motor {
4526        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[1], other.group0()[0], other.group0()[1], other.group0()[1]]) * Simd32x4::from([-1.0, -1.0, 0.0, 0.0]) + Simd32x4::from([self.group0()[1], self.group0()[1], self.group0()[0], self.group0()[0]]) * Simd32x4::from([other.group0()[0], other.group0()[1], other.group0()[0], other.group0()[1]]) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) } }
4527    }
4528}
4529
4530impl OuterProduct<IdealPoint> for Translator {
4531    type Output = IdealPoint;
4532
4533    fn outer_product(self, other: IdealPoint) -> IdealPoint {
4534        IdealPoint { groups: IdealPointGroups { g0: Simd32x2::from(self.group0()[0]) * other.group0() } }
4535    }
4536}
4537
4538impl InnerProduct<IdealPoint> for Translator {
4539    type Output = Translator;
4540
4541    fn inner_product(self, other: IdealPoint) -> Translator {
4542        Translator { groups: TranslatorGroups { g0: Simd32x3::from(self.group0()[2]) * Simd32x3::from(other.group0()[1]) * Simd32x3::from([-1.0, 0.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0) * Simd32x3::from([other.group0()[0], other.group0()[0], other.group0()[1]]) * Simd32x3::from([-1.0, 1.0, 1.0]) } }
4543    }
4544}
4545
4546impl LeftContraction<IdealPoint> for Translator {
4547    type Output = Translator;
4548
4549    fn left_contraction(self, other: IdealPoint) -> Translator {
4550        Translator { groups: TranslatorGroups { g0: Simd32x3::from(self.group0()[2]) * Simd32x3::from(other.group0()[1]) * Simd32x3::from([-1.0, 0.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0) * Simd32x3::from([other.group0()[0], other.group0()[0], other.group0()[1]]) * Simd32x3::from([-1.0, 1.0, 1.0]) } }
4551    }
4552}
4553
4554impl RightContraction<IdealPoint> for Translator {
4555    type Output = f32;
4556
4557    fn right_contraction(self, other: IdealPoint) -> f32 {
4558        0.0 - self.group0()[1] * other.group0()[0] - self.group0()[2] * other.group0()[1]
4559    }
4560}
4561
4562impl ScalarProduct<IdealPoint> for Translator {
4563    type Output = f32;
4564
4565    fn scalar_product(self, other: IdealPoint) -> f32 {
4566        0.0 - self.group0()[1] * other.group0()[0] - self.group0()[2] * other.group0()[1]
4567    }
4568}
4569
4570impl GeometricProduct<Plane> for Translator {
4571    type Output = MotorDual;
4572
4573    fn geometric_product(self, other: Plane) -> MotorDual {
4574        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[1], other.group0()[2], other.group0()[1], other.group0()[0]]) * Simd32x4::from([1.0, 1.0, 0.0, -1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[2], other.group0()[1], other.group0()[0], other.group0()[2]]) * Simd32x4::from([1.0, -1.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
4575    }
4576}
4577
4578impl RegressiveProduct<Plane> for Translator {
4579    type Output = f32;
4580
4581    fn regressive_product(self, other: Plane) -> f32 {
4582        self.group0()[1] * other.group0()[1] + self.group0()[2] * other.group0()[2]
4583    }
4584}
4585
4586impl OuterProduct<Plane> for Translator {
4587    type Output = MotorDual;
4588
4589    fn outer_product(self, other: Plane) -> MotorDual {
4590        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group0()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from([self.group0()[1], self.group0()[0], self.group0()[0], self.group0()[0]]) * Simd32x4::from([other.group0()[1], other.group0()[0], other.group0()[1], other.group0()[2]]) } }
4591    }
4592}
4593
4594impl InnerProduct<Plane> for Translator {
4595    type Output = Plane;
4596
4597    fn inner_product(self, other: Plane) -> Plane {
4598        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() + Simd32x3::from(self.group0()[2]) * swizzle!(other.group0(), 1, 0, 1) * Simd32x3::from([-1.0, 1.0, 0.0]) + swizzle!(self.group0(), 1, 0, 1) * swizzle!(other.group0(), 2, 0, 0) * Simd32x3::from([1.0, 0.0, -1.0]) } }
4599    }
4600}
4601
4602impl LeftContraction<Plane> for Translator {
4603    type Output = Plane;
4604
4605    fn left_contraction(self, other: Plane) -> Plane {
4606        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() } }
4607    }
4608}
4609
4610impl RightContraction<Plane> for Translator {
4611    type Output = Plane;
4612
4613    fn right_contraction(self, other: Plane) -> Plane {
4614        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[2]) * swizzle!(other.group0(), 1, 0, 1) * Simd32x3::from([-1.0, 1.0, 0.0]) + swizzle!(self.group0(), 1, 0, 1) * swizzle!(other.group0(), 2, 0, 0) * Simd32x3::from([1.0, 0.0, -1.0]) } }
4615    }
4616}
4617
4618impl Add<Translator> for Translator {
4619    type Output = Translator;
4620
4621    fn add(self, other: Translator) -> Translator {
4622        Translator { groups: TranslatorGroups { g0: self.group0() + other.group0() } }
4623    }
4624}
4625
4626impl AddAssign<Translator> for Translator {
4627    fn add_assign(&mut self, other: Translator) {
4628        *self = (*self).add(other);
4629    }
4630}
4631
4632impl Sub<Translator> for Translator {
4633    type Output = Translator;
4634
4635    fn sub(self, other: Translator) -> Translator {
4636        Translator { groups: TranslatorGroups { g0: self.group0() - other.group0() } }
4637    }
4638}
4639
4640impl SubAssign<Translator> for Translator {
4641    fn sub_assign(&mut self, other: Translator) {
4642        *self = (*self).sub(other);
4643    }
4644}
4645
4646impl Mul<Translator> for Translator {
4647    type Output = Translator;
4648
4649    fn mul(self, other: Translator) -> Translator {
4650        Translator { groups: TranslatorGroups { g0: self.group0() * other.group0() } }
4651    }
4652}
4653
4654impl MulAssign<Translator> for Translator {
4655    fn mul_assign(&mut self, other: Translator) {
4656        *self = (*self).mul(other);
4657    }
4658}
4659
4660impl Div<Translator> for Translator {
4661    type Output = Translator;
4662
4663    fn div(self, other: Translator) -> Translator {
4664        Translator { groups: TranslatorGroups { g0: Simd32x3::from([self.group0()[0], self.group0()[1], self.group0()[2]]) * Simd32x3::from([1.0, 1.0, 1.0]) / Simd32x3::from([other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x3::from([1.0, 1.0, 1.0]) } }
4665    }
4666}
4667
4668impl DivAssign<Translator> for Translator {
4669    fn div_assign(&mut self, other: Translator) {
4670        *self = (*self).div(other);
4671    }
4672}
4673
4674impl GeometricProduct<Translator> for Translator {
4675    type Output = Motor;
4676
4677    fn geometric_product(self, other: Translator) -> Motor {
4678        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[1], other.group0()[2], other.group0()[0], other.group0()[1]]) * Simd32x4::from([-1.0, 1.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[2], other.group0()[1], other.group0()[2], other.group0()[0]]) * Simd32x4::from([-1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([1.0, 0.0, 1.0, 1.0]) } }
4679    }
4680}
4681
4682impl OuterProduct<Translator> for Translator {
4683    type Output = Translator;
4684
4685    fn outer_product(self, other: Translator) -> Translator {
4686        Translator { groups: TranslatorGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() + self.group0() * Simd32x3::from(other.group0()[0]) * Simd32x3::from([0.0, 1.0, 1.0]) } }
4687    }
4688}
4689
4690impl InnerProduct<Translator> for Translator {
4691    type Output = Translator;
4692
4693    fn inner_product(self, other: Translator) -> Translator {
4694        Translator { groups: TranslatorGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() + Simd32x3::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0) * Simd32x3::from([-1.0, 0.0, 1.0]) + swizzle!(self.group0(), 1, 1, 0) * swizzle!(other.group0(), 1, 0, 0) * Simd32x3::from([-1.0, 1.0, 0.0]) } }
4695    }
4696}
4697
4698impl LeftContraction<Translator> for Translator {
4699    type Output = Translator;
4700
4701    fn left_contraction(self, other: Translator) -> Translator {
4702        Translator { groups: TranslatorGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() + Simd32x3::from(self.group0()[2]) * Simd32x3::from(other.group0()[2]) * Simd32x3::from([-1.0, 0.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0) * swizzle!(other.group0(), 1, 0, 0) * Simd32x3::from([-1.0, 0.0, 0.0]) } }
4703    }
4704}
4705
4706impl RightContraction<Translator> for Translator {
4707    type Output = Translator;
4708
4709    fn right_contraction(self, other: Translator) -> Translator {
4710        Translator { groups: TranslatorGroups { g0: Simd32x3::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0, 1) * Simd32x3::from([-1.0, 1.0, 0.0]) + Simd32x3::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0) * Simd32x3::from([-1.0, 0.0, 1.0]) + Simd32x3::from(self.group0()[0]) * Simd32x3::from(other.group0()[0]) * Simd32x3::from([1.0, 0.0, 0.0]) } }
4711    }
4712}
4713
4714impl ScalarProduct<Translator> for Translator {
4715    type Output = f32;
4716
4717    fn scalar_product(self, other: Translator) -> f32 {
4718        self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group0()[1] - self.group0()[2] * other.group0()[2]
4719    }
4720}
4721
4722impl Add<Motor> for Translator {
4723    type Output = Motor;
4724
4725    fn add(self, other: Motor) -> Motor {
4726        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[1], self.group0()[2]]) * Simd32x4::from([1.0, 0.0, 1.0, 1.0]) + other.group0() } }
4727    }
4728}
4729
4730impl Sub<Motor> for Translator {
4731    type Output = Motor;
4732
4733    fn sub(self, other: Motor) -> Motor {
4734        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[1], self.group0()[2]]) * Simd32x4::from([1.0, 0.0, 1.0, 1.0]) - other.group0() } }
4735    }
4736}
4737
4738impl GeometricProduct<Motor> for Translator {
4739    type Output = Motor;
4740
4741    fn geometric_product(self, other: Motor) -> Motor {
4742        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 2, 3, 0, 1) * Simd32x4::from([-1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([-1.0, -1.0, 1.0, 1.0]) } }
4743    }
4744}
4745
4746impl RegressiveProduct<Motor> for Translator {
4747    type Output = Plane;
4748
4749    fn regressive_product(self, other: Motor) -> Plane {
4750        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[2]) * Simd32x3::from([other.group0()[2], other.group0()[1], other.group0()[2]]) * Simd32x3::from([1.0, -1.0, 0.0]) + swizzle!(self.group0(), 1, 0, 1) * Simd32x3::from([other.group0()[3], other.group0()[0], other.group0()[1]]) * Simd32x3::from([-1.0, 0.0, 1.0]) } }
4751    }
4752}
4753
4754impl OuterProduct<Motor> for Translator {
4755    type Output = Motor;
4756
4757    fn outer_product(self, other: Motor) -> Motor {
4758        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[1], self.group0()[2]]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) } }
4759    }
4760}
4761
4762impl InnerProduct<Motor> for Translator {
4763    type Output = Motor;
4764
4765    fn inner_product(self, other: Motor) -> Motor {
4766        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 1.0]) + Simd32x4::from([self.group0()[1], self.group0()[0], self.group0()[1], self.group0()[0]]) * swizzle!(other.group0(), 2, 0, 0, 0) * Simd32x4::from([-1.0, 0.0, 1.0, 0.0]) } }
4767    }
4768}
4769
4770impl LeftContraction<Motor> for Translator {
4771    type Output = Motor;
4772
4773    fn left_contraction(self, other: Motor) -> Motor {
4774        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group0()[3]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + Simd32x4::from([self.group0()[1], self.group0()[0], self.group0()[0], self.group0()[0]]) * swizzle!(other.group0(), 2, 0, 0, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) } }
4775    }
4776}
4777
4778impl RightContraction<Motor> for Translator {
4779    type Output = Translator;
4780
4781    fn right_contraction(self, other: Motor) -> Translator {
4782        Translator { groups: TranslatorGroups { g0: Simd32x3::from(self.group0()[1]) * Simd32x3::from([other.group0()[2], other.group0()[0], other.group0()[2]]) * Simd32x3::from([-1.0, 1.0, 0.0]) + Simd32x3::from(self.group0()[2]) * Simd32x3::from([other.group0()[3], other.group0()[3], other.group0()[0]]) * Simd32x3::from([-1.0, 0.0, 1.0]) + Simd32x3::from(self.group0()[0]) * Simd32x3::from(other.group0()[0]) * Simd32x3::from([1.0, 0.0, 0.0]) } }
4783    }
4784}
4785
4786impl ScalarProduct<Motor> for Translator {
4787    type Output = f32;
4788
4789    fn scalar_product(self, other: Motor) -> f32 {
4790        self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group0()[2] - self.group0()[2] * other.group0()[3]
4791    }
4792}
4793
4794impl GeometricProduct<MotorDual> for Translator {
4795    type Output = MotorDual;
4796
4797    fn geometric_product(self, other: MotorDual) -> MotorDual {
4798        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 2, 3, 0, 1) * Simd32x4::from([1.0, 1.0, -1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) } }
4799    }
4800}
4801
4802impl RegressiveProduct<MotorDual> for Translator {
4803    type Output = Translator;
4804
4805    fn regressive_product(self, other: MotorDual) -> Translator {
4806        Translator { groups: TranslatorGroups { g0: Simd32x3::from(self.group0()[1]) * Simd32x3::from([other.group0()[2], other.group0()[0], other.group0()[2]]) * Simd32x3::from([1.0, 1.0, 0.0]) + Simd32x3::from(self.group0()[2]) * Simd32x3::from([other.group0()[3], other.group0()[3], other.group0()[0]]) * Simd32x3::from([1.0, 0.0, 1.0]) + Simd32x3::from(self.group0()[0]) * Simd32x3::from(other.group0()[0]) * Simd32x3::from([1.0, 0.0, 0.0]) } }
4807    }
4808}
4809
4810impl OuterProduct<MotorDual> for Translator {
4811    type Output = MotorDual;
4812
4813    fn outer_product(self, other: MotorDual) -> MotorDual {
4814        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group0()[3]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from([self.group0()[1], self.group0()[0], self.group0()[0], self.group0()[0]]) * swizzle!(other.group0(), 2, 0, 0, 0) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
4815    }
4816}
4817
4818impl InnerProduct<MotorDual> for Translator {
4819    type Output = MotorDual;
4820
4821    fn inner_product(self, other: MotorDual) -> MotorDual {
4822        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 1, 0) * Simd32x4::from([0.0, -1.0, 1.0, -1.0]) + Simd32x4::from([self.group0()[0], self.group0()[1], self.group0()[1], self.group0()[1]]) * swizzle!(other.group0(), 0, 3, 0, 1) * Simd32x4::from([0.0, 1.0, -1.0, -1.0]) } }
4823    }
4824}
4825
4826impl LeftContraction<MotorDual> for Translator {
4827    type Output = MotorDual;
4828
4829    fn left_contraction(self, other: MotorDual) -> MotorDual {
4830        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[1], self.group0()[2]]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, -1.0, -1.0]) } }
4831    }
4832}
4833
4834impl RightContraction<MotorDual> for Translator {
4835    type Output = Plane;
4836
4837    fn right_contraction(self, other: MotorDual) -> Plane {
4838        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[2]) * Simd32x3::from([other.group0()[2], other.group0()[1], other.group0()[2]]) * Simd32x3::from([-1.0, 1.0, 0.0]) + swizzle!(self.group0(), 1, 0, 1) * Simd32x3::from([other.group0()[3], other.group0()[0], other.group0()[1]]) * Simd32x3::from([1.0, 0.0, -1.0]) } }
4839    }
4840}
4841
4842impl SquaredMagnitude for Translator {
4843    type Output = f32;
4844
4845    fn squared_magnitude(self) -> f32 {
4846        self.scalar_product(self.reversal())
4847    }
4848}
4849
4850impl Magnitude for Translator {
4851    type Output = f32;
4852
4853    fn magnitude(self) -> f32 {
4854        self.squared_magnitude().sqrt()
4855    }
4856}
4857
4858impl Mul<f32> for Translator {
4859    type Output = Translator;
4860
4861    fn mul(self, other: f32) -> Translator {
4862        self.geometric_product(other)
4863    }
4864}
4865
4866impl MulAssign<f32> for Translator {
4867    fn mul_assign(&mut self, other: f32) {
4868        *self = (*self).mul(other);
4869    }
4870}
4871
4872impl Signum for Translator {
4873    type Output = Translator;
4874
4875    fn signum(self) -> Translator {
4876        self.geometric_product(1.0 / self.magnitude())
4877    }
4878}
4879
4880impl Inverse for Translator {
4881    type Output = Translator;
4882
4883    fn inverse(self) -> Translator {
4884        self.reversal().geometric_product(1.0 / self.squared_magnitude())
4885    }
4886}
4887
4888impl Zero for Motor {
4889    fn zero() -> Self {
4890        Motor { groups: MotorGroups { g0: Simd32x4::from(0.0) } }
4891    }
4892}
4893
4894impl One for Motor {
4895    fn one() -> Self {
4896        Motor { groups: MotorGroups { g0: Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
4897    }
4898}
4899
4900impl Neg for Motor {
4901    type Output = Motor;
4902
4903    fn neg(self) -> Motor {
4904        Motor { groups: MotorGroups { g0: self.group0() * Simd32x4::from(-1.0) } }
4905    }
4906}
4907
4908impl Automorphism for Motor {
4909    type Output = Motor;
4910
4911    fn automorphism(self) -> Motor {
4912        Motor { groups: MotorGroups { g0: self.group0() } }
4913    }
4914}
4915
4916impl Reversal for Motor {
4917    type Output = Motor;
4918
4919    fn reversal(self) -> Motor {
4920        Motor { groups: MotorGroups { g0: self.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) } }
4921    }
4922}
4923
4924impl Conjugation for Motor {
4925    type Output = Motor;
4926
4927    fn conjugation(self) -> Motor {
4928        Motor { groups: MotorGroups { g0: self.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) } }
4929    }
4930}
4931
4932impl Dual for Motor {
4933    type Output = MotorDual;
4934
4935    fn dual(self) -> MotorDual {
4936        MotorDual { groups: MotorDualGroups { g0: self.group0() } }
4937    }
4938}
4939
4940impl Into<f32> for Motor {
4941    fn into(self) -> f32 {
4942        self.group0()[0]
4943    }
4944}
4945
4946impl Add<f32> for Motor {
4947    type Output = Motor;
4948
4949    fn add(self, other: f32) -> Motor {
4950        Motor { groups: MotorGroups { g0: self.group0() + Simd32x4::from(other) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
4951    }
4952}
4953
4954impl AddAssign<f32> for Motor {
4955    fn add_assign(&mut self, other: f32) {
4956        *self = (*self).add(other);
4957    }
4958}
4959
4960impl Sub<f32> for Motor {
4961    type Output = Motor;
4962
4963    fn sub(self, other: f32) -> Motor {
4964        Motor { groups: MotorGroups { g0: self.group0() - Simd32x4::from(other) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
4965    }
4966}
4967
4968impl SubAssign<f32> for Motor {
4969    fn sub_assign(&mut self, other: f32) {
4970        *self = (*self).sub(other);
4971    }
4972}
4973
4974impl GeometricProduct<f32> for Motor {
4975    type Output = Motor;
4976
4977    fn geometric_product(self, other: f32) -> Motor {
4978        Motor { groups: MotorGroups { g0: self.group0() * Simd32x4::from(other) } }
4979    }
4980}
4981
4982impl OuterProduct<f32> for Motor {
4983    type Output = Motor;
4984
4985    fn outer_product(self, other: f32) -> Motor {
4986        Motor { groups: MotorGroups { g0: self.group0() * Simd32x4::from(other) } }
4987    }
4988}
4989
4990impl InnerProduct<f32> for Motor {
4991    type Output = Motor;
4992
4993    fn inner_product(self, other: f32) -> Motor {
4994        Motor { groups: MotorGroups { g0: self.group0() * Simd32x4::from(other) } }
4995    }
4996}
4997
4998impl LeftContraction<f32> for Motor {
4999    type Output = f32;
5000
5001    fn left_contraction(self, other: f32) -> f32 {
5002        self.group0()[0] * other
5003    }
5004}
5005
5006impl RightContraction<f32> for Motor {
5007    type Output = Motor;
5008
5009    fn right_contraction(self, other: f32) -> Motor {
5010        Motor { groups: MotorGroups { g0: self.group0() * Simd32x4::from(other) } }
5011    }
5012}
5013
5014impl ScalarProduct<f32> for Motor {
5015    type Output = f32;
5016
5017    fn scalar_product(self, other: f32) -> f32 {
5018        self.group0()[0] * other
5019    }
5020}
5021
5022impl Add<MultiVector> for Motor {
5023    type Output = MultiVector;
5024
5025    fn add(self, other: MultiVector) -> MultiVector {
5026        MultiVector { groups: MultiVectorGroups { g0: swizzle!(self.group0(), 0, 1, 0, 0) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + other.group0(), g1: swizzle!(self.group0(), 0, 0, 2, 3) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) + other.group1() } }
5027    }
5028}
5029
5030impl Sub<MultiVector> for Motor {
5031    type Output = MultiVector;
5032
5033    fn sub(self, other: MultiVector) -> MultiVector {
5034        MultiVector { groups: MultiVectorGroups { g0: swizzle!(self.group0(), 0, 1, 0, 0) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) - other.group0(), g1: swizzle!(self.group0(), 0, 0, 2, 3) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) - other.group1() } }
5035    }
5036}
5037
5038impl GeometricProduct<MultiVector> for Motor {
5039    type Output = MultiVector;
5040
5041    fn geometric_product(self, other: MultiVector) -> MultiVector {
5042        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group1(), 2, 3, 0, 1) * Simd32x4::from([-1.0, 1.0, -1.0, -1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group1(), 3, 2, 1, 0) * Simd32x4::from([-1.0, -1.0, -1.0, 1.0]), g1: Simd32x4::from(self.group0()[0]) * other.group1() + Simd32x4::from(self.group0()[1]) * swizzle!(other.group1(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 3, 0, 1) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) } }
5043    }
5044}
5045
5046impl OuterProduct<MultiVector> for Motor {
5047    type Output = MultiVector;
5048
5049    fn outer_product(self, other: MultiVector) -> MultiVector {
5050        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + swizzle!(self.group0(), 0, 1, 0, 0) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 0.0, 0.0]), g1: Simd32x4::from(self.group0()[0]) * other.group1() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 3, 3, 0, 3) * Simd32x4::from([0.0, 1.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 2, 2, 2, 0) * Simd32x4::from([0.0, 1.0, 0.0, 1.0]) + swizzle!(self.group0(), 0, 1, 0, 0) * Simd32x4::from(other.group1()[0]) * Simd32x4::from([0.0, 1.0, 0.0, 0.0]) } }
5051    }
5052}
5053
5054impl InnerProduct<MultiVector> for Motor {
5055    type Output = MultiVector;
5056
5057    fn inner_product(self, other: MultiVector) -> MultiVector {
5058        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group1(), 3, 3, 1, 0) * Simd32x4::from([-1.0, 0.0, -1.0, 1.0]) + swizzle!(self.group0(), 2, 0, 2, 2) * swizzle!(other.group1(), 2, 0, 0, 1) * Simd32x4::from([-1.0, 0.0, -1.0, -1.0]), g1: Simd32x4::from(self.group0()[0]) * other.group1() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 1.0]) + swizzle!(self.group0(), 1, 0, 0, 0) * swizzle!(other.group1(), 1, 0, 0, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) } }
5059    }
5060}
5061
5062impl LeftContraction<MultiVector> for Motor {
5063    type Output = MultiVector;
5064
5065    fn left_contraction(self, other: MultiVector) -> MultiVector {
5066        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group1(), 2, 2, 2, 1) * Simd32x4::from([-1.0, 0.0, 0.0, -1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group1(), 3, 3, 1, 3) * Simd32x4::from([-1.0, 0.0, -1.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0, 0) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]), g1: Simd32x4::from(self.group0()[0]) * other.group1() + swizzle!(self.group0(), 1, 0, 0, 0) * swizzle!(other.group1(), 1, 0, 0, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) } }
5067    }
5068}
5069
5070impl ScalarProduct<MultiVector> for Motor {
5071    type Output = f32;
5072
5073    fn scalar_product(self, other: MultiVector) -> f32 {
5074        self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group0()[1] - self.group0()[2] * other.group1()[2] - self.group0()[3] * other.group1()[3]
5075    }
5076}
5077
5078impl Into<Rotor> for Motor {
5079    fn into(self) -> Rotor {
5080        Rotor { groups: RotorGroups { g0: Simd32x2::from([self.group0()[0], self.group0()[1]]) } }
5081    }
5082}
5083
5084impl Add<Rotor> for Motor {
5085    type Output = Motor;
5086
5087    fn add(self, other: Rotor) -> Motor {
5088        Motor { groups: MotorGroups { g0: self.group0() + Simd32x4::from([other.group0()[0], other.group0()[1], other.group0()[0], other.group0()[0]]) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) } }
5089    }
5090}
5091
5092impl AddAssign<Rotor> for Motor {
5093    fn add_assign(&mut self, other: Rotor) {
5094        *self = (*self).add(other);
5095    }
5096}
5097
5098impl Sub<Rotor> for Motor {
5099    type Output = Motor;
5100
5101    fn sub(self, other: Rotor) -> Motor {
5102        Motor { groups: MotorGroups { g0: self.group0() - Simd32x4::from([other.group0()[0], other.group0()[1], other.group0()[0], other.group0()[0]]) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) } }
5103    }
5104}
5105
5106impl SubAssign<Rotor> for Motor {
5107    fn sub_assign(&mut self, other: Rotor) {
5108        *self = (*self).sub(other);
5109    }
5110}
5111
5112impl GeometricProduct<Rotor> for Motor {
5113    type Output = Motor;
5114
5115    fn geometric_product(self, other: Rotor) -> Motor {
5116        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[1], other.group0()[0], other.group0()[1], other.group0()[1]]) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[1], other.group0()[1], other.group0()[1], other.group0()[0]]) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) + swizzle!(self.group0(), 0, 0, 2, 2) * Simd32x4::from([other.group0()[0], other.group0()[1], other.group0()[0], other.group0()[1]]) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) } }
5117    }
5118}
5119
5120impl OuterProduct<Rotor> for Motor {
5121    type Output = Motor;
5122
5123    fn outer_product(self, other: Rotor) -> Motor {
5124        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 0.0, 0.0]) + swizzle!(self.group0(), 0, 0, 2, 3) * Simd32x4::from([other.group0()[0], other.group0()[1], other.group0()[0], other.group0()[0]]) } }
5125    }
5126}
5127
5128impl InnerProduct<Rotor> for Motor {
5129    type Output = Motor;
5130
5131    fn inner_product(self, other: Rotor) -> Motor {
5132        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[1], other.group0()[0], other.group0()[1], other.group0()[1]]) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]) + swizzle!(self.group0(), 0, 0, 2, 3) * Simd32x4::from([other.group0()[0], other.group0()[1], other.group0()[0], other.group0()[0]]) } }
5133    }
5134}
5135
5136impl LeftContraction<Rotor> for Motor {
5137    type Output = Rotor;
5138
5139    fn left_contraction(self, other: Rotor) -> Rotor {
5140        Rotor { groups: RotorGroups { g0: Simd32x2::from(self.group0()[0]) * other.group0() + Simd32x2::from([self.group0()[1], self.group0()[0]]) * swizzle!(other.group0(), 1, 0) * Simd32x2::from([-1.0, 0.0]) } }
5141    }
5142}
5143
5144impl RightContraction<Rotor> for Motor {
5145    type Output = Motor;
5146
5147    fn right_contraction(self, other: Rotor) -> Motor {
5148        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[1], other.group0()[0], other.group0()[1], other.group0()[1]]) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]) + swizzle!(self.group0(), 0, 0, 2, 3) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 1.0, 1.0]) } }
5149    }
5150}
5151
5152impl ScalarProduct<Rotor> for Motor {
5153    type Output = f32;
5154
5155    fn scalar_product(self, other: Rotor) -> f32 {
5156        self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group0()[1]
5157    }
5158}
5159
5160impl Into<Point> for Motor {
5161    fn into(self) -> Point {
5162        Point { groups: PointGroups { g0: Simd32x3::from([self.group0()[1], self.group0()[2], self.group0()[3]]) } }
5163    }
5164}
5165
5166impl Add<Point> for Motor {
5167    type Output = Motor;
5168
5169    fn add(self, other: Point) -> Motor {
5170        Motor { groups: MotorGroups { g0: self.group0() + Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
5171    }
5172}
5173
5174impl AddAssign<Point> for Motor {
5175    fn add_assign(&mut self, other: Point) {
5176        *self = (*self).add(other);
5177    }
5178}
5179
5180impl Sub<Point> for Motor {
5181    type Output = Motor;
5182
5183    fn sub(self, other: Point) -> Motor {
5184        Motor { groups: MotorGroups { g0: self.group0() - Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
5185    }
5186}
5187
5188impl SubAssign<Point> for Motor {
5189    fn sub_assign(&mut self, other: Point) {
5190        *self = (*self).sub(other);
5191    }
5192}
5193
5194impl GeometricProduct<Point> for Motor {
5195    type Output = Motor;
5196
5197    fn geometric_product(self, other: Point) -> Motor {
5198        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[2], other.group0()[1]]) * Simd32x4::from([-1.0, 0.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[1], other.group0()[2], other.group0()[1], other.group0()[0]]) * Simd32x4::from([-1.0, 1.0, 0.0, -1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[2], other.group0()[1], other.group0()[0], other.group0()[2]]) * Simd32x4::from([-1.0, -1.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
5199    }
5200}
5201
5202impl RegressiveProduct<Point> for Motor {
5203    type Output = Plane;
5204
5205    fn regressive_product(self, other: Point) -> Plane {
5206        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0) * Simd32x3::from([-1.0, 0.0, 1.0]) + Simd32x3::from(self.group0()[3]) * swizzle!(other.group0(), 1, 0, 1) * Simd32x3::from([1.0, -1.0, 0.0]) + Simd32x3::from([self.group0()[0], self.group0()[1], self.group0()[1]]) * swizzle!(other.group0(), 0, 2, 1) * Simd32x3::from([0.0, 1.0, -1.0]) } }
5207    }
5208}
5209
5210impl OuterProduct<Point> for Motor {
5211    type Output = Point;
5212
5213    fn outer_product(self, other: Point) -> Point {
5214        Point { groups: PointGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() } }
5215    }
5216}
5217
5218impl InnerProduct<Point> for Motor {
5219    type Output = Motor;
5220
5221    fn inner_product(self, other: Point) -> Motor {
5222        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group0()[1]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group0()[2]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0, 0) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) } }
5223    }
5224}
5225
5226impl LeftContraction<Point> for Motor {
5227    type Output = Motor;
5228
5229    fn left_contraction(self, other: Point) -> Motor {
5230        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group0()[1]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group0()[2]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0, 0) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) } }
5231    }
5232}
5233
5234impl RightContraction<Point> for Motor {
5235    type Output = f32;
5236
5237    fn right_contraction(self, other: Point) -> f32 {
5238        0.0 - self.group0()[1] * other.group0()[0] - self.group0()[2] * other.group0()[1] - self.group0()[3] * other.group0()[2]
5239    }
5240}
5241
5242impl ScalarProduct<Point> for Motor {
5243    type Output = f32;
5244
5245    fn scalar_product(self, other: Point) -> f32 {
5246        0.0 - self.group0()[1] * other.group0()[0] - self.group0()[2] * other.group0()[1] - self.group0()[3] * other.group0()[2]
5247    }
5248}
5249
5250impl Into<IdealPoint> for Motor {
5251    fn into(self) -> IdealPoint {
5252        IdealPoint { groups: IdealPointGroups { g0: Simd32x2::from([self.group0()[2], self.group0()[3]]) } }
5253    }
5254}
5255
5256impl Add<IdealPoint> for Motor {
5257    type Output = Motor;
5258
5259    fn add(self, other: IdealPoint) -> Motor {
5260        Motor { groups: MotorGroups { g0: self.group0() + Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[0], other.group0()[1]]) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) } }
5261    }
5262}
5263
5264impl AddAssign<IdealPoint> for Motor {
5265    fn add_assign(&mut self, other: IdealPoint) {
5266        *self = (*self).add(other);
5267    }
5268}
5269
5270impl Sub<IdealPoint> for Motor {
5271    type Output = Motor;
5272
5273    fn sub(self, other: IdealPoint) -> Motor {
5274        Motor { groups: MotorGroups { g0: self.group0() - Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[0], other.group0()[1]]) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) } }
5275    }
5276}
5277
5278impl SubAssign<IdealPoint> for Motor {
5279    fn sub_assign(&mut self, other: IdealPoint) {
5280        *self = (*self).sub(other);
5281    }
5282}
5283
5284impl GeometricProduct<IdealPoint> for Motor {
5285    type Output = Motor;
5286
5287    fn geometric_product(self, other: IdealPoint) -> Motor {
5288        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[1], other.group0()[1], other.group0()[1], other.group0()[0]]) * Simd32x4::from([0.0, 0.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[1], other.group0()[0], other.group0()[1], other.group0()[1]]) * Simd32x4::from([-1.0, -1.0, 0.0, 0.0]) + swizzle!(self.group0(), 2, 2, 0, 0) * Simd32x4::from([other.group0()[0], other.group0()[1], other.group0()[0], other.group0()[1]]) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) } }
5289    }
5290}
5291
5292impl RegressiveProduct<IdealPoint> for Motor {
5293    type Output = Plane;
5294
5295    fn regressive_product(self, other: IdealPoint) -> Plane {
5296        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[3]) * Simd32x3::from(other.group0()[0]) * Simd32x3::from([1.0, 0.0, 0.0]) + Simd32x3::from([self.group0()[2], self.group0()[1], self.group0()[1]]) * Simd32x3::from([other.group0()[1], other.group0()[1], other.group0()[0]]) * Simd32x3::from([-1.0, 1.0, -1.0]) } }
5297    }
5298}
5299
5300impl OuterProduct<IdealPoint> for Motor {
5301    type Output = IdealPoint;
5302
5303    fn outer_product(self, other: IdealPoint) -> IdealPoint {
5304        IdealPoint { groups: IdealPointGroups { g0: Simd32x2::from(self.group0()[0]) * other.group0() } }
5305    }
5306}
5307
5308impl InnerProduct<IdealPoint> for Motor {
5309    type Output = Translator;
5310
5311    fn inner_product(self, other: IdealPoint) -> Translator {
5312        Translator { groups: TranslatorGroups { g0: Simd32x3::from(self.group0()[3]) * Simd32x3::from(other.group0()[1]) * Simd32x3::from([-1.0, 0.0, 0.0]) + Simd32x3::from([self.group0()[2], self.group0()[0], self.group0()[0]]) * Simd32x3::from([other.group0()[0], other.group0()[0], other.group0()[1]]) * Simd32x3::from([-1.0, 1.0, 1.0]) } }
5313    }
5314}
5315
5316impl LeftContraction<IdealPoint> for Motor {
5317    type Output = Translator;
5318
5319    fn left_contraction(self, other: IdealPoint) -> Translator {
5320        Translator { groups: TranslatorGroups { g0: Simd32x3::from(self.group0()[3]) * Simd32x3::from(other.group0()[1]) * Simd32x3::from([-1.0, 0.0, 0.0]) + Simd32x3::from([self.group0()[2], self.group0()[0], self.group0()[0]]) * Simd32x3::from([other.group0()[0], other.group0()[0], other.group0()[1]]) * Simd32x3::from([-1.0, 1.0, 1.0]) } }
5321    }
5322}
5323
5324impl RightContraction<IdealPoint> for Motor {
5325    type Output = f32;
5326
5327    fn right_contraction(self, other: IdealPoint) -> f32 {
5328        0.0 - self.group0()[2] * other.group0()[0] - self.group0()[3] * other.group0()[1]
5329    }
5330}
5331
5332impl ScalarProduct<IdealPoint> for Motor {
5333    type Output = f32;
5334
5335    fn scalar_product(self, other: IdealPoint) -> f32 {
5336        0.0 - self.group0()[2] * other.group0()[0] - self.group0()[3] * other.group0()[1]
5337    }
5338}
5339
5340impl GeometricProduct<Plane> for Motor {
5341    type Output = MotorDual;
5342
5343    fn geometric_product(self, other: Plane) -> MotorDual {
5344        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[2], other.group0()[1]]) * Simd32x4::from([1.0, 0.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[1], other.group0()[2], other.group0()[1], other.group0()[0]]) * Simd32x4::from([1.0, 1.0, 0.0, -1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[2], other.group0()[1], other.group0()[0], other.group0()[2]]) * Simd32x4::from([1.0, -1.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
5345    }
5346}
5347
5348impl RegressiveProduct<Plane> for Motor {
5349    type Output = f32;
5350
5351    fn regressive_product(self, other: Plane) -> f32 {
5352        self.group0()[1] * other.group0()[0] + self.group0()[2] * other.group0()[1] + self.group0()[3] * other.group0()[2]
5353    }
5354}
5355
5356impl OuterProduct<Plane> for Motor {
5357    type Output = MotorDual;
5358
5359    fn outer_product(self, other: Plane) -> MotorDual {
5360        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group0()[1]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group0()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0, 0) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) } }
5361    }
5362}
5363
5364impl InnerProduct<Plane> for Motor {
5365    type Output = Plane;
5366
5367    fn inner_product(self, other: Plane) -> Plane {
5368        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() + Simd32x3::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0) * Simd32x3::from([1.0, 0.0, -1.0]) + Simd32x3::from(self.group0()[3]) * swizzle!(other.group0(), 1, 0, 1) * Simd32x3::from([-1.0, 1.0, 0.0]) + Simd32x3::from([self.group0()[0], self.group0()[1], self.group0()[1]]) * swizzle!(other.group0(), 0, 2, 1) * Simd32x3::from([0.0, -1.0, 1.0]) } }
5369    }
5370}
5371
5372impl LeftContraction<Plane> for Motor {
5373    type Output = Plane;
5374
5375    fn left_contraction(self, other: Plane) -> Plane {
5376        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() } }
5377    }
5378}
5379
5380impl RightContraction<Plane> for Motor {
5381    type Output = Plane;
5382
5383    fn right_contraction(self, other: Plane) -> Plane {
5384        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0) * Simd32x3::from([1.0, 0.0, -1.0]) + Simd32x3::from(self.group0()[3]) * swizzle!(other.group0(), 1, 0, 1) * Simd32x3::from([-1.0, 1.0, 0.0]) + Simd32x3::from([self.group0()[0], self.group0()[1], self.group0()[1]]) * swizzle!(other.group0(), 0, 2, 1) * Simd32x3::from([0.0, -1.0, 1.0]) } }
5385    }
5386}
5387
5388impl Into<Translator> for Motor {
5389    fn into(self) -> Translator {
5390        Translator { groups: TranslatorGroups { g0: Simd32x3::from([self.group0()[0], self.group0()[2], self.group0()[3]]) } }
5391    }
5392}
5393
5394impl Add<Translator> for Motor {
5395    type Output = Motor;
5396
5397    fn add(self, other: Translator) -> Motor {
5398        Motor { groups: MotorGroups { g0: self.group0() + Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([1.0, 0.0, 1.0, 1.0]) } }
5399    }
5400}
5401
5402impl AddAssign<Translator> for Motor {
5403    fn add_assign(&mut self, other: Translator) {
5404        *self = (*self).add(other);
5405    }
5406}
5407
5408impl Sub<Translator> for Motor {
5409    type Output = Motor;
5410
5411    fn sub(self, other: Translator) -> Motor {
5412        Motor { groups: MotorGroups { g0: self.group0() - Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([1.0, 0.0, 1.0, 1.0]) } }
5413    }
5414}
5415
5416impl SubAssign<Translator> for Motor {
5417    fn sub_assign(&mut self, other: Translator) {
5418        *self = (*self).sub(other);
5419    }
5420}
5421
5422impl GeometricProduct<Translator> for Motor {
5423    type Output = Motor;
5424
5425    fn geometric_product(self, other: Translator) -> Motor {
5426        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[2], other.group0()[1]]) * Simd32x4::from([0.0, 1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[1], other.group0()[2], other.group0()[0], other.group0()[1]]) * Simd32x4::from([-1.0, 1.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[2], other.group0()[1], other.group0()[2], other.group0()[0]]) * Simd32x4::from([-1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([1.0, 0.0, 1.0, 1.0]) } }
5427    }
5428}
5429
5430impl RegressiveProduct<Translator> for Motor {
5431    type Output = Plane;
5432
5433    fn regressive_product(self, other: Translator) -> Plane {
5434        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[3]) * Simd32x3::from(other.group0()[1]) * Simd32x3::from([1.0, 0.0, 0.0]) + Simd32x3::from([self.group0()[2], self.group0()[1], self.group0()[1]]) * swizzle!(other.group0(), 2, 2, 1) * Simd32x3::from([-1.0, 1.0, -1.0]) } }
5435    }
5436}
5437
5438impl OuterProduct<Translator> for Motor {
5439    type Output = Motor;
5440
5441    fn outer_product(self, other: Translator) -> Motor {
5442        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, 0.0, 1.0]) + swizzle!(self.group0(), 0, 1, 0, 0) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) } }
5443    }
5444}
5445
5446impl InnerProduct<Translator> for Motor {
5447    type Output = Motor;
5448
5449    fn inner_product(self, other: Translator) -> Motor {
5450        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[1], other.group0()[1], other.group0()[0], other.group0()[1]]) * Simd32x4::from([-1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[2], other.group0()[2], other.group0()[2], other.group0()[0]]) * Simd32x4::from([-1.0, 0.0, 0.0, 1.0]) + swizzle!(self.group0(), 0, 1, 0, 0) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) } }
5451    }
5452}
5453
5454impl LeftContraction<Translator> for Motor {
5455    type Output = Translator;
5456
5457    fn left_contraction(self, other: Translator) -> Translator {
5458        Translator { groups: TranslatorGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() + Simd32x3::from(self.group0()[3]) * Simd32x3::from(other.group0()[2]) * Simd32x3::from([-1.0, 0.0, 0.0]) + Simd32x3::from([self.group0()[2], self.group0()[0], self.group0()[0]]) * swizzle!(other.group0(), 1, 0, 0) * Simd32x3::from([-1.0, 0.0, 0.0]) } }
5459    }
5460}
5461
5462impl RightContraction<Translator> for Motor {
5463    type Output = Motor;
5464
5465    fn right_contraction(self, other: Translator) -> Motor {
5466        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[1], other.group0()[1], other.group0()[0], other.group0()[1]]) * Simd32x4::from([-1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[2], other.group0()[2], other.group0()[2], other.group0()[0]]) * Simd32x4::from([-1.0, 0.0, 0.0, 1.0]) + swizzle!(self.group0(), 0, 1, 0, 0) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) } }
5467    }
5468}
5469
5470impl ScalarProduct<Translator> for Motor {
5471    type Output = f32;
5472
5473    fn scalar_product(self, other: Translator) -> f32 {
5474        self.group0()[0] * other.group0()[0] - self.group0()[2] * other.group0()[1] - self.group0()[3] * other.group0()[2]
5475    }
5476}
5477
5478impl Add<Motor> for Motor {
5479    type Output = Motor;
5480
5481    fn add(self, other: Motor) -> Motor {
5482        Motor { groups: MotorGroups { g0: self.group0() + other.group0() } }
5483    }
5484}
5485
5486impl AddAssign<Motor> for Motor {
5487    fn add_assign(&mut self, other: Motor) {
5488        *self = (*self).add(other);
5489    }
5490}
5491
5492impl Sub<Motor> for Motor {
5493    type Output = Motor;
5494
5495    fn sub(self, other: Motor) -> Motor {
5496        Motor { groups: MotorGroups { g0: self.group0() - other.group0() } }
5497    }
5498}
5499
5500impl SubAssign<Motor> for Motor {
5501    fn sub_assign(&mut self, other: Motor) {
5502        *self = (*self).sub(other);
5503    }
5504}
5505
5506impl Mul<Motor> for Motor {
5507    type Output = Motor;
5508
5509    fn mul(self, other: Motor) -> Motor {
5510        Motor { groups: MotorGroups { g0: self.group0() * other.group0() } }
5511    }
5512}
5513
5514impl MulAssign<Motor> for Motor {
5515    fn mul_assign(&mut self, other: Motor) {
5516        *self = (*self).mul(other);
5517    }
5518}
5519
5520impl Div<Motor> for Motor {
5521    type Output = Motor;
5522
5523    fn div(self, other: Motor) -> Motor {
5524        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[1], self.group0()[2], self.group0()[3]]) * Simd32x4::from([1.0, 1.0, 1.0, 1.0]) / Simd32x4::from([other.group0()[0], other.group0()[1], other.group0()[2], other.group0()[3]]) * Simd32x4::from([1.0, 1.0, 1.0, 1.0]) } }
5525    }
5526}
5527
5528impl DivAssign<Motor> for Motor {
5529    fn div_assign(&mut self, other: Motor) {
5530        *self = (*self).div(other);
5531    }
5532}
5533
5534impl GeometricProduct<Motor> for Motor {
5535    type Output = Motor;
5536
5537    fn geometric_product(self, other: Motor) -> Motor {
5538        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 3, 0, 1) * Simd32x4::from([-1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([-1.0, -1.0, 1.0, 1.0]) } }
5539    }
5540}
5541
5542impl RegressiveProduct<Motor> for Motor {
5543    type Output = Plane;
5544
5545    fn regressive_product(self, other: Motor) -> Plane {
5546        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[2]) * Simd32x3::from([other.group0()[3], other.group0()[3], other.group0()[1]]) * Simd32x3::from([-1.0, 0.0, 1.0]) + Simd32x3::from(self.group0()[3]) * Simd32x3::from([other.group0()[2], other.group0()[1], other.group0()[2]]) * Simd32x3::from([1.0, -1.0, 0.0]) + Simd32x3::from([self.group0()[0], self.group0()[1], self.group0()[1]]) * Simd32x3::from([other.group0()[0], other.group0()[3], other.group0()[2]]) * Simd32x3::from([0.0, 1.0, -1.0]) } }
5547    }
5548}
5549
5550impl OuterProduct<Motor> for Motor {
5551    type Output = Motor;
5552
5553    fn outer_product(self, other: Motor) -> Motor {
5554        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + self.group0() * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
5555    }
5556}
5557
5558impl InnerProduct<Motor> for Motor {
5559    type Output = Motor;
5560
5561    fn inner_product(self, other: Motor) -> Motor {
5562        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([-1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 1.0]) + swizzle!(self.group0(), 1, 1, 0, 0) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]) } }
5563    }
5564}
5565
5566impl LeftContraction<Motor> for Motor {
5567    type Output = Motor;
5568
5569    fn left_contraction(self, other: Motor) -> Motor {
5570        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group0()[2]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group0()[3]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0, 0) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) } }
5571    }
5572}
5573
5574impl RightContraction<Motor> for Motor {
5575    type Output = Motor;
5576
5577    fn right_contraction(self, other: Motor) -> Motor {
5578        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0, 1, 1) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([-1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
5579    }
5580}
5581
5582impl ScalarProduct<Motor> for Motor {
5583    type Output = f32;
5584
5585    fn scalar_product(self, other: Motor) -> f32 {
5586        self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group0()[1] - self.group0()[2] * other.group0()[2] - self.group0()[3] * other.group0()[3]
5587    }
5588}
5589
5590impl Add<MotorDual> for Motor {
5591    type Output = MultiVector;
5592
5593    fn add(self, other: MotorDual) -> MultiVector {
5594        MultiVector { groups: MultiVectorGroups { g0: swizzle!(self.group0(), 0, 1, 0, 0) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + swizzle!(other.group0(), 0, 0, 3, 2) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]), g1: swizzle!(self.group0(), 0, 0, 2, 3) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) + swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) } }
5595    }
5596}
5597
5598impl Sub<MotorDual> for Motor {
5599    type Output = MultiVector;
5600
5601    fn sub(self, other: MotorDual) -> MultiVector {
5602        MultiVector { groups: MultiVectorGroups { g0: swizzle!(self.group0(), 0, 1, 0, 0) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) - swizzle!(other.group0(), 0, 0, 3, 2) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]), g1: swizzle!(self.group0(), 0, 0, 2, 3) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) - swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) } }
5603    }
5604}
5605
5606impl GeometricProduct<MotorDual> for Motor {
5607    type Output = MotorDual;
5608
5609    fn geometric_product(self, other: MotorDual) -> MotorDual {
5610        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([1.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 3, 0, 1) * Simd32x4::from([1.0, 1.0, -1.0, -1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) } }
5611    }
5612}
5613
5614impl RegressiveProduct<MotorDual> for Motor {
5615    type Output = Motor;
5616
5617    fn regressive_product(self, other: MotorDual) -> Motor {
5618        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0, 1, 1) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
5619    }
5620}
5621
5622impl OuterProduct<MotorDual> for Motor {
5623    type Output = MotorDual;
5624
5625    fn outer_product(self, other: MotorDual) -> MotorDual {
5626        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group0()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group0()[3]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0, 0) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
5627    }
5628}
5629
5630impl InnerProduct<MotorDual> for Motor {
5631    type Output = MotorDual;
5632
5633    fn inner_product(self, other: MotorDual) -> MotorDual {
5634        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 3, 3, 0, 1) * Simd32x4::from([0.0, 1.0, -1.0, -1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 2, 2, 1, 0) * Simd32x4::from([0.0, -1.0, 1.0, -1.0]) + swizzle!(self.group0(), 0, 1, 1, 1) * swizzle!(other.group0(), 0, 0, 3, 2) * Simd32x4::from([0.0, -1.0, -1.0, 1.0]) } }
5635    }
5636}
5637
5638impl LeftContraction<MotorDual> for Motor {
5639    type Output = MotorDual;
5640
5641    fn left_contraction(self, other: MotorDual) -> MotorDual {
5642        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + self.group0() * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, -1.0, -1.0, -1.0]) } }
5643    }
5644}
5645
5646impl RightContraction<MotorDual> for Motor {
5647    type Output = Plane;
5648
5649    fn right_contraction(self, other: MotorDual) -> Plane {
5650        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[2]) * Simd32x3::from([other.group0()[3], other.group0()[3], other.group0()[1]]) * Simd32x3::from([1.0, 0.0, -1.0]) + Simd32x3::from(self.group0()[3]) * Simd32x3::from([other.group0()[2], other.group0()[1], other.group0()[2]]) * Simd32x3::from([-1.0, 1.0, 0.0]) + Simd32x3::from([self.group0()[0], self.group0()[1], self.group0()[1]]) * Simd32x3::from([other.group0()[0], other.group0()[3], other.group0()[2]]) * Simd32x3::from([0.0, -1.0, 1.0]) } }
5651    }
5652}
5653
5654impl SquaredMagnitude for Motor {
5655    type Output = f32;
5656
5657    fn squared_magnitude(self) -> f32 {
5658        self.scalar_product(self.reversal())
5659    }
5660}
5661
5662impl Magnitude for Motor {
5663    type Output = f32;
5664
5665    fn magnitude(self) -> f32 {
5666        self.squared_magnitude().sqrt()
5667    }
5668}
5669
5670impl Mul<f32> for Motor {
5671    type Output = Motor;
5672
5673    fn mul(self, other: f32) -> Motor {
5674        self.geometric_product(other)
5675    }
5676}
5677
5678impl MulAssign<f32> for Motor {
5679    fn mul_assign(&mut self, other: f32) {
5680        *self = (*self).mul(other);
5681    }
5682}
5683
5684impl Signum for Motor {
5685    type Output = Motor;
5686
5687    fn signum(self) -> Motor {
5688        self.geometric_product(1.0 / self.magnitude())
5689    }
5690}
5691
5692impl Inverse for Motor {
5693    type Output = Motor;
5694
5695    fn inverse(self) -> Motor {
5696        self.reversal().geometric_product(1.0 / self.squared_magnitude())
5697    }
5698}
5699
5700impl Zero for MotorDual {
5701    fn zero() -> Self {
5702        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(0.0) } }
5703    }
5704}
5705
5706impl One for MotorDual {
5707    fn one() -> Self {
5708        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(0.0) } }
5709    }
5710}
5711
5712impl Neg for MotorDual {
5713    type Output = MotorDual;
5714
5715    fn neg(self) -> MotorDual {
5716        MotorDual { groups: MotorDualGroups { g0: self.group0() * Simd32x4::from(-1.0) } }
5717    }
5718}
5719
5720impl Automorphism for MotorDual {
5721    type Output = MotorDual;
5722
5723    fn automorphism(self) -> MotorDual {
5724        MotorDual { groups: MotorDualGroups { g0: self.group0() * Simd32x4::from(-1.0) } }
5725    }
5726}
5727
5728impl Reversal for MotorDual {
5729    type Output = MotorDual;
5730
5731    fn reversal(self) -> MotorDual {
5732        MotorDual { groups: MotorDualGroups { g0: self.group0() * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) } }
5733    }
5734}
5735
5736impl Conjugation for MotorDual {
5737    type Output = MotorDual;
5738
5739    fn conjugation(self) -> MotorDual {
5740        MotorDual { groups: MotorDualGroups { g0: self.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) } }
5741    }
5742}
5743
5744impl Dual for MotorDual {
5745    type Output = Motor;
5746
5747    fn dual(self) -> Motor {
5748        Motor { groups: MotorGroups { g0: self.group0() } }
5749    }
5750}
5751
5752impl GeometricProduct<f32> for MotorDual {
5753    type Output = MotorDual;
5754
5755    fn geometric_product(self, other: f32) -> MotorDual {
5756        MotorDual { groups: MotorDualGroups { g0: self.group0() * Simd32x4::from(other) } }
5757    }
5758}
5759
5760impl RegressiveProduct<f32> for MotorDual {
5761    type Output = f32;
5762
5763    fn regressive_product(self, other: f32) -> f32 {
5764        self.group0()[0] * other
5765    }
5766}
5767
5768impl OuterProduct<f32> for MotorDual {
5769    type Output = MotorDual;
5770
5771    fn outer_product(self, other: f32) -> MotorDual {
5772        MotorDual { groups: MotorDualGroups { g0: self.group0() * Simd32x4::from(other) } }
5773    }
5774}
5775
5776impl InnerProduct<f32> for MotorDual {
5777    type Output = MotorDual;
5778
5779    fn inner_product(self, other: f32) -> MotorDual {
5780        MotorDual { groups: MotorDualGroups { g0: self.group0() * Simd32x4::from(other) } }
5781    }
5782}
5783
5784impl RightContraction<f32> for MotorDual {
5785    type Output = MotorDual;
5786
5787    fn right_contraction(self, other: f32) -> MotorDual {
5788        MotorDual { groups: MotorDualGroups { g0: self.group0() * Simd32x4::from(other) } }
5789    }
5790}
5791
5792impl Add<MultiVector> for MotorDual {
5793    type Output = MultiVector;
5794
5795    fn add(self, other: MultiVector) -> MultiVector {
5796        MultiVector { groups: MultiVectorGroups { g0: swizzle!(self.group0(), 0, 0, 3, 2) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) + other.group0(), g1: swizzle!(self.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + other.group1() } }
5797    }
5798}
5799
5800impl Sub<MultiVector> for MotorDual {
5801    type Output = MultiVector;
5802
5803    fn sub(self, other: MultiVector) -> MultiVector {
5804        MultiVector { groups: MultiVectorGroups { g0: swizzle!(self.group0(), 0, 0, 3, 2) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) - other.group0(), g1: swizzle!(self.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) - other.group1() } }
5805    }
5806}
5807
5808impl GeometricProduct<MultiVector> for MotorDual {
5809    type Output = MultiVector;
5810
5811    fn geometric_product(self, other: MultiVector) -> MultiVector {
5812        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * swizzle!(other.group1(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, -1.0, -1.0]) + Simd32x4::from(self.group0()[1]) * other.group1() * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([1.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 2, 3, 0, 1), g1: Simd32x4::from(self.group0()[0]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) + Simd32x4::from(self.group0()[1]) * other.group0() * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group1(), 3, 2, 1, 0) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group1(), 2, 3, 0, 1) * Simd32x4::from([-1.0, 1.0, -1.0, 1.0]) } }
5813    }
5814}
5815
5816impl RegressiveProduct<MultiVector> for MotorDual {
5817    type Output = MultiVector;
5818
5819    fn regressive_product(self, other: MultiVector) -> MultiVector {
5820        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group1(), 2, 2, 2, 1) * Simd32x4::from([1.0, 0.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group1(), 3, 3, 1, 3) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0, 0) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]), g1: Simd32x4::from(self.group0()[0]) * other.group1() + swizzle!(self.group0(), 1, 0, 0, 0) * swizzle!(other.group1(), 1, 0, 0, 0) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
5821    }
5822}
5823
5824impl InnerProduct<MultiVector> for MotorDual {
5825    type Output = MultiVector;
5826
5827    fn inner_product(self, other: MultiVector) -> MultiVector {
5828        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * swizzle!(other.group1(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, -1.0, -1.0]) + Simd32x4::from(self.group0()[1]) * other.group1() * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 2, 2, 0, 1) * Simd32x4::from([1.0, 0.0, 1.0, 1.0]) + swizzle!(self.group0(), 2, 0, 2, 2) * swizzle!(other.group0(), 3, 0, 1, 0) * Simd32x4::from([1.0, 0.0, -1.0, 1.0]), g1: Simd32x4::from(self.group0()[0]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group1(), 3, 3, 1, 3) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group1(), 2, 2, 2, 1) * Simd32x4::from([-1.0, 0.0, 0.0, 1.0]) + swizzle!(self.group0(), 1, 0, 0, 0) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
5829    }
5830}
5831
5832impl RightContraction<MultiVector> for MotorDual {
5833    type Output = MultiVector;
5834
5835    fn right_contraction(self, other: MultiVector) -> MultiVector {
5836        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * swizzle!(other.group1(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, -1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0, 0) * Simd32x4::from(other.group1()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]), g1: Simd32x4::from(self.group0()[0]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) + swizzle!(self.group0(), 1, 0, 0, 0) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
5837    }
5838}
5839
5840impl ScalarProduct<MultiVector> for MotorDual {
5841    type Output = f32;
5842
5843    fn scalar_product(self, other: MultiVector) -> f32 {
5844        0.0 - self.group0()[0] * other.group1()[1] + self.group0()[1] * other.group1()[0] + self.group0()[2] * other.group0()[3] + self.group0()[3] * other.group0()[2]
5845    }
5846}
5847
5848impl GeometricProduct<Rotor> for MotorDual {
5849    type Output = MotorDual;
5850
5851    fn geometric_product(self, other: Rotor) -> MotorDual {
5852        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[1], other.group0()[0], other.group0()[1], other.group0()[1]]) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[1], other.group0()[1], other.group0()[1], other.group0()[0]]) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) + swizzle!(self.group0(), 0, 0, 2, 2) * Simd32x4::from([other.group0()[0], other.group0()[1], other.group0()[0], other.group0()[1]]) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) } }
5853    }
5854}
5855
5856impl RegressiveProduct<Rotor> for MotorDual {
5857    type Output = Rotor;
5858
5859    fn regressive_product(self, other: Rotor) -> Rotor {
5860        Rotor { groups: RotorGroups { g0: Simd32x2::from(self.group0()[0]) * other.group0() + Simd32x2::from([self.group0()[1], self.group0()[0]]) * swizzle!(other.group0(), 1, 0) * Simd32x2::from([1.0, 0.0]) } }
5861    }
5862}
5863
5864impl OuterProduct<Rotor> for MotorDual {
5865    type Output = MotorDual;
5866
5867    fn outer_product(self, other: Rotor) -> MotorDual {
5868        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[1], other.group0()[0], other.group0()[1], other.group0()[1]]) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + swizzle!(self.group0(), 0, 0, 2, 3) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 1.0, 1.0]) } }
5869    }
5870}
5871
5872impl InnerProduct<Rotor> for MotorDual {
5873    type Output = MotorDual;
5874
5875    fn inner_product(self, other: Rotor) -> MotorDual {
5876        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[1], other.group0()[1], other.group0()[1], other.group0()[0]]) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) + swizzle!(self.group0(), 0, 0, 2, 2) * Simd32x4::from([other.group0()[0], other.group0()[1], other.group0()[0], other.group0()[1]]) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) } }
5877    }
5878}
5879
5880impl RightContraction<Rotor> for MotorDual {
5881    type Output = MotorDual;
5882
5883    fn right_contraction(self, other: Rotor) -> MotorDual {
5884        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 0.0, 0.0]) + swizzle!(self.group0(), 0, 0, 2, 3) * Simd32x4::from([other.group0()[0], other.group0()[1], other.group0()[0], other.group0()[0]]) * Simd32x4::from([1.0, -1.0, 1.0, 1.0]) } }
5885    }
5886}
5887
5888impl GeometricProduct<Point> for MotorDual {
5889    type Output = MotorDual;
5890
5891    fn geometric_product(self, other: Point) -> MotorDual {
5892        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[2], other.group0()[1]]) * Simd32x4::from([1.0, 0.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[1], other.group0()[2], other.group0()[1], other.group0()[0]]) * Simd32x4::from([1.0, 1.0, 0.0, -1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[2], other.group0()[1], other.group0()[0], other.group0()[2]]) * Simd32x4::from([1.0, -1.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, -1.0, -1.0, -1.0]) } }
5893    }
5894}
5895
5896impl RegressiveProduct<Point> for MotorDual {
5897    type Output = Motor;
5898
5899    fn regressive_product(self, other: Point) -> Motor {
5900        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group0()[1]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group0()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0, 0) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) } }
5901    }
5902}
5903
5904impl InnerProduct<Point> for MotorDual {
5905    type Output = Plane;
5906
5907    fn inner_product(self, other: Point) -> Plane {
5908        Plane { groups: PlaneGroups { g0: Simd32x3::from(0.0) - Simd32x3::from(self.group0()[0]) * other.group0() + Simd32x3::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0) * Simd32x3::from([1.0, 0.0, -1.0]) + Simd32x3::from(self.group0()[3]) * swizzle!(other.group0(), 1, 0, 1) * Simd32x3::from([-1.0, 1.0, 0.0]) + Simd32x3::from([self.group0()[0], self.group0()[1], self.group0()[1]]) * swizzle!(other.group0(), 0, 2, 1) * Simd32x3::from([0.0, -1.0, 1.0]) } }
5909    }
5910}
5911
5912impl LeftContraction<Point> for MotorDual {
5913    type Output = Plane;
5914
5915    fn left_contraction(self, other: Point) -> Plane {
5916        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0) * Simd32x3::from([1.0, 0.0, -1.0]) + Simd32x3::from(self.group0()[3]) * swizzle!(other.group0(), 1, 0, 1) * Simd32x3::from([-1.0, 1.0, 0.0]) + Simd32x3::from([self.group0()[0], self.group0()[1], self.group0()[1]]) * swizzle!(other.group0(), 0, 2, 1) * Simd32x3::from([0.0, -1.0, 1.0]) } }
5917    }
5918}
5919
5920impl RightContraction<Point> for MotorDual {
5921    type Output = Plane;
5922
5923    fn right_contraction(self, other: Point) -> Plane {
5924        Plane { groups: PlaneGroups { g0: Simd32x3::from(0.0) - Simd32x3::from(self.group0()[0]) * other.group0() } }
5925    }
5926}
5927
5928impl GeometricProduct<IdealPoint> for MotorDual {
5929    type Output = MotorDual;
5930
5931    fn geometric_product(self, other: IdealPoint) -> MotorDual {
5932        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[1], other.group0()[1], other.group0()[1], other.group0()[0]]) * Simd32x4::from([0.0, 0.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[1], other.group0()[0], other.group0()[1], other.group0()[1]]) * Simd32x4::from([1.0, -1.0, 0.0, 0.0]) + swizzle!(self.group0(), 2, 2, 0, 0) * Simd32x4::from([other.group0()[0], other.group0()[1], other.group0()[0], other.group0()[1]]) * Simd32x4::from([1.0, 1.0, -1.0, -1.0]) } }
5933    }
5934}
5935
5936impl RegressiveProduct<IdealPoint> for MotorDual {
5937    type Output = Translator;
5938
5939    fn regressive_product(self, other: IdealPoint) -> Translator {
5940        Translator { groups: TranslatorGroups { g0: Simd32x3::from(self.group0()[3]) * Simd32x3::from(other.group0()[1]) * Simd32x3::from([1.0, 0.0, 0.0]) + Simd32x3::from([self.group0()[2], self.group0()[0], self.group0()[0]]) * Simd32x3::from([other.group0()[0], other.group0()[0], other.group0()[1]]) } }
5941    }
5942}
5943
5944impl InnerProduct<IdealPoint> for MotorDual {
5945    type Output = Plane;
5946
5947    fn inner_product(self, other: IdealPoint) -> Plane {
5948        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[1]) * Simd32x3::from([other.group0()[1], other.group0()[1], other.group0()[0]]) * Simd32x3::from([0.0, -1.0, 1.0]) + Simd32x3::from(self.group0()[3]) * Simd32x3::from(other.group0()[0]) * Simd32x3::from([-1.0, 0.0, 0.0]) + Simd32x3::from([self.group0()[2], self.group0()[0], self.group0()[0]]) * Simd32x3::from([other.group0()[1], other.group0()[0], other.group0()[1]]) * Simd32x3::from([1.0, -1.0, -1.0]) } }
5949    }
5950}
5951
5952impl LeftContraction<IdealPoint> for MotorDual {
5953    type Output = Plane;
5954
5955    fn left_contraction(self, other: IdealPoint) -> Plane {
5956        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[3]) * Simd32x3::from(other.group0()[0]) * Simd32x3::from([-1.0, 0.0, 0.0]) + Simd32x3::from([self.group0()[2], self.group0()[1], self.group0()[1]]) * Simd32x3::from([other.group0()[1], other.group0()[1], other.group0()[0]]) * Simd32x3::from([1.0, -1.0, 1.0]) } }
5957    }
5958}
5959
5960impl Into<Plane> for MotorDual {
5961    fn into(self) -> Plane {
5962        Plane { groups: PlaneGroups { g0: Simd32x3::from([self.group0()[1], self.group0()[2], self.group0()[3]]) } }
5963    }
5964}
5965
5966impl Add<Plane> for MotorDual {
5967    type Output = MotorDual;
5968
5969    fn add(self, other: Plane) -> MotorDual {
5970        MotorDual { groups: MotorDualGroups { g0: self.group0() + Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
5971    }
5972}
5973
5974impl AddAssign<Plane> for MotorDual {
5975    fn add_assign(&mut self, other: Plane) {
5976        *self = (*self).add(other);
5977    }
5978}
5979
5980impl Sub<Plane> for MotorDual {
5981    type Output = MotorDual;
5982
5983    fn sub(self, other: Plane) -> MotorDual {
5984        MotorDual { groups: MotorDualGroups { g0: self.group0() - Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
5985    }
5986}
5987
5988impl SubAssign<Plane> for MotorDual {
5989    fn sub_assign(&mut self, other: Plane) {
5990        *self = (*self).sub(other);
5991    }
5992}
5993
5994impl GeometricProduct<Plane> for MotorDual {
5995    type Output = Motor;
5996
5997    fn geometric_product(self, other: Plane) -> Motor {
5998        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[2], other.group0()[1]]) * Simd32x4::from([1.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[1], other.group0()[2], other.group0()[1], other.group0()[0]]) * Simd32x4::from([1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[2], other.group0()[1], other.group0()[0], other.group0()[2]]) * Simd32x4::from([1.0, 1.0, -1.0, 0.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
5999    }
6000}
6001
6002impl RegressiveProduct<Plane> for MotorDual {
6003    type Output = Plane;
6004
6005    fn regressive_product(self, other: Plane) -> Plane {
6006        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() } }
6007    }
6008}
6009
6010impl OuterProduct<Plane> for MotorDual {
6011    type Output = Point;
6012
6013    fn outer_product(self, other: Plane) -> Point {
6014        Point { groups: PointGroups { g0: Simd32x3::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0) * Simd32x3::from([-1.0, 0.0, 1.0]) + Simd32x3::from(self.group0()[3]) * swizzle!(other.group0(), 1, 0, 1) * Simd32x3::from([1.0, -1.0, 0.0]) + Simd32x3::from([self.group0()[0], self.group0()[1], self.group0()[1]]) * swizzle!(other.group0(), 0, 2, 1) * Simd32x3::from([0.0, 1.0, -1.0]) } }
6015    }
6016}
6017
6018impl InnerProduct<Plane> for MotorDual {
6019    type Output = Motor;
6020
6021    fn inner_product(self, other: Plane) -> Motor {
6022        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group0()[1]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group0()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0, 0) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) } }
6023    }
6024}
6025
6026impl LeftContraction<Plane> for MotorDual {
6027    type Output = f32;
6028
6029    fn left_contraction(self, other: Plane) -> f32 {
6030        self.group0()[1] * other.group0()[0] + self.group0()[2] * other.group0()[1] + self.group0()[3] * other.group0()[2]
6031    }
6032}
6033
6034impl RightContraction<Plane> for MotorDual {
6035    type Output = Motor;
6036
6037    fn right_contraction(self, other: Plane) -> Motor {
6038        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group0()[1]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group0()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0, 0) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) } }
6039    }
6040}
6041
6042impl ScalarProduct<Plane> for MotorDual {
6043    type Output = f32;
6044
6045    fn scalar_product(self, other: Plane) -> f32 {
6046        self.group0()[1] * other.group0()[0] + self.group0()[2] * other.group0()[1] + self.group0()[3] * other.group0()[2]
6047    }
6048}
6049
6050impl GeometricProduct<Translator> for MotorDual {
6051    type Output = MotorDual;
6052
6053    fn geometric_product(self, other: Translator) -> MotorDual {
6054        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[2], other.group0()[1]]) * Simd32x4::from([0.0, 1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[1], other.group0()[2], other.group0()[0], other.group0()[1]]) * Simd32x4::from([1.0, 1.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[2], other.group0()[1], other.group0()[2], other.group0()[0]]) * Simd32x4::from([1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([1.0, 0.0, -1.0, -1.0]) } }
6055    }
6056}
6057
6058impl RegressiveProduct<Translator> for MotorDual {
6059    type Output = Translator;
6060
6061    fn regressive_product(self, other: Translator) -> Translator {
6062        Translator { groups: TranslatorGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() + Simd32x3::from(self.group0()[3]) * Simd32x3::from(other.group0()[2]) * Simd32x3::from([1.0, 0.0, 0.0]) + Simd32x3::from([self.group0()[2], self.group0()[0], self.group0()[0]]) * swizzle!(other.group0(), 1, 0, 0) * Simd32x3::from([1.0, 0.0, 0.0]) } }
6063    }
6064}
6065
6066impl OuterProduct<Translator> for MotorDual {
6067    type Output = MotorDual;
6068
6069    fn outer_product(self, other: Translator) -> MotorDual {
6070        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[1], other.group0()[1], other.group0()[0], other.group0()[1]]) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[2], other.group0()[2], other.group0()[2], other.group0()[0]]) * Simd32x4::from([1.0, 0.0, 0.0, 1.0]) + swizzle!(self.group0(), 0, 1, 0, 0) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) } }
6071    }
6072}
6073
6074impl InnerProduct<Translator> for MotorDual {
6075    type Output = MotorDual;
6076
6077    fn inner_product(self, other: Translator) -> MotorDual {
6078        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[2], other.group0()[1]]) * Simd32x4::from([0.0, 1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[2], other.group0()[2], other.group0()[0], other.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[1], other.group0()[1], other.group0()[1], other.group0()[0]]) * Simd32x4::from([0.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([1.0, 0.0, -1.0, -1.0]) } }
6079    }
6080}
6081
6082impl LeftContraction<Translator> for MotorDual {
6083    type Output = Plane;
6084
6085    fn left_contraction(self, other: Translator) -> Plane {
6086        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[3]) * Simd32x3::from(other.group0()[1]) * Simd32x3::from([-1.0, 0.0, 0.0]) + Simd32x3::from([self.group0()[2], self.group0()[1], self.group0()[1]]) * swizzle!(other.group0(), 2, 2, 1) * Simd32x3::from([1.0, -1.0, 1.0]) } }
6087    }
6088}
6089
6090impl RightContraction<Translator> for MotorDual {
6091    type Output = MotorDual;
6092
6093    fn right_contraction(self, other: Translator) -> MotorDual {
6094        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, 0.0, 1.0]) + swizzle!(self.group0(), 0, 1, 0, 0) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([1.0, 1.0, -1.0, -1.0]) } }
6095    }
6096}
6097
6098impl Add<Motor> for MotorDual {
6099    type Output = MultiVector;
6100
6101    fn add(self, other: Motor) -> MultiVector {
6102        MultiVector { groups: MultiVectorGroups { g0: swizzle!(self.group0(), 0, 0, 3, 2) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) + swizzle!(other.group0(), 0, 1, 0, 0) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]), g1: swizzle!(self.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + swizzle!(other.group0(), 0, 0, 2, 3) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) } }
6103    }
6104}
6105
6106impl Sub<Motor> for MotorDual {
6107    type Output = MultiVector;
6108
6109    fn sub(self, other: Motor) -> MultiVector {
6110        MultiVector { groups: MultiVectorGroups { g0: swizzle!(self.group0(), 0, 0, 3, 2) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) - swizzle!(other.group0(), 0, 1, 0, 0) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]), g1: swizzle!(self.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) - swizzle!(other.group0(), 0, 0, 2, 3) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) } }
6111    }
6112}
6113
6114impl GeometricProduct<Motor> for MotorDual {
6115    type Output = MotorDual;
6116
6117    fn geometric_product(self, other: Motor) -> MotorDual {
6118        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) + Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([1.0, 1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 3, 0, 1) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([1.0, -1.0, 1.0, 1.0]) } }
6119    }
6120}
6121
6122impl RegressiveProduct<Motor> for MotorDual {
6123    type Output = Motor;
6124
6125    fn regressive_product(self, other: Motor) -> Motor {
6126        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group0()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group0()[3]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0, 0) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
6127    }
6128}
6129
6130impl OuterProduct<Motor> for MotorDual {
6131    type Output = MotorDual;
6132
6133    fn outer_product(self, other: Motor) -> MotorDual {
6134        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0, 1, 1) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
6135    }
6136}
6137
6138impl InnerProduct<Motor> for MotorDual {
6139    type Output = MotorDual;
6140
6141    fn inner_product(self, other: Motor) -> MotorDual {
6142        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 3, 3, 0, 1) * Simd32x4::from([0.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 2, 2, 1, 0) * Simd32x4::from([0.0, -1.0, 1.0, 1.0]) + swizzle!(self.group0(), 0, 1, 1, 1) * swizzle!(other.group0(), 0, 0, 3, 2) * Simd32x4::from([0.0, 1.0, -1.0, 1.0]) } }
6143    }
6144}
6145
6146impl LeftContraction<Motor> for MotorDual {
6147    type Output = Plane;
6148
6149    fn left_contraction(self, other: Motor) -> Plane {
6150        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[2]) * Simd32x3::from([other.group0()[3], other.group0()[3], other.group0()[1]]) * Simd32x3::from([1.0, 0.0, -1.0]) + Simd32x3::from(self.group0()[3]) * Simd32x3::from([other.group0()[2], other.group0()[1], other.group0()[2]]) * Simd32x3::from([-1.0, 1.0, 0.0]) + Simd32x3::from([self.group0()[0], self.group0()[1], self.group0()[1]]) * Simd32x3::from([other.group0()[0], other.group0()[3], other.group0()[2]]) * Simd32x3::from([0.0, -1.0, 1.0]) } }
6151    }
6152}
6153
6154impl RightContraction<Motor> for MotorDual {
6155    type Output = MotorDual;
6156
6157    fn right_contraction(self, other: Motor) -> MotorDual {
6158        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) + self.group0() * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
6159    }
6160}
6161
6162impl Add<MotorDual> for MotorDual {
6163    type Output = MotorDual;
6164
6165    fn add(self, other: MotorDual) -> MotorDual {
6166        MotorDual { groups: MotorDualGroups { g0: self.group0() + other.group0() } }
6167    }
6168}
6169
6170impl AddAssign<MotorDual> for MotorDual {
6171    fn add_assign(&mut self, other: MotorDual) {
6172        *self = (*self).add(other);
6173    }
6174}
6175
6176impl Sub<MotorDual> for MotorDual {
6177    type Output = MotorDual;
6178
6179    fn sub(self, other: MotorDual) -> MotorDual {
6180        MotorDual { groups: MotorDualGroups { g0: self.group0() - other.group0() } }
6181    }
6182}
6183
6184impl SubAssign<MotorDual> for MotorDual {
6185    fn sub_assign(&mut self, other: MotorDual) {
6186        *self = (*self).sub(other);
6187    }
6188}
6189
6190impl Mul<MotorDual> for MotorDual {
6191    type Output = MotorDual;
6192
6193    fn mul(self, other: MotorDual) -> MotorDual {
6194        MotorDual { groups: MotorDualGroups { g0: self.group0() * other.group0() } }
6195    }
6196}
6197
6198impl MulAssign<MotorDual> for MotorDual {
6199    fn mul_assign(&mut self, other: MotorDual) {
6200        *self = (*self).mul(other);
6201    }
6202}
6203
6204impl Div<MotorDual> for MotorDual {
6205    type Output = MotorDual;
6206
6207    fn div(self, other: MotorDual) -> MotorDual {
6208        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[1], self.group0()[2], self.group0()[3]]) * Simd32x4::from([1.0, 1.0, 1.0, 1.0]) / Simd32x4::from([other.group0()[0], other.group0()[1], other.group0()[2], other.group0()[3]]) * Simd32x4::from([1.0, 1.0, 1.0, 1.0]) } }
6209    }
6210}
6211
6212impl DivAssign<MotorDual> for MotorDual {
6213    fn div_assign(&mut self, other: MotorDual) {
6214        *self = (*self).div(other);
6215    }
6216}
6217
6218impl GeometricProduct<MotorDual> for MotorDual {
6219    type Output = Motor;
6220
6221    fn geometric_product(self, other: MotorDual) -> Motor {
6222        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) + Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 3, 0, 1) * Simd32x4::from([1.0, -1.0, 1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([1.0, 1.0, -1.0, 1.0]) } }
6223    }
6224}
6225
6226impl RegressiveProduct<MotorDual> for MotorDual {
6227    type Output = MotorDual;
6228
6229    fn regressive_product(self, other: MotorDual) -> MotorDual {
6230        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + self.group0() * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
6231    }
6232}
6233
6234impl OuterProduct<MotorDual> for MotorDual {
6235    type Output = Point;
6236
6237    fn outer_product(self, other: MotorDual) -> Point {
6238        Point { groups: PointGroups { g0: Simd32x3::from(self.group0()[2]) * Simd32x3::from([other.group0()[3], other.group0()[3], other.group0()[1]]) * Simd32x3::from([-1.0, 0.0, 1.0]) + Simd32x3::from(self.group0()[3]) * Simd32x3::from([other.group0()[2], other.group0()[1], other.group0()[2]]) * Simd32x3::from([1.0, -1.0, 0.0]) + Simd32x3::from([self.group0()[0], self.group0()[1], self.group0()[1]]) * Simd32x3::from([other.group0()[0], other.group0()[3], other.group0()[2]]) * Simd32x3::from([0.0, 1.0, -1.0]) } }
6239    }
6240}
6241
6242impl InnerProduct<MotorDual> for MotorDual {
6243    type Output = Motor;
6244
6245    fn inner_product(self, other: MotorDual) -> Motor {
6246        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, 1.0]) + swizzle!(self.group0(), 1, 1, 0, 0) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) } }
6247    }
6248}
6249
6250impl LeftContraction<MotorDual> for MotorDual {
6251    type Output = Motor;
6252
6253    fn left_contraction(self, other: MotorDual) -> Motor {
6254        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0, 1, 1) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) } }
6255    }
6256}
6257
6258impl RightContraction<MotorDual> for MotorDual {
6259    type Output = Motor;
6260
6261    fn right_contraction(self, other: MotorDual) -> Motor {
6262        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group0()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group0()[3]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0, 0) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
6263    }
6264}
6265
6266impl ScalarProduct<MotorDual> for MotorDual {
6267    type Output = f32;
6268
6269    fn scalar_product(self, other: MotorDual) -> f32 {
6270        0.0 - self.group0()[0] * other.group0()[0] + self.group0()[1] * other.group0()[1] + self.group0()[2] * other.group0()[2] + self.group0()[3] * other.group0()[3]
6271    }
6272}
6273
6274impl SquaredMagnitude for MotorDual {
6275    type Output = f32;
6276
6277    fn squared_magnitude(self) -> f32 {
6278        self.scalar_product(self.reversal())
6279    }
6280}
6281
6282impl Magnitude for MotorDual {
6283    type Output = f32;
6284
6285    fn magnitude(self) -> f32 {
6286        self.squared_magnitude().sqrt()
6287    }
6288}
6289
6290impl Mul<f32> for MotorDual {
6291    type Output = MotorDual;
6292
6293    fn mul(self, other: f32) -> MotorDual {
6294        self.geometric_product(other)
6295    }
6296}
6297
6298impl MulAssign<f32> for MotorDual {
6299    fn mul_assign(&mut self, other: f32) {
6300        *self = (*self).mul(other);
6301    }
6302}
6303
6304impl Signum for MotorDual {
6305    type Output = MotorDual;
6306
6307    fn signum(self) -> MotorDual {
6308        self.geometric_product(1.0 / self.magnitude())
6309    }
6310}
6311
6312impl Inverse for MotorDual {
6313    type Output = MotorDual;
6314
6315    fn inverse(self) -> MotorDual {
6316        self.reversal().geometric_product(1.0 / self.squared_magnitude())
6317    }
6318}
6319
6320impl GeometricQuotient<IdealPoint> for IdealPoint {
6321    type Output = Rotor;
6322
6323    fn geometric_quotient(self, other: IdealPoint) -> Rotor {
6324        self.geometric_product(other.inverse())
6325    }
6326}
6327
6328impl Transformation<IdealPoint> for IdealPoint {
6329    type Output = IdealPoint;
6330
6331    fn transformation(self, other: IdealPoint) -> IdealPoint {
6332        self.geometric_product(other).geometric_product(self.reversal())
6333    }
6334}
6335
6336impl GeometricQuotient<Motor> for IdealPoint {
6337    type Output = Motor;
6338
6339    fn geometric_quotient(self, other: Motor) -> Motor {
6340        self.geometric_product(other.inverse())
6341    }
6342}
6343
6344impl Transformation<Motor> for IdealPoint {
6345    type Output = Motor;
6346
6347    fn transformation(self, other: Motor) -> Motor {
6348        self.geometric_product(other).geometric_product(self.reversal())
6349    }
6350}
6351
6352impl GeometricQuotient<MotorDual> for IdealPoint {
6353    type Output = MotorDual;
6354
6355    fn geometric_quotient(self, other: MotorDual) -> MotorDual {
6356        self.geometric_product(other.inverse())
6357    }
6358}
6359
6360impl Transformation<MotorDual> for IdealPoint {
6361    type Output = MotorDual;
6362
6363    fn transformation(self, other: MotorDual) -> MotorDual {
6364        self.geometric_product(other).geometric_product(self.reversal())
6365    }
6366}
6367
6368impl GeometricQuotient<MultiVector> for IdealPoint {
6369    type Output = MultiVector;
6370
6371    fn geometric_quotient(self, other: MultiVector) -> MultiVector {
6372        self.geometric_product(other.inverse())
6373    }
6374}
6375
6376impl Transformation<MultiVector> for IdealPoint {
6377    type Output = MultiVector;
6378
6379    fn transformation(self, other: MultiVector) -> MultiVector {
6380        self.geometric_product(other).geometric_product(self.reversal())
6381    }
6382}
6383
6384impl GeometricQuotient<Plane> for IdealPoint {
6385    type Output = MotorDual;
6386
6387    fn geometric_quotient(self, other: Plane) -> MotorDual {
6388        self.geometric_product(other.inverse())
6389    }
6390}
6391
6392impl Transformation<Plane> for IdealPoint {
6393    type Output = Plane;
6394
6395    fn transformation(self, other: Plane) -> Plane {
6396        self.geometric_product(other).geometric_product(self.reversal()).into()
6397    }
6398}
6399
6400impl GeometricQuotient<Point> for IdealPoint {
6401    type Output = Motor;
6402
6403    fn geometric_quotient(self, other: Point) -> Motor {
6404        self.geometric_product(other.inverse())
6405    }
6406}
6407
6408impl Transformation<Point> for IdealPoint {
6409    type Output = Point;
6410
6411    fn transformation(self, other: Point) -> Point {
6412        self.geometric_product(other).geometric_product(self.reversal()).into()
6413    }
6414}
6415
6416impl GeometricQuotient<Rotor> for IdealPoint {
6417    type Output = IdealPoint;
6418
6419    fn geometric_quotient(self, other: Rotor) -> IdealPoint {
6420        self.geometric_product(other.inverse())
6421    }
6422}
6423
6424impl Transformation<Rotor> for IdealPoint {
6425    type Output = Rotor;
6426
6427    fn transformation(self, other: Rotor) -> Rotor {
6428        self.geometric_product(other).geometric_product(self.reversal())
6429    }
6430}
6431
6432impl GeometricQuotient<f32> for IdealPoint {
6433    type Output = IdealPoint;
6434
6435    fn geometric_quotient(self, other: f32) -> IdealPoint {
6436        self.geometric_product(other.inverse())
6437    }
6438}
6439
6440impl Transformation<f32> for IdealPoint {
6441    type Output = f32;
6442
6443    fn transformation(self, other: f32) -> f32 {
6444        self.geometric_product(other).geometric_product(self.reversal()).into()
6445    }
6446}
6447
6448impl GeometricQuotient<Translator> for IdealPoint {
6449    type Output = Motor;
6450
6451    fn geometric_quotient(self, other: Translator) -> Motor {
6452        self.geometric_product(other.inverse())
6453    }
6454}
6455
6456impl Transformation<Translator> for IdealPoint {
6457    type Output = Translator;
6458
6459    fn transformation(self, other: Translator) -> Translator {
6460        self.geometric_product(other).geometric_product(self.reversal()).into()
6461    }
6462}
6463
6464impl GeometricQuotient<IdealPoint> for Motor {
6465    type Output = Motor;
6466
6467    fn geometric_quotient(self, other: IdealPoint) -> Motor {
6468        self.geometric_product(other.inverse())
6469    }
6470}
6471
6472impl Transformation<IdealPoint> for Motor {
6473    type Output = IdealPoint;
6474
6475    fn transformation(self, other: IdealPoint) -> IdealPoint {
6476        self.geometric_product(other).geometric_product(self.reversal()).into()
6477    }
6478}
6479
6480impl Powi for Motor {
6481    type Output = Motor;
6482
6483    fn powi(self, exponent: isize) -> Motor {
6484        if exponent == 0 {
6485            return Motor::one();
6486        }
6487        let mut x: Motor = if exponent < 0 { self.inverse() } else { self };
6488        let mut y: Motor = Motor::one();
6489        let mut n: isize = exponent.abs();
6490        while 1 < n {
6491            if n & 1 == 1 {
6492                y = x.geometric_product(y);
6493            }
6494            x = x.geometric_product(x);
6495            n = n >> 1;
6496        }
6497        x.geometric_product(y)
6498    }
6499}
6500
6501impl GeometricQuotient<Motor> for Motor {
6502    type Output = Motor;
6503
6504    fn geometric_quotient(self, other: Motor) -> Motor {
6505        self.geometric_product(other.inverse())
6506    }
6507}
6508
6509impl Transformation<Motor> for Motor {
6510    type Output = Motor;
6511
6512    fn transformation(self, other: Motor) -> Motor {
6513        self.geometric_product(other).geometric_product(self.reversal())
6514    }
6515}
6516
6517impl GeometricQuotient<MotorDual> for Motor {
6518    type Output = MotorDual;
6519
6520    fn geometric_quotient(self, other: MotorDual) -> MotorDual {
6521        self.geometric_product(other.inverse())
6522    }
6523}
6524
6525impl Transformation<MotorDual> for Motor {
6526    type Output = MotorDual;
6527
6528    fn transformation(self, other: MotorDual) -> MotorDual {
6529        self.geometric_product(other).geometric_product(self.reversal())
6530    }
6531}
6532
6533impl GeometricQuotient<MultiVector> for Motor {
6534    type Output = MultiVector;
6535
6536    fn geometric_quotient(self, other: MultiVector) -> MultiVector {
6537        self.geometric_product(other.inverse())
6538    }
6539}
6540
6541impl Transformation<MultiVector> for Motor {
6542    type Output = MultiVector;
6543
6544    fn transformation(self, other: MultiVector) -> MultiVector {
6545        self.geometric_product(other).geometric_product(self.reversal())
6546    }
6547}
6548
6549impl GeometricQuotient<Plane> for Motor {
6550    type Output = MotorDual;
6551
6552    fn geometric_quotient(self, other: Plane) -> MotorDual {
6553        self.geometric_product(other.inverse())
6554    }
6555}
6556
6557impl Transformation<Plane> for Motor {
6558    type Output = Plane;
6559
6560    fn transformation(self, other: Plane) -> Plane {
6561        self.geometric_product(other).geometric_product(self.reversal()).into()
6562    }
6563}
6564
6565impl GeometricQuotient<Point> for Motor {
6566    type Output = Motor;
6567
6568    fn geometric_quotient(self, other: Point) -> Motor {
6569        self.geometric_product(other.inverse())
6570    }
6571}
6572
6573impl Transformation<Point> for Motor {
6574    type Output = Point;
6575
6576    fn transformation(self, other: Point) -> Point {
6577        self.geometric_product(other).geometric_product(self.reversal()).into()
6578    }
6579}
6580
6581impl GeometricQuotient<Rotor> for Motor {
6582    type Output = Motor;
6583
6584    fn geometric_quotient(self, other: Rotor) -> Motor {
6585        self.geometric_product(other.inverse())
6586    }
6587}
6588
6589impl Transformation<Rotor> for Motor {
6590    type Output = Rotor;
6591
6592    fn transformation(self, other: Rotor) -> Rotor {
6593        self.geometric_product(other).geometric_product(self.reversal()).into()
6594    }
6595}
6596
6597impl GeometricQuotient<f32> for Motor {
6598    type Output = Motor;
6599
6600    fn geometric_quotient(self, other: f32) -> Motor {
6601        self.geometric_product(other.inverse())
6602    }
6603}
6604
6605impl Transformation<f32> for Motor {
6606    type Output = f32;
6607
6608    fn transformation(self, other: f32) -> f32 {
6609        self.geometric_product(other).geometric_product(self.reversal()).into()
6610    }
6611}
6612
6613impl GeometricQuotient<Translator> for Motor {
6614    type Output = Motor;
6615
6616    fn geometric_quotient(self, other: Translator) -> Motor {
6617        self.geometric_product(other.inverse())
6618    }
6619}
6620
6621impl Transformation<Translator> for Motor {
6622    type Output = Translator;
6623
6624    fn transformation(self, other: Translator) -> Translator {
6625        self.geometric_product(other).geometric_product(self.reversal()).into()
6626    }
6627}
6628
6629impl GeometricQuotient<IdealPoint> for MotorDual {
6630    type Output = MotorDual;
6631
6632    fn geometric_quotient(self, other: IdealPoint) -> MotorDual {
6633        self.geometric_product(other.inverse())
6634    }
6635}
6636
6637impl Transformation<IdealPoint> for MotorDual {
6638    type Output = IdealPoint;
6639
6640    fn transformation(self, other: IdealPoint) -> IdealPoint {
6641        self.geometric_product(other).geometric_product(self.reversal()).into()
6642    }
6643}
6644
6645impl GeometricQuotient<Motor> for MotorDual {
6646    type Output = MotorDual;
6647
6648    fn geometric_quotient(self, other: Motor) -> MotorDual {
6649        self.geometric_product(other.inverse())
6650    }
6651}
6652
6653impl Transformation<Motor> for MotorDual {
6654    type Output = Motor;
6655
6656    fn transformation(self, other: Motor) -> Motor {
6657        self.geometric_product(other).geometric_product(self.reversal())
6658    }
6659}
6660
6661impl GeometricQuotient<MotorDual> for MotorDual {
6662    type Output = Motor;
6663
6664    fn geometric_quotient(self, other: MotorDual) -> Motor {
6665        self.geometric_product(other.inverse())
6666    }
6667}
6668
6669impl Transformation<MotorDual> for MotorDual {
6670    type Output = MotorDual;
6671
6672    fn transformation(self, other: MotorDual) -> MotorDual {
6673        self.geometric_product(other).geometric_product(self.reversal())
6674    }
6675}
6676
6677impl GeometricQuotient<MultiVector> for MotorDual {
6678    type Output = MultiVector;
6679
6680    fn geometric_quotient(self, other: MultiVector) -> MultiVector {
6681        self.geometric_product(other.inverse())
6682    }
6683}
6684
6685impl Transformation<MultiVector> for MotorDual {
6686    type Output = MultiVector;
6687
6688    fn transformation(self, other: MultiVector) -> MultiVector {
6689        self.geometric_product(other).geometric_product(self.reversal())
6690    }
6691}
6692
6693impl GeometricQuotient<Plane> for MotorDual {
6694    type Output = Motor;
6695
6696    fn geometric_quotient(self, other: Plane) -> Motor {
6697        self.geometric_product(other.inverse())
6698    }
6699}
6700
6701impl Transformation<Plane> for MotorDual {
6702    type Output = Plane;
6703
6704    fn transformation(self, other: Plane) -> Plane {
6705        self.geometric_product(other).geometric_product(self.reversal()).into()
6706    }
6707}
6708
6709impl GeometricQuotient<Point> for MotorDual {
6710    type Output = MotorDual;
6711
6712    fn geometric_quotient(self, other: Point) -> MotorDual {
6713        self.geometric_product(other.inverse())
6714    }
6715}
6716
6717impl Transformation<Point> for MotorDual {
6718    type Output = Point;
6719
6720    fn transformation(self, other: Point) -> Point {
6721        self.geometric_product(other).geometric_product(self.reversal()).into()
6722    }
6723}
6724
6725impl GeometricQuotient<Rotor> for MotorDual {
6726    type Output = MotorDual;
6727
6728    fn geometric_quotient(self, other: Rotor) -> MotorDual {
6729        self.geometric_product(other.inverse())
6730    }
6731}
6732
6733impl Transformation<Rotor> for MotorDual {
6734    type Output = Rotor;
6735
6736    fn transformation(self, other: Rotor) -> Rotor {
6737        self.geometric_product(other).geometric_product(self.reversal()).into()
6738    }
6739}
6740
6741impl GeometricQuotient<f32> for MotorDual {
6742    type Output = MotorDual;
6743
6744    fn geometric_quotient(self, other: f32) -> MotorDual {
6745        self.geometric_product(other.inverse())
6746    }
6747}
6748
6749impl Transformation<f32> for MotorDual {
6750    type Output = f32;
6751
6752    fn transformation(self, other: f32) -> f32 {
6753        self.geometric_product(other).geometric_product(self.reversal()).into()
6754    }
6755}
6756
6757impl GeometricQuotient<Translator> for MotorDual {
6758    type Output = MotorDual;
6759
6760    fn geometric_quotient(self, other: Translator) -> MotorDual {
6761        self.geometric_product(other.inverse())
6762    }
6763}
6764
6765impl Transformation<Translator> for MotorDual {
6766    type Output = Translator;
6767
6768    fn transformation(self, other: Translator) -> Translator {
6769        self.geometric_product(other).geometric_product(self.reversal()).into()
6770    }
6771}
6772
6773impl GeometricQuotient<IdealPoint> for MultiVector {
6774    type Output = MultiVector;
6775
6776    fn geometric_quotient(self, other: IdealPoint) -> MultiVector {
6777        self.geometric_product(other.inverse())
6778    }
6779}
6780
6781impl Transformation<IdealPoint> for MultiVector {
6782    type Output = IdealPoint;
6783
6784    fn transformation(self, other: IdealPoint) -> IdealPoint {
6785        self.geometric_product(other).geometric_product(self.reversal()).into()
6786    }
6787}
6788
6789impl GeometricQuotient<Motor> for MultiVector {
6790    type Output = MultiVector;
6791
6792    fn geometric_quotient(self, other: Motor) -> MultiVector {
6793        self.geometric_product(other.inverse())
6794    }
6795}
6796
6797impl Transformation<Motor> for MultiVector {
6798    type Output = Motor;
6799
6800    fn transformation(self, other: Motor) -> Motor {
6801        self.geometric_product(other).geometric_product(self.reversal()).into()
6802    }
6803}
6804
6805impl GeometricQuotient<MotorDual> for MultiVector {
6806    type Output = MultiVector;
6807
6808    fn geometric_quotient(self, other: MotorDual) -> MultiVector {
6809        self.geometric_product(other.inverse())
6810    }
6811}
6812
6813impl Transformation<MotorDual> for MultiVector {
6814    type Output = MotorDual;
6815
6816    fn transformation(self, other: MotorDual) -> MotorDual {
6817        self.geometric_product(other).geometric_product(self.reversal()).into()
6818    }
6819}
6820
6821impl Powi for MultiVector {
6822    type Output = MultiVector;
6823
6824    fn powi(self, exponent: isize) -> MultiVector {
6825        if exponent == 0 {
6826            return MultiVector::one();
6827        }
6828        let mut x: MultiVector = if exponent < 0 { self.inverse() } else { self };
6829        let mut y: MultiVector = MultiVector::one();
6830        let mut n: isize = exponent.abs();
6831        while 1 < n {
6832            if n & 1 == 1 {
6833                y = x.geometric_product(y);
6834            }
6835            x = x.geometric_product(x);
6836            n = n >> 1;
6837        }
6838        x.geometric_product(y)
6839    }
6840}
6841
6842impl GeometricQuotient<MultiVector> for MultiVector {
6843    type Output = MultiVector;
6844
6845    fn geometric_quotient(self, other: MultiVector) -> MultiVector {
6846        self.geometric_product(other.inverse())
6847    }
6848}
6849
6850impl Transformation<MultiVector> for MultiVector {
6851    type Output = MultiVector;
6852
6853    fn transformation(self, other: MultiVector) -> MultiVector {
6854        self.geometric_product(other).geometric_product(self.reversal())
6855    }
6856}
6857
6858impl GeometricQuotient<Plane> for MultiVector {
6859    type Output = MultiVector;
6860
6861    fn geometric_quotient(self, other: Plane) -> MultiVector {
6862        self.geometric_product(other.inverse())
6863    }
6864}
6865
6866impl Transformation<Plane> for MultiVector {
6867    type Output = Plane;
6868
6869    fn transformation(self, other: Plane) -> Plane {
6870        self.geometric_product(other).geometric_product(self.reversal()).into()
6871    }
6872}
6873
6874impl GeometricQuotient<Point> for MultiVector {
6875    type Output = MultiVector;
6876
6877    fn geometric_quotient(self, other: Point) -> MultiVector {
6878        self.geometric_product(other.inverse())
6879    }
6880}
6881
6882impl Transformation<Point> for MultiVector {
6883    type Output = Point;
6884
6885    fn transformation(self, other: Point) -> Point {
6886        self.geometric_product(other).geometric_product(self.reversal()).into()
6887    }
6888}
6889
6890impl GeometricQuotient<Rotor> for MultiVector {
6891    type Output = MultiVector;
6892
6893    fn geometric_quotient(self, other: Rotor) -> MultiVector {
6894        self.geometric_product(other.inverse())
6895    }
6896}
6897
6898impl Transformation<Rotor> for MultiVector {
6899    type Output = Rotor;
6900
6901    fn transformation(self, other: Rotor) -> Rotor {
6902        self.geometric_product(other).geometric_product(self.reversal()).into()
6903    }
6904}
6905
6906impl GeometricQuotient<f32> for MultiVector {
6907    type Output = MultiVector;
6908
6909    fn geometric_quotient(self, other: f32) -> MultiVector {
6910        self.geometric_product(other.inverse())
6911    }
6912}
6913
6914impl Transformation<f32> for MultiVector {
6915    type Output = f32;
6916
6917    fn transformation(self, other: f32) -> f32 {
6918        self.geometric_product(other).geometric_product(self.reversal()).into()
6919    }
6920}
6921
6922impl GeometricQuotient<Translator> for MultiVector {
6923    type Output = MultiVector;
6924
6925    fn geometric_quotient(self, other: Translator) -> MultiVector {
6926        self.geometric_product(other.inverse())
6927    }
6928}
6929
6930impl Transformation<Translator> for MultiVector {
6931    type Output = Translator;
6932
6933    fn transformation(self, other: Translator) -> Translator {
6934        self.geometric_product(other).geometric_product(self.reversal()).into()
6935    }
6936}
6937
6938impl GeometricQuotient<IdealPoint> for Plane {
6939    type Output = MotorDual;
6940
6941    fn geometric_quotient(self, other: IdealPoint) -> MotorDual {
6942        self.geometric_product(other.inverse())
6943    }
6944}
6945
6946impl Transformation<IdealPoint> for Plane {
6947    type Output = IdealPoint;
6948
6949    fn transformation(self, other: IdealPoint) -> IdealPoint {
6950        self.geometric_product(other).geometric_product(self.reversal()).into()
6951    }
6952}
6953
6954impl GeometricQuotient<Motor> for Plane {
6955    type Output = MotorDual;
6956
6957    fn geometric_quotient(self, other: Motor) -> MotorDual {
6958        self.geometric_product(other.inverse())
6959    }
6960}
6961
6962impl Transformation<Motor> for Plane {
6963    type Output = Motor;
6964
6965    fn transformation(self, other: Motor) -> Motor {
6966        self.geometric_product(other).geometric_product(self.reversal())
6967    }
6968}
6969
6970impl GeometricQuotient<MotorDual> for Plane {
6971    type Output = Motor;
6972
6973    fn geometric_quotient(self, other: MotorDual) -> Motor {
6974        self.geometric_product(other.inverse())
6975    }
6976}
6977
6978impl Transformation<MotorDual> for Plane {
6979    type Output = MotorDual;
6980
6981    fn transformation(self, other: MotorDual) -> MotorDual {
6982        self.geometric_product(other).geometric_product(self.reversal())
6983    }
6984}
6985
6986impl GeometricQuotient<MultiVector> for Plane {
6987    type Output = MultiVector;
6988
6989    fn geometric_quotient(self, other: MultiVector) -> MultiVector {
6990        self.geometric_product(other.inverse())
6991    }
6992}
6993
6994impl Transformation<MultiVector> for Plane {
6995    type Output = MultiVector;
6996
6997    fn transformation(self, other: MultiVector) -> MultiVector {
6998        self.geometric_product(other).geometric_product(self.reversal())
6999    }
7000}
7001
7002impl GeometricQuotient<Plane> for Plane {
7003    type Output = Motor;
7004
7005    fn geometric_quotient(self, other: Plane) -> Motor {
7006        self.geometric_product(other.inverse())
7007    }
7008}
7009
7010impl Transformation<Plane> for Plane {
7011    type Output = Plane;
7012
7013    fn transformation(self, other: Plane) -> Plane {
7014        self.geometric_product(other).geometric_product(self.reversal()).into()
7015    }
7016}
7017
7018impl GeometricQuotient<Point> for Plane {
7019    type Output = MotorDual;
7020
7021    fn geometric_quotient(self, other: Point) -> MotorDual {
7022        self.geometric_product(other.inverse())
7023    }
7024}
7025
7026impl Transformation<Point> for Plane {
7027    type Output = Point;
7028
7029    fn transformation(self, other: Point) -> Point {
7030        self.geometric_product(other).geometric_product(self.reversal()).into()
7031    }
7032}
7033
7034impl GeometricQuotient<Rotor> for Plane {
7035    type Output = MotorDual;
7036
7037    fn geometric_quotient(self, other: Rotor) -> MotorDual {
7038        self.geometric_product(other.inverse())
7039    }
7040}
7041
7042impl Transformation<Rotor> for Plane {
7043    type Output = Rotor;
7044
7045    fn transformation(self, other: Rotor) -> Rotor {
7046        self.geometric_product(other).geometric_product(self.reversal()).into()
7047    }
7048}
7049
7050impl GeometricQuotient<f32> for Plane {
7051    type Output = Plane;
7052
7053    fn geometric_quotient(self, other: f32) -> Plane {
7054        self.geometric_product(other.inverse())
7055    }
7056}
7057
7058impl Transformation<f32> for Plane {
7059    type Output = f32;
7060
7061    fn transformation(self, other: f32) -> f32 {
7062        self.geometric_product(other).geometric_product(self.reversal()).into()
7063    }
7064}
7065
7066impl GeometricQuotient<Translator> for Plane {
7067    type Output = MotorDual;
7068
7069    fn geometric_quotient(self, other: Translator) -> MotorDual {
7070        self.geometric_product(other.inverse())
7071    }
7072}
7073
7074impl Transformation<Translator> for Plane {
7075    type Output = Translator;
7076
7077    fn transformation(self, other: Translator) -> Translator {
7078        self.geometric_product(other).geometric_product(self.reversal()).into()
7079    }
7080}
7081
7082impl GeometricQuotient<IdealPoint> for Point {
7083    type Output = Motor;
7084
7085    fn geometric_quotient(self, other: IdealPoint) -> Motor {
7086        self.geometric_product(other.inverse())
7087    }
7088}
7089
7090impl Transformation<IdealPoint> for Point {
7091    type Output = IdealPoint;
7092
7093    fn transformation(self, other: IdealPoint) -> IdealPoint {
7094        self.geometric_product(other).geometric_product(self.reversal()).into()
7095    }
7096}
7097
7098impl GeometricQuotient<Motor> for Point {
7099    type Output = Motor;
7100
7101    fn geometric_quotient(self, other: Motor) -> Motor {
7102        self.geometric_product(other.inverse())
7103    }
7104}
7105
7106impl Transformation<Motor> for Point {
7107    type Output = Motor;
7108
7109    fn transformation(self, other: Motor) -> Motor {
7110        self.geometric_product(other).geometric_product(self.reversal())
7111    }
7112}
7113
7114impl GeometricQuotient<MotorDual> for Point {
7115    type Output = MotorDual;
7116
7117    fn geometric_quotient(self, other: MotorDual) -> MotorDual {
7118        self.geometric_product(other.inverse())
7119    }
7120}
7121
7122impl Transformation<MotorDual> for Point {
7123    type Output = MotorDual;
7124
7125    fn transformation(self, other: MotorDual) -> MotorDual {
7126        self.geometric_product(other).geometric_product(self.reversal())
7127    }
7128}
7129
7130impl GeometricQuotient<MultiVector> for Point {
7131    type Output = MultiVector;
7132
7133    fn geometric_quotient(self, other: MultiVector) -> MultiVector {
7134        self.geometric_product(other.inverse())
7135    }
7136}
7137
7138impl Transformation<MultiVector> for Point {
7139    type Output = MultiVector;
7140
7141    fn transformation(self, other: MultiVector) -> MultiVector {
7142        self.geometric_product(other).geometric_product(self.reversal())
7143    }
7144}
7145
7146impl GeometricQuotient<Plane> for Point {
7147    type Output = MotorDual;
7148
7149    fn geometric_quotient(self, other: Plane) -> MotorDual {
7150        self.geometric_product(other.inverse())
7151    }
7152}
7153
7154impl Transformation<Plane> for Point {
7155    type Output = Plane;
7156
7157    fn transformation(self, other: Plane) -> Plane {
7158        self.geometric_product(other).geometric_product(self.reversal()).into()
7159    }
7160}
7161
7162impl GeometricQuotient<Point> for Point {
7163    type Output = Motor;
7164
7165    fn geometric_quotient(self, other: Point) -> Motor {
7166        self.geometric_product(other.inverse())
7167    }
7168}
7169
7170impl Transformation<Point> for Point {
7171    type Output = Point;
7172
7173    fn transformation(self, other: Point) -> Point {
7174        self.geometric_product(other).geometric_product(self.reversal()).into()
7175    }
7176}
7177
7178impl GeometricQuotient<Rotor> for Point {
7179    type Output = Motor;
7180
7181    fn geometric_quotient(self, other: Rotor) -> Motor {
7182        self.geometric_product(other.inverse())
7183    }
7184}
7185
7186impl Transformation<Rotor> for Point {
7187    type Output = Rotor;
7188
7189    fn transformation(self, other: Rotor) -> Rotor {
7190        self.geometric_product(other).geometric_product(self.reversal()).into()
7191    }
7192}
7193
7194impl GeometricQuotient<f32> for Point {
7195    type Output = Point;
7196
7197    fn geometric_quotient(self, other: f32) -> Point {
7198        self.geometric_product(other.inverse())
7199    }
7200}
7201
7202impl Transformation<f32> for Point {
7203    type Output = f32;
7204
7205    fn transformation(self, other: f32) -> f32 {
7206        self.geometric_product(other).geometric_product(self.reversal()).into()
7207    }
7208}
7209
7210impl GeometricQuotient<Translator> for Point {
7211    type Output = Motor;
7212
7213    fn geometric_quotient(self, other: Translator) -> Motor {
7214        self.geometric_product(other.inverse())
7215    }
7216}
7217
7218impl Transformation<Translator> for Point {
7219    type Output = Translator;
7220
7221    fn transformation(self, other: Translator) -> Translator {
7222        self.geometric_product(other).geometric_product(self.reversal()).into()
7223    }
7224}
7225
7226impl GeometricQuotient<IdealPoint> for Rotor {
7227    type Output = IdealPoint;
7228
7229    fn geometric_quotient(self, other: IdealPoint) -> IdealPoint {
7230        self.geometric_product(other.inverse())
7231    }
7232}
7233
7234impl Transformation<IdealPoint> for Rotor {
7235    type Output = IdealPoint;
7236
7237    fn transformation(self, other: IdealPoint) -> IdealPoint {
7238        self.geometric_product(other).geometric_product(self.reversal())
7239    }
7240}
7241
7242impl GeometricQuotient<Motor> for Rotor {
7243    type Output = Motor;
7244
7245    fn geometric_quotient(self, other: Motor) -> Motor {
7246        self.geometric_product(other.inverse())
7247    }
7248}
7249
7250impl Transformation<Motor> for Rotor {
7251    type Output = Motor;
7252
7253    fn transformation(self, other: Motor) -> Motor {
7254        self.geometric_product(other).geometric_product(self.reversal())
7255    }
7256}
7257
7258impl GeometricQuotient<MotorDual> for Rotor {
7259    type Output = MotorDual;
7260
7261    fn geometric_quotient(self, other: MotorDual) -> MotorDual {
7262        self.geometric_product(other.inverse())
7263    }
7264}
7265
7266impl Transformation<MotorDual> for Rotor {
7267    type Output = MotorDual;
7268
7269    fn transformation(self, other: MotorDual) -> MotorDual {
7270        self.geometric_product(other).geometric_product(self.reversal())
7271    }
7272}
7273
7274impl GeometricQuotient<MultiVector> for Rotor {
7275    type Output = MultiVector;
7276
7277    fn geometric_quotient(self, other: MultiVector) -> MultiVector {
7278        self.geometric_product(other.inverse())
7279    }
7280}
7281
7282impl Transformation<MultiVector> for Rotor {
7283    type Output = MultiVector;
7284
7285    fn transformation(self, other: MultiVector) -> MultiVector {
7286        self.geometric_product(other).geometric_product(self.reversal())
7287    }
7288}
7289
7290impl GeometricQuotient<Plane> for Rotor {
7291    type Output = MotorDual;
7292
7293    fn geometric_quotient(self, other: Plane) -> MotorDual {
7294        self.geometric_product(other.inverse())
7295    }
7296}
7297
7298impl Transformation<Plane> for Rotor {
7299    type Output = Plane;
7300
7301    fn transformation(self, other: Plane) -> Plane {
7302        self.geometric_product(other).geometric_product(self.reversal()).into()
7303    }
7304}
7305
7306impl GeometricQuotient<Point> for Rotor {
7307    type Output = Motor;
7308
7309    fn geometric_quotient(self, other: Point) -> Motor {
7310        self.geometric_product(other.inverse())
7311    }
7312}
7313
7314impl Transformation<Point> for Rotor {
7315    type Output = Point;
7316
7317    fn transformation(self, other: Point) -> Point {
7318        self.geometric_product(other).geometric_product(self.reversal()).into()
7319    }
7320}
7321
7322impl Powi for Rotor {
7323    type Output = Rotor;
7324
7325    fn powi(self, exponent: isize) -> Rotor {
7326        if exponent == 0 {
7327            return Rotor::one();
7328        }
7329        let mut x: Rotor = if exponent < 0 { self.inverse() } else { self };
7330        let mut y: Rotor = Rotor::one();
7331        let mut n: isize = exponent.abs();
7332        while 1 < n {
7333            if n & 1 == 1 {
7334                y = x.geometric_product(y);
7335            }
7336            x = x.geometric_product(x);
7337            n = n >> 1;
7338        }
7339        x.geometric_product(y)
7340    }
7341}
7342
7343impl GeometricQuotient<Rotor> for Rotor {
7344    type Output = Rotor;
7345
7346    fn geometric_quotient(self, other: Rotor) -> Rotor {
7347        self.geometric_product(other.inverse())
7348    }
7349}
7350
7351impl Transformation<Rotor> for Rotor {
7352    type Output = Rotor;
7353
7354    fn transformation(self, other: Rotor) -> Rotor {
7355        self.geometric_product(other).geometric_product(self.reversal())
7356    }
7357}
7358
7359impl GeometricQuotient<f32> for Rotor {
7360    type Output = Rotor;
7361
7362    fn geometric_quotient(self, other: f32) -> Rotor {
7363        self.geometric_product(other.inverse())
7364    }
7365}
7366
7367impl Transformation<f32> for Rotor {
7368    type Output = f32;
7369
7370    fn transformation(self, other: f32) -> f32 {
7371        self.geometric_product(other).geometric_product(self.reversal()).into()
7372    }
7373}
7374
7375impl GeometricQuotient<Translator> for Rotor {
7376    type Output = Motor;
7377
7378    fn geometric_quotient(self, other: Translator) -> Motor {
7379        self.geometric_product(other.inverse())
7380    }
7381}
7382
7383impl Transformation<Translator> for Rotor {
7384    type Output = Translator;
7385
7386    fn transformation(self, other: Translator) -> Translator {
7387        self.geometric_product(other).geometric_product(self.reversal()).into()
7388    }
7389}
7390
7391impl GeometricQuotient<IdealPoint> for f32 {
7392    type Output = IdealPoint;
7393
7394    fn geometric_quotient(self, other: IdealPoint) -> IdealPoint {
7395        self.geometric_product(other.inverse())
7396    }
7397}
7398
7399impl Transformation<IdealPoint> for f32 {
7400    type Output = IdealPoint;
7401
7402    fn transformation(self, other: IdealPoint) -> IdealPoint {
7403        self.geometric_product(other).geometric_product(self.reversal())
7404    }
7405}
7406
7407impl GeometricQuotient<Motor> for f32 {
7408    type Output = Motor;
7409
7410    fn geometric_quotient(self, other: Motor) -> Motor {
7411        self.geometric_product(other.inverse())
7412    }
7413}
7414
7415impl Transformation<Motor> for f32 {
7416    type Output = Motor;
7417
7418    fn transformation(self, other: Motor) -> Motor {
7419        self.geometric_product(other).geometric_product(self.reversal())
7420    }
7421}
7422
7423impl GeometricQuotient<MotorDual> for f32 {
7424    type Output = MotorDual;
7425
7426    fn geometric_quotient(self, other: MotorDual) -> MotorDual {
7427        self.geometric_product(other.inverse())
7428    }
7429}
7430
7431impl Transformation<MotorDual> for f32 {
7432    type Output = MotorDual;
7433
7434    fn transformation(self, other: MotorDual) -> MotorDual {
7435        self.geometric_product(other).geometric_product(self.reversal())
7436    }
7437}
7438
7439impl GeometricQuotient<MultiVector> for f32 {
7440    type Output = MultiVector;
7441
7442    fn geometric_quotient(self, other: MultiVector) -> MultiVector {
7443        self.geometric_product(other.inverse())
7444    }
7445}
7446
7447impl Transformation<MultiVector> for f32 {
7448    type Output = MultiVector;
7449
7450    fn transformation(self, other: MultiVector) -> MultiVector {
7451        self.geometric_product(other).geometric_product(self.reversal())
7452    }
7453}
7454
7455impl GeometricQuotient<Plane> for f32 {
7456    type Output = Plane;
7457
7458    fn geometric_quotient(self, other: Plane) -> Plane {
7459        self.geometric_product(other.inverse())
7460    }
7461}
7462
7463impl Transformation<Plane> for f32 {
7464    type Output = Plane;
7465
7466    fn transformation(self, other: Plane) -> Plane {
7467        self.geometric_product(other).geometric_product(self.reversal())
7468    }
7469}
7470
7471impl GeometricQuotient<Point> for f32 {
7472    type Output = Point;
7473
7474    fn geometric_quotient(self, other: Point) -> Point {
7475        self.geometric_product(other.inverse())
7476    }
7477}
7478
7479impl Transformation<Point> for f32 {
7480    type Output = Point;
7481
7482    fn transformation(self, other: Point) -> Point {
7483        self.geometric_product(other).geometric_product(self.reversal())
7484    }
7485}
7486
7487impl GeometricQuotient<Rotor> for f32 {
7488    type Output = Rotor;
7489
7490    fn geometric_quotient(self, other: Rotor) -> Rotor {
7491        self.geometric_product(other.inverse())
7492    }
7493}
7494
7495impl Transformation<Rotor> for f32 {
7496    type Output = Rotor;
7497
7498    fn transformation(self, other: Rotor) -> Rotor {
7499        self.geometric_product(other).geometric_product(self.reversal())
7500    }
7501}
7502
7503impl GeometricQuotient<Translator> for f32 {
7504    type Output = Translator;
7505
7506    fn geometric_quotient(self, other: Translator) -> Translator {
7507        self.geometric_product(other.inverse())
7508    }
7509}
7510
7511impl Transformation<Translator> for f32 {
7512    type Output = Translator;
7513
7514    fn transformation(self, other: Translator) -> Translator {
7515        self.geometric_product(other).geometric_product(self.reversal())
7516    }
7517}
7518
7519impl GeometricQuotient<IdealPoint> for Translator {
7520    type Output = Motor;
7521
7522    fn geometric_quotient(self, other: IdealPoint) -> Motor {
7523        self.geometric_product(other.inverse())
7524    }
7525}
7526
7527impl Transformation<IdealPoint> for Translator {
7528    type Output = IdealPoint;
7529
7530    fn transformation(self, other: IdealPoint) -> IdealPoint {
7531        self.geometric_product(other).geometric_product(self.reversal()).into()
7532    }
7533}
7534
7535impl GeometricQuotient<Motor> for Translator {
7536    type Output = Motor;
7537
7538    fn geometric_quotient(self, other: Motor) -> Motor {
7539        self.geometric_product(other.inverse())
7540    }
7541}
7542
7543impl Transformation<Motor> for Translator {
7544    type Output = Motor;
7545
7546    fn transformation(self, other: Motor) -> Motor {
7547        self.geometric_product(other).geometric_product(self.reversal())
7548    }
7549}
7550
7551impl GeometricQuotient<MotorDual> for Translator {
7552    type Output = MotorDual;
7553
7554    fn geometric_quotient(self, other: MotorDual) -> MotorDual {
7555        self.geometric_product(other.inverse())
7556    }
7557}
7558
7559impl Transformation<MotorDual> for Translator {
7560    type Output = MotorDual;
7561
7562    fn transformation(self, other: MotorDual) -> MotorDual {
7563        self.geometric_product(other).geometric_product(self.reversal())
7564    }
7565}
7566
7567impl GeometricQuotient<MultiVector> for Translator {
7568    type Output = MultiVector;
7569
7570    fn geometric_quotient(self, other: MultiVector) -> MultiVector {
7571        self.geometric_product(other.inverse())
7572    }
7573}
7574
7575impl Transformation<MultiVector> for Translator {
7576    type Output = MultiVector;
7577
7578    fn transformation(self, other: MultiVector) -> MultiVector {
7579        self.geometric_product(other).geometric_product(self.reversal())
7580    }
7581}
7582
7583impl GeometricQuotient<Plane> for Translator {
7584    type Output = MotorDual;
7585
7586    fn geometric_quotient(self, other: Plane) -> MotorDual {
7587        self.geometric_product(other.inverse())
7588    }
7589}
7590
7591impl Transformation<Plane> for Translator {
7592    type Output = Plane;
7593
7594    fn transformation(self, other: Plane) -> Plane {
7595        self.geometric_product(other).geometric_product(self.reversal()).into()
7596    }
7597}
7598
7599impl GeometricQuotient<Point> for Translator {
7600    type Output = Motor;
7601
7602    fn geometric_quotient(self, other: Point) -> Motor {
7603        self.geometric_product(other.inverse())
7604    }
7605}
7606
7607impl Transformation<Point> for Translator {
7608    type Output = Point;
7609
7610    fn transformation(self, other: Point) -> Point {
7611        self.geometric_product(other).geometric_product(self.reversal()).into()
7612    }
7613}
7614
7615impl GeometricQuotient<Rotor> for Translator {
7616    type Output = Motor;
7617
7618    fn geometric_quotient(self, other: Rotor) -> Motor {
7619        self.geometric_product(other.inverse())
7620    }
7621}
7622
7623impl Transformation<Rotor> for Translator {
7624    type Output = Rotor;
7625
7626    fn transformation(self, other: Rotor) -> Rotor {
7627        self.geometric_product(other).geometric_product(self.reversal()).into()
7628    }
7629}
7630
7631impl GeometricQuotient<f32> for Translator {
7632    type Output = Translator;
7633
7634    fn geometric_quotient(self, other: f32) -> Translator {
7635        self.geometric_product(other.inverse())
7636    }
7637}
7638
7639impl Transformation<f32> for Translator {
7640    type Output = f32;
7641
7642    fn transformation(self, other: f32) -> f32 {
7643        self.geometric_product(other).geometric_product(self.reversal()).into()
7644    }
7645}
7646
7647impl GeometricQuotient<Translator> for Translator {
7648    type Output = Motor;
7649
7650    fn geometric_quotient(self, other: Translator) -> Motor {
7651        self.geometric_product(other.inverse())
7652    }
7653}
7654
7655impl Transformation<Translator> for Translator {
7656    type Output = Translator;
7657
7658    fn transformation(self, other: Translator) -> Translator {
7659        self.geometric_product(other).geometric_product(self.reversal()).into()
7660    }
7661}
7662