1 // The macros break if the references are taken out, for some reason.
2 #![allow(clippy::op_ref)]
3 
4 use std::ops::{Div, DivAssign, Mul, MulAssign};
5 
6 use crate::base::storage::Storage;
7 use crate::base::{Const, Unit, Vector, Vector2};
8 use crate::geometry::{Isometry, Point2, Rotation, Similarity, Translation, UnitComplex};
9 use simba::simd::SimdRealField;
10 
11 /*
12  * This file provides:
13  * ===================
14  *
15  * UnitComplex  × UnitComplex
16  * UnitComplex  × Rotation -> UnitComplex
17  * Rotation × UnitComplex  -> UnitComplex
18  *
19  * UnitComplex  ÷ UnitComplex
20  * UnitComplex  ÷ Rotation -> UnitComplex
21  * Rotation ÷ UnitComplex  -> UnitComplex
22  *
23  *
24  * UnitComplex × Point
25  * UnitComplex × Vector
26  * UnitComplex × Unit<T>
27  *
28  * UnitComplex × Isometry<UnitComplex>
29  * UnitComplex × Similarity<UnitComplex>
30  * UnitComplex × Translation -> Isometry<UnitComplex>
31  *
32  * (Assignment Operators)
33  *
34  * UnitComplex  ×= UnitComplex
35  * UnitComplex  ×= Rotation
36  *
37  * UnitComplex  ÷= UnitComplex
38  * UnitComplex  ÷= Rotation
39  *
40  * Rotation ×= UnitComplex
41  * Rotation ÷= UnitComplex
42  *
43  */
44 
45 // UnitComplex × UnitComplex
46 impl<T: SimdRealField> Mul<Self> for UnitComplex<T> {
47     type Output = Self;
48 
49     #[inline]
mul(self, rhs: Self) -> Self50     fn mul(self, rhs: Self) -> Self {
51         Unit::new_unchecked(self.into_inner() * rhs.into_inner())
52     }
53 }
54 
55 impl<'a, T: SimdRealField> Mul<UnitComplex<T>> for &'a UnitComplex<T>
56 where
57     T::Element: SimdRealField,
58 {
59     type Output = UnitComplex<T>;
60 
61     #[inline]
mul(self, rhs: UnitComplex<T>) -> Self::Output62     fn mul(self, rhs: UnitComplex<T>) -> Self::Output {
63         Unit::new_unchecked(self.complex() * rhs.into_inner())
64     }
65 }
66 
67 impl<'b, T: SimdRealField> Mul<&'b UnitComplex<T>> for UnitComplex<T>
68 where
69     T::Element: SimdRealField,
70 {
71     type Output = Self;
72 
73     #[inline]
mul(self, rhs: &'b UnitComplex<T>) -> Self::Output74     fn mul(self, rhs: &'b UnitComplex<T>) -> Self::Output {
75         Unit::new_unchecked(self.into_inner() * rhs.as_ref())
76     }
77 }
78 
79 impl<'a, 'b, T: SimdRealField> Mul<&'b UnitComplex<T>> for &'a UnitComplex<T>
80 where
81     T::Element: SimdRealField,
82 {
83     type Output = UnitComplex<T>;
84 
85     #[inline]
mul(self, rhs: &'b UnitComplex<T>) -> Self::Output86     fn mul(self, rhs: &'b UnitComplex<T>) -> Self::Output {
87         Unit::new_unchecked(self.complex() * rhs.as_ref())
88     }
89 }
90 
91 // UnitComplex ÷ UnitComplex
92 impl<T: SimdRealField> Div<Self> for UnitComplex<T>
93 where
94     T::Element: SimdRealField,
95 {
96     type Output = Self;
97 
98     #[inline]
div(self, rhs: Self) -> Self::Output99     fn div(self, rhs: Self) -> Self::Output {
100         #[allow(clippy::suspicious_arithmetic_impl)]
101         Unit::new_unchecked(self.into_inner() * rhs.conjugate().into_inner())
102     }
103 }
104 
105 impl<'a, T: SimdRealField> Div<UnitComplex<T>> for &'a UnitComplex<T>
106 where
107     T::Element: SimdRealField,
108 {
109     type Output = UnitComplex<T>;
110 
111     #[inline]
div(self, rhs: UnitComplex<T>) -> Self::Output112     fn div(self, rhs: UnitComplex<T>) -> Self::Output {
113         #[allow(clippy::suspicious_arithmetic_impl)]
114         Unit::new_unchecked(self.complex() * rhs.conjugate().into_inner())
115     }
116 }
117 
118 impl<'b, T: SimdRealField> Div<&'b UnitComplex<T>> for UnitComplex<T>
119 where
120     T::Element: SimdRealField,
121 {
122     type Output = Self;
123 
124     #[inline]
div(self, rhs: &'b UnitComplex<T>) -> Self::Output125     fn div(self, rhs: &'b UnitComplex<T>) -> Self::Output {
126         #[allow(clippy::suspicious_arithmetic_impl)]
127         Unit::new_unchecked(self.into_inner() * rhs.conjugate().into_inner())
128     }
129 }
130 
131 impl<'a, 'b, T: SimdRealField> Div<&'b UnitComplex<T>> for &'a UnitComplex<T>
132 where
133     T::Element: SimdRealField,
134 {
135     type Output = UnitComplex<T>;
136 
137     #[inline]
div(self, rhs: &'b UnitComplex<T>) -> Self::Output138     fn div(self, rhs: &'b UnitComplex<T>) -> Self::Output {
139         #[allow(clippy::suspicious_arithmetic_impl)]
140         Unit::new_unchecked(self.complex() * rhs.conjugate().into_inner())
141     }
142 }
143 
144 macro_rules! complex_op_impl(
145     ($Op: ident, $op: ident;
146      $($Storage: ident: $StoragesBound: ident $(<$($BoundParam: ty),*>)*),*;
147      $lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty, Output = $Result: ty;
148      $action: expr; $($lives: tt),*) => {
149         impl<$($lives ,)* T: SimdRealField $(, $Storage: $StoragesBound $(<$($BoundParam),*>)*)*> $Op<$Rhs> for $Lhs
150             where T::Element: SimdRealField {
151             type Output = $Result;
152 
153             #[inline]
154             fn $op($lhs, $rhs: $Rhs) -> Self::Output {
155                 $action
156             }
157         }
158     }
159 );
160 
161 macro_rules! complex_op_impl_all(
162     ($Op: ident, $op: ident;
163      $($Storage: ident: $StoragesBound: ident $(<$($BoundParam: ty),*>)*),*;
164      $lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty, Output = $Result: ty;
165      [val val] => $action_val_val: expr;
166      [ref val] => $action_ref_val: expr;
167      [val ref] => $action_val_ref: expr;
168      [ref ref] => $action_ref_ref: expr;) => {
169 
170     complex_op_impl!($Op, $op;
171                      $($Storage: $StoragesBound $(<$($BoundParam),*>)*),*;
172                      $lhs: $Lhs, $rhs: $Rhs, Output = $Result;
173                      $action_val_val; );
174 
175     complex_op_impl!($Op, $op;
176                      $($Storage: $StoragesBound $(<$($BoundParam),*>)*),*;
177                      $lhs: &'a $Lhs, $rhs: $Rhs, Output = $Result;
178                      $action_ref_val; 'a);
179 
180     complex_op_impl!($Op, $op;
181                      $($Storage: $StoragesBound $(<$($BoundParam),*>)*),*;
182                      $lhs: $Lhs, $rhs: &'b $Rhs, Output = $Result;
183                      $action_val_ref; 'b);
184 
185     complex_op_impl!($Op, $op;
186                      $($Storage: $StoragesBound $(<$($BoundParam),*>)*),*;
187                      $lhs: &'a $Lhs, $rhs: &'b $Rhs, Output = $Result;
188                      $action_ref_ref; 'a, 'b);
189 
190 
191     }
192 );
193 
194 // UnitComplex × Rotation
195 complex_op_impl_all!(
196     Mul, mul;
197     ;
198     self: UnitComplex<T>, rhs: Rotation<T, 2>, Output = UnitComplex<T>;
199     [val val] => &self * &rhs;
200     [ref val] =>  self * &rhs;
201     [val ref] => &self *  rhs;
202     [ref ref] =>  self * UnitComplex::from_rotation_matrix(rhs);
203 );
204 
205 // UnitComplex ÷ Rotation
206 complex_op_impl_all!(
207     Div, div;
208     ;
209     self: UnitComplex<T>, rhs: Rotation<T, 2>, Output = UnitComplex<T>;
210     [val val] => &self / &rhs;
211     [ref val] =>  self / &rhs;
212     [val ref] => &self /  rhs;
213     [ref ref] => #[allow(clippy::suspicious_arithmetic_impl)] { self * UnitComplex::from_rotation_matrix(rhs).inverse() };
214 );
215 
216 // Rotation × UnitComplex
217 complex_op_impl_all!(
218     Mul, mul;
219     ;
220     self: Rotation<T, 2>, rhs: UnitComplex<T>, Output = UnitComplex<T>;
221     [val val] => &self * &rhs;
222     [ref val] =>  self * &rhs;
223     [val ref] => &self *  rhs;
224     [ref ref] => UnitComplex::from_rotation_matrix(self) * rhs;
225 );
226 
227 // Rotation ÷ UnitComplex
228 complex_op_impl_all!(
229     Div, div;
230     ;
231     self: Rotation<T, 2>, rhs: UnitComplex<T>, Output = UnitComplex<T>;
232     [val val] => &self / &rhs;
233     [ref val] =>  self / &rhs;
234     [val ref] => &self /  rhs;
235     [ref ref] => #[allow(clippy::suspicious_arithmetic_impl)] { UnitComplex::from_rotation_matrix(self) * rhs.inverse() };
236 );
237 
238 // UnitComplex × Point
239 complex_op_impl_all!(
240     Mul, mul;
241     ;
242     self: UnitComplex<T>, rhs: Point2<T>, Output = Point2<T>;
243     [val val] => &self * &rhs;
244     [ref val] =>  self * &rhs;
245     [val ref] => &self *  rhs;
246     [ref ref] => Point2::from(self * &rhs.coords);
247 );
248 
249 // UnitComplex × Vector
250 complex_op_impl_all!(
251     Mul, mul;
252     S: Storage<T, Const<2>>;
253     self: UnitComplex<T>, rhs: Vector<T, Const<2>, S>, Output = Vector2<T>;
254     [val val] => &self * &rhs;
255     [ref val] =>  self * &rhs;
256     [val ref] => &self *  rhs;
257     [ref ref] => {
258         let i = self.as_ref().im.clone();
259         let r = self.as_ref().re.clone();
260         Vector2::new(r.clone() * rhs[0].clone() - i.clone() * rhs[1].clone(), i * rhs[0].clone() + r * rhs[1].clone())
261     };
262 );
263 
264 // UnitComplex × Unit<Vector>
265 complex_op_impl_all!(
266     Mul, mul;
267     S: Storage<T, Const<2>>;
268     self: UnitComplex<T>, rhs: Unit<Vector<T, Const<2>, S>>, Output = Unit<Vector2<T>>;
269     [val val] => &self * &rhs;
270     [ref val] =>  self * &rhs;
271     [val ref] => &self *  rhs;
272     [ref ref] => Unit::new_unchecked(self * rhs.as_ref());
273 );
274 
275 // UnitComplex × Isometry<UnitComplex>
276 complex_op_impl_all!(
277     Mul, mul;
278     ;
279     self: UnitComplex<T>, rhs: Isometry<T, UnitComplex<T>, 2>,
280     Output = Isometry<T, UnitComplex<T>, 2>;
281     [val val] => &self * &rhs;
282     [ref val] =>  self * &rhs;
283     [val ref] => &self *  rhs;
284     [ref ref] => {
285         let shift = self * &rhs.translation.vector;
286         Isometry::from_parts(Translation::from(shift), self * &rhs.rotation)
287     };
288 );
289 
290 // UnitComplex × Similarity<UnitComplex>
291 complex_op_impl_all!(
292     Mul, mul;
293     ;
294     self: UnitComplex<T>, rhs: Similarity<T, UnitComplex<T>, 2>,
295     Output = Similarity<T, UnitComplex<T>, 2>;
296     [val val] => &self * &rhs;
297     [ref val] =>  self * &rhs;
298     [val ref] => &self *  rhs;
299     [ref ref] => Similarity::from_isometry(self * &rhs.isometry, rhs.scaling());
300 );
301 
302 // UnitComplex × Translation
303 complex_op_impl_all!(
304     Mul, mul;
305     ;
306     self: UnitComplex<T>, rhs: Translation<T, 2>,
307     Output = Isometry<T, UnitComplex<T>, 2>;
308     [val val] => Isometry::from_parts(Translation::from(&self *  rhs.vector), self);
309     [ref val] => Isometry::from_parts(Translation::from( self *  rhs.vector), self.clone());
310     [val ref] => Isometry::from_parts(Translation::from(&self * &rhs.vector), self);
311     [ref ref] => Isometry::from_parts(Translation::from( self * &rhs.vector), self.clone());
312 );
313 
314 // Translation × UnitComplex
315 complex_op_impl_all!(
316     Mul, mul;
317     ;
318     self: Translation<T, 2>, right: UnitComplex<T>,
319     Output = Isometry<T, UnitComplex<T>, 2>;
320     [val val] => Isometry::from_parts(self,   right);
321     [ref val] => Isometry::from_parts(self.clone(),  right);
322     [val ref] => Isometry::from_parts(self,  right.clone());
323     [ref ref] => Isometry::from_parts(self.clone(), right.clone());
324 );
325 
326 // UnitComplex ×= UnitComplex
327 impl<T: SimdRealField> MulAssign<UnitComplex<T>> for UnitComplex<T>
328 where
329     T::Element: SimdRealField,
330 {
331     #[inline]
mul_assign(&mut self, rhs: UnitComplex<T>)332     fn mul_assign(&mut self, rhs: UnitComplex<T>) {
333         *self = self.clone() * rhs
334     }
335 }
336 
337 impl<'b, T: SimdRealField> MulAssign<&'b UnitComplex<T>> for UnitComplex<T>
338 where
339     T::Element: SimdRealField,
340 {
341     #[inline]
mul_assign(&mut self, rhs: &'b UnitComplex<T>)342     fn mul_assign(&mut self, rhs: &'b UnitComplex<T>) {
343         *self = self.clone() * rhs
344     }
345 }
346 
347 // UnitComplex /= UnitComplex
348 impl<T: SimdRealField> DivAssign<UnitComplex<T>> for UnitComplex<T>
349 where
350     T::Element: SimdRealField,
351 {
352     #[inline]
div_assign(&mut self, rhs: UnitComplex<T>)353     fn div_assign(&mut self, rhs: UnitComplex<T>) {
354         *self = self.clone() / rhs
355     }
356 }
357 
358 impl<'b, T: SimdRealField> DivAssign<&'b UnitComplex<T>> for UnitComplex<T>
359 where
360     T::Element: SimdRealField,
361 {
362     #[inline]
div_assign(&mut self, rhs: &'b UnitComplex<T>)363     fn div_assign(&mut self, rhs: &'b UnitComplex<T>) {
364         *self = self.clone() / rhs
365     }
366 }
367 
368 // UnitComplex ×= Rotation
369 impl<T: SimdRealField> MulAssign<Rotation<T, 2>> for UnitComplex<T>
370 where
371     T::Element: SimdRealField,
372 {
373     #[inline]
mul_assign(&mut self, rhs: Rotation<T, 2>)374     fn mul_assign(&mut self, rhs: Rotation<T, 2>) {
375         *self = self.clone() * rhs
376     }
377 }
378 
379 impl<'b, T: SimdRealField> MulAssign<&'b Rotation<T, 2>> for UnitComplex<T>
380 where
381     T::Element: SimdRealField,
382 {
383     #[inline]
mul_assign(&mut self, rhs: &'b Rotation<T, 2>)384     fn mul_assign(&mut self, rhs: &'b Rotation<T, 2>) {
385         *self = self.clone() * rhs
386     }
387 }
388 
389 // UnitComplex ÷= Rotation
390 impl<T: SimdRealField> DivAssign<Rotation<T, 2>> for UnitComplex<T>
391 where
392     T::Element: SimdRealField,
393 {
394     #[inline]
div_assign(&mut self, rhs: Rotation<T, 2>)395     fn div_assign(&mut self, rhs: Rotation<T, 2>) {
396         *self = self.clone() / rhs
397     }
398 }
399 
400 impl<'b, T: SimdRealField> DivAssign<&'b Rotation<T, 2>> for UnitComplex<T>
401 where
402     T::Element: SimdRealField,
403 {
404     #[inline]
div_assign(&mut self, rhs: &'b Rotation<T, 2>)405     fn div_assign(&mut self, rhs: &'b Rotation<T, 2>) {
406         *self = self.clone() / rhs
407     }
408 }
409 
410 // Rotation ×= UnitComplex
411 impl<T: SimdRealField> MulAssign<UnitComplex<T>> for Rotation<T, 2>
412 where
413     T::Element: SimdRealField,
414 {
415     #[inline]
mul_assign(&mut self, rhs: UnitComplex<T>)416     fn mul_assign(&mut self, rhs: UnitComplex<T>) {
417         self.mul_assign(rhs.to_rotation_matrix())
418     }
419 }
420 
421 impl<'b, T: SimdRealField> MulAssign<&'b UnitComplex<T>> for Rotation<T, 2>
422 where
423     T::Element: SimdRealField,
424 {
425     #[inline]
mul_assign(&mut self, rhs: &'b UnitComplex<T>)426     fn mul_assign(&mut self, rhs: &'b UnitComplex<T>) {
427         self.mul_assign(rhs.clone().to_rotation_matrix())
428     }
429 }
430 
431 // Rotation ÷= UnitComplex
432 impl<T: SimdRealField> DivAssign<UnitComplex<T>> for Rotation<T, 2>
433 where
434     T::Element: SimdRealField,
435 {
436     #[inline]
div_assign(&mut self, rhs: UnitComplex<T>)437     fn div_assign(&mut self, rhs: UnitComplex<T>) {
438         self.div_assign(rhs.to_rotation_matrix())
439     }
440 }
441 
442 impl<'b, T: SimdRealField> DivAssign<&'b UnitComplex<T>> for Rotation<T, 2>
443 where
444     T::Element: SimdRealField,
445 {
446     #[inline]
div_assign(&mut self, rhs: &'b UnitComplex<T>)447     fn div_assign(&mut self, rhs: &'b UnitComplex<T>) {
448         self.div_assign(rhs.clone().to_rotation_matrix())
449     }
450 }
451