geometric_algebra/
ppga2d.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]), 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]) + 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]) + 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.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]
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: 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]
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 Into<Plane> for MultiVector {
1425    fn into(self) -> Plane {
1426        Plane { groups: PlaneGroups { g0: Simd32x3::from([self.group1()[0], self.group0()[3], self.group0()[2]]) } }
1427    }
1428}
1429
1430impl Add<Plane> for MultiVector {
1431    type Output = MultiVector;
1432
1433    fn add(self, other: Plane) -> MultiVector {
1434        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]) } }
1435    }
1436}
1437
1438impl AddAssign<Plane> for MultiVector {
1439    fn add_assign(&mut self, other: Plane) {
1440        *self = (*self).add(other);
1441    }
1442}
1443
1444impl Sub<Plane> for MultiVector {
1445    type Output = MultiVector;
1446
1447    fn sub(self, other: Plane) -> MultiVector {
1448        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]) } }
1449    }
1450}
1451
1452impl SubAssign<Plane> for MultiVector {
1453    fn sub_assign(&mut self, other: Plane) {
1454        *self = (*self).sub(other);
1455    }
1456}
1457
1458impl GeometricProduct<Plane> for MultiVector {
1459    type Output = MultiVector;
1460
1461    fn geometric_product(self, other: Plane) -> MultiVector {
1462        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]) + 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]) } }
1463    }
1464}
1465
1466impl ScalarProduct<Plane> for MultiVector {
1467    type Output = f32;
1468
1469    fn scalar_product(self, other: Plane) -> f32 {
1470        self.group0()[2] * other.group0()[2] + self.group0()[3] * other.group0()[1]
1471    }
1472}
1473
1474impl Into<Translator> for MultiVector {
1475    fn into(self) -> Translator {
1476        Translator { groups: TranslatorGroups { g0: Simd32x3::from([self.group0()[0], self.group1()[2], self.group1()[3]]) } }
1477    }
1478}
1479
1480impl Add<Translator> for MultiVector {
1481    type Output = MultiVector;
1482
1483    fn add(self, other: Translator) -> MultiVector {
1484        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]) } }
1485    }
1486}
1487
1488impl AddAssign<Translator> for MultiVector {
1489    fn add_assign(&mut self, other: Translator) {
1490        *self = (*self).add(other);
1491    }
1492}
1493
1494impl Sub<Translator> for MultiVector {
1495    type Output = MultiVector;
1496
1497    fn sub(self, other: Translator) -> MultiVector {
1498        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]) } }
1499    }
1500}
1501
1502impl SubAssign<Translator> for MultiVector {
1503    fn sub_assign(&mut self, other: Translator) {
1504        *self = (*self).sub(other);
1505    }
1506}
1507
1508impl GeometricProduct<Translator> for MultiVector {
1509    type Output = MultiVector;
1510
1511    fn geometric_product(self, other: Translator) -> MultiVector {
1512        MultiVector { groups: MultiVectorGroups { g0: 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]) } }
1513    }
1514}
1515
1516impl OuterProduct<Translator> for MultiVector {
1517    type Output = MultiVector;
1518
1519    fn outer_product(self, other: Translator) -> MultiVector {
1520        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]]) } }
1521    }
1522}
1523
1524impl InnerProduct<Translator> for MultiVector {
1525    type Output = MultiVector;
1526
1527    fn inner_product(self, other: Translator) -> MultiVector {
1528        MultiVector { groups: MultiVectorGroups { g0: 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]) } }
1529    }
1530}
1531
1532impl RightContraction<Translator> for MultiVector {
1533    type Output = MultiVector;
1534
1535    fn right_contraction(self, other: Translator) -> MultiVector {
1536        MultiVector { groups: MultiVectorGroups { g0: self.group0() * Simd32x4::from(other.group0()[0]), g1: self.group1() * Simd32x4::from(other.group0()[0]) } }
1537    }
1538}
1539
1540impl ScalarProduct<Translator> for MultiVector {
1541    type Output = f32;
1542
1543    fn scalar_product(self, other: Translator) -> f32 {
1544        self.group0()[0] * other.group0()[0]
1545    }
1546}
1547
1548impl Into<Motor> for MultiVector {
1549    fn into(self) -> Motor {
1550        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[1], self.group1()[2], self.group1()[3]]) } }
1551    }
1552}
1553
1554impl Add<Motor> for MultiVector {
1555    type Output = MultiVector;
1556
1557    fn add(self, other: Motor) -> MultiVector {
1558        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]) } }
1559    }
1560}
1561
1562impl AddAssign<Motor> for MultiVector {
1563    fn add_assign(&mut self, other: Motor) {
1564        *self = (*self).add(other);
1565    }
1566}
1567
1568impl Sub<Motor> for MultiVector {
1569    type Output = MultiVector;
1570
1571    fn sub(self, other: Motor) -> MultiVector {
1572        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]) } }
1573    }
1574}
1575
1576impl SubAssign<Motor> for MultiVector {
1577    fn sub_assign(&mut self, other: Motor) {
1578        *self = (*self).sub(other);
1579    }
1580}
1581
1582impl GeometricProduct<Motor> for MultiVector {
1583    type Output = MultiVector;
1584
1585    fn geometric_product(self, other: Motor) -> MultiVector {
1586        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]) + 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]) } }
1587    }
1588}
1589
1590impl OuterProduct<Motor> for MultiVector {
1591    type Output = MultiVector;
1592
1593    fn outer_product(self, other: Motor) -> MultiVector {
1594        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]) } }
1595    }
1596}
1597
1598impl InnerProduct<Motor> for MultiVector {
1599    type Output = MultiVector;
1600
1601    fn inner_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]) + 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]) } }
1603    }
1604}
1605
1606impl RightContraction<Motor> for MultiVector {
1607    type Output = MultiVector;
1608
1609    fn right_contraction(self, other: Motor) -> MultiVector {
1610        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]) + 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]) } }
1611    }
1612}
1613
1614impl ScalarProduct<Motor> for MultiVector {
1615    type Output = f32;
1616
1617    fn scalar_product(self, other: Motor) -> f32 {
1618        self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group0()[1]
1619    }
1620}
1621
1622impl Into<MotorDual> for MultiVector {
1623    fn into(self) -> MotorDual {
1624        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from([self.group1()[1], self.group1()[0], self.group0()[3], self.group0()[2]]) } }
1625    }
1626}
1627
1628impl Add<MotorDual> for MultiVector {
1629    type Output = MultiVector;
1630
1631    fn add(self, other: MotorDual) -> MultiVector {
1632        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]) } }
1633    }
1634}
1635
1636impl AddAssign<MotorDual> for MultiVector {
1637    fn add_assign(&mut self, other: MotorDual) {
1638        *self = (*self).add(other);
1639    }
1640}
1641
1642impl Sub<MotorDual> for MultiVector {
1643    type Output = MultiVector;
1644
1645    fn sub(self, other: MotorDual) -> MultiVector {
1646        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]) } }
1647    }
1648}
1649
1650impl SubAssign<MotorDual> for MultiVector {
1651    fn sub_assign(&mut self, other: MotorDual) {
1652        *self = (*self).sub(other);
1653    }
1654}
1655
1656impl GeometricProduct<MotorDual> for MultiVector {
1657    type Output = MultiVector;
1658
1659    fn geometric_product(self, other: MotorDual) -> MultiVector {
1660        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]) + 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]) } }
1661    }
1662}
1663
1664impl RegressiveProduct<MotorDual> for MultiVector {
1665    type Output = MultiVector;
1666
1667    fn regressive_product(self, other: MotorDual) -> MultiVector {
1668        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]) } }
1669    }
1670}
1671
1672impl ScalarProduct<MotorDual> for MultiVector {
1673    type Output = f32;
1674
1675    fn scalar_product(self, other: MotorDual) -> f32 {
1676        self.group0()[2] * other.group0()[3] + self.group0()[3] * other.group0()[2]
1677    }
1678}
1679
1680impl SquaredMagnitude for MultiVector {
1681    type Output = f32;
1682
1683    fn squared_magnitude(self) -> f32 {
1684        self.scalar_product(self.reversal())
1685    }
1686}
1687
1688impl Magnitude for MultiVector {
1689    type Output = f32;
1690
1691    fn magnitude(self) -> f32 {
1692        self.squared_magnitude().sqrt()
1693    }
1694}
1695
1696impl Mul<f32> for MultiVector {
1697    type Output = MultiVector;
1698
1699    fn mul(self, other: f32) -> MultiVector {
1700        self.geometric_product(other)
1701    }
1702}
1703
1704impl MulAssign<f32> for MultiVector {
1705    fn mul_assign(&mut self, other: f32) {
1706        *self = (*self).mul(other);
1707    }
1708}
1709
1710impl Signum for MultiVector {
1711    type Output = MultiVector;
1712
1713    fn signum(self) -> MultiVector {
1714        self.geometric_product(1.0 / self.magnitude())
1715    }
1716}
1717
1718impl Inverse for MultiVector {
1719    type Output = MultiVector;
1720
1721    fn inverse(self) -> MultiVector {
1722        self.reversal().geometric_product(1.0 / self.squared_magnitude())
1723    }
1724}
1725
1726impl Zero for Rotor {
1727    fn zero() -> Self {
1728        Rotor { groups: RotorGroups { g0: Simd32x2::from(0.0) } }
1729    }
1730}
1731
1732impl One for Rotor {
1733    fn one() -> Self {
1734        Rotor { groups: RotorGroups { g0: Simd32x2::from([1.0, 0.0]) } }
1735    }
1736}
1737
1738impl Neg for Rotor {
1739    type Output = Rotor;
1740
1741    fn neg(self) -> Rotor {
1742        Rotor { groups: RotorGroups { g0: self.group0() * Simd32x2::from(-1.0) } }
1743    }
1744}
1745
1746impl Automorphism for Rotor {
1747    type Output = Rotor;
1748
1749    fn automorphism(self) -> Rotor {
1750        Rotor { groups: RotorGroups { g0: self.group0() } }
1751    }
1752}
1753
1754impl Reversal for Rotor {
1755    type Output = Rotor;
1756
1757    fn reversal(self) -> Rotor {
1758        Rotor { groups: RotorGroups { g0: self.group0() * Simd32x2::from([1.0, -1.0]) } }
1759    }
1760}
1761
1762impl Conjugation for Rotor {
1763    type Output = Rotor;
1764
1765    fn conjugation(self) -> Rotor {
1766        Rotor { groups: RotorGroups { g0: self.group0() * Simd32x2::from([1.0, -1.0]) } }
1767    }
1768}
1769
1770impl Into<f32> for Rotor {
1771    fn into(self) -> f32 {
1772        self.group0()[0]
1773    }
1774}
1775
1776impl Add<f32> for Rotor {
1777    type Output = Rotor;
1778
1779    fn add(self, other: f32) -> Rotor {
1780        Rotor { groups: RotorGroups { g0: self.group0() + Simd32x2::from(other) * Simd32x2::from([1.0, 0.0]) } }
1781    }
1782}
1783
1784impl AddAssign<f32> for Rotor {
1785    fn add_assign(&mut self, other: f32) {
1786        *self = (*self).add(other);
1787    }
1788}
1789
1790impl Sub<f32> for Rotor {
1791    type Output = Rotor;
1792
1793    fn sub(self, other: f32) -> Rotor {
1794        Rotor { groups: RotorGroups { g0: self.group0() - Simd32x2::from(other) * Simd32x2::from([1.0, 0.0]) } }
1795    }
1796}
1797
1798impl SubAssign<f32> for Rotor {
1799    fn sub_assign(&mut self, other: f32) {
1800        *self = (*self).sub(other);
1801    }
1802}
1803
1804impl GeometricProduct<f32> for Rotor {
1805    type Output = Rotor;
1806
1807    fn geometric_product(self, other: f32) -> Rotor {
1808        Rotor { groups: RotorGroups { g0: self.group0() * Simd32x2::from(other) } }
1809    }
1810}
1811
1812impl OuterProduct<f32> for Rotor {
1813    type Output = Rotor;
1814
1815    fn outer_product(self, other: f32) -> Rotor {
1816        Rotor { groups: RotorGroups { g0: self.group0() * Simd32x2::from(other) } }
1817    }
1818}
1819
1820impl InnerProduct<f32> for Rotor {
1821    type Output = Rotor;
1822
1823    fn inner_product(self, other: f32) -> Rotor {
1824        Rotor { groups: RotorGroups { g0: self.group0() * Simd32x2::from(other) } }
1825    }
1826}
1827
1828impl LeftContraction<f32> for Rotor {
1829    type Output = f32;
1830
1831    fn left_contraction(self, other: f32) -> f32 {
1832        self.group0()[0] * other
1833    }
1834}
1835
1836impl RightContraction<f32> for Rotor {
1837    type Output = Rotor;
1838
1839    fn right_contraction(self, other: f32) -> Rotor {
1840        Rotor { groups: RotorGroups { g0: self.group0() * Simd32x2::from(other) } }
1841    }
1842}
1843
1844impl ScalarProduct<f32> for Rotor {
1845    type Output = f32;
1846
1847    fn scalar_product(self, other: f32) -> f32 {
1848        self.group0()[0] * other
1849    }
1850}
1851
1852impl Add<MultiVector> for Rotor {
1853    type Output = MultiVector;
1854
1855    fn add(self, other: MultiVector) -> MultiVector {
1856        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() } }
1857    }
1858}
1859
1860impl Sub<MultiVector> for Rotor {
1861    type Output = MultiVector;
1862
1863    fn sub(self, other: MultiVector) -> MultiVector {
1864        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() } }
1865    }
1866}
1867
1868impl GeometricProduct<MultiVector> for Rotor {
1869    type Output = MultiVector;
1870
1871    fn geometric_product(self, other: MultiVector) -> MultiVector {
1872        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]) } }
1873    }
1874}
1875
1876impl OuterProduct<MultiVector> for Rotor {
1877    type Output = MultiVector;
1878
1879    fn outer_product(self, other: MultiVector) -> MultiVector {
1880        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]) } }
1881    }
1882}
1883
1884impl InnerProduct<MultiVector> for Rotor {
1885    type Output = MultiVector;
1886
1887    fn inner_product(self, other: MultiVector) -> MultiVector {
1888        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]) } }
1889    }
1890}
1891
1892impl LeftContraction<MultiVector> for Rotor {
1893    type Output = MultiVector;
1894
1895    fn left_contraction(self, other: MultiVector) -> MultiVector {
1896        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]) } }
1897    }
1898}
1899
1900impl ScalarProduct<MultiVector> for Rotor {
1901    type Output = f32;
1902
1903    fn scalar_product(self, other: MultiVector) -> f32 {
1904        self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group0()[1]
1905    }
1906}
1907
1908impl Add<Rotor> for Rotor {
1909    type Output = Rotor;
1910
1911    fn add(self, other: Rotor) -> Rotor {
1912        Rotor { groups: RotorGroups { g0: self.group0() + other.group0() } }
1913    }
1914}
1915
1916impl AddAssign<Rotor> for Rotor {
1917    fn add_assign(&mut self, other: Rotor) {
1918        *self = (*self).add(other);
1919    }
1920}
1921
1922impl Sub<Rotor> for Rotor {
1923    type Output = Rotor;
1924
1925    fn sub(self, other: Rotor) -> Rotor {
1926        Rotor { groups: RotorGroups { g0: self.group0() - other.group0() } }
1927    }
1928}
1929
1930impl SubAssign<Rotor> for Rotor {
1931    fn sub_assign(&mut self, other: Rotor) {
1932        *self = (*self).sub(other);
1933    }
1934}
1935
1936impl Mul<Rotor> for Rotor {
1937    type Output = Rotor;
1938
1939    fn mul(self, other: Rotor) -> Rotor {
1940        Rotor { groups: RotorGroups { g0: self.group0() * other.group0() } }
1941    }
1942}
1943
1944impl MulAssign<Rotor> for Rotor {
1945    fn mul_assign(&mut self, other: Rotor) {
1946        *self = (*self).mul(other);
1947    }
1948}
1949
1950impl Div<Rotor> for Rotor {
1951    type Output = Rotor;
1952
1953    fn div(self, other: Rotor) -> Rotor {
1954        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]) } }
1955    }
1956}
1957
1958impl DivAssign<Rotor> for Rotor {
1959    fn div_assign(&mut self, other: Rotor) {
1960        *self = (*self).div(other);
1961    }
1962}
1963
1964impl GeometricProduct<Rotor> for Rotor {
1965    type Output = Rotor;
1966
1967    fn geometric_product(self, other: Rotor) -> Rotor {
1968        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]) } }
1969    }
1970}
1971
1972impl OuterProduct<Rotor> for Rotor {
1973    type Output = Rotor;
1974
1975    fn outer_product(self, other: Rotor) -> Rotor {
1976        Rotor { groups: RotorGroups { g0: Simd32x2::from(self.group0()[0]) * other.group0() + self.group0() * Simd32x2::from(other.group0()[0]) * Simd32x2::from([0.0, 1.0]) } }
1977    }
1978}
1979
1980impl InnerProduct<Rotor> for Rotor {
1981    type Output = Rotor;
1982
1983    fn inner_product(self, other: Rotor) -> Rotor {
1984        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]) } }
1985    }
1986}
1987
1988impl LeftContraction<Rotor> for Rotor {
1989    type Output = Rotor;
1990
1991    fn left_contraction(self, other: Rotor) -> Rotor {
1992        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]) } }
1993    }
1994}
1995
1996impl RightContraction<Rotor> for Rotor {
1997    type Output = Rotor;
1998
1999    fn right_contraction(self, other: Rotor) -> Rotor {
2000        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]) } }
2001    }
2002}
2003
2004impl ScalarProduct<Rotor> for Rotor {
2005    type Output = f32;
2006
2007    fn scalar_product(self, other: Rotor) -> f32 {
2008        self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group0()[1]
2009    }
2010}
2011
2012impl Add<Point> for Rotor {
2013    type Output = Motor;
2014
2015    fn add(self, other: Point) -> Motor {
2016        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]) } }
2017    }
2018}
2019
2020impl Sub<Point> for Rotor {
2021    type Output = Motor;
2022
2023    fn sub(self, other: Point) -> Motor {
2024        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]) } }
2025    }
2026}
2027
2028impl GeometricProduct<Point> for Rotor {
2029    type Output = Motor;
2030
2031    fn geometric_product(self, other: Point) -> Motor {
2032        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]) } }
2033    }
2034}
2035
2036impl OuterProduct<Point> for Rotor {
2037    type Output = Point;
2038
2039    fn outer_product(self, other: Point) -> Point {
2040        Point { groups: PointGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() } }
2041    }
2042}
2043
2044impl InnerProduct<Point> for Rotor {
2045    type Output = Motor;
2046
2047    fn inner_product(self, other: Point) -> Motor {
2048        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]) } }
2049    }
2050}
2051
2052impl LeftContraction<Point> for Rotor {
2053    type Output = Motor;
2054
2055    fn left_contraction(self, other: Point) -> Motor {
2056        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]) } }
2057    }
2058}
2059
2060impl RightContraction<Point> for Rotor {
2061    type Output = f32;
2062
2063    fn right_contraction(self, other: Point) -> f32 {
2064        0.0 - self.group0()[1] * other.group0()[0]
2065    }
2066}
2067
2068impl ScalarProduct<Point> for Rotor {
2069    type Output = f32;
2070
2071    fn scalar_product(self, other: Point) -> f32 {
2072        0.0 - self.group0()[1] * other.group0()[0]
2073    }
2074}
2075
2076impl Add<IdealPoint> for Rotor {
2077    type Output = Motor;
2078
2079    fn add(self, other: IdealPoint) -> Motor {
2080        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]) } }
2081    }
2082}
2083
2084impl Sub<IdealPoint> for Rotor {
2085    type Output = Motor;
2086
2087    fn sub(self, other: IdealPoint) -> Motor {
2088        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]) } }
2089    }
2090}
2091
2092impl GeometricProduct<IdealPoint> for Rotor {
2093    type Output = IdealPoint;
2094
2095    fn geometric_product(self, other: IdealPoint) -> IdealPoint {
2096        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]) } }
2097    }
2098}
2099
2100impl OuterProduct<IdealPoint> for Rotor {
2101    type Output = IdealPoint;
2102
2103    fn outer_product(self, other: IdealPoint) -> IdealPoint {
2104        IdealPoint { groups: IdealPointGroups { g0: Simd32x2::from(self.group0()[0]) * other.group0() } }
2105    }
2106}
2107
2108impl InnerProduct<IdealPoint> for Rotor {
2109    type Output = IdealPoint;
2110
2111    fn inner_product(self, other: IdealPoint) -> IdealPoint {
2112        IdealPoint { groups: IdealPointGroups { g0: Simd32x2::from(self.group0()[0]) * other.group0() } }
2113    }
2114}
2115
2116impl LeftContraction<IdealPoint> for Rotor {
2117    type Output = IdealPoint;
2118
2119    fn left_contraction(self, other: IdealPoint) -> IdealPoint {
2120        IdealPoint { groups: IdealPointGroups { g0: Simd32x2::from(self.group0()[0]) * other.group0() } }
2121    }
2122}
2123
2124impl GeometricProduct<Plane> for Rotor {
2125    type Output = MotorDual;
2126
2127    fn geometric_product(self, other: Plane) -> MotorDual {
2128        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]) } }
2129    }
2130}
2131
2132impl RegressiveProduct<Plane> for Rotor {
2133    type Output = f32;
2134
2135    fn regressive_product(self, other: Plane) -> f32 {
2136        self.group0()[1] * other.group0()[0]
2137    }
2138}
2139
2140impl OuterProduct<Plane> for Rotor {
2141    type Output = MotorDual;
2142
2143    fn outer_product(self, other: Plane) -> MotorDual {
2144        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]]) } }
2145    }
2146}
2147
2148impl InnerProduct<Plane> for Rotor {
2149    type Output = Plane;
2150
2151    fn inner_product(self, other: Plane) -> Plane {
2152        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]) } }
2153    }
2154}
2155
2156impl LeftContraction<Plane> for Rotor {
2157    type Output = Plane;
2158
2159    fn left_contraction(self, other: Plane) -> Plane {
2160        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() } }
2161    }
2162}
2163
2164impl Add<Translator> for Rotor {
2165    type Output = Motor;
2166
2167    fn add(self, other: Translator) -> Motor {
2168        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]) } }
2169    }
2170}
2171
2172impl Sub<Translator> for Rotor {
2173    type Output = Motor;
2174
2175    fn sub(self, other: Translator) -> Motor {
2176        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]) } }
2177    }
2178}
2179
2180impl GeometricProduct<Translator> for Rotor {
2181    type Output = Motor;
2182
2183    fn geometric_product(self, other: Translator) -> Motor {
2184        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]) } }
2185    }
2186}
2187
2188impl OuterProduct<Translator> for Rotor {
2189    type Output = Motor;
2190
2191    fn outer_product(self, other: Translator) -> Motor {
2192        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]]) } }
2193    }
2194}
2195
2196impl InnerProduct<Translator> for Rotor {
2197    type Output = Motor;
2198
2199    fn inner_product(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([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) } }
2201    }
2202}
2203
2204impl LeftContraction<Translator> for Rotor {
2205    type Output = Translator;
2206
2207    fn left_contraction(self, other: Translator) -> Translator {
2208        Translator { groups: TranslatorGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() } }
2209    }
2210}
2211
2212impl RightContraction<Translator> for Rotor {
2213    type Output = Rotor;
2214
2215    fn right_contraction(self, other: Translator) -> Rotor {
2216        Rotor { groups: RotorGroups { g0: self.group0() * Simd32x2::from(other.group0()[0]) } }
2217    }
2218}
2219
2220impl ScalarProduct<Translator> for Rotor {
2221    type Output = f32;
2222
2223    fn scalar_product(self, other: Translator) -> f32 {
2224        self.group0()[0] * other.group0()[0]
2225    }
2226}
2227
2228impl Add<Motor> for Rotor {
2229    type Output = Motor;
2230
2231    fn add(self, other: Motor) -> Motor {
2232        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() } }
2233    }
2234}
2235
2236impl Sub<Motor> for Rotor {
2237    type Output = Motor;
2238
2239    fn sub(self, other: Motor) -> Motor {
2240        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() } }
2241    }
2242}
2243
2244impl GeometricProduct<Motor> for Rotor {
2245    type Output = Motor;
2246
2247    fn geometric_product(self, other: Motor) -> Motor {
2248        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]) } }
2249    }
2250}
2251
2252impl OuterProduct<Motor> for Rotor {
2253    type Output = Motor;
2254
2255    fn outer_product(self, other: Motor) -> Motor {
2256        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]) } }
2257    }
2258}
2259
2260impl InnerProduct<Motor> for Rotor {
2261    type Output = Motor;
2262
2263    fn inner_product(self, other: Motor) -> Motor {
2264        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]) } }
2265    }
2266}
2267
2268impl LeftContraction<Motor> for Rotor {
2269    type Output = Motor;
2270
2271    fn left_contraction(self, other: Motor) -> Motor {
2272        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]) } }
2273    }
2274}
2275
2276impl RightContraction<Motor> for Rotor {
2277    type Output = Rotor;
2278
2279    fn right_contraction(self, other: Motor) -> Rotor {
2280        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]) } }
2281    }
2282}
2283
2284impl ScalarProduct<Motor> for Rotor {
2285    type Output = f32;
2286
2287    fn scalar_product(self, other: Motor) -> f32 {
2288        self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group0()[1]
2289    }
2290}
2291
2292impl GeometricProduct<MotorDual> for Rotor {
2293    type Output = MotorDual;
2294
2295    fn geometric_product(self, other: MotorDual) -> MotorDual {
2296        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]) } }
2297    }
2298}
2299
2300impl RegressiveProduct<MotorDual> for Rotor {
2301    type Output = Rotor;
2302
2303    fn regressive_product(self, other: MotorDual) -> Rotor {
2304        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]) } }
2305    }
2306}
2307
2308impl OuterProduct<MotorDual> for Rotor {
2309    type Output = MotorDual;
2310
2311    fn outer_product(self, other: MotorDual) -> MotorDual {
2312        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]) } }
2313    }
2314}
2315
2316impl InnerProduct<MotorDual> for Rotor {
2317    type Output = MotorDual;
2318
2319    fn inner_product(self, other: MotorDual) -> MotorDual {
2320        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]) } }
2321    }
2322}
2323
2324impl LeftContraction<MotorDual> for Rotor {
2325    type Output = MotorDual;
2326
2327    fn left_contraction(self, other: MotorDual) -> MotorDual {
2328        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]) } }
2329    }
2330}
2331
2332impl SquaredMagnitude for Rotor {
2333    type Output = f32;
2334
2335    fn squared_magnitude(self) -> f32 {
2336        self.scalar_product(self.reversal())
2337    }
2338}
2339
2340impl Magnitude for Rotor {
2341    type Output = f32;
2342
2343    fn magnitude(self) -> f32 {
2344        self.squared_magnitude().sqrt()
2345    }
2346}
2347
2348impl Mul<f32> for Rotor {
2349    type Output = Rotor;
2350
2351    fn mul(self, other: f32) -> Rotor {
2352        self.geometric_product(other)
2353    }
2354}
2355
2356impl MulAssign<f32> for Rotor {
2357    fn mul_assign(&mut self, other: f32) {
2358        *self = (*self).mul(other);
2359    }
2360}
2361
2362impl Signum for Rotor {
2363    type Output = Rotor;
2364
2365    fn signum(self) -> Rotor {
2366        self.geometric_product(1.0 / self.magnitude())
2367    }
2368}
2369
2370impl Inverse for Rotor {
2371    type Output = Rotor;
2372
2373    fn inverse(self) -> Rotor {
2374        self.reversal().geometric_product(1.0 / self.squared_magnitude())
2375    }
2376}
2377
2378impl Zero for Point {
2379    fn zero() -> Self {
2380        Point { groups: PointGroups { g0: Simd32x3::from(0.0) } }
2381    }
2382}
2383
2384impl One for Point {
2385    fn one() -> Self {
2386        Point { groups: PointGroups { g0: Simd32x3::from(0.0) } }
2387    }
2388}
2389
2390impl Neg for Point {
2391    type Output = Point;
2392
2393    fn neg(self) -> Point {
2394        Point { groups: PointGroups { g0: self.group0() * Simd32x3::from(-1.0) } }
2395    }
2396}
2397
2398impl Automorphism for Point {
2399    type Output = Point;
2400
2401    fn automorphism(self) -> Point {
2402        Point { groups: PointGroups { g0: self.group0() } }
2403    }
2404}
2405
2406impl Reversal for Point {
2407    type Output = Point;
2408
2409    fn reversal(self) -> Point {
2410        Point { groups: PointGroups { g0: self.group0() * Simd32x3::from(-1.0) } }
2411    }
2412}
2413
2414impl Conjugation for Point {
2415    type Output = Point;
2416
2417    fn conjugation(self) -> Point {
2418        Point { groups: PointGroups { g0: self.group0() * Simd32x3::from(-1.0) } }
2419    }
2420}
2421
2422impl Dual for Point {
2423    type Output = Plane;
2424
2425    fn dual(self) -> Plane {
2426        Plane { groups: PlaneGroups { g0: self.group0() } }
2427    }
2428}
2429
2430impl Add<f32> for Point {
2431    type Output = Motor;
2432
2433    fn add(self, other: f32) -> Motor {
2434        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]) } }
2435    }
2436}
2437
2438impl Sub<f32> for Point {
2439    type Output = Motor;
2440
2441    fn sub(self, other: f32) -> Motor {
2442        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]) } }
2443    }
2444}
2445
2446impl GeometricProduct<f32> for Point {
2447    type Output = Point;
2448
2449    fn geometric_product(self, other: f32) -> Point {
2450        Point { groups: PointGroups { g0: self.group0() * Simd32x3::from(other) } }
2451    }
2452}
2453
2454impl OuterProduct<f32> for Point {
2455    type Output = Point;
2456
2457    fn outer_product(self, other: f32) -> Point {
2458        Point { groups: PointGroups { g0: self.group0() * Simd32x3::from(other) } }
2459    }
2460}
2461
2462impl InnerProduct<f32> for Point {
2463    type Output = Point;
2464
2465    fn inner_product(self, other: f32) -> Point {
2466        Point { groups: PointGroups { g0: self.group0() * Simd32x3::from(other) } }
2467    }
2468}
2469
2470impl RightContraction<f32> for Point {
2471    type Output = Point;
2472
2473    fn right_contraction(self, other: f32) -> Point {
2474        Point { groups: PointGroups { g0: self.group0() * Simd32x3::from(other) } }
2475    }
2476}
2477
2478impl Add<MultiVector> for Point {
2479    type Output = MultiVector;
2480
2481    fn add(self, other: MultiVector) -> MultiVector {
2482        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() } }
2483    }
2484}
2485
2486impl Sub<MultiVector> for Point {
2487    type Output = MultiVector;
2488
2489    fn sub(self, other: MultiVector) -> MultiVector {
2490        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() } }
2491    }
2492}
2493
2494impl GeometricProduct<MultiVector> for Point {
2495    type Output = MultiVector;
2496
2497    fn geometric_product(self, other: MultiVector) -> MultiVector {
2498        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]), 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]) } }
2499    }
2500}
2501
2502impl ScalarProduct<MultiVector> for Point {
2503    type Output = f32;
2504
2505    fn scalar_product(self, other: MultiVector) -> f32 {
2506        0.0 - self.group0()[0] * other.group0()[1]
2507    }
2508}
2509
2510impl Add<Rotor> for Point {
2511    type Output = Motor;
2512
2513    fn add(self, other: Rotor) -> Motor {
2514        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]) } }
2515    }
2516}
2517
2518impl Sub<Rotor> for Point {
2519    type Output = Motor;
2520
2521    fn sub(self, other: Rotor) -> Motor {
2522        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]) } }
2523    }
2524}
2525
2526impl GeometricProduct<Rotor> for Point {
2527    type Output = Motor;
2528
2529    fn geometric_product(self, other: Rotor) -> Motor {
2530        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]) } }
2531    }
2532}
2533
2534impl OuterProduct<Rotor> for Point {
2535    type Output = Point;
2536
2537    fn outer_product(self, other: Rotor) -> Point {
2538        Point { groups: PointGroups { g0: self.group0() * Simd32x3::from(other.group0()[0]) } }
2539    }
2540}
2541
2542impl InnerProduct<Rotor> for Point {
2543    type Output = Motor;
2544
2545    fn inner_product(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([other.group0()[1], other.group0()[0], other.group0()[0], other.group0()[0]]) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) } }
2547    }
2548}
2549
2550impl LeftContraction<Rotor> for Point {
2551    type Output = f32;
2552
2553    fn left_contraction(self, other: Rotor) -> f32 {
2554        0.0 - self.group0()[0] * other.group0()[1]
2555    }
2556}
2557
2558impl RightContraction<Rotor> for Point {
2559    type Output = Motor;
2560
2561    fn right_contraction(self, other: Rotor) -> Motor {
2562        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]) } }
2563    }
2564}
2565
2566impl ScalarProduct<Rotor> for Point {
2567    type Output = f32;
2568
2569    fn scalar_product(self, other: Rotor) -> f32 {
2570        0.0 - self.group0()[0] * other.group0()[1]
2571    }
2572}
2573
2574impl Add<Point> for Point {
2575    type Output = Point;
2576
2577    fn add(self, other: Point) -> Point {
2578        Point { groups: PointGroups { g0: self.group0() + other.group0() } }
2579    }
2580}
2581
2582impl AddAssign<Point> for Point {
2583    fn add_assign(&mut self, other: Point) {
2584        *self = (*self).add(other);
2585    }
2586}
2587
2588impl Sub<Point> for Point {
2589    type Output = Point;
2590
2591    fn sub(self, other: Point) -> Point {
2592        Point { groups: PointGroups { g0: self.group0() - other.group0() } }
2593    }
2594}
2595
2596impl SubAssign<Point> for Point {
2597    fn sub_assign(&mut self, other: Point) {
2598        *self = (*self).sub(other);
2599    }
2600}
2601
2602impl Mul<Point> for Point {
2603    type Output = Point;
2604
2605    fn mul(self, other: Point) -> Point {
2606        Point { groups: PointGroups { g0: self.group0() * other.group0() } }
2607    }
2608}
2609
2610impl MulAssign<Point> for Point {
2611    fn mul_assign(&mut self, other: Point) {
2612        *self = (*self).mul(other);
2613    }
2614}
2615
2616impl Div<Point> for Point {
2617    type Output = Point;
2618
2619    fn div(self, other: Point) -> Point {
2620        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]) } }
2621    }
2622}
2623
2624impl DivAssign<Point> for Point {
2625    fn div_assign(&mut self, other: Point) {
2626        *self = (*self).div(other);
2627    }
2628}
2629
2630impl GeometricProduct<Point> for Point {
2631    type Output = Translator;
2632
2633    fn geometric_product(self, other: Point) -> Translator {
2634        Translator { groups: TranslatorGroups { g0: Simd32x3::from(self.group0()[0]) * swizzle!(other.group0(), 0, 2, 1) * Simd32x3::from([-1.0, -1.0, 1.0]) + swizzle!(self.group0(), 0, 2, 1) * Simd32x3::from(other.group0()[0]) * Simd32x3::from([0.0, 1.0, -1.0]) } }
2635    }
2636}
2637
2638impl RegressiveProduct<Point> for Point {
2639    type Output = Plane;
2640
2641    fn regressive_product(self, other: Point) -> Plane {
2642        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]) } }
2643    }
2644}
2645
2646impl InnerProduct<Point> for Point {
2647    type Output = f32;
2648
2649    fn inner_product(self, other: Point) -> f32 {
2650        0.0 - self.group0()[0] * other.group0()[0]
2651    }
2652}
2653
2654impl LeftContraction<Point> for Point {
2655    type Output = f32;
2656
2657    fn left_contraction(self, other: Point) -> f32 {
2658        0.0 - self.group0()[0] * other.group0()[0]
2659    }
2660}
2661
2662impl RightContraction<Point> for Point {
2663    type Output = f32;
2664
2665    fn right_contraction(self, other: Point) -> f32 {
2666        0.0 - self.group0()[0] * other.group0()[0]
2667    }
2668}
2669
2670impl ScalarProduct<Point> for Point {
2671    type Output = f32;
2672
2673    fn scalar_product(self, other: Point) -> f32 {
2674        0.0 - self.group0()[0] * other.group0()[0]
2675    }
2676}
2677
2678impl Into<IdealPoint> for Point {
2679    fn into(self) -> IdealPoint {
2680        IdealPoint { groups: IdealPointGroups { g0: Simd32x2::from([self.group0()[1], self.group0()[2]]) } }
2681    }
2682}
2683
2684impl Add<IdealPoint> for Point {
2685    type Output = Point;
2686
2687    fn add(self, other: IdealPoint) -> Point {
2688        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]) } }
2689    }
2690}
2691
2692impl AddAssign<IdealPoint> for Point {
2693    fn add_assign(&mut self, other: IdealPoint) {
2694        *self = (*self).add(other);
2695    }
2696}
2697
2698impl Sub<IdealPoint> for Point {
2699    type Output = Point;
2700
2701    fn sub(self, other: IdealPoint) -> Point {
2702        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]) } }
2703    }
2704}
2705
2706impl SubAssign<IdealPoint> for Point {
2707    fn sub_assign(&mut self, other: IdealPoint) {
2708        *self = (*self).sub(other);
2709    }
2710}
2711
2712impl GeometricProduct<IdealPoint> for Point {
2713    type Output = IdealPoint;
2714
2715    fn geometric_product(self, other: IdealPoint) -> IdealPoint {
2716        IdealPoint { groups: IdealPointGroups { g0: Simd32x2::from(self.group0()[0]) * swizzle!(other.group0(), 1, 0) * Simd32x2::from([-1.0, 1.0]) } }
2717    }
2718}
2719
2720impl RegressiveProduct<IdealPoint> for Point {
2721    type Output = Plane;
2722
2723    fn regressive_product(self, other: IdealPoint) -> Plane {
2724        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]) } }
2725    }
2726}
2727
2728impl GeometricProduct<Plane> for Point {
2729    type Output = MotorDual;
2730
2731    fn geometric_product(self, other: Plane) -> MotorDual {
2732        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[1]) * 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.group0()[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.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]) } }
2733    }
2734}
2735
2736impl RegressiveProduct<Plane> for Point {
2737    type Output = f32;
2738
2739    fn regressive_product(self, other: Plane) -> f32 {
2740        self.group0()[0] * other.group0()[0] + self.group0()[1] * other.group0()[1] + self.group0()[2] * other.group0()[2]
2741    }
2742}
2743
2744impl InnerProduct<Plane> for Point {
2745    type Output = Plane;
2746
2747    fn inner_product(self, other: Plane) -> Plane {
2748        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]) } }
2749    }
2750}
2751
2752impl RightContraction<Plane> for Point {
2753    type Output = Plane;
2754
2755    fn right_contraction(self, other: Plane) -> Plane {
2756        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]) } }
2757    }
2758}
2759
2760impl Add<Translator> for Point {
2761    type Output = Motor;
2762
2763    fn add(self, other: Translator) -> Motor {
2764        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]) } }
2765    }
2766}
2767
2768impl Sub<Translator> for Point {
2769    type Output = Motor;
2770
2771    fn sub(self, other: Translator) -> Motor {
2772        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]) } }
2773    }
2774}
2775
2776impl GeometricProduct<Translator> for Point {
2777    type Output = Point;
2778
2779    fn geometric_product(self, other: Translator) -> Point {
2780        Point { groups: PointGroups { g0: Simd32x3::from(self.group0()[0]) * swizzle!(other.group0(), 0, 2, 1) * Simd32x3::from([1.0, -1.0, 1.0]) + self.group0() * Simd32x3::from(other.group0()[0]) * Simd32x3::from([0.0, 1.0, 1.0]) } }
2781    }
2782}
2783
2784impl RegressiveProduct<Translator> for Point {
2785    type Output = Plane;
2786
2787    fn regressive_product(self, other: Translator) -> Plane {
2788        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]) } }
2789    }
2790}
2791
2792impl OuterProduct<Translator> for Point {
2793    type Output = Point;
2794
2795    fn outer_product(self, other: Translator) -> Point {
2796        Point { groups: PointGroups { g0: self.group0() * Simd32x3::from(other.group0()[0]) } }
2797    }
2798}
2799
2800impl InnerProduct<Translator> for Point {
2801    type Output = Point;
2802
2803    fn inner_product(self, other: Translator) -> Point {
2804        Point { groups: PointGroups { g0: self.group0() * Simd32x3::from(other.group0()[0]) } }
2805    }
2806}
2807
2808impl RightContraction<Translator> for Point {
2809    type Output = Point;
2810
2811    fn right_contraction(self, other: Translator) -> Point {
2812        Point { groups: PointGroups { g0: self.group0() * Simd32x3::from(other.group0()[0]) } }
2813    }
2814}
2815
2816impl Add<Motor> for Point {
2817    type Output = Motor;
2818
2819    fn add(self, other: Motor) -> Motor {
2820        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() } }
2821    }
2822}
2823
2824impl Sub<Motor> for Point {
2825    type Output = Motor;
2826
2827    fn sub(self, other: Motor) -> 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]) - other.group0() } }
2829    }
2830}
2831
2832impl GeometricProduct<Motor> for Point {
2833    type Output = Motor;
2834
2835    fn geometric_product(self, other: Motor) -> Motor {
2836        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()[2]) * swizzle!(other.group0(), 1, 1, 1, 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]]) * swizzle!(other.group0(), 0, 0, 0, 1) * Simd32x4::from([0.0, 0.0, 1.0, -1.0]) } }
2837    }
2838}
2839
2840impl RegressiveProduct<Motor> for Point {
2841    type Output = Plane;
2842
2843    fn regressive_product(self, other: Motor) -> Plane {
2844        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]) } }
2845    }
2846}
2847
2848impl OuterProduct<Motor> for Point {
2849    type Output = Point;
2850
2851    fn outer_product(self, other: Motor) -> Point {
2852        Point { groups: PointGroups { g0: self.group0() * Simd32x3::from(other.group0()[0]) } }
2853    }
2854}
2855
2856impl InnerProduct<Motor> for Point {
2857    type Output = Motor;
2858
2859    fn inner_product(self, other: Motor) -> Motor {
2860        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[1], self.group0()[2]]) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) } }
2861    }
2862}
2863
2864impl LeftContraction<Motor> for Point {
2865    type Output = f32;
2866
2867    fn left_contraction(self, other: Motor) -> f32 {
2868        0.0 - self.group0()[0] * other.group0()[1]
2869    }
2870}
2871
2872impl RightContraction<Motor> for Point {
2873    type Output = Motor;
2874
2875    fn right_contraction(self, other: Motor) -> Motor {
2876        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group0()[0], self.group0()[1], self.group0()[2]]) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) } }
2877    }
2878}
2879
2880impl ScalarProduct<Motor> for Point {
2881    type Output = f32;
2882
2883    fn scalar_product(self, other: Motor) -> f32 {
2884        0.0 - self.group0()[0] * other.group0()[1]
2885    }
2886}
2887
2888impl GeometricProduct<MotorDual> for Point {
2889    type Output = MotorDual;
2890
2891    fn geometric_product(self, other: MotorDual) -> MotorDual {
2892        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()[2]) * swizzle!(other.group0(), 3, 2, 3, 3) * Simd32x4::from([1.0, -1.0, 0.0, 0.0]) + Simd32x4::from([self.group0()[1], self.group0()[1], self.group0()[0], self.group0()[0]]) * swizzle!(other.group0(), 2, 3, 0, 0) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) } }
2893    }
2894}
2895
2896impl RegressiveProduct<MotorDual> for Point {
2897    type Output = Motor;
2898
2899    fn regressive_product(self, other: MotorDual) -> Motor {
2900        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]) } }
2901    }
2902}
2903
2904impl InnerProduct<MotorDual> for Point {
2905    type Output = Plane;
2906
2907    fn inner_product(self, other: MotorDual) -> Plane {
2908        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()[2]) * Simd32x3::from(other.group0()[2]) * Simd32x3::from([-1.0, 0.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0) * Simd32x3::from([other.group0()[3], other.group0()[0], other.group0()[0]]) * Simd32x3::from([1.0, 0.0, 0.0]) } }
2909    }
2910}
2911
2912impl RightContraction<MotorDual> for Point {
2913    type Output = Plane;
2914
2915    fn right_contraction(self, other: MotorDual) -> Plane {
2916        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[2]) * Simd32x3::from(other.group0()[2]) * Simd32x3::from([-1.0, 0.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0) * Simd32x3::from([other.group0()[3], other.group0()[3], other.group0()[2]]) * Simd32x3::from([1.0, -1.0, 1.0]) } }
2917    }
2918}
2919
2920impl SquaredMagnitude for Point {
2921    type Output = f32;
2922
2923    fn squared_magnitude(self) -> f32 {
2924        self.scalar_product(self.reversal())
2925    }
2926}
2927
2928impl Magnitude for Point {
2929    type Output = f32;
2930
2931    fn magnitude(self) -> f32 {
2932        self.squared_magnitude().sqrt()
2933    }
2934}
2935
2936impl Mul<f32> for Point {
2937    type Output = Point;
2938
2939    fn mul(self, other: f32) -> Point {
2940        self.geometric_product(other)
2941    }
2942}
2943
2944impl MulAssign<f32> for Point {
2945    fn mul_assign(&mut self, other: f32) {
2946        *self = (*self).mul(other);
2947    }
2948}
2949
2950impl Signum for Point {
2951    type Output = Point;
2952
2953    fn signum(self) -> Point {
2954        self.geometric_product(1.0 / self.magnitude())
2955    }
2956}
2957
2958impl Inverse for Point {
2959    type Output = Point;
2960
2961    fn inverse(self) -> Point {
2962        self.reversal().geometric_product(1.0 / self.squared_magnitude())
2963    }
2964}
2965
2966impl Zero for IdealPoint {
2967    fn zero() -> Self {
2968        IdealPoint { groups: IdealPointGroups { g0: Simd32x2::from(0.0) } }
2969    }
2970}
2971
2972impl One for IdealPoint {
2973    fn one() -> Self {
2974        IdealPoint { groups: IdealPointGroups { g0: Simd32x2::from(0.0) } }
2975    }
2976}
2977
2978impl Neg for IdealPoint {
2979    type Output = IdealPoint;
2980
2981    fn neg(self) -> IdealPoint {
2982        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x2::from(-1.0) } }
2983    }
2984}
2985
2986impl Automorphism for IdealPoint {
2987    type Output = IdealPoint;
2988
2989    fn automorphism(self) -> IdealPoint {
2990        IdealPoint { groups: IdealPointGroups { g0: self.group0() } }
2991    }
2992}
2993
2994impl Reversal for IdealPoint {
2995    type Output = IdealPoint;
2996
2997    fn reversal(self) -> IdealPoint {
2998        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x2::from(-1.0) } }
2999    }
3000}
3001
3002impl Conjugation for IdealPoint {
3003    type Output = IdealPoint;
3004
3005    fn conjugation(self) -> IdealPoint {
3006        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x2::from(-1.0) } }
3007    }
3008}
3009
3010impl Add<f32> for IdealPoint {
3011    type Output = Translator;
3012
3013    fn add(self, other: f32) -> Translator {
3014        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]) } }
3015    }
3016}
3017
3018impl Sub<f32> for IdealPoint {
3019    type Output = Translator;
3020
3021    fn sub(self, other: f32) -> Translator {
3022        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]) } }
3023    }
3024}
3025
3026impl GeometricProduct<f32> for IdealPoint {
3027    type Output = IdealPoint;
3028
3029    fn geometric_product(self, other: f32) -> IdealPoint {
3030        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x2::from(other) } }
3031    }
3032}
3033
3034impl OuterProduct<f32> for IdealPoint {
3035    type Output = IdealPoint;
3036
3037    fn outer_product(self, other: f32) -> IdealPoint {
3038        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x2::from(other) } }
3039    }
3040}
3041
3042impl InnerProduct<f32> for IdealPoint {
3043    type Output = IdealPoint;
3044
3045    fn inner_product(self, other: f32) -> IdealPoint {
3046        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x2::from(other) } }
3047    }
3048}
3049
3050impl RightContraction<f32> for IdealPoint {
3051    type Output = IdealPoint;
3052
3053    fn right_contraction(self, other: f32) -> IdealPoint {
3054        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x2::from(other) } }
3055    }
3056}
3057
3058impl Add<MultiVector> for IdealPoint {
3059    type Output = MultiVector;
3060
3061    fn add(self, other: MultiVector) -> MultiVector {
3062        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() } }
3063    }
3064}
3065
3066impl Sub<MultiVector> for IdealPoint {
3067    type Output = MultiVector;
3068
3069    fn sub(self, other: MultiVector) -> MultiVector {
3070        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() } }
3071    }
3072}
3073
3074impl Add<Rotor> for IdealPoint {
3075    type Output = Motor;
3076
3077    fn add(self, other: Rotor) -> Motor {
3078        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]) } }
3079    }
3080}
3081
3082impl Sub<Rotor> for IdealPoint {
3083    type Output = Motor;
3084
3085    fn sub(self, other: Rotor) -> Motor {
3086        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]) } }
3087    }
3088}
3089
3090impl GeometricProduct<Rotor> for IdealPoint {
3091    type Output = IdealPoint;
3092
3093    fn geometric_product(self, other: Rotor) -> IdealPoint {
3094        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) } }
3095    }
3096}
3097
3098impl OuterProduct<Rotor> for IdealPoint {
3099    type Output = IdealPoint;
3100
3101    fn outer_product(self, other: Rotor) -> IdealPoint {
3102        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x2::from(other.group0()[0]) } }
3103    }
3104}
3105
3106impl InnerProduct<Rotor> for IdealPoint {
3107    type Output = IdealPoint;
3108
3109    fn inner_product(self, other: Rotor) -> IdealPoint {
3110        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x2::from(other.group0()[0]) } }
3111    }
3112}
3113
3114impl RightContraction<Rotor> for IdealPoint {
3115    type Output = IdealPoint;
3116
3117    fn right_contraction(self, other: Rotor) -> IdealPoint {
3118        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x2::from(other.group0()[0]) } }
3119    }
3120}
3121
3122impl Add<Point> for IdealPoint {
3123    type Output = Point;
3124
3125    fn add(self, other: Point) -> Point {
3126        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() } }
3127    }
3128}
3129
3130impl Sub<Point> for IdealPoint {
3131    type Output = Point;
3132
3133    fn sub(self, other: Point) -> Point {
3134        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() } }
3135    }
3136}
3137
3138impl GeometricProduct<Point> for IdealPoint {
3139    type Output = IdealPoint;
3140
3141    fn geometric_product(self, other: Point) -> IdealPoint {
3142        IdealPoint { groups: IdealPointGroups { g0: swizzle!(self.group0(), 1, 0) * Simd32x2::from(other.group0()[0]) * Simd32x2::from([1.0, -1.0]) } }
3143    }
3144}
3145
3146impl RegressiveProduct<Point> for IdealPoint {
3147    type Output = Plane;
3148
3149    fn regressive_product(self, other: Point) -> Plane {
3150        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]) } }
3151    }
3152}
3153
3154impl Add<IdealPoint> for IdealPoint {
3155    type Output = IdealPoint;
3156
3157    fn add(self, other: IdealPoint) -> IdealPoint {
3158        IdealPoint { groups: IdealPointGroups { g0: self.group0() + other.group0() } }
3159    }
3160}
3161
3162impl AddAssign<IdealPoint> for IdealPoint {
3163    fn add_assign(&mut self, other: IdealPoint) {
3164        *self = (*self).add(other);
3165    }
3166}
3167
3168impl Sub<IdealPoint> for IdealPoint {
3169    type Output = IdealPoint;
3170
3171    fn sub(self, other: IdealPoint) -> IdealPoint {
3172        IdealPoint { groups: IdealPointGroups { g0: self.group0() - other.group0() } }
3173    }
3174}
3175
3176impl SubAssign<IdealPoint> for IdealPoint {
3177    fn sub_assign(&mut self, other: IdealPoint) {
3178        *self = (*self).sub(other);
3179    }
3180}
3181
3182impl Mul<IdealPoint> for IdealPoint {
3183    type Output = IdealPoint;
3184
3185    fn mul(self, other: IdealPoint) -> IdealPoint {
3186        IdealPoint { groups: IdealPointGroups { g0: self.group0() * other.group0() } }
3187    }
3188}
3189
3190impl MulAssign<IdealPoint> for IdealPoint {
3191    fn mul_assign(&mut self, other: IdealPoint) {
3192        *self = (*self).mul(other);
3193    }
3194}
3195
3196impl Div<IdealPoint> for IdealPoint {
3197    type Output = IdealPoint;
3198
3199    fn div(self, other: IdealPoint) -> IdealPoint {
3200        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]) } }
3201    }
3202}
3203
3204impl DivAssign<IdealPoint> for IdealPoint {
3205    fn div_assign(&mut self, other: IdealPoint) {
3206        *self = (*self).div(other);
3207    }
3208}
3209
3210impl RegressiveProduct<Plane> for IdealPoint {
3211    type Output = f32;
3212
3213    fn regressive_product(self, other: Plane) -> f32 {
3214        self.group0()[0] * other.group0()[1] + self.group0()[1] * other.group0()[2]
3215    }
3216}
3217
3218impl Add<Translator> for IdealPoint {
3219    type Output = Translator;
3220
3221    fn add(self, other: Translator) -> Translator {
3222        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() } }
3223    }
3224}
3225
3226impl Sub<Translator> for IdealPoint {
3227    type Output = Translator;
3228
3229    fn sub(self, other: Translator) -> Translator {
3230        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() } }
3231    }
3232}
3233
3234impl GeometricProduct<Translator> for IdealPoint {
3235    type Output = IdealPoint;
3236
3237    fn geometric_product(self, other: Translator) -> IdealPoint {
3238        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x2::from(other.group0()[0]) } }
3239    }
3240}
3241
3242impl OuterProduct<Translator> for IdealPoint {
3243    type Output = IdealPoint;
3244
3245    fn outer_product(self, other: Translator) -> IdealPoint {
3246        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x2::from(other.group0()[0]) } }
3247    }
3248}
3249
3250impl InnerProduct<Translator> for IdealPoint {
3251    type Output = IdealPoint;
3252
3253    fn inner_product(self, other: Translator) -> IdealPoint {
3254        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x2::from(other.group0()[0]) } }
3255    }
3256}
3257
3258impl RightContraction<Translator> for IdealPoint {
3259    type Output = IdealPoint;
3260
3261    fn right_contraction(self, other: Translator) -> IdealPoint {
3262        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x2::from(other.group0()[0]) } }
3263    }
3264}
3265
3266impl Add<Motor> for IdealPoint {
3267    type Output = Motor;
3268
3269    fn add(self, other: Motor) -> Motor {
3270        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() } }
3271    }
3272}
3273
3274impl Sub<Motor> for IdealPoint {
3275    type Output = Motor;
3276
3277    fn sub(self, other: Motor) -> Motor {
3278        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() } }
3279    }
3280}
3281
3282impl GeometricProduct<Motor> for IdealPoint {
3283    type Output = IdealPoint;
3284
3285    fn geometric_product(self, other: Motor) -> IdealPoint {
3286        IdealPoint { groups: IdealPointGroups { g0: Simd32x2::from(self.group0()[0]) * Simd32x2::from([other.group0()[0], other.group0()[1]]) * Simd32x2::from([1.0, -1.0]) + Simd32x2::from(self.group0()[1]) * Simd32x2::from([other.group0()[1], other.group0()[0]]) } }
3287    }
3288}
3289
3290impl RegressiveProduct<Motor> for IdealPoint {
3291    type Output = Plane;
3292
3293    fn regressive_product(self, other: Motor) -> Plane {
3294        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]) } }
3295    }
3296}
3297
3298impl OuterProduct<Motor> for IdealPoint {
3299    type Output = IdealPoint;
3300
3301    fn outer_product(self, other: Motor) -> IdealPoint {
3302        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x2::from(other.group0()[0]) } }
3303    }
3304}
3305
3306impl InnerProduct<Motor> for IdealPoint {
3307    type Output = IdealPoint;
3308
3309    fn inner_product(self, other: Motor) -> IdealPoint {
3310        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x2::from(other.group0()[0]) } }
3311    }
3312}
3313
3314impl RightContraction<Motor> for IdealPoint {
3315    type Output = IdealPoint;
3316
3317    fn right_contraction(self, other: Motor) -> IdealPoint {
3318        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x2::from(other.group0()[0]) } }
3319    }
3320}
3321
3322impl RegressiveProduct<MotorDual> for IdealPoint {
3323    type Output = Translator;
3324
3325    fn regressive_product(self, other: MotorDual) -> Translator {
3326        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]) } }
3327    }
3328}
3329
3330impl Mul<f32> for IdealPoint {
3331    type Output = IdealPoint;
3332
3333    fn mul(self, other: f32) -> IdealPoint {
3334        self.geometric_product(other)
3335    }
3336}
3337
3338impl MulAssign<f32> for IdealPoint {
3339    fn mul_assign(&mut self, other: f32) {
3340        *self = (*self).mul(other);
3341    }
3342}
3343
3344impl Zero for Plane {
3345    fn zero() -> Self {
3346        Plane { groups: PlaneGroups { g0: Simd32x3::from(0.0) } }
3347    }
3348}
3349
3350impl One for Plane {
3351    fn one() -> Self {
3352        Plane { groups: PlaneGroups { g0: Simd32x3::from(0.0) } }
3353    }
3354}
3355
3356impl Neg for Plane {
3357    type Output = Plane;
3358
3359    fn neg(self) -> Plane {
3360        Plane { groups: PlaneGroups { g0: self.group0() * Simd32x3::from(-1.0) } }
3361    }
3362}
3363
3364impl Automorphism for Plane {
3365    type Output = Plane;
3366
3367    fn automorphism(self) -> Plane {
3368        Plane { groups: PlaneGroups { g0: self.group0() * Simd32x3::from(-1.0) } }
3369    }
3370}
3371
3372impl Reversal for Plane {
3373    type Output = Plane;
3374
3375    fn reversal(self) -> Plane {
3376        Plane { groups: PlaneGroups { g0: self.group0() } }
3377    }
3378}
3379
3380impl Conjugation for Plane {
3381    type Output = Plane;
3382
3383    fn conjugation(self) -> Plane {
3384        Plane { groups: PlaneGroups { g0: self.group0() * Simd32x3::from(-1.0) } }
3385    }
3386}
3387
3388impl Dual for Plane {
3389    type Output = Point;
3390
3391    fn dual(self) -> Point {
3392        Point { groups: PointGroups { g0: self.group0() } }
3393    }
3394}
3395
3396impl GeometricProduct<f32> for Plane {
3397    type Output = Plane;
3398
3399    fn geometric_product(self, other: f32) -> Plane {
3400        Plane { groups: PlaneGroups { g0: self.group0() * Simd32x3::from(other) } }
3401    }
3402}
3403
3404impl OuterProduct<f32> for Plane {
3405    type Output = Plane;
3406
3407    fn outer_product(self, other: f32) -> Plane {
3408        Plane { groups: PlaneGroups { g0: self.group0() * Simd32x3::from(other) } }
3409    }
3410}
3411
3412impl InnerProduct<f32> for Plane {
3413    type Output = Plane;
3414
3415    fn inner_product(self, other: f32) -> Plane {
3416        Plane { groups: PlaneGroups { g0: self.group0() * Simd32x3::from(other) } }
3417    }
3418}
3419
3420impl RightContraction<f32> for Plane {
3421    type Output = Plane;
3422
3423    fn right_contraction(self, other: f32) -> Plane {
3424        Plane { groups: PlaneGroups { g0: self.group0() * Simd32x3::from(other) } }
3425    }
3426}
3427
3428impl Add<MultiVector> for Plane {
3429    type Output = MultiVector;
3430
3431    fn add(self, other: MultiVector) -> MultiVector {
3432        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() } }
3433    }
3434}
3435
3436impl Sub<MultiVector> for Plane {
3437    type Output = MultiVector;
3438
3439    fn sub(self, other: MultiVector) -> MultiVector {
3440        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() } }
3441    }
3442}
3443
3444impl GeometricProduct<MultiVector> for Plane {
3445    type Output = MultiVector;
3446
3447    fn geometric_product(self, other: MultiVector) -> MultiVector {
3448        MultiVector { groups: MultiVectorGroups { g0: 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]) } }
3449    }
3450}
3451
3452impl ScalarProduct<MultiVector> for Plane {
3453    type Output = f32;
3454
3455    fn scalar_product(self, other: MultiVector) -> f32 {
3456        self.group0()[1] * other.group0()[3] + self.group0()[2] * other.group0()[2]
3457    }
3458}
3459
3460impl GeometricProduct<Rotor> for Plane {
3461    type Output = MotorDual;
3462
3463    fn geometric_product(self, other: Rotor) -> MotorDual {
3464        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]) } }
3465    }
3466}
3467
3468impl RegressiveProduct<Rotor> for Plane {
3469    type Output = f32;
3470
3471    fn regressive_product(self, other: Rotor) -> f32 {
3472        self.group0()[0] * other.group0()[1]
3473    }
3474}
3475
3476impl OuterProduct<Rotor> for Plane {
3477    type Output = MotorDual;
3478
3479    fn outer_product(self, other: Rotor) -> MotorDual {
3480        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]]) } }
3481    }
3482}
3483
3484impl InnerProduct<Rotor> for Plane {
3485    type Output = Plane;
3486
3487    fn inner_product(self, other: Rotor) -> Plane {
3488        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]) } }
3489    }
3490}
3491
3492impl RightContraction<Rotor> for Plane {
3493    type Output = Plane;
3494
3495    fn right_contraction(self, other: Rotor) -> Plane {
3496        Plane { groups: PlaneGroups { g0: self.group0() * Simd32x3::from(other.group0()[0]) } }
3497    }
3498}
3499
3500impl GeometricProduct<Point> for Plane {
3501    type Output = MotorDual;
3502
3503    fn geometric_product(self, other: Point) -> MotorDual {
3504        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]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
3505    }
3506}
3507
3508impl RegressiveProduct<Point> for Plane {
3509    type Output = f32;
3510
3511    fn regressive_product(self, other: Point) -> f32 {
3512        self.group0()[0] * other.group0()[0] + self.group0()[1] * other.group0()[1] + self.group0()[2] * other.group0()[2]
3513    }
3514}
3515
3516impl InnerProduct<Point> for Plane {
3517    type Output = Plane;
3518
3519    fn inner_product(self, other: Point) -> Plane {
3520        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]) } }
3521    }
3522}
3523
3524impl LeftContraction<Point> for Plane {
3525    type Output = Plane;
3526
3527    fn left_contraction(self, other: Point) -> Plane {
3528        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]) } }
3529    }
3530}
3531
3532impl RegressiveProduct<IdealPoint> for Plane {
3533    type Output = f32;
3534
3535    fn regressive_product(self, other: IdealPoint) -> f32 {
3536        self.group0()[1] * other.group0()[0] + self.group0()[2] * other.group0()[1]
3537    }
3538}
3539
3540impl Add<Plane> for Plane {
3541    type Output = Plane;
3542
3543    fn add(self, other: Plane) -> Plane {
3544        Plane { groups: PlaneGroups { g0: self.group0() + other.group0() } }
3545    }
3546}
3547
3548impl AddAssign<Plane> for Plane {
3549    fn add_assign(&mut self, other: Plane) {
3550        *self = (*self).add(other);
3551    }
3552}
3553
3554impl Sub<Plane> for Plane {
3555    type Output = Plane;
3556
3557    fn sub(self, other: Plane) -> Plane {
3558        Plane { groups: PlaneGroups { g0: self.group0() - other.group0() } }
3559    }
3560}
3561
3562impl SubAssign<Plane> for Plane {
3563    fn sub_assign(&mut self, other: Plane) {
3564        *self = (*self).sub(other);
3565    }
3566}
3567
3568impl Mul<Plane> for Plane {
3569    type Output = Plane;
3570
3571    fn mul(self, other: Plane) -> Plane {
3572        Plane { groups: PlaneGroups { g0: self.group0() * other.group0() } }
3573    }
3574}
3575
3576impl MulAssign<Plane> for Plane {
3577    fn mul_assign(&mut self, other: Plane) {
3578        *self = (*self).mul(other);
3579    }
3580}
3581
3582impl Div<Plane> for Plane {
3583    type Output = Plane;
3584
3585    fn div(self, other: Plane) -> Plane {
3586        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]) } }
3587    }
3588}
3589
3590impl DivAssign<Plane> for Plane {
3591    fn div_assign(&mut self, other: Plane) {
3592        *self = (*self).div(other);
3593    }
3594}
3595
3596impl GeometricProduct<Plane> for Plane {
3597    type Output = Motor;
3598
3599    fn geometric_product(self, other: Plane) -> Motor {
3600        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([0.0, 0.0, 1.0, -1.0]) } }
3601    }
3602}
3603
3604impl OuterProduct<Plane> for Plane {
3605    type Output = Point;
3606
3607    fn outer_product(self, other: Plane) -> Point {
3608        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]) } }
3609    }
3610}
3611
3612impl InnerProduct<Plane> for Plane {
3613    type Output = f32;
3614
3615    fn inner_product(self, other: Plane) -> f32 {
3616        self.group0()[1] * other.group0()[1] + self.group0()[2] * other.group0()[2]
3617    }
3618}
3619
3620impl LeftContraction<Plane> for Plane {
3621    type Output = f32;
3622
3623    fn left_contraction(self, other: Plane) -> f32 {
3624        self.group0()[1] * other.group0()[1] + self.group0()[2] * other.group0()[2]
3625    }
3626}
3627
3628impl RightContraction<Plane> for Plane {
3629    type Output = f32;
3630
3631    fn right_contraction(self, other: Plane) -> f32 {
3632        self.group0()[1] * other.group0()[1] + self.group0()[2] * other.group0()[2]
3633    }
3634}
3635
3636impl ScalarProduct<Plane> for Plane {
3637    type Output = f32;
3638
3639    fn scalar_product(self, other: Plane) -> f32 {
3640        self.group0()[1] * other.group0()[1] + self.group0()[2] * other.group0()[2]
3641    }
3642}
3643
3644impl GeometricProduct<Translator> for Plane {
3645    type Output = MotorDual;
3646
3647    fn geometric_product(self, other: Translator) -> MotorDual {
3648        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]) * Simd32x4::from([0.0, 1.0, 0.0, 0.0]) } }
3649    }
3650}
3651
3652impl RegressiveProduct<Translator> for Plane {
3653    type Output = f32;
3654
3655    fn regressive_product(self, other: Translator) -> f32 {
3656        self.group0()[1] * other.group0()[1] + self.group0()[2] * other.group0()[2]
3657    }
3658}
3659
3660impl OuterProduct<Translator> for Plane {
3661    type Output = MotorDual;
3662
3663    fn outer_product(self, other: Translator) -> MotorDual {
3664        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]) } }
3665    }
3666}
3667
3668impl InnerProduct<Translator> for Plane {
3669    type Output = Plane;
3670
3671    fn inner_product(self, other: Translator) -> Plane {
3672        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[1]) * swizzle!(other.group0(), 2, 0, 2) * Simd32x3::from([1.0, 1.0, 0.0]) + Simd32x3::from(self.group0()[2]) * swizzle!(other.group0(), 1, 1, 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]) } }
3673    }
3674}
3675
3676impl RightContraction<Translator> for Plane {
3677    type Output = Plane;
3678
3679    fn right_contraction(self, other: Translator) -> Plane {
3680        Plane { groups: PlaneGroups { g0: self.group0() * Simd32x3::from(other.group0()[0]) } }
3681    }
3682}
3683
3684impl GeometricProduct<Motor> for Plane {
3685    type Output = MotorDual;
3686
3687    fn geometric_product(self, other: Motor) -> MotorDual {
3688        MotorDual { groups: MotorDualGroups { g0: 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]) + Simd32x4::from(self.group0()[0]) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) } }
3689    }
3690}
3691
3692impl RegressiveProduct<Motor> for Plane {
3693    type Output = f32;
3694
3695    fn regressive_product(self, other: Motor) -> f32 {
3696        self.group0()[0] * other.group0()[1] + self.group0()[1] * other.group0()[2] + self.group0()[2] * other.group0()[3]
3697    }
3698}
3699
3700impl OuterProduct<Motor> for Plane {
3701    type Output = MotorDual;
3702
3703    fn outer_product(self, other: Motor) -> MotorDual {
3704        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]) } }
3705    }
3706}
3707
3708impl InnerProduct<Motor> for Plane {
3709    type Output = Plane;
3710
3711    fn inner_product(self, other: Motor) -> Plane {
3712        Plane { groups: PlaneGroups { g0: 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]) + Simd32x3::from(self.group0()[0]) * Simd32x3::from(other.group0()[0]) * Simd32x3::from([1.0, 0.0, 0.0]) } }
3713    }
3714}
3715
3716impl LeftContraction<Motor> for Plane {
3717    type Output = Plane;
3718
3719    fn left_contraction(self, other: Motor) -> Plane {
3720        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]) } }
3721    }
3722}
3723
3724impl RightContraction<Motor> for Plane {
3725    type Output = Plane;
3726
3727    fn right_contraction(self, other: Motor) -> Plane {
3728        Plane { groups: PlaneGroups { g0: self.group0() * Simd32x3::from(other.group0()[0]) } }
3729    }
3730}
3731
3732impl Add<MotorDual> for Plane {
3733    type Output = MotorDual;
3734
3735    fn add(self, other: MotorDual) -> MotorDual {
3736        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() } }
3737    }
3738}
3739
3740impl Sub<MotorDual> for Plane {
3741    type Output = MotorDual;
3742
3743    fn sub(self, other: MotorDual) -> MotorDual {
3744        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() } }
3745    }
3746}
3747
3748impl GeometricProduct<MotorDual> for Plane {
3749    type Output = Motor;
3750
3751    fn geometric_product(self, other: MotorDual) -> Motor {
3752        Motor { groups: MotorGroups { g0: 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]) + Simd32x4::from(self.group0()[0]) * swizzle!(other.group0(), 0, 0, 3, 2) * Simd32x4::from([0.0, 0.0, 1.0, -1.0]) } }
3753    }
3754}
3755
3756impl RegressiveProduct<MotorDual> for Plane {
3757    type Output = Plane;
3758
3759    fn regressive_product(self, other: MotorDual) -> Plane {
3760        Plane { groups: PlaneGroups { g0: self.group0() * Simd32x3::from(other.group0()[0]) } }
3761    }
3762}
3763
3764impl OuterProduct<MotorDual> for Plane {
3765    type Output = Point;
3766
3767    fn outer_product(self, other: MotorDual) -> Point {
3768        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]) } }
3769    }
3770}
3771
3772impl InnerProduct<MotorDual> for Plane {
3773    type Output = Translator;
3774
3775    fn inner_product(self, other: MotorDual) -> Translator {
3776        Translator { groups: TranslatorGroups { g0: Simd32x3::from(self.group0()[2]) * Simd32x3::from([other.group0()[3], other.group0()[3], other.group0()[0]]) * Simd32x3::from([1.0, 0.0, 1.0]) + swizzle!(self.group0(), 1, 1, 0) * Simd32x3::from([other.group0()[2], other.group0()[0], other.group0()[0]]) * Simd32x3::from([1.0, 1.0, 0.0]) } }
3777    }
3778}
3779
3780impl LeftContraction<MotorDual> for Plane {
3781    type Output = Translator;
3782
3783    fn left_contraction(self, other: MotorDual) -> Translator {
3784        Translator { groups: TranslatorGroups { g0: Simd32x3::from(self.group0()[2]) * Simd32x3::from([other.group0()[3], other.group0()[3], other.group0()[0]]) * Simd32x3::from([1.0, 0.0, 1.0]) + swizzle!(self.group0(), 1, 1, 0) * Simd32x3::from([other.group0()[2], other.group0()[0], other.group0()[0]]) * Simd32x3::from([1.0, 1.0, 0.0]) } }
3785    }
3786}
3787
3788impl RightContraction<MotorDual> for Plane {
3789    type Output = f32;
3790
3791    fn right_contraction(self, other: MotorDual) -> f32 {
3792        self.group0()[1] * other.group0()[2] + self.group0()[2] * other.group0()[3]
3793    }
3794}
3795
3796impl ScalarProduct<MotorDual> for Plane {
3797    type Output = f32;
3798
3799    fn scalar_product(self, other: MotorDual) -> f32 {
3800        self.group0()[1] * other.group0()[2] + self.group0()[2] * other.group0()[3]
3801    }
3802}
3803
3804impl SquaredMagnitude for Plane {
3805    type Output = f32;
3806
3807    fn squared_magnitude(self) -> f32 {
3808        self.scalar_product(self.reversal())
3809    }
3810}
3811
3812impl Magnitude for Plane {
3813    type Output = f32;
3814
3815    fn magnitude(self) -> f32 {
3816        self.squared_magnitude().sqrt()
3817    }
3818}
3819
3820impl Mul<f32> for Plane {
3821    type Output = Plane;
3822
3823    fn mul(self, other: f32) -> Plane {
3824        self.geometric_product(other)
3825    }
3826}
3827
3828impl MulAssign<f32> for Plane {
3829    fn mul_assign(&mut self, other: f32) {
3830        *self = (*self).mul(other);
3831    }
3832}
3833
3834impl Signum for Plane {
3835    type Output = Plane;
3836
3837    fn signum(self) -> Plane {
3838        self.geometric_product(1.0 / self.magnitude())
3839    }
3840}
3841
3842impl Inverse for Plane {
3843    type Output = Plane;
3844
3845    fn inverse(self) -> Plane {
3846        self.reversal().geometric_product(1.0 / self.squared_magnitude())
3847    }
3848}
3849
3850impl Zero for Translator {
3851    fn zero() -> Self {
3852        Translator { groups: TranslatorGroups { g0: Simd32x3::from(0.0) } }
3853    }
3854}
3855
3856impl One for Translator {
3857    fn one() -> Self {
3858        Translator { groups: TranslatorGroups { g0: Simd32x3::from([1.0, 0.0, 0.0]) } }
3859    }
3860}
3861
3862impl Neg for Translator {
3863    type Output = Translator;
3864
3865    fn neg(self) -> Translator {
3866        Translator { groups: TranslatorGroups { g0: self.group0() * Simd32x3::from(-1.0) } }
3867    }
3868}
3869
3870impl Automorphism for Translator {
3871    type Output = Translator;
3872
3873    fn automorphism(self) -> Translator {
3874        Translator { groups: TranslatorGroups { g0: self.group0() } }
3875    }
3876}
3877
3878impl Reversal for Translator {
3879    type Output = Translator;
3880
3881    fn reversal(self) -> Translator {
3882        Translator { groups: TranslatorGroups { g0: self.group0() * Simd32x3::from([1.0, -1.0, -1.0]) } }
3883    }
3884}
3885
3886impl Conjugation for Translator {
3887    type Output = Translator;
3888
3889    fn conjugation(self) -> Translator {
3890        Translator { groups: TranslatorGroups { g0: self.group0() * Simd32x3::from([1.0, -1.0, -1.0]) } }
3891    }
3892}
3893
3894impl Into<f32> for Translator {
3895    fn into(self) -> f32 {
3896        self.group0()[0]
3897    }
3898}
3899
3900impl Add<f32> for Translator {
3901    type Output = Translator;
3902
3903    fn add(self, other: f32) -> Translator {
3904        Translator { groups: TranslatorGroups { g0: self.group0() + Simd32x3::from(other) * Simd32x3::from([1.0, 0.0, 0.0]) } }
3905    }
3906}
3907
3908impl AddAssign<f32> for Translator {
3909    fn add_assign(&mut self, other: f32) {
3910        *self = (*self).add(other);
3911    }
3912}
3913
3914impl Sub<f32> for Translator {
3915    type Output = Translator;
3916
3917    fn sub(self, other: f32) -> Translator {
3918        Translator { groups: TranslatorGroups { g0: self.group0() - Simd32x3::from(other) * Simd32x3::from([1.0, 0.0, 0.0]) } }
3919    }
3920}
3921
3922impl SubAssign<f32> for Translator {
3923    fn sub_assign(&mut self, other: f32) {
3924        *self = (*self).sub(other);
3925    }
3926}
3927
3928impl GeometricProduct<f32> for Translator {
3929    type Output = Translator;
3930
3931    fn geometric_product(self, other: f32) -> Translator {
3932        Translator { groups: TranslatorGroups { g0: self.group0() * Simd32x3::from(other) } }
3933    }
3934}
3935
3936impl OuterProduct<f32> for Translator {
3937    type Output = Translator;
3938
3939    fn outer_product(self, other: f32) -> Translator {
3940        Translator { groups: TranslatorGroups { g0: self.group0() * Simd32x3::from(other) } }
3941    }
3942}
3943
3944impl InnerProduct<f32> for Translator {
3945    type Output = Translator;
3946
3947    fn inner_product(self, other: f32) -> Translator {
3948        Translator { groups: TranslatorGroups { g0: self.group0() * Simd32x3::from(other) } }
3949    }
3950}
3951
3952impl LeftContraction<f32> for Translator {
3953    type Output = f32;
3954
3955    fn left_contraction(self, other: f32) -> f32 {
3956        self.group0()[0] * other
3957    }
3958}
3959
3960impl RightContraction<f32> for Translator {
3961    type Output = Translator;
3962
3963    fn right_contraction(self, other: f32) -> Translator {
3964        Translator { groups: TranslatorGroups { g0: self.group0() * Simd32x3::from(other) } }
3965    }
3966}
3967
3968impl ScalarProduct<f32> for Translator {
3969    type Output = f32;
3970
3971    fn scalar_product(self, other: f32) -> f32 {
3972        self.group0()[0] * other
3973    }
3974}
3975
3976impl Add<MultiVector> for Translator {
3977    type Output = MultiVector;
3978
3979    fn add(self, other: MultiVector) -> MultiVector {
3980        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() } }
3981    }
3982}
3983
3984impl Sub<MultiVector> for Translator {
3985    type Output = MultiVector;
3986
3987    fn sub(self, other: MultiVector) -> MultiVector {
3988        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() } }
3989    }
3990}
3991
3992impl GeometricProduct<MultiVector> for Translator {
3993    type Output = MultiVector;
3994
3995    fn geometric_product(self, other: MultiVector) -> MultiVector {
3996        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0(), 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]) } }
3997    }
3998}
3999
4000impl OuterProduct<MultiVector> for Translator {
4001    type Output = MultiVector;
4002
4003    fn outer_product(self, other: MultiVector) -> MultiVector {
4004        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]) } }
4005    }
4006}
4007
4008impl InnerProduct<MultiVector> for Translator {
4009    type Output = MultiVector;
4010
4011    fn inner_product(self, other: MultiVector) -> MultiVector {
4012        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(), 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]) } }
4013    }
4014}
4015
4016impl LeftContraction<MultiVector> for Translator {
4017    type Output = MultiVector;
4018
4019    fn left_contraction(self, other: MultiVector) -> MultiVector {
4020        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0(), g1: Simd32x4::from(self.group0()[0]) * other.group1() } }
4021    }
4022}
4023
4024impl ScalarProduct<MultiVector> for Translator {
4025    type Output = f32;
4026
4027    fn scalar_product(self, other: MultiVector) -> f32 {
4028        self.group0()[0] * other.group0()[0]
4029    }
4030}
4031
4032impl Add<Rotor> for Translator {
4033    type Output = Motor;
4034
4035    fn add(self, other: Rotor) -> Motor {
4036        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]) } }
4037    }
4038}
4039
4040impl Sub<Rotor> for Translator {
4041    type Output = Motor;
4042
4043    fn sub(self, other: Rotor) -> Motor {
4044        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]) } }
4045    }
4046}
4047
4048impl GeometricProduct<Rotor> for Translator {
4049    type Output = Motor;
4050
4051    fn geometric_product(self, other: Rotor) -> Motor {
4052        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]) } }
4053    }
4054}
4055
4056impl OuterProduct<Rotor> for Translator {
4057    type Output = Motor;
4058
4059    fn outer_product(self, other: Rotor) -> Motor {
4060        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]]) } }
4061    }
4062}
4063
4064impl InnerProduct<Rotor> for Translator {
4065    type Output = Motor;
4066
4067    fn inner_product(self, other: Rotor) -> Motor {
4068        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]]) } }
4069    }
4070}
4071
4072impl LeftContraction<Rotor> for Translator {
4073    type Output = Rotor;
4074
4075    fn left_contraction(self, other: Rotor) -> Rotor {
4076        Rotor { groups: RotorGroups { g0: Simd32x2::from(self.group0()[0]) * other.group0() } }
4077    }
4078}
4079
4080impl RightContraction<Rotor> for Translator {
4081    type Output = Translator;
4082
4083    fn right_contraction(self, other: Rotor) -> Translator {
4084        Translator { groups: TranslatorGroups { g0: self.group0() * Simd32x3::from(other.group0()[0]) } }
4085    }
4086}
4087
4088impl ScalarProduct<Rotor> for Translator {
4089    type Output = f32;
4090
4091    fn scalar_product(self, other: Rotor) -> f32 {
4092        self.group0()[0] * other.group0()[0]
4093    }
4094}
4095
4096impl Add<Point> for Translator {
4097    type Output = Motor;
4098
4099    fn add(self, other: Point) -> Motor {
4100        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]) } }
4101    }
4102}
4103
4104impl Sub<Point> for Translator {
4105    type Output = Motor;
4106
4107    fn sub(self, other: Point) -> Motor {
4108        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]) } }
4109    }
4110}
4111
4112impl GeometricProduct<Point> for Translator {
4113    type Output = Point;
4114
4115    fn geometric_product(self, other: Point) -> Point {
4116        Point { groups: PointGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() + swizzle!(self.group0(), 0, 2, 1) * Simd32x3::from(other.group0()[0]) * Simd32x3::from([0.0, 1.0, -1.0]) } }
4117    }
4118}
4119
4120impl RegressiveProduct<Point> for Translator {
4121    type Output = Plane;
4122
4123    fn regressive_product(self, other: Point) -> Plane {
4124        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]) } }
4125    }
4126}
4127
4128impl OuterProduct<Point> for Translator {
4129    type Output = Point;
4130
4131    fn outer_product(self, other: Point) -> Point {
4132        Point { groups: PointGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() } }
4133    }
4134}
4135
4136impl InnerProduct<Point> for Translator {
4137    type Output = Point;
4138
4139    fn inner_product(self, other: Point) -> Point {
4140        Point { groups: PointGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() } }
4141    }
4142}
4143
4144impl LeftContraction<Point> for Translator {
4145    type Output = Point;
4146
4147    fn left_contraction(self, other: Point) -> Point {
4148        Point { groups: PointGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() } }
4149    }
4150}
4151
4152impl Into<IdealPoint> for Translator {
4153    fn into(self) -> IdealPoint {
4154        IdealPoint { groups: IdealPointGroups { g0: Simd32x2::from([self.group0()[1], self.group0()[2]]) } }
4155    }
4156}
4157
4158impl Add<IdealPoint> for Translator {
4159    type Output = Translator;
4160
4161    fn add(self, other: IdealPoint) -> Translator {
4162        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]) } }
4163    }
4164}
4165
4166impl AddAssign<IdealPoint> for Translator {
4167    fn add_assign(&mut self, other: IdealPoint) {
4168        *self = (*self).add(other);
4169    }
4170}
4171
4172impl Sub<IdealPoint> for Translator {
4173    type Output = Translator;
4174
4175    fn sub(self, other: IdealPoint) -> Translator {
4176        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]) } }
4177    }
4178}
4179
4180impl SubAssign<IdealPoint> for Translator {
4181    fn sub_assign(&mut self, other: IdealPoint) {
4182        *self = (*self).sub(other);
4183    }
4184}
4185
4186impl GeometricProduct<IdealPoint> for Translator {
4187    type Output = IdealPoint;
4188
4189    fn geometric_product(self, other: IdealPoint) -> IdealPoint {
4190        IdealPoint { groups: IdealPointGroups { g0: Simd32x2::from(self.group0()[0]) * other.group0() } }
4191    }
4192}
4193
4194impl OuterProduct<IdealPoint> for Translator {
4195    type Output = IdealPoint;
4196
4197    fn outer_product(self, other: IdealPoint) -> IdealPoint {
4198        IdealPoint { groups: IdealPointGroups { g0: Simd32x2::from(self.group0()[0]) * other.group0() } }
4199    }
4200}
4201
4202impl InnerProduct<IdealPoint> for Translator {
4203    type Output = IdealPoint;
4204
4205    fn inner_product(self, other: IdealPoint) -> IdealPoint {
4206        IdealPoint { groups: IdealPointGroups { g0: Simd32x2::from(self.group0()[0]) * other.group0() } }
4207    }
4208}
4209
4210impl LeftContraction<IdealPoint> for Translator {
4211    type Output = IdealPoint;
4212
4213    fn left_contraction(self, other: IdealPoint) -> IdealPoint {
4214        IdealPoint { groups: IdealPointGroups { g0: Simd32x2::from(self.group0()[0]) * other.group0() } }
4215    }
4216}
4217
4218impl GeometricProduct<Plane> for Translator {
4219    type Output = MotorDual;
4220
4221    fn geometric_product(self, other: Plane) -> MotorDual {
4222        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[1]) * 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.group0()[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.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]) } }
4223    }
4224}
4225
4226impl RegressiveProduct<Plane> for Translator {
4227    type Output = f32;
4228
4229    fn regressive_product(self, other: Plane) -> f32 {
4230        self.group0()[1] * other.group0()[1] + self.group0()[2] * other.group0()[2]
4231    }
4232}
4233
4234impl OuterProduct<Plane> for Translator {
4235    type Output = MotorDual;
4236
4237    fn outer_product(self, other: Plane) -> MotorDual {
4238        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]]) } }
4239    }
4240}
4241
4242impl InnerProduct<Plane> for Translator {
4243    type Output = Plane;
4244
4245    fn inner_product(self, other: Plane) -> Plane {
4246        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() + 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, 0, 0) * Simd32x3::from([1.0, 0.0, 0.0]) } }
4247    }
4248}
4249
4250impl LeftContraction<Plane> for Translator {
4251    type Output = Plane;
4252
4253    fn left_contraction(self, other: Plane) -> Plane {
4254        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() } }
4255    }
4256}
4257
4258impl Add<Translator> for Translator {
4259    type Output = Translator;
4260
4261    fn add(self, other: Translator) -> Translator {
4262        Translator { groups: TranslatorGroups { g0: self.group0() + other.group0() } }
4263    }
4264}
4265
4266impl AddAssign<Translator> for Translator {
4267    fn add_assign(&mut self, other: Translator) {
4268        *self = (*self).add(other);
4269    }
4270}
4271
4272impl Sub<Translator> for Translator {
4273    type Output = Translator;
4274
4275    fn sub(self, other: Translator) -> Translator {
4276        Translator { groups: TranslatorGroups { g0: self.group0() - other.group0() } }
4277    }
4278}
4279
4280impl SubAssign<Translator> for Translator {
4281    fn sub_assign(&mut self, other: Translator) {
4282        *self = (*self).sub(other);
4283    }
4284}
4285
4286impl Mul<Translator> for Translator {
4287    type Output = Translator;
4288
4289    fn mul(self, other: Translator) -> Translator {
4290        Translator { groups: TranslatorGroups { g0: self.group0() * other.group0() } }
4291    }
4292}
4293
4294impl MulAssign<Translator> for Translator {
4295    fn mul_assign(&mut self, other: Translator) {
4296        *self = (*self).mul(other);
4297    }
4298}
4299
4300impl Div<Translator> for Translator {
4301    type Output = Translator;
4302
4303    fn div(self, other: Translator) -> Translator {
4304        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]) } }
4305    }
4306}
4307
4308impl DivAssign<Translator> for Translator {
4309    fn div_assign(&mut self, other: Translator) {
4310        *self = (*self).div(other);
4311    }
4312}
4313
4314impl GeometricProduct<Translator> for Translator {
4315    type Output = Translator;
4316
4317    fn geometric_product(self, other: Translator) -> Translator {
4318        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]) } }
4319    }
4320}
4321
4322impl OuterProduct<Translator> for Translator {
4323    type Output = Translator;
4324
4325    fn outer_product(self, other: Translator) -> Translator {
4326        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]) } }
4327    }
4328}
4329
4330impl InnerProduct<Translator> for Translator {
4331    type Output = Translator;
4332
4333    fn inner_product(self, other: Translator) -> Translator {
4334        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]) } }
4335    }
4336}
4337
4338impl LeftContraction<Translator> for Translator {
4339    type Output = Translator;
4340
4341    fn left_contraction(self, other: Translator) -> Translator {
4342        Translator { groups: TranslatorGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() } }
4343    }
4344}
4345
4346impl RightContraction<Translator> for Translator {
4347    type Output = Translator;
4348
4349    fn right_contraction(self, other: Translator) -> Translator {
4350        Translator { groups: TranslatorGroups { g0: self.group0() * Simd32x3::from(other.group0()[0]) } }
4351    }
4352}
4353
4354impl ScalarProduct<Translator> for Translator {
4355    type Output = f32;
4356
4357    fn scalar_product(self, other: Translator) -> f32 {
4358        self.group0()[0] * other.group0()[0]
4359    }
4360}
4361
4362impl Add<Motor> for Translator {
4363    type Output = Motor;
4364
4365    fn add(self, other: Motor) -> Motor {
4366        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() } }
4367    }
4368}
4369
4370impl Sub<Motor> for Translator {
4371    type Output = Motor;
4372
4373    fn sub(self, other: Motor) -> Motor {
4374        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() } }
4375    }
4376}
4377
4378impl GeometricProduct<Motor> for Translator {
4379    type Output = Motor;
4380
4381    fn geometric_product(self, other: Motor) -> Motor {
4382        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 1, 1, 1, 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]]) * swizzle!(other.group0(), 0, 0, 0, 1) * Simd32x4::from([0.0, 0.0, 1.0, -1.0]) } }
4383    }
4384}
4385
4386impl RegressiveProduct<Motor> for Translator {
4387    type Output = Plane;
4388
4389    fn regressive_product(self, other: Motor) -> Plane {
4390        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]) } }
4391    }
4392}
4393
4394impl OuterProduct<Motor> for Translator {
4395    type Output = Motor;
4396
4397    fn outer_product(self, other: Motor) -> Motor {
4398        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]) } }
4399    }
4400}
4401
4402impl InnerProduct<Motor> for Translator {
4403    type Output = Motor;
4404
4405    fn inner_product(self, other: Motor) -> Motor {
4406        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]) } }
4407    }
4408}
4409
4410impl LeftContraction<Motor> for Translator {
4411    type Output = Motor;
4412
4413    fn left_contraction(self, other: Motor) -> Motor {
4414        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() } }
4415    }
4416}
4417
4418impl RightContraction<Motor> for Translator {
4419    type Output = Translator;
4420
4421    fn right_contraction(self, other: Motor) -> Translator {
4422        Translator { groups: TranslatorGroups { g0: self.group0() * Simd32x3::from(other.group0()[0]) } }
4423    }
4424}
4425
4426impl ScalarProduct<Motor> for Translator {
4427    type Output = f32;
4428
4429    fn scalar_product(self, other: Motor) -> f32 {
4430        self.group0()[0] * other.group0()[0]
4431    }
4432}
4433
4434impl GeometricProduct<MotorDual> for Translator {
4435    type Output = MotorDual;
4436
4437    fn geometric_product(self, other: MotorDual) -> MotorDual {
4438        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 3, 2, 3, 3) * Simd32x4::from([1.0, -1.0, 0.0, 0.0]) + Simd32x4::from([self.group0()[1], self.group0()[1], self.group0()[0], self.group0()[0]]) * swizzle!(other.group0(), 2, 3, 0, 0) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) } }
4439    }
4440}
4441
4442impl RegressiveProduct<MotorDual> for Translator {
4443    type Output = Translator;
4444
4445    fn regressive_product(self, other: MotorDual) -> Translator {
4446        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]) } }
4447    }
4448}
4449
4450impl OuterProduct<MotorDual> for Translator {
4451    type Output = MotorDual;
4452
4453    fn outer_product(self, other: MotorDual) -> MotorDual {
4454        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]) } }
4455    }
4456}
4457
4458impl InnerProduct<MotorDual> for Translator {
4459    type Output = MotorDual;
4460
4461    fn inner_product(self, other: MotorDual) -> MotorDual {
4462        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group0()[2]) * Simd32x4::from([0.0, -1.0, 0.0, 0.0]) + Simd32x4::from([self.group0()[0], self.group0()[1], self.group0()[0], self.group0()[0]]) * swizzle!(other.group0(), 0, 3, 0, 0) * Simd32x4::from([0.0, 1.0, 0.0, 0.0]) } }
4463    }
4464}
4465
4466impl LeftContraction<MotorDual> for Translator {
4467    type Output = MotorDual;
4468
4469    fn left_contraction(self, other: MotorDual) -> MotorDual {
4470        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() } }
4471    }
4472}
4473
4474impl SquaredMagnitude for Translator {
4475    type Output = f32;
4476
4477    fn squared_magnitude(self) -> f32 {
4478        self.scalar_product(self.reversal())
4479    }
4480}
4481
4482impl Magnitude for Translator {
4483    type Output = f32;
4484
4485    fn magnitude(self) -> f32 {
4486        self.squared_magnitude().sqrt()
4487    }
4488}
4489
4490impl Mul<f32> for Translator {
4491    type Output = Translator;
4492
4493    fn mul(self, other: f32) -> Translator {
4494        self.geometric_product(other)
4495    }
4496}
4497
4498impl MulAssign<f32> for Translator {
4499    fn mul_assign(&mut self, other: f32) {
4500        *self = (*self).mul(other);
4501    }
4502}
4503
4504impl Signum for Translator {
4505    type Output = Translator;
4506
4507    fn signum(self) -> Translator {
4508        self.geometric_product(1.0 / self.magnitude())
4509    }
4510}
4511
4512impl Inverse for Translator {
4513    type Output = Translator;
4514
4515    fn inverse(self) -> Translator {
4516        self.reversal().geometric_product(1.0 / self.squared_magnitude())
4517    }
4518}
4519
4520impl Zero for Motor {
4521    fn zero() -> Self {
4522        Motor { groups: MotorGroups { g0: Simd32x4::from(0.0) } }
4523    }
4524}
4525
4526impl One for Motor {
4527    fn one() -> Self {
4528        Motor { groups: MotorGroups { g0: Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
4529    }
4530}
4531
4532impl Neg for Motor {
4533    type Output = Motor;
4534
4535    fn neg(self) -> Motor {
4536        Motor { groups: MotorGroups { g0: self.group0() * Simd32x4::from(-1.0) } }
4537    }
4538}
4539
4540impl Automorphism for Motor {
4541    type Output = Motor;
4542
4543    fn automorphism(self) -> Motor {
4544        Motor { groups: MotorGroups { g0: self.group0() } }
4545    }
4546}
4547
4548impl Reversal for Motor {
4549    type Output = Motor;
4550
4551    fn reversal(self) -> Motor {
4552        Motor { groups: MotorGroups { g0: self.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) } }
4553    }
4554}
4555
4556impl Conjugation for Motor {
4557    type Output = Motor;
4558
4559    fn conjugation(self) -> Motor {
4560        Motor { groups: MotorGroups { g0: self.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) } }
4561    }
4562}
4563
4564impl Dual for Motor {
4565    type Output = MotorDual;
4566
4567    fn dual(self) -> MotorDual {
4568        MotorDual { groups: MotorDualGroups { g0: self.group0() } }
4569    }
4570}
4571
4572impl Into<f32> for Motor {
4573    fn into(self) -> f32 {
4574        self.group0()[0]
4575    }
4576}
4577
4578impl Add<f32> for Motor {
4579    type Output = Motor;
4580
4581    fn add(self, other: f32) -> Motor {
4582        Motor { groups: MotorGroups { g0: self.group0() + Simd32x4::from(other) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
4583    }
4584}
4585
4586impl AddAssign<f32> for Motor {
4587    fn add_assign(&mut self, other: f32) {
4588        *self = (*self).add(other);
4589    }
4590}
4591
4592impl Sub<f32> for Motor {
4593    type Output = Motor;
4594
4595    fn sub(self, other: f32) -> Motor {
4596        Motor { groups: MotorGroups { g0: self.group0() - Simd32x4::from(other) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
4597    }
4598}
4599
4600impl SubAssign<f32> for Motor {
4601    fn sub_assign(&mut self, other: f32) {
4602        *self = (*self).sub(other);
4603    }
4604}
4605
4606impl GeometricProduct<f32> for Motor {
4607    type Output = Motor;
4608
4609    fn geometric_product(self, other: f32) -> Motor {
4610        Motor { groups: MotorGroups { g0: self.group0() * Simd32x4::from(other) } }
4611    }
4612}
4613
4614impl OuterProduct<f32> for Motor {
4615    type Output = Motor;
4616
4617    fn outer_product(self, other: f32) -> Motor {
4618        Motor { groups: MotorGroups { g0: self.group0() * Simd32x4::from(other) } }
4619    }
4620}
4621
4622impl InnerProduct<f32> for Motor {
4623    type Output = Motor;
4624
4625    fn inner_product(self, other: f32) -> Motor {
4626        Motor { groups: MotorGroups { g0: self.group0() * Simd32x4::from(other) } }
4627    }
4628}
4629
4630impl LeftContraction<f32> for Motor {
4631    type Output = f32;
4632
4633    fn left_contraction(self, other: f32) -> f32 {
4634        self.group0()[0] * other
4635    }
4636}
4637
4638impl RightContraction<f32> for Motor {
4639    type Output = Motor;
4640
4641    fn right_contraction(self, other: f32) -> Motor {
4642        Motor { groups: MotorGroups { g0: self.group0() * Simd32x4::from(other) } }
4643    }
4644}
4645
4646impl ScalarProduct<f32> for Motor {
4647    type Output = f32;
4648
4649    fn scalar_product(self, other: f32) -> f32 {
4650        self.group0()[0] * other
4651    }
4652}
4653
4654impl Add<MultiVector> for Motor {
4655    type Output = MultiVector;
4656
4657    fn add(self, other: MultiVector) -> MultiVector {
4658        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() } }
4659    }
4660}
4661
4662impl Sub<MultiVector> for Motor {
4663    type Output = MultiVector;
4664
4665    fn sub(self, other: MultiVector) -> MultiVector {
4666        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() } }
4667    }
4668}
4669
4670impl GeometricProduct<MultiVector> for Motor {
4671    type Output = MultiVector;
4672
4673    fn geometric_product(self, other: MultiVector) -> MultiVector {
4674        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]) + 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]) } }
4675    }
4676}
4677
4678impl OuterProduct<MultiVector> for Motor {
4679    type Output = MultiVector;
4680
4681    fn outer_product(self, other: MultiVector) -> MultiVector {
4682        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]) } }
4683    }
4684}
4685
4686impl InnerProduct<MultiVector> for Motor {
4687    type Output = MultiVector;
4688
4689    fn inner_product(self, other: MultiVector) -> MultiVector {
4690        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()[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]) } }
4691    }
4692}
4693
4694impl LeftContraction<MultiVector> for Motor {
4695    type Output = MultiVector;
4696
4697    fn left_contraction(self, other: MultiVector) -> MultiVector {
4698        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + 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]) } }
4699    }
4700}
4701
4702impl ScalarProduct<MultiVector> for Motor {
4703    type Output = f32;
4704
4705    fn scalar_product(self, other: MultiVector) -> f32 {
4706        self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group0()[1]
4707    }
4708}
4709
4710impl Into<Rotor> for Motor {
4711    fn into(self) -> Rotor {
4712        Rotor { groups: RotorGroups { g0: Simd32x2::from([self.group0()[0], self.group0()[1]]) } }
4713    }
4714}
4715
4716impl Add<Rotor> for Motor {
4717    type Output = Motor;
4718
4719    fn add(self, other: Rotor) -> Motor {
4720        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]) } }
4721    }
4722}
4723
4724impl AddAssign<Rotor> for Motor {
4725    fn add_assign(&mut self, other: Rotor) {
4726        *self = (*self).add(other);
4727    }
4728}
4729
4730impl Sub<Rotor> for Motor {
4731    type Output = Motor;
4732
4733    fn sub(self, other: Rotor) -> Motor {
4734        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]) } }
4735    }
4736}
4737
4738impl SubAssign<Rotor> for Motor {
4739    fn sub_assign(&mut self, other: Rotor) {
4740        *self = (*self).sub(other);
4741    }
4742}
4743
4744impl GeometricProduct<Rotor> for Motor {
4745    type Output = Motor;
4746
4747    fn geometric_product(self, other: Rotor) -> Motor {
4748        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]) } }
4749    }
4750}
4751
4752impl OuterProduct<Rotor> for Motor {
4753    type Output = Motor;
4754
4755    fn outer_product(self, other: Rotor) -> Motor {
4756        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]]) } }
4757    }
4758}
4759
4760impl InnerProduct<Rotor> for Motor {
4761    type Output = Motor;
4762
4763    fn inner_product(self, other: Rotor) -> Motor {
4764        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]]) } }
4765    }
4766}
4767
4768impl LeftContraction<Rotor> for Motor {
4769    type Output = Rotor;
4770
4771    fn left_contraction(self, other: Rotor) -> Rotor {
4772        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]) } }
4773    }
4774}
4775
4776impl RightContraction<Rotor> for Motor {
4777    type Output = Motor;
4778
4779    fn right_contraction(self, other: Rotor) -> Motor {
4780        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]) } }
4781    }
4782}
4783
4784impl ScalarProduct<Rotor> for Motor {
4785    type Output = f32;
4786
4787    fn scalar_product(self, other: Rotor) -> f32 {
4788        self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group0()[1]
4789    }
4790}
4791
4792impl Into<Point> for Motor {
4793    fn into(self) -> Point {
4794        Point { groups: PointGroups { g0: Simd32x3::from([self.group0()[1], self.group0()[2], self.group0()[3]]) } }
4795    }
4796}
4797
4798impl Add<Point> for Motor {
4799    type Output = Motor;
4800
4801    fn add(self, other: Point) -> Motor {
4802        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]) } }
4803    }
4804}
4805
4806impl AddAssign<Point> for Motor {
4807    fn add_assign(&mut self, other: Point) {
4808        *self = (*self).add(other);
4809    }
4810}
4811
4812impl Sub<Point> for Motor {
4813    type Output = Motor;
4814
4815    fn sub(self, other: Point) -> Motor {
4816        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]) } }
4817    }
4818}
4819
4820impl SubAssign<Point> for Motor {
4821    fn sub_assign(&mut self, other: Point) {
4822        *self = (*self).sub(other);
4823    }
4824}
4825
4826impl GeometricProduct<Point> for Motor {
4827    type Output = Motor;
4828
4829    fn geometric_product(self, other: Point) -> Motor {
4830        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()[0]) * Simd32x4::from([0.0, 0.0, 0.0, -1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.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]) } }
4831    }
4832}
4833
4834impl RegressiveProduct<Point> for Motor {
4835    type Output = Plane;
4836
4837    fn regressive_product(self, other: Point) -> Plane {
4838        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]) } }
4839    }
4840}
4841
4842impl OuterProduct<Point> for Motor {
4843    type Output = Point;
4844
4845    fn outer_product(self, other: Point) -> Point {
4846        Point { groups: PointGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() } }
4847    }
4848}
4849
4850impl InnerProduct<Point> for Motor {
4851    type Output = Motor;
4852
4853    fn inner_product(self, other: Point) -> Motor {
4854        Motor { groups: MotorGroups { g0: 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]) } }
4855    }
4856}
4857
4858impl LeftContraction<Point> for Motor {
4859    type Output = Motor;
4860
4861    fn left_contraction(self, other: Point) -> Motor {
4862        Motor { groups: MotorGroups { g0: 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]) } }
4863    }
4864}
4865
4866impl RightContraction<Point> for Motor {
4867    type Output = f32;
4868
4869    fn right_contraction(self, other: Point) -> f32 {
4870        0.0 - self.group0()[1] * other.group0()[0]
4871    }
4872}
4873
4874impl ScalarProduct<Point> for Motor {
4875    type Output = f32;
4876
4877    fn scalar_product(self, other: Point) -> f32 {
4878        0.0 - self.group0()[1] * other.group0()[0]
4879    }
4880}
4881
4882impl Into<IdealPoint> for Motor {
4883    fn into(self) -> IdealPoint {
4884        IdealPoint { groups: IdealPointGroups { g0: Simd32x2::from([self.group0()[2], self.group0()[3]]) } }
4885    }
4886}
4887
4888impl Add<IdealPoint> for Motor {
4889    type Output = Motor;
4890
4891    fn add(self, other: IdealPoint) -> Motor {
4892        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]) } }
4893    }
4894}
4895
4896impl AddAssign<IdealPoint> for Motor {
4897    fn add_assign(&mut self, other: IdealPoint) {
4898        *self = (*self).add(other);
4899    }
4900}
4901
4902impl Sub<IdealPoint> for Motor {
4903    type Output = Motor;
4904
4905    fn sub(self, other: IdealPoint) -> Motor {
4906        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]) } }
4907    }
4908}
4909
4910impl SubAssign<IdealPoint> for Motor {
4911    fn sub_assign(&mut self, other: IdealPoint) {
4912        *self = (*self).sub(other);
4913    }
4914}
4915
4916impl GeometricProduct<IdealPoint> for Motor {
4917    type Output = IdealPoint;
4918
4919    fn geometric_product(self, other: IdealPoint) -> IdealPoint {
4920        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]) } }
4921    }
4922}
4923
4924impl RegressiveProduct<IdealPoint> for Motor {
4925    type Output = Plane;
4926
4927    fn regressive_product(self, other: IdealPoint) -> Plane {
4928        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]) } }
4929    }
4930}
4931
4932impl OuterProduct<IdealPoint> for Motor {
4933    type Output = IdealPoint;
4934
4935    fn outer_product(self, other: IdealPoint) -> IdealPoint {
4936        IdealPoint { groups: IdealPointGroups { g0: Simd32x2::from(self.group0()[0]) * other.group0() } }
4937    }
4938}
4939
4940impl InnerProduct<IdealPoint> for Motor {
4941    type Output = IdealPoint;
4942
4943    fn inner_product(self, other: IdealPoint) -> IdealPoint {
4944        IdealPoint { groups: IdealPointGroups { g0: Simd32x2::from(self.group0()[0]) * other.group0() } }
4945    }
4946}
4947
4948impl LeftContraction<IdealPoint> for Motor {
4949    type Output = IdealPoint;
4950
4951    fn left_contraction(self, other: IdealPoint) -> IdealPoint {
4952        IdealPoint { groups: IdealPointGroups { g0: Simd32x2::from(self.group0()[0]) * other.group0() } }
4953    }
4954}
4955
4956impl GeometricProduct<Plane> for Motor {
4957    type Output = MotorDual;
4958
4959    fn geometric_product(self, other: Plane) -> MotorDual {
4960        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()[1]]) * Simd32x4::from([1.0, 1.0, 0.0, 0.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.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]) } }
4961    }
4962}
4963
4964impl RegressiveProduct<Plane> for Motor {
4965    type Output = f32;
4966
4967    fn regressive_product(self, other: Plane) -> f32 {
4968        self.group0()[1] * other.group0()[0] + self.group0()[2] * other.group0()[1] + self.group0()[3] * other.group0()[2]
4969    }
4970}
4971
4972impl OuterProduct<Plane> for Motor {
4973    type Output = MotorDual;
4974
4975    fn outer_product(self, other: Plane) -> MotorDual {
4976        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]]) } }
4977    }
4978}
4979
4980impl InnerProduct<Plane> for Motor {
4981    type Output = Plane;
4982
4983    fn inner_product(self, other: Plane) -> Plane {
4984        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() + 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]) } }
4985    }
4986}
4987
4988impl LeftContraction<Plane> for Motor {
4989    type Output = Plane;
4990
4991    fn left_contraction(self, other: Plane) -> Plane {
4992        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() } }
4993    }
4994}
4995
4996impl RightContraction<Plane> for Motor {
4997    type Output = Plane;
4998
4999    fn right_contraction(self, other: Plane) -> Plane {
5000        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]) } }
5001    }
5002}
5003
5004impl Into<Translator> for Motor {
5005    fn into(self) -> Translator {
5006        Translator { groups: TranslatorGroups { g0: Simd32x3::from([self.group0()[0], self.group0()[2], self.group0()[3]]) } }
5007    }
5008}
5009
5010impl Add<Translator> for Motor {
5011    type Output = Motor;
5012
5013    fn add(self, other: Translator) -> Motor {
5014        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]) } }
5015    }
5016}
5017
5018impl AddAssign<Translator> for Motor {
5019    fn add_assign(&mut self, other: Translator) {
5020        *self = (*self).add(other);
5021    }
5022}
5023
5024impl Sub<Translator> for Motor {
5025    type Output = Motor;
5026
5027    fn sub(self, other: Translator) -> Motor {
5028        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]) } }
5029    }
5030}
5031
5032impl SubAssign<Translator> for Motor {
5033    fn sub_assign(&mut self, other: Translator) {
5034        *self = (*self).sub(other);
5035    }
5036}
5037
5038impl GeometricProduct<Translator> for Motor {
5039    type Output = Motor;
5040
5041    fn geometric_product(self, other: Translator) -> Motor {
5042        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()[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]) + 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]) } }
5043    }
5044}
5045
5046impl RegressiveProduct<Translator> for Motor {
5047    type Output = Plane;
5048
5049    fn regressive_product(self, other: Translator) -> Plane {
5050        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]) } }
5051    }
5052}
5053
5054impl OuterProduct<Translator> for Motor {
5055    type Output = Motor;
5056
5057    fn outer_product(self, other: Translator) -> Motor {
5058        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]]) } }
5059    }
5060}
5061
5062impl InnerProduct<Translator> for Motor {
5063    type Output = Motor;
5064
5065    fn inner_product(self, other: Translator) -> Motor {
5066        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]]) } }
5067    }
5068}
5069
5070impl LeftContraction<Translator> for Motor {
5071    type Output = Translator;
5072
5073    fn left_contraction(self, other: Translator) -> Translator {
5074        Translator { groups: TranslatorGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() } }
5075    }
5076}
5077
5078impl RightContraction<Translator> for Motor {
5079    type Output = Motor;
5080
5081    fn right_contraction(self, other: Translator) -> Motor {
5082        Motor { groups: MotorGroups { g0: self.group0() * Simd32x4::from(other.group0()[0]) } }
5083    }
5084}
5085
5086impl ScalarProduct<Translator> for Motor {
5087    type Output = f32;
5088
5089    fn scalar_product(self, other: Translator) -> f32 {
5090        self.group0()[0] * other.group0()[0]
5091    }
5092}
5093
5094impl Add<Motor> for Motor {
5095    type Output = Motor;
5096
5097    fn add(self, other: Motor) -> Motor {
5098        Motor { groups: MotorGroups { g0: self.group0() + other.group0() } }
5099    }
5100}
5101
5102impl AddAssign<Motor> for Motor {
5103    fn add_assign(&mut self, other: Motor) {
5104        *self = (*self).add(other);
5105    }
5106}
5107
5108impl Sub<Motor> for Motor {
5109    type Output = Motor;
5110
5111    fn sub(self, other: Motor) -> Motor {
5112        Motor { groups: MotorGroups { g0: self.group0() - other.group0() } }
5113    }
5114}
5115
5116impl SubAssign<Motor> for Motor {
5117    fn sub_assign(&mut self, other: Motor) {
5118        *self = (*self).sub(other);
5119    }
5120}
5121
5122impl Mul<Motor> for Motor {
5123    type Output = Motor;
5124
5125    fn mul(self, other: Motor) -> Motor {
5126        Motor { groups: MotorGroups { g0: self.group0() * other.group0() } }
5127    }
5128}
5129
5130impl MulAssign<Motor> for Motor {
5131    fn mul_assign(&mut self, other: Motor) {
5132        *self = (*self).mul(other);
5133    }
5134}
5135
5136impl Div<Motor> for Motor {
5137    type Output = Motor;
5138
5139    fn div(self, other: Motor) -> Motor {
5140        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]) } }
5141    }
5142}
5143
5144impl DivAssign<Motor> for Motor {
5145    fn div_assign(&mut self, other: Motor) {
5146        *self = (*self).div(other);
5147    }
5148}
5149
5150impl GeometricProduct<Motor> for Motor {
5151    type Output = Motor;
5152
5153    fn geometric_product(self, other: Motor) -> Motor {
5154        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()[3]) * swizzle!(other.group0(), 1, 1, 1, 0) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) + swizzle!(self.group0(), 0, 0, 2, 2) * swizzle!(other.group0(), 0, 0, 0, 1) * Simd32x4::from([0.0, 0.0, 1.0, -1.0]) } }
5155    }
5156}
5157
5158impl RegressiveProduct<Motor> for Motor {
5159    type Output = Plane;
5160
5161    fn regressive_product(self, other: Motor) -> Plane {
5162        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]) } }
5163    }
5164}
5165
5166impl OuterProduct<Motor> for Motor {
5167    type Output = Motor;
5168
5169    fn outer_product(self, other: Motor) -> Motor {
5170        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]) } }
5171    }
5172}
5173
5174impl InnerProduct<Motor> for Motor {
5175    type Output = Motor;
5176
5177    fn inner_product(self, other: Motor) -> Motor {
5178        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + swizzle!(self.group0(), 1, 1, 2, 3) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) } }
5179    }
5180}
5181
5182impl LeftContraction<Motor> for Motor {
5183    type Output = Motor;
5184
5185    fn left_contraction(self, other: Motor) -> Motor {
5186        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + swizzle!(self.group0(), 1, 0, 0, 0) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) } }
5187    }
5188}
5189
5190impl RightContraction<Motor> for Motor {
5191    type Output = Motor;
5192
5193    fn right_contraction(self, other: Motor) -> Motor {
5194        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]) + swizzle!(self.group0(), 0, 0, 2, 3) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 1.0, 1.0]) } }
5195    }
5196}
5197
5198impl ScalarProduct<Motor> for Motor {
5199    type Output = f32;
5200
5201    fn scalar_product(self, other: Motor) -> f32 {
5202        self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group0()[1]
5203    }
5204}
5205
5206impl Add<MotorDual> for Motor {
5207    type Output = MultiVector;
5208
5209    fn add(self, other: MotorDual) -> MultiVector {
5210        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]) } }
5211    }
5212}
5213
5214impl Sub<MotorDual> for Motor {
5215    type Output = MultiVector;
5216
5217    fn sub(self, other: MotorDual) -> MultiVector {
5218        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]) } }
5219    }
5220}
5221
5222impl GeometricProduct<MotorDual> for Motor {
5223    type Output = MotorDual;
5224
5225    fn geometric_product(self, other: MotorDual) -> MotorDual {
5226        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()[3]) * swizzle!(other.group0(), 3, 2, 3, 3) * Simd32x4::from([1.0, -1.0, 0.0, 0.0]) + swizzle!(self.group0(), 2, 2, 0, 0) * swizzle!(other.group0(), 2, 3, 0, 0) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) } }
5227    }
5228}
5229
5230impl RegressiveProduct<MotorDual> for Motor {
5231    type Output = Motor;
5232
5233    fn regressive_product(self, other: MotorDual) -> Motor {
5234        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]) } }
5235    }
5236}
5237
5238impl OuterProduct<MotorDual> for Motor {
5239    type Output = MotorDual;
5240
5241    fn outer_product(self, other: MotorDual) -> MotorDual {
5242        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]) } }
5243    }
5244}
5245
5246impl InnerProduct<MotorDual> for Motor {
5247    type Output = MotorDual;
5248
5249    fn inner_product(self, other: MotorDual) -> MotorDual {
5250        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group0()[3]) * Simd32x4::from([0.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group0()[2]) * Simd32x4::from([0.0, -1.0, 0.0, 0.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]) } }
5251    }
5252}
5253
5254impl LeftContraction<MotorDual> for Motor {
5255    type Output = MotorDual;
5256
5257    fn left_contraction(self, other: MotorDual) -> MotorDual {
5258        MotorDual { groups: MotorDualGroups { 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]) } }
5259    }
5260}
5261
5262impl RightContraction<MotorDual> for Motor {
5263    type Output = Plane;
5264
5265    fn right_contraction(self, other: MotorDual) -> Plane {
5266        Plane { groups: PlaneGroups { g0: 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()[1], self.group0()[1]]) * Simd32x3::from([other.group0()[3], other.group0()[3], other.group0()[2]]) * Simd32x3::from([1.0, -1.0, 1.0]) } }
5267    }
5268}
5269
5270impl SquaredMagnitude for Motor {
5271    type Output = f32;
5272
5273    fn squared_magnitude(self) -> f32 {
5274        self.scalar_product(self.reversal())
5275    }
5276}
5277
5278impl Magnitude for Motor {
5279    type Output = f32;
5280
5281    fn magnitude(self) -> f32 {
5282        self.squared_magnitude().sqrt()
5283    }
5284}
5285
5286impl Mul<f32> for Motor {
5287    type Output = Motor;
5288
5289    fn mul(self, other: f32) -> Motor {
5290        self.geometric_product(other)
5291    }
5292}
5293
5294impl MulAssign<f32> for Motor {
5295    fn mul_assign(&mut self, other: f32) {
5296        *self = (*self).mul(other);
5297    }
5298}
5299
5300impl Signum for Motor {
5301    type Output = Motor;
5302
5303    fn signum(self) -> Motor {
5304        self.geometric_product(1.0 / self.magnitude())
5305    }
5306}
5307
5308impl Inverse for Motor {
5309    type Output = Motor;
5310
5311    fn inverse(self) -> Motor {
5312        self.reversal().geometric_product(1.0 / self.squared_magnitude())
5313    }
5314}
5315
5316impl Zero for MotorDual {
5317    fn zero() -> Self {
5318        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(0.0) } }
5319    }
5320}
5321
5322impl One for MotorDual {
5323    fn one() -> Self {
5324        MotorDual { groups: MotorDualGroups { g0: Simd32x4::from(0.0) } }
5325    }
5326}
5327
5328impl Neg for MotorDual {
5329    type Output = MotorDual;
5330
5331    fn neg(self) -> MotorDual {
5332        MotorDual { groups: MotorDualGroups { g0: self.group0() * Simd32x4::from(-1.0) } }
5333    }
5334}
5335
5336impl Automorphism for MotorDual {
5337    type Output = MotorDual;
5338
5339    fn automorphism(self) -> MotorDual {
5340        MotorDual { groups: MotorDualGroups { g0: self.group0() * Simd32x4::from(-1.0) } }
5341    }
5342}
5343
5344impl Reversal for MotorDual {
5345    type Output = MotorDual;
5346
5347    fn reversal(self) -> MotorDual {
5348        MotorDual { groups: MotorDualGroups { g0: self.group0() * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) } }
5349    }
5350}
5351
5352impl Conjugation for MotorDual {
5353    type Output = MotorDual;
5354
5355    fn conjugation(self) -> MotorDual {
5356        MotorDual { groups: MotorDualGroups { g0: self.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) } }
5357    }
5358}
5359
5360impl Dual for MotorDual {
5361    type Output = Motor;
5362
5363    fn dual(self) -> Motor {
5364        Motor { groups: MotorGroups { g0: self.group0() } }
5365    }
5366}
5367
5368impl GeometricProduct<f32> for MotorDual {
5369    type Output = MotorDual;
5370
5371    fn geometric_product(self, other: f32) -> MotorDual {
5372        MotorDual { groups: MotorDualGroups { g0: self.group0() * Simd32x4::from(other) } }
5373    }
5374}
5375
5376impl RegressiveProduct<f32> for MotorDual {
5377    type Output = f32;
5378
5379    fn regressive_product(self, other: f32) -> f32 {
5380        self.group0()[0] * other
5381    }
5382}
5383
5384impl OuterProduct<f32> for MotorDual {
5385    type Output = MotorDual;
5386
5387    fn outer_product(self, other: f32) -> MotorDual {
5388        MotorDual { groups: MotorDualGroups { g0: self.group0() * Simd32x4::from(other) } }
5389    }
5390}
5391
5392impl InnerProduct<f32> for MotorDual {
5393    type Output = MotorDual;
5394
5395    fn inner_product(self, other: f32) -> MotorDual {
5396        MotorDual { groups: MotorDualGroups { g0: self.group0() * Simd32x4::from(other) } }
5397    }
5398}
5399
5400impl RightContraction<f32> for MotorDual {
5401    type Output = MotorDual;
5402
5403    fn right_contraction(self, other: f32) -> MotorDual {
5404        MotorDual { groups: MotorDualGroups { g0: self.group0() * Simd32x4::from(other) } }
5405    }
5406}
5407
5408impl Add<MultiVector> for MotorDual {
5409    type Output = MultiVector;
5410
5411    fn add(self, other: MultiVector) -> MultiVector {
5412        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() } }
5413    }
5414}
5415
5416impl Sub<MultiVector> for MotorDual {
5417    type Output = MultiVector;
5418
5419    fn sub(self, other: MultiVector) -> MultiVector {
5420        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() } }
5421    }
5422}
5423
5424impl GeometricProduct<MultiVector> for MotorDual {
5425    type Output = MultiVector;
5426
5427    fn geometric_product(self, other: MultiVector) -> MultiVector {
5428        MultiVector { groups: MultiVectorGroups { g0: 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]) } }
5429    }
5430}
5431
5432impl RegressiveProduct<MultiVector> for MotorDual {
5433    type Output = MultiVector;
5434
5435    fn regressive_product(self, other: MultiVector) -> MultiVector {
5436        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]) } }
5437    }
5438}
5439
5440impl ScalarProduct<MultiVector> for MotorDual {
5441    type Output = f32;
5442
5443    fn scalar_product(self, other: MultiVector) -> f32 {
5444        self.group0()[2] * other.group0()[3] + self.group0()[3] * other.group0()[2]
5445    }
5446}
5447
5448impl GeometricProduct<Rotor> for MotorDual {
5449    type Output = MotorDual;
5450
5451    fn geometric_product(self, other: Rotor) -> MotorDual {
5452        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]) } }
5453    }
5454}
5455
5456impl RegressiveProduct<Rotor> for MotorDual {
5457    type Output = Rotor;
5458
5459    fn regressive_product(self, other: Rotor) -> Rotor {
5460        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]) } }
5461    }
5462}
5463
5464impl OuterProduct<Rotor> for MotorDual {
5465    type Output = MotorDual;
5466
5467    fn outer_product(self, other: Rotor) -> MotorDual {
5468        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]) } }
5469    }
5470}
5471
5472impl InnerProduct<Rotor> for MotorDual {
5473    type Output = MotorDual;
5474
5475    fn inner_product(self, other: Rotor) -> MotorDual {
5476        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]) } }
5477    }
5478}
5479
5480impl RightContraction<Rotor> for MotorDual {
5481    type Output = MotorDual;
5482
5483    fn right_contraction(self, other: Rotor) -> MotorDual {
5484        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]) } }
5485    }
5486}
5487
5488impl GeometricProduct<Point> for MotorDual {
5489    type Output = MotorDual;
5490
5491    fn geometric_product(self, other: Point) -> MotorDual {
5492        MotorDual { groups: MotorDualGroups { g0: 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]) + swizzle!(self.group0(), 1, 0, 0, 0) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, -1.0, 0.0, 0.0]) } }
5493    }
5494}
5495
5496impl RegressiveProduct<Point> for MotorDual {
5497    type Output = Motor;
5498
5499    fn regressive_product(self, other: Point) -> Motor {
5500        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]]) } }
5501    }
5502}
5503
5504impl InnerProduct<Point> for MotorDual {
5505    type Output = Plane;
5506
5507    fn inner_product(self, other: Point) -> Plane {
5508        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]) * Simd32x3::from(other.group0()[0]) * Simd32x3::from([-1.0, 0.0, 0.0]) } }
5509    }
5510}
5511
5512impl LeftContraction<Point> for MotorDual {
5513    type Output = Plane;
5514
5515    fn left_contraction(self, other: Point) -> Plane {
5516        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[3]) * swizzle!(other.group0(), 1, 0, 1) * Simd32x3::from([-1.0, 1.0, 0.0]) + Simd32x3::from([self.group0()[2], self.group0()[0], self.group0()[2]]) * swizzle!(other.group0(), 2, 0, 0) * Simd32x3::from([1.0, 0.0, -1.0]) } }
5517    }
5518}
5519
5520impl RegressiveProduct<IdealPoint> for MotorDual {
5521    type Output = Translator;
5522
5523    fn regressive_product(self, other: IdealPoint) -> Translator {
5524        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]]) } }
5525    }
5526}
5527
5528impl Into<Plane> for MotorDual {
5529    fn into(self) -> Plane {
5530        Plane { groups: PlaneGroups { g0: Simd32x3::from([self.group0()[1], self.group0()[2], self.group0()[3]]) } }
5531    }
5532}
5533
5534impl Add<Plane> for MotorDual {
5535    type Output = MotorDual;
5536
5537    fn add(self, other: Plane) -> MotorDual {
5538        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]) } }
5539    }
5540}
5541
5542impl AddAssign<Plane> for MotorDual {
5543    fn add_assign(&mut self, other: Plane) {
5544        *self = (*self).add(other);
5545    }
5546}
5547
5548impl Sub<Plane> for MotorDual {
5549    type Output = MotorDual;
5550
5551    fn sub(self, other: Plane) -> MotorDual {
5552        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]) } }
5553    }
5554}
5555
5556impl SubAssign<Plane> for MotorDual {
5557    fn sub_assign(&mut self, other: Plane) {
5558        *self = (*self).sub(other);
5559    }
5560}
5561
5562impl GeometricProduct<Plane> for MotorDual {
5563    type Output = Motor;
5564
5565    fn geometric_product(self, other: Plane) -> Motor {
5566        Motor { groups: MotorGroups { g0: 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()[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, 0.0, 1.0, 1.0]) } }
5567    }
5568}
5569
5570impl RegressiveProduct<Plane> for MotorDual {
5571    type Output = Plane;
5572
5573    fn regressive_product(self, other: Plane) -> Plane {
5574        Plane { groups: PlaneGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() } }
5575    }
5576}
5577
5578impl OuterProduct<Plane> for MotorDual {
5579    type Output = Point;
5580
5581    fn outer_product(self, other: Plane) -> Point {
5582        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]) } }
5583    }
5584}
5585
5586impl InnerProduct<Plane> for MotorDual {
5587    type Output = Translator;
5588
5589    fn inner_product(self, other: Plane) -> Translator {
5590        Translator { groups: TranslatorGroups { g0: 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, 1, 2) } }
5591    }
5592}
5593
5594impl LeftContraction<Plane> for MotorDual {
5595    type Output = f32;
5596
5597    fn left_contraction(self, other: Plane) -> f32 {
5598        self.group0()[2] * other.group0()[1] + self.group0()[3] * other.group0()[2]
5599    }
5600}
5601
5602impl RightContraction<Plane> for MotorDual {
5603    type Output = Translator;
5604
5605    fn right_contraction(self, other: Plane) -> Translator {
5606        Translator { groups: TranslatorGroups { g0: 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, 1, 2) } }
5607    }
5608}
5609
5610impl ScalarProduct<Plane> for MotorDual {
5611    type Output = f32;
5612
5613    fn scalar_product(self, other: Plane) -> f32 {
5614        self.group0()[2] * other.group0()[1] + self.group0()[3] * other.group0()[2]
5615    }
5616}
5617
5618impl GeometricProduct<Translator> for MotorDual {
5619    type Output = MotorDual;
5620
5621    fn geometric_product(self, other: Translator) -> MotorDual {
5622        MotorDual { groups: MotorDualGroups { g0: 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]) + swizzle!(self.group0(), 0, 1, 0, 0) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) } }
5623    }
5624}
5625
5626impl RegressiveProduct<Translator> for MotorDual {
5627    type Output = Translator;
5628
5629    fn regressive_product(self, other: Translator) -> Translator {
5630        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]) } }
5631    }
5632}
5633
5634impl OuterProduct<Translator> for MotorDual {
5635    type Output = MotorDual;
5636
5637    fn outer_product(self, other: Translator) -> MotorDual {
5638        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]) } }
5639    }
5640}
5641
5642impl InnerProduct<Translator> for MotorDual {
5643    type Output = MotorDual;
5644
5645    fn inner_product(self, other: Translator) -> MotorDual {
5646        MotorDual { groups: MotorDualGroups { g0: 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]) + swizzle!(self.group0(), 0, 1, 0, 0) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) } }
5647    }
5648}
5649
5650impl RightContraction<Translator> for MotorDual {
5651    type Output = MotorDual;
5652
5653    fn right_contraction(self, other: Translator) -> MotorDual {
5654        MotorDual { groups: MotorDualGroups { g0: self.group0() * Simd32x4::from(other.group0()[0]) } }
5655    }
5656}
5657
5658impl Add<Motor> for MotorDual {
5659    type Output = MultiVector;
5660
5661    fn add(self, other: Motor) -> MultiVector {
5662        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]) } }
5663    }
5664}
5665
5666impl Sub<Motor> for MotorDual {
5667    type Output = MultiVector;
5668
5669    fn sub(self, other: Motor) -> MultiVector {
5670        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]) } }
5671    }
5672}
5673
5674impl GeometricProduct<Motor> for MotorDual {
5675    type Output = MotorDual;
5676
5677    fn geometric_product(self, other: Motor) -> MotorDual {
5678        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, 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]) + Simd32x4::from(self.group0()[0]) * swizzle!(other.group0(), 0, 1, 0, 0) * Simd32x4::from([1.0, -1.0, 0.0, 0.0]) } }
5679    }
5680}
5681
5682impl RegressiveProduct<Motor> for MotorDual {
5683    type Output = Motor;
5684
5685    fn regressive_product(self, other: Motor) -> Motor {
5686        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]) } }
5687    }
5688}
5689
5690impl OuterProduct<Motor> for MotorDual {
5691    type Output = MotorDual;
5692
5693    fn outer_product(self, other: Motor) -> MotorDual {
5694        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]) } }
5695    }
5696}
5697
5698impl InnerProduct<Motor> for MotorDual {
5699    type Output = MotorDual;
5700
5701    fn inner_product(self, other: Motor) -> MotorDual {
5702        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()[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]) + Simd32x4::from(self.group0()[0]) * swizzle!(other.group0(), 0, 1, 0, 0) * Simd32x4::from([1.0, -1.0, 0.0, 0.0]) } }
5703    }
5704}
5705
5706impl LeftContraction<Motor> for MotorDual {
5707    type Output = Plane;
5708
5709    fn left_contraction(self, other: Motor) -> Plane {
5710        Plane { groups: PlaneGroups { g0: 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()[2], self.group0()[0], self.group0()[2]]) * Simd32x3::from([other.group0()[3], other.group0()[0], other.group0()[1]]) * Simd32x3::from([1.0, 0.0, -1.0]) } }
5711    }
5712}
5713
5714impl RightContraction<Motor> for MotorDual {
5715    type Output = MotorDual;
5716
5717    fn right_contraction(self, other: Motor) -> MotorDual {
5718        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) * swizzle!(other.group0(), 0, 1, 0, 0) * Simd32x4::from([1.0, -1.0, 1.0, 1.0]) } }
5719    }
5720}
5721
5722impl Add<MotorDual> for MotorDual {
5723    type Output = MotorDual;
5724
5725    fn add(self, other: MotorDual) -> MotorDual {
5726        MotorDual { groups: MotorDualGroups { g0: self.group0() + other.group0() } }
5727    }
5728}
5729
5730impl AddAssign<MotorDual> for MotorDual {
5731    fn add_assign(&mut self, other: MotorDual) {
5732        *self = (*self).add(other);
5733    }
5734}
5735
5736impl Sub<MotorDual> for MotorDual {
5737    type Output = MotorDual;
5738
5739    fn sub(self, other: MotorDual) -> MotorDual {
5740        MotorDual { groups: MotorDualGroups { g0: self.group0() - other.group0() } }
5741    }
5742}
5743
5744impl SubAssign<MotorDual> for MotorDual {
5745    fn sub_assign(&mut self, other: MotorDual) {
5746        *self = (*self).sub(other);
5747    }
5748}
5749
5750impl Mul<MotorDual> for MotorDual {
5751    type Output = MotorDual;
5752
5753    fn mul(self, other: MotorDual) -> MotorDual {
5754        MotorDual { groups: MotorDualGroups { g0: self.group0() * other.group0() } }
5755    }
5756}
5757
5758impl MulAssign<MotorDual> for MotorDual {
5759    fn mul_assign(&mut self, other: MotorDual) {
5760        *self = (*self).mul(other);
5761    }
5762}
5763
5764impl Div<MotorDual> for MotorDual {
5765    type Output = MotorDual;
5766
5767    fn div(self, other: MotorDual) -> MotorDual {
5768        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]) } }
5769    }
5770}
5771
5772impl DivAssign<MotorDual> for MotorDual {
5773    fn div_assign(&mut self, other: MotorDual) {
5774        *self = (*self).div(other);
5775    }
5776}
5777
5778impl GeometricProduct<MotorDual> for MotorDual {
5779    type Output = Motor;
5780
5781    fn geometric_product(self, other: MotorDual) -> Motor {
5782        Motor { groups: MotorGroups { g0: 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()[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]) + Simd32x4::from(self.group0()[0]) * swizzle!(other.group0(), 0, 0, 2, 3) * Simd32x4::from([0.0, 0.0, 1.0, 1.0]) } }
5783    }
5784}
5785
5786impl RegressiveProduct<MotorDual> for MotorDual {
5787    type Output = MotorDual;
5788
5789    fn regressive_product(self, other: MotorDual) -> MotorDual {
5790        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]) } }
5791    }
5792}
5793
5794impl OuterProduct<MotorDual> for MotorDual {
5795    type Output = Point;
5796
5797    fn outer_product(self, other: MotorDual) -> Point {
5798        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]) } }
5799    }
5800}
5801
5802impl InnerProduct<MotorDual> for MotorDual {
5803    type Output = Translator;
5804
5805    fn inner_product(self, other: MotorDual) -> Translator {
5806        Translator { groups: TranslatorGroups { g0: Simd32x3::from(self.group0()[2]) * Simd32x3::from([other.group0()[2], other.group0()[0], other.group0()[2]]) * Simd32x3::from([1.0, 1.0, 0.0]) + Simd32x3::from(self.group0()[3]) * 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], other.group0()[2], other.group0()[3]]) * Simd32x3::from([0.0, 1.0, 1.0]) } }
5807    }
5808}
5809
5810impl LeftContraction<MotorDual> for MotorDual {
5811    type Output = Translator;
5812
5813    fn left_contraction(self, other: MotorDual) -> Translator {
5814        Translator { groups: TranslatorGroups { g0: Simd32x3::from(self.group0()[3]) * Simd32x3::from([other.group0()[3], other.group0()[3], other.group0()[0]]) * Simd32x3::from([1.0, 0.0, 1.0]) + Simd32x3::from([self.group0()[2], self.group0()[2], self.group0()[0]]) * Simd32x3::from([other.group0()[2], other.group0()[0], other.group0()[0]]) * Simd32x3::from([1.0, 1.0, 0.0]) } }
5815    }
5816}
5817
5818impl RightContraction<MotorDual> for MotorDual {
5819    type Output = Translator;
5820
5821    fn right_contraction(self, other: MotorDual) -> Translator {
5822        Translator { groups: TranslatorGroups { g0: Simd32x3::from(self.group0()[3]) * Simd32x3::from(other.group0()[3]) * Simd32x3::from([1.0, 0.0, 0.0]) + Simd32x3::from([self.group0()[2], self.group0()[0], self.group0()[0]]) * Simd32x3::from([other.group0()[2], other.group0()[2], other.group0()[3]]) } }
5823    }
5824}
5825
5826impl ScalarProduct<MotorDual> for MotorDual {
5827    type Output = f32;
5828
5829    fn scalar_product(self, other: MotorDual) -> f32 {
5830        self.group0()[2] * other.group0()[2] + self.group0()[3] * other.group0()[3]
5831    }
5832}
5833
5834impl SquaredMagnitude for MotorDual {
5835    type Output = f32;
5836
5837    fn squared_magnitude(self) -> f32 {
5838        self.scalar_product(self.reversal())
5839    }
5840}
5841
5842impl Magnitude for MotorDual {
5843    type Output = f32;
5844
5845    fn magnitude(self) -> f32 {
5846        self.squared_magnitude().sqrt()
5847    }
5848}
5849
5850impl Mul<f32> for MotorDual {
5851    type Output = MotorDual;
5852
5853    fn mul(self, other: f32) -> MotorDual {
5854        self.geometric_product(other)
5855    }
5856}
5857
5858impl MulAssign<f32> for MotorDual {
5859    fn mul_assign(&mut self, other: f32) {
5860        *self = (*self).mul(other);
5861    }
5862}
5863
5864impl Signum for MotorDual {
5865    type Output = MotorDual;
5866
5867    fn signum(self) -> MotorDual {
5868        self.geometric_product(1.0 / self.magnitude())
5869    }
5870}
5871
5872impl Inverse for MotorDual {
5873    type Output = MotorDual;
5874
5875    fn inverse(self) -> MotorDual {
5876        self.reversal().geometric_product(1.0 / self.squared_magnitude())
5877    }
5878}
5879
5880impl GeometricQuotient<Motor> for IdealPoint {
5881    type Output = IdealPoint;
5882
5883    fn geometric_quotient(self, other: Motor) -> IdealPoint {
5884        self.geometric_product(other.inverse())
5885    }
5886}
5887
5888impl GeometricQuotient<Point> for IdealPoint {
5889    type Output = IdealPoint;
5890
5891    fn geometric_quotient(self, other: Point) -> IdealPoint {
5892        self.geometric_product(other.inverse())
5893    }
5894}
5895
5896impl GeometricQuotient<Rotor> for IdealPoint {
5897    type Output = IdealPoint;
5898
5899    fn geometric_quotient(self, other: Rotor) -> IdealPoint {
5900        self.geometric_product(other.inverse())
5901    }
5902}
5903
5904impl GeometricQuotient<f32> for IdealPoint {
5905    type Output = IdealPoint;
5906
5907    fn geometric_quotient(self, other: f32) -> IdealPoint {
5908        self.geometric_product(other.inverse())
5909    }
5910}
5911
5912impl GeometricQuotient<Translator> for IdealPoint {
5913    type Output = IdealPoint;
5914
5915    fn geometric_quotient(self, other: Translator) -> IdealPoint {
5916        self.geometric_product(other.inverse())
5917    }
5918}
5919
5920impl Transformation<IdealPoint> for Motor {
5921    type Output = IdealPoint;
5922
5923    fn transformation(self, other: IdealPoint) -> IdealPoint {
5924        self.geometric_product(other).geometric_product(self.reversal())
5925    }
5926}
5927
5928impl Powi for Motor {
5929    type Output = Motor;
5930
5931    fn powi(self, exponent: isize) -> Motor {
5932        if exponent == 0 {
5933            return Motor::one();
5934        }
5935        let mut x: Motor = if exponent < 0 { self.inverse() } else { self };
5936        let mut y: Motor = Motor::one();
5937        let mut n: isize = exponent.abs();
5938        while 1 < n {
5939            if n & 1 == 1 {
5940                y = x.geometric_product(y);
5941            }
5942            x = x.geometric_product(x);
5943            n = n >> 1;
5944        }
5945        x.geometric_product(y)
5946    }
5947}
5948
5949impl GeometricQuotient<Motor> for Motor {
5950    type Output = Motor;
5951
5952    fn geometric_quotient(self, other: Motor) -> Motor {
5953        self.geometric_product(other.inverse())
5954    }
5955}
5956
5957impl Transformation<Motor> for Motor {
5958    type Output = Motor;
5959
5960    fn transformation(self, other: Motor) -> Motor {
5961        self.geometric_product(other).geometric_product(self.reversal())
5962    }
5963}
5964
5965impl GeometricQuotient<MotorDual> for Motor {
5966    type Output = MotorDual;
5967
5968    fn geometric_quotient(self, other: MotorDual) -> MotorDual {
5969        self.geometric_product(other.inverse())
5970    }
5971}
5972
5973impl Transformation<MotorDual> for Motor {
5974    type Output = MotorDual;
5975
5976    fn transformation(self, other: MotorDual) -> MotorDual {
5977        self.geometric_product(other).geometric_product(self.reversal())
5978    }
5979}
5980
5981impl GeometricQuotient<MultiVector> for Motor {
5982    type Output = MultiVector;
5983
5984    fn geometric_quotient(self, other: MultiVector) -> MultiVector {
5985        self.geometric_product(other.inverse())
5986    }
5987}
5988
5989impl Transformation<MultiVector> for Motor {
5990    type Output = MultiVector;
5991
5992    fn transformation(self, other: MultiVector) -> MultiVector {
5993        self.geometric_product(other).geometric_product(self.reversal())
5994    }
5995}
5996
5997impl GeometricQuotient<Plane> for Motor {
5998    type Output = MotorDual;
5999
6000    fn geometric_quotient(self, other: Plane) -> MotorDual {
6001        self.geometric_product(other.inverse())
6002    }
6003}
6004
6005impl Transformation<Plane> for Motor {
6006    type Output = Plane;
6007
6008    fn transformation(self, other: Plane) -> Plane {
6009        self.geometric_product(other).geometric_product(self.reversal()).into()
6010    }
6011}
6012
6013impl GeometricQuotient<Point> for Motor {
6014    type Output = Motor;
6015
6016    fn geometric_quotient(self, other: Point) -> Motor {
6017        self.geometric_product(other.inverse())
6018    }
6019}
6020
6021impl Transformation<Point> for Motor {
6022    type Output = Point;
6023
6024    fn transformation(self, other: Point) -> Point {
6025        self.geometric_product(other).geometric_product(self.reversal()).into()
6026    }
6027}
6028
6029impl GeometricQuotient<Rotor> for Motor {
6030    type Output = Motor;
6031
6032    fn geometric_quotient(self, other: Rotor) -> Motor {
6033        self.geometric_product(other.inverse())
6034    }
6035}
6036
6037impl Transformation<Rotor> for Motor {
6038    type Output = Rotor;
6039
6040    fn transformation(self, other: Rotor) -> Rotor {
6041        self.geometric_product(other).geometric_product(self.reversal()).into()
6042    }
6043}
6044
6045impl GeometricQuotient<f32> for Motor {
6046    type Output = Motor;
6047
6048    fn geometric_quotient(self, other: f32) -> Motor {
6049        self.geometric_product(other.inverse())
6050    }
6051}
6052
6053impl Transformation<f32> for Motor {
6054    type Output = f32;
6055
6056    fn transformation(self, other: f32) -> f32 {
6057        self.geometric_product(other).geometric_product(self.reversal()).into()
6058    }
6059}
6060
6061impl GeometricQuotient<Translator> for Motor {
6062    type Output = Motor;
6063
6064    fn geometric_quotient(self, other: Translator) -> Motor {
6065        self.geometric_product(other.inverse())
6066    }
6067}
6068
6069impl Transformation<Translator> for Motor {
6070    type Output = Translator;
6071
6072    fn transformation(self, other: Translator) -> Translator {
6073        self.geometric_product(other).geometric_product(self.reversal()).into()
6074    }
6075}
6076
6077impl GeometricQuotient<Motor> for MotorDual {
6078    type Output = MotorDual;
6079
6080    fn geometric_quotient(self, other: Motor) -> MotorDual {
6081        self.geometric_product(other.inverse())
6082    }
6083}
6084
6085impl Transformation<Motor> for MotorDual {
6086    type Output = Motor;
6087
6088    fn transformation(self, other: Motor) -> Motor {
6089        self.geometric_product(other).geometric_product(self.reversal())
6090    }
6091}
6092
6093impl GeometricQuotient<MotorDual> for MotorDual {
6094    type Output = Motor;
6095
6096    fn geometric_quotient(self, other: MotorDual) -> Motor {
6097        self.geometric_product(other.inverse())
6098    }
6099}
6100
6101impl Transformation<MotorDual> for MotorDual {
6102    type Output = MotorDual;
6103
6104    fn transformation(self, other: MotorDual) -> MotorDual {
6105        self.geometric_product(other).geometric_product(self.reversal())
6106    }
6107}
6108
6109impl GeometricQuotient<MultiVector> for MotorDual {
6110    type Output = MultiVector;
6111
6112    fn geometric_quotient(self, other: MultiVector) -> MultiVector {
6113        self.geometric_product(other.inverse())
6114    }
6115}
6116
6117impl Transformation<MultiVector> for MotorDual {
6118    type Output = MultiVector;
6119
6120    fn transformation(self, other: MultiVector) -> MultiVector {
6121        self.geometric_product(other).geometric_product(self.reversal())
6122    }
6123}
6124
6125impl GeometricQuotient<Plane> for MotorDual {
6126    type Output = Motor;
6127
6128    fn geometric_quotient(self, other: Plane) -> Motor {
6129        self.geometric_product(other.inverse())
6130    }
6131}
6132
6133impl Transformation<Plane> for MotorDual {
6134    type Output = Plane;
6135
6136    fn transformation(self, other: Plane) -> Plane {
6137        self.geometric_product(other).geometric_product(self.reversal()).into()
6138    }
6139}
6140
6141impl GeometricQuotient<Point> for MotorDual {
6142    type Output = MotorDual;
6143
6144    fn geometric_quotient(self, other: Point) -> MotorDual {
6145        self.geometric_product(other.inverse())
6146    }
6147}
6148
6149impl Transformation<Point> for MotorDual {
6150    type Output = Point;
6151
6152    fn transformation(self, other: Point) -> Point {
6153        self.geometric_product(other).geometric_product(self.reversal()).into()
6154    }
6155}
6156
6157impl GeometricQuotient<Rotor> for MotorDual {
6158    type Output = MotorDual;
6159
6160    fn geometric_quotient(self, other: Rotor) -> MotorDual {
6161        self.geometric_product(other.inverse())
6162    }
6163}
6164
6165impl Transformation<Rotor> for MotorDual {
6166    type Output = Rotor;
6167
6168    fn transformation(self, other: Rotor) -> Rotor {
6169        self.geometric_product(other).geometric_product(self.reversal()).into()
6170    }
6171}
6172
6173impl GeometricQuotient<f32> for MotorDual {
6174    type Output = MotorDual;
6175
6176    fn geometric_quotient(self, other: f32) -> MotorDual {
6177        self.geometric_product(other.inverse())
6178    }
6179}
6180
6181impl Transformation<f32> for MotorDual {
6182    type Output = f32;
6183
6184    fn transformation(self, other: f32) -> f32 {
6185        self.geometric_product(other).geometric_product(self.reversal()).into()
6186    }
6187}
6188
6189impl GeometricQuotient<Translator> for MotorDual {
6190    type Output = MotorDual;
6191
6192    fn geometric_quotient(self, other: Translator) -> MotorDual {
6193        self.geometric_product(other.inverse())
6194    }
6195}
6196
6197impl Transformation<Translator> for MotorDual {
6198    type Output = Translator;
6199
6200    fn transformation(self, other: Translator) -> Translator {
6201        self.geometric_product(other).geometric_product(self.reversal()).into()
6202    }
6203}
6204
6205impl GeometricQuotient<Motor> for MultiVector {
6206    type Output = MultiVector;
6207
6208    fn geometric_quotient(self, other: Motor) -> MultiVector {
6209        self.geometric_product(other.inverse())
6210    }
6211}
6212
6213impl Transformation<Motor> for MultiVector {
6214    type Output = Motor;
6215
6216    fn transformation(self, other: Motor) -> Motor {
6217        self.geometric_product(other).geometric_product(self.reversal()).into()
6218    }
6219}
6220
6221impl GeometricQuotient<MotorDual> for MultiVector {
6222    type Output = MultiVector;
6223
6224    fn geometric_quotient(self, other: MotorDual) -> MultiVector {
6225        self.geometric_product(other.inverse())
6226    }
6227}
6228
6229impl Transformation<MotorDual> for MultiVector {
6230    type Output = MotorDual;
6231
6232    fn transformation(self, other: MotorDual) -> MotorDual {
6233        self.geometric_product(other).geometric_product(self.reversal()).into()
6234    }
6235}
6236
6237impl Powi for MultiVector {
6238    type Output = MultiVector;
6239
6240    fn powi(self, exponent: isize) -> MultiVector {
6241        if exponent == 0 {
6242            return MultiVector::one();
6243        }
6244        let mut x: MultiVector = if exponent < 0 { self.inverse() } else { self };
6245        let mut y: MultiVector = MultiVector::one();
6246        let mut n: isize = exponent.abs();
6247        while 1 < n {
6248            if n & 1 == 1 {
6249                y = x.geometric_product(y);
6250            }
6251            x = x.geometric_product(x);
6252            n = n >> 1;
6253        }
6254        x.geometric_product(y)
6255    }
6256}
6257
6258impl GeometricQuotient<MultiVector> for MultiVector {
6259    type Output = MultiVector;
6260
6261    fn geometric_quotient(self, other: MultiVector) -> MultiVector {
6262        self.geometric_product(other.inverse())
6263    }
6264}
6265
6266impl Transformation<MultiVector> for MultiVector {
6267    type Output = MultiVector;
6268
6269    fn transformation(self, other: MultiVector) -> MultiVector {
6270        self.geometric_product(other).geometric_product(self.reversal())
6271    }
6272}
6273
6274impl GeometricQuotient<Plane> for MultiVector {
6275    type Output = MultiVector;
6276
6277    fn geometric_quotient(self, other: Plane) -> MultiVector {
6278        self.geometric_product(other.inverse())
6279    }
6280}
6281
6282impl Transformation<Plane> for MultiVector {
6283    type Output = Plane;
6284
6285    fn transformation(self, other: Plane) -> Plane {
6286        self.geometric_product(other).geometric_product(self.reversal()).into()
6287    }
6288}
6289
6290impl GeometricQuotient<Point> for MultiVector {
6291    type Output = MultiVector;
6292
6293    fn geometric_quotient(self, other: Point) -> MultiVector {
6294        self.geometric_product(other.inverse())
6295    }
6296}
6297
6298impl Transformation<Point> for MultiVector {
6299    type Output = Point;
6300
6301    fn transformation(self, other: Point) -> Point {
6302        self.geometric_product(other).geometric_product(self.reversal()).into()
6303    }
6304}
6305
6306impl GeometricQuotient<Rotor> for MultiVector {
6307    type Output = MultiVector;
6308
6309    fn geometric_quotient(self, other: Rotor) -> MultiVector {
6310        self.geometric_product(other.inverse())
6311    }
6312}
6313
6314impl Transformation<Rotor> for MultiVector {
6315    type Output = Rotor;
6316
6317    fn transformation(self, other: Rotor) -> Rotor {
6318        self.geometric_product(other).geometric_product(self.reversal()).into()
6319    }
6320}
6321
6322impl GeometricQuotient<f32> for MultiVector {
6323    type Output = MultiVector;
6324
6325    fn geometric_quotient(self, other: f32) -> MultiVector {
6326        self.geometric_product(other.inverse())
6327    }
6328}
6329
6330impl Transformation<f32> for MultiVector {
6331    type Output = f32;
6332
6333    fn transformation(self, other: f32) -> f32 {
6334        self.geometric_product(other).geometric_product(self.reversal()).into()
6335    }
6336}
6337
6338impl GeometricQuotient<Translator> for MultiVector {
6339    type Output = MultiVector;
6340
6341    fn geometric_quotient(self, other: Translator) -> MultiVector {
6342        self.geometric_product(other.inverse())
6343    }
6344}
6345
6346impl Transformation<Translator> for MultiVector {
6347    type Output = Translator;
6348
6349    fn transformation(self, other: Translator) -> Translator {
6350        self.geometric_product(other).geometric_product(self.reversal()).into()
6351    }
6352}
6353
6354impl GeometricQuotient<Motor> for Plane {
6355    type Output = MotorDual;
6356
6357    fn geometric_quotient(self, other: Motor) -> MotorDual {
6358        self.geometric_product(other.inverse())
6359    }
6360}
6361
6362impl Transformation<Motor> for Plane {
6363    type Output = Motor;
6364
6365    fn transformation(self, other: Motor) -> Motor {
6366        self.geometric_product(other).geometric_product(self.reversal())
6367    }
6368}
6369
6370impl GeometricQuotient<MotorDual> for Plane {
6371    type Output = Motor;
6372
6373    fn geometric_quotient(self, other: MotorDual) -> Motor {
6374        self.geometric_product(other.inverse())
6375    }
6376}
6377
6378impl Transformation<MotorDual> for Plane {
6379    type Output = MotorDual;
6380
6381    fn transformation(self, other: MotorDual) -> MotorDual {
6382        self.geometric_product(other).geometric_product(self.reversal())
6383    }
6384}
6385
6386impl GeometricQuotient<MultiVector> for Plane {
6387    type Output = MultiVector;
6388
6389    fn geometric_quotient(self, other: MultiVector) -> MultiVector {
6390        self.geometric_product(other.inverse())
6391    }
6392}
6393
6394impl Transformation<MultiVector> for Plane {
6395    type Output = MultiVector;
6396
6397    fn transformation(self, other: MultiVector) -> MultiVector {
6398        self.geometric_product(other).geometric_product(self.reversal())
6399    }
6400}
6401
6402impl GeometricQuotient<Plane> for Plane {
6403    type Output = Motor;
6404
6405    fn geometric_quotient(self, other: Plane) -> Motor {
6406        self.geometric_product(other.inverse())
6407    }
6408}
6409
6410impl Transformation<Plane> for Plane {
6411    type Output = Plane;
6412
6413    fn transformation(self, other: Plane) -> Plane {
6414        self.geometric_product(other).geometric_product(self.reversal()).into()
6415    }
6416}
6417
6418impl GeometricQuotient<Point> for Plane {
6419    type Output = MotorDual;
6420
6421    fn geometric_quotient(self, other: Point) -> MotorDual {
6422        self.geometric_product(other.inverse())
6423    }
6424}
6425
6426impl Transformation<Point> for Plane {
6427    type Output = Point;
6428
6429    fn transformation(self, other: Point) -> Point {
6430        self.geometric_product(other).geometric_product(self.reversal()).into()
6431    }
6432}
6433
6434impl GeometricQuotient<Rotor> for Plane {
6435    type Output = MotorDual;
6436
6437    fn geometric_quotient(self, other: Rotor) -> MotorDual {
6438        self.geometric_product(other.inverse())
6439    }
6440}
6441
6442impl Transformation<Rotor> for Plane {
6443    type Output = Rotor;
6444
6445    fn transformation(self, other: Rotor) -> Rotor {
6446        self.geometric_product(other).geometric_product(self.reversal()).into()
6447    }
6448}
6449
6450impl GeometricQuotient<f32> for Plane {
6451    type Output = Plane;
6452
6453    fn geometric_quotient(self, other: f32) -> Plane {
6454        self.geometric_product(other.inverse())
6455    }
6456}
6457
6458impl Transformation<f32> for Plane {
6459    type Output = f32;
6460
6461    fn transformation(self, other: f32) -> f32 {
6462        self.geometric_product(other).geometric_product(self.reversal()).into()
6463    }
6464}
6465
6466impl GeometricQuotient<Translator> for Plane {
6467    type Output = MotorDual;
6468
6469    fn geometric_quotient(self, other: Translator) -> MotorDual {
6470        self.geometric_product(other.inverse())
6471    }
6472}
6473
6474impl Transformation<Translator> for Plane {
6475    type Output = Translator;
6476
6477    fn transformation(self, other: Translator) -> Translator {
6478        self.geometric_product(other).geometric_product(self.reversal()).into()
6479    }
6480}
6481
6482impl Transformation<IdealPoint> for Point {
6483    type Output = IdealPoint;
6484
6485    fn transformation(self, other: IdealPoint) -> IdealPoint {
6486        self.geometric_product(other).geometric_product(self.reversal())
6487    }
6488}
6489
6490impl GeometricQuotient<Motor> for Point {
6491    type Output = Motor;
6492
6493    fn geometric_quotient(self, other: Motor) -> Motor {
6494        self.geometric_product(other.inverse())
6495    }
6496}
6497
6498impl Transformation<Motor> for Point {
6499    type Output = Motor;
6500
6501    fn transformation(self, other: Motor) -> Motor {
6502        self.geometric_product(other).geometric_product(self.reversal())
6503    }
6504}
6505
6506impl GeometricQuotient<MotorDual> for Point {
6507    type Output = MotorDual;
6508
6509    fn geometric_quotient(self, other: MotorDual) -> MotorDual {
6510        self.geometric_product(other.inverse())
6511    }
6512}
6513
6514impl Transformation<MotorDual> for Point {
6515    type Output = MotorDual;
6516
6517    fn transformation(self, other: MotorDual) -> MotorDual {
6518        self.geometric_product(other).geometric_product(self.reversal())
6519    }
6520}
6521
6522impl GeometricQuotient<MultiVector> for Point {
6523    type Output = MultiVector;
6524
6525    fn geometric_quotient(self, other: MultiVector) -> MultiVector {
6526        self.geometric_product(other.inverse())
6527    }
6528}
6529
6530impl Transformation<MultiVector> for Point {
6531    type Output = MultiVector;
6532
6533    fn transformation(self, other: MultiVector) -> MultiVector {
6534        self.geometric_product(other).geometric_product(self.reversal())
6535    }
6536}
6537
6538impl GeometricQuotient<Plane> for Point {
6539    type Output = MotorDual;
6540
6541    fn geometric_quotient(self, other: Plane) -> MotorDual {
6542        self.geometric_product(other.inverse())
6543    }
6544}
6545
6546impl Transformation<Plane> for Point {
6547    type Output = Plane;
6548
6549    fn transformation(self, other: Plane) -> Plane {
6550        self.geometric_product(other).geometric_product(self.reversal()).into()
6551    }
6552}
6553
6554impl GeometricQuotient<Point> for Point {
6555    type Output = Translator;
6556
6557    fn geometric_quotient(self, other: Point) -> Translator {
6558        self.geometric_product(other.inverse())
6559    }
6560}
6561
6562impl Transformation<Point> for Point {
6563    type Output = Point;
6564
6565    fn transformation(self, other: Point) -> Point {
6566        self.geometric_product(other).geometric_product(self.reversal())
6567    }
6568}
6569
6570impl GeometricQuotient<Rotor> for Point {
6571    type Output = Motor;
6572
6573    fn geometric_quotient(self, other: Rotor) -> Motor {
6574        self.geometric_product(other.inverse())
6575    }
6576}
6577
6578impl Transformation<Rotor> for Point {
6579    type Output = Rotor;
6580
6581    fn transformation(self, other: Rotor) -> Rotor {
6582        self.geometric_product(other).geometric_product(self.reversal()).into()
6583    }
6584}
6585
6586impl GeometricQuotient<f32> for Point {
6587    type Output = Point;
6588
6589    fn geometric_quotient(self, other: f32) -> Point {
6590        self.geometric_product(other.inverse())
6591    }
6592}
6593
6594impl Transformation<f32> for Point {
6595    type Output = f32;
6596
6597    fn transformation(self, other: f32) -> f32 {
6598        self.geometric_product(other).geometric_product(self.reversal()).into()
6599    }
6600}
6601
6602impl GeometricQuotient<Translator> for Point {
6603    type Output = Point;
6604
6605    fn geometric_quotient(self, other: Translator) -> Point {
6606        self.geometric_product(other.inverse())
6607    }
6608}
6609
6610impl Transformation<Translator> for Point {
6611    type Output = Translator;
6612
6613    fn transformation(self, other: Translator) -> Translator {
6614        self.geometric_product(other).geometric_product(self.reversal())
6615    }
6616}
6617
6618impl Transformation<IdealPoint> for Rotor {
6619    type Output = IdealPoint;
6620
6621    fn transformation(self, other: IdealPoint) -> IdealPoint {
6622        self.geometric_product(other).geometric_product(self.reversal())
6623    }
6624}
6625
6626impl GeometricQuotient<Motor> for Rotor {
6627    type Output = Motor;
6628
6629    fn geometric_quotient(self, other: Motor) -> Motor {
6630        self.geometric_product(other.inverse())
6631    }
6632}
6633
6634impl Transformation<Motor> for Rotor {
6635    type Output = Motor;
6636
6637    fn transformation(self, other: Motor) -> Motor {
6638        self.geometric_product(other).geometric_product(self.reversal())
6639    }
6640}
6641
6642impl GeometricQuotient<MotorDual> for Rotor {
6643    type Output = MotorDual;
6644
6645    fn geometric_quotient(self, other: MotorDual) -> MotorDual {
6646        self.geometric_product(other.inverse())
6647    }
6648}
6649
6650impl Transformation<MotorDual> for Rotor {
6651    type Output = MotorDual;
6652
6653    fn transformation(self, other: MotorDual) -> MotorDual {
6654        self.geometric_product(other).geometric_product(self.reversal())
6655    }
6656}
6657
6658impl GeometricQuotient<MultiVector> for Rotor {
6659    type Output = MultiVector;
6660
6661    fn geometric_quotient(self, other: MultiVector) -> MultiVector {
6662        self.geometric_product(other.inverse())
6663    }
6664}
6665
6666impl Transformation<MultiVector> for Rotor {
6667    type Output = MultiVector;
6668
6669    fn transformation(self, other: MultiVector) -> MultiVector {
6670        self.geometric_product(other).geometric_product(self.reversal())
6671    }
6672}
6673
6674impl GeometricQuotient<Plane> for Rotor {
6675    type Output = MotorDual;
6676
6677    fn geometric_quotient(self, other: Plane) -> MotorDual {
6678        self.geometric_product(other.inverse())
6679    }
6680}
6681
6682impl Transformation<Plane> for Rotor {
6683    type Output = Plane;
6684
6685    fn transformation(self, other: Plane) -> Plane {
6686        self.geometric_product(other).geometric_product(self.reversal()).into()
6687    }
6688}
6689
6690impl GeometricQuotient<Point> for Rotor {
6691    type Output = Motor;
6692
6693    fn geometric_quotient(self, other: Point) -> Motor {
6694        self.geometric_product(other.inverse())
6695    }
6696}
6697
6698impl Transformation<Point> for Rotor {
6699    type Output = Point;
6700
6701    fn transformation(self, other: Point) -> Point {
6702        self.geometric_product(other).geometric_product(self.reversal()).into()
6703    }
6704}
6705
6706impl Powi for Rotor {
6707    type Output = Rotor;
6708
6709    fn powi(self, exponent: isize) -> Rotor {
6710        if exponent == 0 {
6711            return Rotor::one();
6712        }
6713        let mut x: Rotor = if exponent < 0 { self.inverse() } else { self };
6714        let mut y: Rotor = Rotor::one();
6715        let mut n: isize = exponent.abs();
6716        while 1 < n {
6717            if n & 1 == 1 {
6718                y = x.geometric_product(y);
6719            }
6720            x = x.geometric_product(x);
6721            n = n >> 1;
6722        }
6723        x.geometric_product(y)
6724    }
6725}
6726
6727impl GeometricQuotient<Rotor> for Rotor {
6728    type Output = Rotor;
6729
6730    fn geometric_quotient(self, other: Rotor) -> Rotor {
6731        self.geometric_product(other.inverse())
6732    }
6733}
6734
6735impl Transformation<Rotor> for Rotor {
6736    type Output = Rotor;
6737
6738    fn transformation(self, other: Rotor) -> Rotor {
6739        self.geometric_product(other).geometric_product(self.reversal())
6740    }
6741}
6742
6743impl GeometricQuotient<f32> for Rotor {
6744    type Output = Rotor;
6745
6746    fn geometric_quotient(self, other: f32) -> Rotor {
6747        self.geometric_product(other.inverse())
6748    }
6749}
6750
6751impl Transformation<f32> for Rotor {
6752    type Output = f32;
6753
6754    fn transformation(self, other: f32) -> f32 {
6755        self.geometric_product(other).geometric_product(self.reversal()).into()
6756    }
6757}
6758
6759impl GeometricQuotient<Translator> for Rotor {
6760    type Output = Motor;
6761
6762    fn geometric_quotient(self, other: Translator) -> Motor {
6763        self.geometric_product(other.inverse())
6764    }
6765}
6766
6767impl Transformation<Translator> for Rotor {
6768    type Output = Translator;
6769
6770    fn transformation(self, other: Translator) -> Translator {
6771        self.geometric_product(other).geometric_product(self.reversal()).into()
6772    }
6773}
6774
6775impl Transformation<IdealPoint> for f32 {
6776    type Output = IdealPoint;
6777
6778    fn transformation(self, other: IdealPoint) -> IdealPoint {
6779        self.geometric_product(other).geometric_product(self.reversal())
6780    }
6781}
6782
6783impl GeometricQuotient<Motor> for f32 {
6784    type Output = Motor;
6785
6786    fn geometric_quotient(self, other: Motor) -> Motor {
6787        self.geometric_product(other.inverse())
6788    }
6789}
6790
6791impl Transformation<Motor> for f32 {
6792    type Output = Motor;
6793
6794    fn transformation(self, other: Motor) -> Motor {
6795        self.geometric_product(other).geometric_product(self.reversal())
6796    }
6797}
6798
6799impl GeometricQuotient<MotorDual> for f32 {
6800    type Output = MotorDual;
6801
6802    fn geometric_quotient(self, other: MotorDual) -> MotorDual {
6803        self.geometric_product(other.inverse())
6804    }
6805}
6806
6807impl Transformation<MotorDual> for f32 {
6808    type Output = MotorDual;
6809
6810    fn transformation(self, other: MotorDual) -> MotorDual {
6811        self.geometric_product(other).geometric_product(self.reversal())
6812    }
6813}
6814
6815impl GeometricQuotient<MultiVector> for f32 {
6816    type Output = MultiVector;
6817
6818    fn geometric_quotient(self, other: MultiVector) -> MultiVector {
6819        self.geometric_product(other.inverse())
6820    }
6821}
6822
6823impl Transformation<MultiVector> for f32 {
6824    type Output = MultiVector;
6825
6826    fn transformation(self, other: MultiVector) -> MultiVector {
6827        self.geometric_product(other).geometric_product(self.reversal())
6828    }
6829}
6830
6831impl GeometricQuotient<Plane> for f32 {
6832    type Output = Plane;
6833
6834    fn geometric_quotient(self, other: Plane) -> Plane {
6835        self.geometric_product(other.inverse())
6836    }
6837}
6838
6839impl Transformation<Plane> for f32 {
6840    type Output = Plane;
6841
6842    fn transformation(self, other: Plane) -> Plane {
6843        self.geometric_product(other).geometric_product(self.reversal())
6844    }
6845}
6846
6847impl GeometricQuotient<Point> for f32 {
6848    type Output = Point;
6849
6850    fn geometric_quotient(self, other: Point) -> Point {
6851        self.geometric_product(other.inverse())
6852    }
6853}
6854
6855impl Transformation<Point> for f32 {
6856    type Output = Point;
6857
6858    fn transformation(self, other: Point) -> Point {
6859        self.geometric_product(other).geometric_product(self.reversal())
6860    }
6861}
6862
6863impl GeometricQuotient<Rotor> for f32 {
6864    type Output = Rotor;
6865
6866    fn geometric_quotient(self, other: Rotor) -> Rotor {
6867        self.geometric_product(other.inverse())
6868    }
6869}
6870
6871impl Transformation<Rotor> for f32 {
6872    type Output = Rotor;
6873
6874    fn transformation(self, other: Rotor) -> Rotor {
6875        self.geometric_product(other).geometric_product(self.reversal())
6876    }
6877}
6878
6879impl GeometricQuotient<Translator> for f32 {
6880    type Output = Translator;
6881
6882    fn geometric_quotient(self, other: Translator) -> Translator {
6883        self.geometric_product(other.inverse())
6884    }
6885}
6886
6887impl Transformation<Translator> for f32 {
6888    type Output = Translator;
6889
6890    fn transformation(self, other: Translator) -> Translator {
6891        self.geometric_product(other).geometric_product(self.reversal())
6892    }
6893}
6894
6895impl Transformation<IdealPoint> for Translator {
6896    type Output = IdealPoint;
6897
6898    fn transformation(self, other: IdealPoint) -> IdealPoint {
6899        self.geometric_product(other).geometric_product(self.reversal())
6900    }
6901}
6902
6903impl GeometricQuotient<Motor> for Translator {
6904    type Output = Motor;
6905
6906    fn geometric_quotient(self, other: Motor) -> Motor {
6907        self.geometric_product(other.inverse())
6908    }
6909}
6910
6911impl Transformation<Motor> for Translator {
6912    type Output = Motor;
6913
6914    fn transformation(self, other: Motor) -> Motor {
6915        self.geometric_product(other).geometric_product(self.reversal())
6916    }
6917}
6918
6919impl GeometricQuotient<MotorDual> for Translator {
6920    type Output = MotorDual;
6921
6922    fn geometric_quotient(self, other: MotorDual) -> MotorDual {
6923        self.geometric_product(other.inverse())
6924    }
6925}
6926
6927impl Transformation<MotorDual> for Translator {
6928    type Output = MotorDual;
6929
6930    fn transformation(self, other: MotorDual) -> MotorDual {
6931        self.geometric_product(other).geometric_product(self.reversal())
6932    }
6933}
6934
6935impl GeometricQuotient<MultiVector> for Translator {
6936    type Output = MultiVector;
6937
6938    fn geometric_quotient(self, other: MultiVector) -> MultiVector {
6939        self.geometric_product(other.inverse())
6940    }
6941}
6942
6943impl Transformation<MultiVector> for Translator {
6944    type Output = MultiVector;
6945
6946    fn transformation(self, other: MultiVector) -> MultiVector {
6947        self.geometric_product(other).geometric_product(self.reversal())
6948    }
6949}
6950
6951impl GeometricQuotient<Plane> for Translator {
6952    type Output = MotorDual;
6953
6954    fn geometric_quotient(self, other: Plane) -> MotorDual {
6955        self.geometric_product(other.inverse())
6956    }
6957}
6958
6959impl Transformation<Plane> for Translator {
6960    type Output = Plane;
6961
6962    fn transformation(self, other: Plane) -> Plane {
6963        self.geometric_product(other).geometric_product(self.reversal()).into()
6964    }
6965}
6966
6967impl GeometricQuotient<Point> for Translator {
6968    type Output = Point;
6969
6970    fn geometric_quotient(self, other: Point) -> Point {
6971        self.geometric_product(other.inverse())
6972    }
6973}
6974
6975impl Transformation<Point> for Translator {
6976    type Output = Point;
6977
6978    fn transformation(self, other: Point) -> Point {
6979        self.geometric_product(other).geometric_product(self.reversal())
6980    }
6981}
6982
6983impl GeometricQuotient<Rotor> for Translator {
6984    type Output = Motor;
6985
6986    fn geometric_quotient(self, other: Rotor) -> Motor {
6987        self.geometric_product(other.inverse())
6988    }
6989}
6990
6991impl Transformation<Rotor> for Translator {
6992    type Output = Rotor;
6993
6994    fn transformation(self, other: Rotor) -> Rotor {
6995        self.geometric_product(other).geometric_product(self.reversal()).into()
6996    }
6997}
6998
6999impl GeometricQuotient<f32> for Translator {
7000    type Output = Translator;
7001
7002    fn geometric_quotient(self, other: f32) -> Translator {
7003        self.geometric_product(other.inverse())
7004    }
7005}
7006
7007impl Transformation<f32> for Translator {
7008    type Output = f32;
7009
7010    fn transformation(self, other: f32) -> f32 {
7011        self.geometric_product(other).geometric_product(self.reversal()).into()
7012    }
7013}
7014
7015impl Powi for Translator {
7016    type Output = Translator;
7017
7018    fn powi(self, exponent: isize) -> Translator {
7019        if exponent == 0 {
7020            return Translator::one();
7021        }
7022        let mut x: Translator = if exponent < 0 { self.inverse() } else { self };
7023        let mut y: Translator = Translator::one();
7024        let mut n: isize = exponent.abs();
7025        while 1 < n {
7026            if n & 1 == 1 {
7027                y = x.geometric_product(y);
7028            }
7029            x = x.geometric_product(x);
7030            n = n >> 1;
7031        }
7032        x.geometric_product(y)
7033    }
7034}
7035
7036impl GeometricQuotient<Translator> for Translator {
7037    type Output = Translator;
7038
7039    fn geometric_quotient(self, other: Translator) -> Translator {
7040        self.geometric_product(other.inverse())
7041    }
7042}
7043
7044impl Transformation<Translator> for Translator {
7045    type Output = Translator;
7046
7047    fn transformation(self, other: Translator) -> Translator {
7048        self.geometric_product(other).geometric_product(self.reversal())
7049    }
7050}
7051