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