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