geometric_algebra/
ppga3d.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, e23, -e13, e12
8    g0: Simd32x4,
9    /// e0, -e023, e013, -e012
10    g1: Simd32x4,
11    /// e123, e1, e2, e3
12    g2: Simd32x4,
13    /// e0123, e01, e02, e03
14    g3: Simd32x4,
15}
16
17#[derive(Clone, Copy)]
18pub union MultiVector {
19    groups: MultiVectorGroups,
20    /// 1, e23, -e13, e12, e0, -e023, e013, -e012, e123, e1, e2, e3, e0123, e01, e02, e03
21    elements: [f32; 16],
22}
23
24impl MultiVector {
25    #[allow(clippy::too_many_arguments)]
26    pub const fn new(scalar: f32, e23: f32, _e13: f32, e12: f32, e0: f32, _e023: f32, e013: f32, _e012: f32, e123: f32, e1: f32, e2: f32, e3: f32, e0123: f32, e01: f32, e02: f32, e03: f32) -> Self {
27        Self { elements: [scalar, e23, _e13, e12, e0, _e023, e013, _e012, e123, e1, e2, e3, e0123, e01, e02, e03] }
28    }
29    pub const fn from_groups(g0: Simd32x4, g1: Simd32x4, g2: Simd32x4, g3: Simd32x4) -> Self {
30        Self { groups: MultiVectorGroups { g0, g1, g2, g3 } }
31    }
32    #[inline(always)]
33    pub fn group0(&self) -> Simd32x4 {
34        unsafe { self.groups.g0 }
35    }
36    #[inline(always)]
37    pub fn group0_mut(&mut self) -> &mut Simd32x4 {
38        unsafe { &mut self.groups.g0 }
39    }
40    #[inline(always)]
41    pub fn group1(&self) -> Simd32x4 {
42        unsafe { self.groups.g1 }
43    }
44    #[inline(always)]
45    pub fn group1_mut(&mut self) -> &mut Simd32x4 {
46        unsafe { &mut self.groups.g1 }
47    }
48    #[inline(always)]
49    pub fn group2(&self) -> Simd32x4 {
50        unsafe { self.groups.g2 }
51    }
52    #[inline(always)]
53    pub fn group2_mut(&mut self) -> &mut Simd32x4 {
54        unsafe { &mut self.groups.g2 }
55    }
56    #[inline(always)]
57    pub fn group3(&self) -> Simd32x4 {
58        unsafe { self.groups.g3 }
59    }
60    #[inline(always)]
61    pub fn group3_mut(&mut self) -> &mut Simd32x4 {
62        unsafe { &mut self.groups.g3 }
63    }
64}
65
66const MULTIVECTOR_INDEX_REMAP: [usize; 16] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
67
68impl std::ops::Index<usize> for MultiVector {
69    type Output = f32;
70
71    fn index(&self, index: usize) -> &Self::Output {
72        unsafe { &self.elements[MULTIVECTOR_INDEX_REMAP[index]] }
73    }
74}
75
76impl std::ops::IndexMut<usize> for MultiVector {
77    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
78        unsafe { &mut self.elements[MULTIVECTOR_INDEX_REMAP[index]] }
79    }
80}
81
82impl std::convert::From<MultiVector> for [f32; 16] {
83    fn from(vector: MultiVector) -> Self {
84        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], vector.elements[8], vector.elements[9], vector.elements[10], vector.elements[11], vector.elements[12], vector.elements[13], vector.elements[14], vector.elements[15]] }
85    }
86}
87
88impl std::convert::From<[f32; 16]> for MultiVector {
89    fn from(array: [f32; 16]) -> Self {
90        Self { elements: [array[0], array[1], array[2], array[3], array[4], array[5], array[6], array[7], array[8], array[9], array[10], array[11], array[12], array[13], array[14], array[15]] }
91    }
92}
93
94impl std::fmt::Debug for MultiVector {
95    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
96        formatter
97            .debug_struct("MultiVector")
98            .field("1", &self[0])
99            .field("e23", &self[1])
100            .field("-e13", &self[2])
101            .field("e12", &self[3])
102            .field("e0", &self[4])
103            .field("-e023", &self[5])
104            .field("e013", &self[6])
105            .field("-e012", &self[7])
106            .field("e123", &self[8])
107            .field("e1", &self[9])
108            .field("e2", &self[10])
109            .field("e3", &self[11])
110            .field("e0123", &self[12])
111            .field("e01", &self[13])
112            .field("e02", &self[14])
113            .field("e03", &self[15])
114            .finish()
115    }
116}
117
118#[derive(Clone, Copy)]
119struct RotorGroups {
120    /// 1, e23, -e13, e12
121    g0: Simd32x4,
122}
123
124#[derive(Clone, Copy)]
125pub union Rotor {
126    groups: RotorGroups,
127    /// 1, e23, -e13, e12
128    elements: [f32; 4],
129}
130
131impl Rotor {
132    #[allow(clippy::too_many_arguments)]
133    pub const fn new(scalar: f32, e23: f32, _e13: f32, e12: f32) -> Self {
134        Self { elements: [scalar, e23, _e13, e12] }
135    }
136    pub const fn from_groups(g0: Simd32x4) -> Self {
137        Self { groups: RotorGroups { g0 } }
138    }
139    #[inline(always)]
140    pub fn group0(&self) -> Simd32x4 {
141        unsafe { self.groups.g0 }
142    }
143    #[inline(always)]
144    pub fn group0_mut(&mut self) -> &mut Simd32x4 {
145        unsafe { &mut self.groups.g0 }
146    }
147}
148
149const ROTOR_INDEX_REMAP: [usize; 4] = [0, 1, 2, 3];
150
151impl std::ops::Index<usize> for Rotor {
152    type Output = f32;
153
154    fn index(&self, index: usize) -> &Self::Output {
155        unsafe { &self.elements[ROTOR_INDEX_REMAP[index]] }
156    }
157}
158
159impl std::ops::IndexMut<usize> for Rotor {
160    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
161        unsafe { &mut self.elements[ROTOR_INDEX_REMAP[index]] }
162    }
163}
164
165impl std::convert::From<Rotor> for [f32; 4] {
166    fn from(vector: Rotor) -> Self {
167        unsafe { [vector.elements[0], vector.elements[1], vector.elements[2], vector.elements[3]] }
168    }
169}
170
171impl std::convert::From<[f32; 4]> for Rotor {
172    fn from(array: [f32; 4]) -> Self {
173        Self { elements: [array[0], array[1], array[2], array[3]] }
174    }
175}
176
177impl std::fmt::Debug for Rotor {
178    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
179        formatter
180            .debug_struct("Rotor")
181            .field("1", &self[0])
182            .field("e23", &self[1])
183            .field("-e13", &self[2])
184            .field("e12", &self[3])
185            .finish()
186    }
187}
188
189#[derive(Clone, Copy)]
190struct PointGroups {
191    /// e123, -e023, e013, -e012
192    g0: Simd32x4,
193}
194
195#[derive(Clone, Copy)]
196pub union Point {
197    groups: PointGroups,
198    /// e123, -e023, e013, -e012
199    elements: [f32; 4],
200}
201
202impl Point {
203    #[allow(clippy::too_many_arguments)]
204    pub const fn new(e123: f32, _e023: f32, e013: f32, _e012: f32) -> Self {
205        Self { elements: [e123, _e023, e013, _e012] }
206    }
207    pub const fn from_groups(g0: Simd32x4) -> Self {
208        Self { groups: PointGroups { g0 } }
209    }
210    #[inline(always)]
211    pub fn group0(&self) -> Simd32x4 {
212        unsafe { self.groups.g0 }
213    }
214    #[inline(always)]
215    pub fn group0_mut(&mut self) -> &mut Simd32x4 {
216        unsafe { &mut self.groups.g0 }
217    }
218}
219
220const POINT_INDEX_REMAP: [usize; 4] = [0, 1, 2, 3];
221
222impl std::ops::Index<usize> for Point {
223    type Output = f32;
224
225    fn index(&self, index: usize) -> &Self::Output {
226        unsafe { &self.elements[POINT_INDEX_REMAP[index]] }
227    }
228}
229
230impl std::ops::IndexMut<usize> for Point {
231    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
232        unsafe { &mut self.elements[POINT_INDEX_REMAP[index]] }
233    }
234}
235
236impl std::convert::From<Point> for [f32; 4] {
237    fn from(vector: Point) -> Self {
238        unsafe { [vector.elements[0], vector.elements[1], vector.elements[2], vector.elements[3]] }
239    }
240}
241
242impl std::convert::From<[f32; 4]> for Point {
243    fn from(array: [f32; 4]) -> Self {
244        Self { elements: [array[0], array[1], array[2], array[3]] }
245    }
246}
247
248impl std::fmt::Debug for Point {
249    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
250        formatter
251            .debug_struct("Point")
252            .field("e123", &self[0])
253            .field("-e023", &self[1])
254            .field("e013", &self[2])
255            .field("-e012", &self[3])
256            .finish()
257    }
258}
259
260#[derive(Clone, Copy)]
261struct IdealPointGroups {
262    /// e01, e02, e03
263    g0: Simd32x3,
264}
265
266#[derive(Clone, Copy)]
267pub union IdealPoint {
268    groups: IdealPointGroups,
269    /// e01, e02, e03, 0
270    elements: [f32; 4],
271}
272
273impl IdealPoint {
274    #[allow(clippy::too_many_arguments)]
275    pub const fn new(e01: f32, e02: f32, e03: f32) -> Self {
276        Self { elements: [e01, e02, e03, 0.0] }
277    }
278    pub const fn from_groups(g0: Simd32x3) -> Self {
279        Self { groups: IdealPointGroups { g0 } }
280    }
281    #[inline(always)]
282    pub fn group0(&self) -> Simd32x3 {
283        unsafe { self.groups.g0 }
284    }
285    #[inline(always)]
286    pub fn group0_mut(&mut self) -> &mut Simd32x3 {
287        unsafe { &mut self.groups.g0 }
288    }
289}
290
291const IDEALPOINT_INDEX_REMAP: [usize; 3] = [0, 1, 2];
292
293impl std::ops::Index<usize> for IdealPoint {
294    type Output = f32;
295
296    fn index(&self, index: usize) -> &Self::Output {
297        unsafe { &self.elements[IDEALPOINT_INDEX_REMAP[index]] }
298    }
299}
300
301impl std::ops::IndexMut<usize> for IdealPoint {
302    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
303        unsafe { &mut self.elements[IDEALPOINT_INDEX_REMAP[index]] }
304    }
305}
306
307impl std::convert::From<IdealPoint> for [f32; 3] {
308    fn from(vector: IdealPoint) -> Self {
309        unsafe { [vector.elements[0], vector.elements[1], vector.elements[2]] }
310    }
311}
312
313impl std::convert::From<[f32; 3]> for IdealPoint {
314    fn from(array: [f32; 3]) -> Self {
315        Self { elements: [array[0], array[1], array[2], 0.0] }
316    }
317}
318
319impl std::fmt::Debug for IdealPoint {
320    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
321        formatter
322            .debug_struct("IdealPoint")
323            .field("e01", &self[0])
324            .field("e02", &self[1])
325            .field("e03", &self[2])
326            .finish()
327    }
328}
329
330#[derive(Clone, Copy)]
331struct PlaneGroups {
332    /// e0, e1, e2, e3
333    g0: Simd32x4,
334}
335
336#[derive(Clone, Copy)]
337pub union Plane {
338    groups: PlaneGroups,
339    /// e0, e1, e2, e3
340    elements: [f32; 4],
341}
342
343impl Plane {
344    #[allow(clippy::too_many_arguments)]
345    pub const fn new(e0: f32, e1: f32, e2: f32, e3: f32) -> Self {
346        Self { elements: [e0, e1, e2, e3] }
347    }
348    pub const fn from_groups(g0: Simd32x4) -> Self {
349        Self { groups: PlaneGroups { g0 } }
350    }
351    #[inline(always)]
352    pub fn group0(&self) -> Simd32x4 {
353        unsafe { self.groups.g0 }
354    }
355    #[inline(always)]
356    pub fn group0_mut(&mut self) -> &mut Simd32x4 {
357        unsafe { &mut self.groups.g0 }
358    }
359}
360
361const PLANE_INDEX_REMAP: [usize; 4] = [0, 1, 2, 3];
362
363impl std::ops::Index<usize> for Plane {
364    type Output = f32;
365
366    fn index(&self, index: usize) -> &Self::Output {
367        unsafe { &self.elements[PLANE_INDEX_REMAP[index]] }
368    }
369}
370
371impl std::ops::IndexMut<usize> for Plane {
372    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
373        unsafe { &mut self.elements[PLANE_INDEX_REMAP[index]] }
374    }
375}
376
377impl std::convert::From<Plane> for [f32; 4] {
378    fn from(vector: Plane) -> Self {
379        unsafe { [vector.elements[0], vector.elements[1], vector.elements[2], vector.elements[3]] }
380    }
381}
382
383impl std::convert::From<[f32; 4]> for Plane {
384    fn from(array: [f32; 4]) -> Self {
385        Self { elements: [array[0], array[1], array[2], array[3]] }
386    }
387}
388
389impl std::fmt::Debug for Plane {
390    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
391        formatter
392            .debug_struct("Plane")
393            .field("e0", &self[0])
394            .field("e1", &self[1])
395            .field("e2", &self[2])
396            .field("e3", &self[3])
397            .finish()
398    }
399}
400
401#[derive(Clone, Copy)]
402struct LineGroups {
403    /// e01, e02, e03
404    g0: Simd32x3,
405    /// e23, -e13, e12
406    g1: Simd32x3,
407}
408
409#[derive(Clone, Copy)]
410pub union Line {
411    groups: LineGroups,
412    /// e01, e02, e03, 0, e23, -e13, e12, 0
413    elements: [f32; 8],
414}
415
416impl Line {
417    #[allow(clippy::too_many_arguments)]
418    pub const fn new(e01: f32, e02: f32, e03: f32, e23: f32, _e13: f32, e12: f32) -> Self {
419        Self { elements: [e01, e02, e03, 0.0, e23, _e13, e12, 0.0] }
420    }
421    pub const fn from_groups(g0: Simd32x3, g1: Simd32x3) -> Self {
422        Self { groups: LineGroups { g0, g1 } }
423    }
424    #[inline(always)]
425    pub fn group0(&self) -> Simd32x3 {
426        unsafe { self.groups.g0 }
427    }
428    #[inline(always)]
429    pub fn group0_mut(&mut self) -> &mut Simd32x3 {
430        unsafe { &mut self.groups.g0 }
431    }
432    #[inline(always)]
433    pub fn group1(&self) -> Simd32x3 {
434        unsafe { self.groups.g1 }
435    }
436    #[inline(always)]
437    pub fn group1_mut(&mut self) -> &mut Simd32x3 {
438        unsafe { &mut self.groups.g1 }
439    }
440}
441
442const LINE_INDEX_REMAP: [usize; 6] = [0, 1, 2, 4, 5, 6];
443
444impl std::ops::Index<usize> for Line {
445    type Output = f32;
446
447    fn index(&self, index: usize) -> &Self::Output {
448        unsafe { &self.elements[LINE_INDEX_REMAP[index]] }
449    }
450}
451
452impl std::ops::IndexMut<usize> for Line {
453    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
454        unsafe { &mut self.elements[LINE_INDEX_REMAP[index]] }
455    }
456}
457
458impl std::convert::From<Line> for [f32; 6] {
459    fn from(vector: Line) -> Self {
460        unsafe { [vector.elements[0], vector.elements[1], vector.elements[2], vector.elements[4], vector.elements[5], vector.elements[6]] }
461    }
462}
463
464impl std::convert::From<[f32; 6]> for Line {
465    fn from(array: [f32; 6]) -> Self {
466        Self { elements: [array[0], array[1], array[2], 0.0, array[3], array[4], array[5], 0.0] }
467    }
468}
469
470impl std::fmt::Debug for Line {
471    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
472        formatter
473            .debug_struct("Line")
474            .field("e01", &self[0])
475            .field("e02", &self[1])
476            .field("e03", &self[2])
477            .field("e23", &self[3])
478            .field("-e13", &self[4])
479            .field("e12", &self[5])
480            .finish()
481    }
482}
483
484#[derive(Clone, Copy)]
485struct TranslatorGroups {
486    /// 1, e01, e02, e03
487    g0: Simd32x4,
488}
489
490#[derive(Clone, Copy)]
491pub union Translator {
492    groups: TranslatorGroups,
493    /// 1, e01, e02, e03
494    elements: [f32; 4],
495}
496
497impl Translator {
498    #[allow(clippy::too_many_arguments)]
499    pub const fn new(scalar: f32, e01: f32, e02: f32, e03: f32) -> Self {
500        Self { elements: [scalar, e01, e02, e03] }
501    }
502    pub const fn from_groups(g0: Simd32x4) -> Self {
503        Self { groups: TranslatorGroups { g0 } }
504    }
505    #[inline(always)]
506    pub fn group0(&self) -> Simd32x4 {
507        unsafe { self.groups.g0 }
508    }
509    #[inline(always)]
510    pub fn group0_mut(&mut self) -> &mut Simd32x4 {
511        unsafe { &mut self.groups.g0 }
512    }
513}
514
515const TRANSLATOR_INDEX_REMAP: [usize; 4] = [0, 1, 2, 3];
516
517impl std::ops::Index<usize> for Translator {
518    type Output = f32;
519
520    fn index(&self, index: usize) -> &Self::Output {
521        unsafe { &self.elements[TRANSLATOR_INDEX_REMAP[index]] }
522    }
523}
524
525impl std::ops::IndexMut<usize> for Translator {
526    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
527        unsafe { &mut self.elements[TRANSLATOR_INDEX_REMAP[index]] }
528    }
529}
530
531impl std::convert::From<Translator> for [f32; 4] {
532    fn from(vector: Translator) -> Self {
533        unsafe { [vector.elements[0], vector.elements[1], vector.elements[2], vector.elements[3]] }
534    }
535}
536
537impl std::convert::From<[f32; 4]> for Translator {
538    fn from(array: [f32; 4]) -> Self {
539        Self { elements: [array[0], array[1], array[2], array[3]] }
540    }
541}
542
543impl std::fmt::Debug for Translator {
544    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
545        formatter
546            .debug_struct("Translator")
547            .field("1", &self[0])
548            .field("e01", &self[1])
549            .field("e02", &self[2])
550            .field("e03", &self[3])
551            .finish()
552    }
553}
554
555#[derive(Clone, Copy)]
556struct MotorGroups {
557    /// 1, e23, -e13, e12
558    g0: Simd32x4,
559    /// e0123, e01, e02, e03
560    g1: Simd32x4,
561}
562
563#[derive(Clone, Copy)]
564pub union Motor {
565    groups: MotorGroups,
566    /// 1, e23, -e13, e12, e0123, e01, e02, e03
567    elements: [f32; 8],
568}
569
570impl Motor {
571    #[allow(clippy::too_many_arguments)]
572    pub const fn new(scalar: f32, e23: f32, _e13: f32, e12: f32, e0123: f32, e01: f32, e02: f32, e03: f32) -> Self {
573        Self { elements: [scalar, e23, _e13, e12, e0123, e01, e02, e03] }
574    }
575    pub const fn from_groups(g0: Simd32x4, g1: Simd32x4) -> Self {
576        Self { groups: MotorGroups { g0, g1 } }
577    }
578    #[inline(always)]
579    pub fn group0(&self) -> Simd32x4 {
580        unsafe { self.groups.g0 }
581    }
582    #[inline(always)]
583    pub fn group0_mut(&mut self) -> &mut Simd32x4 {
584        unsafe { &mut self.groups.g0 }
585    }
586    #[inline(always)]
587    pub fn group1(&self) -> Simd32x4 {
588        unsafe { self.groups.g1 }
589    }
590    #[inline(always)]
591    pub fn group1_mut(&mut self) -> &mut Simd32x4 {
592        unsafe { &mut self.groups.g1 }
593    }
594}
595
596const MOTOR_INDEX_REMAP: [usize; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
597
598impl std::ops::Index<usize> for Motor {
599    type Output = f32;
600
601    fn index(&self, index: usize) -> &Self::Output {
602        unsafe { &self.elements[MOTOR_INDEX_REMAP[index]] }
603    }
604}
605
606impl std::ops::IndexMut<usize> for Motor {
607    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
608        unsafe { &mut self.elements[MOTOR_INDEX_REMAP[index]] }
609    }
610}
611
612impl std::convert::From<Motor> for [f32; 8] {
613    fn from(vector: Motor) -> Self {
614        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]] }
615    }
616}
617
618impl std::convert::From<[f32; 8]> for Motor {
619    fn from(array: [f32; 8]) -> Self {
620        Self { elements: [array[0], array[1], array[2], array[3], array[4], array[5], array[6], array[7]] }
621    }
622}
623
624impl std::fmt::Debug for Motor {
625    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
626        formatter
627            .debug_struct("Motor")
628            .field("1", &self[0])
629            .field("e23", &self[1])
630            .field("-e13", &self[2])
631            .field("e12", &self[3])
632            .field("e0123", &self[4])
633            .field("e01", &self[5])
634            .field("e02", &self[6])
635            .field("e03", &self[7])
636            .finish()
637    }
638}
639
640#[derive(Clone, Copy)]
641struct PointAndPlaneGroups {
642    /// e123, -e023, e013, -e012
643    g0: Simd32x4,
644    /// e0, e1, e2, e3
645    g1: Simd32x4,
646}
647
648#[derive(Clone, Copy)]
649pub union PointAndPlane {
650    groups: PointAndPlaneGroups,
651    /// e123, -e023, e013, -e012, e0, e1, e2, e3
652    elements: [f32; 8],
653}
654
655impl PointAndPlane {
656    #[allow(clippy::too_many_arguments)]
657    pub const fn new(e123: f32, _e023: f32, e013: f32, _e012: f32, e0: f32, e1: f32, e2: f32, e3: f32) -> Self {
658        Self { elements: [e123, _e023, e013, _e012, e0, e1, e2, e3] }
659    }
660    pub const fn from_groups(g0: Simd32x4, g1: Simd32x4) -> Self {
661        Self { groups: PointAndPlaneGroups { g0, g1 } }
662    }
663    #[inline(always)]
664    pub fn group0(&self) -> Simd32x4 {
665        unsafe { self.groups.g0 }
666    }
667    #[inline(always)]
668    pub fn group0_mut(&mut self) -> &mut Simd32x4 {
669        unsafe { &mut self.groups.g0 }
670    }
671    #[inline(always)]
672    pub fn group1(&self) -> Simd32x4 {
673        unsafe { self.groups.g1 }
674    }
675    #[inline(always)]
676    pub fn group1_mut(&mut self) -> &mut Simd32x4 {
677        unsafe { &mut self.groups.g1 }
678    }
679}
680
681const POINTANDPLANE_INDEX_REMAP: [usize; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
682
683impl std::ops::Index<usize> for PointAndPlane {
684    type Output = f32;
685
686    fn index(&self, index: usize) -> &Self::Output {
687        unsafe { &self.elements[POINTANDPLANE_INDEX_REMAP[index]] }
688    }
689}
690
691impl std::ops::IndexMut<usize> for PointAndPlane {
692    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
693        unsafe { &mut self.elements[POINTANDPLANE_INDEX_REMAP[index]] }
694    }
695}
696
697impl std::convert::From<PointAndPlane> for [f32; 8] {
698    fn from(vector: PointAndPlane) -> Self {
699        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]] }
700    }
701}
702
703impl std::convert::From<[f32; 8]> for PointAndPlane {
704    fn from(array: [f32; 8]) -> Self {
705        Self { elements: [array[0], array[1], array[2], array[3], array[4], array[5], array[6], array[7]] }
706    }
707}
708
709impl std::fmt::Debug for PointAndPlane {
710    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
711        formatter
712            .debug_struct("PointAndPlane")
713            .field("e123", &self[0])
714            .field("-e023", &self[1])
715            .field("e013", &self[2])
716            .field("-e012", &self[3])
717            .field("e0", &self[4])
718            .field("e1", &self[5])
719            .field("e2", &self[6])
720            .field("e3", &self[7])
721            .finish()
722    }
723}
724
725impl Add<MultiVector> for f32 {
726    type Output = MultiVector;
727
728    fn add(self, other: MultiVector) -> MultiVector {
729        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + other.group0(), g1: other.group1(), g2: other.group2(), g3: other.group3() } }
730    }
731}
732
733impl Sub<MultiVector> for f32 {
734    type Output = MultiVector;
735
736    fn sub(self, other: MultiVector) -> MultiVector {
737        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(), g2: Simd32x4::from(0.0) - other.group2(), g3: Simd32x4::from(0.0) - other.group3() } }
738    }
739}
740
741impl GeometricProduct<MultiVector> for f32 {
742    type Output = MultiVector;
743
744    fn geometric_product(self, other: MultiVector) -> MultiVector {
745        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self) * other.group0(), g1: Simd32x4::from(self) * other.group1(), g2: Simd32x4::from(self) * other.group2(), g3: Simd32x4::from(self) * other.group3() } }
746    }
747}
748
749impl RegressiveProduct<MultiVector> for f32 {
750    type Output = f32;
751
752    fn regressive_product(self, other: MultiVector) -> f32 {
753        self * other.group3()[0]
754    }
755}
756
757impl OuterProduct<MultiVector> for f32 {
758    type Output = MultiVector;
759
760    fn outer_product(self, other: MultiVector) -> MultiVector {
761        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self) * other.group0(), g1: Simd32x4::from(self) * other.group1(), g2: Simd32x4::from(self) * other.group2(), g3: Simd32x4::from(self) * other.group3() } }
762    }
763}
764
765impl InnerProduct<MultiVector> for f32 {
766    type Output = MultiVector;
767
768    fn inner_product(self, other: MultiVector) -> MultiVector {
769        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self) * other.group0(), g1: Simd32x4::from(self) * other.group1(), g2: Simd32x4::from(self) * other.group2(), g3: Simd32x4::from(self) * other.group3() } }
770    }
771}
772
773impl LeftContraction<MultiVector> for f32 {
774    type Output = MultiVector;
775
776    fn left_contraction(self, other: MultiVector) -> MultiVector {
777        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self) * other.group0(), g1: Simd32x4::from(self) * other.group1(), g2: Simd32x4::from(self) * other.group2(), g3: Simd32x4::from(self) * other.group3() } }
778    }
779}
780
781impl RightContraction<MultiVector> for f32 {
782    type Output = f32;
783
784    fn right_contraction(self, other: MultiVector) -> f32 {
785        self * other.group0()[0]
786    }
787}
788
789impl ScalarProduct<MultiVector> for f32 {
790    type Output = f32;
791
792    fn scalar_product(self, other: MultiVector) -> f32 {
793        self * other.group0()[0]
794    }
795}
796
797impl Add<Rotor> for f32 {
798    type Output = Rotor;
799
800    fn add(self, other: Rotor) -> Rotor {
801        Rotor { groups: RotorGroups { g0: Simd32x4::from(self) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + other.group0() } }
802    }
803}
804
805impl Sub<Rotor> for f32 {
806    type Output = Rotor;
807
808    fn sub(self, other: Rotor) -> Rotor {
809        Rotor { groups: RotorGroups { g0: Simd32x4::from(self) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) - other.group0() } }
810    }
811}
812
813impl GeometricProduct<Rotor> for f32 {
814    type Output = Rotor;
815
816    fn geometric_product(self, other: Rotor) -> Rotor {
817        Rotor { groups: RotorGroups { g0: Simd32x4::from(self) * other.group0() } }
818    }
819}
820
821impl OuterProduct<Rotor> for f32 {
822    type Output = Rotor;
823
824    fn outer_product(self, other: Rotor) -> Rotor {
825        Rotor { groups: RotorGroups { g0: Simd32x4::from(self) * other.group0() } }
826    }
827}
828
829impl InnerProduct<Rotor> for f32 {
830    type Output = Rotor;
831
832    fn inner_product(self, other: Rotor) -> Rotor {
833        Rotor { groups: RotorGroups { g0: Simd32x4::from(self) * other.group0() } }
834    }
835}
836
837impl LeftContraction<Rotor> for f32 {
838    type Output = Rotor;
839
840    fn left_contraction(self, other: Rotor) -> Rotor {
841        Rotor { groups: RotorGroups { g0: Simd32x4::from(self) * other.group0() } }
842    }
843}
844
845impl RightContraction<Rotor> for f32 {
846    type Output = f32;
847
848    fn right_contraction(self, other: Rotor) -> f32 {
849        self * other.group0()[0]
850    }
851}
852
853impl ScalarProduct<Rotor> for f32 {
854    type Output = f32;
855
856    fn scalar_product(self, other: Rotor) -> f32 {
857        self * other.group0()[0]
858    }
859}
860
861impl GeometricProduct<Point> for f32 {
862    type Output = Point;
863
864    fn geometric_product(self, other: Point) -> Point {
865        Point { groups: PointGroups { g0: Simd32x4::from(self) * other.group0() } }
866    }
867}
868
869impl OuterProduct<Point> for f32 {
870    type Output = Point;
871
872    fn outer_product(self, other: Point) -> Point {
873        Point { groups: PointGroups { g0: Simd32x4::from(self) * other.group0() } }
874    }
875}
876
877impl InnerProduct<Point> for f32 {
878    type Output = Point;
879
880    fn inner_product(self, other: Point) -> Point {
881        Point { groups: PointGroups { g0: Simd32x4::from(self) * other.group0() } }
882    }
883}
884
885impl LeftContraction<Point> for f32 {
886    type Output = Point;
887
888    fn left_contraction(self, other: Point) -> Point {
889        Point { groups: PointGroups { g0: Simd32x4::from(self) * other.group0() } }
890    }
891}
892
893impl Add<IdealPoint> for f32 {
894    type Output = Translator;
895
896    fn add(self, other: IdealPoint) -> Translator {
897        Translator { groups: TranslatorGroups { 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]) } }
898    }
899}
900
901impl Sub<IdealPoint> for f32 {
902    type Output = Translator;
903
904    fn sub(self, other: IdealPoint) -> Translator {
905        Translator { groups: TranslatorGroups { 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]) } }
906    }
907}
908
909impl GeometricProduct<IdealPoint> for f32 {
910    type Output = IdealPoint;
911
912    fn geometric_product(self, other: IdealPoint) -> IdealPoint {
913        IdealPoint { groups: IdealPointGroups { g0: Simd32x3::from(self) * other.group0() } }
914    }
915}
916
917impl OuterProduct<IdealPoint> for f32 {
918    type Output = IdealPoint;
919
920    fn outer_product(self, other: IdealPoint) -> IdealPoint {
921        IdealPoint { groups: IdealPointGroups { g0: Simd32x3::from(self) * other.group0() } }
922    }
923}
924
925impl InnerProduct<IdealPoint> for f32 {
926    type Output = IdealPoint;
927
928    fn inner_product(self, other: IdealPoint) -> IdealPoint {
929        IdealPoint { groups: IdealPointGroups { g0: Simd32x3::from(self) * other.group0() } }
930    }
931}
932
933impl LeftContraction<IdealPoint> for f32 {
934    type Output = IdealPoint;
935
936    fn left_contraction(self, other: IdealPoint) -> IdealPoint {
937        IdealPoint { groups: IdealPointGroups { g0: Simd32x3::from(self) * other.group0() } }
938    }
939}
940
941impl GeometricProduct<Plane> for f32 {
942    type Output = Plane;
943
944    fn geometric_product(self, other: Plane) -> Plane {
945        Plane { groups: PlaneGroups { g0: Simd32x4::from(self) * other.group0() } }
946    }
947}
948
949impl OuterProduct<Plane> for f32 {
950    type Output = Plane;
951
952    fn outer_product(self, other: Plane) -> Plane {
953        Plane { groups: PlaneGroups { g0: Simd32x4::from(self) * other.group0() } }
954    }
955}
956
957impl InnerProduct<Plane> for f32 {
958    type Output = Plane;
959
960    fn inner_product(self, other: Plane) -> Plane {
961        Plane { groups: PlaneGroups { g0: Simd32x4::from(self) * other.group0() } }
962    }
963}
964
965impl LeftContraction<Plane> for f32 {
966    type Output = Plane;
967
968    fn left_contraction(self, other: Plane) -> Plane {
969        Plane { groups: PlaneGroups { g0: Simd32x4::from(self) * other.group0() } }
970    }
971}
972
973impl GeometricProduct<Line> for f32 {
974    type Output = Line;
975
976    fn geometric_product(self, other: Line) -> Line {
977        Line { groups: LineGroups { g0: Simd32x3::from(self) * other.group0(), g1: Simd32x3::from(self) * other.group1() } }
978    }
979}
980
981impl OuterProduct<Line> for f32 {
982    type Output = Line;
983
984    fn outer_product(self, other: Line) -> Line {
985        Line { groups: LineGroups { g0: Simd32x3::from(self) * other.group0(), g1: Simd32x3::from(self) * other.group1() } }
986    }
987}
988
989impl InnerProduct<Line> for f32 {
990    type Output = Line;
991
992    fn inner_product(self, other: Line) -> Line {
993        Line { groups: LineGroups { g0: Simd32x3::from(self) * other.group0(), g1: Simd32x3::from(self) * other.group1() } }
994    }
995}
996
997impl LeftContraction<Line> for f32 {
998    type Output = Line;
999
1000    fn left_contraction(self, other: Line) -> Line {
1001        Line { groups: LineGroups { g0: Simd32x3::from(self) * other.group0(), g1: Simd32x3::from(self) * other.group1() } }
1002    }
1003}
1004
1005impl Add<Translator> for f32 {
1006    type Output = Translator;
1007
1008    fn add(self, other: Translator) -> Translator {
1009        Translator { groups: TranslatorGroups { g0: Simd32x4::from(self) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + other.group0() } }
1010    }
1011}
1012
1013impl Sub<Translator> for f32 {
1014    type Output = Translator;
1015
1016    fn sub(self, other: Translator) -> Translator {
1017        Translator { groups: TranslatorGroups { g0: Simd32x4::from(self) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) - other.group0() } }
1018    }
1019}
1020
1021impl GeometricProduct<Translator> for f32 {
1022    type Output = Translator;
1023
1024    fn geometric_product(self, other: Translator) -> Translator {
1025        Translator { groups: TranslatorGroups { g0: Simd32x4::from(self) * other.group0() } }
1026    }
1027}
1028
1029impl OuterProduct<Translator> for f32 {
1030    type Output = Translator;
1031
1032    fn outer_product(self, other: Translator) -> Translator {
1033        Translator { groups: TranslatorGroups { g0: Simd32x4::from(self) * other.group0() } }
1034    }
1035}
1036
1037impl InnerProduct<Translator> for f32 {
1038    type Output = Translator;
1039
1040    fn inner_product(self, other: Translator) -> Translator {
1041        Translator { groups: TranslatorGroups { g0: Simd32x4::from(self) * other.group0() } }
1042    }
1043}
1044
1045impl LeftContraction<Translator> for f32 {
1046    type Output = Translator;
1047
1048    fn left_contraction(self, other: Translator) -> Translator {
1049        Translator { groups: TranslatorGroups { g0: Simd32x4::from(self) * other.group0() } }
1050    }
1051}
1052
1053impl RightContraction<Translator> for f32 {
1054    type Output = f32;
1055
1056    fn right_contraction(self, other: Translator) -> f32 {
1057        self * other.group0()[0]
1058    }
1059}
1060
1061impl ScalarProduct<Translator> for f32 {
1062    type Output = f32;
1063
1064    fn scalar_product(self, other: Translator) -> f32 {
1065        self * other.group0()[0]
1066    }
1067}
1068
1069impl Add<Motor> for f32 {
1070    type Output = Motor;
1071
1072    fn add(self, other: Motor) -> Motor {
1073        Motor { groups: MotorGroups { g0: Simd32x4::from(self) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + other.group0(), g1: other.group1() } }
1074    }
1075}
1076
1077impl Sub<Motor> for f32 {
1078    type Output = Motor;
1079
1080    fn sub(self, other: Motor) -> Motor {
1081        Motor { groups: MotorGroups { g0: Simd32x4::from(self) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) - other.group0(), g1: Simd32x4::from(0.0) - other.group1() } }
1082    }
1083}
1084
1085impl GeometricProduct<Motor> for f32 {
1086    type Output = Motor;
1087
1088    fn geometric_product(self, other: Motor) -> Motor {
1089        Motor { groups: MotorGroups { g0: Simd32x4::from(self) * other.group0(), g1: Simd32x4::from(self) * other.group1() } }
1090    }
1091}
1092
1093impl RegressiveProduct<Motor> for f32 {
1094    type Output = f32;
1095
1096    fn regressive_product(self, other: Motor) -> f32 {
1097        self * other.group1()[0]
1098    }
1099}
1100
1101impl OuterProduct<Motor> for f32 {
1102    type Output = Motor;
1103
1104    fn outer_product(self, other: Motor) -> Motor {
1105        Motor { groups: MotorGroups { g0: Simd32x4::from(self) * other.group0(), g1: Simd32x4::from(self) * other.group1() } }
1106    }
1107}
1108
1109impl InnerProduct<Motor> for f32 {
1110    type Output = Motor;
1111
1112    fn inner_product(self, other: Motor) -> Motor {
1113        Motor { groups: MotorGroups { g0: Simd32x4::from(self) * other.group0(), g1: Simd32x4::from(self) * other.group1() } }
1114    }
1115}
1116
1117impl LeftContraction<Motor> for f32 {
1118    type Output = Motor;
1119
1120    fn left_contraction(self, other: Motor) -> Motor {
1121        Motor { groups: MotorGroups { g0: Simd32x4::from(self) * other.group0(), g1: Simd32x4::from(self) * other.group1() } }
1122    }
1123}
1124
1125impl RightContraction<Motor> for f32 {
1126    type Output = f32;
1127
1128    fn right_contraction(self, other: Motor) -> f32 {
1129        self * other.group0()[0]
1130    }
1131}
1132
1133impl ScalarProduct<Motor> for f32 {
1134    type Output = f32;
1135
1136    fn scalar_product(self, other: Motor) -> f32 {
1137        self * other.group0()[0]
1138    }
1139}
1140
1141impl GeometricProduct<PointAndPlane> for f32 {
1142    type Output = PointAndPlane;
1143
1144    fn geometric_product(self, other: PointAndPlane) -> PointAndPlane {
1145        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self) * other.group0(), g1: Simd32x4::from(self) * other.group1() } }
1146    }
1147}
1148
1149impl OuterProduct<PointAndPlane> for f32 {
1150    type Output = PointAndPlane;
1151
1152    fn outer_product(self, other: PointAndPlane) -> PointAndPlane {
1153        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self) * other.group0(), g1: Simd32x4::from(self) * other.group1() } }
1154    }
1155}
1156
1157impl InnerProduct<PointAndPlane> for f32 {
1158    type Output = PointAndPlane;
1159
1160    fn inner_product(self, other: PointAndPlane) -> PointAndPlane {
1161        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self) * other.group0(), g1: Simd32x4::from(self) * other.group1() } }
1162    }
1163}
1164
1165impl LeftContraction<PointAndPlane> for f32 {
1166    type Output = PointAndPlane;
1167
1168    fn left_contraction(self, other: PointAndPlane) -> PointAndPlane {
1169        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self) * other.group0(), g1: Simd32x4::from(self) * other.group1() } }
1170    }
1171}
1172
1173impl Zero for MultiVector {
1174    fn zero() -> Self {
1175        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(0.0), g1: Simd32x4::from(0.0), g2: Simd32x4::from(0.0), g3: Simd32x4::from(0.0) } }
1176    }
1177}
1178
1179impl One for MultiVector {
1180    fn one() -> Self {
1181        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from([1.0, 0.0, 0.0, 0.0]), g1: Simd32x4::from(0.0), g2: Simd32x4::from(0.0), g3: Simd32x4::from(0.0) } }
1182    }
1183}
1184
1185impl Neg for MultiVector {
1186    type Output = MultiVector;
1187
1188    fn neg(self) -> MultiVector {
1189        MultiVector { groups: MultiVectorGroups { g0: self.group0() * Simd32x4::from(-1.0), g1: self.group1() * Simd32x4::from(-1.0), g2: self.group2() * Simd32x4::from(-1.0), g3: self.group3() * Simd32x4::from(-1.0) } }
1190    }
1191}
1192
1193impl Automorphism for MultiVector {
1194    type Output = MultiVector;
1195
1196    fn automorphism(self) -> MultiVector {
1197        MultiVector { groups: MultiVectorGroups { g0: self.group0(), g1: self.group1() * Simd32x4::from(-1.0), g2: self.group2() * Simd32x4::from(-1.0), g3: self.group3() } }
1198    }
1199}
1200
1201impl Reversal for MultiVector {
1202    type Output = MultiVector;
1203
1204    fn reversal(self) -> MultiVector {
1205        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]), g2: self.group2() * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]), g3: self.group3() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) } }
1206    }
1207}
1208
1209impl Conjugation for MultiVector {
1210    type Output = MultiVector;
1211
1212    fn conjugation(self) -> MultiVector {
1213        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]), g2: self.group2() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]), g3: self.group3() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) } }
1214    }
1215}
1216
1217impl Dual for MultiVector {
1218    type Output = MultiVector;
1219
1220    fn dual(self) -> MultiVector {
1221        MultiVector { groups: MultiVectorGroups { g0: self.group3(), g1: self.group2() * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]), g2: self.group1() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]), g3: self.group0() } }
1222    }
1223}
1224
1225impl Into<f32> for MultiVector {
1226    fn into(self) -> f32 {
1227        self.group0()[0]
1228    }
1229}
1230
1231impl Add<f32> for MultiVector {
1232    type Output = MultiVector;
1233
1234    fn add(self, other: f32) -> MultiVector {
1235        MultiVector { groups: MultiVectorGroups { g0: self.group0() + Simd32x4::from(other) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]), g1: self.group1(), g2: self.group2(), g3: self.group3() } }
1236    }
1237}
1238
1239impl AddAssign<f32> for MultiVector {
1240    fn add_assign(&mut self, other: f32) {
1241        *self = (*self).add(other);
1242    }
1243}
1244
1245impl Sub<f32> for MultiVector {
1246    type Output = MultiVector;
1247
1248    fn sub(self, other: f32) -> MultiVector {
1249        MultiVector { groups: MultiVectorGroups { g0: self.group0() - Simd32x4::from(other) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]), g1: self.group1(), g2: self.group2(), g3: self.group3() } }
1250    }
1251}
1252
1253impl SubAssign<f32> for MultiVector {
1254    fn sub_assign(&mut self, other: f32) {
1255        *self = (*self).sub(other);
1256    }
1257}
1258
1259impl GeometricProduct<f32> for MultiVector {
1260    type Output = MultiVector;
1261
1262    fn geometric_product(self, other: f32) -> MultiVector {
1263        MultiVector { groups: MultiVectorGroups { g0: self.group0() * Simd32x4::from(other), g1: self.group1() * Simd32x4::from(other), g2: self.group2() * Simd32x4::from(other), g3: self.group3() * Simd32x4::from(other) } }
1264    }
1265}
1266
1267impl RegressiveProduct<f32> for MultiVector {
1268    type Output = f32;
1269
1270    fn regressive_product(self, other: f32) -> f32 {
1271        self.group3()[0] * other
1272    }
1273}
1274
1275impl OuterProduct<f32> for MultiVector {
1276    type Output = MultiVector;
1277
1278    fn outer_product(self, other: f32) -> MultiVector {
1279        MultiVector { groups: MultiVectorGroups { g0: self.group0() * Simd32x4::from(other), g1: self.group1() * Simd32x4::from(other), g2: self.group2() * Simd32x4::from(other), g3: self.group3() * Simd32x4::from(other) } }
1280    }
1281}
1282
1283impl InnerProduct<f32> for MultiVector {
1284    type Output = MultiVector;
1285
1286    fn inner_product(self, other: f32) -> MultiVector {
1287        MultiVector { groups: MultiVectorGroups { g0: self.group0() * Simd32x4::from(other), g1: self.group1() * Simd32x4::from(other), g2: self.group2() * Simd32x4::from(other), g3: self.group3() * Simd32x4::from(other) } }
1288    }
1289}
1290
1291impl LeftContraction<f32> for MultiVector {
1292    type Output = f32;
1293
1294    fn left_contraction(self, other: f32) -> f32 {
1295        self.group0()[0] * other
1296    }
1297}
1298
1299impl RightContraction<f32> for MultiVector {
1300    type Output = MultiVector;
1301
1302    fn right_contraction(self, other: f32) -> MultiVector {
1303        MultiVector { groups: MultiVectorGroups { g0: self.group0() * Simd32x4::from(other), g1: self.group1() * Simd32x4::from(other), g2: self.group2() * Simd32x4::from(other), g3: self.group3() * Simd32x4::from(other) } }
1304    }
1305}
1306
1307impl ScalarProduct<f32> for MultiVector {
1308    type Output = f32;
1309
1310    fn scalar_product(self, other: f32) -> f32 {
1311        self.group0()[0] * other
1312    }
1313}
1314
1315impl Add<MultiVector> for MultiVector {
1316    type Output = MultiVector;
1317
1318    fn add(self, other: MultiVector) -> MultiVector {
1319        MultiVector { groups: MultiVectorGroups { g0: self.group0() + other.group0(), g1: self.group1() + other.group1(), g2: self.group2() + other.group2(), g3: self.group3() + other.group3() } }
1320    }
1321}
1322
1323impl AddAssign<MultiVector> for MultiVector {
1324    fn add_assign(&mut self, other: MultiVector) {
1325        *self = (*self).add(other);
1326    }
1327}
1328
1329impl Sub<MultiVector> for MultiVector {
1330    type Output = MultiVector;
1331
1332    fn sub(self, other: MultiVector) -> MultiVector {
1333        MultiVector { groups: MultiVectorGroups { g0: self.group0() - other.group0(), g1: self.group1() - other.group1(), g2: self.group2() - other.group2(), g3: self.group3() - other.group3() } }
1334    }
1335}
1336
1337impl SubAssign<MultiVector> for MultiVector {
1338    fn sub_assign(&mut self, other: MultiVector) {
1339        *self = (*self).sub(other);
1340    }
1341}
1342
1343impl Mul<MultiVector> for MultiVector {
1344    type Output = MultiVector;
1345
1346    fn mul(self, other: MultiVector) -> MultiVector {
1347        MultiVector { groups: MultiVectorGroups { g0: self.group0() * other.group0(), g1: self.group1() * other.group1(), g2: self.group2() * other.group2(), g3: self.group3() * other.group3() } }
1348    }
1349}
1350
1351impl MulAssign<MultiVector> for MultiVector {
1352    fn mul_assign(&mut self, other: MultiVector) {
1353        *self = (*self).mul(other);
1354    }
1355}
1356
1357impl Div<MultiVector> for MultiVector {
1358    type Output = MultiVector;
1359
1360    fn div(self, other: MultiVector) -> MultiVector {
1361        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]), g2: Simd32x4::from([self.group2()[0], self.group2()[1], self.group2()[2], self.group2()[3]]) * Simd32x4::from([1.0, 1.0, 1.0, 1.0]) / Simd32x4::from([other.group2()[0], other.group2()[1], other.group2()[2], other.group2()[3]]) * Simd32x4::from([1.0, 1.0, 1.0, 1.0]), g3: Simd32x4::from([self.group3()[0], self.group3()[1], self.group3()[2], self.group3()[3]]) * Simd32x4::from([1.0, 1.0, 1.0, 1.0]) / Simd32x4::from([other.group3()[0], other.group3()[1], other.group3()[2], other.group3()[3]]) * Simd32x4::from([1.0, 1.0, 1.0, 1.0]) } }
1362    }
1363}
1364
1365impl DivAssign<MultiVector> for MultiVector {
1366    fn div_assign(&mut self, other: MultiVector) {
1367        *self = (*self).div(other);
1368    }
1369}
1370
1371impl GeometricProduct<MultiVector> for MultiVector {
1372    type Output = MultiVector;
1373
1374    fn geometric_product(self, other: MultiVector) -> MultiVector {
1375        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([-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.group2()[0]) * other.group2() * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) + Simd32x4::from(self.group2()[1]) * swizzle!(other.group2(), 1, 0, 3, 2) * Simd32x4::from([1.0, 1.0, -1.0, 1.0]) + Simd32x4::from(self.group2()[2]) * swizzle!(other.group2(), 2, 3, 0, 1) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group2()[3]) * swizzle!(other.group2(), 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([1.0, 1.0, -1.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]) * 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]) + Simd32x4::from(self.group2()[0]) * other.group3() + Simd32x4::from(self.group2()[1]) * swizzle!(other.group3(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, -1.0, 1.0]) + Simd32x4::from(self.group2()[2]) * swizzle!(other.group3(), 2, 3, 0, 1) * Simd32x4::from([-1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group2()[3]) * swizzle!(other.group3(), 3, 2, 1, 0) * Simd32x4::from([-1.0, -1.0, 1.0, 1.0]) - Simd32x4::from(self.group3()[0]) * other.group2() + Simd32x4::from(self.group3()[1]) * swizzle!(other.group2(), 1, 0, 3, 2) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) + Simd32x4::from(self.group3()[2]) * swizzle!(other.group2(), 2, 3, 0, 1) * Simd32x4::from([1.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group3()[3]) * swizzle!(other.group2(), 3, 2, 1, 0) * Simd32x4::from([1.0, 1.0, -1.0, -1.0]), g2: Simd32x4::from(self.group0()[0]) * other.group2() + Simd32x4::from(self.group0()[1]) * swizzle!(other.group2(), 1, 0, 3, 2) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group2(), 2, 3, 0, 1) * Simd32x4::from([1.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group2(), 3, 2, 1, 0) * Simd32x4::from([1.0, 1.0, -1.0, -1.0]) + Simd32x4::from(self.group2()[0]) * other.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) + Simd32x4::from(self.group2()[1]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group2()[2]) * swizzle!(other.group0(), 2, 3, 0, 1) * Simd32x4::from([1.0, -1.0, 1.0, 1.0]) + Simd32x4::from(self.group2()[3]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([1.0, 1.0, -1.0, 1.0]), g3: Simd32x4::from(self.group0()[0]) * other.group3() + Simd32x4::from(self.group0()[1]) * swizzle!(other.group3(), 1, 0, 3, 2) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group3(), 2, 3, 0, 1) * Simd32x4::from([1.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group3(), 3, 2, 1, 0) * Simd32x4::from([1.0, 1.0, -1.0, -1.0]) + Simd32x4::from(self.group1()[0]) * other.group2() + Simd32x4::from(self.group1()[1]) * swizzle!(other.group2(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, -1.0, 1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group2(), 2, 3, 0, 1) * Simd32x4::from([-1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group2(), 3, 2, 1, 0) * Simd32x4::from([-1.0, -1.0, 1.0, 1.0]) - Simd32x4::from(self.group2()[0]) * other.group1() + Simd32x4::from(self.group2()[1]) * swizzle!(other.group1(), 1, 0, 3, 2) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) + Simd32x4::from(self.group2()[2]) * swizzle!(other.group1(), 2, 3, 0, 1) * Simd32x4::from([1.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group2()[3]) * swizzle!(other.group1(), 3, 2, 1, 0) * Simd32x4::from([1.0, 1.0, -1.0, -1.0]) + Simd32x4::from(self.group3()[0]) * other.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) + Simd32x4::from(self.group3()[1]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group3()[2]) * swizzle!(other.group0(), 2, 3, 0, 1) * Simd32x4::from([1.0, -1.0, 1.0, 1.0]) + Simd32x4::from(self.group3()[3]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([1.0, 1.0, -1.0, 1.0]) } }
1376    }
1377}
1378
1379impl RegressiveProduct<MultiVector> for MultiVector {
1380    type Output = MultiVector;
1381
1382    fn regressive_product(self, other: MultiVector) -> MultiVector {
1383        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[1]) * swizzle!(other.group3(), 1, 0, 1, 1) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group3(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group3(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, 1.0]) + Simd32x4::from(self.group1()[0]) * Simd32x4::from(other.group2()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[1]) * swizzle!(other.group2(), 1, 0, 1, 1) * Simd32x4::from([-1.0, -1.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group2(), 2, 2, 0, 2) * Simd32x4::from([-1.0, 0.0, -1.0, 0.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group2(), 3, 3, 3, 0) * Simd32x4::from([-1.0, 0.0, 0.0, -1.0]) + Simd32x4::from(self.group2()[0]) * other.group1() * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) + Simd32x4::from(self.group2()[1]) * Simd32x4::from(other.group1()[1]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group2()[2]) * Simd32x4::from(other.group1()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group2()[3]) * Simd32x4::from(other.group1()[3]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group3()[0]) * other.group0() + Simd32x4::from(self.group3()[1]) * Simd32x4::from(other.group0()[1]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group3()[2]) * Simd32x4::from(other.group0()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group3()[3]) * Simd32x4::from(other.group0()[3]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from(other.group3()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]), g1: Simd32x4::from(self.group1()[1]) * swizzle!(other.group3(), 1, 0, 1, 1) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group3(), 2, 2, 0, 2) * Simd32x4::from([-1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group3(), 3, 3, 3, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 1.0]) + Simd32x4::from(self.group3()[0]) * other.group1() + Simd32x4::from(self.group3()[1]) * Simd32x4::from(other.group1()[1]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group3()[2]) * Simd32x4::from(other.group1()[2]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group3()[3]) * Simd32x4::from(other.group1()[3]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[0]) * Simd32x4::from(other.group3()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]), g2: Simd32x4::from(self.group0()[2]) * swizzle!(other.group1(), 3, 3, 3, 1) * Simd32x4::from([0.0, 1.0, 0.0, -1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group1(), 2, 2, 1, 2) * Simd32x4::from([0.0, -1.0, 1.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]) * swizzle!(other.group0(), 3, 3, 3, 1) * Simd32x4::from([0.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group0(), 2, 2, 1, 2) * Simd32x4::from([0.0, 1.0, -1.0, 0.0]) + Simd32x4::from(self.group2()[0]) * other.group3() + Simd32x4::from(self.group2()[2]) * Simd32x4::from(other.group3()[0]) * Simd32x4::from([0.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group2()[3]) * Simd32x4::from(other.group3()[0]) * Simd32x4::from([0.0, 0.0, 0.0, 1.0]) + Simd32x4::from(self.group3()[0]) * other.group2() + Simd32x4::from(self.group3()[1]) * Simd32x4::from(other.group2()[0]) * Simd32x4::from([0.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group3()[2]) * Simd32x4::from(other.group2()[0]) * Simd32x4::from([0.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group3()[3]) * Simd32x4::from(other.group2()[0]) * Simd32x4::from([0.0, 0.0, 0.0, 1.0]) + Simd32x4::from([self.group0()[0], self.group2()[1], self.group0()[1], self.group0()[1]]) * Simd32x4::from([other.group1()[0], other.group3()[0], other.group1()[3], other.group1()[2]]) * Simd32x4::from([0.0, 1.0, -1.0, 1.0]), g3: Simd32x4::from(self.group1()[2]) * swizzle!(other.group1(), 3, 3, 3, 1) * Simd32x4::from([0.0, 1.0, 0.0, -1.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group1(), 2, 2, 1, 2) * Simd32x4::from([0.0, -1.0, 1.0, 0.0]) + Simd32x4::from(self.group3()[0]) * other.group3() + Simd32x4::from(self.group3()[2]) * Simd32x4::from(other.group3()[0]) * Simd32x4::from([0.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group3()[3]) * Simd32x4::from(other.group3()[0]) * Simd32x4::from([0.0, 0.0, 0.0, 1.0]) + Simd32x4::from([self.group1()[0], self.group3()[1], self.group1()[1], self.group1()[1]]) * Simd32x4::from([other.group1()[0], other.group3()[0], other.group1()[3], other.group1()[2]]) * Simd32x4::from([0.0, 1.0, -1.0, 1.0]) } }
1384    }
1385}
1386
1387impl OuterProduct<MultiVector> for MultiVector {
1388    type Output = MultiVector;
1389
1390    fn outer_product(self, other: MultiVector) -> MultiVector {
1391        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group2()[1]) * swizzle!(other.group2(), 3, 3, 3, 2) * Simd32x4::from([0.0, 0.0, -1.0, 1.0]) + Simd32x4::from(self.group2()[2]) * swizzle!(other.group2(), 3, 3, 3, 1) * Simd32x4::from([0.0, 1.0, 0.0, -1.0]) + Simd32x4::from(self.group2()[3]) * swizzle!(other.group2(), 2, 2, 1, 2) * Simd32x4::from([0.0, -1.0, 1.0, 0.0]) + self.group0() * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]), g1: Simd32x4::from(self.group0()[0]) * other.group1() + 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]) * 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.group2()[1]) * swizzle!(other.group3(), 3, 3, 3, 2) * Simd32x4::from([0.0, 0.0, -1.0, 1.0]) + Simd32x4::from(self.group2()[2]) * swizzle!(other.group3(), 3, 3, 3, 1) * Simd32x4::from([0.0, 1.0, 0.0, -1.0]) + Simd32x4::from(self.group2()[3]) * swizzle!(other.group3(), 2, 2, 1, 2) * Simd32x4::from([0.0, -1.0, 1.0, 0.0]) + Simd32x4::from(self.group3()[1]) * swizzle!(other.group2(), 3, 3, 3, 2) * Simd32x4::from([0.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group3()[2]) * swizzle!(other.group2(), 3, 3, 3, 1) * Simd32x4::from([0.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group3()[3]) * swizzle!(other.group2(), 2, 2, 1, 2) * Simd32x4::from([0.0, 1.0, -1.0, 0.0]) + self.group0() * Simd32x4::from(other.group1()[0]) * Simd32x4::from([0.0, -1.0, -1.0, -1.0]), g2: Simd32x4::from(self.group0()[0]) * other.group2() + Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group2()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group2()[3]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group2()[0]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group2()[1]) * swizzle!(other.group0(), 1, 0, 1, 1) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group2()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group2()[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.group2(), 1, 0, 0, 0) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]), g3: Simd32x4::from(self.group0()[0]) * other.group3() + Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group3()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group3()[3]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[0]) * other.group2() + Simd32x4::from(self.group1()[1]) * Simd32x4::from(other.group2()[1]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from(other.group2()[2]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from(other.group2()[3]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group2()[0]) * Simd32x4::from(other.group1()[0]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group2()[1]) * swizzle!(other.group1(), 1, 0, 1, 1) * Simd32x4::from([1.0, -1.0, 0.0, 0.0]) + Simd32x4::from(self.group2()[2]) * swizzle!(other.group1(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, -1.0, 0.0]) + Simd32x4::from(self.group2()[3]) * swizzle!(other.group1(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, -1.0]) + Simd32x4::from(self.group3()[0]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group3()[1]) * swizzle!(other.group0(), 1, 0, 1, 1) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group3()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group3()[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.group3(), 1, 0, 0, 0) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
1392    }
1393}
1394
1395impl InnerProduct<MultiVector> for MultiVector {
1396    type Output = MultiVector;
1397
1398    fn inner_product(self, other: MultiVector) -> MultiVector {
1399        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([-1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 1.0]) + Simd32x4::from(self.group2()[0]) * other.group2() * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) + Simd32x4::from(self.group2()[1]) * swizzle!(other.group2(), 1, 0, 1, 1) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group2()[2]) * swizzle!(other.group2(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group2()[3]) * swizzle!(other.group2(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, 1.0]) + swizzle!(self.group0(), 1, 1, 0, 0) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]), g1: Simd32x4::from(self.group0()[0]) * other.group1() + Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group1()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group1()[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]) * 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.group2()[0]) * Simd32x4::from(other.group3()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group2()[1]) * swizzle!(other.group3(), 1, 0, 1, 1) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group2()[2]) * swizzle!(other.group3(), 2, 2, 0, 2) * Simd32x4::from([-1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group2()[3]) * swizzle!(other.group3(), 3, 3, 3, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 1.0]) - Simd32x4::from(self.group3()[0]) * other.group2() + Simd32x4::from(self.group3()[1]) * Simd32x4::from(other.group2()[1]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group3()[2]) * Simd32x4::from(other.group2()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group3()[3]) * Simd32x4::from(other.group2()[3]) * Simd32x4::from([1.0, 0.0, 0.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]), g2: Simd32x4::from(self.group0()[0]) * other.group2() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group2(), 3, 3, 0, 1) * Simd32x4::from([0.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group2(), 2, 2, 1, 0) * Simd32x4::from([0.0, 1.0, -1.0, -1.0]) + Simd32x4::from(self.group2()[0]) * other.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) + Simd32x4::from(self.group2()[1]) * swizzle!(other.group0(), 0, 0, 3, 2) * Simd32x4::from([0.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group2()[2]) * swizzle!(other.group0(), 3, 3, 0, 1) * Simd32x4::from([0.0, -1.0, 1.0, 1.0]) + Simd32x4::from(self.group2()[3]) * swizzle!(other.group0(), 2, 2, 1, 0) * Simd32x4::from([0.0, 1.0, -1.0, 1.0]) + swizzle!(self.group0(), 0, 1, 1, 1) * swizzle!(other.group2(), 0, 0, 3, 2) * Simd32x4::from([0.0, -1.0, 1.0, -1.0]), g3: Simd32x4::from(self.group0()[0]) * other.group3() + Simd32x4::from(self.group1()[1]) * swizzle!(other.group2(), 3, 3, 3, 2) * Simd32x4::from([0.0, 0.0, -1.0, 1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group2(), 3, 3, 3, 1) * Simd32x4::from([0.0, 1.0, 0.0, -1.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group2(), 2, 2, 1, 2) * Simd32x4::from([0.0, -1.0, 1.0, 0.0]) + Simd32x4::from(self.group2()[1]) * swizzle!(other.group1(), 3, 3, 3, 2) * Simd32x4::from([0.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group2()[2]) * swizzle!(other.group1(), 3, 3, 3, 1) * Simd32x4::from([0.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group2()[3]) * swizzle!(other.group1(), 2, 2, 1, 2) * Simd32x4::from([0.0, 1.0, -1.0, 0.0]) + Simd32x4::from(self.group3()[0]) * other.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) + Simd32x4::from(self.group3()[1]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group3()[2]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group3()[3]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, 0.0, 1.0]) + self.group0() * Simd32x4::from(other.group3()[0]) * Simd32x4::from([0.0, -1.0, -1.0, -1.0]) } }
1400    }
1401}
1402
1403impl LeftContraction<MultiVector> for MultiVector {
1404    type Output = MultiVector;
1405
1406    fn left_contraction(self, other: MultiVector) -> MultiVector {
1407        MultiVector { groups: MultiVectorGroups { 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]) + Simd32x4::from(self.group2()[0]) * Simd32x4::from(other.group2()[0]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group2()[1]) * swizzle!(other.group2(), 1, 0, 1, 1) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group2()[2]) * swizzle!(other.group2(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group2()[3]) * swizzle!(other.group2(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, 1.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]) * Simd32x4::from(other.group1()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group1()[3]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group2()[0]) * Simd32x4::from(other.group3()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group2()[1]) * swizzle!(other.group3(), 1, 0, 1, 1) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group2()[2]) * swizzle!(other.group3(), 2, 2, 0, 2) * Simd32x4::from([-1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group2()[3]) * swizzle!(other.group3(), 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]), g2: Simd32x4::from(self.group0()[0]) * other.group2() + Simd32x4::from(self.group2()[1]) * swizzle!(other.group0(), 3, 3, 3, 2) * Simd32x4::from([0.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group2()[2]) * swizzle!(other.group0(), 3, 3, 3, 1) * Simd32x4::from([0.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group2()[3]) * swizzle!(other.group0(), 2, 2, 1, 2) * Simd32x4::from([0.0, 1.0, -1.0, 0.0]) + self.group0() * Simd32x4::from(other.group2()[0]) * Simd32x4::from([0.0, -1.0, -1.0, -1.0]), g3: Simd32x4::from(self.group0()[0]) * other.group3() + Simd32x4::from(self.group2()[1]) * swizzle!(other.group1(), 3, 3, 3, 2) * Simd32x4::from([0.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group2()[2]) * swizzle!(other.group1(), 3, 3, 3, 1) * Simd32x4::from([0.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group2()[3]) * swizzle!(other.group1(), 2, 2, 1, 2) * Simd32x4::from([0.0, 1.0, -1.0, 0.0]) + self.group0() * Simd32x4::from(other.group3()[0]) * Simd32x4::from([0.0, -1.0, -1.0, -1.0]) } }
1408    }
1409}
1410
1411impl RightContraction<MultiVector> for MultiVector {
1412    type Output = MultiVector;
1413
1414    fn right_contraction(self, other: MultiVector) -> MultiVector {
1415        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()[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.group2()[0]) * other.group2() * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) + Simd32x4::from(self.group2()[1]) * Simd32x4::from(other.group2()[1]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group2()[2]) * Simd32x4::from(other.group2()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group2()[3]) * Simd32x4::from(other.group2()[3]) * Simd32x4::from([1.0, 0.0, 0.0, 0.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, 1, 1) * Simd32x4::from([1.0, 1.0, 0.0, 0.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.group3()[0]) * other.group2() + Simd32x4::from(self.group3()[1]) * Simd32x4::from(other.group2()[1]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group3()[2]) * Simd32x4::from(other.group2()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group3()[3]) * Simd32x4::from(other.group2()[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]), g2: Simd32x4::from(self.group0()[2]) * swizzle!(other.group2(), 3, 3, 3, 1) * Simd32x4::from([0.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group2(), 2, 2, 1, 2) * Simd32x4::from([0.0, 1.0, -1.0, 0.0]) + Simd32x4::from(self.group2()[0]) * other.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) + Simd32x4::from(self.group2()[2]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group2()[3]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, 0.0, 1.0]) + Simd32x4::from([self.group0()[0], self.group2()[1], self.group0()[1], self.group0()[1]]) * Simd32x4::from([other.group2()[0], other.group0()[0], other.group2()[3], other.group2()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, -1.0]), g3: Simd32x4::from(self.group1()[2]) * swizzle!(other.group2(), 3, 3, 3, 1) * Simd32x4::from([0.0, 1.0, 0.0, -1.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group2(), 2, 2, 1, 2) * Simd32x4::from([0.0, -1.0, 1.0, 0.0]) + Simd32x4::from(self.group3()[0]) * other.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) + Simd32x4::from(self.group3()[2]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group3()[3]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, 0.0, 1.0]) + Simd32x4::from([self.group1()[0], self.group3()[1], self.group1()[1], self.group1()[1]]) * Simd32x4::from([other.group2()[0], other.group0()[0], other.group2()[3], other.group2()[2]]) * Simd32x4::from([0.0, 1.0, -1.0, 1.0]) } }
1416    }
1417}
1418
1419impl ScalarProduct<MultiVector> for MultiVector {
1420    type Output = f32;
1421
1422    fn scalar_product(self, other: MultiVector) -> f32 {
1423        self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group0()[1] - self.group0()[2] * other.group0()[2] - self.group0()[3] * other.group0()[3] - self.group2()[0] * other.group2()[0] + self.group2()[1] * other.group2()[1] + self.group2()[2] * other.group2()[2] + self.group2()[3] * other.group2()[3]
1424    }
1425}
1426
1427impl Into<Rotor> for MultiVector {
1428    fn into(self) -> Rotor {
1429        Rotor { groups: RotorGroups { g0: self.group0() } }
1430    }
1431}
1432
1433impl Add<Rotor> for MultiVector {
1434    type Output = MultiVector;
1435
1436    fn add(self, other: Rotor) -> MultiVector {
1437        MultiVector { groups: MultiVectorGroups { g0: self.group0() + other.group0(), g1: self.group1(), g2: self.group2(), g3: self.group3() } }
1438    }
1439}
1440
1441impl AddAssign<Rotor> for MultiVector {
1442    fn add_assign(&mut self, other: Rotor) {
1443        *self = (*self).add(other);
1444    }
1445}
1446
1447impl Sub<Rotor> for MultiVector {
1448    type Output = MultiVector;
1449
1450    fn sub(self, other: Rotor) -> MultiVector {
1451        MultiVector { groups: MultiVectorGroups { g0: self.group0() - other.group0(), g1: self.group1(), g2: self.group2(), g3: self.group3() } }
1452    }
1453}
1454
1455impl SubAssign<Rotor> for MultiVector {
1456    fn sub_assign(&mut self, other: Rotor) {
1457        *self = (*self).sub(other);
1458    }
1459}
1460
1461impl GeometricProduct<Rotor> for MultiVector {
1462    type Output = MultiVector;
1463
1464    fn geometric_product(self, other: Rotor) -> MultiVector {
1465        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([-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]), g1: 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]), g2: Simd32x4::from(self.group2()[0]) * other.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) + Simd32x4::from(self.group2()[1]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group2()[2]) * swizzle!(other.group0(), 2, 3, 0, 1) * Simd32x4::from([1.0, -1.0, 1.0, 1.0]) + Simd32x4::from(self.group2()[3]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([1.0, 1.0, -1.0, 1.0]), g3: Simd32x4::from(self.group3()[0]) * other.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) + Simd32x4::from(self.group3()[1]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group3()[2]) * swizzle!(other.group0(), 2, 3, 0, 1) * Simd32x4::from([1.0, -1.0, 1.0, 1.0]) + Simd32x4::from(self.group3()[3]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([1.0, 1.0, -1.0, 1.0]) } }
1466    }
1467}
1468
1469impl OuterProduct<Rotor> for MultiVector {
1470    type Output = MultiVector;
1471
1472    fn outer_product(self, other: Rotor) -> MultiVector {
1473        MultiVector { groups: MultiVectorGroups { 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]), g1: Simd32x4::from(self.group1()[0]) * other.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) + self.group1() * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]), g2: Simd32x4::from(self.group2()[1]) * swizzle!(other.group0(), 1, 0, 1, 1) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group2()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group2()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, 1.0]) + Simd32x4::from(self.group2()[0]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]), g3: Simd32x4::from(self.group3()[1]) * swizzle!(other.group0(), 1, 0, 1, 1) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group3()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group3()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, 1.0]) + Simd32x4::from(self.group3()[0]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
1474    }
1475}
1476
1477impl InnerProduct<Rotor> for MultiVector {
1478    type Output = MultiVector;
1479
1480    fn inner_product(self, other: Rotor) -> MultiVector {
1481        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([-1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 1.0]) + swizzle!(self.group0(), 1, 1, 0, 0) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]), g1: 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(), 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]), g2: Simd32x4::from(self.group2()[0]) * other.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) + Simd32x4::from(self.group2()[2]) * swizzle!(other.group0(), 3, 3, 0, 1) * Simd32x4::from([0.0, -1.0, 1.0, 1.0]) + Simd32x4::from(self.group2()[3]) * swizzle!(other.group0(), 2, 2, 1, 0) * Simd32x4::from([0.0, 1.0, -1.0, 1.0]) + swizzle!(self.group2(), 0, 1, 1, 1) * swizzle!(other.group0(), 0, 0, 3, 2) * Simd32x4::from([0.0, 1.0, 1.0, -1.0]), g3: Simd32x4::from(self.group3()[0]) * other.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) + self.group3() * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
1482    }
1483}
1484
1485impl RightContraction<Rotor> for MultiVector {
1486    type Output = MultiVector;
1487
1488    fn right_contraction(self, other: Rotor) -> MultiVector {
1489        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()[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, 1, 1) * Simd32x4::from([1.0, 1.0, 0.0, 0.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]), g2: Simd32x4::from(self.group2()[0]) * other.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) + self.group2() * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]), g3: Simd32x4::from(self.group3()[0]) * other.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) + self.group3() * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
1490    }
1491}
1492
1493impl ScalarProduct<Rotor> for MultiVector {
1494    type Output = f32;
1495
1496    fn scalar_product(self, other: Rotor) -> f32 {
1497        self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group0()[1] - self.group0()[2] * other.group0()[2] - self.group0()[3] * other.group0()[3]
1498    }
1499}
1500
1501impl Into<Point> for MultiVector {
1502    fn into(self) -> Point {
1503        Point { groups: PointGroups { g0: Simd32x4::from([self.group2()[0], self.group1()[1], self.group1()[2], self.group1()[3]]) } }
1504    }
1505}
1506
1507impl Add<Point> for MultiVector {
1508    type Output = MultiVector;
1509
1510    fn add(self, other: Point) -> MultiVector {
1511        MultiVector { groups: MultiVectorGroups { g0: self.group0(), g1: self.group1() + other.group0() * Simd32x4::from([0.0, 1.0, 1.0, 1.0]), g2: self.group2() + Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]), g3: self.group3() } }
1512    }
1513}
1514
1515impl AddAssign<Point> for MultiVector {
1516    fn add_assign(&mut self, other: Point) {
1517        *self = (*self).add(other);
1518    }
1519}
1520
1521impl Sub<Point> for MultiVector {
1522    type Output = MultiVector;
1523
1524    fn sub(self, other: Point) -> MultiVector {
1525        MultiVector { groups: MultiVectorGroups { g0: self.group0(), g1: self.group1() - other.group0() * Simd32x4::from([0.0, 1.0, 1.0, 1.0]), g2: self.group2() - Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]), g3: self.group3() } }
1526    }
1527}
1528
1529impl SubAssign<Point> for MultiVector {
1530    fn sub_assign(&mut self, other: Point) {
1531        *self = (*self).sub(other);
1532    }
1533}
1534
1535impl GeometricProduct<Point> for MultiVector {
1536    type Output = MultiVector;
1537
1538    fn geometric_product(self, other: Point) -> MultiVector {
1539        MultiVector { groups: MultiVectorGroups { g0: self.group2() * Simd32x4::from(other.group0()[0]) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]), g1: Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 1, 1, 3, 2) * Simd32x4::from([1.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 3, 2, 1) * Simd32x4::from([1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 2, 1, 3) * Simd32x4::from([1.0, 1.0, -1.0, 0.0]) + Simd32x4::from(self.group3()[1]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, -1.0, 0.0, 0.0]) + Simd32x4::from(self.group3()[2]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, -1.0, 0.0]) + Simd32x4::from(self.group3()[3]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, 0.0, -1.0]) + Simd32x4::from([self.group3()[0], self.group0()[0], self.group0()[0], self.group0()[0]]) * other.group0() * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]), g2: self.group0() * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, -1.0, -1.0, -1.0]), g3: Simd32x4::from(self.group2()[0]) * swizzle!(other.group0(), 1, 1, 2, 3) * Simd32x4::from([0.0, -1.0, -1.0, -1.0]) + Simd32x4::from(self.group2()[1]) * swizzle!(other.group0(), 1, 1, 3, 2) * Simd32x4::from([1.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group2()[2]) * swizzle!(other.group0(), 2, 3, 2, 1) * Simd32x4::from([1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group2()[3]) * swizzle!(other.group0(), 3, 2, 1, 3) * Simd32x4::from([1.0, 1.0, -1.0, 0.0]) + self.group1() * Simd32x4::from(other.group0()[0]) } }
1540    }
1541}
1542
1543impl ScalarProduct<Point> for MultiVector {
1544    type Output = f32;
1545
1546    fn scalar_product(self, other: Point) -> f32 {
1547        0.0 - self.group2()[0] * other.group0()[0]
1548    }
1549}
1550
1551impl Into<IdealPoint> for MultiVector {
1552    fn into(self) -> IdealPoint {
1553        IdealPoint { groups: IdealPointGroups { g0: Simd32x3::from([self.group3()[1], self.group3()[2], self.group3()[3]]) } }
1554    }
1555}
1556
1557impl Add<IdealPoint> for MultiVector {
1558    type Output = MultiVector;
1559
1560    fn add(self, other: IdealPoint) -> MultiVector {
1561        MultiVector { groups: MultiVectorGroups { g0: self.group0(), g1: self.group1(), g2: self.group2(), g3: self.group3() + Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
1562    }
1563}
1564
1565impl AddAssign<IdealPoint> for MultiVector {
1566    fn add_assign(&mut self, other: IdealPoint) {
1567        *self = (*self).add(other);
1568    }
1569}
1570
1571impl Sub<IdealPoint> for MultiVector {
1572    type Output = MultiVector;
1573
1574    fn sub(self, other: IdealPoint) -> MultiVector {
1575        MultiVector { groups: MultiVectorGroups { g0: self.group0(), g1: self.group1(), g2: self.group2(), g3: self.group3() - Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
1576    }
1577}
1578
1579impl SubAssign<IdealPoint> for MultiVector {
1580    fn sub_assign(&mut self, other: IdealPoint) {
1581        *self = (*self).sub(other);
1582    }
1583}
1584
1585impl Into<Plane> for MultiVector {
1586    fn into(self) -> Plane {
1587        Plane { groups: PlaneGroups { g0: Simd32x4::from([self.group1()[0], self.group2()[1], self.group2()[2], self.group2()[3]]) } }
1588    }
1589}
1590
1591impl Add<Plane> for MultiVector {
1592    type Output = MultiVector;
1593
1594    fn add(self, other: Plane) -> MultiVector {
1595        MultiVector { groups: MultiVectorGroups { g0: self.group0(), g1: self.group1() + Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]), g2: self.group2() + other.group0() * Simd32x4::from([0.0, 1.0, 1.0, 1.0]), g3: self.group3() } }
1596    }
1597}
1598
1599impl AddAssign<Plane> for MultiVector {
1600    fn add_assign(&mut self, other: Plane) {
1601        *self = (*self).add(other);
1602    }
1603}
1604
1605impl Sub<Plane> for MultiVector {
1606    type Output = MultiVector;
1607
1608    fn sub(self, other: Plane) -> MultiVector {
1609        MultiVector { groups: MultiVectorGroups { g0: self.group0(), g1: self.group1() - Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]), g2: self.group2() - other.group0() * Simd32x4::from([0.0, 1.0, 1.0, 1.0]), g3: self.group3() } }
1610    }
1611}
1612
1613impl SubAssign<Plane> for MultiVector {
1614    fn sub_assign(&mut self, other: Plane) {
1615        *self = (*self).sub(other);
1616    }
1617}
1618
1619impl GeometricProduct<Plane> for MultiVector {
1620    type Output = MultiVector;
1621
1622    fn geometric_product(self, other: Plane) -> MultiVector {
1623        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group2()[1]) * swizzle!(other.group0(), 1, 1, 3, 2) * Simd32x4::from([1.0, 0.0, -1.0, 1.0]) + Simd32x4::from(self.group2()[2]) * swizzle!(other.group0(), 2, 3, 2, 1) * Simd32x4::from([1.0, 1.0, 0.0, -1.0]) + Simd32x4::from(self.group2()[3]) * swizzle!(other.group0(), 3, 2, 1, 3) * Simd32x4::from([1.0, -1.0, 1.0, 0.0]) + Simd32x4::from(self.group2()[0]) * other.group0() * Simd32x4::from([0.0, 1.0, 1.0, 1.0]), g1: Simd32x4::from(self.group3()[0]) * swizzle!(other.group0(), 1, 1, 2, 3) * Simd32x4::from([0.0, -1.0, -1.0, -1.0]) + Simd32x4::from(self.group3()[1]) * swizzle!(other.group0(), 1, 1, 3, 2) * Simd32x4::from([1.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group3()[2]) * swizzle!(other.group0(), 2, 3, 2, 1) * Simd32x4::from([1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group3()[3]) * swizzle!(other.group0(), 3, 2, 1, 3) * Simd32x4::from([1.0, 1.0, -1.0, 0.0]) + self.group0() * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, -1.0, -1.0, -1.0]), g2: Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 1, 1, 3, 2) * Simd32x4::from([1.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 3, 2, 1) * Simd32x4::from([1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 2, 1, 3) * Simd32x4::from([1.0, 1.0, -1.0, 0.0]) + Simd32x4::from(self.group0()[0]) * other.group0() * Simd32x4::from([0.0, 1.0, 1.0, 1.0]), g3: Simd32x4::from(self.group1()[1]) * swizzle!(other.group0(), 1, 1, 3, 2) * Simd32x4::from([-1.0, 0.0, -1.0, 1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group0(), 2, 3, 2, 1) * Simd32x4::from([-1.0, 1.0, 0.0, -1.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group0(), 3, 2, 1, 3) * Simd32x4::from([-1.0, -1.0, 1.0, 0.0]) + Simd32x4::from(self.group2()[1]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, -1.0, 0.0, 0.0]) + Simd32x4::from(self.group2()[2]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, -1.0, 0.0]) + Simd32x4::from(self.group2()[3]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, 0.0, -1.0]) + Simd32x4::from([self.group2()[0], self.group1()[0], self.group1()[0], self.group1()[0]]) * other.group0() * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) } }
1624    }
1625}
1626
1627impl ScalarProduct<Plane> for MultiVector {
1628    type Output = f32;
1629
1630    fn scalar_product(self, other: Plane) -> f32 {
1631        self.group2()[1] * other.group0()[1] + self.group2()[2] * other.group0()[2] + self.group2()[3] * other.group0()[3]
1632    }
1633}
1634
1635impl Into<Line> for MultiVector {
1636    fn into(self) -> Line {
1637        Line { groups: LineGroups { g0: Simd32x3::from([self.group3()[1], self.group3()[2], self.group3()[3]]), g1: Simd32x3::from([self.group0()[1], self.group0()[2], self.group0()[3]]) } }
1638    }
1639}
1640
1641impl Add<Line> for MultiVector {
1642    type Output = MultiVector;
1643
1644    fn add(self, other: Line) -> MultiVector {
1645        MultiVector { groups: MultiVectorGroups { g0: self.group0() + Simd32x4::from([other.group0()[0], other.group1()[0], other.group1()[1], other.group1()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]), g1: self.group1(), g2: self.group2(), g3: self.group3() + Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
1646    }
1647}
1648
1649impl AddAssign<Line> for MultiVector {
1650    fn add_assign(&mut self, other: Line) {
1651        *self = (*self).add(other);
1652    }
1653}
1654
1655impl Sub<Line> for MultiVector {
1656    type Output = MultiVector;
1657
1658    fn sub(self, other: Line) -> MultiVector {
1659        MultiVector { groups: MultiVectorGroups { g0: self.group0() - Simd32x4::from([other.group0()[0], other.group1()[0], other.group1()[1], other.group1()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]), g1: self.group1(), g2: self.group2(), g3: self.group3() - Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
1660    }
1661}
1662
1663impl SubAssign<Line> for MultiVector {
1664    fn sub_assign(&mut self, other: Line) {
1665        *self = (*self).sub(other);
1666    }
1667}
1668
1669impl GeometricProduct<Line> for MultiVector {
1670    type Output = MultiVector;
1671
1672    fn geometric_product(self, other: Line) -> MultiVector {
1673        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group1()[0], other.group1()[0], other.group1()[2], other.group1()[1]]) * Simd32x4::from([-1.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group1()[1], other.group1()[2], other.group1()[1], other.group1()[0]]) * Simd32x4::from([-1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group1()[2], other.group1()[1], other.group1()[0], other.group1()[2]]) * Simd32x4::from([-1.0, 1.0, -1.0, 0.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group1()[0], other.group1()[0], other.group1()[1], other.group1()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]), g1: Simd32x4::from(self.group1()[1]) * Simd32x4::from([other.group1()[0], other.group1()[0], other.group1()[2], other.group1()[1]]) * Simd32x4::from([1.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from([other.group1()[1], other.group1()[2], other.group1()[1], other.group1()[0]]) * Simd32x4::from([1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from([other.group1()[2], other.group1()[1], other.group1()[0], other.group1()[2]]) * Simd32x4::from([1.0, 1.0, -1.0, 0.0]) + Simd32x4::from(self.group2()[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]) + Simd32x4::from(self.group2()[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.group2()[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.group2()[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.group1()[0]) * Simd32x4::from([other.group1()[0], other.group1()[0], other.group1()[1], other.group1()[2]]) * Simd32x4::from([0.0, -1.0, -1.0, -1.0]), g2: Simd32x4::from(self.group2()[1]) * Simd32x4::from([other.group1()[0], other.group1()[0], other.group1()[2], other.group1()[1]]) * Simd32x4::from([1.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group2()[2]) * Simd32x4::from([other.group1()[1], other.group1()[2], other.group1()[1], other.group1()[0]]) * Simd32x4::from([1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group2()[3]) * Simd32x4::from([other.group1()[2], other.group1()[1], other.group1()[0], other.group1()[2]]) * Simd32x4::from([1.0, 1.0, -1.0, 0.0]) + Simd32x4::from(self.group2()[0]) * Simd32x4::from([other.group1()[0], other.group1()[0], other.group1()[1], other.group1()[2]]) * Simd32x4::from([0.0, -1.0, -1.0, -1.0]), g3: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[2], other.group0()[1]]) * Simd32x4::from([1.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[1], other.group0()[2], other.group0()[1], other.group0()[0]]) * Simd32x4::from([1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[2], other.group0()[1], other.group0()[0], other.group0()[2]]) * Simd32x4::from([1.0, 1.0, -1.0, 0.0]) + Simd32x4::from(self.group3()[0]) * Simd32x4::from([other.group1()[0], other.group1()[0], other.group1()[1], other.group1()[2]]) * Simd32x4::from([0.0, -1.0, -1.0, -1.0]) + Simd32x4::from(self.group3()[1]) * Simd32x4::from([other.group1()[0], other.group1()[0], other.group1()[2], other.group1()[1]]) * Simd32x4::from([1.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group3()[2]) * Simd32x4::from([other.group1()[1], other.group1()[2], other.group1()[1], other.group1()[0]]) * Simd32x4::from([1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group3()[3]) * Simd32x4::from([other.group1()[2], other.group1()[1], other.group1()[0], other.group1()[2]]) * Simd32x4::from([1.0, 1.0, -1.0, 0.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
1674    }
1675}
1676
1677impl ScalarProduct<Line> for MultiVector {
1678    type Output = f32;
1679
1680    fn scalar_product(self, other: Line) -> f32 {
1681        0.0 - self.group0()[1] * other.group1()[0] - self.group0()[2] * other.group1()[1] - self.group0()[3] * other.group1()[2]
1682    }
1683}
1684
1685impl Into<Translator> for MultiVector {
1686    fn into(self) -> Translator {
1687        Translator { groups: TranslatorGroups { g0: Simd32x4::from([self.group0()[0], self.group3()[1], self.group3()[2], self.group3()[3]]) } }
1688    }
1689}
1690
1691impl Add<Translator> for MultiVector {
1692    type Output = MultiVector;
1693
1694    fn add(self, other: Translator) -> MultiVector {
1695        MultiVector { groups: MultiVectorGroups { g0: self.group0() + Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]), g1: self.group1(), g2: self.group2(), g3: self.group3() + other.group0() * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
1696    }
1697}
1698
1699impl AddAssign<Translator> for MultiVector {
1700    fn add_assign(&mut self, other: Translator) {
1701        *self = (*self).add(other);
1702    }
1703}
1704
1705impl Sub<Translator> for MultiVector {
1706    type Output = MultiVector;
1707
1708    fn sub(self, other: Translator) -> MultiVector {
1709        MultiVector { groups: MultiVectorGroups { g0: self.group0() - Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]), g1: self.group1(), g2: self.group2(), g3: self.group3() - other.group0() * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
1710    }
1711}
1712
1713impl SubAssign<Translator> for MultiVector {
1714    fn sub_assign(&mut self, other: Translator) {
1715        *self = (*self).sub(other);
1716    }
1717}
1718
1719impl GeometricProduct<Translator> for MultiVector {
1720    type Output = MultiVector;
1721
1722    fn geometric_product(self, other: Translator) -> MultiVector {
1723        MultiVector { groups: MultiVectorGroups { g0: self.group0() * Simd32x4::from(other.group0()[0]), g1: Simd32x4::from(self.group2()[0]) * swizzle!(other.group0(), 1, 1, 2, 3) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) + Simd32x4::from(self.group2()[1]) * swizzle!(other.group0(), 1, 1, 3, 2) * Simd32x4::from([-1.0, 0.0, -1.0, 1.0]) + Simd32x4::from(self.group2()[2]) * swizzle!(other.group0(), 2, 3, 2, 1) * Simd32x4::from([-1.0, 1.0, 0.0, -1.0]) + Simd32x4::from(self.group2()[3]) * swizzle!(other.group0(), 3, 2, 1, 3) * Simd32x4::from([-1.0, -1.0, 1.0, 0.0]) + self.group1() * Simd32x4::from(other.group0()[0]), g2: self.group2() * Simd32x4::from(other.group0()[0]), g3: Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 1, 1, 3, 2) * Simd32x4::from([1.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 3, 2, 1) * Simd32x4::from([1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 2, 1, 3) * Simd32x4::from([1.0, 1.0, -1.0, 0.0]) + Simd32x4::from(self.group3()[1]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group3()[2]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group3()[3]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, 0.0, 1.0]) + Simd32x4::from([self.group3()[0], self.group0()[0], self.group0()[0], self.group0()[0]]) * other.group0() } }
1724    }
1725}
1726
1727impl OuterProduct<Translator> for MultiVector {
1728    type Output = MultiVector;
1729
1730    fn outer_product(self, other: Translator) -> MultiVector {
1731        MultiVector { groups: MultiVectorGroups { g0: self.group0() * Simd32x4::from(other.group0()[0]), g1: Simd32x4::from(self.group2()[1]) * swizzle!(other.group0(), 3, 3, 3, 2) * Simd32x4::from([0.0, 0.0, -1.0, 1.0]) + Simd32x4::from(self.group2()[2]) * swizzle!(other.group0(), 3, 3, 3, 1) * Simd32x4::from([0.0, 1.0, 0.0, -1.0]) + Simd32x4::from(self.group2()[3]) * swizzle!(other.group0(), 2, 2, 1, 2) * Simd32x4::from([0.0, -1.0, 1.0, 0.0]) + self.group1() * Simd32x4::from(other.group0()[0]), g2: self.group2() * Simd32x4::from(other.group0()[0]), g3: 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]) + Simd32x4::from(self.group3()[0]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group3()[1]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group3()[2]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group3()[3]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, 0.0, 1.0]) + swizzle!(self.group0(), 1, 0, 0, 0) * swizzle!(other.group0(), 1, 1, 2, 3) } }
1732    }
1733}
1734
1735impl InnerProduct<Translator> for MultiVector {
1736    type Output = MultiVector;
1737
1738    fn inner_product(self, other: Translator) -> MultiVector {
1739        MultiVector { groups: MultiVectorGroups { g0: self.group0() * Simd32x4::from(other.group0()[0]), g1: Simd32x4::from(self.group2()[1]) * Simd32x4::from(other.group0()[1]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group2()[2]) * Simd32x4::from(other.group0()[2]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group2()[3]) * Simd32x4::from(other.group0()[3]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + self.group1() * Simd32x4::from(other.group0()[0]), g2: self.group2() * Simd32x4::from(other.group0()[0]), g3: Simd32x4::from(self.group3()[1]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group3()[2]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group3()[3]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, 0.0, 1.0]) + Simd32x4::from([self.group3()[0], self.group0()[0], self.group0()[0], self.group0()[0]]) * other.group0() } }
1740    }
1741}
1742
1743impl RightContraction<Translator> for MultiVector {
1744    type Output = MultiVector;
1745
1746    fn right_contraction(self, other: Translator) -> MultiVector {
1747        MultiVector { groups: MultiVectorGroups { g0: self.group0() * Simd32x4::from(other.group0()[0]), g1: self.group1() * Simd32x4::from(other.group0()[0]), g2: self.group2() * Simd32x4::from(other.group0()[0]), g3: self.group3() * Simd32x4::from(other.group0()[0]) } }
1748    }
1749}
1750
1751impl ScalarProduct<Translator> for MultiVector {
1752    type Output = f32;
1753
1754    fn scalar_product(self, other: Translator) -> f32 {
1755        self.group0()[0] * other.group0()[0]
1756    }
1757}
1758
1759impl Into<Motor> for MultiVector {
1760    fn into(self) -> Motor {
1761        Motor { groups: MotorGroups { g0: self.group0(), g1: self.group3() } }
1762    }
1763}
1764
1765impl Add<Motor> for MultiVector {
1766    type Output = MultiVector;
1767
1768    fn add(self, other: Motor) -> MultiVector {
1769        MultiVector { groups: MultiVectorGroups { g0: self.group0() + other.group0(), g1: self.group1(), g2: self.group2(), g3: self.group3() + other.group1() } }
1770    }
1771}
1772
1773impl AddAssign<Motor> for MultiVector {
1774    fn add_assign(&mut self, other: Motor) {
1775        *self = (*self).add(other);
1776    }
1777}
1778
1779impl Sub<Motor> for MultiVector {
1780    type Output = MultiVector;
1781
1782    fn sub(self, other: Motor) -> MultiVector {
1783        MultiVector { groups: MultiVectorGroups { g0: self.group0() - other.group0(), g1: self.group1(), g2: self.group2(), g3: self.group3() - other.group1() } }
1784    }
1785}
1786
1787impl SubAssign<Motor> for MultiVector {
1788    fn sub_assign(&mut self, other: Motor) {
1789        *self = (*self).sub(other);
1790    }
1791}
1792
1793impl GeometricProduct<Motor> for MultiVector {
1794    type Output = MultiVector;
1795
1796    fn geometric_product(self, other: Motor) -> MultiVector {
1797        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([-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]), g1: 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]) + Simd32x4::from(self.group2()[0]) * other.group1() + Simd32x4::from(self.group2()[1]) * swizzle!(other.group1(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, -1.0, 1.0]) + Simd32x4::from(self.group2()[2]) * swizzle!(other.group1(), 2, 3, 0, 1) * Simd32x4::from([-1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group2()[3]) * swizzle!(other.group1(), 3, 2, 1, 0) * Simd32x4::from([-1.0, -1.0, 1.0, 1.0]), g2: Simd32x4::from(self.group2()[0]) * other.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) + Simd32x4::from(self.group2()[1]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group2()[2]) * swizzle!(other.group0(), 2, 3, 0, 1) * Simd32x4::from([1.0, -1.0, 1.0, 1.0]) + Simd32x4::from(self.group2()[3]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([1.0, 1.0, -1.0, 1.0]), g3: 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([1.0, 1.0, -1.0, -1.0]) + Simd32x4::from(self.group3()[0]) * other.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) + Simd32x4::from(self.group3()[1]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group3()[2]) * swizzle!(other.group0(), 2, 3, 0, 1) * Simd32x4::from([1.0, -1.0, 1.0, 1.0]) + Simd32x4::from(self.group3()[3]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([1.0, 1.0, -1.0, 1.0]) } }
1798    }
1799}
1800
1801impl RegressiveProduct<Motor> for MultiVector {
1802    type Output = MultiVector;
1803
1804    fn regressive_product(self, other: Motor) -> MultiVector {
1805        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[1]) * swizzle!(other.group1(), 1, 0, 1, 1) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group1(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group1(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, 1.0]) + Simd32x4::from(self.group3()[0]) * other.group0() + Simd32x4::from(self.group3()[1]) * Simd32x4::from(other.group0()[1]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group3()[2]) * Simd32x4::from(other.group0()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group3()[3]) * Simd32x4::from(other.group0()[3]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from(other.group1()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]), g1: Simd32x4::from(self.group1()[1]) * swizzle!(other.group1(), 1, 0, 1, 1) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group1(), 2, 2, 0, 2) * Simd32x4::from([-1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group1(), 3, 3, 3, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 1.0]) + Simd32x4::from(self.group1()[0]) * Simd32x4::from(other.group1()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]), g2: Simd32x4::from(self.group1()[2]) * swizzle!(other.group0(), 3, 3, 3, 1) * Simd32x4::from([0.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group0(), 2, 2, 1, 2) * Simd32x4::from([0.0, 1.0, -1.0, 0.0]) + Simd32x4::from(self.group2()[0]) * other.group1() + Simd32x4::from(self.group2()[2]) * Simd32x4::from(other.group1()[0]) * Simd32x4::from([0.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group2()[3]) * Simd32x4::from(other.group1()[0]) * Simd32x4::from([0.0, 0.0, 0.0, 1.0]) + Simd32x4::from([self.group1()[0], self.group2()[1], self.group1()[1], self.group1()[1]]) * Simd32x4::from([other.group0()[0], other.group1()[0], other.group0()[3], other.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, -1.0]), g3: Simd32x4::from(self.group3()[0]) * other.group1() + self.group3() * Simd32x4::from(other.group1()[0]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
1806    }
1807}
1808
1809impl OuterProduct<Motor> for MultiVector {
1810    type Output = MultiVector;
1811
1812    fn outer_product(self, other: Motor) -> MultiVector {
1813        MultiVector { groups: MultiVectorGroups { 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]), g1: Simd32x4::from(self.group1()[0]) * other.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) + Simd32x4::from(self.group2()[1]) * swizzle!(other.group1(), 3, 3, 3, 2) * Simd32x4::from([0.0, 0.0, -1.0, 1.0]) + Simd32x4::from(self.group2()[2]) * swizzle!(other.group1(), 3, 3, 3, 1) * Simd32x4::from([0.0, 1.0, 0.0, -1.0]) + Simd32x4::from(self.group2()[3]) * swizzle!(other.group1(), 2, 2, 1, 2) * Simd32x4::from([0.0, -1.0, 1.0, 0.0]) + self.group1() * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]), g2: Simd32x4::from(self.group2()[1]) * swizzle!(other.group0(), 1, 0, 1, 1) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group2()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group2()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, 1.0]) + Simd32x4::from(self.group2()[0]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]), g3: Simd32x4::from(self.group0()[0]) * other.group1() + Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group1()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group1()[3]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group3()[0]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group3()[1]) * swizzle!(other.group0(), 1, 0, 1, 1) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group3()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group3()[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]) } }
1814    }
1815}
1816
1817impl InnerProduct<Motor> for MultiVector {
1818    type Output = MultiVector;
1819
1820    fn inner_product(self, other: Motor) -> MultiVector {
1821        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([-1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 1.0]) + swizzle!(self.group0(), 1, 1, 0, 0) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]), g1: 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(), 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.group2()[0]) * Simd32x4::from(other.group1()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group2()[1]) * swizzle!(other.group1(), 1, 0, 1, 1) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group2()[2]) * swizzle!(other.group1(), 2, 2, 0, 2) * Simd32x4::from([-1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group2()[3]) * swizzle!(other.group1(), 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]), g2: Simd32x4::from(self.group2()[0]) * other.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) + Simd32x4::from(self.group2()[2]) * swizzle!(other.group0(), 3, 3, 0, 1) * Simd32x4::from([0.0, -1.0, 1.0, 1.0]) + Simd32x4::from(self.group2()[3]) * swizzle!(other.group0(), 2, 2, 1, 0) * Simd32x4::from([0.0, 1.0, -1.0, 1.0]) + swizzle!(self.group2(), 0, 1, 1, 1) * swizzle!(other.group0(), 0, 0, 3, 2) * Simd32x4::from([0.0, 1.0, 1.0, -1.0]), g3: Simd32x4::from(self.group0()[0]) * other.group1() + Simd32x4::from(self.group3()[0]) * other.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) + Simd32x4::from(self.group3()[1]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group3()[2]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group3()[3]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 0.0, 0.0, 1.0]) + self.group0() * Simd32x4::from(other.group1()[0]) * Simd32x4::from([0.0, -1.0, -1.0, -1.0]) } }
1822    }
1823}
1824
1825impl RightContraction<Motor> for MultiVector {
1826    type Output = MultiVector;
1827
1828    fn right_contraction(self, other: Motor) -> MultiVector {
1829        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()[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, 1, 1) * Simd32x4::from([1.0, 1.0, 0.0, 0.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]), g2: Simd32x4::from(self.group2()[0]) * other.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) + self.group2() * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]), g3: Simd32x4::from(self.group3()[0]) * other.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) + self.group3() * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
1830    }
1831}
1832
1833impl ScalarProduct<Motor> for MultiVector {
1834    type Output = f32;
1835
1836    fn scalar_product(self, other: Motor) -> f32 {
1837        self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group0()[1] - self.group0()[2] * other.group0()[2] - self.group0()[3] * other.group0()[3]
1838    }
1839}
1840
1841impl Into<PointAndPlane> for MultiVector {
1842    fn into(self) -> PointAndPlane {
1843        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from([self.group2()[0], self.group1()[1], self.group1()[2], self.group1()[3]]), g1: Simd32x4::from([self.group1()[0], self.group2()[1], self.group2()[2], self.group2()[3]]) } }
1844    }
1845}
1846
1847impl Add<PointAndPlane> for MultiVector {
1848    type Output = MultiVector;
1849
1850    fn add(self, other: PointAndPlane) -> MultiVector {
1851        MultiVector { groups: MultiVectorGroups { g0: self.group0(), g1: self.group1() + Simd32x4::from([other.group1()[0], other.group0()[1], other.group0()[2], other.group0()[3]]), g2: self.group2() + Simd32x4::from([other.group0()[0], other.group1()[1], other.group1()[2], other.group1()[3]]), g3: self.group3() } }
1852    }
1853}
1854
1855impl AddAssign<PointAndPlane> for MultiVector {
1856    fn add_assign(&mut self, other: PointAndPlane) {
1857        *self = (*self).add(other);
1858    }
1859}
1860
1861impl Sub<PointAndPlane> for MultiVector {
1862    type Output = MultiVector;
1863
1864    fn sub(self, other: PointAndPlane) -> MultiVector {
1865        MultiVector { groups: MultiVectorGroups { g0: self.group0(), g1: self.group1() - Simd32x4::from([other.group1()[0], other.group0()[1], other.group0()[2], other.group0()[3]]), g2: self.group2() - Simd32x4::from([other.group0()[0], other.group1()[1], other.group1()[2], other.group1()[3]]), g3: self.group3() } }
1866    }
1867}
1868
1869impl SubAssign<PointAndPlane> for MultiVector {
1870    fn sub_assign(&mut self, other: PointAndPlane) {
1871        *self = (*self).sub(other);
1872    }
1873}
1874
1875impl GeometricProduct<PointAndPlane> for MultiVector {
1876    type Output = MultiVector;
1877
1878    fn geometric_product(self, other: PointAndPlane) -> MultiVector {
1879        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group2()[0]) * Simd32x4::from([other.group0()[0], other.group1()[1], other.group1()[2], other.group1()[3]]) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) + Simd32x4::from(self.group2()[1]) * Simd32x4::from([other.group1()[1], other.group0()[0], other.group1()[3], other.group1()[2]]) * Simd32x4::from([1.0, 1.0, -1.0, 1.0]) + Simd32x4::from(self.group2()[2]) * Simd32x4::from([other.group1()[2], other.group1()[3], other.group0()[0], other.group1()[1]]) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group2()[3]) * Simd32x4::from([other.group1()[3], other.group1()[2], other.group1()[1], other.group0()[0]]) * Simd32x4::from([1.0, -1.0, 1.0, 1.0]), g1: Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group1()[0], other.group0()[1], other.group0()[2], other.group0()[3]]) + Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[1], other.group1()[0], other.group0()[3], other.group0()[2]]) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[2], other.group0()[3], other.group1()[0], other.group0()[1]]) * Simd32x4::from([1.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[3], other.group0()[2], other.group0()[1], other.group1()[0]]) * Simd32x4::from([1.0, 1.0, -1.0, -1.0]) - Simd32x4::from(self.group3()[0]) * Simd32x4::from([other.group0()[0], other.group1()[1], other.group1()[2], other.group1()[3]]) + Simd32x4::from(self.group3()[1]) * Simd32x4::from([other.group1()[1], other.group0()[0], other.group1()[3], other.group1()[2]]) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) + Simd32x4::from(self.group3()[2]) * Simd32x4::from([other.group1()[2], other.group1()[3], other.group0()[0], other.group1()[1]]) * Simd32x4::from([1.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group3()[3]) * Simd32x4::from([other.group1()[3], other.group1()[2], other.group1()[1], other.group0()[0]]) * Simd32x4::from([1.0, 1.0, -1.0, -1.0]), g2: Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group0()[0], other.group1()[1], other.group1()[2], other.group1()[3]]) + Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group1()[1], other.group0()[0], other.group1()[3], other.group1()[2]]) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group1()[2], other.group1()[3], other.group0()[0], other.group1()[1]]) * Simd32x4::from([1.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group1()[3], other.group1()[2], other.group1()[1], other.group0()[0]]) * Simd32x4::from([1.0, 1.0, -1.0, -1.0]), g3: Simd32x4::from(self.group1()[0]) * Simd32x4::from([other.group0()[0], other.group1()[1], other.group1()[2], other.group1()[3]]) + Simd32x4::from(self.group1()[1]) * Simd32x4::from([other.group1()[1], other.group0()[0], other.group1()[3], other.group1()[2]]) * Simd32x4::from([-1.0, 1.0, -1.0, 1.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from([other.group1()[2], other.group1()[3], other.group0()[0], other.group1()[1]]) * Simd32x4::from([-1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from([other.group1()[3], other.group1()[2], other.group1()[1], other.group0()[0]]) * Simd32x4::from([-1.0, -1.0, 1.0, 1.0]) - Simd32x4::from(self.group2()[0]) * Simd32x4::from([other.group1()[0], other.group0()[1], other.group0()[2], other.group0()[3]]) + Simd32x4::from(self.group2()[1]) * Simd32x4::from([other.group0()[1], other.group1()[0], other.group0()[3], other.group0()[2]]) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) + Simd32x4::from(self.group2()[2]) * Simd32x4::from([other.group0()[2], other.group0()[3], other.group1()[0], other.group0()[1]]) * Simd32x4::from([1.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group2()[3]) * Simd32x4::from([other.group0()[3], other.group0()[2], other.group0()[1], other.group1()[0]]) * Simd32x4::from([1.0, 1.0, -1.0, -1.0]) } }
1880    }
1881}
1882
1883impl ScalarProduct<PointAndPlane> for MultiVector {
1884    type Output = f32;
1885
1886    fn scalar_product(self, other: PointAndPlane) -> f32 {
1887        0.0 - self.group2()[0] * other.group0()[0] + self.group2()[1] * other.group1()[1] + self.group2()[2] * other.group1()[2] + self.group2()[3] * other.group1()[3]
1888    }
1889}
1890
1891impl SquaredMagnitude for MultiVector {
1892    type Output = f32;
1893
1894    fn squared_magnitude(self) -> f32 {
1895        self.scalar_product(self.reversal())
1896    }
1897}
1898
1899impl Magnitude for MultiVector {
1900    type Output = f32;
1901
1902    fn magnitude(self) -> f32 {
1903        self.squared_magnitude().sqrt()
1904    }
1905}
1906
1907impl Mul<f32> for MultiVector {
1908    type Output = MultiVector;
1909
1910    fn mul(self, other: f32) -> MultiVector {
1911        self.geometric_product(other)
1912    }
1913}
1914
1915impl MulAssign<f32> for MultiVector {
1916    fn mul_assign(&mut self, other: f32) {
1917        *self = (*self).mul(other);
1918    }
1919}
1920
1921impl Signum for MultiVector {
1922    type Output = MultiVector;
1923
1924    fn signum(self) -> MultiVector {
1925        self.geometric_product(1.0 / self.magnitude())
1926    }
1927}
1928
1929impl Inverse for MultiVector {
1930    type Output = MultiVector;
1931
1932    fn inverse(self) -> MultiVector {
1933        self.reversal().geometric_product(1.0 / self.squared_magnitude())
1934    }
1935}
1936
1937impl Zero for Rotor {
1938    fn zero() -> Self {
1939        Rotor { groups: RotorGroups { g0: Simd32x4::from(0.0) } }
1940    }
1941}
1942
1943impl One for Rotor {
1944    fn one() -> Self {
1945        Rotor { groups: RotorGroups { g0: Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
1946    }
1947}
1948
1949impl Neg for Rotor {
1950    type Output = Rotor;
1951
1952    fn neg(self) -> Rotor {
1953        Rotor { groups: RotorGroups { g0: self.group0() * Simd32x4::from(-1.0) } }
1954    }
1955}
1956
1957impl Automorphism for Rotor {
1958    type Output = Rotor;
1959
1960    fn automorphism(self) -> Rotor {
1961        Rotor { groups: RotorGroups { g0: self.group0() } }
1962    }
1963}
1964
1965impl Reversal for Rotor {
1966    type Output = Rotor;
1967
1968    fn reversal(self) -> Rotor {
1969        Rotor { groups: RotorGroups { g0: self.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) } }
1970    }
1971}
1972
1973impl Conjugation for Rotor {
1974    type Output = Rotor;
1975
1976    fn conjugation(self) -> Rotor {
1977        Rotor { groups: RotorGroups { g0: self.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) } }
1978    }
1979}
1980
1981impl Into<f32> for Rotor {
1982    fn into(self) -> f32 {
1983        self.group0()[0]
1984    }
1985}
1986
1987impl Add<f32> for Rotor {
1988    type Output = Rotor;
1989
1990    fn add(self, other: f32) -> Rotor {
1991        Rotor { groups: RotorGroups { g0: self.group0() + Simd32x4::from(other) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
1992    }
1993}
1994
1995impl AddAssign<f32> for Rotor {
1996    fn add_assign(&mut self, other: f32) {
1997        *self = (*self).add(other);
1998    }
1999}
2000
2001impl Sub<f32> for Rotor {
2002    type Output = Rotor;
2003
2004    fn sub(self, other: f32) -> Rotor {
2005        Rotor { groups: RotorGroups { g0: self.group0() - Simd32x4::from(other) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
2006    }
2007}
2008
2009impl SubAssign<f32> for Rotor {
2010    fn sub_assign(&mut self, other: f32) {
2011        *self = (*self).sub(other);
2012    }
2013}
2014
2015impl GeometricProduct<f32> for Rotor {
2016    type Output = Rotor;
2017
2018    fn geometric_product(self, other: f32) -> Rotor {
2019        Rotor { groups: RotorGroups { g0: self.group0() * Simd32x4::from(other) } }
2020    }
2021}
2022
2023impl OuterProduct<f32> for Rotor {
2024    type Output = Rotor;
2025
2026    fn outer_product(self, other: f32) -> Rotor {
2027        Rotor { groups: RotorGroups { g0: self.group0() * Simd32x4::from(other) } }
2028    }
2029}
2030
2031impl InnerProduct<f32> for Rotor {
2032    type Output = Rotor;
2033
2034    fn inner_product(self, other: f32) -> Rotor {
2035        Rotor { groups: RotorGroups { g0: self.group0() * Simd32x4::from(other) } }
2036    }
2037}
2038
2039impl LeftContraction<f32> for Rotor {
2040    type Output = f32;
2041
2042    fn left_contraction(self, other: f32) -> f32 {
2043        self.group0()[0] * other
2044    }
2045}
2046
2047impl RightContraction<f32> for Rotor {
2048    type Output = Rotor;
2049
2050    fn right_contraction(self, other: f32) -> Rotor {
2051        Rotor { groups: RotorGroups { g0: self.group0() * Simd32x4::from(other) } }
2052    }
2053}
2054
2055impl ScalarProduct<f32> for Rotor {
2056    type Output = f32;
2057
2058    fn scalar_product(self, other: f32) -> f32 {
2059        self.group0()[0] * other
2060    }
2061}
2062
2063impl Add<MultiVector> for Rotor {
2064    type Output = MultiVector;
2065
2066    fn add(self, other: MultiVector) -> MultiVector {
2067        MultiVector { groups: MultiVectorGroups { g0: self.group0() + other.group0(), g1: other.group1(), g2: other.group2(), g3: other.group3() } }
2068    }
2069}
2070
2071impl Sub<MultiVector> for Rotor {
2072    type Output = MultiVector;
2073
2074    fn sub(self, other: MultiVector) -> MultiVector {
2075        MultiVector { groups: MultiVectorGroups { g0: self.group0() - other.group0(), g1: Simd32x4::from(0.0) - other.group1(), g2: Simd32x4::from(0.0) - other.group2(), g3: Simd32x4::from(0.0) - other.group3() } }
2076    }
2077}
2078
2079impl GeometricProduct<MultiVector> for Rotor {
2080    type Output = MultiVector;
2081
2082    fn geometric_product(self, other: MultiVector) -> MultiVector {
2083        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([-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]), 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([1.0, 1.0, -1.0, -1.0]), g2: Simd32x4::from(self.group0()[0]) * other.group2() + Simd32x4::from(self.group0()[1]) * swizzle!(other.group2(), 1, 0, 3, 2) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group2(), 2, 3, 0, 1) * Simd32x4::from([1.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group2(), 3, 2, 1, 0) * Simd32x4::from([1.0, 1.0, -1.0, -1.0]), g3: Simd32x4::from(self.group0()[0]) * other.group3() + Simd32x4::from(self.group0()[1]) * swizzle!(other.group3(), 1, 0, 3, 2) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group3(), 2, 3, 0, 1) * Simd32x4::from([1.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group3(), 3, 2, 1, 0) * Simd32x4::from([1.0, 1.0, -1.0, -1.0]) } }
2084    }
2085}
2086
2087impl OuterProduct<MultiVector> for Rotor {
2088    type Output = MultiVector;
2089
2090    fn outer_product(self, other: MultiVector) -> MultiVector {
2091        MultiVector { groups: MultiVectorGroups { 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]), g1: Simd32x4::from(self.group0()[0]) * other.group1() + self.group0() * Simd32x4::from(other.group1()[0]) * Simd32x4::from([0.0, -1.0, -1.0, -1.0]), g2: Simd32x4::from(self.group0()[0]) * other.group2() + Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group2()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group2()[3]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0, 0) * swizzle!(other.group2(), 1, 0, 0, 0) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]), g3: Simd32x4::from(self.group0()[0]) * other.group3() + Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group3()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group3()[3]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0, 0) * swizzle!(other.group3(), 1, 0, 0, 0) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
2092    }
2093}
2094
2095impl InnerProduct<MultiVector> for Rotor {
2096    type Output = MultiVector;
2097
2098    fn inner_product(self, other: MultiVector) -> MultiVector {
2099        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([-1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 1.0]) + swizzle!(self.group0(), 1, 1, 0, 0) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]), g1: Simd32x4::from(self.group0()[0]) * other.group1() + Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group1()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group1()[3]) * Simd32x4::from([1.0, 0.0, 0.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]), g2: Simd32x4::from(self.group0()[0]) * other.group2() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group2(), 3, 3, 0, 1) * Simd32x4::from([0.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group2(), 2, 2, 1, 0) * Simd32x4::from([0.0, 1.0, -1.0, -1.0]) + swizzle!(self.group0(), 0, 1, 1, 1) * swizzle!(other.group2(), 0, 0, 3, 2) * Simd32x4::from([0.0, -1.0, 1.0, -1.0]), g3: Simd32x4::from(self.group0()[0]) * other.group3() + self.group0() * Simd32x4::from(other.group3()[0]) * Simd32x4::from([0.0, -1.0, -1.0, -1.0]) } }
2100    }
2101}
2102
2103impl LeftContraction<MultiVector> for Rotor {
2104    type Output = MultiVector;
2105
2106    fn left_contraction(self, other: MultiVector) -> MultiVector {
2107        MultiVector { groups: MultiVectorGroups { 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]), g1: Simd32x4::from(self.group0()[0]) * other.group1() + Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group1()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group1()[3]) * Simd32x4::from([1.0, 0.0, 0.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]), g2: Simd32x4::from(self.group0()[0]) * other.group2() + self.group0() * Simd32x4::from(other.group2()[0]) * Simd32x4::from([0.0, -1.0, -1.0, -1.0]), g3: Simd32x4::from(self.group0()[0]) * other.group3() + self.group0() * Simd32x4::from(other.group3()[0]) * Simd32x4::from([0.0, -1.0, -1.0, -1.0]) } }
2108    }
2109}
2110
2111impl ScalarProduct<MultiVector> for Rotor {
2112    type Output = f32;
2113
2114    fn scalar_product(self, other: MultiVector) -> f32 {
2115        self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group0()[1] - self.group0()[2] * other.group0()[2] - self.group0()[3] * other.group0()[3]
2116    }
2117}
2118
2119impl Add<Rotor> for Rotor {
2120    type Output = Rotor;
2121
2122    fn add(self, other: Rotor) -> Rotor {
2123        Rotor { groups: RotorGroups { g0: self.group0() + other.group0() } }
2124    }
2125}
2126
2127impl AddAssign<Rotor> for Rotor {
2128    fn add_assign(&mut self, other: Rotor) {
2129        *self = (*self).add(other);
2130    }
2131}
2132
2133impl Sub<Rotor> for Rotor {
2134    type Output = Rotor;
2135
2136    fn sub(self, other: Rotor) -> Rotor {
2137        Rotor { groups: RotorGroups { g0: self.group0() - other.group0() } }
2138    }
2139}
2140
2141impl SubAssign<Rotor> for Rotor {
2142    fn sub_assign(&mut self, other: Rotor) {
2143        *self = (*self).sub(other);
2144    }
2145}
2146
2147impl Mul<Rotor> for Rotor {
2148    type Output = Rotor;
2149
2150    fn mul(self, other: Rotor) -> Rotor {
2151        Rotor { groups: RotorGroups { g0: self.group0() * other.group0() } }
2152    }
2153}
2154
2155impl MulAssign<Rotor> for Rotor {
2156    fn mul_assign(&mut self, other: Rotor) {
2157        *self = (*self).mul(other);
2158    }
2159}
2160
2161impl Div<Rotor> for Rotor {
2162    type Output = Rotor;
2163
2164    fn div(self, other: Rotor) -> Rotor {
2165        Rotor { groups: RotorGroups { 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]) } }
2166    }
2167}
2168
2169impl DivAssign<Rotor> for Rotor {
2170    fn div_assign(&mut self, other: Rotor) {
2171        *self = (*self).div(other);
2172    }
2173}
2174
2175impl GeometricProduct<Rotor> for Rotor {
2176    type Output = Rotor;
2177
2178    fn geometric_product(self, other: Rotor) -> Rotor {
2179        Rotor { groups: RotorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 3, 0, 1) * Simd32x4::from([-1.0, -1.0, 1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([-1.0, 1.0, -1.0, 1.0]) } }
2180    }
2181}
2182
2183impl OuterProduct<Rotor> for Rotor {
2184    type Output = Rotor;
2185
2186    fn outer_product(self, other: Rotor) -> Rotor {
2187        Rotor { groups: RotorGroups { 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]) } }
2188    }
2189}
2190
2191impl InnerProduct<Rotor> for Rotor {
2192    type Output = Rotor;
2193
2194    fn inner_product(self, other: Rotor) -> Rotor {
2195        Rotor { groups: RotorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([-1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 1.0]) + swizzle!(self.group0(), 1, 1, 0, 0) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]) } }
2196    }
2197}
2198
2199impl LeftContraction<Rotor> for Rotor {
2200    type Output = Rotor;
2201
2202    fn left_contraction(self, other: Rotor) -> Rotor {
2203        Rotor { groups: RotorGroups { 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]) } }
2204    }
2205}
2206
2207impl RightContraction<Rotor> for Rotor {
2208    type Output = Rotor;
2209
2210    fn right_contraction(self, other: Rotor) -> Rotor {
2211        Rotor { groups: RotorGroups { 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]) } }
2212    }
2213}
2214
2215impl ScalarProduct<Rotor> for Rotor {
2216    type Output = f32;
2217
2218    fn scalar_product(self, other: Rotor) -> f32 {
2219        self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group0()[1] - self.group0()[2] * other.group0()[2] - self.group0()[3] * other.group0()[3]
2220    }
2221}
2222
2223impl GeometricProduct<Point> for Rotor {
2224    type Output = PointAndPlane;
2225
2226    fn geometric_product(self, other: Point) -> PointAndPlane {
2227        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 3, 3, 3, 1) * Simd32x4::from([0.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 2, 2, 1, 2) * Simd32x4::from([0.0, 1.0, -1.0, 0.0]) + swizzle!(self.group0(), 0, 0, 1, 1) * swizzle!(other.group0(), 0, 0, 3, 2) * Simd32x4::from([0.0, 0.0, 1.0, -1.0]), g1: Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, -1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, -1.0]) + swizzle!(self.group0(), 1, 1, 0, 0) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, -1.0, 0.0, 0.0]) } }
2228    }
2229}
2230
2231impl OuterProduct<Point> for Rotor {
2232    type Output = Point;
2233
2234    fn outer_product(self, other: Point) -> Point {
2235        Point { groups: PointGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() } }
2236    }
2237}
2238
2239impl InnerProduct<Point> for Rotor {
2240    type Output = PointAndPlane;
2241
2242    fn inner_product(self, other: Point) -> PointAndPlane {
2243        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0(), g1: Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, -1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, -1.0]) + swizzle!(self.group0(), 1, 1, 0, 0) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, -1.0, 0.0, 0.0]) } }
2244    }
2245}
2246
2247impl LeftContraction<Point> for Rotor {
2248    type Output = PointAndPlane;
2249
2250    fn left_contraction(self, other: Point) -> PointAndPlane {
2251        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0(), g1: Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, -1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, -1.0]) + swizzle!(self.group0(), 1, 1, 0, 0) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, -1.0, 0.0, 0.0]) } }
2252    }
2253}
2254
2255impl RegressiveProduct<IdealPoint> for Rotor {
2256    type Output = f32;
2257
2258    fn regressive_product(self, other: IdealPoint) -> f32 {
2259        self.group0()[1] * other.group0()[0] + self.group0()[2] * other.group0()[1] + self.group0()[3] * other.group0()[2]
2260    }
2261}
2262
2263impl InnerProduct<IdealPoint> for Rotor {
2264    type Output = IdealPoint;
2265
2266    fn inner_product(self, other: IdealPoint) -> IdealPoint {
2267        IdealPoint { groups: IdealPointGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() } }
2268    }
2269}
2270
2271impl LeftContraction<IdealPoint> for Rotor {
2272    type Output = IdealPoint;
2273
2274    fn left_contraction(self, other: IdealPoint) -> IdealPoint {
2275        IdealPoint { groups: IdealPointGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() } }
2276    }
2277}
2278
2279impl GeometricProduct<Plane> for Rotor {
2280    type Output = PointAndPlane;
2281
2282    fn geometric_product(self, other: Plane) -> PointAndPlane {
2283        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, -1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, -1.0]) + swizzle!(self.group0(), 1, 1, 0, 0) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, -1.0, 0.0, 0.0]), g1: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 3, 3, 3, 1) * Simd32x4::from([0.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 2, 2, 1, 2) * Simd32x4::from([0.0, 1.0, -1.0, 0.0]) + swizzle!(self.group0(), 0, 0, 1, 1) * swizzle!(other.group0(), 0, 0, 3, 2) * Simd32x4::from([0.0, 0.0, 1.0, -1.0]) } }
2284    }
2285}
2286
2287impl OuterProduct<Plane> for Rotor {
2288    type Output = PointAndPlane;
2289
2290    fn outer_product(self, other: Plane) -> PointAndPlane {
2291        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, -1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, -1.0]) + swizzle!(self.group0(), 1, 1, 0, 0) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, -1.0, 0.0, 0.0]), g1: Simd32x4::from(self.group0()[0]) * other.group0() } }
2292    }
2293}
2294
2295impl InnerProduct<Plane> for Rotor {
2296    type Output = Plane;
2297
2298    fn inner_product(self, other: Plane) -> Plane {
2299        Plane { groups: PlaneGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 3, 3, 3, 1) * Simd32x4::from([0.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 2, 2, 1, 2) * Simd32x4::from([0.0, 1.0, -1.0, 0.0]) + swizzle!(self.group0(), 0, 0, 1, 1) * swizzle!(other.group0(), 0, 0, 3, 2) * Simd32x4::from([0.0, 0.0, 1.0, -1.0]) } }
2300    }
2301}
2302
2303impl LeftContraction<Plane> for Rotor {
2304    type Output = Plane;
2305
2306    fn left_contraction(self, other: Plane) -> Plane {
2307        Plane { groups: PlaneGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() } }
2308    }
2309}
2310
2311impl GeometricProduct<Line> for Rotor {
2312    type Output = Motor;
2313
2314    fn geometric_product(self, other: Line) -> Motor {
2315        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group1()[0], other.group1()[0], other.group1()[2], other.group1()[1]]) * Simd32x4::from([-1.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group1()[1], other.group1()[2], other.group1()[1], other.group1()[0]]) * Simd32x4::from([-1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group1()[2], other.group1()[1], other.group1()[0], other.group1()[2]]) * Simd32x4::from([-1.0, 1.0, -1.0, 0.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group1()[0], other.group1()[0], other.group1()[1], other.group1()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]), g1: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[2], other.group0()[1]]) * Simd32x4::from([1.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[1], other.group0()[2], other.group0()[1], other.group0()[0]]) * Simd32x4::from([1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[2], other.group0()[1], other.group0()[0], other.group0()[2]]) * Simd32x4::from([1.0, 1.0, -1.0, 0.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
2316    }
2317}
2318
2319impl RegressiveProduct<Line> for Rotor {
2320    type Output = f32;
2321
2322    fn regressive_product(self, other: Line) -> f32 {
2323        self.group0()[1] * other.group0()[0] + self.group0()[2] * other.group0()[1] + self.group0()[3] * other.group0()[2]
2324    }
2325}
2326
2327impl RightContraction<Line> for Rotor {
2328    type Output = f32;
2329
2330    fn right_contraction(self, other: Line) -> f32 {
2331        0.0 - self.group0()[1] * other.group1()[0] - self.group0()[2] * other.group1()[1] - self.group0()[3] * other.group1()[2]
2332    }
2333}
2334
2335impl ScalarProduct<Line> for Rotor {
2336    type Output = f32;
2337
2338    fn scalar_product(self, other: Line) -> f32 {
2339        0.0 - self.group0()[1] * other.group1()[0] - self.group0()[2] * other.group1()[1] - self.group0()[3] * other.group1()[2]
2340    }
2341}
2342
2343impl GeometricProduct<Translator> for Rotor {
2344    type Output = Motor;
2345
2346    fn geometric_product(self, other: Translator) -> Motor {
2347        Motor { groups: MotorGroups { g0: self.group0() * Simd32x4::from(other.group0()[0]), g1: Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 1, 1, 3, 2) * Simd32x4::from([1.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 3, 2, 1) * Simd32x4::from([1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 2, 1, 3) * Simd32x4::from([1.0, 1.0, -1.0, 0.0]) + Simd32x4::from(self.group0()[0]) * other.group0() * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
2348    }
2349}
2350
2351impl RegressiveProduct<Translator> for Rotor {
2352    type Output = f32;
2353
2354    fn regressive_product(self, other: Translator) -> f32 {
2355        self.group0()[1] * other.group0()[1] + self.group0()[2] * other.group0()[2] + self.group0()[3] * other.group0()[3]
2356    }
2357}
2358
2359impl OuterProduct<Translator> for Rotor {
2360    type Output = Motor;
2361
2362    fn outer_product(self, other: Translator) -> Motor {
2363        Motor { groups: MotorGroups { g0: self.group0() * Simd32x4::from(other.group0()[0]), g1: 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, 1, 2, 3) } }
2364    }
2365}
2366
2367impl LeftContraction<Translator> for Rotor {
2368    type Output = Translator;
2369
2370    fn left_contraction(self, other: Translator) -> Translator {
2371        Translator { groups: TranslatorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() } }
2372    }
2373}
2374
2375impl RightContraction<Translator> for Rotor {
2376    type Output = Rotor;
2377
2378    fn right_contraction(self, other: Translator) -> Rotor {
2379        Rotor { groups: RotorGroups { g0: self.group0() * Simd32x4::from(other.group0()[0]) } }
2380    }
2381}
2382
2383impl ScalarProduct<Translator> for Rotor {
2384    type Output = f32;
2385
2386    fn scalar_product(self, other: Translator) -> f32 {
2387        self.group0()[0] * other.group0()[0]
2388    }
2389}
2390
2391impl Add<Motor> for Rotor {
2392    type Output = Motor;
2393
2394    fn add(self, other: Motor) -> Motor {
2395        Motor { groups: MotorGroups { g0: self.group0() + other.group0(), g1: other.group1() } }
2396    }
2397}
2398
2399impl Sub<Motor> for Rotor {
2400    type Output = Motor;
2401
2402    fn sub(self, other: Motor) -> Motor {
2403        Motor { groups: MotorGroups { g0: self.group0() - other.group0(), g1: Simd32x4::from(0.0) - other.group1() } }
2404    }
2405}
2406
2407impl GeometricProduct<Motor> for Rotor {
2408    type Output = Motor;
2409
2410    fn geometric_product(self, other: Motor) -> Motor {
2411        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 3, 0, 1) * Simd32x4::from([-1.0, -1.0, 1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([-1.0, 1.0, -1.0, 1.0]), 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([1.0, 1.0, -1.0, -1.0]) } }
2412    }
2413}
2414
2415impl RegressiveProduct<Motor> for Rotor {
2416    type Output = Rotor;
2417
2418    fn regressive_product(self, other: Motor) -> Rotor {
2419        Rotor { groups: RotorGroups { g0: Simd32x4::from(self.group0()[1]) * swizzle!(other.group1(), 1, 0, 1, 1) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group1(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group1(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from(other.group1()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
2420    }
2421}
2422
2423impl OuterProduct<Motor> for Rotor {
2424    type Output = Motor;
2425
2426    fn outer_product(self, other: Motor) -> Motor {
2427        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]), g1: Simd32x4::from(self.group0()[0]) * other.group1() + Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group1()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group1()[3]) * Simd32x4::from([1.0, 0.0, 0.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]) } }
2428    }
2429}
2430
2431impl InnerProduct<Motor> for Rotor {
2432    type Output = Motor;
2433
2434    fn inner_product(self, other: Motor) -> Motor {
2435        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([-1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 1.0]) + swizzle!(self.group0(), 1, 1, 0, 0) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]), g1: Simd32x4::from(self.group0()[0]) * other.group1() + self.group0() * Simd32x4::from(other.group1()[0]) * Simd32x4::from([0.0, -1.0, -1.0, -1.0]) } }
2436    }
2437}
2438
2439impl LeftContraction<Motor> for Rotor {
2440    type Output = Motor;
2441
2442    fn left_contraction(self, other: Motor) -> Motor {
2443        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]), g1: Simd32x4::from(self.group0()[0]) * other.group1() + self.group0() * Simd32x4::from(other.group1()[0]) * Simd32x4::from([0.0, -1.0, -1.0, -1.0]) } }
2444    }
2445}
2446
2447impl RightContraction<Motor> for Rotor {
2448    type Output = Rotor;
2449
2450    fn right_contraction(self, other: Motor) -> Rotor {
2451        Rotor { groups: RotorGroups { 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]) } }
2452    }
2453}
2454
2455impl ScalarProduct<Motor> for Rotor {
2456    type Output = f32;
2457
2458    fn scalar_product(self, other: Motor) -> f32 {
2459        self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group0()[1] - self.group0()[2] * other.group0()[2] - self.group0()[3] * other.group0()[3]
2460    }
2461}
2462
2463impl GeometricProduct<PointAndPlane> for Rotor {
2464    type Output = PointAndPlane;
2465
2466    fn geometric_product(self, other: PointAndPlane) -> PointAndPlane {
2467        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group1()[1], other.group1()[0], other.group0()[3], other.group0()[2]]) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group1()[2], other.group0()[3], other.group1()[0], other.group0()[1]]) * Simd32x4::from([1.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group1()[3], other.group0()[2], other.group0()[1], other.group1()[0]]) * Simd32x4::from([1.0, 1.0, -1.0, -1.0]), g1: Simd32x4::from(self.group0()[0]) * other.group1() + Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[1], other.group0()[0], other.group1()[3], other.group1()[2]]) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[2], other.group1()[3], other.group0()[0], other.group1()[1]]) * Simd32x4::from([1.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[3], other.group1()[2], other.group1()[1], other.group0()[0]]) * Simd32x4::from([1.0, 1.0, -1.0, -1.0]) } }
2468    }
2469}
2470
2471impl OuterProduct<PointAndPlane> for Rotor {
2472    type Output = PointAndPlane;
2473
2474    fn outer_product(self, other: PointAndPlane) -> PointAndPlane {
2475        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group1(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, -1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group1(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, -1.0]) + swizzle!(self.group0(), 1, 1, 0, 0) * swizzle!(other.group1(), 1, 0, 0, 0) * Simd32x4::from([1.0, -1.0, 0.0, 0.0]), g1: Simd32x4::from(self.group0()[0]) * other.group1() } }
2476    }
2477}
2478
2479impl InnerProduct<PointAndPlane> for Rotor {
2480    type Output = PointAndPlane;
2481
2482    fn inner_product(self, other: PointAndPlane) -> PointAndPlane {
2483        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0(), g1: Simd32x4::from(self.group0()[0]) * other.group1() + Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[1], other.group0()[0], other.group1()[3], other.group1()[2]]) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[2], other.group1()[3], other.group0()[0], other.group1()[1]]) * Simd32x4::from([1.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[3], other.group1()[2], other.group1()[1], other.group0()[0]]) * Simd32x4::from([1.0, 1.0, -1.0, -1.0]) } }
2484    }
2485}
2486
2487impl LeftContraction<PointAndPlane> for Rotor {
2488    type Output = PointAndPlane;
2489
2490    fn left_contraction(self, other: PointAndPlane) -> PointAndPlane {
2491        PointAndPlane { groups: PointAndPlaneGroups { 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, 0, 2) * Simd32x4::from([1.0, 0.0, -1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, -1.0]) + swizzle!(self.group0(), 1, 1, 0, 0) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, -1.0, 0.0, 0.0]) } }
2492    }
2493}
2494
2495impl SquaredMagnitude for Rotor {
2496    type Output = f32;
2497
2498    fn squared_magnitude(self) -> f32 {
2499        self.scalar_product(self.reversal())
2500    }
2501}
2502
2503impl Magnitude for Rotor {
2504    type Output = f32;
2505
2506    fn magnitude(self) -> f32 {
2507        self.squared_magnitude().sqrt()
2508    }
2509}
2510
2511impl Mul<f32> for Rotor {
2512    type Output = Rotor;
2513
2514    fn mul(self, other: f32) -> Rotor {
2515        self.geometric_product(other)
2516    }
2517}
2518
2519impl MulAssign<f32> for Rotor {
2520    fn mul_assign(&mut self, other: f32) {
2521        *self = (*self).mul(other);
2522    }
2523}
2524
2525impl Signum for Rotor {
2526    type Output = Rotor;
2527
2528    fn signum(self) -> Rotor {
2529        self.geometric_product(1.0 / self.magnitude())
2530    }
2531}
2532
2533impl Inverse for Rotor {
2534    type Output = Rotor;
2535
2536    fn inverse(self) -> Rotor {
2537        self.reversal().geometric_product(1.0 / self.squared_magnitude())
2538    }
2539}
2540
2541impl Zero for Point {
2542    fn zero() -> Self {
2543        Point { groups: PointGroups { g0: Simd32x4::from(0.0) } }
2544    }
2545}
2546
2547impl One for Point {
2548    fn one() -> Self {
2549        Point { groups: PointGroups { g0: Simd32x4::from(0.0) } }
2550    }
2551}
2552
2553impl Neg for Point {
2554    type Output = Point;
2555
2556    fn neg(self) -> Point {
2557        Point { groups: PointGroups { g0: self.group0() * Simd32x4::from(-1.0) } }
2558    }
2559}
2560
2561impl Automorphism for Point {
2562    type Output = Point;
2563
2564    fn automorphism(self) -> Point {
2565        Point { groups: PointGroups { g0: self.group0() * Simd32x4::from(-1.0) } }
2566    }
2567}
2568
2569impl Reversal for Point {
2570    type Output = Point;
2571
2572    fn reversal(self) -> Point {
2573        Point { groups: PointGroups { g0: self.group0() * Simd32x4::from(-1.0) } }
2574    }
2575}
2576
2577impl Conjugation for Point {
2578    type Output = Point;
2579
2580    fn conjugation(self) -> Point {
2581        Point { groups: PointGroups { g0: self.group0() } }
2582    }
2583}
2584
2585impl Dual for Point {
2586    type Output = Plane;
2587
2588    fn dual(self) -> Plane {
2589        Plane { groups: PlaneGroups { g0: self.group0() * Simd32x4::from(-1.0) } }
2590    }
2591}
2592
2593impl GeometricProduct<f32> for Point {
2594    type Output = Point;
2595
2596    fn geometric_product(self, other: f32) -> Point {
2597        Point { groups: PointGroups { g0: self.group0() * Simd32x4::from(other) } }
2598    }
2599}
2600
2601impl OuterProduct<f32> for Point {
2602    type Output = Point;
2603
2604    fn outer_product(self, other: f32) -> Point {
2605        Point { groups: PointGroups { g0: self.group0() * Simd32x4::from(other) } }
2606    }
2607}
2608
2609impl InnerProduct<f32> for Point {
2610    type Output = Point;
2611
2612    fn inner_product(self, other: f32) -> Point {
2613        Point { groups: PointGroups { g0: self.group0() * Simd32x4::from(other) } }
2614    }
2615}
2616
2617impl RightContraction<f32> for Point {
2618    type Output = Point;
2619
2620    fn right_contraction(self, other: f32) -> Point {
2621        Point { groups: PointGroups { g0: self.group0() * Simd32x4::from(other) } }
2622    }
2623}
2624
2625impl Add<MultiVector> for Point {
2626    type Output = MultiVector;
2627
2628    fn add(self, other: MultiVector) -> MultiVector {
2629        MultiVector { groups: MultiVectorGroups { g0: other.group0(), g1: self.group0() * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) + other.group1(), g2: Simd32x4::from(self.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + other.group2(), g3: other.group3() } }
2630    }
2631}
2632
2633impl Sub<MultiVector> for Point {
2634    type Output = MultiVector;
2635
2636    fn sub(self, other: MultiVector) -> MultiVector {
2637        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(0.0) - other.group0(), g1: self.group0() * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) - other.group1(), g2: Simd32x4::from(self.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) - other.group2(), g3: Simd32x4::from(0.0) - other.group3() } }
2638    }
2639}
2640
2641impl GeometricProduct<MultiVector> for Point {
2642    type Output = MultiVector;
2643
2644    fn geometric_product(self, other: MultiVector) -> MultiVector {
2645        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group2() * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]), g1: Simd32x4::from(self.group0()[0]) * other.group3() + Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 3, 0, 1) * Simd32x4::from([1.0, -1.0, 1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([1.0, 1.0, -1.0, 1.0]), g2: Simd32x4::from(self.group0()[0]) * other.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]), g3: Simd32x4::from(0.0) - Simd32x4::from(self.group0()[0]) * other.group1() + Simd32x4::from(self.group0()[1]) * swizzle!(other.group2(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group2(), 2, 3, 0, 1) * Simd32x4::from([-1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group2(), 3, 2, 1, 0) * Simd32x4::from([-1.0, -1.0, 1.0, 1.0]) } }
2646    }
2647}
2648
2649impl ScalarProduct<MultiVector> for Point {
2650    type Output = f32;
2651
2652    fn scalar_product(self, other: MultiVector) -> f32 {
2653        0.0 - self.group0()[0] * other.group2()[0]
2654    }
2655}
2656
2657impl GeometricProduct<Rotor> for Point {
2658    type Output = PointAndPlane;
2659
2660    fn geometric_product(self, other: Rotor) -> PointAndPlane {
2661        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 3, 3, 0, 1) * Simd32x4::from([0.0, -1.0, 1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 2, 2, 1, 0) * Simd32x4::from([0.0, 1.0, -1.0, 1.0]) + swizzle!(self.group0(), 0, 1, 1, 1) * swizzle!(other.group0(), 0, 0, 3, 2) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]), g1: 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, 1, 2, 3) * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) } }
2662    }
2663}
2664
2665impl OuterProduct<Rotor> for Point {
2666    type Output = Point;
2667
2668    fn outer_product(self, other: Rotor) -> Point {
2669        Point { groups: PointGroups { g0: self.group0() * Simd32x4::from(other.group0()[0]) } }
2670    }
2671}
2672
2673impl InnerProduct<Rotor> for Point {
2674    type Output = PointAndPlane;
2675
2676    fn inner_product(self, other: Rotor) -> PointAndPlane {
2677        PointAndPlane { groups: PointAndPlaneGroups { g0: self.group0() * Simd32x4::from(other.group0()[0]), g1: 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, 1, 2, 3) * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) } }
2678    }
2679}
2680
2681impl RightContraction<Rotor> for Point {
2682    type Output = PointAndPlane;
2683
2684    fn right_contraction(self, other: Rotor) -> PointAndPlane {
2685        PointAndPlane { groups: PointAndPlaneGroups { g0: self.group0() * Simd32x4::from(other.group0()[0]), g1: 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, 1, 2, 3) * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) } }
2686    }
2687}
2688
2689impl Add<Point> for Point {
2690    type Output = Point;
2691
2692    fn add(self, other: Point) -> Point {
2693        Point { groups: PointGroups { g0: self.group0() + other.group0() } }
2694    }
2695}
2696
2697impl AddAssign<Point> for Point {
2698    fn add_assign(&mut self, other: Point) {
2699        *self = (*self).add(other);
2700    }
2701}
2702
2703impl Sub<Point> for Point {
2704    type Output = Point;
2705
2706    fn sub(self, other: Point) -> Point {
2707        Point { groups: PointGroups { g0: self.group0() - other.group0() } }
2708    }
2709}
2710
2711impl SubAssign<Point> for Point {
2712    fn sub_assign(&mut self, other: Point) {
2713        *self = (*self).sub(other);
2714    }
2715}
2716
2717impl Mul<Point> for Point {
2718    type Output = Point;
2719
2720    fn mul(self, other: Point) -> Point {
2721        Point { groups: PointGroups { g0: self.group0() * other.group0() } }
2722    }
2723}
2724
2725impl MulAssign<Point> for Point {
2726    fn mul_assign(&mut self, other: Point) {
2727        *self = (*self).mul(other);
2728    }
2729}
2730
2731impl Div<Point> for Point {
2732    type Output = Point;
2733
2734    fn div(self, other: Point) -> Point {
2735        Point { groups: PointGroups { 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]) } }
2736    }
2737}
2738
2739impl DivAssign<Point> for Point {
2740    fn div_assign(&mut self, other: Point) {
2741        *self = (*self).div(other);
2742    }
2743}
2744
2745impl GeometricProduct<Point> for Point {
2746    type Output = Translator;
2747
2748    fn geometric_product(self, other: Point) -> Translator {
2749        Translator { groups: TranslatorGroups { g0: Simd32x4::from(0.0) - Simd32x4::from(self.group0()[0]) * other.group0() + self.group0() * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
2750    }
2751}
2752
2753impl RegressiveProduct<Point> for Point {
2754    type Output = Line;
2755
2756    fn regressive_product(self, other: Point) -> Line {
2757        Line { groups: LineGroups { 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]), g1: Simd32x3::from(self.group0()[0]) * Simd32x3::from([other.group0()[1], other.group0()[2], other.group0()[3]]) + Simd32x3::from([self.group0()[1], self.group0()[2], self.group0()[3]]) * Simd32x3::from(other.group0()[0]) * Simd32x3::from(-1.0) } }
2758    }
2759}
2760
2761impl InnerProduct<Point> for Point {
2762    type Output = f32;
2763
2764    fn inner_product(self, other: Point) -> f32 {
2765        0.0 - self.group0()[0] * other.group0()[0]
2766    }
2767}
2768
2769impl LeftContraction<Point> for Point {
2770    type Output = f32;
2771
2772    fn left_contraction(self, other: Point) -> f32 {
2773        0.0 - self.group0()[0] * other.group0()[0]
2774    }
2775}
2776
2777impl RightContraction<Point> for Point {
2778    type Output = f32;
2779
2780    fn right_contraction(self, other: Point) -> f32 {
2781        0.0 - self.group0()[0] * other.group0()[0]
2782    }
2783}
2784
2785impl ScalarProduct<Point> for Point {
2786    type Output = f32;
2787
2788    fn scalar_product(self, other: Point) -> f32 {
2789        0.0 - self.group0()[0] * other.group0()[0]
2790    }
2791}
2792
2793impl RegressiveProduct<IdealPoint> for Point {
2794    type Output = Plane;
2795
2796    fn regressive_product(self, other: IdealPoint) -> Plane {
2797        Plane { groups: PlaneGroups { g0: Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group0()[1]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group0()[2]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0, 0) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) } }
2798    }
2799}
2800
2801impl Add<Plane> for Point {
2802    type Output = PointAndPlane;
2803
2804    fn add(self, other: Plane) -> PointAndPlane {
2805        PointAndPlane { groups: PointAndPlaneGroups { g0: self.group0(), g1: other.group0() } }
2806    }
2807}
2808
2809impl Sub<Plane> for Point {
2810    type Output = PointAndPlane;
2811
2812    fn sub(self, other: Plane) -> PointAndPlane {
2813        PointAndPlane { groups: PointAndPlaneGroups { g0: self.group0(), g1: Simd32x4::from(0.0) - other.group0() } }
2814    }
2815}
2816
2817impl RegressiveProduct<Plane> for Point {
2818    type Output = f32;
2819
2820    fn regressive_product(self, other: Plane) -> f32 {
2821        0.0 - self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group0()[1] - self.group0()[2] * other.group0()[2] - self.group0()[3] * other.group0()[3]
2822    }
2823}
2824
2825impl InnerProduct<Plane> for Point {
2826    type Output = Line;
2827
2828    fn inner_product(self, other: Plane) -> Line {
2829        Line { groups: LineGroups { 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]), g1: Simd32x3::from(self.group0()[0]) * Simd32x3::from([other.group0()[1], other.group0()[2], other.group0()[3]]) } }
2830    }
2831}
2832
2833impl RightContraction<Plane> for Point {
2834    type Output = Line;
2835
2836    fn right_contraction(self, other: Plane) -> Line {
2837        Line { groups: LineGroups { 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]), g1: Simd32x3::from(self.group0()[0]) * Simd32x3::from([other.group0()[1], other.group0()[2], other.group0()[3]]) } }
2838    }
2839}
2840
2841impl RegressiveProduct<Line> for Point {
2842    type Output = Plane;
2843
2844    fn regressive_product(self, other: Line) -> Plane {
2845        Plane { groups: PlaneGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group1()[2], other.group1()[1]]) * Simd32x4::from([-1.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[1], other.group1()[2], other.group0()[1], other.group1()[0]]) * Simd32x4::from([-1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[2], other.group1()[1], other.group1()[0], other.group0()[2]]) * Simd32x4::from([-1.0, 1.0, -1.0, 0.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
2846    }
2847}
2848
2849impl InnerProduct<Line> for Point {
2850    type Output = Plane;
2851
2852    fn inner_product(self, other: Line) -> Plane {
2853        Plane { groups: PlaneGroups { g0: Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group1()[1]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group1()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0, 0) * Simd32x4::from([other.group1()[0], other.group1()[0], other.group1()[1], other.group1()[2]]) * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) } }
2854    }
2855}
2856
2857impl RightContraction<Line> for Point {
2858    type Output = Plane;
2859
2860    fn right_contraction(self, other: Line) -> Plane {
2861        Plane { groups: PlaneGroups { g0: Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group1()[1]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group1()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0, 0) * Simd32x4::from([other.group1()[0], other.group1()[0], other.group1()[1], other.group1()[2]]) * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) } }
2862    }
2863}
2864
2865impl GeometricProduct<Translator> for Point {
2866    type Output = Point;
2867
2868    fn geometric_product(self, other: Translator) -> Point {
2869        Point { groups: PointGroups { 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]) } }
2870    }
2871}
2872
2873impl RegressiveProduct<Translator> for Point {
2874    type Output = Plane;
2875
2876    fn regressive_product(self, other: Translator) -> Plane {
2877        Plane { groups: PlaneGroups { 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()[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, 1, 2, 3) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) } }
2878    }
2879}
2880
2881impl OuterProduct<Translator> for Point {
2882    type Output = Point;
2883
2884    fn outer_product(self, other: Translator) -> Point {
2885        Point { groups: PointGroups { g0: self.group0() * Simd32x4::from(other.group0()[0]) } }
2886    }
2887}
2888
2889impl InnerProduct<Translator> for Point {
2890    type Output = Point;
2891
2892    fn inner_product(self, other: Translator) -> Point {
2893        Point { groups: PointGroups { g0: self.group0() * Simd32x4::from(other.group0()[0]) } }
2894    }
2895}
2896
2897impl RightContraction<Translator> for Point {
2898    type Output = Point;
2899
2900    fn right_contraction(self, other: Translator) -> Point {
2901        Point { groups: PointGroups { g0: self.group0() * Simd32x4::from(other.group0()[0]) } }
2902    }
2903}
2904
2905impl GeometricProduct<Motor> for Point {
2906    type Output = PointAndPlane;
2907
2908    fn geometric_product(self, other: Motor) -> PointAndPlane {
2909        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group0()[0], other.group1()[1], other.group1()[2], other.group1()[3]]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 3, 3, 0, 1) * Simd32x4::from([0.0, -1.0, 1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 2, 2, 1, 0) * Simd32x4::from([0.0, 1.0, -1.0, 1.0]) + swizzle!(self.group0(), 0, 1, 1, 1) * swizzle!(other.group0(), 0, 0, 3, 2) * Simd32x4::from([0.0, 1.0, 1.0, -1.0]), g1: Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group1()[0], other.group0()[1], other.group0()[2], other.group0()[3]]) * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group0()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group0()[3]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0, 0) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
2910    }
2911}
2912
2913impl RegressiveProduct<Motor> for Point {
2914    type Output = PointAndPlane;
2915
2916    fn regressive_product(self, other: Motor) -> PointAndPlane {
2917        PointAndPlane { groups: PointAndPlaneGroups { g0: self.group0() * Simd32x4::from(other.group1()[0]), g1: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group1()[1], other.group1()[1], other.group0()[3], other.group0()[2]]) * Simd32x4::from([-1.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group1()[2], other.group0()[3], other.group1()[2], other.group0()[1]]) * Simd32x4::from([-1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group1()[3], other.group0()[2], other.group0()[1], other.group1()[3]]) * Simd32x4::from([-1.0, 1.0, -1.0, 0.0]) + Simd32x4::from(self.group0()[0]) * other.group1() * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
2918    }
2919}
2920
2921impl OuterProduct<Motor> for Point {
2922    type Output = Point;
2923
2924    fn outer_product(self, other: Motor) -> Point {
2925        Point { groups: PointGroups { g0: self.group0() * Simd32x4::from(other.group0()[0]) } }
2926    }
2927}
2928
2929impl InnerProduct<Motor> for Point {
2930    type Output = PointAndPlane;
2931
2932    fn inner_product(self, other: Motor) -> PointAndPlane {
2933        PointAndPlane { groups: PointAndPlaneGroups { g0: self.group0() * Simd32x4::from(other.group0()[0]), g1: Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group1()[0], other.group0()[1], other.group0()[2], other.group0()[3]]) * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group0()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group0()[3]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0, 0) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
2934    }
2935}
2936
2937impl RightContraction<Motor> for Point {
2938    type Output = PointAndPlane;
2939
2940    fn right_contraction(self, other: Motor) -> PointAndPlane {
2941        PointAndPlane { groups: PointAndPlaneGroups { g0: self.group0() * Simd32x4::from(other.group0()[0]), g1: 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, 1, 2, 3) * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) } }
2942    }
2943}
2944
2945impl Add<PointAndPlane> for Point {
2946    type Output = PointAndPlane;
2947
2948    fn add(self, other: PointAndPlane) -> PointAndPlane {
2949        PointAndPlane { groups: PointAndPlaneGroups { g0: self.group0() + other.group0(), g1: other.group1() } }
2950    }
2951}
2952
2953impl Sub<PointAndPlane> for Point {
2954    type Output = PointAndPlane;
2955
2956    fn sub(self, other: PointAndPlane) -> PointAndPlane {
2957        PointAndPlane { groups: PointAndPlaneGroups { g0: self.group0() - other.group0(), g1: Simd32x4::from(0.0) - other.group1() } }
2958    }
2959}
2960
2961impl GeometricProduct<PointAndPlane> for Point {
2962    type Output = Motor;
2963
2964    fn geometric_product(self, other: PointAndPlane) -> Motor {
2965        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group0()[0], other.group1()[1], other.group1()[2], other.group1()[3]]) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]), g1: Simd32x4::from(0.0) - Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group1()[0], other.group0()[1], other.group0()[2], other.group0()[3]]) + Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group1()[1], other.group0()[0], other.group1()[3], other.group1()[2]]) * Simd32x4::from([-1.0, 1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group1()[2], other.group1()[3], other.group0()[0], other.group1()[1]]) * Simd32x4::from([-1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group1()[3], other.group1()[2], other.group1()[1], other.group0()[0]]) * Simd32x4::from([-1.0, -1.0, 1.0, 1.0]) } }
2966    }
2967}
2968
2969impl LeftContraction<PointAndPlane> for Point {
2970    type Output = f32;
2971
2972    fn left_contraction(self, other: PointAndPlane) -> f32 {
2973        0.0 - self.group0()[0] * other.group0()[0]
2974    }
2975}
2976
2977impl ScalarProduct<PointAndPlane> for Point {
2978    type Output = f32;
2979
2980    fn scalar_product(self, other: PointAndPlane) -> f32 {
2981        0.0 - self.group0()[0] * other.group0()[0]
2982    }
2983}
2984
2985impl SquaredMagnitude for Point {
2986    type Output = f32;
2987
2988    fn squared_magnitude(self) -> f32 {
2989        self.scalar_product(self.reversal())
2990    }
2991}
2992
2993impl Magnitude for Point {
2994    type Output = f32;
2995
2996    fn magnitude(self) -> f32 {
2997        self.squared_magnitude().sqrt()
2998    }
2999}
3000
3001impl Mul<f32> for Point {
3002    type Output = Point;
3003
3004    fn mul(self, other: f32) -> Point {
3005        self.geometric_product(other)
3006    }
3007}
3008
3009impl MulAssign<f32> for Point {
3010    fn mul_assign(&mut self, other: f32) {
3011        *self = (*self).mul(other);
3012    }
3013}
3014
3015impl Signum for Point {
3016    type Output = Point;
3017
3018    fn signum(self) -> Point {
3019        self.geometric_product(1.0 / self.magnitude())
3020    }
3021}
3022
3023impl Inverse for Point {
3024    type Output = Point;
3025
3026    fn inverse(self) -> Point {
3027        self.reversal().geometric_product(1.0 / self.squared_magnitude())
3028    }
3029}
3030
3031impl Zero for IdealPoint {
3032    fn zero() -> Self {
3033        IdealPoint { groups: IdealPointGroups { g0: Simd32x3::from(0.0) } }
3034    }
3035}
3036
3037impl One for IdealPoint {
3038    fn one() -> Self {
3039        IdealPoint { groups: IdealPointGroups { g0: Simd32x3::from(0.0) } }
3040    }
3041}
3042
3043impl Neg for IdealPoint {
3044    type Output = IdealPoint;
3045
3046    fn neg(self) -> IdealPoint {
3047        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x3::from(-1.0) } }
3048    }
3049}
3050
3051impl Automorphism for IdealPoint {
3052    type Output = IdealPoint;
3053
3054    fn automorphism(self) -> IdealPoint {
3055        IdealPoint { groups: IdealPointGroups { g0: self.group0() } }
3056    }
3057}
3058
3059impl Reversal for IdealPoint {
3060    type Output = IdealPoint;
3061
3062    fn reversal(self) -> IdealPoint {
3063        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x3::from(-1.0) } }
3064    }
3065}
3066
3067impl Conjugation for IdealPoint {
3068    type Output = IdealPoint;
3069
3070    fn conjugation(self) -> IdealPoint {
3071        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x3::from(-1.0) } }
3072    }
3073}
3074
3075impl Add<f32> for IdealPoint {
3076    type Output = Translator;
3077
3078    fn add(self, other: f32) -> Translator {
3079        Translator { groups: TranslatorGroups { 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]) } }
3080    }
3081}
3082
3083impl Sub<f32> for IdealPoint {
3084    type Output = Translator;
3085
3086    fn sub(self, other: f32) -> Translator {
3087        Translator { groups: TranslatorGroups { 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]) } }
3088    }
3089}
3090
3091impl GeometricProduct<f32> for IdealPoint {
3092    type Output = IdealPoint;
3093
3094    fn geometric_product(self, other: f32) -> IdealPoint {
3095        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x3::from(other) } }
3096    }
3097}
3098
3099impl OuterProduct<f32> for IdealPoint {
3100    type Output = IdealPoint;
3101
3102    fn outer_product(self, other: f32) -> IdealPoint {
3103        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x3::from(other) } }
3104    }
3105}
3106
3107impl InnerProduct<f32> for IdealPoint {
3108    type Output = IdealPoint;
3109
3110    fn inner_product(self, other: f32) -> IdealPoint {
3111        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x3::from(other) } }
3112    }
3113}
3114
3115impl RightContraction<f32> for IdealPoint {
3116    type Output = IdealPoint;
3117
3118    fn right_contraction(self, other: f32) -> IdealPoint {
3119        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x3::from(other) } }
3120    }
3121}
3122
3123impl Add<MultiVector> for IdealPoint {
3124    type Output = MultiVector;
3125
3126    fn add(self, other: MultiVector) -> MultiVector {
3127        MultiVector { groups: MultiVectorGroups { g0: other.group0(), g1: other.group1(), g2: other.group2(), g3: 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.group3() } }
3128    }
3129}
3130
3131impl Sub<MultiVector> for IdealPoint {
3132    type Output = MultiVector;
3133
3134    fn sub(self, other: MultiVector) -> MultiVector {
3135        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(0.0) - other.group0(), g1: Simd32x4::from(0.0) - other.group1(), g2: Simd32x4::from(0.0) - other.group2(), g3: 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.group3() } }
3136    }
3137}
3138
3139impl RegressiveProduct<Rotor> for IdealPoint {
3140    type Output = f32;
3141
3142    fn regressive_product(self, other: Rotor) -> f32 {
3143        self.group0()[0] * other.group0()[1] + self.group0()[1] * other.group0()[2] + self.group0()[2] * other.group0()[3]
3144    }
3145}
3146
3147impl InnerProduct<Rotor> for IdealPoint {
3148    type Output = IdealPoint;
3149
3150    fn inner_product(self, other: Rotor) -> IdealPoint {
3151        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x3::from(other.group0()[0]) } }
3152    }
3153}
3154
3155impl RightContraction<Rotor> for IdealPoint {
3156    type Output = IdealPoint;
3157
3158    fn right_contraction(self, other: Rotor) -> IdealPoint {
3159        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x3::from(other.group0()[0]) } }
3160    }
3161}
3162
3163impl RegressiveProduct<Point> for IdealPoint {
3164    type Output = Plane;
3165
3166    fn regressive_product(self, other: Point) -> Plane {
3167        Plane { groups: PlaneGroups { 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]) } }
3168    }
3169}
3170
3171impl Add<IdealPoint> for IdealPoint {
3172    type Output = IdealPoint;
3173
3174    fn add(self, other: IdealPoint) -> IdealPoint {
3175        IdealPoint { groups: IdealPointGroups { g0: self.group0() + other.group0() } }
3176    }
3177}
3178
3179impl AddAssign<IdealPoint> for IdealPoint {
3180    fn add_assign(&mut self, other: IdealPoint) {
3181        *self = (*self).add(other);
3182    }
3183}
3184
3185impl Sub<IdealPoint> for IdealPoint {
3186    type Output = IdealPoint;
3187
3188    fn sub(self, other: IdealPoint) -> IdealPoint {
3189        IdealPoint { groups: IdealPointGroups { g0: self.group0() - other.group0() } }
3190    }
3191}
3192
3193impl SubAssign<IdealPoint> for IdealPoint {
3194    fn sub_assign(&mut self, other: IdealPoint) {
3195        *self = (*self).sub(other);
3196    }
3197}
3198
3199impl Mul<IdealPoint> for IdealPoint {
3200    type Output = IdealPoint;
3201
3202    fn mul(self, other: IdealPoint) -> IdealPoint {
3203        IdealPoint { groups: IdealPointGroups { g0: self.group0() * other.group0() } }
3204    }
3205}
3206
3207impl MulAssign<IdealPoint> for IdealPoint {
3208    fn mul_assign(&mut self, other: IdealPoint) {
3209        *self = (*self).mul(other);
3210    }
3211}
3212
3213impl Div<IdealPoint> for IdealPoint {
3214    type Output = IdealPoint;
3215
3216    fn div(self, other: IdealPoint) -> IdealPoint {
3217        IdealPoint { groups: IdealPointGroups { 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]) } }
3218    }
3219}
3220
3221impl DivAssign<IdealPoint> for IdealPoint {
3222    fn div_assign(&mut self, other: IdealPoint) {
3223        *self = (*self).div(other);
3224    }
3225}
3226
3227impl Add<Line> for IdealPoint {
3228    type Output = Line;
3229
3230    fn add(self, other: Line) -> Line {
3231        Line { groups: LineGroups { g0: self.group0() + other.group0(), g1: other.group1() } }
3232    }
3233}
3234
3235impl Sub<Line> for IdealPoint {
3236    type Output = Line;
3237
3238    fn sub(self, other: Line) -> Line {
3239        Line { groups: LineGroups { g0: self.group0() - other.group0(), g1: Simd32x3::from(0.0) - other.group1() } }
3240    }
3241}
3242
3243impl RegressiveProduct<Line> for IdealPoint {
3244    type Output = f32;
3245
3246    fn regressive_product(self, other: Line) -> f32 {
3247        self.group0()[0] * other.group1()[0] + self.group0()[1] * other.group1()[1] + self.group0()[2] * other.group1()[2]
3248    }
3249}
3250
3251impl Add<Translator> for IdealPoint {
3252    type Output = Translator;
3253
3254    fn add(self, other: Translator) -> Translator {
3255        Translator { groups: TranslatorGroups { 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() } }
3256    }
3257}
3258
3259impl Sub<Translator> for IdealPoint {
3260    type Output = Translator;
3261
3262    fn sub(self, other: Translator) -> Translator {
3263        Translator { groups: TranslatorGroups { 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() } }
3264    }
3265}
3266
3267impl GeometricProduct<Translator> for IdealPoint {
3268    type Output = IdealPoint;
3269
3270    fn geometric_product(self, other: Translator) -> IdealPoint {
3271        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x3::from(other.group0()[0]) } }
3272    }
3273}
3274
3275impl OuterProduct<Translator> for IdealPoint {
3276    type Output = IdealPoint;
3277
3278    fn outer_product(self, other: Translator) -> IdealPoint {
3279        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x3::from(other.group0()[0]) } }
3280    }
3281}
3282
3283impl InnerProduct<Translator> for IdealPoint {
3284    type Output = IdealPoint;
3285
3286    fn inner_product(self, other: Translator) -> IdealPoint {
3287        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x3::from(other.group0()[0]) } }
3288    }
3289}
3290
3291impl RightContraction<Translator> for IdealPoint {
3292    type Output = IdealPoint;
3293
3294    fn right_contraction(self, other: Translator) -> IdealPoint {
3295        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x3::from(other.group0()[0]) } }
3296    }
3297}
3298
3299impl Add<Motor> for IdealPoint {
3300    type Output = Motor;
3301
3302    fn add(self, other: Motor) -> Motor {
3303        Motor { groups: MotorGroups { g0: other.group0(), g1: 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.group1() } }
3304    }
3305}
3306
3307impl Sub<Motor> for IdealPoint {
3308    type Output = Motor;
3309
3310    fn sub(self, other: Motor) -> Motor {
3311        Motor { groups: MotorGroups { g0: Simd32x4::from(0.0) - other.group0(), g1: 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.group1() } }
3312    }
3313}
3314
3315impl RegressiveProduct<Motor> for IdealPoint {
3316    type Output = Translator;
3317
3318    fn regressive_product(self, other: Motor) -> Translator {
3319        Translator { groups: TranslatorGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[2], other.group0()[2], other.group1()[0], other.group0()[2]]) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[3], other.group0()[3], other.group0()[3], other.group1()[0]]) * Simd32x4::from([1.0, 0.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group0()[1], other.group1()[0], other.group0()[0], other.group0()[0]]) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) } }
3320    }
3321}
3322
3323impl InnerProduct<Motor> for IdealPoint {
3324    type Output = IdealPoint;
3325
3326    fn inner_product(self, other: Motor) -> IdealPoint {
3327        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x3::from(other.group0()[0]) } }
3328    }
3329}
3330
3331impl RightContraction<Motor> for IdealPoint {
3332    type Output = IdealPoint;
3333
3334    fn right_contraction(self, other: Motor) -> IdealPoint {
3335        IdealPoint { groups: IdealPointGroups { g0: self.group0() * Simd32x3::from(other.group0()[0]) } }
3336    }
3337}
3338
3339impl RegressiveProduct<PointAndPlane> for IdealPoint {
3340    type Output = Plane;
3341
3342    fn regressive_product(self, other: PointAndPlane) -> Plane {
3343        Plane { groups: PlaneGroups { 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]) } }
3344    }
3345}
3346
3347impl Mul<f32> for IdealPoint {
3348    type Output = IdealPoint;
3349
3350    fn mul(self, other: f32) -> IdealPoint {
3351        self.geometric_product(other)
3352    }
3353}
3354
3355impl MulAssign<f32> for IdealPoint {
3356    fn mul_assign(&mut self, other: f32) {
3357        *self = (*self).mul(other);
3358    }
3359}
3360
3361impl Zero for Plane {
3362    fn zero() -> Self {
3363        Plane { groups: PlaneGroups { g0: Simd32x4::from(0.0) } }
3364    }
3365}
3366
3367impl One for Plane {
3368    fn one() -> Self {
3369        Plane { groups: PlaneGroups { g0: Simd32x4::from(0.0) } }
3370    }
3371}
3372
3373impl Neg for Plane {
3374    type Output = Plane;
3375
3376    fn neg(self) -> Plane {
3377        Plane { groups: PlaneGroups { g0: self.group0() * Simd32x4::from(-1.0) } }
3378    }
3379}
3380
3381impl Automorphism for Plane {
3382    type Output = Plane;
3383
3384    fn automorphism(self) -> Plane {
3385        Plane { groups: PlaneGroups { g0: self.group0() * Simd32x4::from(-1.0) } }
3386    }
3387}
3388
3389impl Reversal for Plane {
3390    type Output = Plane;
3391
3392    fn reversal(self) -> Plane {
3393        Plane { groups: PlaneGroups { g0: self.group0() } }
3394    }
3395}
3396
3397impl Conjugation for Plane {
3398    type Output = Plane;
3399
3400    fn conjugation(self) -> Plane {
3401        Plane { groups: PlaneGroups { g0: self.group0() * Simd32x4::from(-1.0) } }
3402    }
3403}
3404
3405impl Dual for Plane {
3406    type Output = Point;
3407
3408    fn dual(self) -> Point {
3409        Point { groups: PointGroups { g0: self.group0() } }
3410    }
3411}
3412
3413impl GeometricProduct<f32> for Plane {
3414    type Output = Plane;
3415
3416    fn geometric_product(self, other: f32) -> Plane {
3417        Plane { groups: PlaneGroups { g0: self.group0() * Simd32x4::from(other) } }
3418    }
3419}
3420
3421impl OuterProduct<f32> for Plane {
3422    type Output = Plane;
3423
3424    fn outer_product(self, other: f32) -> Plane {
3425        Plane { groups: PlaneGroups { g0: self.group0() * Simd32x4::from(other) } }
3426    }
3427}
3428
3429impl InnerProduct<f32> for Plane {
3430    type Output = Plane;
3431
3432    fn inner_product(self, other: f32) -> Plane {
3433        Plane { groups: PlaneGroups { g0: self.group0() * Simd32x4::from(other) } }
3434    }
3435}
3436
3437impl RightContraction<f32> for Plane {
3438    type Output = Plane;
3439
3440    fn right_contraction(self, other: f32) -> Plane {
3441        Plane { groups: PlaneGroups { g0: self.group0() * Simd32x4::from(other) } }
3442    }
3443}
3444
3445impl Add<MultiVector> for Plane {
3446    type Output = MultiVector;
3447
3448    fn add(self, other: MultiVector) -> MultiVector {
3449        MultiVector { groups: MultiVectorGroups { g0: other.group0(), g1: Simd32x4::from(self.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + other.group1(), g2: self.group0() * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) + other.group2(), g3: other.group3() } }
3450    }
3451}
3452
3453impl Sub<MultiVector> for Plane {
3454    type Output = MultiVector;
3455
3456    fn sub(self, other: MultiVector) -> MultiVector {
3457        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(0.0) - other.group0(), g1: Simd32x4::from(self.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) - other.group1(), g2: self.group0() * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) - other.group2(), g3: Simd32x4::from(0.0) - other.group3() } }
3458    }
3459}
3460
3461impl GeometricProduct<MultiVector> for Plane {
3462    type Output = MultiVector;
3463
3464    fn geometric_product(self, other: MultiVector) -> MultiVector {
3465        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[1]) * swizzle!(other.group2(), 1, 0, 3, 2) * Simd32x4::from([1.0, 1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group2(), 2, 3, 0, 1) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group2(), 3, 2, 1, 0) * Simd32x4::from([1.0, -1.0, 1.0, 1.0]), 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.group3(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group3(), 2, 3, 0, 1) * Simd32x4::from([-1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group3(), 3, 2, 1, 0) * Simd32x4::from([-1.0, -1.0, 1.0, 1.0]), g2: Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 3, 0, 1) * Simd32x4::from([1.0, -1.0, 1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([1.0, 1.0, -1.0, 1.0]), g3: Simd32x4::from(self.group0()[0]) * other.group2() + 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([1.0, 1.0, -1.0, -1.0]) } }
3466    }
3467}
3468
3469impl ScalarProduct<MultiVector> for Plane {
3470    type Output = f32;
3471
3472    fn scalar_product(self, other: MultiVector) -> f32 {
3473        self.group0()[1] * other.group2()[1] + self.group0()[2] * other.group2()[2] + self.group0()[3] * other.group2()[3]
3474    }
3475}
3476
3477impl GeometricProduct<Rotor> for Plane {
3478    type Output = PointAndPlane;
3479
3480    fn geometric_product(self, other: Rotor) -> PointAndPlane {
3481        PointAndPlane { groups: PointAndPlaneGroups { 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()[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, 1, 2, 3) * Simd32x4::from([1.0, -1.0, -1.0, -1.0]), g1: Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 3, 3, 0, 1) * Simd32x4::from([0.0, -1.0, 1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 2, 2, 1, 0) * Simd32x4::from([0.0, 1.0, -1.0, 1.0]) + swizzle!(self.group0(), 0, 1, 1, 1) * swizzle!(other.group0(), 0, 0, 3, 2) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) } }
3482    }
3483}
3484
3485impl OuterProduct<Rotor> for Plane {
3486    type Output = PointAndPlane;
3487
3488    fn outer_product(self, other: Rotor) -> PointAndPlane {
3489        PointAndPlane { groups: PointAndPlaneGroups { 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()[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, 1, 2, 3) * Simd32x4::from([1.0, -1.0, -1.0, -1.0]), g1: self.group0() * Simd32x4::from(other.group0()[0]) } }
3490    }
3491}
3492
3493impl InnerProduct<Rotor> for Plane {
3494    type Output = Plane;
3495
3496    fn inner_product(self, other: Rotor) -> Plane {
3497        Plane { groups: PlaneGroups { g0: Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 3, 3, 0, 1) * Simd32x4::from([0.0, -1.0, 1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 2, 2, 1, 0) * Simd32x4::from([0.0, 1.0, -1.0, 1.0]) + swizzle!(self.group0(), 0, 1, 1, 1) * swizzle!(other.group0(), 0, 0, 3, 2) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) } }
3498    }
3499}
3500
3501impl RightContraction<Rotor> for Plane {
3502    type Output = Plane;
3503
3504    fn right_contraction(self, other: Rotor) -> Plane {
3505        Plane { groups: PlaneGroups { g0: self.group0() * Simd32x4::from(other.group0()[0]) } }
3506    }
3507}
3508
3509impl Add<Point> for Plane {
3510    type Output = PointAndPlane;
3511
3512    fn add(self, other: Point) -> PointAndPlane {
3513        PointAndPlane { groups: PointAndPlaneGroups { g0: other.group0(), g1: self.group0() } }
3514    }
3515}
3516
3517impl Sub<Point> for Plane {
3518    type Output = PointAndPlane;
3519
3520    fn sub(self, other: Point) -> PointAndPlane {
3521        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(0.0) - other.group0(), g1: self.group0() } }
3522    }
3523}
3524
3525impl RegressiveProduct<Point> for Plane {
3526    type Output = f32;
3527
3528    fn regressive_product(self, other: Point) -> f32 {
3529        self.group0()[0] * other.group0()[0] + self.group0()[1] * other.group0()[1] + self.group0()[2] * other.group0()[2] + self.group0()[3] * other.group0()[3]
3530    }
3531}
3532
3533impl InnerProduct<Point> for Plane {
3534    type Output = Line;
3535
3536    fn inner_product(self, other: Point) -> Line {
3537        Line { groups: LineGroups { 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]), g1: Simd32x3::from([self.group0()[1], self.group0()[2], self.group0()[3]]) * Simd32x3::from(other.group0()[0]) } }
3538    }
3539}
3540
3541impl LeftContraction<Point> for Plane {
3542    type Output = Line;
3543
3544    fn left_contraction(self, other: Point) -> Line {
3545        Line { groups: LineGroups { 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]), g1: Simd32x3::from([self.group0()[1], self.group0()[2], self.group0()[3]]) * Simd32x3::from(other.group0()[0]) } }
3546    }
3547}
3548
3549impl Add<Plane> for Plane {
3550    type Output = Plane;
3551
3552    fn add(self, other: Plane) -> Plane {
3553        Plane { groups: PlaneGroups { g0: self.group0() + other.group0() } }
3554    }
3555}
3556
3557impl AddAssign<Plane> for Plane {
3558    fn add_assign(&mut self, other: Plane) {
3559        *self = (*self).add(other);
3560    }
3561}
3562
3563impl Sub<Plane> for Plane {
3564    type Output = Plane;
3565
3566    fn sub(self, other: Plane) -> Plane {
3567        Plane { groups: PlaneGroups { g0: self.group0() - other.group0() } }
3568    }
3569}
3570
3571impl SubAssign<Plane> for Plane {
3572    fn sub_assign(&mut self, other: Plane) {
3573        *self = (*self).sub(other);
3574    }
3575}
3576
3577impl Mul<Plane> for Plane {
3578    type Output = Plane;
3579
3580    fn mul(self, other: Plane) -> Plane {
3581        Plane { groups: PlaneGroups { g0: self.group0() * other.group0() } }
3582    }
3583}
3584
3585impl MulAssign<Plane> for Plane {
3586    fn mul_assign(&mut self, other: Plane) {
3587        *self = (*self).mul(other);
3588    }
3589}
3590
3591impl Div<Plane> for Plane {
3592    type Output = Plane;
3593
3594    fn div(self, other: Plane) -> Plane {
3595        Plane { groups: PlaneGroups { 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]) } }
3596    }
3597}
3598
3599impl DivAssign<Plane> for Plane {
3600    fn div_assign(&mut self, other: Plane) {
3601        *self = (*self).div(other);
3602    }
3603}
3604
3605impl OuterProduct<Plane> for Plane {
3606    type Output = Line;
3607
3608    fn outer_product(self, other: Plane) -> Line {
3609        Line { groups: LineGroups { g0: Simd32x3::from(self.group0()[0]) * Simd32x3::from([other.group0()[1], other.group0()[2], other.group0()[3]]) + Simd32x3::from([self.group0()[1], self.group0()[2], self.group0()[3]]) * Simd32x3::from(other.group0()[0]) * Simd32x3::from(-1.0), g1: 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]) } }
3610    }
3611}
3612
3613impl InnerProduct<Plane> for Plane {
3614    type Output = f32;
3615
3616    fn inner_product(self, other: Plane) -> f32 {
3617        self.group0()[1] * other.group0()[1] + self.group0()[2] * other.group0()[2] + self.group0()[3] * other.group0()[3]
3618    }
3619}
3620
3621impl LeftContraction<Plane> for Plane {
3622    type Output = f32;
3623
3624    fn left_contraction(self, other: Plane) -> f32 {
3625        self.group0()[1] * other.group0()[1] + self.group0()[2] * other.group0()[2] + self.group0()[3] * other.group0()[3]
3626    }
3627}
3628
3629impl RightContraction<Plane> for Plane {
3630    type Output = f32;
3631
3632    fn right_contraction(self, other: Plane) -> f32 {
3633        self.group0()[1] * other.group0()[1] + self.group0()[2] * other.group0()[2] + self.group0()[3] * other.group0()[3]
3634    }
3635}
3636
3637impl ScalarProduct<Plane> for Plane {
3638    type Output = f32;
3639
3640    fn scalar_product(self, other: Plane) -> f32 {
3641        self.group0()[1] * other.group0()[1] + self.group0()[2] * other.group0()[2] + self.group0()[3] * other.group0()[3]
3642    }
3643}
3644
3645impl GeometricProduct<Line> for Plane {
3646    type Output = PointAndPlane;
3647
3648    fn geometric_product(self, other: Line) -> PointAndPlane {
3649        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group1()[0], other.group1()[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.group1()[1], other.group0()[2], other.group1()[1], other.group0()[0]]) * Simd32x4::from([1.0, 1.0, 0.0, -1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group1()[2], other.group0()[1], other.group0()[0], other.group1()[2]]) * Simd32x4::from([1.0, -1.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group1()[0], other.group1()[0], other.group1()[1], other.group1()[2]]) * Simd32x4::from([0.0, -1.0, -1.0, -1.0]), g1: Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[1], other.group1()[2], other.group0()[1], other.group1()[0]]) * Simd32x4::from([-1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[2], other.group1()[1], other.group1()[0], other.group0()[2]]) * Simd32x4::from([-1.0, 1.0, -1.0, 0.0]) + swizzle!(self.group0(), 1, 0, 1, 1) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group1()[2], other.group1()[1]]) * Simd32x4::from([-1.0, 0.0, 1.0, -1.0]) } }
3650    }
3651}
3652
3653impl OuterProduct<Line> for Plane {
3654    type Output = Point;
3655
3656    fn outer_product(self, other: Line) -> Point {
3657        Point { groups: PointGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group1()[0], other.group1()[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.group1()[1], other.group0()[2], other.group1()[1], other.group0()[0]]) * Simd32x4::from([1.0, 1.0, 0.0, -1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group1()[2], other.group0()[1], other.group0()[0], other.group1()[2]]) * Simd32x4::from([1.0, -1.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group1()[0], other.group1()[0], other.group1()[1], other.group1()[2]]) * Simd32x4::from([0.0, -1.0, -1.0, -1.0]) } }
3658    }
3659}
3660
3661impl InnerProduct<Line> for Plane {
3662    type Output = Plane;
3663
3664    fn inner_product(self, other: Line) -> Plane {
3665        Plane { groups: PlaneGroups { g0: Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[1], other.group1()[2], other.group0()[1], other.group1()[0]]) * Simd32x4::from([-1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[2], other.group1()[1], other.group1()[0], other.group0()[2]]) * Simd32x4::from([-1.0, 1.0, -1.0, 0.0]) + swizzle!(self.group0(), 1, 0, 1, 1) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group1()[2], other.group1()[1]]) * Simd32x4::from([-1.0, 0.0, 1.0, -1.0]) } }
3666    }
3667}
3668
3669impl LeftContraction<Line> for Plane {
3670    type Output = Plane;
3671
3672    fn left_contraction(self, other: Line) -> Plane {
3673        Plane { groups: PlaneGroups { g0: Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[1], other.group1()[2], other.group0()[1], other.group1()[0]]) * Simd32x4::from([-1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[2], other.group1()[1], other.group1()[0], other.group0()[2]]) * Simd32x4::from([-1.0, 1.0, -1.0, 0.0]) + swizzle!(self.group0(), 1, 0, 1, 1) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group1()[2], other.group1()[1]]) * Simd32x4::from([-1.0, 0.0, 1.0, -1.0]) } }
3674    }
3675}
3676
3677impl InnerProduct<Translator> for Plane {
3678    type Output = Plane;
3679
3680    fn inner_product(self, other: Translator) -> Plane {
3681        Plane { groups: PlaneGroups { 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]) } }
3682    }
3683}
3684
3685impl RightContraction<Translator> for Plane {
3686    type Output = Plane;
3687
3688    fn right_contraction(self, other: Translator) -> Plane {
3689        Plane { groups: PlaneGroups { g0: self.group0() * Simd32x4::from(other.group0()[0]) } }
3690    }
3691}
3692
3693impl GeometricProduct<Motor> for Plane {
3694    type Output = PointAndPlane;
3695
3696    fn geometric_product(self, other: Motor) -> PointAndPlane {
3697        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[1], other.group1()[0], other.group1()[3], other.group1()[2]]) * Simd32x4::from([1.0, 1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[2], other.group1()[3], other.group1()[0], other.group1()[1]]) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[3], other.group1()[2], other.group1()[1], other.group1()[0]]) * Simd32x4::from([1.0, -1.0, 1.0, 1.0]) + Simd32x4::from(self.group0()[0]) * other.group0() * Simd32x4::from([0.0, -1.0, -1.0, -1.0]), g1: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group1()[1], other.group0()[0], other.group0()[3], other.group0()[2]]) * Simd32x4::from([-1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group1()[2], other.group0()[3], other.group0()[0], other.group0()[1]]) * Simd32x4::from([-1.0, -1.0, 1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group1()[3], other.group0()[2], other.group0()[1], other.group0()[0]]) * Simd32x4::from([-1.0, 1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
3698    }
3699}
3700
3701impl RegressiveProduct<Motor> for Plane {
3702    type Output = Plane;
3703
3704    fn regressive_product(self, other: Motor) -> Plane {
3705        Plane { groups: PlaneGroups { g0: self.group0() * Simd32x4::from(other.group1()[0]) } }
3706    }
3707}
3708
3709impl OuterProduct<Motor> for Plane {
3710    type Output = PointAndPlane;
3711
3712    fn outer_product(self, other: Motor) -> PointAndPlane {
3713        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[1], other.group0()[1], other.group1()[3], other.group1()[2]]) * Simd32x4::from([1.0, 0.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[2], other.group1()[3], other.group0()[2], other.group1()[1]]) * Simd32x4::from([1.0, 1.0, 0.0, -1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[3], other.group1()[2], other.group1()[1], other.group0()[3]]) * Simd32x4::from([1.0, -1.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[0]) * other.group0() * Simd32x4::from([0.0, -1.0, -1.0, -1.0]), g1: self.group0() * Simd32x4::from(other.group0()[0]) } }
3714    }
3715}
3716
3717impl RightContraction<Motor> for Plane {
3718    type Output = Plane;
3719
3720    fn right_contraction(self, other: Motor) -> Plane {
3721        Plane { groups: PlaneGroups { g0: self.group0() * Simd32x4::from(other.group0()[0]) } }
3722    }
3723}
3724
3725impl Add<PointAndPlane> for Plane {
3726    type Output = PointAndPlane;
3727
3728    fn add(self, other: PointAndPlane) -> PointAndPlane {
3729        PointAndPlane { groups: PointAndPlaneGroups { g0: other.group0(), g1: self.group0() + other.group1() } }
3730    }
3731}
3732
3733impl Sub<PointAndPlane> for Plane {
3734    type Output = PointAndPlane;
3735
3736    fn sub(self, other: PointAndPlane) -> PointAndPlane {
3737        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(0.0) - other.group0(), g1: self.group0() - other.group1() } }
3738    }
3739}
3740
3741impl GeometricProduct<PointAndPlane> for Plane {
3742    type Output = Motor;
3743
3744    fn geometric_product(self, other: PointAndPlane) -> Motor {
3745        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group1()[1], other.group0()[0], other.group1()[3], other.group1()[2]]) * Simd32x4::from([1.0, 1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group1()[2], other.group1()[3], other.group0()[0], other.group1()[1]]) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group1()[3], other.group1()[2], other.group1()[1], other.group0()[0]]) * Simd32x4::from([1.0, -1.0, 1.0, 1.0]), g1: Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group0()[0], other.group1()[1], other.group1()[2], other.group1()[3]]) + Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[1], other.group1()[0], other.group0()[3], other.group0()[2]]) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[2], other.group0()[3], other.group1()[0], other.group0()[1]]) * Simd32x4::from([1.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[3], other.group0()[2], other.group0()[1], other.group1()[0]]) * Simd32x4::from([1.0, 1.0, -1.0, -1.0]) } }
3746    }
3747}
3748
3749impl RegressiveProduct<PointAndPlane> for Plane {
3750    type Output = f32;
3751
3752    fn regressive_product(self, other: PointAndPlane) -> f32 {
3753        self.group0()[0] * other.group0()[0] + self.group0()[1] * other.group0()[1] + self.group0()[2] * other.group0()[2] + self.group0()[3] * other.group0()[3]
3754    }
3755}
3756
3757impl RightContraction<PointAndPlane> for Plane {
3758    type Output = f32;
3759
3760    fn right_contraction(self, other: PointAndPlane) -> f32 {
3761        self.group0()[1] * other.group1()[1] + self.group0()[2] * other.group1()[2] + self.group0()[3] * other.group1()[3]
3762    }
3763}
3764
3765impl ScalarProduct<PointAndPlane> for Plane {
3766    type Output = f32;
3767
3768    fn scalar_product(self, other: PointAndPlane) -> f32 {
3769        self.group0()[1] * other.group1()[1] + self.group0()[2] * other.group1()[2] + self.group0()[3] * other.group1()[3]
3770    }
3771}
3772
3773impl SquaredMagnitude for Plane {
3774    type Output = f32;
3775
3776    fn squared_magnitude(self) -> f32 {
3777        self.scalar_product(self.reversal())
3778    }
3779}
3780
3781impl Magnitude for Plane {
3782    type Output = f32;
3783
3784    fn magnitude(self) -> f32 {
3785        self.squared_magnitude().sqrt()
3786    }
3787}
3788
3789impl Mul<f32> for Plane {
3790    type Output = Plane;
3791
3792    fn mul(self, other: f32) -> Plane {
3793        self.geometric_product(other)
3794    }
3795}
3796
3797impl MulAssign<f32> for Plane {
3798    fn mul_assign(&mut self, other: f32) {
3799        *self = (*self).mul(other);
3800    }
3801}
3802
3803impl Signum for Plane {
3804    type Output = Plane;
3805
3806    fn signum(self) -> Plane {
3807        self.geometric_product(1.0 / self.magnitude())
3808    }
3809}
3810
3811impl Inverse for Plane {
3812    type Output = Plane;
3813
3814    fn inverse(self) -> Plane {
3815        self.reversal().geometric_product(1.0 / self.squared_magnitude())
3816    }
3817}
3818
3819impl Zero for Line {
3820    fn zero() -> Self {
3821        Line { groups: LineGroups { g0: Simd32x3::from(0.0), g1: Simd32x3::from(0.0) } }
3822    }
3823}
3824
3825impl One for Line {
3826    fn one() -> Self {
3827        Line { groups: LineGroups { g0: Simd32x3::from(0.0), g1: Simd32x3::from(0.0) } }
3828    }
3829}
3830
3831impl Neg for Line {
3832    type Output = Line;
3833
3834    fn neg(self) -> Line {
3835        Line { groups: LineGroups { g0: self.group0() * Simd32x3::from(-1.0), g1: self.group1() * Simd32x3::from(-1.0) } }
3836    }
3837}
3838
3839impl Automorphism for Line {
3840    type Output = Line;
3841
3842    fn automorphism(self) -> Line {
3843        Line { groups: LineGroups { g0: self.group0(), g1: self.group1() } }
3844    }
3845}
3846
3847impl Reversal for Line {
3848    type Output = Line;
3849
3850    fn reversal(self) -> Line {
3851        Line { groups: LineGroups { g0: self.group0() * Simd32x3::from(-1.0), g1: self.group1() * Simd32x3::from(-1.0) } }
3852    }
3853}
3854
3855impl Conjugation for Line {
3856    type Output = Line;
3857
3858    fn conjugation(self) -> Line {
3859        Line { groups: LineGroups { g0: self.group0() * Simd32x3::from(-1.0), g1: self.group1() * Simd32x3::from(-1.0) } }
3860    }
3861}
3862
3863impl Dual for Line {
3864    type Output = Line;
3865
3866    fn dual(self) -> Line {
3867        Line { groups: LineGroups { g0: self.group1(), g1: self.group0() } }
3868    }
3869}
3870
3871impl GeometricProduct<f32> for Line {
3872    type Output = Line;
3873
3874    fn geometric_product(self, other: f32) -> Line {
3875        Line { groups: LineGroups { g0: self.group0() * Simd32x3::from(other), g1: self.group1() * Simd32x3::from(other) } }
3876    }
3877}
3878
3879impl OuterProduct<f32> for Line {
3880    type Output = Line;
3881
3882    fn outer_product(self, other: f32) -> Line {
3883        Line { groups: LineGroups { g0: self.group0() * Simd32x3::from(other), g1: self.group1() * Simd32x3::from(other) } }
3884    }
3885}
3886
3887impl InnerProduct<f32> for Line {
3888    type Output = Line;
3889
3890    fn inner_product(self, other: f32) -> Line {
3891        Line { groups: LineGroups { g0: self.group0() * Simd32x3::from(other), g1: self.group1() * Simd32x3::from(other) } }
3892    }
3893}
3894
3895impl RightContraction<f32> for Line {
3896    type Output = Line;
3897
3898    fn right_contraction(self, other: f32) -> Line {
3899        Line { groups: LineGroups { g0: self.group0() * Simd32x3::from(other), g1: self.group1() * Simd32x3::from(other) } }
3900    }
3901}
3902
3903impl Add<MultiVector> for Line {
3904    type Output = MultiVector;
3905
3906    fn add(self, other: MultiVector) -> MultiVector {
3907        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from([self.group0()[0], self.group1()[0], self.group1()[1], self.group1()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) + other.group0(), g1: other.group1(), g2: other.group2(), g3: 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.group3() } }
3908    }
3909}
3910
3911impl Sub<MultiVector> for Line {
3912    type Output = MultiVector;
3913
3914    fn sub(self, other: MultiVector) -> MultiVector {
3915        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from([self.group0()[0], self.group1()[0], self.group1()[1], self.group1()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) - other.group0(), g1: Simd32x4::from(0.0) - other.group1(), g2: Simd32x4::from(0.0) - other.group2(), g3: 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.group3() } }
3916    }
3917}
3918
3919impl GeometricProduct<MultiVector> for Line {
3920    type Output = MultiVector;
3921
3922    fn geometric_product(self, other: MultiVector) -> MultiVector {
3923        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group1()[0]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[1]) * swizzle!(other.group0(), 2, 3, 0, 1) * Simd32x4::from([-1.0, -1.0, 1.0, 1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([-1.0, 1.0, -1.0, 1.0]), g1: Simd32x4::from(self.group0()[0]) * swizzle!(other.group2(), 1, 0, 3, 2) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[1]) * swizzle!(other.group2(), 2, 3, 0, 1) * Simd32x4::from([1.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group2(), 3, 2, 1, 0) * Simd32x4::from([1.0, 1.0, -1.0, -1.0]) + Simd32x4::from(self.group1()[0]) * swizzle!(other.group1(), 1, 0, 3, 2) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[1]) * swizzle!(other.group1(), 2, 3, 0, 1) * Simd32x4::from([1.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group1(), 3, 2, 1, 0) * Simd32x4::from([1.0, 1.0, -1.0, -1.0]), g2: Simd32x4::from(self.group1()[0]) * swizzle!(other.group2(), 1, 0, 3, 2) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[1]) * swizzle!(other.group2(), 2, 3, 0, 1) * Simd32x4::from([1.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group2(), 3, 2, 1, 0) * Simd32x4::from([1.0, 1.0, -1.0, -1.0]), g3: Simd32x4::from(self.group0()[0]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 2, 3, 0, 1) * Simd32x4::from([1.0, -1.0, 1.0, 1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([1.0, 1.0, -1.0, 1.0]) + Simd32x4::from(self.group1()[0]) * swizzle!(other.group3(), 1, 0, 3, 2) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[1]) * swizzle!(other.group3(), 2, 3, 0, 1) * Simd32x4::from([1.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group3(), 3, 2, 1, 0) * Simd32x4::from([1.0, 1.0, -1.0, -1.0]) } }
3924    }
3925}
3926
3927impl ScalarProduct<MultiVector> for Line {
3928    type Output = f32;
3929
3930    fn scalar_product(self, other: MultiVector) -> f32 {
3931        0.0 - self.group1()[0] * other.group0()[1] - self.group1()[1] * other.group0()[2] - self.group1()[2] * other.group0()[3]
3932    }
3933}
3934
3935impl GeometricProduct<Rotor> for Line {
3936    type Output = Motor;
3937
3938    fn geometric_product(self, other: Rotor) -> Motor {
3939        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group1()[0]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[1]) * swizzle!(other.group0(), 2, 3, 0, 1) * Simd32x4::from([-1.0, -1.0, 1.0, 1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([-1.0, 1.0, -1.0, 1.0]), g1: Simd32x4::from(self.group0()[0]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[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]) } }
3940    }
3941}
3942
3943impl RegressiveProduct<Rotor> for Line {
3944    type Output = f32;
3945
3946    fn regressive_product(self, other: Rotor) -> f32 {
3947        self.group0()[0] * other.group0()[1] + self.group0()[1] * other.group0()[2] + self.group0()[2] * other.group0()[3]
3948    }
3949}
3950
3951impl LeftContraction<Rotor> for Line {
3952    type Output = f32;
3953
3954    fn left_contraction(self, other: Rotor) -> f32 {
3955        0.0 - self.group1()[0] * other.group0()[1] - self.group1()[1] * other.group0()[2] - self.group1()[2] * other.group0()[3]
3956    }
3957}
3958
3959impl ScalarProduct<Rotor> for Line {
3960    type Output = f32;
3961
3962    fn scalar_product(self, other: Rotor) -> f32 {
3963        0.0 - self.group1()[0] * other.group0()[1] - self.group1()[1] * other.group0()[2] - self.group1()[2] * other.group0()[3]
3964    }
3965}
3966
3967impl RegressiveProduct<Point> for Line {
3968    type Output = Plane;
3969
3970    fn regressive_product(self, other: Point) -> Plane {
3971        Plane { groups: PlaneGroups { 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.group1()[1]) * swizzle!(other.group0(), 3, 3, 3, 1) * Simd32x4::from([0.0, 1.0, 0.0, -1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group0(), 2, 2, 1, 2) * Simd32x4::from([0.0, -1.0, 1.0, 0.0]) + Simd32x4::from([self.group0()[0], self.group0()[0], self.group1()[0], self.group1()[0]]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, -1.0, 1.0]) } }
3972    }
3973}
3974
3975impl InnerProduct<Point> for Line {
3976    type Output = Plane;
3977
3978    fn inner_product(self, other: Point) -> Plane {
3979        Plane { groups: PlaneGroups { g0: Simd32x4::from(self.group1()[1]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, -1.0, 0.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, -1.0]) + Simd32x4::from(self.group1()[0]) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, -1.0, 0.0, 0.0]) } }
3980    }
3981}
3982
3983impl LeftContraction<Point> for Line {
3984    type Output = Plane;
3985
3986    fn left_contraction(self, other: Point) -> Plane {
3987        Plane { groups: PlaneGroups { g0: Simd32x4::from(self.group1()[1]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, -1.0, 0.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, -1.0]) + Simd32x4::from(self.group1()[0]) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, -1.0, 0.0, 0.0]) } }
3988    }
3989}
3990
3991impl Into<IdealPoint> for Line {
3992    fn into(self) -> IdealPoint {
3993        IdealPoint { groups: IdealPointGroups { g0: self.group0() } }
3994    }
3995}
3996
3997impl Add<IdealPoint> for Line {
3998    type Output = Line;
3999
4000    fn add(self, other: IdealPoint) -> Line {
4001        Line { groups: LineGroups { g0: self.group0() + other.group0(), g1: self.group1() } }
4002    }
4003}
4004
4005impl AddAssign<IdealPoint> for Line {
4006    fn add_assign(&mut self, other: IdealPoint) {
4007        *self = (*self).add(other);
4008    }
4009}
4010
4011impl Sub<IdealPoint> for Line {
4012    type Output = Line;
4013
4014    fn sub(self, other: IdealPoint) -> Line {
4015        Line { groups: LineGroups { g0: self.group0() - other.group0(), g1: self.group1() } }
4016    }
4017}
4018
4019impl SubAssign<IdealPoint> for Line {
4020    fn sub_assign(&mut self, other: IdealPoint) {
4021        *self = (*self).sub(other);
4022    }
4023}
4024
4025impl RegressiveProduct<IdealPoint> for Line {
4026    type Output = f32;
4027
4028    fn regressive_product(self, other: IdealPoint) -> f32 {
4029        self.group1()[0] * other.group0()[0] + self.group1()[1] * other.group0()[1] + self.group1()[2] * other.group0()[2]
4030    }
4031}
4032
4033impl GeometricProduct<Plane> for Line {
4034    type Output = PointAndPlane;
4035
4036    fn geometric_product(self, other: Plane) -> PointAndPlane {
4037        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 3, 3, 3, 1) * Simd32x4::from([0.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 1, 2) * Simd32x4::from([0.0, 1.0, -1.0, 0.0]) + Simd32x4::from(self.group1()[1]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, -1.0, 0.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, -1.0]) + Simd32x4::from([self.group1()[0], self.group1()[0], self.group0()[0], 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()[1]) * Simd32x4::from(other.group0()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group0()[3]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[1]) * swizzle!(other.group0(), 3, 3, 3, 1) * Simd32x4::from([0.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group0(), 2, 2, 1, 2) * Simd32x4::from([0.0, 1.0, -1.0, 0.0]) + Simd32x4::from([self.group0()[0], self.group0()[0], self.group1()[0], self.group1()[0]]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([1.0, 0.0, 1.0, -1.0]) } }
4038    }
4039}
4040
4041impl OuterProduct<Plane> for Line {
4042    type Output = Point;
4043
4044    fn outer_product(self, other: Plane) -> Point {
4045        Point { groups: PointGroups { g0: Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 3, 3, 3, 1) * Simd32x4::from([0.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 1, 2) * Simd32x4::from([0.0, 1.0, -1.0, 0.0]) + Simd32x4::from(self.group1()[1]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, -1.0, 0.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, -1.0]) + Simd32x4::from([self.group1()[0], self.group1()[0], self.group0()[0], self.group0()[0]]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) } }
4046    }
4047}
4048
4049impl InnerProduct<Plane> for Line {
4050    type Output = Plane;
4051
4052    fn inner_product(self, other: Plane) -> Plane {
4053        Plane { groups: PlaneGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from(other.group0()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group0()[3]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[1]) * swizzle!(other.group0(), 3, 3, 3, 1) * Simd32x4::from([0.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group0(), 2, 2, 1, 2) * Simd32x4::from([0.0, 1.0, -1.0, 0.0]) + Simd32x4::from([self.group0()[0], self.group0()[0], self.group1()[0], self.group1()[0]]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([1.0, 0.0, 1.0, -1.0]) } }
4054    }
4055}
4056
4057impl RightContraction<Plane> for Line {
4058    type Output = Plane;
4059
4060    fn right_contraction(self, other: Plane) -> Plane {
4061        Plane { groups: PlaneGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from(other.group0()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group0()[3]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[1]) * swizzle!(other.group0(), 3, 3, 3, 1) * Simd32x4::from([0.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group0(), 2, 2, 1, 2) * Simd32x4::from([0.0, 1.0, -1.0, 0.0]) + Simd32x4::from([self.group0()[0], self.group0()[0], self.group1()[0], self.group1()[0]]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([1.0, 0.0, 1.0, -1.0]) } }
4062    }
4063}
4064
4065impl Add<Line> for Line {
4066    type Output = Line;
4067
4068    fn add(self, other: Line) -> Line {
4069        Line { groups: LineGroups { g0: self.group0() + other.group0(), g1: self.group1() + other.group1() } }
4070    }
4071}
4072
4073impl AddAssign<Line> for Line {
4074    fn add_assign(&mut self, other: Line) {
4075        *self = (*self).add(other);
4076    }
4077}
4078
4079impl Sub<Line> for Line {
4080    type Output = Line;
4081
4082    fn sub(self, other: Line) -> Line {
4083        Line { groups: LineGroups { g0: self.group0() - other.group0(), g1: self.group1() - other.group1() } }
4084    }
4085}
4086
4087impl SubAssign<Line> for Line {
4088    fn sub_assign(&mut self, other: Line) {
4089        *self = (*self).sub(other);
4090    }
4091}
4092
4093impl Mul<Line> for Line {
4094    type Output = Line;
4095
4096    fn mul(self, other: Line) -> Line {
4097        Line { groups: LineGroups { g0: self.group0() * other.group0(), g1: self.group1() * other.group1() } }
4098    }
4099}
4100
4101impl MulAssign<Line> for Line {
4102    fn mul_assign(&mut self, other: Line) {
4103        *self = (*self).mul(other);
4104    }
4105}
4106
4107impl Div<Line> for Line {
4108    type Output = Line;
4109
4110    fn div(self, other: Line) -> Line {
4111        Line { groups: LineGroups { 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]), g1: Simd32x3::from([self.group1()[0], self.group1()[1], self.group1()[2]]) * Simd32x3::from([1.0, 1.0, 1.0]) / Simd32x3::from([other.group1()[0], other.group1()[1], other.group1()[2]]) * Simd32x3::from([1.0, 1.0, 1.0]) } }
4112    }
4113}
4114
4115impl DivAssign<Line> for Line {
4116    fn div_assign(&mut self, other: Line) {
4117        *self = (*self).div(other);
4118    }
4119}
4120
4121impl GeometricProduct<Line> for Line {
4122    type Output = Motor;
4123
4124    fn geometric_product(self, other: Line) -> Motor {
4125        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group1()[1]) * Simd32x4::from([other.group1()[1], other.group1()[2], other.group1()[1], other.group1()[0]]) * Simd32x4::from([-1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from([other.group1()[2], other.group1()[1], other.group1()[0], other.group1()[2]]) * Simd32x4::from([-1.0, 1.0, -1.0, 0.0]) + Simd32x4::from(self.group1()[0]) * Simd32x4::from([other.group1()[0], other.group1()[0], other.group1()[2], other.group1()[1]]) * Simd32x4::from([-1.0, 0.0, 1.0, -1.0]), g1: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group1()[1], other.group1()[2], other.group1()[1], other.group1()[0]]) * Simd32x4::from([1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group1()[2], other.group1()[1], other.group1()[0], other.group1()[2]]) * Simd32x4::from([1.0, 1.0, -1.0, 0.0]) + Simd32x4::from(self.group1()[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]) + Simd32x4::from(self.group1()[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.group1()[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.group1()[0], other.group1()[0], other.group1()[2], other.group1()[1]]) * Simd32x4::from([1.0, 0.0, 1.0, -1.0]) } }
4126    }
4127}
4128
4129impl RegressiveProduct<Line> for Line {
4130    type Output = f32;
4131
4132    fn regressive_product(self, other: Line) -> f32 {
4133        self.group0()[0] * other.group1()[0] + self.group0()[1] * other.group1()[1] + self.group0()[2] * other.group1()[2] + self.group1()[0] * other.group0()[0] + self.group1()[1] * other.group0()[1] + self.group1()[2] * other.group0()[2]
4134    }
4135}
4136
4137impl InnerProduct<Line> for Line {
4138    type Output = f32;
4139
4140    fn inner_product(self, other: Line) -> f32 {
4141        0.0 - self.group1()[0] * other.group1()[0] - self.group1()[1] * other.group1()[1] - self.group1()[2] * other.group1()[2]
4142    }
4143}
4144
4145impl LeftContraction<Line> for Line {
4146    type Output = f32;
4147
4148    fn left_contraction(self, other: Line) -> f32 {
4149        0.0 - self.group1()[0] * other.group1()[0] - self.group1()[1] * other.group1()[1] - self.group1()[2] * other.group1()[2]
4150    }
4151}
4152
4153impl RightContraction<Line> for Line {
4154    type Output = f32;
4155
4156    fn right_contraction(self, other: Line) -> f32 {
4157        0.0 - self.group1()[0] * other.group1()[0] - self.group1()[1] * other.group1()[1] - self.group1()[2] * other.group1()[2]
4158    }
4159}
4160
4161impl ScalarProduct<Line> for Line {
4162    type Output = f32;
4163
4164    fn scalar_product(self, other: Line) -> f32 {
4165        0.0 - self.group1()[0] * other.group1()[0] - self.group1()[1] * other.group1()[1] - self.group1()[2] * other.group1()[2]
4166    }
4167}
4168
4169impl RegressiveProduct<Translator> for Line {
4170    type Output = f32;
4171
4172    fn regressive_product(self, other: Translator) -> f32 {
4173        self.group1()[0] * other.group0()[1] + self.group1()[1] * other.group0()[2] + self.group1()[2] * other.group0()[3]
4174    }
4175}
4176
4177impl InnerProduct<Translator> for Line {
4178    type Output = Line;
4179
4180    fn inner_product(self, other: Translator) -> Line {
4181        Line { groups: LineGroups { g0: self.group0() * Simd32x3::from(other.group0()[0]), g1: self.group1() * Simd32x3::from(other.group0()[0]) } }
4182    }
4183}
4184
4185impl RightContraction<Translator> for Line {
4186    type Output = Line;
4187
4188    fn right_contraction(self, other: Translator) -> Line {
4189        Line { groups: LineGroups { g0: self.group0() * Simd32x3::from(other.group0()[0]), g1: self.group1() * Simd32x3::from(other.group0()[0]) } }
4190    }
4191}
4192
4193impl Add<Motor> for Line {
4194    type Output = Motor;
4195
4196    fn add(self, other: Motor) -> Motor {
4197        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group1()[0], self.group1()[1], self.group1()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) + other.group0(), g1: 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.group1() } }
4198    }
4199}
4200
4201impl Sub<Motor> for Line {
4202    type Output = Motor;
4203
4204    fn sub(self, other: Motor) -> Motor {
4205        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group1()[0], self.group1()[1], self.group1()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) - other.group0(), g1: 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.group1() } }
4206    }
4207}
4208
4209impl GeometricProduct<Motor> for Line {
4210    type Output = Motor;
4211
4212    fn geometric_product(self, other: Motor) -> Motor {
4213        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group1()[0]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[1]) * swizzle!(other.group0(), 2, 3, 0, 1) * Simd32x4::from([-1.0, -1.0, 1.0, 1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([-1.0, 1.0, -1.0, 1.0]), g1: Simd32x4::from(self.group0()[0]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[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.group1()[0]) * swizzle!(other.group1(), 1, 0, 3, 2) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[1]) * swizzle!(other.group1(), 2, 3, 0, 1) * Simd32x4::from([1.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group1(), 3, 2, 1, 0) * Simd32x4::from([1.0, 1.0, -1.0, -1.0]) } }
4214    }
4215}
4216
4217impl LeftContraction<Motor> for Line {
4218    type Output = Translator;
4219
4220    fn left_contraction(self, other: Motor) -> Translator {
4221        Translator { groups: TranslatorGroups { g0: Simd32x4::from(self.group1()[1]) * Simd32x4::from([other.group0()[2], other.group0()[2], other.group1()[0], other.group0()[2]]) * Simd32x4::from([-1.0, 0.0, -1.0, 0.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from([other.group0()[3], other.group0()[3], other.group0()[3], other.group1()[0]]) * Simd32x4::from([-1.0, 0.0, 0.0, -1.0]) + Simd32x4::from(self.group1()[0]) * Simd32x4::from([other.group0()[1], other.group1()[0], other.group0()[0], other.group0()[0]]) * Simd32x4::from([-1.0, -1.0, 0.0, 0.0]) } }
4222    }
4223}
4224
4225impl ScalarProduct<Motor> for Line {
4226    type Output = f32;
4227
4228    fn scalar_product(self, other: Motor) -> f32 {
4229        0.0 - self.group1()[0] * other.group0()[1] - self.group1()[1] * other.group0()[2] - self.group1()[2] * other.group0()[3]
4230    }
4231}
4232
4233impl GeometricProduct<PointAndPlane> for Line {
4234    type Output = PointAndPlane;
4235
4236    fn geometric_product(self, other: PointAndPlane) -> PointAndPlane {
4237        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group1()[3], other.group1()[3], other.group0()[0], other.group1()[1]]) * Simd32x4::from([0.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group1()[2], other.group1()[2], other.group1()[1], other.group0()[0]]) * Simd32x4::from([0.0, 1.0, -1.0, -1.0]) + Simd32x4::from(self.group1()[0]) * Simd32x4::from([other.group1()[1], other.group1()[0], other.group0()[3], other.group0()[2]]) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[1]) * Simd32x4::from([other.group1()[2], other.group0()[3], other.group1()[0], other.group0()[1]]) * Simd32x4::from([1.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from([other.group1()[3], other.group0()[2], other.group0()[1], other.group1()[0]]) * Simd32x4::from([1.0, 1.0, -1.0, -1.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group1()[3], other.group1()[2]]) * Simd32x4::from([0.0, -1.0, 1.0, -1.0]), g1: Simd32x4::from(self.group0()[1]) * Simd32x4::from(other.group1()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group1()[3]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[0]) * Simd32x4::from([other.group0()[1], other.group0()[0], other.group1()[3], other.group1()[2]]) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[1]) * Simd32x4::from([other.group0()[2], other.group1()[3], other.group0()[0], other.group1()[1]]) * Simd32x4::from([1.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from([other.group0()[3], other.group1()[2], other.group1()[1], other.group0()[0]]) * Simd32x4::from([1.0, 1.0, -1.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]) } }
4238    }
4239}
4240
4241impl RegressiveProduct<PointAndPlane> for Line {
4242    type Output = Plane;
4243
4244    fn regressive_product(self, other: PointAndPlane) -> Plane {
4245        Plane { groups: PlaneGroups { 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.group1()[1]) * swizzle!(other.group0(), 3, 3, 3, 1) * Simd32x4::from([0.0, 1.0, 0.0, -1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group0(), 2, 2, 1, 2) * Simd32x4::from([0.0, -1.0, 1.0, 0.0]) + Simd32x4::from([self.group0()[0], self.group0()[0], self.group1()[0], self.group1()[0]]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, -1.0, 1.0]) } }
4246    }
4247}
4248
4249impl OuterProduct<PointAndPlane> for Line {
4250    type Output = Point;
4251
4252    fn outer_product(self, other: PointAndPlane) -> Point {
4253        Point { groups: PointGroups { g0: Simd32x4::from(self.group0()[1]) * swizzle!(other.group1(), 3, 3, 3, 1) * Simd32x4::from([0.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group1(), 2, 2, 1, 2) * Simd32x4::from([0.0, 1.0, -1.0, 0.0]) + Simd32x4::from(self.group1()[1]) * swizzle!(other.group1(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, -1.0, 0.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group1(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, -1.0]) + Simd32x4::from([self.group1()[0], self.group1()[0], self.group0()[0], self.group0()[0]]) * swizzle!(other.group1(), 1, 0, 3, 2) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) } }
4254    }
4255}
4256
4257impl InnerProduct<PointAndPlane> for Line {
4258    type Output = Plane;
4259
4260    fn inner_product(self, other: PointAndPlane) -> Plane {
4261        Plane { groups: PlaneGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from(other.group1()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group1()[3]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[0]) * Simd32x4::from([other.group0()[1], other.group0()[0], other.group1()[3], other.group1()[2]]) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[1]) * Simd32x4::from([other.group0()[2], other.group1()[3], other.group0()[0], other.group1()[1]]) * Simd32x4::from([1.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from([other.group0()[3], other.group1()[2], other.group1()[1], other.group0()[0]]) * Simd32x4::from([1.0, 1.0, -1.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]) } }
4262    }
4263}
4264
4265impl LeftContraction<PointAndPlane> for Line {
4266    type Output = Plane;
4267
4268    fn left_contraction(self, other: PointAndPlane) -> Plane {
4269        Plane { groups: PlaneGroups { g0: Simd32x4::from(self.group1()[1]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, -1.0, 0.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, -1.0]) + Simd32x4::from(self.group1()[0]) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, -1.0, 0.0, 0.0]) } }
4270    }
4271}
4272
4273impl RightContraction<PointAndPlane> for Line {
4274    type Output = Plane;
4275
4276    fn right_contraction(self, other: PointAndPlane) -> Plane {
4277        Plane { groups: PlaneGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from(other.group1()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group1()[3]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[1]) * swizzle!(other.group1(), 3, 3, 3, 1) * Simd32x4::from([0.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group1(), 2, 2, 1, 2) * Simd32x4::from([0.0, 1.0, -1.0, 0.0]) + Simd32x4::from([self.group0()[0], self.group0()[0], self.group1()[0], self.group1()[0]]) * swizzle!(other.group1(), 1, 0, 3, 2) * Simd32x4::from([1.0, 0.0, 1.0, -1.0]) } }
4278    }
4279}
4280
4281impl SquaredMagnitude for Line {
4282    type Output = f32;
4283
4284    fn squared_magnitude(self) -> f32 {
4285        self.scalar_product(self.reversal())
4286    }
4287}
4288
4289impl Magnitude for Line {
4290    type Output = f32;
4291
4292    fn magnitude(self) -> f32 {
4293        self.squared_magnitude().sqrt()
4294    }
4295}
4296
4297impl Mul<f32> for Line {
4298    type Output = Line;
4299
4300    fn mul(self, other: f32) -> Line {
4301        self.geometric_product(other)
4302    }
4303}
4304
4305impl MulAssign<f32> for Line {
4306    fn mul_assign(&mut self, other: f32) {
4307        *self = (*self).mul(other);
4308    }
4309}
4310
4311impl Signum for Line {
4312    type Output = Line;
4313
4314    fn signum(self) -> Line {
4315        self.geometric_product(1.0 / self.magnitude())
4316    }
4317}
4318
4319impl Inverse for Line {
4320    type Output = Line;
4321
4322    fn inverse(self) -> Line {
4323        self.reversal().geometric_product(1.0 / self.squared_magnitude())
4324    }
4325}
4326
4327impl Zero for Translator {
4328    fn zero() -> Self {
4329        Translator { groups: TranslatorGroups { g0: Simd32x4::from(0.0) } }
4330    }
4331}
4332
4333impl One for Translator {
4334    fn one() -> Self {
4335        Translator { groups: TranslatorGroups { g0: Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
4336    }
4337}
4338
4339impl Neg for Translator {
4340    type Output = Translator;
4341
4342    fn neg(self) -> Translator {
4343        Translator { groups: TranslatorGroups { g0: self.group0() * Simd32x4::from(-1.0) } }
4344    }
4345}
4346
4347impl Automorphism for Translator {
4348    type Output = Translator;
4349
4350    fn automorphism(self) -> Translator {
4351        Translator { groups: TranslatorGroups { g0: self.group0() } }
4352    }
4353}
4354
4355impl Reversal for Translator {
4356    type Output = Translator;
4357
4358    fn reversal(self) -> Translator {
4359        Translator { groups: TranslatorGroups { g0: self.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) } }
4360    }
4361}
4362
4363impl Conjugation for Translator {
4364    type Output = Translator;
4365
4366    fn conjugation(self) -> Translator {
4367        Translator { groups: TranslatorGroups { g0: self.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) } }
4368    }
4369}
4370
4371impl Into<f32> for Translator {
4372    fn into(self) -> f32 {
4373        self.group0()[0]
4374    }
4375}
4376
4377impl Add<f32> for Translator {
4378    type Output = Translator;
4379
4380    fn add(self, other: f32) -> Translator {
4381        Translator { groups: TranslatorGroups { g0: self.group0() + Simd32x4::from(other) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
4382    }
4383}
4384
4385impl AddAssign<f32> for Translator {
4386    fn add_assign(&mut self, other: f32) {
4387        *self = (*self).add(other);
4388    }
4389}
4390
4391impl Sub<f32> for Translator {
4392    type Output = Translator;
4393
4394    fn sub(self, other: f32) -> Translator {
4395        Translator { groups: TranslatorGroups { g0: self.group0() - Simd32x4::from(other) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
4396    }
4397}
4398
4399impl SubAssign<f32> for Translator {
4400    fn sub_assign(&mut self, other: f32) {
4401        *self = (*self).sub(other);
4402    }
4403}
4404
4405impl GeometricProduct<f32> for Translator {
4406    type Output = Translator;
4407
4408    fn geometric_product(self, other: f32) -> Translator {
4409        Translator { groups: TranslatorGroups { g0: self.group0() * Simd32x4::from(other) } }
4410    }
4411}
4412
4413impl OuterProduct<f32> for Translator {
4414    type Output = Translator;
4415
4416    fn outer_product(self, other: f32) -> Translator {
4417        Translator { groups: TranslatorGroups { g0: self.group0() * Simd32x4::from(other) } }
4418    }
4419}
4420
4421impl InnerProduct<f32> for Translator {
4422    type Output = Translator;
4423
4424    fn inner_product(self, other: f32) -> Translator {
4425        Translator { groups: TranslatorGroups { g0: self.group0() * Simd32x4::from(other) } }
4426    }
4427}
4428
4429impl LeftContraction<f32> for Translator {
4430    type Output = f32;
4431
4432    fn left_contraction(self, other: f32) -> f32 {
4433        self.group0()[0] * other
4434    }
4435}
4436
4437impl RightContraction<f32> for Translator {
4438    type Output = Translator;
4439
4440    fn right_contraction(self, other: f32) -> Translator {
4441        Translator { groups: TranslatorGroups { g0: self.group0() * Simd32x4::from(other) } }
4442    }
4443}
4444
4445impl ScalarProduct<f32> for Translator {
4446    type Output = f32;
4447
4448    fn scalar_product(self, other: f32) -> f32 {
4449        self.group0()[0] * other
4450    }
4451}
4452
4453impl Add<MultiVector> for Translator {
4454    type Output = MultiVector;
4455
4456    fn add(self, other: MultiVector) -> MultiVector {
4457        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + other.group0(), g1: other.group1(), g2: other.group2(), g3: self.group0() * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) + other.group3() } }
4458    }
4459}
4460
4461impl Sub<MultiVector> for Translator {
4462    type Output = MultiVector;
4463
4464    fn sub(self, other: MultiVector) -> MultiVector {
4465        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) - other.group0(), g1: Simd32x4::from(0.0) - other.group1(), g2: Simd32x4::from(0.0) - other.group2(), g3: self.group0() * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) - other.group3() } }
4466    }
4467}
4468
4469impl GeometricProduct<MultiVector> for Translator {
4470    type Output = MultiVector;
4471
4472    fn geometric_product(self, other: MultiVector) -> MultiVector {
4473        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.group2(), 1, 0, 3, 2) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group2(), 2, 3, 0, 1) * Simd32x4::from([1.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group2(), 3, 2, 1, 0) * Simd32x4::from([1.0, 1.0, -1.0, -1.0]), g2: Simd32x4::from(self.group0()[0]) * other.group2(), g3: Simd32x4::from(self.group0()[0]) * other.group3() + Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 3, 0, 1) * Simd32x4::from([1.0, -1.0, 1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([1.0, 1.0, -1.0, 1.0]) } }
4474    }
4475}
4476
4477impl OuterProduct<MultiVector> for Translator {
4478    type Output = MultiVector;
4479
4480    fn outer_product(self, other: MultiVector) -> MultiVector {
4481        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.group2(), 3, 3, 3, 1) * Simd32x4::from([0.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group2(), 2, 2, 1, 2) * Simd32x4::from([0.0, 1.0, -1.0, 0.0]) + swizzle!(self.group0(), 0, 0, 1, 1) * swizzle!(other.group2(), 0, 0, 3, 2) * Simd32x4::from([0.0, 0.0, 1.0, -1.0]), g2: Simd32x4::from(self.group0()[0]) * other.group2(), g3: Simd32x4::from(self.group0()[0]) * other.group3() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, 1.0]) + swizzle!(self.group0(), 1, 1, 0, 0) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) } }
4482    }
4483}
4484
4485impl InnerProduct<MultiVector> for Translator {
4486    type Output = MultiVector;
4487
4488    fn inner_product(self, other: MultiVector) -> MultiVector {
4489        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0(), g1: Simd32x4::from(self.group0()[0]) * other.group1() + Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group2()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group2()[3]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0, 0) * swizzle!(other.group2(), 1, 0, 0, 0) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]), g2: Simd32x4::from(self.group0()[0]) * other.group2(), g3: Simd32x4::from(self.group0()[0]) * other.group3() + self.group0() * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
4490    }
4491}
4492
4493impl LeftContraction<MultiVector> for Translator {
4494    type Output = MultiVector;
4495
4496    fn left_contraction(self, other: MultiVector) -> MultiVector {
4497        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0(), g1: Simd32x4::from(self.group0()[0]) * other.group1(), g2: Simd32x4::from(self.group0()[0]) * other.group2(), g3: Simd32x4::from(self.group0()[0]) * other.group3() } }
4498    }
4499}
4500
4501impl ScalarProduct<MultiVector> for Translator {
4502    type Output = f32;
4503
4504    fn scalar_product(self, other: MultiVector) -> f32 {
4505        self.group0()[0] * other.group0()[0]
4506    }
4507}
4508
4509impl GeometricProduct<Rotor> for Translator {
4510    type Output = Motor;
4511
4512    fn geometric_product(self, other: Rotor) -> Motor {
4513        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0(), g1: Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 3, 0, 1) * Simd32x4::from([1.0, -1.0, 1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([1.0, 1.0, -1.0, 1.0]) } }
4514    }
4515}
4516
4517impl RegressiveProduct<Rotor> for Translator {
4518    type Output = f32;
4519
4520    fn regressive_product(self, other: Rotor) -> f32 {
4521        self.group0()[1] * other.group0()[1] + self.group0()[2] * other.group0()[2] + self.group0()[3] * other.group0()[3]
4522    }
4523}
4524
4525impl OuterProduct<Rotor> for Translator {
4526    type Output = Motor;
4527
4528    fn outer_product(self, other: Rotor) -> Motor {
4529        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0(), g1: Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, 1.0]) + swizzle!(self.group0(), 1, 1, 0, 0) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) } }
4530    }
4531}
4532
4533impl LeftContraction<Rotor> for Translator {
4534    type Output = Rotor;
4535
4536    fn left_contraction(self, other: Rotor) -> Rotor {
4537        Rotor { groups: RotorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() } }
4538    }
4539}
4540
4541impl RightContraction<Rotor> for Translator {
4542    type Output = Translator;
4543
4544    fn right_contraction(self, other: Rotor) -> Translator {
4545        Translator { groups: TranslatorGroups { g0: self.group0() * Simd32x4::from(other.group0()[0]) } }
4546    }
4547}
4548
4549impl ScalarProduct<Rotor> for Translator {
4550    type Output = f32;
4551
4552    fn scalar_product(self, other: Rotor) -> f32 {
4553        self.group0()[0] * other.group0()[0]
4554    }
4555}
4556
4557impl GeometricProduct<Point> for Translator {
4558    type Output = Point;
4559
4560    fn geometric_product(self, other: Point) -> Point {
4561        Point { groups: PointGroups { 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]) } }
4562    }
4563}
4564
4565impl RegressiveProduct<Point> for Translator {
4566    type Output = Plane;
4567
4568    fn regressive_product(self, other: Point) -> Plane {
4569        Plane { groups: PlaneGroups { g0: Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([-1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 1.0]) + swizzle!(self.group0(), 1, 1, 0, 0) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]) } }
4570    }
4571}
4572
4573impl OuterProduct<Point> for Translator {
4574    type Output = Point;
4575
4576    fn outer_product(self, other: Point) -> Point {
4577        Point { groups: PointGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() } }
4578    }
4579}
4580
4581impl InnerProduct<Point> for Translator {
4582    type Output = Point;
4583
4584    fn inner_product(self, other: Point) -> Point {
4585        Point { groups: PointGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() } }
4586    }
4587}
4588
4589impl LeftContraction<Point> for Translator {
4590    type Output = Point;
4591
4592    fn left_contraction(self, other: Point) -> Point {
4593        Point { groups: PointGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() } }
4594    }
4595}
4596
4597impl Into<IdealPoint> for Translator {
4598    fn into(self) -> IdealPoint {
4599        IdealPoint { groups: IdealPointGroups { g0: Simd32x3::from([self.group0()[1], self.group0()[2], self.group0()[3]]) } }
4600    }
4601}
4602
4603impl Add<IdealPoint> for Translator {
4604    type Output = Translator;
4605
4606    fn add(self, other: IdealPoint) -> Translator {
4607        Translator { groups: TranslatorGroups { 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]) } }
4608    }
4609}
4610
4611impl AddAssign<IdealPoint> for Translator {
4612    fn add_assign(&mut self, other: IdealPoint) {
4613        *self = (*self).add(other);
4614    }
4615}
4616
4617impl Sub<IdealPoint> for Translator {
4618    type Output = Translator;
4619
4620    fn sub(self, other: IdealPoint) -> Translator {
4621        Translator { groups: TranslatorGroups { 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]) } }
4622    }
4623}
4624
4625impl SubAssign<IdealPoint> for Translator {
4626    fn sub_assign(&mut self, other: IdealPoint) {
4627        *self = (*self).sub(other);
4628    }
4629}
4630
4631impl GeometricProduct<IdealPoint> for Translator {
4632    type Output = IdealPoint;
4633
4634    fn geometric_product(self, other: IdealPoint) -> IdealPoint {
4635        IdealPoint { groups: IdealPointGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() } }
4636    }
4637}
4638
4639impl OuterProduct<IdealPoint> for Translator {
4640    type Output = IdealPoint;
4641
4642    fn outer_product(self, other: IdealPoint) -> IdealPoint {
4643        IdealPoint { groups: IdealPointGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() } }
4644    }
4645}
4646
4647impl InnerProduct<IdealPoint> for Translator {
4648    type Output = IdealPoint;
4649
4650    fn inner_product(self, other: IdealPoint) -> IdealPoint {
4651        IdealPoint { groups: IdealPointGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() } }
4652    }
4653}
4654
4655impl LeftContraction<IdealPoint> for Translator {
4656    type Output = IdealPoint;
4657
4658    fn left_contraction(self, other: IdealPoint) -> IdealPoint {
4659        IdealPoint { groups: IdealPointGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() } }
4660    }
4661}
4662
4663impl InnerProduct<Plane> for Translator {
4664    type Output = Plane;
4665
4666    fn inner_product(self, other: Plane) -> Plane {
4667        Plane { groups: PlaneGroups { 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]) } }
4668    }
4669}
4670
4671impl LeftContraction<Plane> for Translator {
4672    type Output = Plane;
4673
4674    fn left_contraction(self, other: Plane) -> Plane {
4675        Plane { groups: PlaneGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() } }
4676    }
4677}
4678
4679impl RegressiveProduct<Line> for Translator {
4680    type Output = f32;
4681
4682    fn regressive_product(self, other: Line) -> f32 {
4683        self.group0()[1] * other.group1()[0] + self.group0()[2] * other.group1()[1] + self.group0()[3] * other.group1()[2]
4684    }
4685}
4686
4687impl InnerProduct<Line> for Translator {
4688    type Output = Line;
4689
4690    fn inner_product(self, other: Line) -> Line {
4691        Line { groups: LineGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0(), g1: Simd32x3::from(self.group0()[0]) * other.group1() } }
4692    }
4693}
4694
4695impl LeftContraction<Line> for Translator {
4696    type Output = Line;
4697
4698    fn left_contraction(self, other: Line) -> Line {
4699        Line { groups: LineGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0(), g1: Simd32x3::from(self.group0()[0]) * other.group1() } }
4700    }
4701}
4702
4703impl Add<Translator> for Translator {
4704    type Output = Translator;
4705
4706    fn add(self, other: Translator) -> Translator {
4707        Translator { groups: TranslatorGroups { g0: self.group0() + other.group0() } }
4708    }
4709}
4710
4711impl AddAssign<Translator> for Translator {
4712    fn add_assign(&mut self, other: Translator) {
4713        *self = (*self).add(other);
4714    }
4715}
4716
4717impl Sub<Translator> for Translator {
4718    type Output = Translator;
4719
4720    fn sub(self, other: Translator) -> Translator {
4721        Translator { groups: TranslatorGroups { g0: self.group0() - other.group0() } }
4722    }
4723}
4724
4725impl SubAssign<Translator> for Translator {
4726    fn sub_assign(&mut self, other: Translator) {
4727        *self = (*self).sub(other);
4728    }
4729}
4730
4731impl Mul<Translator> for Translator {
4732    type Output = Translator;
4733
4734    fn mul(self, other: Translator) -> Translator {
4735        Translator { groups: TranslatorGroups { g0: self.group0() * other.group0() } }
4736    }
4737}
4738
4739impl MulAssign<Translator> for Translator {
4740    fn mul_assign(&mut self, other: Translator) {
4741        *self = (*self).mul(other);
4742    }
4743}
4744
4745impl Div<Translator> for Translator {
4746    type Output = Translator;
4747
4748    fn div(self, other: Translator) -> Translator {
4749        Translator { groups: TranslatorGroups { 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]) } }
4750    }
4751}
4752
4753impl DivAssign<Translator> for Translator {
4754    fn div_assign(&mut self, other: Translator) {
4755        *self = (*self).div(other);
4756    }
4757}
4758
4759impl GeometricProduct<Translator> for Translator {
4760    type Output = Translator;
4761
4762    fn geometric_product(self, other: Translator) -> Translator {
4763        Translator { groups: TranslatorGroups { 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]) } }
4764    }
4765}
4766
4767impl OuterProduct<Translator> for Translator {
4768    type Output = Translator;
4769
4770    fn outer_product(self, other: Translator) -> Translator {
4771        Translator { groups: TranslatorGroups { 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]) } }
4772    }
4773}
4774
4775impl InnerProduct<Translator> for Translator {
4776    type Output = Translator;
4777
4778    fn inner_product(self, other: Translator) -> Translator {
4779        Translator { groups: TranslatorGroups { 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]) } }
4780    }
4781}
4782
4783impl LeftContraction<Translator> for Translator {
4784    type Output = Translator;
4785
4786    fn left_contraction(self, other: Translator) -> Translator {
4787        Translator { groups: TranslatorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() } }
4788    }
4789}
4790
4791impl RightContraction<Translator> for Translator {
4792    type Output = Translator;
4793
4794    fn right_contraction(self, other: Translator) -> Translator {
4795        Translator { groups: TranslatorGroups { g0: self.group0() * Simd32x4::from(other.group0()[0]) } }
4796    }
4797}
4798
4799impl ScalarProduct<Translator> for Translator {
4800    type Output = f32;
4801
4802    fn scalar_product(self, other: Translator) -> f32 {
4803        self.group0()[0] * other.group0()[0]
4804    }
4805}
4806
4807impl Add<Motor> for Translator {
4808    type Output = Motor;
4809
4810    fn add(self, other: Motor) -> Motor {
4811        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + other.group0(), g1: self.group0() * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) + other.group1() } }
4812    }
4813}
4814
4815impl Sub<Motor> for Translator {
4816    type Output = Motor;
4817
4818    fn sub(self, other: Motor) -> Motor {
4819        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) - other.group0(), g1: self.group0() * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) - other.group1() } }
4820    }
4821}
4822
4823impl GeometricProduct<Motor> for Translator {
4824    type Output = Motor;
4825
4826    fn geometric_product(self, other: Motor) -> Motor {
4827        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0(), g1: Simd32x4::from(self.group0()[0]) * other.group1() + Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 3, 0, 1) * Simd32x4::from([1.0, -1.0, 1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([1.0, 1.0, -1.0, 1.0]) } }
4828    }
4829}
4830
4831impl RegressiveProduct<Motor> for Translator {
4832    type Output = Translator;
4833
4834    fn regressive_product(self, other: Motor) -> Translator {
4835        Translator { groups: TranslatorGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[1], other.group1()[0], 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()[2], other.group1()[0], other.group0()[2]]) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[3], other.group0()[3], other.group0()[3], other.group1()[0]]) * Simd32x4::from([1.0, 0.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from(other.group1()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
4836    }
4837}
4838
4839impl OuterProduct<Motor> for Translator {
4840    type Output = Motor;
4841
4842    fn outer_product(self, other: Motor) -> Motor {
4843        Motor { groups: MotorGroups { 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, 0, 2) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, 1.0]) + swizzle!(self.group0(), 1, 1, 0, 0) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) } }
4844    }
4845}
4846
4847impl InnerProduct<Motor> for Translator {
4848    type Output = Motor;
4849
4850    fn inner_product(self, other: Motor) -> Motor {
4851        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0(), g1: Simd32x4::from(self.group0()[0]) * other.group1() + self.group0() * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
4852    }
4853}
4854
4855impl LeftContraction<Motor> for Translator {
4856    type Output = Motor;
4857
4858    fn left_contraction(self, other: Motor) -> Motor {
4859        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0(), g1: Simd32x4::from(self.group0()[0]) * other.group1() } }
4860    }
4861}
4862
4863impl RightContraction<Motor> for Translator {
4864    type Output = Translator;
4865
4866    fn right_contraction(self, other: Motor) -> Translator {
4867        Translator { groups: TranslatorGroups { g0: self.group0() * Simd32x4::from(other.group0()[0]) } }
4868    }
4869}
4870
4871impl ScalarProduct<Motor> for Translator {
4872    type Output = f32;
4873
4874    fn scalar_product(self, other: Motor) -> f32 {
4875        self.group0()[0] * other.group0()[0]
4876    }
4877}
4878
4879impl GeometricProduct<PointAndPlane> for Translator {
4880    type Output = PointAndPlane;
4881
4882    fn geometric_product(self, other: PointAndPlane) -> PointAndPlane {
4883        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group1()[3], other.group1()[3], other.group0()[0], other.group1()[1]]) * Simd32x4::from([0.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group1()[2], other.group1()[2], other.group1()[1], other.group0()[0]]) * Simd32x4::from([0.0, 1.0, -1.0, -1.0]) + swizzle!(self.group0(), 0, 1, 1, 1) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group1()[3], other.group1()[2]]) * Simd32x4::from([0.0, -1.0, 1.0, -1.0]), g1: Simd32x4::from(self.group0()[0]) * other.group1() + Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group1()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group1()[3]) * Simd32x4::from([1.0, 0.0, 0.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]) } }
4884    }
4885}
4886
4887impl RegressiveProduct<PointAndPlane> for Translator {
4888    type Output = Plane;
4889
4890    fn regressive_product(self, other: PointAndPlane) -> Plane {
4891        Plane { groups: PlaneGroups { g0: Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([-1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 1.0]) + swizzle!(self.group0(), 1, 1, 0, 0) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]) } }
4892    }
4893}
4894
4895impl OuterProduct<PointAndPlane> for Translator {
4896    type Output = PointAndPlane;
4897
4898    fn outer_product(self, other: PointAndPlane) -> PointAndPlane {
4899        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group1(), 3, 3, 3, 1) * Simd32x4::from([0.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group1(), 2, 2, 1, 2) * Simd32x4::from([0.0, 1.0, -1.0, 0.0]) + swizzle!(self.group0(), 0, 0, 1, 1) * swizzle!(other.group1(), 0, 0, 3, 2) * Simd32x4::from([0.0, 0.0, 1.0, -1.0]), g1: Simd32x4::from(self.group0()[0]) * other.group1() } }
4900    }
4901}
4902
4903impl InnerProduct<PointAndPlane> for Translator {
4904    type Output = PointAndPlane;
4905
4906    fn inner_product(self, other: PointAndPlane) -> PointAndPlane {
4907        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0(), g1: Simd32x4::from(self.group0()[0]) * other.group1() + Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group1()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group1()[3]) * Simd32x4::from([1.0, 0.0, 0.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]) } }
4908    }
4909}
4910
4911impl LeftContraction<PointAndPlane> for Translator {
4912    type Output = PointAndPlane;
4913
4914    fn left_contraction(self, other: PointAndPlane) -> PointAndPlane {
4915        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0(), g1: Simd32x4::from(self.group0()[0]) * other.group1() } }
4916    }
4917}
4918
4919impl SquaredMagnitude for Translator {
4920    type Output = f32;
4921
4922    fn squared_magnitude(self) -> f32 {
4923        self.scalar_product(self.reversal())
4924    }
4925}
4926
4927impl Magnitude for Translator {
4928    type Output = f32;
4929
4930    fn magnitude(self) -> f32 {
4931        self.squared_magnitude().sqrt()
4932    }
4933}
4934
4935impl Mul<f32> for Translator {
4936    type Output = Translator;
4937
4938    fn mul(self, other: f32) -> Translator {
4939        self.geometric_product(other)
4940    }
4941}
4942
4943impl MulAssign<f32> for Translator {
4944    fn mul_assign(&mut self, other: f32) {
4945        *self = (*self).mul(other);
4946    }
4947}
4948
4949impl Signum for Translator {
4950    type Output = Translator;
4951
4952    fn signum(self) -> Translator {
4953        self.geometric_product(1.0 / self.magnitude())
4954    }
4955}
4956
4957impl Inverse for Translator {
4958    type Output = Translator;
4959
4960    fn inverse(self) -> Translator {
4961        self.reversal().geometric_product(1.0 / self.squared_magnitude())
4962    }
4963}
4964
4965impl Zero for Motor {
4966    fn zero() -> Self {
4967        Motor { groups: MotorGroups { g0: Simd32x4::from(0.0), g1: Simd32x4::from(0.0) } }
4968    }
4969}
4970
4971impl One for Motor {
4972    fn one() -> Self {
4973        Motor { groups: MotorGroups { g0: Simd32x4::from([1.0, 0.0, 0.0, 0.0]), g1: Simd32x4::from(0.0) } }
4974    }
4975}
4976
4977impl Neg for Motor {
4978    type Output = Motor;
4979
4980    fn neg(self) -> Motor {
4981        Motor { groups: MotorGroups { g0: self.group0() * Simd32x4::from(-1.0), g1: self.group1() * Simd32x4::from(-1.0) } }
4982    }
4983}
4984
4985impl Automorphism for Motor {
4986    type Output = Motor;
4987
4988    fn automorphism(self) -> Motor {
4989        Motor { groups: MotorGroups { g0: self.group0(), g1: self.group1() } }
4990    }
4991}
4992
4993impl Reversal for Motor {
4994    type Output = Motor;
4995
4996    fn reversal(self) -> Motor {
4997        Motor { groups: MotorGroups { 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]) } }
4998    }
4999}
5000
5001impl Conjugation for Motor {
5002    type Output = Motor;
5003
5004    fn conjugation(self) -> Motor {
5005        Motor { groups: MotorGroups { 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]) } }
5006    }
5007}
5008
5009impl Dual for Motor {
5010    type Output = Motor;
5011
5012    fn dual(self) -> Motor {
5013        Motor { groups: MotorGroups { g0: self.group1(), g1: self.group0() } }
5014    }
5015}
5016
5017impl Into<f32> for Motor {
5018    fn into(self) -> f32 {
5019        self.group0()[0]
5020    }
5021}
5022
5023impl Add<f32> for Motor {
5024    type Output = Motor;
5025
5026    fn add(self, other: f32) -> Motor {
5027        Motor { groups: MotorGroups { g0: self.group0() + Simd32x4::from(other) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]), g1: self.group1() } }
5028    }
5029}
5030
5031impl AddAssign<f32> for Motor {
5032    fn add_assign(&mut self, other: f32) {
5033        *self = (*self).add(other);
5034    }
5035}
5036
5037impl Sub<f32> for Motor {
5038    type Output = Motor;
5039
5040    fn sub(self, other: f32) -> Motor {
5041        Motor { groups: MotorGroups { g0: self.group0() - Simd32x4::from(other) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]), g1: self.group1() } }
5042    }
5043}
5044
5045impl SubAssign<f32> for Motor {
5046    fn sub_assign(&mut self, other: f32) {
5047        *self = (*self).sub(other);
5048    }
5049}
5050
5051impl GeometricProduct<f32> for Motor {
5052    type Output = Motor;
5053
5054    fn geometric_product(self, other: f32) -> Motor {
5055        Motor { groups: MotorGroups { g0: self.group0() * Simd32x4::from(other), g1: self.group1() * Simd32x4::from(other) } }
5056    }
5057}
5058
5059impl RegressiveProduct<f32> for Motor {
5060    type Output = f32;
5061
5062    fn regressive_product(self, other: f32) -> f32 {
5063        self.group1()[0] * other
5064    }
5065}
5066
5067impl OuterProduct<f32> for Motor {
5068    type Output = Motor;
5069
5070    fn outer_product(self, other: f32) -> Motor {
5071        Motor { groups: MotorGroups { g0: self.group0() * Simd32x4::from(other), g1: self.group1() * Simd32x4::from(other) } }
5072    }
5073}
5074
5075impl InnerProduct<f32> for Motor {
5076    type Output = Motor;
5077
5078    fn inner_product(self, other: f32) -> Motor {
5079        Motor { groups: MotorGroups { g0: self.group0() * Simd32x4::from(other), g1: self.group1() * Simd32x4::from(other) } }
5080    }
5081}
5082
5083impl LeftContraction<f32> for Motor {
5084    type Output = f32;
5085
5086    fn left_contraction(self, other: f32) -> f32 {
5087        self.group0()[0] * other
5088    }
5089}
5090
5091impl RightContraction<f32> for Motor {
5092    type Output = Motor;
5093
5094    fn right_contraction(self, other: f32) -> Motor {
5095        Motor { groups: MotorGroups { g0: self.group0() * Simd32x4::from(other), g1: self.group1() * Simd32x4::from(other) } }
5096    }
5097}
5098
5099impl ScalarProduct<f32> for Motor {
5100    type Output = f32;
5101
5102    fn scalar_product(self, other: f32) -> f32 {
5103        self.group0()[0] * other
5104    }
5105}
5106
5107impl Add<MultiVector> for Motor {
5108    type Output = MultiVector;
5109
5110    fn add(self, other: MultiVector) -> MultiVector {
5111        MultiVector { groups: MultiVectorGroups { g0: self.group0() + other.group0(), g1: other.group1(), g2: other.group2(), g3: self.group1() + other.group3() } }
5112    }
5113}
5114
5115impl Sub<MultiVector> for Motor {
5116    type Output = MultiVector;
5117
5118    fn sub(self, other: MultiVector) -> MultiVector {
5119        MultiVector { groups: MultiVectorGroups { g0: self.group0() - other.group0(), g1: Simd32x4::from(0.0) - other.group1(), g2: Simd32x4::from(0.0) - other.group2(), g3: self.group1() - other.group3() } }
5120    }
5121}
5122
5123impl GeometricProduct<MultiVector> for Motor {
5124    type Output = MultiVector;
5125
5126    fn geometric_product(self, other: MultiVector) -> MultiVector {
5127        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([-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]), 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([1.0, 1.0, -1.0, -1.0]) - Simd32x4::from(self.group1()[0]) * other.group2() + Simd32x4::from(self.group1()[1]) * swizzle!(other.group2(), 1, 0, 3, 2) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group2(), 2, 3, 0, 1) * Simd32x4::from([1.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group2(), 3, 2, 1, 0) * Simd32x4::from([1.0, 1.0, -1.0, -1.0]), g2: Simd32x4::from(self.group0()[0]) * other.group2() + Simd32x4::from(self.group0()[1]) * swizzle!(other.group2(), 1, 0, 3, 2) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group2(), 2, 3, 0, 1) * Simd32x4::from([1.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group2(), 3, 2, 1, 0) * Simd32x4::from([1.0, 1.0, -1.0, -1.0]), g3: Simd32x4::from(self.group0()[0]) * other.group3() + Simd32x4::from(self.group0()[1]) * swizzle!(other.group3(), 1, 0, 3, 2) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group3(), 2, 3, 0, 1) * Simd32x4::from([1.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group3(), 3, 2, 1, 0) * Simd32x4::from([1.0, 1.0, -1.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]) * 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]) } }
5128    }
5129}
5130
5131impl RegressiveProduct<MultiVector> for Motor {
5132    type Output = MultiVector;
5133
5134    fn regressive_product(self, other: MultiVector) -> MultiVector {
5135        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[1]) * swizzle!(other.group3(), 1, 0, 1, 1) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group3(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group3(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, 1.0]) + Simd32x4::from(self.group1()[0]) * other.group0() + Simd32x4::from(self.group1()[1]) * Simd32x4::from(other.group0()[1]) * Simd32x4::from([1.0, 0.0, 0.0, 0.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]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from(other.group3()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]), g1: Simd32x4::from(self.group1()[0]) * other.group1() + Simd32x4::from(self.group1()[2]) * Simd32x4::from(other.group1()[2]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from(other.group1()[3]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + swizzle!(self.group1(), 1, 0, 0, 0) * swizzle!(other.group1(), 1, 0, 0, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]), g2: Simd32x4::from(self.group0()[2]) * swizzle!(other.group1(), 3, 3, 3, 1) * Simd32x4::from([0.0, 1.0, 0.0, -1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group1(), 2, 2, 1, 2) * Simd32x4::from([0.0, -1.0, 1.0, 0.0]) + Simd32x4::from(self.group1()[0]) * other.group2() + Simd32x4::from(self.group1()[2]) * Simd32x4::from(other.group2()[0]) * Simd32x4::from([0.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from(other.group2()[0]) * Simd32x4::from([0.0, 0.0, 0.0, 1.0]) + Simd32x4::from([self.group0()[0], self.group1()[1], self.group0()[1], self.group0()[1]]) * Simd32x4::from([other.group1()[0], other.group2()[0], other.group1()[3], other.group1()[2]]) * Simd32x4::from([0.0, 1.0, -1.0, 1.0]), g3: Simd32x4::from(self.group1()[0]) * other.group3() + self.group1() * Simd32x4::from(other.group3()[0]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
5136    }
5137}
5138
5139impl OuterProduct<MultiVector> for Motor {
5140    type Output = MultiVector;
5141
5142    fn outer_product(self, other: MultiVector) -> MultiVector {
5143        MultiVector { groups: MultiVectorGroups { 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]), g1: Simd32x4::from(self.group0()[0]) * other.group1() + Simd32x4::from(self.group1()[1]) * swizzle!(other.group2(), 3, 3, 3, 2) * Simd32x4::from([0.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group2(), 3, 3, 3, 1) * Simd32x4::from([0.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group2(), 2, 2, 1, 2) * Simd32x4::from([0.0, 1.0, -1.0, 0.0]) + self.group0() * Simd32x4::from(other.group1()[0]) * Simd32x4::from([0.0, -1.0, -1.0, -1.0]), g2: Simd32x4::from(self.group0()[0]) * other.group2() + Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group2()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group2()[3]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0, 0) * swizzle!(other.group2(), 1, 0, 0, 0) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]), g3: Simd32x4::from(self.group0()[0]) * other.group3() + Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group3()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group3()[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]) * 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.group3(), 1, 0, 0, 0) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
5144    }
5145}
5146
5147impl InnerProduct<MultiVector> for Motor {
5148    type Output = MultiVector;
5149
5150    fn inner_product(self, other: MultiVector) -> MultiVector {
5151        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([-1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 1.0]) + swizzle!(self.group0(), 1, 1, 0, 0) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]), g1: Simd32x4::from(self.group0()[0]) * other.group1() + Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group1()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group1()[3]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) - Simd32x4::from(self.group1()[0]) * other.group2() + Simd32x4::from(self.group1()[1]) * Simd32x4::from(other.group2()[1]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from(other.group2()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from(other.group2()[3]) * Simd32x4::from([1.0, 0.0, 0.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]), g2: Simd32x4::from(self.group0()[0]) * other.group2() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group2(), 3, 3, 0, 1) * Simd32x4::from([0.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group2(), 2, 2, 1, 0) * Simd32x4::from([0.0, 1.0, -1.0, -1.0]) + swizzle!(self.group0(), 0, 1, 1, 1) * swizzle!(other.group2(), 0, 0, 3, 2) * Simd32x4::from([0.0, -1.0, 1.0, -1.0]), g3: Simd32x4::from(self.group0()[0]) * other.group3() + 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]) * 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]) + self.group0() * Simd32x4::from(other.group3()[0]) * Simd32x4::from([0.0, -1.0, -1.0, -1.0]) } }
5152    }
5153}
5154
5155impl LeftContraction<MultiVector> for Motor {
5156    type Output = MultiVector;
5157
5158    fn left_contraction(self, other: MultiVector) -> MultiVector {
5159        MultiVector { groups: MultiVectorGroups { 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]), g1: Simd32x4::from(self.group0()[0]) * other.group1() + Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group1()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group1()[3]) * Simd32x4::from([1.0, 0.0, 0.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]), g2: Simd32x4::from(self.group0()[0]) * other.group2() + self.group0() * Simd32x4::from(other.group2()[0]) * Simd32x4::from([0.0, -1.0, -1.0, -1.0]), g3: Simd32x4::from(self.group0()[0]) * other.group3() + self.group0() * Simd32x4::from(other.group3()[0]) * Simd32x4::from([0.0, -1.0, -1.0, -1.0]) } }
5160    }
5161}
5162
5163impl ScalarProduct<MultiVector> for Motor {
5164    type Output = f32;
5165
5166    fn scalar_product(self, other: MultiVector) -> f32 {
5167        self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group0()[1] - self.group0()[2] * other.group0()[2] - self.group0()[3] * other.group0()[3]
5168    }
5169}
5170
5171impl Into<Rotor> for Motor {
5172    fn into(self) -> Rotor {
5173        Rotor { groups: RotorGroups { g0: self.group0() } }
5174    }
5175}
5176
5177impl Add<Rotor> for Motor {
5178    type Output = Motor;
5179
5180    fn add(self, other: Rotor) -> Motor {
5181        Motor { groups: MotorGroups { g0: self.group0() + other.group0(), g1: self.group1() } }
5182    }
5183}
5184
5185impl AddAssign<Rotor> for Motor {
5186    fn add_assign(&mut self, other: Rotor) {
5187        *self = (*self).add(other);
5188    }
5189}
5190
5191impl Sub<Rotor> for Motor {
5192    type Output = Motor;
5193
5194    fn sub(self, other: Rotor) -> Motor {
5195        Motor { groups: MotorGroups { g0: self.group0() - other.group0(), g1: self.group1() } }
5196    }
5197}
5198
5199impl SubAssign<Rotor> for Motor {
5200    fn sub_assign(&mut self, other: Rotor) {
5201        *self = (*self).sub(other);
5202    }
5203}
5204
5205impl GeometricProduct<Rotor> for Motor {
5206    type Output = Motor;
5207
5208    fn geometric_product(self, other: Rotor) -> Motor {
5209        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 3, 0, 1) * Simd32x4::from([-1.0, -1.0, 1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([-1.0, 1.0, -1.0, 1.0]), g1: 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]) } }
5210    }
5211}
5212
5213impl RegressiveProduct<Rotor> for Motor {
5214    type Output = Rotor;
5215
5216    fn regressive_product(self, other: Rotor) -> Rotor {
5217        Rotor { groups: RotorGroups { g0: Simd32x4::from(self.group1()[0]) * other.group0() + 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.group1(), 1, 0, 0, 0) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) } }
5218    }
5219}
5220
5221impl OuterProduct<Rotor> for Motor {
5222    type Output = Motor;
5223
5224    fn outer_product(self, other: Rotor) -> Motor {
5225        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]), g1: 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(), 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]) } }
5226    }
5227}
5228
5229impl InnerProduct<Rotor> for Motor {
5230    type Output = Motor;
5231
5232    fn inner_product(self, other: Rotor) -> Motor {
5233        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([-1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 1.0]) + swizzle!(self.group0(), 1, 1, 0, 0) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]), g1: Simd32x4::from(self.group1()[0]) * other.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) + self.group1() * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
5234    }
5235}
5236
5237impl LeftContraction<Rotor> for Motor {
5238    type Output = Rotor;
5239
5240    fn left_contraction(self, other: Rotor) -> Rotor {
5241        Rotor { groups: RotorGroups { 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]) } }
5242    }
5243}
5244
5245impl RightContraction<Rotor> for Motor {
5246    type Output = Motor;
5247
5248    fn right_contraction(self, other: Rotor) -> Motor {
5249        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]), g1: Simd32x4::from(self.group1()[0]) * other.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) + self.group1() * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
5250    }
5251}
5252
5253impl ScalarProduct<Rotor> for Motor {
5254    type Output = f32;
5255
5256    fn scalar_product(self, other: Rotor) -> f32 {
5257        self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group0()[1] - self.group0()[2] * other.group0()[2] - self.group0()[3] * other.group0()[3]
5258    }
5259}
5260
5261impl GeometricProduct<Point> for Motor {
5262    type Output = PointAndPlane;
5263
5264    fn geometric_product(self, other: Point) -> PointAndPlane {
5265        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 3, 3, 3, 1) * Simd32x4::from([0.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 2, 2, 1, 2) * Simd32x4::from([0.0, 1.0, -1.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()[0], self.group1()[1], self.group0()[1], self.group0()[1]]) * swizzle!(other.group0(), 0, 0, 3, 2) * Simd32x4::from([0.0, -1.0, 1.0, -1.0]), g1: Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, -1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, -1.0]) + Simd32x4::from(self.group1()[0]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + swizzle!(self.group0(), 1, 1, 0, 0) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, -1.0, 0.0, 0.0]) } }
5266    }
5267}
5268
5269impl RegressiveProduct<Point> for Motor {
5270    type Output = PointAndPlane;
5271
5272    fn regressive_product(self, other: Point) -> PointAndPlane {
5273        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self.group1()[0]) * other.group0(), g1: Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 3, 3, 3, 1) * Simd32x4::from([0.0, 1.0, 0.0, -1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 2, 2, 1, 2) * Simd32x4::from([0.0, -1.0, 1.0, 0.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()[1], self.group1()[1], self.group0()[1], self.group0()[1]]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, -1.0, 1.0]) } }
5274    }
5275}
5276
5277impl OuterProduct<Point> for Motor {
5278    type Output = Point;
5279
5280    fn outer_product(self, other: Point) -> Point {
5281        Point { groups: PointGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() } }
5282    }
5283}
5284
5285impl InnerProduct<Point> for Motor {
5286    type Output = PointAndPlane;
5287
5288    fn inner_product(self, other: Point) -> PointAndPlane {
5289        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0(), g1: Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, -1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, -1.0]) + Simd32x4::from(self.group1()[0]) * Simd32x4::from(other.group0()[0]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + swizzle!(self.group0(), 1, 1, 0, 0) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, -1.0, 0.0, 0.0]) } }
5290    }
5291}
5292
5293impl LeftContraction<Point> for Motor {
5294    type Output = PointAndPlane;
5295
5296    fn left_contraction(self, other: Point) -> PointAndPlane {
5297        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0(), g1: Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, -1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, -1.0]) + swizzle!(self.group0(), 1, 1, 0, 0) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, -1.0, 0.0, 0.0]) } }
5298    }
5299}
5300
5301impl Into<IdealPoint> for Motor {
5302    fn into(self) -> IdealPoint {
5303        IdealPoint { groups: IdealPointGroups { g0: Simd32x3::from([self.group1()[1], self.group1()[2], self.group1()[3]]) } }
5304    }
5305}
5306
5307impl Add<IdealPoint> for Motor {
5308    type Output = Motor;
5309
5310    fn add(self, other: IdealPoint) -> Motor {
5311        Motor { groups: MotorGroups { g0: self.group0(), g1: self.group1() + Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
5312    }
5313}
5314
5315impl AddAssign<IdealPoint> for Motor {
5316    fn add_assign(&mut self, other: IdealPoint) {
5317        *self = (*self).add(other);
5318    }
5319}
5320
5321impl Sub<IdealPoint> for Motor {
5322    type Output = Motor;
5323
5324    fn sub(self, other: IdealPoint) -> Motor {
5325        Motor { groups: MotorGroups { g0: self.group0(), g1: self.group1() - Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
5326    }
5327}
5328
5329impl SubAssign<IdealPoint> for Motor {
5330    fn sub_assign(&mut self, other: IdealPoint) {
5331        *self = (*self).sub(other);
5332    }
5333}
5334
5335impl RegressiveProduct<IdealPoint> for Motor {
5336    type Output = Translator;
5337
5338    fn regressive_product(self, other: IdealPoint) -> Translator {
5339        Translator { groups: TranslatorGroups { 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]) + Simd32x4::from([self.group0()[1], self.group1()[0], self.group1()[0], self.group1()[0]]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) } }
5340    }
5341}
5342
5343impl InnerProduct<IdealPoint> for Motor {
5344    type Output = IdealPoint;
5345
5346    fn inner_product(self, other: IdealPoint) -> IdealPoint {
5347        IdealPoint { groups: IdealPointGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() } }
5348    }
5349}
5350
5351impl LeftContraction<IdealPoint> for Motor {
5352    type Output = IdealPoint;
5353
5354    fn left_contraction(self, other: IdealPoint) -> IdealPoint {
5355        IdealPoint { groups: IdealPointGroups { g0: Simd32x3::from(self.group0()[0]) * other.group0() } }
5356    }
5357}
5358
5359impl GeometricProduct<Plane> for Motor {
5360    type Output = PointAndPlane;
5361
5362    fn geometric_product(self, other: Plane) -> PointAndPlane {
5363        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, -1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, -1.0]) + Simd32x4::from(self.group1()[0]) * swizzle!(other.group0(), 1, 1, 2, 3) * Simd32x4::from([0.0, -1.0, -1.0, -1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group0(), 3, 3, 3, 1) * Simd32x4::from([0.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group0(), 2, 2, 1, 2) * Simd32x4::from([0.0, 1.0, -1.0, 0.0]) + Simd32x4::from([self.group0()[1], self.group0()[1], self.group1()[1], self.group1()[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.group0() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 3, 3, 3, 1) * Simd32x4::from([0.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 2, 2, 1, 2) * Simd32x4::from([0.0, 1.0, -1.0, 0.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]) + Simd32x4::from([self.group1()[1], self.group0()[0], self.group0()[1], self.group0()[1]]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([1.0, 0.0, 1.0, -1.0]) } }
5364    }
5365}
5366
5367impl RegressiveProduct<Plane> for Motor {
5368    type Output = Plane;
5369
5370    fn regressive_product(self, other: Plane) -> Plane {
5371        Plane { groups: PlaneGroups { g0: Simd32x4::from(self.group1()[0]) * other.group0() } }
5372    }
5373}
5374
5375impl OuterProduct<Plane> for Motor {
5376    type Output = PointAndPlane;
5377
5378    fn outer_product(self, other: Plane) -> PointAndPlane {
5379        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, -1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, -1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group0(), 3, 3, 3, 1) * Simd32x4::from([0.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group0(), 2, 2, 1, 2) * Simd32x4::from([0.0, 1.0, -1.0, 0.0]) + Simd32x4::from([self.group0()[1], self.group0()[1], self.group1()[1], self.group1()[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.group0() } }
5380    }
5381}
5382
5383impl LeftContraction<Plane> for Motor {
5384    type Output = Plane;
5385
5386    fn left_contraction(self, other: Plane) -> Plane {
5387        Plane { groups: PlaneGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() } }
5388    }
5389}
5390
5391impl Into<Line> for Motor {
5392    fn into(self) -> Line {
5393        Line { groups: LineGroups { g0: Simd32x3::from([self.group1()[1], self.group1()[2], self.group1()[3]]), g1: Simd32x3::from([self.group0()[1], self.group0()[2], self.group0()[3]]) } }
5394    }
5395}
5396
5397impl Add<Line> for Motor {
5398    type Output = Motor;
5399
5400    fn add(self, other: Line) -> Motor {
5401        Motor { groups: MotorGroups { g0: self.group0() + Simd32x4::from([other.group0()[0], other.group1()[0], other.group1()[1], other.group1()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]), g1: self.group1() + Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
5402    }
5403}
5404
5405impl AddAssign<Line> for Motor {
5406    fn add_assign(&mut self, other: Line) {
5407        *self = (*self).add(other);
5408    }
5409}
5410
5411impl Sub<Line> for Motor {
5412    type Output = Motor;
5413
5414    fn sub(self, other: Line) -> Motor {
5415        Motor { groups: MotorGroups { g0: self.group0() - Simd32x4::from([other.group0()[0], other.group1()[0], other.group1()[1], other.group1()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]), g1: self.group1() - Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
5416    }
5417}
5418
5419impl SubAssign<Line> for Motor {
5420    fn sub_assign(&mut self, other: Line) {
5421        *self = (*self).sub(other);
5422    }
5423}
5424
5425impl GeometricProduct<Line> for Motor {
5426    type Output = Motor;
5427
5428    fn geometric_product(self, other: Line) -> Motor {
5429        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group1()[0], other.group1()[0], other.group1()[2], other.group1()[1]]) * Simd32x4::from([-1.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group1()[1], other.group1()[2], other.group1()[1], other.group1()[0]]) * Simd32x4::from([-1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group1()[2], other.group1()[1], other.group1()[0], other.group1()[2]]) * Simd32x4::from([-1.0, 1.0, -1.0, 0.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group1()[0], other.group1()[0], other.group1()[1], other.group1()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]), g1: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[2], other.group0()[1]]) * Simd32x4::from([1.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[1], other.group0()[2], other.group0()[1], other.group0()[0]]) * Simd32x4::from([1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[2], other.group0()[1], other.group0()[0], other.group0()[2]]) * Simd32x4::from([1.0, 1.0, -1.0, 0.0]) + Simd32x4::from(self.group1()[0]) * Simd32x4::from([other.group1()[0], other.group1()[0], other.group1()[1], other.group1()[2]]) * Simd32x4::from([0.0, -1.0, -1.0, -1.0]) + Simd32x4::from(self.group1()[1]) * Simd32x4::from([other.group1()[0], other.group1()[0], other.group1()[2], other.group1()[1]]) * Simd32x4::from([1.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from([other.group1()[1], other.group1()[2], other.group1()[1], other.group1()[0]]) * Simd32x4::from([1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from([other.group1()[2], other.group1()[1], other.group1()[0], other.group1()[2]]) * Simd32x4::from([1.0, 1.0, -1.0, 0.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
5430    }
5431}
5432
5433impl RightContraction<Line> for Motor {
5434    type Output = Translator;
5435
5436    fn right_contraction(self, other: Line) -> Translator {
5437        Translator { groups: TranslatorGroups { g0: Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group1()[1]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group1()[2]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + Simd32x4::from([self.group0()[1], self.group1()[0], self.group1()[0], self.group1()[0]]) * Simd32x4::from([other.group1()[0], other.group1()[0], other.group1()[1], other.group1()[2]]) * Simd32x4::from(-1.0) } }
5438    }
5439}
5440
5441impl ScalarProduct<Line> for Motor {
5442    type Output = f32;
5443
5444    fn scalar_product(self, other: Line) -> f32 {
5445        0.0 - self.group0()[1] * other.group1()[0] - self.group0()[2] * other.group1()[1] - self.group0()[3] * other.group1()[2]
5446    }
5447}
5448
5449impl Into<Translator> for Motor {
5450    fn into(self) -> Translator {
5451        Translator { groups: TranslatorGroups { g0: Simd32x4::from([self.group0()[0], self.group1()[1], self.group1()[2], self.group1()[3]]) } }
5452    }
5453}
5454
5455impl Add<Translator> for Motor {
5456    type Output = Motor;
5457
5458    fn add(self, other: Translator) -> Motor {
5459        Motor { groups: MotorGroups { g0: self.group0() + Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]), g1: self.group1() + other.group0() * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
5460    }
5461}
5462
5463impl AddAssign<Translator> for Motor {
5464    fn add_assign(&mut self, other: Translator) {
5465        *self = (*self).add(other);
5466    }
5467}
5468
5469impl Sub<Translator> for Motor {
5470    type Output = Motor;
5471
5472    fn sub(self, other: Translator) -> Motor {
5473        Motor { groups: MotorGroups { g0: self.group0() - Simd32x4::from(other.group0()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]), g1: self.group1() - other.group0() * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
5474    }
5475}
5476
5477impl SubAssign<Translator> for Motor {
5478    fn sub_assign(&mut self, other: Translator) {
5479        *self = (*self).sub(other);
5480    }
5481}
5482
5483impl GeometricProduct<Translator> for Motor {
5484    type Output = Motor;
5485
5486    fn geometric_product(self, other: Translator) -> Motor {
5487        Motor { groups: MotorGroups { g0: self.group0() * Simd32x4::from(other.group0()[0]), g1: Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 1, 1, 3, 2) * Simd32x4::from([1.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 3, 2, 1) * Simd32x4::from([1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 2, 1, 3) * Simd32x4::from([1.0, 1.0, -1.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()[0], self.group0()[0], self.group0()[0]]) * other.group0() } }
5488    }
5489}
5490
5491impl RegressiveProduct<Translator> for Motor {
5492    type Output = Translator;
5493
5494    fn regressive_product(self, other: Translator) -> Translator {
5495        Translator { groups: TranslatorGroups { 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()[3]) * Simd32x4::from(other.group0()[3]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[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]) } }
5496    }
5497}
5498
5499impl OuterProduct<Translator> for Motor {
5500    type Output = Motor;
5501
5502    fn outer_product(self, other: Translator) -> Motor {
5503        Motor { groups: MotorGroups { g0: self.group0() * Simd32x4::from(other.group0()[0]), g1: 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]) + 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(), 1, 0, 0, 0) * swizzle!(other.group0(), 1, 1, 2, 3) } }
5504    }
5505}
5506
5507impl InnerProduct<Translator> for Motor {
5508    type Output = Motor;
5509
5510    fn inner_product(self, other: Translator) -> Motor {
5511        Motor { groups: MotorGroups { g0: self.group0() * Simd32x4::from(other.group0()[0]), g1: 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()[0], self.group0()[0], self.group0()[0]]) * other.group0() } }
5512    }
5513}
5514
5515impl LeftContraction<Translator> for Motor {
5516    type Output = Translator;
5517
5518    fn left_contraction(self, other: Translator) -> Translator {
5519        Translator { groups: TranslatorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() } }
5520    }
5521}
5522
5523impl RightContraction<Translator> for Motor {
5524    type Output = Motor;
5525
5526    fn right_contraction(self, other: Translator) -> Motor {
5527        Motor { groups: MotorGroups { g0: self.group0() * Simd32x4::from(other.group0()[0]), g1: self.group1() * Simd32x4::from(other.group0()[0]) } }
5528    }
5529}
5530
5531impl ScalarProduct<Translator> for Motor {
5532    type Output = f32;
5533
5534    fn scalar_product(self, other: Translator) -> f32 {
5535        self.group0()[0] * other.group0()[0]
5536    }
5537}
5538
5539impl Add<Motor> for Motor {
5540    type Output = Motor;
5541
5542    fn add(self, other: Motor) -> Motor {
5543        Motor { groups: MotorGroups { g0: self.group0() + other.group0(), g1: self.group1() + other.group1() } }
5544    }
5545}
5546
5547impl AddAssign<Motor> for Motor {
5548    fn add_assign(&mut self, other: Motor) {
5549        *self = (*self).add(other);
5550    }
5551}
5552
5553impl Sub<Motor> for Motor {
5554    type Output = Motor;
5555
5556    fn sub(self, other: Motor) -> Motor {
5557        Motor { groups: MotorGroups { g0: self.group0() - other.group0(), g1: self.group1() - other.group1() } }
5558    }
5559}
5560
5561impl SubAssign<Motor> for Motor {
5562    fn sub_assign(&mut self, other: Motor) {
5563        *self = (*self).sub(other);
5564    }
5565}
5566
5567impl Mul<Motor> for Motor {
5568    type Output = Motor;
5569
5570    fn mul(self, other: Motor) -> Motor {
5571        Motor { groups: MotorGroups { g0: self.group0() * other.group0(), g1: self.group1() * other.group1() } }
5572    }
5573}
5574
5575impl MulAssign<Motor> for Motor {
5576    fn mul_assign(&mut self, other: Motor) {
5577        *self = (*self).mul(other);
5578    }
5579}
5580
5581impl Div<Motor> for Motor {
5582    type Output = Motor;
5583
5584    fn div(self, other: Motor) -> Motor {
5585        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]), 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]) } }
5586    }
5587}
5588
5589impl DivAssign<Motor> for Motor {
5590    fn div_assign(&mut self, other: Motor) {
5591        *self = (*self).div(other);
5592    }
5593}
5594
5595impl GeometricProduct<Motor> for Motor {
5596    type Output = Motor;
5597
5598    fn geometric_product(self, other: Motor) -> Motor {
5599        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 3, 0, 1) * Simd32x4::from([-1.0, -1.0, 1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([-1.0, 1.0, -1.0, 1.0]), 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([1.0, 1.0, -1.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]) * 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]) } }
5600    }
5601}
5602
5603impl RegressiveProduct<Motor> for Motor {
5604    type Output = Motor;
5605
5606    fn regressive_product(self, other: Motor) -> Motor {
5607        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[1]) * swizzle!(other.group1(), 1, 0, 1, 1) * Simd32x4::from([1.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group1(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group1(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, 1.0]) + Simd32x4::from(self.group1()[0]) * other.group0() + Simd32x4::from(self.group1()[1]) * Simd32x4::from(other.group0()[1]) * Simd32x4::from([1.0, 0.0, 0.0, 0.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]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from(other.group1()[0]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]), g1: Simd32x4::from(self.group1()[0]) * other.group1() + self.group1() * Simd32x4::from(other.group1()[0]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
5608    }
5609}
5610
5611impl OuterProduct<Motor> for Motor {
5612    type Output = Motor;
5613
5614    fn outer_product(self, other: Motor) -> Motor {
5615        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]), g1: Simd32x4::from(self.group0()[0]) * other.group1() + Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group1()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group1()[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]) * 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]) } }
5616    }
5617}
5618
5619impl InnerProduct<Motor> for Motor {
5620    type Output = Motor;
5621
5622    fn inner_product(self, other: Motor) -> Motor {
5623        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 2, 0, 2) * Simd32x4::from([-1.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([-1.0, 0.0, 0.0, 1.0]) + swizzle!(self.group0(), 1, 1, 0, 0) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([-1.0, 1.0, 0.0, 0.0]), g1: Simd32x4::from(self.group0()[0]) * other.group1() + 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]) * 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]) + self.group0() * Simd32x4::from(other.group1()[0]) * Simd32x4::from([0.0, -1.0, -1.0, -1.0]) } }
5624    }
5625}
5626
5627impl LeftContraction<Motor> for Motor {
5628    type Output = Motor;
5629
5630    fn left_contraction(self, other: Motor) -> Motor {
5631        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]), g1: Simd32x4::from(self.group0()[0]) * other.group1() + self.group0() * Simd32x4::from(other.group1()[0]) * Simd32x4::from([0.0, -1.0, -1.0, -1.0]) } }
5632    }
5633}
5634
5635impl RightContraction<Motor> for Motor {
5636    type Output = Motor;
5637
5638    fn right_contraction(self, other: Motor) -> Motor {
5639        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]), g1: Simd32x4::from(self.group1()[0]) * other.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) + self.group1() * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
5640    }
5641}
5642
5643impl ScalarProduct<Motor> for Motor {
5644    type Output = f32;
5645
5646    fn scalar_product(self, other: Motor) -> f32 {
5647        self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group0()[1] - self.group0()[2] * other.group0()[2] - self.group0()[3] * other.group0()[3]
5648    }
5649}
5650
5651impl Add<PointAndPlane> for Motor {
5652    type Output = MultiVector;
5653
5654    fn add(self, other: PointAndPlane) -> MultiVector {
5655        MultiVector { groups: MultiVectorGroups { g0: self.group0(), g1: Simd32x4::from([other.group1()[0], other.group0()[1], other.group0()[2], other.group0()[3]]), g2: Simd32x4::from([other.group0()[0], other.group1()[1], other.group1()[2], other.group1()[3]]), g3: self.group1() } }
5656    }
5657}
5658
5659impl Sub<PointAndPlane> for Motor {
5660    type Output = MultiVector;
5661
5662    fn sub(self, other: PointAndPlane) -> MultiVector {
5663        MultiVector { groups: MultiVectorGroups { g0: self.group0(), g1: Simd32x4::from(0.0) - Simd32x4::from([other.group1()[0], other.group0()[1], other.group0()[2], other.group0()[3]]), g2: Simd32x4::from(0.0) - Simd32x4::from([other.group0()[0], other.group1()[1], other.group1()[2], other.group1()[3]]), g3: self.group1() } }
5664    }
5665}
5666
5667impl GeometricProduct<PointAndPlane> for Motor {
5668    type Output = PointAndPlane;
5669
5670    fn geometric_product(self, other: PointAndPlane) -> PointAndPlane {
5671        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group1()[1], other.group1()[0], other.group0()[3], other.group0()[2]]) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group1()[2], other.group0()[3], other.group1()[0], other.group0()[1]]) * Simd32x4::from([1.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group1()[3], other.group0()[2], other.group0()[1], other.group1()[0]]) * Simd32x4::from([1.0, 1.0, -1.0, -1.0]) + Simd32x4::from(self.group1()[1]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group1()[3], other.group1()[2]]) * Simd32x4::from([0.0, -1.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from([other.group1()[3], other.group1()[3], other.group0()[0], other.group1()[1]]) * Simd32x4::from([0.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from([other.group1()[2], other.group1()[2], other.group1()[1], other.group0()[0]]) * Simd32x4::from([0.0, 1.0, -1.0, -1.0]) + Simd32x4::from(self.group1()[0]) * other.group1() * Simd32x4::from([0.0, -1.0, -1.0, -1.0]), g1: Simd32x4::from(self.group0()[0]) * other.group1() + Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[1], other.group0()[0], other.group1()[3], other.group1()[2]]) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[2], other.group1()[3], other.group0()[0], other.group1()[1]]) * Simd32x4::from([1.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[3], other.group1()[2], other.group1()[1], other.group0()[0]]) * Simd32x4::from([1.0, 1.0, -1.0, -1.0]) + Simd32x4::from(self.group1()[1]) * Simd32x4::from(other.group1()[1]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from(other.group1()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from(other.group1()[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]) } }
5672    }
5673}
5674
5675impl RegressiveProduct<PointAndPlane> for Motor {
5676    type Output = PointAndPlane;
5677
5678    fn regressive_product(self, other: PointAndPlane) -> PointAndPlane {
5679        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self.group1()[0]) * other.group0(), g1: Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 3, 3, 3, 1) * Simd32x4::from([0.0, 1.0, 0.0, -1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 2, 2, 1, 2) * Simd32x4::from([0.0, -1.0, 1.0, 0.0]) + Simd32x4::from(self.group1()[0]) * other.group1() + 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()[1], self.group1()[1], self.group0()[1], self.group0()[1]]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, -1.0, 1.0]) } }
5680    }
5681}
5682
5683impl OuterProduct<PointAndPlane> for Motor {
5684    type Output = PointAndPlane;
5685
5686    fn outer_product(self, other: PointAndPlane) -> PointAndPlane {
5687        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group0()[2]) * swizzle!(other.group1(), 2, 2, 0, 2) * Simd32x4::from([1.0, 0.0, -1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group1(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, -1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group1(), 3, 3, 3, 1) * Simd32x4::from([0.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group1(), 2, 2, 1, 2) * Simd32x4::from([0.0, 1.0, -1.0, 0.0]) + Simd32x4::from([self.group0()[1], self.group0()[1], self.group1()[1], self.group1()[1]]) * swizzle!(other.group1(), 1, 0, 3, 2) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]), g1: Simd32x4::from(self.group0()[0]) * other.group1() } }
5688    }
5689}
5690
5691impl InnerProduct<PointAndPlane> for Motor {
5692    type Output = PointAndPlane;
5693
5694    fn inner_product(self, other: PointAndPlane) -> PointAndPlane {
5695        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group1()[0]) * other.group1() * Simd32x4::from([0.0, -1.0, -1.0, -1.0]), g1: Simd32x4::from(self.group0()[0]) * other.group1() + Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[1], other.group0()[0], other.group1()[3], other.group1()[2]]) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[2], other.group1()[3], other.group0()[0], other.group1()[1]]) * Simd32x4::from([1.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[3], other.group1()[2], other.group1()[1], other.group0()[0]]) * Simd32x4::from([1.0, 1.0, -1.0, -1.0]) + Simd32x4::from(self.group1()[1]) * Simd32x4::from(other.group1()[1]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from(other.group1()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from(other.group1()[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]) } }
5696    }
5697}
5698
5699impl LeftContraction<PointAndPlane> for Motor {
5700    type Output = PointAndPlane;
5701
5702    fn left_contraction(self, other: PointAndPlane) -> PointAndPlane {
5703        PointAndPlane { groups: PointAndPlaneGroups { 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, 0, 2) * Simd32x4::from([1.0, 0.0, -1.0, 0.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 3, 3, 0) * Simd32x4::from([1.0, 0.0, 0.0, -1.0]) + swizzle!(self.group0(), 1, 1, 0, 0) * swizzle!(other.group0(), 1, 0, 0, 0) * Simd32x4::from([1.0, -1.0, 0.0, 0.0]) } }
5704    }
5705}
5706
5707impl SquaredMagnitude for Motor {
5708    type Output = f32;
5709
5710    fn squared_magnitude(self) -> f32 {
5711        self.scalar_product(self.reversal())
5712    }
5713}
5714
5715impl Magnitude for Motor {
5716    type Output = f32;
5717
5718    fn magnitude(self) -> f32 {
5719        self.squared_magnitude().sqrt()
5720    }
5721}
5722
5723impl Mul<f32> for Motor {
5724    type Output = Motor;
5725
5726    fn mul(self, other: f32) -> Motor {
5727        self.geometric_product(other)
5728    }
5729}
5730
5731impl MulAssign<f32> for Motor {
5732    fn mul_assign(&mut self, other: f32) {
5733        *self = (*self).mul(other);
5734    }
5735}
5736
5737impl Signum for Motor {
5738    type Output = Motor;
5739
5740    fn signum(self) -> Motor {
5741        self.geometric_product(1.0 / self.magnitude())
5742    }
5743}
5744
5745impl Inverse for Motor {
5746    type Output = Motor;
5747
5748    fn inverse(self) -> Motor {
5749        self.reversal().geometric_product(1.0 / self.squared_magnitude())
5750    }
5751}
5752
5753impl Zero for PointAndPlane {
5754    fn zero() -> Self {
5755        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(0.0), g1: Simd32x4::from(0.0) } }
5756    }
5757}
5758
5759impl One for PointAndPlane {
5760    fn one() -> Self {
5761        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(0.0), g1: Simd32x4::from(0.0) } }
5762    }
5763}
5764
5765impl Neg for PointAndPlane {
5766    type Output = PointAndPlane;
5767
5768    fn neg(self) -> PointAndPlane {
5769        PointAndPlane { groups: PointAndPlaneGroups { g0: self.group0() * Simd32x4::from(-1.0), g1: self.group1() * Simd32x4::from(-1.0) } }
5770    }
5771}
5772
5773impl Automorphism for PointAndPlane {
5774    type Output = PointAndPlane;
5775
5776    fn automorphism(self) -> PointAndPlane {
5777        PointAndPlane { groups: PointAndPlaneGroups { g0: self.group0() * Simd32x4::from(-1.0), g1: self.group1() * Simd32x4::from(-1.0) } }
5778    }
5779}
5780
5781impl Reversal for PointAndPlane {
5782    type Output = PointAndPlane;
5783
5784    fn reversal(self) -> PointAndPlane {
5785        PointAndPlane { groups: PointAndPlaneGroups { g0: self.group0() * Simd32x4::from(-1.0), g1: self.group1() } }
5786    }
5787}
5788
5789impl Conjugation for PointAndPlane {
5790    type Output = PointAndPlane;
5791
5792    fn conjugation(self) -> PointAndPlane {
5793        PointAndPlane { groups: PointAndPlaneGroups { g0: self.group0(), g1: self.group1() * Simd32x4::from(-1.0) } }
5794    }
5795}
5796
5797impl Dual for PointAndPlane {
5798    type Output = PointAndPlane;
5799
5800    fn dual(self) -> PointAndPlane {
5801        PointAndPlane { groups: PointAndPlaneGroups { g0: self.group1(), g1: self.group0() * Simd32x4::from(-1.0) } }
5802    }
5803}
5804
5805impl GeometricProduct<f32> for PointAndPlane {
5806    type Output = PointAndPlane;
5807
5808    fn geometric_product(self, other: f32) -> PointAndPlane {
5809        PointAndPlane { groups: PointAndPlaneGroups { g0: self.group0() * Simd32x4::from(other), g1: self.group1() * Simd32x4::from(other) } }
5810    }
5811}
5812
5813impl OuterProduct<f32> for PointAndPlane {
5814    type Output = PointAndPlane;
5815
5816    fn outer_product(self, other: f32) -> PointAndPlane {
5817        PointAndPlane { groups: PointAndPlaneGroups { g0: self.group0() * Simd32x4::from(other), g1: self.group1() * Simd32x4::from(other) } }
5818    }
5819}
5820
5821impl InnerProduct<f32> for PointAndPlane {
5822    type Output = PointAndPlane;
5823
5824    fn inner_product(self, other: f32) -> PointAndPlane {
5825        PointAndPlane { groups: PointAndPlaneGroups { g0: self.group0() * Simd32x4::from(other), g1: self.group1() * Simd32x4::from(other) } }
5826    }
5827}
5828
5829impl RightContraction<f32> for PointAndPlane {
5830    type Output = PointAndPlane;
5831
5832    fn right_contraction(self, other: f32) -> PointAndPlane {
5833        PointAndPlane { groups: PointAndPlaneGroups { g0: self.group0() * Simd32x4::from(other), g1: self.group1() * Simd32x4::from(other) } }
5834    }
5835}
5836
5837impl Add<MultiVector> for PointAndPlane {
5838    type Output = MultiVector;
5839
5840    fn add(self, other: MultiVector) -> MultiVector {
5841        MultiVector { groups: MultiVectorGroups { g0: other.group0(), g1: Simd32x4::from([self.group1()[0], self.group0()[1], self.group0()[2], self.group0()[3]]) + other.group1(), g2: Simd32x4::from([self.group0()[0], self.group1()[1], self.group1()[2], self.group1()[3]]) + other.group2(), g3: other.group3() } }
5842    }
5843}
5844
5845impl Sub<MultiVector> for PointAndPlane {
5846    type Output = MultiVector;
5847
5848    fn sub(self, other: MultiVector) -> MultiVector {
5849        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(0.0) - other.group0(), g1: Simd32x4::from([self.group1()[0], self.group0()[1], self.group0()[2], self.group0()[3]]) - other.group1(), g2: Simd32x4::from([self.group0()[0], self.group1()[1], self.group1()[2], self.group1()[3]]) - other.group2(), g3: Simd32x4::from(0.0) - other.group3() } }
5850    }
5851}
5852
5853impl GeometricProduct<MultiVector> for PointAndPlane {
5854    type Output = MultiVector;
5855
5856    fn geometric_product(self, other: MultiVector) -> MultiVector {
5857        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(self.group0()[0]) * other.group2() * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) + Simd32x4::from(self.group1()[1]) * swizzle!(other.group2(), 1, 0, 3, 2) * Simd32x4::from([1.0, 1.0, -1.0, 1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group2(), 2, 3, 0, 1) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group2(), 3, 2, 1, 0) * Simd32x4::from([1.0, -1.0, 1.0, 1.0]), g1: Simd32x4::from(self.group0()[0]) * other.group3() + Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 1, 0, 3, 2) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 3, 0, 1) * Simd32x4::from([1.0, -1.0, 1.0, 1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 2, 1, 0) * Simd32x4::from([1.0, 1.0, -1.0, 1.0]) + Simd32x4::from(self.group1()[0]) * other.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) + Simd32x4::from(self.group1()[1]) * swizzle!(other.group3(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, -1.0, 1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group3(), 2, 3, 0, 1) * Simd32x4::from([-1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group3(), 3, 2, 1, 0) * Simd32x4::from([-1.0, -1.0, 1.0, 1.0]), g2: Simd32x4::from(self.group0()[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]), g3: Simd32x4::from(0.0) - Simd32x4::from(self.group0()[0]) * other.group1() + Simd32x4::from(self.group0()[1]) * swizzle!(other.group2(), 1, 0, 3, 2) * Simd32x4::from([-1.0, 1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group2(), 2, 3, 0, 1) * Simd32x4::from([-1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group2(), 3, 2, 1, 0) * Simd32x4::from([-1.0, -1.0, 1.0, 1.0]) + Simd32x4::from(self.group1()[0]) * other.group2() + Simd32x4::from(self.group1()[1]) * swizzle!(other.group1(), 1, 0, 3, 2) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group1(), 2, 3, 0, 1) * Simd32x4::from([1.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group1(), 3, 2, 1, 0) * Simd32x4::from([1.0, 1.0, -1.0, -1.0]) } }
5858    }
5859}
5860
5861impl ScalarProduct<MultiVector> for PointAndPlane {
5862    type Output = f32;
5863
5864    fn scalar_product(self, other: MultiVector) -> f32 {
5865        0.0 - self.group0()[0] * other.group2()[0] + self.group1()[1] * other.group2()[1] + self.group1()[2] * other.group2()[2] + self.group1()[3] * other.group2()[3]
5866    }
5867}
5868
5869impl GeometricProduct<Rotor> for PointAndPlane {
5870    type Output = PointAndPlane;
5871
5872    fn geometric_product(self, other: Rotor) -> PointAndPlane {
5873        PointAndPlane { groups: PointAndPlaneGroups { g0: 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.group1()[0]) * swizzle!(other.group0(), 1, 1, 2, 3) * Simd32x4::from([0.0, -1.0, -1.0, -1.0]) + Simd32x4::from(self.group1()[1]) * Simd32x4::from(other.group0()[1]) * Simd32x4::from([1.0, 0.0, 0.0, 0.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, 1, 1, 1) * swizzle!(other.group0(), 0, 0, 3, 2) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]), g1: 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]) + 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(), 0, 0, 3, 2) * Simd32x4::from([0.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group0(), 3, 3, 0, 1) * Simd32x4::from([0.0, -1.0, 1.0, 1.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group0(), 2, 2, 1, 0) * Simd32x4::from([0.0, 1.0, -1.0, 1.0]) + swizzle!(self.group0(), 1, 0, 0, 0) * swizzle!(other.group0(), 1, 1, 2, 3) * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) } }
5874    }
5875}
5876
5877impl OuterProduct<Rotor> for PointAndPlane {
5878    type Output = PointAndPlane;
5879
5880    fn outer_product(self, other: Rotor) -> PointAndPlane {
5881        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self.group1()[0]) * swizzle!(other.group0(), 1, 1, 2, 3) * Simd32x4::from([0.0, -1.0, -1.0, -1.0]) + Simd32x4::from(self.group1()[1]) * Simd32x4::from(other.group0()[1]) * Simd32x4::from([1.0, 0.0, 0.0, 0.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]) + self.group0() * Simd32x4::from(other.group0()[0]), g1: self.group1() * Simd32x4::from(other.group0()[0]) } }
5882    }
5883}
5884
5885impl InnerProduct<Rotor> for PointAndPlane {
5886    type Output = PointAndPlane;
5887
5888    fn inner_product(self, other: Rotor) -> PointAndPlane {
5889        PointAndPlane { groups: PointAndPlaneGroups { g0: self.group0() * Simd32x4::from(other.group0()[0]), g1: 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]) + 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(), 0, 0, 3, 2) * Simd32x4::from([0.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group0(), 3, 3, 0, 1) * Simd32x4::from([0.0, -1.0, 1.0, 1.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group0(), 2, 2, 1, 0) * Simd32x4::from([0.0, 1.0, -1.0, 1.0]) + swizzle!(self.group0(), 1, 0, 0, 0) * swizzle!(other.group0(), 1, 1, 2, 3) * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) } }
5890    }
5891}
5892
5893impl RightContraction<Rotor> for PointAndPlane {
5894    type Output = PointAndPlane;
5895
5896    fn right_contraction(self, other: Rotor) -> PointAndPlane {
5897        PointAndPlane { groups: PointAndPlaneGroups { g0: self.group0() * Simd32x4::from(other.group0()[0]), g1: 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]) + 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(), 1, 0, 0, 0) * swizzle!(other.group0(), 1, 1, 2, 3) * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) } }
5898    }
5899}
5900
5901impl Into<Point> for PointAndPlane {
5902    fn into(self) -> Point {
5903        Point { groups: PointGroups { g0: self.group0() } }
5904    }
5905}
5906
5907impl Add<Point> for PointAndPlane {
5908    type Output = PointAndPlane;
5909
5910    fn add(self, other: Point) -> PointAndPlane {
5911        PointAndPlane { groups: PointAndPlaneGroups { g0: self.group0() + other.group0(), g1: self.group1() } }
5912    }
5913}
5914
5915impl AddAssign<Point> for PointAndPlane {
5916    fn add_assign(&mut self, other: Point) {
5917        *self = (*self).add(other);
5918    }
5919}
5920
5921impl Sub<Point> for PointAndPlane {
5922    type Output = PointAndPlane;
5923
5924    fn sub(self, other: Point) -> PointAndPlane {
5925        PointAndPlane { groups: PointAndPlaneGroups { g0: self.group0() - other.group0(), g1: self.group1() } }
5926    }
5927}
5928
5929impl SubAssign<Point> for PointAndPlane {
5930    fn sub_assign(&mut self, other: Point) {
5931        *self = (*self).sub(other);
5932    }
5933}
5934
5935impl GeometricProduct<Point> for PointAndPlane {
5936    type Output = Motor;
5937
5938    fn geometric_product(self, other: Point) -> Motor {
5939        Motor { groups: MotorGroups { g0: Simd32x4::from([self.group0()[0], self.group1()[1], self.group1()[2], self.group1()[3]]) * 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()[0]) * Simd32x4::from([0.0, 1.0, 0.0, 0.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.group1()[1]) * swizzle!(other.group0(), 1, 1, 3, 2) * Simd32x4::from([1.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group0(), 2, 3, 2, 1) * Simd32x4::from([1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group0(), 3, 2, 1, 3) * Simd32x4::from([1.0, 1.0, -1.0, 0.0]) + Simd32x4::from([self.group1()[0], self.group0()[0], self.group0()[0], self.group0()[0]]) * other.group0() * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) } }
5940    }
5941}
5942
5943impl RightContraction<Point> for PointAndPlane {
5944    type Output = f32;
5945
5946    fn right_contraction(self, other: Point) -> f32 {
5947        0.0 - self.group0()[0] * other.group0()[0]
5948    }
5949}
5950
5951impl ScalarProduct<Point> for PointAndPlane {
5952    type Output = f32;
5953
5954    fn scalar_product(self, other: Point) -> f32 {
5955        0.0 - self.group0()[0] * other.group0()[0]
5956    }
5957}
5958
5959impl RegressiveProduct<IdealPoint> for PointAndPlane {
5960    type Output = Plane;
5961
5962    fn regressive_product(self, other: IdealPoint) -> Plane {
5963        Plane { groups: PlaneGroups { g0: Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group0()[1]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group0()[2]) * Simd32x4::from([-1.0, 0.0, 0.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0, 0) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) } }
5964    }
5965}
5966
5967impl Into<Plane> for PointAndPlane {
5968    fn into(self) -> Plane {
5969        Plane { groups: PlaneGroups { g0: self.group1() } }
5970    }
5971}
5972
5973impl Add<Plane> for PointAndPlane {
5974    type Output = PointAndPlane;
5975
5976    fn add(self, other: Plane) -> PointAndPlane {
5977        PointAndPlane { groups: PointAndPlaneGroups { g0: self.group0(), g1: self.group1() + other.group0() } }
5978    }
5979}
5980
5981impl AddAssign<Plane> for PointAndPlane {
5982    fn add_assign(&mut self, other: Plane) {
5983        *self = (*self).add(other);
5984    }
5985}
5986
5987impl Sub<Plane> for PointAndPlane {
5988    type Output = PointAndPlane;
5989
5990    fn sub(self, other: Plane) -> PointAndPlane {
5991        PointAndPlane { groups: PointAndPlaneGroups { g0: self.group0(), g1: self.group1() - other.group0() } }
5992    }
5993}
5994
5995impl SubAssign<Plane> for PointAndPlane {
5996    fn sub_assign(&mut self, other: Plane) {
5997        *self = (*self).sub(other);
5998    }
5999}
6000
6001impl GeometricProduct<Plane> for PointAndPlane {
6002    type Output = Motor;
6003
6004    fn geometric_product(self, other: Plane) -> Motor {
6005        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group1()[1]) * swizzle!(other.group0(), 1, 1, 3, 2) * Simd32x4::from([1.0, 0.0, -1.0, 1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group0(), 2, 3, 2, 1) * Simd32x4::from([1.0, 1.0, 0.0, -1.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group0(), 3, 2, 1, 3) * Simd32x4::from([1.0, -1.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[0]) * other.group0() * Simd32x4::from([0.0, 1.0, 1.0, 1.0]), g1: Simd32x4::from(self.group0()[1]) * swizzle!(other.group0(), 1, 1, 3, 2) * Simd32x4::from([-1.0, 0.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[2]) * swizzle!(other.group0(), 2, 3, 2, 1) * Simd32x4::from([-1.0, 1.0, 0.0, -1.0]) + Simd32x4::from(self.group0()[3]) * swizzle!(other.group0(), 3, 2, 1, 3) * Simd32x4::from([-1.0, -1.0, 1.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.group0()[0], self.group1()[0], self.group1()[0], self.group1()[0]]) * other.group0() * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) } }
6006    }
6007}
6008
6009impl RegressiveProduct<Plane> for PointAndPlane {
6010    type Output = f32;
6011
6012    fn regressive_product(self, other: Plane) -> f32 {
6013        0.0 - self.group0()[0] * other.group0()[0] - self.group0()[1] * other.group0()[1] - self.group0()[2] * other.group0()[2] - self.group0()[3] * other.group0()[3]
6014    }
6015}
6016
6017impl LeftContraction<Plane> for PointAndPlane {
6018    type Output = f32;
6019
6020    fn left_contraction(self, other: Plane) -> f32 {
6021        self.group1()[1] * other.group0()[1] + self.group1()[2] * other.group0()[2] + self.group1()[3] * other.group0()[3]
6022    }
6023}
6024
6025impl ScalarProduct<Plane> for PointAndPlane {
6026    type Output = f32;
6027
6028    fn scalar_product(self, other: Plane) -> f32 {
6029        self.group1()[1] * other.group0()[1] + self.group1()[2] * other.group0()[2] + self.group1()[3] * other.group0()[3]
6030    }
6031}
6032
6033impl GeometricProduct<Line> for PointAndPlane {
6034    type Output = PointAndPlane;
6035
6036    fn geometric_product(self, other: Line) -> PointAndPlane {
6037        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group1()[2], other.group1()[2], other.group1()[2], other.group1()[1]]) * Simd32x4::from([0.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group1()[2], other.group1()[2], other.group1()[2], other.group1()[0]]) * Simd32x4::from([0.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group1()[1], other.group1()[1], other.group1()[0], other.group1()[1]]) * Simd32x4::from([0.0, 1.0, -1.0, 0.0]) + Simd32x4::from(self.group1()[0]) * Simd32x4::from([other.group1()[0], other.group1()[0], other.group1()[1], other.group1()[2]]) * Simd32x4::from([0.0, -1.0, -1.0, -1.0]) + Simd32x4::from(self.group1()[1]) * Simd32x4::from([other.group1()[0], other.group1()[0], other.group0()[2], other.group0()[1]]) * Simd32x4::from([1.0, 0.0, -1.0, 1.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from([other.group1()[1], other.group0()[2], other.group1()[1], other.group0()[0]]) * Simd32x4::from([1.0, 1.0, 0.0, -1.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from([other.group1()[2], other.group0()[1], other.group0()[0], other.group1()[2]]) * Simd32x4::from([1.0, -1.0, 1.0, 0.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]), g1: Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group1()[1]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group1()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[1]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group1()[2], other.group1()[1]]) * Simd32x4::from([-1.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from([other.group0()[1], other.group1()[2], other.group0()[1], other.group1()[0]]) * Simd32x4::from([-1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from([other.group0()[2], other.group1()[1], other.group1()[0], other.group0()[2]]) * Simd32x4::from([-1.0, 1.0, -1.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0, 0) * Simd32x4::from([other.group1()[0], other.group1()[0], other.group1()[1], other.group1()[2]]) * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) } }
6038    }
6039}
6040
6041impl RegressiveProduct<Line> for PointAndPlane {
6042    type Output = Plane;
6043
6044    fn regressive_product(self, other: Line) -> Plane {
6045        Plane { groups: PlaneGroups { g0: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group1()[2], other.group1()[1]]) * Simd32x4::from([-1.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group0()[1], other.group1()[2], other.group0()[1], other.group1()[0]]) * Simd32x4::from([-1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group0()[2], other.group1()[1], other.group1()[0], other.group0()[2]]) * Simd32x4::from([-1.0, 1.0, -1.0, 0.0]) + Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group0()[1], other.group0()[2]]) * Simd32x4::from([0.0, 1.0, 1.0, 1.0]) } }
6046    }
6047}
6048
6049impl OuterProduct<Line> for PointAndPlane {
6050    type Output = Point;
6051
6052    fn outer_product(self, other: Line) -> Point {
6053        Point { groups: PointGroups { g0: Simd32x4::from(self.group1()[1]) * Simd32x4::from([other.group1()[0], other.group1()[0], other.group0()[2], other.group0()[1]]) * Simd32x4::from([1.0, 0.0, -1.0, 1.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from([other.group1()[1], other.group0()[2], other.group1()[1], other.group0()[0]]) * Simd32x4::from([1.0, 1.0, 0.0, -1.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from([other.group1()[2], other.group0()[1], other.group0()[0], other.group1()[2]]) * Simd32x4::from([1.0, -1.0, 1.0, 0.0]) + Simd32x4::from(self.group1()[0]) * Simd32x4::from([other.group1()[0], other.group1()[0], other.group1()[1], other.group1()[2]]) * Simd32x4::from([0.0, -1.0, -1.0, -1.0]) } }
6054    }
6055}
6056
6057impl InnerProduct<Line> for PointAndPlane {
6058    type Output = Plane;
6059
6060    fn inner_product(self, other: Line) -> Plane {
6061        Plane { groups: PlaneGroups { g0: Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group1()[1]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group1()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[1]) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group1()[2], other.group1()[1]]) * Simd32x4::from([-1.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from([other.group0()[1], other.group1()[2], other.group0()[1], other.group1()[0]]) * Simd32x4::from([-1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from([other.group0()[2], other.group1()[1], other.group1()[0], other.group0()[2]]) * Simd32x4::from([-1.0, 1.0, -1.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0, 0) * Simd32x4::from([other.group1()[0], other.group1()[0], other.group1()[1], other.group1()[2]]) * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) } }
6062    }
6063}
6064
6065impl LeftContraction<Line> for PointAndPlane {
6066    type Output = Plane;
6067
6068    fn left_contraction(self, other: Line) -> Plane {
6069        Plane { groups: PlaneGroups { g0: Simd32x4::from(self.group1()[2]) * Simd32x4::from([other.group0()[1], other.group1()[2], other.group0()[1], other.group1()[0]]) * Simd32x4::from([-1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from([other.group0()[2], other.group1()[1], other.group1()[0], other.group0()[2]]) * Simd32x4::from([-1.0, 1.0, -1.0, 0.0]) + swizzle!(self.group1(), 1, 0, 1, 1) * Simd32x4::from([other.group0()[0], other.group0()[0], other.group1()[2], other.group1()[1]]) * Simd32x4::from([-1.0, 0.0, 1.0, -1.0]) } }
6070    }
6071}
6072
6073impl RightContraction<Line> for PointAndPlane {
6074    type Output = Plane;
6075
6076    fn right_contraction(self, other: Line) -> Plane {
6077        Plane { groups: PlaneGroups { g0: Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group1()[1]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group1()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + swizzle!(self.group0(), 1, 0, 0, 0) * Simd32x4::from([other.group1()[0], other.group1()[0], other.group1()[1], other.group1()[2]]) * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) } }
6078    }
6079}
6080
6081impl GeometricProduct<Translator> for PointAndPlane {
6082    type Output = PointAndPlane;
6083
6084    fn geometric_product(self, other: Translator) -> PointAndPlane {
6085        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self.group0()[0]) * other.group0() + Simd32x4::from(self.group1()[1]) * swizzle!(other.group0(), 3, 3, 3, 2) * Simd32x4::from([0.0, 0.0, -1.0, 1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group0(), 3, 3, 3, 1) * Simd32x4::from([0.0, 1.0, 0.0, -1.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group0(), 2, 2, 1, 2) * Simd32x4::from([0.0, -1.0, 1.0, 0.0]) + self.group0() * Simd32x4::from(other.group0()[0]) * Simd32x4::from([0.0, 1.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]) + 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]) } }
6086    }
6087}
6088
6089impl RegressiveProduct<Translator> for PointAndPlane {
6090    type Output = Plane;
6091
6092    fn regressive_product(self, other: Translator) -> Plane {
6093        Plane { groups: PlaneGroups { 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()[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, 1, 2, 3) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) } }
6094    }
6095}
6096
6097impl OuterProduct<Translator> for PointAndPlane {
6098    type Output = PointAndPlane;
6099
6100    fn outer_product(self, other: Translator) -> PointAndPlane {
6101        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self.group1()[1]) * swizzle!(other.group0(), 3, 3, 3, 2) * Simd32x4::from([0.0, 0.0, -1.0, 1.0]) + Simd32x4::from(self.group1()[2]) * swizzle!(other.group0(), 3, 3, 3, 1) * Simd32x4::from([0.0, 1.0, 0.0, -1.0]) + Simd32x4::from(self.group1()[3]) * swizzle!(other.group0(), 2, 2, 1, 2) * Simd32x4::from([0.0, -1.0, 1.0, 0.0]) + self.group0() * Simd32x4::from(other.group0()[0]), g1: self.group1() * Simd32x4::from(other.group0()[0]) } }
6102    }
6103}
6104
6105impl InnerProduct<Translator> for PointAndPlane {
6106    type Output = PointAndPlane;
6107
6108    fn inner_product(self, other: Translator) -> PointAndPlane {
6109        PointAndPlane { groups: PointAndPlaneGroups { g0: self.group0() * Simd32x4::from(other.group0()[0]), g1: 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(), 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]) } }
6110    }
6111}
6112
6113impl RightContraction<Translator> for PointAndPlane {
6114    type Output = PointAndPlane;
6115
6116    fn right_contraction(self, other: Translator) -> PointAndPlane {
6117        PointAndPlane { groups: PointAndPlaneGroups { g0: self.group0() * Simd32x4::from(other.group0()[0]), g1: self.group1() * Simd32x4::from(other.group0()[0]) } }
6118    }
6119}
6120
6121impl Add<Motor> for PointAndPlane {
6122    type Output = MultiVector;
6123
6124    fn add(self, other: Motor) -> MultiVector {
6125        MultiVector { groups: MultiVectorGroups { g0: other.group0(), g1: Simd32x4::from([self.group1()[0], self.group0()[1], self.group0()[2], self.group0()[3]]), g2: Simd32x4::from([self.group0()[0], self.group1()[1], self.group1()[2], self.group1()[3]]), g3: other.group1() } }
6126    }
6127}
6128
6129impl Sub<Motor> for PointAndPlane {
6130    type Output = MultiVector;
6131
6132    fn sub(self, other: Motor) -> MultiVector {
6133        MultiVector { groups: MultiVectorGroups { g0: Simd32x4::from(0.0) - other.group0(), g1: Simd32x4::from([self.group1()[0], self.group0()[1], self.group0()[2], self.group0()[3]]), g2: Simd32x4::from([self.group0()[0], self.group1()[1], self.group1()[2], self.group1()[3]]), g3: Simd32x4::from(0.0) - other.group1() } }
6134    }
6135}
6136
6137impl GeometricProduct<Motor> for PointAndPlane {
6138    type Output = PointAndPlane;
6139
6140    fn geometric_product(self, other: Motor) -> PointAndPlane {
6141        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group0()[0], other.group1()[1], other.group1()[2], other.group1()[3]]) + 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.group1()[0]) * swizzle!(other.group0(), 1, 1, 2, 3) * Simd32x4::from([0.0, -1.0, -1.0, -1.0]) + Simd32x4::from(self.group1()[1]) * Simd32x4::from([other.group0()[1], other.group1()[0], other.group1()[3], other.group1()[2]]) * Simd32x4::from([1.0, 1.0, -1.0, 1.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from([other.group0()[2], other.group1()[3], other.group1()[0], other.group1()[1]]) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from([other.group0()[3], other.group1()[2], other.group1()[1], other.group1()[0]]) * Simd32x4::from([1.0, -1.0, 1.0, 1.0]) + swizzle!(self.group0(), 0, 1, 1, 1) * swizzle!(other.group0(), 0, 0, 3, 2) * Simd32x4::from([0.0, 1.0, 1.0, -1.0]), g1: Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group1()[0], other.group0()[1], other.group0()[2], other.group0()[3]]) * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group0()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group0()[3]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + 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.group1()[1], other.group0()[0], other.group0()[3], other.group0()[2]]) * Simd32x4::from([-1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from([other.group1()[2], other.group0()[3], other.group0()[0], other.group0()[1]]) * Simd32x4::from([-1.0, -1.0, 1.0, 1.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from([other.group1()[3], other.group0()[2], other.group0()[1], other.group0()[0]]) * Simd32x4::from([-1.0, 1.0, -1.0, 1.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]) } }
6142    }
6143}
6144
6145impl RegressiveProduct<Motor> for PointAndPlane {
6146    type Output = PointAndPlane;
6147
6148    fn regressive_product(self, other: Motor) -> PointAndPlane {
6149        PointAndPlane { groups: PointAndPlaneGroups { g0: self.group0() * Simd32x4::from(other.group1()[0]), g1: Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group1()[1], other.group1()[1], other.group0()[3], other.group0()[2]]) * Simd32x4::from([-1.0, 0.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group1()[2], other.group0()[3], other.group1()[2], other.group0()[1]]) * Simd32x4::from([-1.0, -1.0, 0.0, 1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group1()[3], other.group0()[2], other.group0()[1], other.group1()[3]]) * Simd32x4::from([-1.0, 1.0, -1.0, 0.0]) + Simd32x4::from(self.group1()[1]) * Simd32x4::from(other.group1()[0]) * Simd32x4::from([0.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from(other.group1()[0]) * Simd32x4::from([0.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from(other.group1()[0]) * Simd32x4::from([0.0, 0.0, 0.0, 1.0]) + Simd32x4::from([self.group1()[0], self.group0()[0], self.group0()[0], self.group0()[0]]) * other.group1() } }
6150    }
6151}
6152
6153impl OuterProduct<Motor> for PointAndPlane {
6154    type Output = PointAndPlane;
6155
6156    fn outer_product(self, other: Motor) -> PointAndPlane {
6157        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self.group1()[0]) * swizzle!(other.group0(), 1, 1, 2, 3) * Simd32x4::from([0.0, -1.0, -1.0, -1.0]) + Simd32x4::from(self.group1()[1]) * Simd32x4::from([other.group0()[1], other.group0()[1], other.group1()[3], other.group1()[2]]) * Simd32x4::from([1.0, 0.0, -1.0, 1.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from([other.group0()[2], other.group1()[3], other.group0()[2], other.group1()[1]]) * Simd32x4::from([1.0, 1.0, 0.0, -1.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from([other.group0()[3], other.group1()[2], other.group1()[1], other.group0()[3]]) * Simd32x4::from([1.0, -1.0, 1.0, 0.0]) + self.group0() * Simd32x4::from(other.group0()[0]), g1: self.group1() * Simd32x4::from(other.group0()[0]) } }
6158    }
6159}
6160
6161impl InnerProduct<Motor> for PointAndPlane {
6162    type Output = PointAndPlane;
6163
6164    fn inner_product(self, other: Motor) -> PointAndPlane {
6165        PointAndPlane { groups: PointAndPlaneGroups { g0: Simd32x4::from(self.group1()[1]) * Simd32x4::from(other.group1()[0]) * Simd32x4::from([0.0, 1.0, 0.0, 0.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from(other.group1()[0]) * Simd32x4::from([0.0, 0.0, 1.0, 0.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from(other.group1()[0]) * Simd32x4::from([0.0, 0.0, 0.0, 1.0]) + self.group0() * Simd32x4::from(other.group0()[0]), g1: Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group1()[0], other.group0()[1], other.group0()[2], other.group0()[3]]) * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from(other.group0()[2]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from(other.group0()[3]) * Simd32x4::from([1.0, 0.0, 0.0, 0.0]) + 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.group1()[1], other.group0()[0], other.group0()[3], other.group0()[2]]) * Simd32x4::from([-1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from([other.group1()[2], other.group0()[3], other.group0()[0], other.group0()[1]]) * Simd32x4::from([-1.0, -1.0, 1.0, 1.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from([other.group1()[3], other.group0()[2], other.group0()[1], other.group0()[0]]) * Simd32x4::from([-1.0, 1.0, -1.0, 1.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]) } }
6166    }
6167}
6168
6169impl RightContraction<Motor> for PointAndPlane {
6170    type Output = PointAndPlane;
6171
6172    fn right_contraction(self, other: Motor) -> PointAndPlane {
6173        PointAndPlane { groups: PointAndPlaneGroups { g0: self.group0() * Simd32x4::from(other.group0()[0]), g1: 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]) + 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(), 1, 0, 0, 0) * swizzle!(other.group0(), 1, 1, 2, 3) * Simd32x4::from([1.0, -1.0, -1.0, -1.0]) } }
6174    }
6175}
6176
6177impl Add<PointAndPlane> for PointAndPlane {
6178    type Output = PointAndPlane;
6179
6180    fn add(self, other: PointAndPlane) -> PointAndPlane {
6181        PointAndPlane { groups: PointAndPlaneGroups { g0: self.group0() + other.group0(), g1: self.group1() + other.group1() } }
6182    }
6183}
6184
6185impl AddAssign<PointAndPlane> for PointAndPlane {
6186    fn add_assign(&mut self, other: PointAndPlane) {
6187        *self = (*self).add(other);
6188    }
6189}
6190
6191impl Sub<PointAndPlane> for PointAndPlane {
6192    type Output = PointAndPlane;
6193
6194    fn sub(self, other: PointAndPlane) -> PointAndPlane {
6195        PointAndPlane { groups: PointAndPlaneGroups { g0: self.group0() - other.group0(), g1: self.group1() - other.group1() } }
6196    }
6197}
6198
6199impl SubAssign<PointAndPlane> for PointAndPlane {
6200    fn sub_assign(&mut self, other: PointAndPlane) {
6201        *self = (*self).sub(other);
6202    }
6203}
6204
6205impl Mul<PointAndPlane> for PointAndPlane {
6206    type Output = PointAndPlane;
6207
6208    fn mul(self, other: PointAndPlane) -> PointAndPlane {
6209        PointAndPlane { groups: PointAndPlaneGroups { g0: self.group0() * other.group0(), g1: self.group1() * other.group1() } }
6210    }
6211}
6212
6213impl MulAssign<PointAndPlane> for PointAndPlane {
6214    fn mul_assign(&mut self, other: PointAndPlane) {
6215        *self = (*self).mul(other);
6216    }
6217}
6218
6219impl Div<PointAndPlane> for PointAndPlane {
6220    type Output = PointAndPlane;
6221
6222    fn div(self, other: PointAndPlane) -> PointAndPlane {
6223        PointAndPlane { groups: PointAndPlaneGroups { 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]) } }
6224    }
6225}
6226
6227impl DivAssign<PointAndPlane> for PointAndPlane {
6228    fn div_assign(&mut self, other: PointAndPlane) {
6229        *self = (*self).div(other);
6230    }
6231}
6232
6233impl GeometricProduct<PointAndPlane> for PointAndPlane {
6234    type Output = Motor;
6235
6236    fn geometric_product(self, other: PointAndPlane) -> Motor {
6237        Motor { groups: MotorGroups { g0: Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group0()[0], other.group1()[1], other.group1()[2], other.group1()[3]]) * Simd32x4::from([-1.0, 1.0, 1.0, 1.0]) + Simd32x4::from(self.group1()[1]) * Simd32x4::from([other.group1()[1], other.group0()[0], other.group1()[3], other.group1()[2]]) * Simd32x4::from([1.0, 1.0, -1.0, 1.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from([other.group1()[2], other.group1()[3], other.group0()[0], other.group1()[1]]) * Simd32x4::from([1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from([other.group1()[3], other.group1()[2], other.group1()[1], other.group0()[0]]) * Simd32x4::from([1.0, -1.0, 1.0, 1.0]), g1: Simd32x4::from(0.0) - Simd32x4::from(self.group0()[0]) * Simd32x4::from([other.group1()[0], other.group0()[1], other.group0()[2], other.group0()[3]]) + Simd32x4::from(self.group0()[1]) * Simd32x4::from([other.group1()[1], other.group0()[0], other.group1()[3], other.group1()[2]]) * Simd32x4::from([-1.0, 1.0, -1.0, 1.0]) + Simd32x4::from(self.group0()[2]) * Simd32x4::from([other.group1()[2], other.group1()[3], other.group0()[0], other.group1()[1]]) * Simd32x4::from([-1.0, 1.0, 1.0, -1.0]) + Simd32x4::from(self.group0()[3]) * Simd32x4::from([other.group1()[3], other.group1()[2], other.group1()[1], other.group0()[0]]) * Simd32x4::from([-1.0, -1.0, 1.0, 1.0]) + Simd32x4::from(self.group1()[0]) * Simd32x4::from([other.group0()[0], other.group1()[1], other.group1()[2], other.group1()[3]]) + Simd32x4::from(self.group1()[1]) * Simd32x4::from([other.group0()[1], other.group1()[0], other.group0()[3], other.group0()[2]]) * Simd32x4::from([1.0, -1.0, 1.0, -1.0]) + Simd32x4::from(self.group1()[2]) * Simd32x4::from([other.group0()[2], other.group0()[3], other.group1()[0], other.group0()[1]]) * Simd32x4::from([1.0, -1.0, -1.0, 1.0]) + Simd32x4::from(self.group1()[3]) * Simd32x4::from([other.group0()[3], other.group0()[2], other.group0()[1], other.group1()[0]]) * Simd32x4::from([1.0, 1.0, -1.0, -1.0]) } }
6238    }
6239}
6240
6241impl ScalarProduct<PointAndPlane> for PointAndPlane {
6242    type Output = f32;
6243
6244    fn scalar_product(self, other: PointAndPlane) -> f32 {
6245        0.0 - self.group0()[0] * other.group0()[0] + self.group1()[1] * other.group1()[1] + self.group1()[2] * other.group1()[2] + self.group1()[3] * other.group1()[3]
6246    }
6247}
6248
6249impl SquaredMagnitude for PointAndPlane {
6250    type Output = f32;
6251
6252    fn squared_magnitude(self) -> f32 {
6253        self.scalar_product(self.reversal())
6254    }
6255}
6256
6257impl Magnitude for PointAndPlane {
6258    type Output = f32;
6259
6260    fn magnitude(self) -> f32 {
6261        self.squared_magnitude().sqrt()
6262    }
6263}
6264
6265impl Mul<f32> for PointAndPlane {
6266    type Output = PointAndPlane;
6267
6268    fn mul(self, other: f32) -> PointAndPlane {
6269        self.geometric_product(other)
6270    }
6271}
6272
6273impl MulAssign<f32> for PointAndPlane {
6274    fn mul_assign(&mut self, other: f32) {
6275        *self = (*self).mul(other);
6276    }
6277}
6278
6279impl Signum for PointAndPlane {
6280    type Output = PointAndPlane;
6281
6282    fn signum(self) -> PointAndPlane {
6283        self.geometric_product(1.0 / self.magnitude())
6284    }
6285}
6286
6287impl Inverse for PointAndPlane {
6288    type Output = PointAndPlane;
6289
6290    fn inverse(self) -> PointAndPlane {
6291        self.reversal().geometric_product(1.0 / self.squared_magnitude())
6292    }
6293}
6294
6295impl GeometricQuotient<f32> for IdealPoint {
6296    type Output = IdealPoint;
6297
6298    fn geometric_quotient(self, other: f32) -> IdealPoint {
6299        self.geometric_product(other.inverse())
6300    }
6301}
6302
6303impl GeometricQuotient<Translator> for IdealPoint {
6304    type Output = IdealPoint;
6305
6306    fn geometric_quotient(self, other: Translator) -> IdealPoint {
6307        self.geometric_product(other.inverse())
6308    }
6309}
6310
6311impl GeometricQuotient<Line> for Line {
6312    type Output = Motor;
6313
6314    fn geometric_quotient(self, other: Line) -> Motor {
6315        self.geometric_product(other.inverse())
6316    }
6317}
6318
6319impl Transformation<Line> for Line {
6320    type Output = Line;
6321
6322    fn transformation(self, other: Line) -> Line {
6323        self.geometric_product(other).geometric_product(self.reversal()).into()
6324    }
6325}
6326
6327impl GeometricQuotient<Motor> for Line {
6328    type Output = Motor;
6329
6330    fn geometric_quotient(self, other: Motor) -> Motor {
6331        self.geometric_product(other.inverse())
6332    }
6333}
6334
6335impl Transformation<Motor> for Line {
6336    type Output = Motor;
6337
6338    fn transformation(self, other: Motor) -> Motor {
6339        self.geometric_product(other).geometric_product(self.reversal())
6340    }
6341}
6342
6343impl GeometricQuotient<MultiVector> for Line {
6344    type Output = MultiVector;
6345
6346    fn geometric_quotient(self, other: MultiVector) -> MultiVector {
6347        self.geometric_product(other.inverse())
6348    }
6349}
6350
6351impl Transformation<MultiVector> for Line {
6352    type Output = MultiVector;
6353
6354    fn transformation(self, other: MultiVector) -> MultiVector {
6355        self.geometric_product(other).geometric_product(self.reversal())
6356    }
6357}
6358
6359impl GeometricQuotient<Plane> for Line {
6360    type Output = PointAndPlane;
6361
6362    fn geometric_quotient(self, other: Plane) -> PointAndPlane {
6363        self.geometric_product(other.inverse())
6364    }
6365}
6366
6367impl Transformation<Plane> for Line {
6368    type Output = Plane;
6369
6370    fn transformation(self, other: Plane) -> Plane {
6371        self.geometric_product(other).geometric_product(self.reversal()).into()
6372    }
6373}
6374
6375impl GeometricQuotient<PointAndPlane> for Line {
6376    type Output = PointAndPlane;
6377
6378    fn geometric_quotient(self, other: PointAndPlane) -> PointAndPlane {
6379        self.geometric_product(other.inverse())
6380    }
6381}
6382
6383impl Transformation<PointAndPlane> for Line {
6384    type Output = PointAndPlane;
6385
6386    fn transformation(self, other: PointAndPlane) -> PointAndPlane {
6387        self.geometric_product(other).geometric_product(self.reversal())
6388    }
6389}
6390
6391impl GeometricQuotient<Rotor> for Line {
6392    type Output = Motor;
6393
6394    fn geometric_quotient(self, other: Rotor) -> Motor {
6395        self.geometric_product(other.inverse())
6396    }
6397}
6398
6399impl Transformation<Rotor> for Line {
6400    type Output = Rotor;
6401
6402    fn transformation(self, other: Rotor) -> Rotor {
6403        self.geometric_product(other).geometric_product(self.reversal()).into()
6404    }
6405}
6406
6407impl GeometricQuotient<f32> for Line {
6408    type Output = Line;
6409
6410    fn geometric_quotient(self, other: f32) -> Line {
6411        self.geometric_product(other.inverse())
6412    }
6413}
6414
6415impl Transformation<f32> for Line {
6416    type Output = f32;
6417
6418    fn transformation(self, other: f32) -> f32 {
6419        self.geometric_product(other).geometric_product(self.reversal()).into()
6420    }
6421}
6422
6423impl GeometricQuotient<Line> for Motor {
6424    type Output = Motor;
6425
6426    fn geometric_quotient(self, other: Line) -> Motor {
6427        self.geometric_product(other.inverse())
6428    }
6429}
6430
6431impl Transformation<Line> for Motor {
6432    type Output = Line;
6433
6434    fn transformation(self, other: Line) -> Line {
6435        self.geometric_product(other).geometric_product(self.reversal()).into()
6436    }
6437}
6438
6439impl Powi for Motor {
6440    type Output = Motor;
6441
6442    fn powi(self, exponent: isize) -> Motor {
6443        if exponent == 0 {
6444            return Motor::one();
6445        }
6446        let mut x: Motor = if exponent < 0 { self.inverse() } else { self };
6447        let mut y: Motor = Motor::one();
6448        let mut n: isize = exponent.abs();
6449        while 1 < n {
6450            if n & 1 == 1 {
6451                y = x.geometric_product(y);
6452            }
6453            x = x.geometric_product(x);
6454            n = n >> 1;
6455        }
6456        x.geometric_product(y)
6457    }
6458}
6459
6460impl GeometricQuotient<Motor> for Motor {
6461    type Output = Motor;
6462
6463    fn geometric_quotient(self, other: Motor) -> Motor {
6464        self.geometric_product(other.inverse())
6465    }
6466}
6467
6468impl Transformation<Motor> for Motor {
6469    type Output = Motor;
6470
6471    fn transformation(self, other: Motor) -> Motor {
6472        self.geometric_product(other).geometric_product(self.reversal())
6473    }
6474}
6475
6476impl GeometricQuotient<MultiVector> for Motor {
6477    type Output = MultiVector;
6478
6479    fn geometric_quotient(self, other: MultiVector) -> MultiVector {
6480        self.geometric_product(other.inverse())
6481    }
6482}
6483
6484impl Transformation<MultiVector> for Motor {
6485    type Output = MultiVector;
6486
6487    fn transformation(self, other: MultiVector) -> MultiVector {
6488        self.geometric_product(other).geometric_product(self.reversal())
6489    }
6490}
6491
6492impl GeometricQuotient<Plane> for Motor {
6493    type Output = PointAndPlane;
6494
6495    fn geometric_quotient(self, other: Plane) -> PointAndPlane {
6496        self.geometric_product(other.inverse())
6497    }
6498}
6499
6500impl Transformation<Plane> for Motor {
6501    type Output = Plane;
6502
6503    fn transformation(self, other: Plane) -> Plane {
6504        self.geometric_product(other).geometric_product(self.reversal()).into()
6505    }
6506}
6507
6508impl GeometricQuotient<Point> for Motor {
6509    type Output = PointAndPlane;
6510
6511    fn geometric_quotient(self, other: Point) -> PointAndPlane {
6512        self.geometric_product(other.inverse())
6513    }
6514}
6515
6516impl Transformation<Point> for Motor {
6517    type Output = Point;
6518
6519    fn transformation(self, other: Point) -> Point {
6520        self.geometric_product(other).geometric_product(self.reversal()).into()
6521    }
6522}
6523
6524impl GeometricQuotient<PointAndPlane> for Motor {
6525    type Output = PointAndPlane;
6526
6527    fn geometric_quotient(self, other: PointAndPlane) -> PointAndPlane {
6528        self.geometric_product(other.inverse())
6529    }
6530}
6531
6532impl Transformation<PointAndPlane> for Motor {
6533    type Output = PointAndPlane;
6534
6535    fn transformation(self, other: PointAndPlane) -> PointAndPlane {
6536        self.geometric_product(other).geometric_product(self.reversal())
6537    }
6538}
6539
6540impl GeometricQuotient<Rotor> for Motor {
6541    type Output = Motor;
6542
6543    fn geometric_quotient(self, other: Rotor) -> Motor {
6544        self.geometric_product(other.inverse())
6545    }
6546}
6547
6548impl Transformation<Rotor> for Motor {
6549    type Output = Rotor;
6550
6551    fn transformation(self, other: Rotor) -> Rotor {
6552        self.geometric_product(other).geometric_product(self.reversal()).into()
6553    }
6554}
6555
6556impl GeometricQuotient<f32> for Motor {
6557    type Output = Motor;
6558
6559    fn geometric_quotient(self, other: f32) -> Motor {
6560        self.geometric_product(other.inverse())
6561    }
6562}
6563
6564impl Transformation<f32> for Motor {
6565    type Output = f32;
6566
6567    fn transformation(self, other: f32) -> f32 {
6568        self.geometric_product(other).geometric_product(self.reversal()).into()
6569    }
6570}
6571
6572impl GeometricQuotient<Translator> for Motor {
6573    type Output = Motor;
6574
6575    fn geometric_quotient(self, other: Translator) -> Motor {
6576        self.geometric_product(other.inverse())
6577    }
6578}
6579
6580impl Transformation<Translator> for Motor {
6581    type Output = Translator;
6582
6583    fn transformation(self, other: Translator) -> Translator {
6584        self.geometric_product(other).geometric_product(self.reversal()).into()
6585    }
6586}
6587
6588impl GeometricQuotient<Line> for MultiVector {
6589    type Output = MultiVector;
6590
6591    fn geometric_quotient(self, other: Line) -> MultiVector {
6592        self.geometric_product(other.inverse())
6593    }
6594}
6595
6596impl Transformation<Line> for MultiVector {
6597    type Output = Line;
6598
6599    fn transformation(self, other: Line) -> Line {
6600        self.geometric_product(other).geometric_product(self.reversal()).into()
6601    }
6602}
6603
6604impl GeometricQuotient<Motor> for MultiVector {
6605    type Output = MultiVector;
6606
6607    fn geometric_quotient(self, other: Motor) -> MultiVector {
6608        self.geometric_product(other.inverse())
6609    }
6610}
6611
6612impl Transformation<Motor> for MultiVector {
6613    type Output = Motor;
6614
6615    fn transformation(self, other: Motor) -> Motor {
6616        self.geometric_product(other).geometric_product(self.reversal()).into()
6617    }
6618}
6619
6620impl Powi for MultiVector {
6621    type Output = MultiVector;
6622
6623    fn powi(self, exponent: isize) -> MultiVector {
6624        if exponent == 0 {
6625            return MultiVector::one();
6626        }
6627        let mut x: MultiVector = if exponent < 0 { self.inverse() } else { self };
6628        let mut y: MultiVector = MultiVector::one();
6629        let mut n: isize = exponent.abs();
6630        while 1 < n {
6631            if n & 1 == 1 {
6632                y = x.geometric_product(y);
6633            }
6634            x = x.geometric_product(x);
6635            n = n >> 1;
6636        }
6637        x.geometric_product(y)
6638    }
6639}
6640
6641impl GeometricQuotient<MultiVector> for MultiVector {
6642    type Output = MultiVector;
6643
6644    fn geometric_quotient(self, other: MultiVector) -> MultiVector {
6645        self.geometric_product(other.inverse())
6646    }
6647}
6648
6649impl Transformation<MultiVector> for MultiVector {
6650    type Output = MultiVector;
6651
6652    fn transformation(self, other: MultiVector) -> MultiVector {
6653        self.geometric_product(other).geometric_product(self.reversal())
6654    }
6655}
6656
6657impl GeometricQuotient<Plane> for MultiVector {
6658    type Output = MultiVector;
6659
6660    fn geometric_quotient(self, other: Plane) -> MultiVector {
6661        self.geometric_product(other.inverse())
6662    }
6663}
6664
6665impl Transformation<Plane> for MultiVector {
6666    type Output = Plane;
6667
6668    fn transformation(self, other: Plane) -> Plane {
6669        self.geometric_product(other).geometric_product(self.reversal()).into()
6670    }
6671}
6672
6673impl GeometricQuotient<Point> for MultiVector {
6674    type Output = MultiVector;
6675
6676    fn geometric_quotient(self, other: Point) -> MultiVector {
6677        self.geometric_product(other.inverse())
6678    }
6679}
6680
6681impl Transformation<Point> for MultiVector {
6682    type Output = Point;
6683
6684    fn transformation(self, other: Point) -> Point {
6685        self.geometric_product(other).geometric_product(self.reversal()).into()
6686    }
6687}
6688
6689impl GeometricQuotient<PointAndPlane> for MultiVector {
6690    type Output = MultiVector;
6691
6692    fn geometric_quotient(self, other: PointAndPlane) -> MultiVector {
6693        self.geometric_product(other.inverse())
6694    }
6695}
6696
6697impl Transformation<PointAndPlane> for MultiVector {
6698    type Output = PointAndPlane;
6699
6700    fn transformation(self, other: PointAndPlane) -> PointAndPlane {
6701        self.geometric_product(other).geometric_product(self.reversal()).into()
6702    }
6703}
6704
6705impl GeometricQuotient<Rotor> for MultiVector {
6706    type Output = MultiVector;
6707
6708    fn geometric_quotient(self, other: Rotor) -> MultiVector {
6709        self.geometric_product(other.inverse())
6710    }
6711}
6712
6713impl Transformation<Rotor> for MultiVector {
6714    type Output = Rotor;
6715
6716    fn transformation(self, other: Rotor) -> Rotor {
6717        self.geometric_product(other).geometric_product(self.reversal()).into()
6718    }
6719}
6720
6721impl GeometricQuotient<f32> for MultiVector {
6722    type Output = MultiVector;
6723
6724    fn geometric_quotient(self, other: f32) -> MultiVector {
6725        self.geometric_product(other.inverse())
6726    }
6727}
6728
6729impl Transformation<f32> for MultiVector {
6730    type Output = f32;
6731
6732    fn transformation(self, other: f32) -> f32 {
6733        self.geometric_product(other).geometric_product(self.reversal()).into()
6734    }
6735}
6736
6737impl GeometricQuotient<Translator> for MultiVector {
6738    type Output = MultiVector;
6739
6740    fn geometric_quotient(self, other: Translator) -> MultiVector {
6741        self.geometric_product(other.inverse())
6742    }
6743}
6744
6745impl Transformation<Translator> for MultiVector {
6746    type Output = Translator;
6747
6748    fn transformation(self, other: Translator) -> Translator {
6749        self.geometric_product(other).geometric_product(self.reversal()).into()
6750    }
6751}
6752
6753impl GeometricQuotient<Line> for Plane {
6754    type Output = PointAndPlane;
6755
6756    fn geometric_quotient(self, other: Line) -> PointAndPlane {
6757        self.geometric_product(other.inverse())
6758    }
6759}
6760
6761impl Transformation<Line> for Plane {
6762    type Output = Line;
6763
6764    fn transformation(self, other: Line) -> Line {
6765        self.geometric_product(other).geometric_product(self.reversal()).into()
6766    }
6767}
6768
6769impl GeometricQuotient<Motor> for Plane {
6770    type Output = PointAndPlane;
6771
6772    fn geometric_quotient(self, other: Motor) -> PointAndPlane {
6773        self.geometric_product(other.inverse())
6774    }
6775}
6776
6777impl Transformation<Motor> for Plane {
6778    type Output = Motor;
6779
6780    fn transformation(self, other: Motor) -> Motor {
6781        self.geometric_product(other).geometric_product(self.reversal())
6782    }
6783}
6784
6785impl GeometricQuotient<MultiVector> for Plane {
6786    type Output = MultiVector;
6787
6788    fn geometric_quotient(self, other: MultiVector) -> MultiVector {
6789        self.geometric_product(other.inverse())
6790    }
6791}
6792
6793impl Transformation<MultiVector> for Plane {
6794    type Output = MultiVector;
6795
6796    fn transformation(self, other: MultiVector) -> MultiVector {
6797        self.geometric_product(other).geometric_product(self.reversal())
6798    }
6799}
6800
6801impl GeometricQuotient<PointAndPlane> for Plane {
6802    type Output = Motor;
6803
6804    fn geometric_quotient(self, other: PointAndPlane) -> Motor {
6805        self.geometric_product(other.inverse())
6806    }
6807}
6808
6809impl Transformation<PointAndPlane> for Plane {
6810    type Output = PointAndPlane;
6811
6812    fn transformation(self, other: PointAndPlane) -> PointAndPlane {
6813        self.geometric_product(other).geometric_product(self.reversal())
6814    }
6815}
6816
6817impl GeometricQuotient<Rotor> for Plane {
6818    type Output = PointAndPlane;
6819
6820    fn geometric_quotient(self, other: Rotor) -> PointAndPlane {
6821        self.geometric_product(other.inverse())
6822    }
6823}
6824
6825impl Transformation<Rotor> for Plane {
6826    type Output = Rotor;
6827
6828    fn transformation(self, other: Rotor) -> Rotor {
6829        self.geometric_product(other).geometric_product(self.reversal()).into()
6830    }
6831}
6832
6833impl GeometricQuotient<f32> for Plane {
6834    type Output = Plane;
6835
6836    fn geometric_quotient(self, other: f32) -> Plane {
6837        self.geometric_product(other.inverse())
6838    }
6839}
6840
6841impl GeometricQuotient<Motor> for Point {
6842    type Output = PointAndPlane;
6843
6844    fn geometric_quotient(self, other: Motor) -> PointAndPlane {
6845        self.geometric_product(other.inverse())
6846    }
6847}
6848
6849impl Transformation<Motor> for Point {
6850    type Output = Motor;
6851
6852    fn transformation(self, other: Motor) -> Motor {
6853        self.geometric_product(other).geometric_product(self.reversal())
6854    }
6855}
6856
6857impl GeometricQuotient<MultiVector> for Point {
6858    type Output = MultiVector;
6859
6860    fn geometric_quotient(self, other: MultiVector) -> MultiVector {
6861        self.geometric_product(other.inverse())
6862    }
6863}
6864
6865impl Transformation<MultiVector> for Point {
6866    type Output = MultiVector;
6867
6868    fn transformation(self, other: MultiVector) -> MultiVector {
6869        self.geometric_product(other).geometric_product(self.reversal())
6870    }
6871}
6872
6873impl GeometricQuotient<Point> for Point {
6874    type Output = Translator;
6875
6876    fn geometric_quotient(self, other: Point) -> Translator {
6877        self.geometric_product(other.inverse())
6878    }
6879}
6880
6881impl Transformation<Point> for Point {
6882    type Output = Point;
6883
6884    fn transformation(self, other: Point) -> Point {
6885        self.geometric_product(other).geometric_product(self.reversal())
6886    }
6887}
6888
6889impl GeometricQuotient<PointAndPlane> for Point {
6890    type Output = Motor;
6891
6892    fn geometric_quotient(self, other: PointAndPlane) -> Motor {
6893        self.geometric_product(other.inverse())
6894    }
6895}
6896
6897impl Transformation<PointAndPlane> for Point {
6898    type Output = PointAndPlane;
6899
6900    fn transformation(self, other: PointAndPlane) -> PointAndPlane {
6901        self.geometric_product(other).geometric_product(self.reversal())
6902    }
6903}
6904
6905impl GeometricQuotient<Rotor> for Point {
6906    type Output = PointAndPlane;
6907
6908    fn geometric_quotient(self, other: Rotor) -> PointAndPlane {
6909        self.geometric_product(other.inverse())
6910    }
6911}
6912
6913impl Transformation<Rotor> for Point {
6914    type Output = Rotor;
6915
6916    fn transformation(self, other: Rotor) -> Rotor {
6917        self.geometric_product(other).geometric_product(self.reversal()).into()
6918    }
6919}
6920
6921impl GeometricQuotient<f32> for Point {
6922    type Output = Point;
6923
6924    fn geometric_quotient(self, other: f32) -> Point {
6925        self.geometric_product(other.inverse())
6926    }
6927}
6928
6929impl Transformation<f32> for Point {
6930    type Output = f32;
6931
6932    fn transformation(self, other: f32) -> f32 {
6933        self.geometric_product(other).geometric_product(self.reversal()).into()
6934    }
6935}
6936
6937impl GeometricQuotient<Translator> for Point {
6938    type Output = Point;
6939
6940    fn geometric_quotient(self, other: Translator) -> Point {
6941        self.geometric_product(other.inverse())
6942    }
6943}
6944
6945impl Transformation<Translator> for Point {
6946    type Output = Translator;
6947
6948    fn transformation(self, other: Translator) -> Translator {
6949        self.geometric_product(other).geometric_product(self.reversal())
6950    }
6951}
6952
6953impl GeometricQuotient<Line> for PointAndPlane {
6954    type Output = PointAndPlane;
6955
6956    fn geometric_quotient(self, other: Line) -> PointAndPlane {
6957        self.geometric_product(other.inverse())
6958    }
6959}
6960
6961impl Transformation<Line> for PointAndPlane {
6962    type Output = Line;
6963
6964    fn transformation(self, other: Line) -> Line {
6965        self.geometric_product(other).geometric_product(self.reversal()).into()
6966    }
6967}
6968
6969impl GeometricQuotient<Motor> for PointAndPlane {
6970    type Output = PointAndPlane;
6971
6972    fn geometric_quotient(self, other: Motor) -> PointAndPlane {
6973        self.geometric_product(other.inverse())
6974    }
6975}
6976
6977impl Transformation<Motor> for PointAndPlane {
6978    type Output = Motor;
6979
6980    fn transformation(self, other: Motor) -> Motor {
6981        self.geometric_product(other).geometric_product(self.reversal())
6982    }
6983}
6984
6985impl GeometricQuotient<MultiVector> for PointAndPlane {
6986    type Output = MultiVector;
6987
6988    fn geometric_quotient(self, other: MultiVector) -> MultiVector {
6989        self.geometric_product(other.inverse())
6990    }
6991}
6992
6993impl Transformation<MultiVector> for PointAndPlane {
6994    type Output = MultiVector;
6995
6996    fn transformation(self, other: MultiVector) -> MultiVector {
6997        self.geometric_product(other).geometric_product(self.reversal())
6998    }
6999}
7000
7001impl GeometricQuotient<Plane> for PointAndPlane {
7002    type Output = Motor;
7003
7004    fn geometric_quotient(self, other: Plane) -> Motor {
7005        self.geometric_product(other.inverse())
7006    }
7007}
7008
7009impl Transformation<Plane> for PointAndPlane {
7010    type Output = Plane;
7011
7012    fn transformation(self, other: Plane) -> Plane {
7013        self.geometric_product(other).geometric_product(self.reversal()).into()
7014    }
7015}
7016
7017impl GeometricQuotient<Point> for PointAndPlane {
7018    type Output = Motor;
7019
7020    fn geometric_quotient(self, other: Point) -> Motor {
7021        self.geometric_product(other.inverse())
7022    }
7023}
7024
7025impl Transformation<Point> for PointAndPlane {
7026    type Output = Point;
7027
7028    fn transformation(self, other: Point) -> Point {
7029        self.geometric_product(other).geometric_product(self.reversal()).into()
7030    }
7031}
7032
7033impl GeometricQuotient<PointAndPlane> for PointAndPlane {
7034    type Output = Motor;
7035
7036    fn geometric_quotient(self, other: PointAndPlane) -> Motor {
7037        self.geometric_product(other.inverse())
7038    }
7039}
7040
7041impl Transformation<PointAndPlane> for PointAndPlane {
7042    type Output = PointAndPlane;
7043
7044    fn transformation(self, other: PointAndPlane) -> PointAndPlane {
7045        self.geometric_product(other).geometric_product(self.reversal())
7046    }
7047}
7048
7049impl GeometricQuotient<Rotor> for PointAndPlane {
7050    type Output = PointAndPlane;
7051
7052    fn geometric_quotient(self, other: Rotor) -> PointAndPlane {
7053        self.geometric_product(other.inverse())
7054    }
7055}
7056
7057impl Transformation<Rotor> for PointAndPlane {
7058    type Output = Rotor;
7059
7060    fn transformation(self, other: Rotor) -> Rotor {
7061        self.geometric_product(other).geometric_product(self.reversal()).into()
7062    }
7063}
7064
7065impl GeometricQuotient<f32> for PointAndPlane {
7066    type Output = PointAndPlane;
7067
7068    fn geometric_quotient(self, other: f32) -> PointAndPlane {
7069        self.geometric_product(other.inverse())
7070    }
7071}
7072
7073impl Transformation<f32> for PointAndPlane {
7074    type Output = f32;
7075
7076    fn transformation(self, other: f32) -> f32 {
7077        self.geometric_product(other).geometric_product(self.reversal()).into()
7078    }
7079}
7080
7081impl GeometricQuotient<Translator> for PointAndPlane {
7082    type Output = PointAndPlane;
7083
7084    fn geometric_quotient(self, other: Translator) -> PointAndPlane {
7085        self.geometric_product(other.inverse())
7086    }
7087}
7088
7089impl Transformation<Translator> for PointAndPlane {
7090    type Output = Translator;
7091
7092    fn transformation(self, other: Translator) -> Translator {
7093        self.geometric_product(other).geometric_product(self.reversal()).into()
7094    }
7095}
7096
7097impl GeometricQuotient<Line> for Rotor {
7098    type Output = Motor;
7099
7100    fn geometric_quotient(self, other: Line) -> Motor {
7101        self.geometric_product(other.inverse())
7102    }
7103}
7104
7105impl Transformation<Line> for Rotor {
7106    type Output = Line;
7107
7108    fn transformation(self, other: Line) -> Line {
7109        self.geometric_product(other).geometric_product(self.reversal()).into()
7110    }
7111}
7112
7113impl GeometricQuotient<Motor> for Rotor {
7114    type Output = Motor;
7115
7116    fn geometric_quotient(self, other: Motor) -> Motor {
7117        self.geometric_product(other.inverse())
7118    }
7119}
7120
7121impl Transformation<Motor> for Rotor {
7122    type Output = Motor;
7123
7124    fn transformation(self, other: Motor) -> Motor {
7125        self.geometric_product(other).geometric_product(self.reversal())
7126    }
7127}
7128
7129impl GeometricQuotient<MultiVector> for Rotor {
7130    type Output = MultiVector;
7131
7132    fn geometric_quotient(self, other: MultiVector) -> MultiVector {
7133        self.geometric_product(other.inverse())
7134    }
7135}
7136
7137impl Transformation<MultiVector> for Rotor {
7138    type Output = MultiVector;
7139
7140    fn transformation(self, other: MultiVector) -> MultiVector {
7141        self.geometric_product(other).geometric_product(self.reversal())
7142    }
7143}
7144
7145impl GeometricQuotient<Plane> for Rotor {
7146    type Output = PointAndPlane;
7147
7148    fn geometric_quotient(self, other: Plane) -> PointAndPlane {
7149        self.geometric_product(other.inverse())
7150    }
7151}
7152
7153impl Transformation<Plane> for Rotor {
7154    type Output = Plane;
7155
7156    fn transformation(self, other: Plane) -> Plane {
7157        self.geometric_product(other).geometric_product(self.reversal()).into()
7158    }
7159}
7160
7161impl GeometricQuotient<Point> for Rotor {
7162    type Output = PointAndPlane;
7163
7164    fn geometric_quotient(self, other: Point) -> PointAndPlane {
7165        self.geometric_product(other.inverse())
7166    }
7167}
7168
7169impl Transformation<Point> for Rotor {
7170    type Output = Point;
7171
7172    fn transformation(self, other: Point) -> Point {
7173        self.geometric_product(other).geometric_product(self.reversal()).into()
7174    }
7175}
7176
7177impl GeometricQuotient<PointAndPlane> for Rotor {
7178    type Output = PointAndPlane;
7179
7180    fn geometric_quotient(self, other: PointAndPlane) -> PointAndPlane {
7181        self.geometric_product(other.inverse())
7182    }
7183}
7184
7185impl Transformation<PointAndPlane> for Rotor {
7186    type Output = PointAndPlane;
7187
7188    fn transformation(self, other: PointAndPlane) -> PointAndPlane {
7189        self.geometric_product(other).geometric_product(self.reversal())
7190    }
7191}
7192
7193impl Powi for Rotor {
7194    type Output = Rotor;
7195
7196    fn powi(self, exponent: isize) -> Rotor {
7197        if exponent == 0 {
7198            return Rotor::one();
7199        }
7200        let mut x: Rotor = if exponent < 0 { self.inverse() } else { self };
7201        let mut y: Rotor = Rotor::one();
7202        let mut n: isize = exponent.abs();
7203        while 1 < n {
7204            if n & 1 == 1 {
7205                y = x.geometric_product(y);
7206            }
7207            x = x.geometric_product(x);
7208            n = n >> 1;
7209        }
7210        x.geometric_product(y)
7211    }
7212}
7213
7214impl GeometricQuotient<Rotor> for Rotor {
7215    type Output = Rotor;
7216
7217    fn geometric_quotient(self, other: Rotor) -> Rotor {
7218        self.geometric_product(other.inverse())
7219    }
7220}
7221
7222impl Transformation<Rotor> for Rotor {
7223    type Output = Rotor;
7224
7225    fn transformation(self, other: Rotor) -> Rotor {
7226        self.geometric_product(other).geometric_product(self.reversal())
7227    }
7228}
7229
7230impl GeometricQuotient<f32> for Rotor {
7231    type Output = Rotor;
7232
7233    fn geometric_quotient(self, other: f32) -> Rotor {
7234        self.geometric_product(other.inverse())
7235    }
7236}
7237
7238impl Transformation<f32> for Rotor {
7239    type Output = f32;
7240
7241    fn transformation(self, other: f32) -> f32 {
7242        self.geometric_product(other).geometric_product(self.reversal()).into()
7243    }
7244}
7245
7246impl GeometricQuotient<Translator> for Rotor {
7247    type Output = Motor;
7248
7249    fn geometric_quotient(self, other: Translator) -> Motor {
7250        self.geometric_product(other.inverse())
7251    }
7252}
7253
7254impl Transformation<Translator> for Rotor {
7255    type Output = Translator;
7256
7257    fn transformation(self, other: Translator) -> Translator {
7258        self.geometric_product(other).geometric_product(self.reversal()).into()
7259    }
7260}
7261
7262impl Transformation<IdealPoint> for f32 {
7263    type Output = IdealPoint;
7264
7265    fn transformation(self, other: IdealPoint) -> IdealPoint {
7266        self.geometric_product(other).geometric_product(self.reversal())
7267    }
7268}
7269
7270impl GeometricQuotient<Line> for f32 {
7271    type Output = Line;
7272
7273    fn geometric_quotient(self, other: Line) -> Line {
7274        self.geometric_product(other.inverse())
7275    }
7276}
7277
7278impl Transformation<Line> for f32 {
7279    type Output = Line;
7280
7281    fn transformation(self, other: Line) -> Line {
7282        self.geometric_product(other).geometric_product(self.reversal())
7283    }
7284}
7285
7286impl GeometricQuotient<Motor> for f32 {
7287    type Output = Motor;
7288
7289    fn geometric_quotient(self, other: Motor) -> Motor {
7290        self.geometric_product(other.inverse())
7291    }
7292}
7293
7294impl Transformation<Motor> for f32 {
7295    type Output = Motor;
7296
7297    fn transformation(self, other: Motor) -> Motor {
7298        self.geometric_product(other).geometric_product(self.reversal())
7299    }
7300}
7301
7302impl GeometricQuotient<MultiVector> for f32 {
7303    type Output = MultiVector;
7304
7305    fn geometric_quotient(self, other: MultiVector) -> MultiVector {
7306        self.geometric_product(other.inverse())
7307    }
7308}
7309
7310impl Transformation<MultiVector> for f32 {
7311    type Output = MultiVector;
7312
7313    fn transformation(self, other: MultiVector) -> MultiVector {
7314        self.geometric_product(other).geometric_product(self.reversal())
7315    }
7316}
7317
7318impl GeometricQuotient<Plane> for f32 {
7319    type Output = Plane;
7320
7321    fn geometric_quotient(self, other: Plane) -> Plane {
7322        self.geometric_product(other.inverse())
7323    }
7324}
7325
7326impl Transformation<Plane> for f32 {
7327    type Output = Plane;
7328
7329    fn transformation(self, other: Plane) -> Plane {
7330        self.geometric_product(other).geometric_product(self.reversal())
7331    }
7332}
7333
7334impl GeometricQuotient<Point> for f32 {
7335    type Output = Point;
7336
7337    fn geometric_quotient(self, other: Point) -> Point {
7338        self.geometric_product(other.inverse())
7339    }
7340}
7341
7342impl Transformation<Point> for f32 {
7343    type Output = Point;
7344
7345    fn transformation(self, other: Point) -> Point {
7346        self.geometric_product(other).geometric_product(self.reversal())
7347    }
7348}
7349
7350impl GeometricQuotient<PointAndPlane> for f32 {
7351    type Output = PointAndPlane;
7352
7353    fn geometric_quotient(self, other: PointAndPlane) -> PointAndPlane {
7354        self.geometric_product(other.inverse())
7355    }
7356}
7357
7358impl Transformation<PointAndPlane> for f32 {
7359    type Output = PointAndPlane;
7360
7361    fn transformation(self, other: PointAndPlane) -> PointAndPlane {
7362        self.geometric_product(other).geometric_product(self.reversal())
7363    }
7364}
7365
7366impl GeometricQuotient<Rotor> for f32 {
7367    type Output = Rotor;
7368
7369    fn geometric_quotient(self, other: Rotor) -> Rotor {
7370        self.geometric_product(other.inverse())
7371    }
7372}
7373
7374impl Transformation<Rotor> for f32 {
7375    type Output = Rotor;
7376
7377    fn transformation(self, other: Rotor) -> Rotor {
7378        self.geometric_product(other).geometric_product(self.reversal())
7379    }
7380}
7381
7382impl GeometricQuotient<Translator> for f32 {
7383    type Output = Translator;
7384
7385    fn geometric_quotient(self, other: Translator) -> Translator {
7386        self.geometric_product(other.inverse())
7387    }
7388}
7389
7390impl Transformation<Translator> for f32 {
7391    type Output = Translator;
7392
7393    fn transformation(self, other: Translator) -> Translator {
7394        self.geometric_product(other).geometric_product(self.reversal())
7395    }
7396}
7397
7398impl Transformation<IdealPoint> for Translator {
7399    type Output = IdealPoint;
7400
7401    fn transformation(self, other: IdealPoint) -> IdealPoint {
7402        self.geometric_product(other).geometric_product(self.reversal())
7403    }
7404}
7405
7406impl GeometricQuotient<Motor> for Translator {
7407    type Output = Motor;
7408
7409    fn geometric_quotient(self, other: Motor) -> Motor {
7410        self.geometric_product(other.inverse())
7411    }
7412}
7413
7414impl Transformation<Motor> for Translator {
7415    type Output = Motor;
7416
7417    fn transformation(self, other: Motor) -> Motor {
7418        self.geometric_product(other).geometric_product(self.reversal())
7419    }
7420}
7421
7422impl GeometricQuotient<MultiVector> for Translator {
7423    type Output = MultiVector;
7424
7425    fn geometric_quotient(self, other: MultiVector) -> MultiVector {
7426        self.geometric_product(other.inverse())
7427    }
7428}
7429
7430impl Transformation<MultiVector> for Translator {
7431    type Output = MultiVector;
7432
7433    fn transformation(self, other: MultiVector) -> MultiVector {
7434        self.geometric_product(other).geometric_product(self.reversal())
7435    }
7436}
7437
7438impl GeometricQuotient<Point> for Translator {
7439    type Output = Point;
7440
7441    fn geometric_quotient(self, other: Point) -> Point {
7442        self.geometric_product(other.inverse())
7443    }
7444}
7445
7446impl Transformation<Point> for Translator {
7447    type Output = Point;
7448
7449    fn transformation(self, other: Point) -> Point {
7450        self.geometric_product(other).geometric_product(self.reversal())
7451    }
7452}
7453
7454impl GeometricQuotient<PointAndPlane> for Translator {
7455    type Output = PointAndPlane;
7456
7457    fn geometric_quotient(self, other: PointAndPlane) -> PointAndPlane {
7458        self.geometric_product(other.inverse())
7459    }
7460}
7461
7462impl Transformation<PointAndPlane> for Translator {
7463    type Output = PointAndPlane;
7464
7465    fn transformation(self, other: PointAndPlane) -> PointAndPlane {
7466        self.geometric_product(other).geometric_product(self.reversal())
7467    }
7468}
7469
7470impl GeometricQuotient<Rotor> for Translator {
7471    type Output = Motor;
7472
7473    fn geometric_quotient(self, other: Rotor) -> Motor {
7474        self.geometric_product(other.inverse())
7475    }
7476}
7477
7478impl Transformation<Rotor> for Translator {
7479    type Output = Rotor;
7480
7481    fn transformation(self, other: Rotor) -> Rotor {
7482        self.geometric_product(other).geometric_product(self.reversal()).into()
7483    }
7484}
7485
7486impl GeometricQuotient<f32> for Translator {
7487    type Output = Translator;
7488
7489    fn geometric_quotient(self, other: f32) -> Translator {
7490        self.geometric_product(other.inverse())
7491    }
7492}
7493
7494impl Transformation<f32> for Translator {
7495    type Output = f32;
7496
7497    fn transformation(self, other: f32) -> f32 {
7498        self.geometric_product(other).geometric_product(self.reversal()).into()
7499    }
7500}
7501
7502impl Powi for Translator {
7503    type Output = Translator;
7504
7505    fn powi(self, exponent: isize) -> Translator {
7506        if exponent == 0 {
7507            return Translator::one();
7508        }
7509        let mut x: Translator = if exponent < 0 { self.inverse() } else { self };
7510        let mut y: Translator = Translator::one();
7511        let mut n: isize = exponent.abs();
7512        while 1 < n {
7513            if n & 1 == 1 {
7514                y = x.geometric_product(y);
7515            }
7516            x = x.geometric_product(x);
7517            n = n >> 1;
7518        }
7519        x.geometric_product(y)
7520    }
7521}
7522
7523impl GeometricQuotient<Translator> for Translator {
7524    type Output = Translator;
7525
7526    fn geometric_quotient(self, other: Translator) -> Translator {
7527        self.geometric_product(other.inverse())
7528    }
7529}
7530
7531impl Transformation<Translator> for Translator {
7532    type Output = Translator;
7533
7534    fn transformation(self, other: Translator) -> Translator {
7535        self.geometric_product(other).geometric_product(self.reversal())
7536    }
7537}
7538