1#![allow(clippy::op_ref)]
3
4use crate::base::storage::Storage;
51use crate::{
52 DualQuaternion, Isometry3, Point, Point3, Quaternion, SimdRealField, Translation3, Unit,
53 UnitDualQuaternion, UnitQuaternion, Vector, Vector3, U3,
54};
55use std::ops::{
56 Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign,
57};
58
59impl<T: SimdRealField> AsRef<[T; 8]> for DualQuaternion<T> {
60 #[inline]
61 fn as_ref(&self) -> &[T; 8] {
62 unsafe { &*(self as *const Self as *const [T; 8]) }
63 }
64}
65
66impl<T: SimdRealField> AsMut<[T; 8]> for DualQuaternion<T> {
67 #[inline]
68 fn as_mut(&mut self) -> &mut [T; 8] {
69 unsafe { &mut *(self as *mut Self as *mut [T; 8]) }
70 }
71}
72
73impl<T: SimdRealField> Index<usize> for DualQuaternion<T> {
74 type Output = T;
75
76 #[inline]
77 fn index(&self, i: usize) -> &Self::Output {
78 &self.as_ref()[i]
79 }
80}
81
82impl<T: SimdRealField> IndexMut<usize> for DualQuaternion<T> {
83 #[inline]
84 fn index_mut(&mut self, i: usize) -> &mut T {
85 &mut self.as_mut()[i]
86 }
87}
88
89impl<T: SimdRealField> Neg for DualQuaternion<T>
90where
91 T::Element: SimdRealField,
92{
93 type Output = DualQuaternion<T>;
94
95 #[inline]
96 fn neg(self) -> Self::Output {
97 DualQuaternion::from_real_and_dual(-self.real, -self.dual)
98 }
99}
100
101impl<'a, T: SimdRealField> Neg for &'a DualQuaternion<T>
102where
103 T::Element: SimdRealField,
104{
105 type Output = DualQuaternion<T>;
106
107 #[inline]
108 fn neg(self) -> Self::Output {
109 DualQuaternion::from_real_and_dual(-&self.real, -&self.dual)
110 }
111}
112
113impl<T: SimdRealField> Neg for UnitDualQuaternion<T>
114where
115 T::Element: SimdRealField,
116{
117 type Output = UnitDualQuaternion<T>;
118
119 #[inline]
120 fn neg(self) -> Self::Output {
121 UnitDualQuaternion::new_unchecked(-self.into_inner())
122 }
123}
124
125impl<'a, T: SimdRealField> Neg for &'a UnitDualQuaternion<T>
126where
127 T::Element: SimdRealField,
128{
129 type Output = UnitDualQuaternion<T>;
130
131 #[inline]
132 fn neg(self) -> Self::Output {
133 UnitDualQuaternion::new_unchecked(-self.as_ref())
134 }
135}
136
137macro_rules! dual_quaternion_op_impl(
138 ($Op: ident, $op: ident;
139 ($LhsRDim: ident, $LhsCDim: ident), ($RhsRDim: ident, $RhsCDim: ident)
140 $(for $Storage: ident: $StoragesBound: ident $(<$($BoundParam: ty),*>)*),*;
141 $lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty, Output = $Result: ty $(=> $VDimA: ty, $VDimB: ty)*;
142 $action: expr; $($lives: tt),*) => {
143 impl<$($lives ,)* T: SimdRealField $(, $Storage: $StoragesBound $(<$($BoundParam),*>)*)*> $Op<$Rhs> for $Lhs
144 where T::Element: SimdRealField, {
145 type Output = $Result;
146
147 #[inline]
148 fn $op($lhs, $rhs: $Rhs) -> Self::Output {
149 $action
150 }
151 }
152 }
153);
154
155dual_quaternion_op_impl!(
157 Add, add;
158 (U4, U1), (U4, U1);
159 self: &'a DualQuaternion<T>, rhs: &'b DualQuaternion<T>, Output = DualQuaternion<T>;
160 DualQuaternion::from_real_and_dual(
161 &self.real + &rhs.real,
162 &self.dual + &rhs.dual,
163 );
164 'a, 'b);
165
166dual_quaternion_op_impl!(
167 Add, add;
168 (U4, U1), (U4, U1);
169 self: &'a DualQuaternion<T>, rhs: DualQuaternion<T>, Output = DualQuaternion<T>;
170 DualQuaternion::from_real_and_dual(
171 &self.real + rhs.real,
172 &self.dual + rhs.dual,
173 );
174 'a);
175
176dual_quaternion_op_impl!(
177 Add, add;
178 (U4, U1), (U4, U1);
179 self: DualQuaternion<T>, rhs: &'b DualQuaternion<T>, Output = DualQuaternion<T>;
180 DualQuaternion::from_real_and_dual(
181 self.real + &rhs.real,
182 self.dual + &rhs.dual,
183 );
184 'b);
185
186dual_quaternion_op_impl!(
187 Add, add;
188 (U4, U1), (U4, U1);
189 self: DualQuaternion<T>, rhs: DualQuaternion<T>, Output = DualQuaternion<T>;
190 DualQuaternion::from_real_and_dual(
191 self.real + rhs.real,
192 self.dual + rhs.dual,
193 ); );
194
195dual_quaternion_op_impl!(
197 Sub, sub;
198 (U4, U1), (U4, U1);
199 self: &'a DualQuaternion<T>, rhs: &'b DualQuaternion<T>, Output = DualQuaternion<T>;
200 DualQuaternion::from_real_and_dual(
201 &self.real - &rhs.real,
202 &self.dual - &rhs.dual,
203 );
204 'a, 'b);
205
206dual_quaternion_op_impl!(
207 Sub, sub;
208 (U4, U1), (U4, U1);
209 self: &'a DualQuaternion<T>, rhs: DualQuaternion<T>, Output = DualQuaternion<T>;
210 DualQuaternion::from_real_and_dual(
211 &self.real - rhs.real,
212 &self.dual - rhs.dual,
213 );
214 'a);
215
216dual_quaternion_op_impl!(
217 Sub, sub;
218 (U4, U1), (U4, U1);
219 self: DualQuaternion<T>, rhs: &'b DualQuaternion<T>, Output = DualQuaternion<T>;
220 DualQuaternion::from_real_and_dual(
221 self.real - &rhs.real,
222 self.dual - &rhs.dual,
223 );
224 'b);
225
226dual_quaternion_op_impl!(
227 Sub, sub;
228 (U4, U1), (U4, U1);
229 self: DualQuaternion<T>, rhs: DualQuaternion<T>, Output = DualQuaternion<T>;
230 DualQuaternion::from_real_and_dual(
231 self.real - rhs.real,
232 self.dual - rhs.dual,
233 ); );
234
235dual_quaternion_op_impl!(
237 Mul, mul;
238 (U4, U1), (U4, U1);
239 self: &'a DualQuaternion<T>, rhs: &'b DualQuaternion<T>, Output = DualQuaternion<T>;
240 DualQuaternion::from_real_and_dual(
241 &self.real * &rhs.real,
242 &self.real * &rhs.dual + &self.dual * &rhs.real,
243 );
244 'a, 'b);
245
246dual_quaternion_op_impl!(
247 Mul, mul;
248 (U4, U1), (U4, U1);
249 self: &'a DualQuaternion<T>, rhs: DualQuaternion<T>, Output = DualQuaternion<T>;
250 self * &rhs;
251 'a);
252
253dual_quaternion_op_impl!(
254 Mul, mul;
255 (U4, U1), (U4, U1);
256 self: DualQuaternion<T>, rhs: &'b DualQuaternion<T>, Output = DualQuaternion<T>;
257 &self * rhs;
258 'b);
259
260dual_quaternion_op_impl!(
261 Mul, mul;
262 (U4, U1), (U4, U1);
263 self: DualQuaternion<T>, rhs: DualQuaternion<T>, Output = DualQuaternion<T>;
264 &self * &rhs; );
265
266dual_quaternion_op_impl!(
268 Mul, mul;
269 (U4, U1), (U4, U1);
270 self: &'a DualQuaternion<T>, rhs: &'b UnitDualQuaternion<T>, Output = DualQuaternion<T>;
271 self * rhs.dual_quaternion();
272 'a, 'b);
273
274dual_quaternion_op_impl!(
275 Mul, mul;
276 (U4, U1), (U4, U1);
277 self: &'a DualQuaternion<T>, rhs: UnitDualQuaternion<T>, Output = DualQuaternion<T>;
278 self * rhs.dual_quaternion();
279 'a);
280
281dual_quaternion_op_impl!(
282 Mul, mul;
283 (U4, U1), (U4, U1);
284 self: DualQuaternion<T>, rhs: &'b UnitDualQuaternion<T>, Output = DualQuaternion<T>;
285 self * rhs.dual_quaternion();
286 'b);
287
288dual_quaternion_op_impl!(
289 Mul, mul;
290 (U4, U1), (U4, U1);
291 self: DualQuaternion<T>, rhs: UnitDualQuaternion<T>, Output = DualQuaternion<T>;
292 self * rhs.dual_quaternion(););
293
294dual_quaternion_op_impl!(
296 Div, div;
297 (U4, U1), (U4, U1);
298 self: &'a DualQuaternion<T>, rhs: &'b UnitDualQuaternion<T>, Output = DualQuaternion<T>;
299 #[allow(clippy::suspicious_arithmetic_impl)]
300 { self * rhs.inverse().dual_quaternion() };
301 'a, 'b);
302
303dual_quaternion_op_impl!(
304 Div, div;
305 (U4, U1), (U4, U1);
306 self: &'a DualQuaternion<T>, rhs: UnitDualQuaternion<T>, Output = DualQuaternion<T>;
307 #[allow(clippy::suspicious_arithmetic_impl)]
308 { self * rhs.inverse().dual_quaternion() };
309 'a);
310
311dual_quaternion_op_impl!(
312 Div, div;
313 (U4, U1), (U4, U1);
314 self: DualQuaternion<T>, rhs: &'b UnitDualQuaternion<T>, Output = DualQuaternion<T>;
315 #[allow(clippy::suspicious_arithmetic_impl)]
316 { self * rhs.inverse().dual_quaternion() };
317 'b);
318
319dual_quaternion_op_impl!(
320 Div, div;
321 (U4, U1), (U4, U1);
322 self: DualQuaternion<T>, rhs: UnitDualQuaternion<T>, Output = DualQuaternion<T>;
323 #[allow(clippy::suspicious_arithmetic_impl)]
324 { self * rhs.inverse().dual_quaternion() };);
325
326dual_quaternion_op_impl!(
328 Mul, mul;
329 (U4, U1), (U4, U1);
330 self: &'a UnitDualQuaternion<T>, rhs: &'b UnitDualQuaternion<T>, Output = UnitDualQuaternion<T>;
331 UnitDualQuaternion::new_unchecked(self.as_ref() * rhs.as_ref());
332 'a, 'b);
333
334dual_quaternion_op_impl!(
335 Mul, mul;
336 (U4, U1), (U4, U1);
337 self: &'a UnitDualQuaternion<T>, rhs: UnitDualQuaternion<T>, Output = UnitDualQuaternion<T>;
338 self * &rhs;
339 'a);
340
341dual_quaternion_op_impl!(
342 Mul, mul;
343 (U4, U1), (U4, U1);
344 self: UnitDualQuaternion<T>, rhs: &'b UnitDualQuaternion<T>, Output = UnitDualQuaternion<T>;
345 &self * rhs;
346 'b);
347
348dual_quaternion_op_impl!(
349 Mul, mul;
350 (U4, U1), (U4, U1);
351 self: UnitDualQuaternion<T>, rhs: UnitDualQuaternion<T>, Output = UnitDualQuaternion<T>;
352 &self * &rhs; );
353
354dual_quaternion_op_impl!(
356 Div, div;
357 (U4, U1), (U4, U1);
358 self: &'a UnitDualQuaternion<T>, rhs: &'b UnitDualQuaternion<T>, Output = UnitDualQuaternion<T>;
359 #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() };
360 'a, 'b);
361
362dual_quaternion_op_impl!(
363 Div, div;
364 (U4, U1), (U4, U1);
365 self: &'a UnitDualQuaternion<T>, rhs: UnitDualQuaternion<T>, Output = UnitDualQuaternion<T>;
366 self / &rhs;
367 'a);
368
369dual_quaternion_op_impl!(
370 Div, div;
371 (U4, U1), (U4, U1);
372 self: UnitDualQuaternion<T>, rhs: &'b UnitDualQuaternion<T>, Output = UnitDualQuaternion<T>;
373 &self / rhs;
374 'b);
375
376dual_quaternion_op_impl!(
377 Div, div;
378 (U4, U1), (U4, U1);
379 self: UnitDualQuaternion<T>, rhs: UnitDualQuaternion<T>, Output = UnitDualQuaternion<T>;
380 &self / &rhs; );
381
382dual_quaternion_op_impl!(
384 Mul, mul;
385 (U4, U1), (U4, U1);
386 self: &'a UnitDualQuaternion<T>, rhs: &'b DualQuaternion<T>,
387 Output = DualQuaternion<T> => U1, U4;
388 self.dual_quaternion() * rhs;
389 'a, 'b);
390
391dual_quaternion_op_impl!(
392 Mul, mul;
393 (U4, U1), (U4, U1);
394 self: &'a UnitDualQuaternion<T>, rhs: DualQuaternion<T>,
395 Output = DualQuaternion<T> => U3, U3;
396 self.dual_quaternion() * rhs;
397 'a);
398
399dual_quaternion_op_impl!(
400 Mul, mul;
401 (U4, U1), (U4, U1);
402 self: UnitDualQuaternion<T>, rhs: &'b DualQuaternion<T>,
403 Output = DualQuaternion<T> => U3, U3;
404 self.dual_quaternion() * rhs;
405 'b);
406
407dual_quaternion_op_impl!(
408 Mul, mul;
409 (U4, U1), (U4, U1);
410 self: UnitDualQuaternion<T>, rhs: DualQuaternion<T>,
411 Output = DualQuaternion<T> => U3, U3;
412 self.dual_quaternion() * rhs;);
413
414dual_quaternion_op_impl!(
416 Mul, mul;
417 (U4, U1), (U4, U1);
418 self: &'a UnitDualQuaternion<T>, rhs: &'b UnitQuaternion<T>,
419 Output = UnitDualQuaternion<T> => U1, U4;
420 self * UnitDualQuaternion::<T>::new_unchecked(DualQuaternion::from_real(rhs.clone().into_inner()));
421 'a, 'b);
422
423dual_quaternion_op_impl!(
424 Mul, mul;
425 (U4, U1), (U4, U1);
426 self: &'a UnitDualQuaternion<T>, rhs: UnitQuaternion<T>,
427 Output = UnitDualQuaternion<T> => U3, U3;
428 self * UnitDualQuaternion::<T>::new_unchecked(DualQuaternion::from_real(rhs.into_inner()));
429 'a);
430
431dual_quaternion_op_impl!(
432 Mul, mul;
433 (U4, U1), (U4, U1);
434 self: UnitDualQuaternion<T>, rhs: &'b UnitQuaternion<T>,
435 Output = UnitDualQuaternion<T> => U3, U3;
436 self * UnitDualQuaternion::<T>::new_unchecked(DualQuaternion::from_real(rhs.clone().into_inner()));
437 'b);
438
439dual_quaternion_op_impl!(
440 Mul, mul;
441 (U4, U1), (U4, U1);
442 self: UnitDualQuaternion<T>, rhs: UnitQuaternion<T>,
443 Output = UnitDualQuaternion<T> => U3, U3;
444 self * UnitDualQuaternion::<T>::new_unchecked(DualQuaternion::from_real(rhs.into_inner())););
445
446dual_quaternion_op_impl!(
448 Mul, mul;
449 (U4, U1), (U4, U1);
450 self: &'a UnitQuaternion<T>, rhs: &'b UnitDualQuaternion<T>,
451 Output = UnitDualQuaternion<T> => U1, U4;
452 UnitDualQuaternion::<T>::new_unchecked(DualQuaternion::from_real(self.clone().into_inner())) * rhs;
453 'a, 'b);
454
455dual_quaternion_op_impl!(
456 Mul, mul;
457 (U4, U1), (U4, U1);
458 self: &'a UnitQuaternion<T>, rhs: UnitDualQuaternion<T>,
459 Output = UnitDualQuaternion<T> => U3, U3;
460 UnitDualQuaternion::<T>::new_unchecked(DualQuaternion::from_real(self.clone().into_inner())) * rhs;
461 'a);
462
463dual_quaternion_op_impl!(
464 Mul, mul;
465 (U4, U1), (U4, U1);
466 self: UnitQuaternion<T>, rhs: &'b UnitDualQuaternion<T>,
467 Output = UnitDualQuaternion<T> => U3, U3;
468 UnitDualQuaternion::<T>::new_unchecked(DualQuaternion::from_real(self.into_inner())) * rhs;
469 'b);
470
471dual_quaternion_op_impl!(
472 Mul, mul;
473 (U4, U1), (U4, U1);
474 self: UnitQuaternion<T>, rhs: UnitDualQuaternion<T>,
475 Output = UnitDualQuaternion<T> => U3, U3;
476 UnitDualQuaternion::<T>::new_unchecked(DualQuaternion::from_real(self.into_inner())) * rhs;);
477
478dual_quaternion_op_impl!(
480 Div, div;
481 (U4, U1), (U4, U1);
482 self: &'a UnitDualQuaternion<T>, rhs: &'b UnitQuaternion<T>,
483 Output = UnitDualQuaternion<T> => U1, U4;
484 #[allow(clippy::suspicious_arithmetic_impl)]
485 { self * UnitDualQuaternion::<T>::from_rotation(rhs.inverse()) };
486 'a, 'b);
487
488dual_quaternion_op_impl!(
489 Div, div;
490 (U4, U1), (U4, U1);
491 self: &'a UnitDualQuaternion<T>, rhs: UnitQuaternion<T>,
492 Output = UnitDualQuaternion<T> => U3, U3;
493 #[allow(clippy::suspicious_arithmetic_impl)]
494 { self * UnitDualQuaternion::<T>::from_rotation(rhs.inverse()) };
495 'a);
496
497dual_quaternion_op_impl!(
498 Div, div;
499 (U4, U1), (U4, U1);
500 self: UnitDualQuaternion<T>, rhs: &'b UnitQuaternion<T>,
501 Output = UnitDualQuaternion<T> => U3, U3;
502 #[allow(clippy::suspicious_arithmetic_impl)]
503 { self * UnitDualQuaternion::<T>::from_rotation(rhs.inverse()) };
504 'b);
505
506dual_quaternion_op_impl!(
507 Div, div;
508 (U4, U1), (U4, U1);
509 self: UnitDualQuaternion<T>, rhs: UnitQuaternion<T>,
510 Output = UnitDualQuaternion<T> => U3, U3;
511 #[allow(clippy::suspicious_arithmetic_impl)]
512 { self * UnitDualQuaternion::<T>::from_rotation(rhs.inverse()) };);
513
514dual_quaternion_op_impl!(
516 Div, div;
517 (U4, U1), (U4, U1);
518 self: &'a UnitQuaternion<T>, rhs: &'b UnitDualQuaternion<T>,
519 Output = UnitDualQuaternion<T> => U1, U4;
520 #[allow(clippy::suspicious_arithmetic_impl)]
521 {
522 UnitDualQuaternion::<T>::new_unchecked(
523 DualQuaternion::from_real(self.clone().into_inner())
524 ) * rhs.inverse()
525 }; 'a, 'b);
526
527dual_quaternion_op_impl!(
528 Div, div;
529 (U4, U1), (U4, U1);
530 self: &'a UnitQuaternion<T>, rhs: UnitDualQuaternion<T>,
531 Output = UnitDualQuaternion<T> => U3, U3;
532 #[allow(clippy::suspicious_arithmetic_impl)]
533 {
534 UnitDualQuaternion::<T>::new_unchecked(
535 DualQuaternion::from_real(self.clone().into_inner())
536 ) * rhs.inverse()
537 }; 'a);
538
539dual_quaternion_op_impl!(
540 Div, div;
541 (U4, U1), (U4, U1);
542 self: UnitQuaternion<T>, rhs: &'b UnitDualQuaternion<T>,
543 Output = UnitDualQuaternion<T> => U3, U3;
544 #[allow(clippy::suspicious_arithmetic_impl)]
545 {
546 UnitDualQuaternion::<T>::new_unchecked(
547 DualQuaternion::from_real(self.into_inner())
548 ) * rhs.inverse()
549 }; 'b);
550
551dual_quaternion_op_impl!(
552 Div, div;
553 (U4, U1), (U4, U1);
554 self: UnitQuaternion<T>, rhs: UnitDualQuaternion<T>,
555 Output = UnitDualQuaternion<T> => U3, U3;
556 #[allow(clippy::suspicious_arithmetic_impl)]
557 {
558 UnitDualQuaternion::<T>::new_unchecked(
559 DualQuaternion::from_real(self.into_inner())
560 ) * rhs.inverse()
561 };);
562
563dual_quaternion_op_impl!(
565 Mul, mul;
566 (U4, U1), (U3, U1);
567 self: &'a UnitDualQuaternion<T>, rhs: &'b Translation3<T>,
568 Output = UnitDualQuaternion<T> => U3, U1;
569 self * UnitDualQuaternion::<T>::from_parts(rhs.clone(), UnitQuaternion::identity());
570 'a, 'b);
571
572dual_quaternion_op_impl!(
573 Mul, mul;
574 (U4, U1), (U3, U3);
575 self: &'a UnitDualQuaternion<T>, rhs: Translation3<T>,
576 Output = UnitDualQuaternion<T> => U3, U1;
577 self * UnitDualQuaternion::<T>::from_parts(rhs, UnitQuaternion::identity());
578 'a);
579
580dual_quaternion_op_impl!(
581 Mul, mul;
582 (U4, U1), (U3, U3);
583 self: UnitDualQuaternion<T>, rhs: &'b Translation3<T>,
584 Output = UnitDualQuaternion<T> => U3, U1;
585 self * UnitDualQuaternion::<T>::from_parts(rhs.clone(), UnitQuaternion::identity());
586 'b);
587
588dual_quaternion_op_impl!(
589 Mul, mul;
590 (U4, U1), (U3, U3);
591 self: UnitDualQuaternion<T>, rhs: Translation3<T>,
592 Output = UnitDualQuaternion<T> => U3, U1;
593 self * UnitDualQuaternion::<T>::from_parts(rhs, UnitQuaternion::identity()); );
594
595dual_quaternion_op_impl!(
597 Div, div;
598 (U4, U1), (U3, U1);
599 self: &'a UnitDualQuaternion<T>, rhs: &'b Translation3<T>,
600 Output = UnitDualQuaternion<T> => U3, U1;
601 #[allow(clippy::suspicious_arithmetic_impl)]
602 { self * UnitDualQuaternion::<T>::from_parts(rhs.inverse(), UnitQuaternion::identity()) };
603 'a, 'b);
604
605dual_quaternion_op_impl!(
606 Div, div;
607 (U4, U1), (U3, U3);
608 self: &'a UnitDualQuaternion<T>, rhs: Translation3<T>,
609 Output = UnitDualQuaternion<T> => U3, U1;
610 #[allow(clippy::suspicious_arithmetic_impl)]
611 { self * UnitDualQuaternion::<T>::from_parts(rhs.inverse(), UnitQuaternion::identity()) };
612 'a);
613
614dual_quaternion_op_impl!(
615 Div, div;
616 (U4, U1), (U3, U3);
617 self: UnitDualQuaternion<T>, rhs: &'b Translation3<T>,
618 Output = UnitDualQuaternion<T> => U3, U1;
619 #[allow(clippy::suspicious_arithmetic_impl)]
620 { self * UnitDualQuaternion::<T>::from_parts(rhs.inverse(), UnitQuaternion::identity()) };
621 'b);
622
623dual_quaternion_op_impl!(
624 Div, div;
625 (U4, U1), (U3, U3);
626 self: UnitDualQuaternion<T>, rhs: Translation3<T>,
627 Output = UnitDualQuaternion<T> => U3, U1;
628 #[allow(clippy::suspicious_arithmetic_impl)]
629 { self * UnitDualQuaternion::<T>::from_parts(rhs.inverse(), UnitQuaternion::identity()) };);
630
631dual_quaternion_op_impl!(
633 Mul, mul;
634 (U3, U1), (U4, U1);
635 self: &'b Translation3<T>, rhs: &'a UnitDualQuaternion<T>,
636 Output = UnitDualQuaternion<T> => U3, U1;
637 UnitDualQuaternion::<T>::from_parts(self.clone(), UnitQuaternion::identity()) * rhs;
638 'a, 'b);
639
640dual_quaternion_op_impl!(
641 Mul, mul;
642 (U3, U1), (U4, U1);
643 self: &'a Translation3<T>, rhs: UnitDualQuaternion<T>,
644 Output = UnitDualQuaternion<T> => U3, U1;
645 UnitDualQuaternion::<T>::from_parts(self.clone(), UnitQuaternion::identity()) * rhs;
646 'a);
647
648dual_quaternion_op_impl!(
649 Mul, mul;
650 (U3, U1), (U4, U1);
651 self: Translation3<T>, rhs: &'b UnitDualQuaternion<T>,
652 Output = UnitDualQuaternion<T> => U3, U1;
653 UnitDualQuaternion::<T>::from_parts(self, UnitQuaternion::identity()) * rhs;
654 'b);
655
656dual_quaternion_op_impl!(
657 Mul, mul;
658 (U3, U1), (U4, U1);
659 self: Translation3<T>, rhs: UnitDualQuaternion<T>,
660 Output = UnitDualQuaternion<T> => U3, U1;
661 UnitDualQuaternion::<T>::from_parts(self, UnitQuaternion::identity()) * rhs;);
662
663dual_quaternion_op_impl!(
665 Div, div;
666 (U3, U1), (U4, U1);
667 self: &'b Translation3<T>, rhs: &'a UnitDualQuaternion<T>,
668 Output = UnitDualQuaternion<T> => U3, U1;
669 UnitDualQuaternion::<T>::from_parts(self.clone(), UnitQuaternion::identity()) / rhs;
670 'a, 'b);
671
672dual_quaternion_op_impl!(
673 Div, div;
674 (U3, U1), (U4, U1);
675 self: &'a Translation3<T>, rhs: UnitDualQuaternion<T>,
676 Output = UnitDualQuaternion<T> => U3, U1;
677 UnitDualQuaternion::<T>::from_parts(self.clone(), UnitQuaternion::identity()) / rhs;
678 'a);
679
680dual_quaternion_op_impl!(
681 Div, div;
682 (U3, U1), (U4, U1);
683 self: Translation3<T>, rhs: &'b UnitDualQuaternion<T>,
684 Output = UnitDualQuaternion<T> => U3, U1;
685 UnitDualQuaternion::<T>::from_parts(self, UnitQuaternion::identity()) / rhs;
686 'b);
687
688dual_quaternion_op_impl!(
689 Div, div;
690 (U3, U1), (U4, U1);
691 self: Translation3<T>, rhs: UnitDualQuaternion<T>,
692 Output = UnitDualQuaternion<T> => U3, U1;
693 UnitDualQuaternion::<T>::from_parts(self, UnitQuaternion::identity()) / rhs;);
694
695dual_quaternion_op_impl!(
697 Mul, mul;
698 (U4, U1), (U3, U1);
699 self: &'a UnitDualQuaternion<T>, rhs: &'b Isometry3<T>,
700 Output = UnitDualQuaternion<T> => U3, U1;
701 self * UnitDualQuaternion::<T>::from_isometry(rhs);
702 'a, 'b);
703
704dual_quaternion_op_impl!(
705 Mul, mul;
706 (U4, U1), (U3, U3);
707 self: &'a UnitDualQuaternion<T>, rhs: Isometry3<T>,
708 Output = UnitDualQuaternion<T> => U3, U1;
709 self * UnitDualQuaternion::<T>::from_isometry(&rhs);
710 'a);
711
712dual_quaternion_op_impl!(
713 Mul, mul;
714 (U4, U1), (U3, U3);
715 self: UnitDualQuaternion<T>, rhs: &'b Isometry3<T>,
716 Output = UnitDualQuaternion<T> => U3, U1;
717 self * UnitDualQuaternion::<T>::from_isometry(rhs);
718 'b);
719
720dual_quaternion_op_impl!(
721 Mul, mul;
722 (U4, U1), (U3, U3);
723 self: UnitDualQuaternion<T>, rhs: Isometry3<T>,
724 Output = UnitDualQuaternion<T> => U3, U1;
725 self * UnitDualQuaternion::<T>::from_isometry(&rhs); );
726
727dual_quaternion_op_impl!(
729 Div, div;
730 (U4, U1), (U3, U1);
731 self: &'a UnitDualQuaternion<T>, rhs: &'b Isometry3<T>,
732 Output = UnitDualQuaternion<T> => U3, U1;
733 self / UnitDualQuaternion::<T>::from_isometry(rhs);
735 'a, 'b);
736
737dual_quaternion_op_impl!(
738 Div, div;
739 (U4, U1), (U3, U3);
740 self: &'a UnitDualQuaternion<T>, rhs: Isometry3<T>,
741 Output = UnitDualQuaternion<T> => U3, U1;
742 self / UnitDualQuaternion::<T>::from_isometry(&rhs);
743 'a);
744
745dual_quaternion_op_impl!(
746 Div, div;
747 (U4, U1), (U3, U3);
748 self: UnitDualQuaternion<T>, rhs: &'b Isometry3<T>,
749 Output = UnitDualQuaternion<T> => U3, U1;
750 self / UnitDualQuaternion::<T>::from_isometry(rhs);
751 'b);
752
753dual_quaternion_op_impl!(
754 Div, div;
755 (U4, U1), (U3, U3);
756 self: UnitDualQuaternion<T>, rhs: Isometry3<T>,
757 Output = UnitDualQuaternion<T> => U3, U1;
758 self / UnitDualQuaternion::<T>::from_isometry(&rhs); );
759
760dual_quaternion_op_impl!(
762 Mul, mul;
763 (U3, U1), (U4, U1);
764 self: &'a Isometry3<T>, rhs: &'b UnitDualQuaternion<T>,
765 Output = UnitDualQuaternion<T> => U3, U1;
766 UnitDualQuaternion::<T>::from_isometry(self) * rhs;
767 'a, 'b);
768
769dual_quaternion_op_impl!(
770 Mul, mul;
771 (U3, U1), (U4, U1);
772 self: &'a Isometry3<T>, rhs: UnitDualQuaternion<T>,
773 Output = UnitDualQuaternion<T> => U3, U1;
774 UnitDualQuaternion::<T>::from_isometry(self) * rhs;
775 'a);
776
777dual_quaternion_op_impl!(
778 Mul, mul;
779 (U3, U1), (U4, U1);
780 self: Isometry3<T>, rhs: &'b UnitDualQuaternion<T>,
781 Output = UnitDualQuaternion<T> => U3, U1;
782 UnitDualQuaternion::<T>::from_isometry(&self) * rhs;
783 'b);
784
785dual_quaternion_op_impl!(
786 Mul, mul;
787 (U3, U1), (U4, U1);
788 self: Isometry3<T>, rhs: UnitDualQuaternion<T>,
789 Output = UnitDualQuaternion<T> => U3, U1;
790 UnitDualQuaternion::<T>::from_isometry(&self) * rhs; );
791
792dual_quaternion_op_impl!(
794 Div, div;
795 (U3, U1), (U4, U1);
796 self: &'a Isometry3<T>, rhs: &'b UnitDualQuaternion<T>,
797 Output = UnitDualQuaternion<T> => U3, U1;
798 UnitDualQuaternion::<T>::from_isometry(self) / rhs;
800 'a, 'b);
801
802dual_quaternion_op_impl!(
803 Div, div;
804 (U3, U1), (U4, U1);
805 self: &'a Isometry3<T>, rhs: UnitDualQuaternion<T>,
806 Output = UnitDualQuaternion<T> => U3, U1;
807 UnitDualQuaternion::<T>::from_isometry(self) / rhs;
808 'a);
809
810dual_quaternion_op_impl!(
811 Div, div;
812 (U3, U1), (U4, U1);
813 self: Isometry3<T>, rhs: &'b UnitDualQuaternion<T>,
814 Output = UnitDualQuaternion<T> => U3, U1;
815 UnitDualQuaternion::<T>::from_isometry(&self) / rhs;
816 'b);
817
818dual_quaternion_op_impl!(
819 Div, div;
820 (U3, U1), (U4, U1);
821 self: Isometry3<T>, rhs: UnitDualQuaternion<T>,
822 Output = UnitDualQuaternion<T> => U3, U1;
823 UnitDualQuaternion::<T>::from_isometry(&self) / rhs; );
824
825dual_quaternion_op_impl!(
827 Mul, mul;
828 (U4, U1), (U3, U1) for SB: Storage<T, U3> ;
829 self: &'a UnitDualQuaternion<T>, rhs: &'b Vector<T, U3, SB>,
830 Output = Vector3<T> => U3, U1;
831 Unit::new_unchecked(self.as_ref().real.clone()) * rhs;
832 'a, 'b);
833
834dual_quaternion_op_impl!(
835 Mul, mul;
836 (U4, U1), (U3, U1) for SB: Storage<T, U3> ;
837 self: &'a UnitDualQuaternion<T>, rhs: Vector<T, U3, SB>,
838 Output = Vector3<T> => U3, U1;
839 self * &rhs;
840 'a);
841
842dual_quaternion_op_impl!(
843 Mul, mul;
844 (U4, U1), (U3, U1) for SB: Storage<T, U3> ;
845 self: UnitDualQuaternion<T>, rhs: &'b Vector<T, U3, SB>,
846 Output = Vector3<T> => U3, U1;
847 &self * rhs;
848 'b);
849
850dual_quaternion_op_impl!(
851 Mul, mul;
852 (U4, U1), (U3, U1) for SB: Storage<T, U3> ;
853 self: UnitDualQuaternion<T>, rhs: Vector<T, U3, SB>,
854 Output = Vector3<T> => U3, U1;
855 &self * &rhs; );
856
857dual_quaternion_op_impl!(
859 Mul, mul;
860 (U4, U1), (U3, U1);
861 self: &'a UnitDualQuaternion<T>, rhs: &'b Point3<T>,
862 Output = Point3<T> => U3, U1;
863 {
864 let two: T = crate::convert(2.0f64);
865 let q_point = Quaternion::from_parts(T::zero(), rhs.coords.clone());
866 Point::from(
867 ((self.as_ref().real.clone() * q_point + self.as_ref().dual.clone() * two) * self.as_ref().real.clone().conjugate())
868 .vector()
869 .into_owned(),
870 )
871 };
872 'a, 'b);
873
874dual_quaternion_op_impl!(
875 Mul, mul;
876 (U4, U1), (U3, U1);
877 self: &'a UnitDualQuaternion<T>, rhs: Point3<T>,
878 Output = Point3<T> => U3, U1;
879 self * &rhs;
880 'a);
881
882dual_quaternion_op_impl!(
883 Mul, mul;
884 (U4, U1), (U3, U1);
885 self: UnitDualQuaternion<T>, rhs: &'b Point3<T>,
886 Output = Point3<T> => U3, U1;
887 &self * rhs;
888 'b);
889
890dual_quaternion_op_impl!(
891 Mul, mul;
892 (U4, U1), (U3, U1);
893 self: UnitDualQuaternion<T>, rhs: Point3<T>,
894 Output = Point3<T> => U3, U1;
895 &self * &rhs; );
896
897dual_quaternion_op_impl!(
899 Mul, mul;
900 (U4, U1), (U3, U1) for SB: Storage<T, U3> ;
901 self: &'a UnitDualQuaternion<T>, rhs: &'b Unit<Vector<T, U3, SB>>,
902 Output = Unit<Vector3<T>> => U3, U4;
903 Unit::new_unchecked(self * rhs.as_ref());
904 'a, 'b);
905
906dual_quaternion_op_impl!(
907 Mul, mul;
908 (U4, U1), (U3, U1) for SB: Storage<T, U3> ;
909 self: &'a UnitDualQuaternion<T>, rhs: Unit<Vector<T, U3, SB>>,
910 Output = Unit<Vector3<T>> => U3, U4;
911 Unit::new_unchecked(self * rhs.into_inner());
912 'a);
913
914dual_quaternion_op_impl!(
915 Mul, mul;
916 (U4, U1), (U3, U1) for SB: Storage<T, U3> ;
917 self: UnitDualQuaternion<T>, rhs: &'b Unit<Vector<T, U3, SB>>,
918 Output = Unit<Vector3<T>> => U3, U4;
919 Unit::new_unchecked(self * rhs.as_ref());
920 'b);
921
922dual_quaternion_op_impl!(
923 Mul, mul;
924 (U4, U1), (U3, U1) for SB: Storage<T, U3> ;
925 self: UnitDualQuaternion<T>, rhs: Unit<Vector<T, U3, SB>>,
926 Output = Unit<Vector3<T>> => U3, U4;
927 Unit::new_unchecked(self * rhs.into_inner()); );
928
929macro_rules! left_scalar_mul_impl(
930 ($($T: ty),* $(,)*) => {$(
931 impl Mul<DualQuaternion<$T>> for $T {
932 type Output = DualQuaternion<$T>;
933
934 #[inline]
935 fn mul(self, right: DualQuaternion<$T>) -> Self::Output {
936 DualQuaternion::from_real_and_dual(
937 self * right.real,
938 self * right.dual
939 )
940 }
941 }
942
943 impl<'b> Mul<&'b DualQuaternion<$T>> for $T {
944 type Output = DualQuaternion<$T>;
945
946 #[inline]
947 fn mul(self, right: &'b DualQuaternion<$T>) -> Self::Output {
948 DualQuaternion::from_real_and_dual(
949 self * &right.real,
950 self * &right.dual
951 )
952 }
953 }
954 )*}
955);
956
957left_scalar_mul_impl!(f32, f64);
958
959macro_rules! dual_quaternion_op_impl(
960 ($OpAssign: ident, $op_assign: ident;
961 ($LhsRDim: ident, $LhsCDim: ident), ($RhsRDim: ident, $RhsCDim: ident);
962 $lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty $(=> $VDimA: ty, $VDimB: ty)*;
963 $action: expr; $($lives: tt),*) => {
964 impl<$($lives ,)* T: SimdRealField> $OpAssign<$Rhs> for $Lhs
965 where T::Element: SimdRealField {
966
967 #[inline]
968 fn $op_assign(&mut $lhs, $rhs: $Rhs) {
969 $action
970 }
971 }
972 }
973);
974
975dual_quaternion_op_impl!(
977 AddAssign, add_assign;
978 (U4, U1), (U4, U1);
979 self: DualQuaternion<T>, rhs: &'b DualQuaternion<T>;
980 {
981 self.real += &rhs.real;
982 self.dual += &rhs.dual;
983 };
984 'b);
985
986dual_quaternion_op_impl!(
987 AddAssign, add_assign;
988 (U4, U1), (U4, U1);
989 self: DualQuaternion<T>, rhs: DualQuaternion<T>;
990 {
991 self.real += rhs.real;
992 self.dual += rhs.dual;
993 };);
994
995dual_quaternion_op_impl!(
997 SubAssign, sub_assign;
998 (U4, U1), (U4, U1);
999 self: DualQuaternion<T>, rhs: &'b DualQuaternion<T>;
1000 {
1001 self.real -= &rhs.real;
1002 self.dual -= &rhs.dual;
1003 };
1004 'b);
1005
1006dual_quaternion_op_impl!(
1007 SubAssign, sub_assign;
1008 (U4, U1), (U4, U1);
1009 self: DualQuaternion<T>, rhs: DualQuaternion<T>;
1010 {
1011 self.real -= rhs.real;
1012 self.dual -= rhs.dual;
1013 };);
1014
1015dual_quaternion_op_impl!(
1017 MulAssign, mul_assign;
1018 (U4, U1), (U4, U1);
1019 self: DualQuaternion<T>, rhs: &'b DualQuaternion<T>;
1020 {
1021 let res = &*self * rhs;
1022 self.real.coords.copy_from(&res.real.coords);
1023 self.dual.coords.copy_from(&res.dual.coords);
1024 };
1025 'b);
1026
1027dual_quaternion_op_impl!(
1028 MulAssign, mul_assign;
1029 (U4, U1), (U4, U1);
1030 self: DualQuaternion<T>, rhs: DualQuaternion<T>;
1031 *self *= &rhs;);
1032
1033dual_quaternion_op_impl!(
1035 MulAssign, mul_assign;
1036 (U4, U1), (U4, U1);
1037 self: DualQuaternion<T>, rhs: &'b UnitDualQuaternion<T>;
1038 {
1039 let res = &*self * rhs;
1040 self.real.coords.copy_from(&res.real.coords);
1041 self.dual.coords.copy_from(&res.dual.coords);
1042 };
1043 'b);
1044
1045dual_quaternion_op_impl!(
1046 MulAssign, mul_assign;
1047 (U4, U1), (U4, U1);
1048 self: DualQuaternion<T>, rhs: UnitDualQuaternion<T>;
1049 *self *= &rhs; );
1050
1051dual_quaternion_op_impl!(
1053 DivAssign, div_assign;
1054 (U4, U1), (U4, U1);
1055 self: DualQuaternion<T>, rhs: &'b UnitDualQuaternion<T>;
1056 {
1057 let res = &*self / rhs;
1058 self.real.coords.copy_from(&res.real.coords);
1059 self.dual.coords.copy_from(&res.dual.coords);
1060 };
1061 'b);
1062
1063dual_quaternion_op_impl!(
1064 DivAssign, div_assign;
1065 (U4, U1), (U4, U1);
1066 self: DualQuaternion<T>, rhs: UnitDualQuaternion<T>;
1067 *self /= &rhs; );
1068
1069dual_quaternion_op_impl!(
1071 MulAssign, mul_assign;
1072 (U4, U1), (U4, U1);
1073 self: UnitDualQuaternion<T>, rhs: &'b UnitDualQuaternion<T>;
1074 {
1075 let res = &*self * rhs;
1076 self.as_mut_unchecked().real.coords.copy_from(&res.as_ref().real.coords);
1077 self.as_mut_unchecked().dual.coords.copy_from(&res.as_ref().dual.coords);
1078 };
1079 'b);
1080
1081dual_quaternion_op_impl!(
1082 MulAssign, mul_assign;
1083 (U4, U1), (U4, U1);
1084 self: UnitDualQuaternion<T>, rhs: UnitDualQuaternion<T>;
1085 *self *= &rhs; );
1086
1087dual_quaternion_op_impl!(
1089 DivAssign, div_assign;
1090 (U4, U1), (U4, U1);
1091 self: UnitDualQuaternion<T>, rhs: &'b UnitDualQuaternion<T>;
1092 {
1093 let res = &*self / rhs;
1094 self.as_mut_unchecked().real.coords.copy_from(&res.as_ref().real.coords);
1095 self.as_mut_unchecked().dual.coords.copy_from(&res.as_ref().dual.coords);
1096 };
1097 'b);
1098
1099dual_quaternion_op_impl!(
1100 DivAssign, div_assign;
1101 (U4, U1), (U4, U1);
1102 self: UnitDualQuaternion<T>, rhs: UnitDualQuaternion<T>;
1103 *self /= &rhs; );
1104
1105dual_quaternion_op_impl!(
1107 MulAssign, mul_assign;
1108 (U4, U1), (U4, U1);
1109 self: UnitDualQuaternion<T>, rhs: UnitQuaternion<T>;
1110 {
1111 let res = &*self * UnitDualQuaternion::from_rotation(rhs);
1112 self.as_mut_unchecked().real.coords.copy_from(&res.as_ref().real.coords);
1113 self.as_mut_unchecked().dual.coords.copy_from(&res.as_ref().dual.coords);
1114 };);
1115
1116dual_quaternion_op_impl!(
1117 MulAssign, mul_assign;
1118 (U4, U1), (U4, U1);
1119 self: UnitDualQuaternion<T>, rhs: &'b UnitQuaternion<T>;
1120 *self *= rhs.clone(); 'b);
1121
1122dual_quaternion_op_impl!(
1124 DivAssign, div_assign;
1125 (U4, U1), (U4, U1);
1126 self: UnitDualQuaternion<T>, rhs: &'b UnitQuaternion<T>;
1127 #[allow(clippy::suspicious_op_assign_impl)]
1128 {
1129 let res = &*self * UnitDualQuaternion::from_rotation(rhs.inverse());
1130 self.as_mut_unchecked().real.coords.copy_from(&res.as_ref().real.coords);
1131 self.as_mut_unchecked().dual.coords.copy_from(&res.as_ref().dual.coords);
1132 };
1133 'b);
1134
1135dual_quaternion_op_impl!(
1136 DivAssign, div_assign;
1137 (U4, U1), (U4, U1);
1138 self: UnitDualQuaternion<T>, rhs: UnitQuaternion<T>;
1139 *self /= &rhs; );
1140
1141dual_quaternion_op_impl!(
1143 MulAssign, mul_assign;
1144 (U4, U1), (U4, U1);
1145 self: UnitDualQuaternion<T>, rhs: Translation3<T>;
1146 {
1147 let res = &*self * UnitDualQuaternion::from_parts(rhs, UnitQuaternion::identity());
1148 self.as_mut_unchecked().real.coords.copy_from(&res.as_ref().real.coords);
1149 self.as_mut_unchecked().dual.coords.copy_from(&res.as_ref().dual.coords);
1150 };);
1151
1152dual_quaternion_op_impl!(
1153 MulAssign, mul_assign;
1154 (U4, U1), (U4, U1);
1155 self: UnitDualQuaternion<T>, rhs: &'b Translation3<T>;
1156 *self *= rhs.clone(); 'b);
1157
1158dual_quaternion_op_impl!(
1160 DivAssign, div_assign;
1161 (U4, U1), (U4, U1);
1162 self: UnitDualQuaternion<T>, rhs: &'b Translation3<T>;
1163 #[allow(clippy::suspicious_op_assign_impl)]
1164 {
1165 let res = &*self * UnitDualQuaternion::from_parts(rhs.inverse(), UnitQuaternion::identity());
1166 self.as_mut_unchecked().real.coords.copy_from(&res.as_ref().real.coords);
1167 self.as_mut_unchecked().dual.coords.copy_from(&res.as_ref().dual.coords);
1168 };
1169 'b);
1170
1171dual_quaternion_op_impl!(
1172 DivAssign, div_assign;
1173 (U4, U1), (U4, U1);
1174 self: UnitDualQuaternion<T>, rhs: Translation3<T>;
1175 *self /= &rhs; );
1176
1177dual_quaternion_op_impl!(
1179 MulAssign, mul_assign;
1180 (U4, U1), (U3, U1);
1181 self: UnitDualQuaternion<T>, rhs: &'b Isometry3<T> => U3, U1;
1182 {
1183 let res = &*self * rhs;
1184 self.as_mut_unchecked().real.coords.copy_from(&res.as_ref().real.coords);
1185 self.as_mut_unchecked().dual.coords.copy_from(&res.as_ref().dual.coords);
1186 };
1187 'b);
1188
1189dual_quaternion_op_impl!(
1190 MulAssign, mul_assign;
1191 (U4, U1), (U3, U1);
1192 self: UnitDualQuaternion<T>, rhs: Isometry3<T> => U3, U1;
1193 *self *= &rhs; );
1194
1195dual_quaternion_op_impl!(
1197 DivAssign, div_assign;
1198 (U4, U1), (U3, U1);
1199 self: UnitDualQuaternion<T>, rhs: &'b Isometry3<T> => U3, U1;
1200 {
1201 let res = &*self / rhs;
1202 self.as_mut_unchecked().real.coords.copy_from(&res.as_ref().real.coords);
1203 self.as_mut_unchecked().dual.coords.copy_from(&res.as_ref().dual.coords);
1204 };
1205 'b);
1206
1207dual_quaternion_op_impl!(
1208 DivAssign, div_assign;
1209 (U4, U1), (U3, U1);
1210 self: UnitDualQuaternion<T>, rhs: Isometry3<T> => U3, U1;
1211 *self /= &rhs; );
1212
1213macro_rules! scalar_op_impl(
1214 ($($Op: ident, $op: ident, $OpAssign: ident, $op_assign: ident);* $(;)*) => {$(
1215 impl<T: SimdRealField> $Op<T> for DualQuaternion<T>
1216 where T::Element: SimdRealField {
1217 type Output = DualQuaternion<T>;
1218
1219 #[inline]
1220 fn $op(self, n: T) -> Self::Output {
1221 DualQuaternion::from_real_and_dual(
1222 self.real.clone().$op(n.clone()),
1223 self.dual.clone().$op(n)
1224 )
1225 }
1226 }
1227
1228 impl<'a, T: SimdRealField> $Op<T> for &'a DualQuaternion<T>
1229 where T::Element: SimdRealField {
1230 type Output = DualQuaternion<T>;
1231
1232 #[inline]
1233 fn $op(self, n: T) -> Self::Output {
1234 DualQuaternion::from_real_and_dual(
1235 self.real.clone().$op(n.clone()),
1236 self.dual.clone().$op(n)
1237 )
1238 }
1239 }
1240
1241 impl<T: SimdRealField> $OpAssign<T> for DualQuaternion<T>
1242 where T::Element: SimdRealField {
1243
1244 #[inline]
1245 fn $op_assign(&mut self, n: T) {
1246 self.real.$op_assign(n.clone());
1247 self.dual.$op_assign(n);
1248 }
1249 }
1250 )*}
1251);
1252
1253scalar_op_impl!(
1254 Mul, mul, MulAssign, mul_assign;
1255 Div, div, DivAssign, div_assign;
1256);