nalgebra/geometry/
unit_complex_ops.rs

1// The macros break if the references are taken out, for some reason.
2#![allow(clippy::op_ref)]
3
4use std::ops::{Div, DivAssign, Mul, MulAssign};
5
6use crate::base::storage::Storage;
7use crate::base::{Const, Unit, Vector, Vector2};
8use crate::geometry::{Isometry, Point2, Rotation, Similarity, Translation, UnitComplex};
9use 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
46impl<T: SimdRealField> Mul<Self> for UnitComplex<T> {
47    type Output = Self;
48
49    #[inline]
50    fn mul(self, rhs: Self) -> Self {
51        Unit::new_unchecked(self.into_inner() * rhs.into_inner())
52    }
53}
54
55impl<'a, T: SimdRealField> Mul<UnitComplex<T>> for &'a UnitComplex<T>
56where
57    T::Element: SimdRealField,
58{
59    type Output = UnitComplex<T>;
60
61    #[inline]
62    fn mul(self, rhs: UnitComplex<T>) -> Self::Output {
63        Unit::new_unchecked(self.complex() * rhs.into_inner())
64    }
65}
66
67impl<'b, T: SimdRealField> Mul<&'b UnitComplex<T>> for UnitComplex<T>
68where
69    T::Element: SimdRealField,
70{
71    type Output = Self;
72
73    #[inline]
74    fn mul(self, rhs: &'b UnitComplex<T>) -> Self::Output {
75        Unit::new_unchecked(self.into_inner() * rhs.as_ref())
76    }
77}
78
79impl<'a, 'b, T: SimdRealField> Mul<&'b UnitComplex<T>> for &'a UnitComplex<T>
80where
81    T::Element: SimdRealField,
82{
83    type Output = UnitComplex<T>;
84
85    #[inline]
86    fn mul(self, rhs: &'b UnitComplex<T>) -> Self::Output {
87        Unit::new_unchecked(self.complex() * rhs.as_ref())
88    }
89}
90
91// UnitComplex ÷ UnitComplex
92impl<T: SimdRealField> Div<Self> for UnitComplex<T>
93where
94    T::Element: SimdRealField,
95{
96    type Output = Self;
97
98    #[inline]
99    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
105impl<'a, T: SimdRealField> Div<UnitComplex<T>> for &'a UnitComplex<T>
106where
107    T::Element: SimdRealField,
108{
109    type Output = UnitComplex<T>;
110
111    #[inline]
112    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
118impl<'b, T: SimdRealField> Div<&'b UnitComplex<T>> for UnitComplex<T>
119where
120    T::Element: SimdRealField,
121{
122    type Output = Self;
123
124    #[inline]
125    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
131impl<'a, 'b, T: SimdRealField> Div<&'b UnitComplex<T>> for &'a UnitComplex<T>
132where
133    T::Element: SimdRealField,
134{
135    type Output = UnitComplex<T>;
136
137    #[inline]
138    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
144macro_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
161macro_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
195complex_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
206complex_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
217complex_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
228complex_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
239complex_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
250complex_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>
265complex_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>
276complex_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>
291complex_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
303complex_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
315complex_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
327impl<T: SimdRealField> MulAssign<UnitComplex<T>> for UnitComplex<T>
328where
329    T::Element: SimdRealField,
330{
331    #[inline]
332    fn mul_assign(&mut self, rhs: UnitComplex<T>) {
333        *self = self.clone() * rhs
334    }
335}
336
337impl<'b, T: SimdRealField> MulAssign<&'b UnitComplex<T>> for UnitComplex<T>
338where
339    T::Element: SimdRealField,
340{
341    #[inline]
342    fn mul_assign(&mut self, rhs: &'b UnitComplex<T>) {
343        *self = self.clone() * rhs
344    }
345}
346
347// UnitComplex /= UnitComplex
348impl<T: SimdRealField> DivAssign<UnitComplex<T>> for UnitComplex<T>
349where
350    T::Element: SimdRealField,
351{
352    #[inline]
353    fn div_assign(&mut self, rhs: UnitComplex<T>) {
354        *self = self.clone() / rhs
355    }
356}
357
358impl<'b, T: SimdRealField> DivAssign<&'b UnitComplex<T>> for UnitComplex<T>
359where
360    T::Element: SimdRealField,
361{
362    #[inline]
363    fn div_assign(&mut self, rhs: &'b UnitComplex<T>) {
364        *self = self.clone() / rhs
365    }
366}
367
368// UnitComplex ×= Rotation
369impl<T: SimdRealField> MulAssign<Rotation<T, 2>> for UnitComplex<T>
370where
371    T::Element: SimdRealField,
372{
373    #[inline]
374    fn mul_assign(&mut self, rhs: Rotation<T, 2>) {
375        *self = self.clone() * rhs
376    }
377}
378
379impl<'b, T: SimdRealField> MulAssign<&'b Rotation<T, 2>> for UnitComplex<T>
380where
381    T::Element: SimdRealField,
382{
383    #[inline]
384    fn mul_assign(&mut self, rhs: &'b Rotation<T, 2>) {
385        *self = self.clone() * rhs
386    }
387}
388
389// UnitComplex ÷= Rotation
390impl<T: SimdRealField> DivAssign<Rotation<T, 2>> for UnitComplex<T>
391where
392    T::Element: SimdRealField,
393{
394    #[inline]
395    fn div_assign(&mut self, rhs: Rotation<T, 2>) {
396        *self = self.clone() / rhs
397    }
398}
399
400impl<'b, T: SimdRealField> DivAssign<&'b Rotation<T, 2>> for UnitComplex<T>
401where
402    T::Element: SimdRealField,
403{
404    #[inline]
405    fn div_assign(&mut self, rhs: &'b Rotation<T, 2>) {
406        *self = self.clone() / rhs
407    }
408}
409
410// Rotation ×= UnitComplex
411impl<T: SimdRealField> MulAssign<UnitComplex<T>> for Rotation<T, 2>
412where
413    T::Element: SimdRealField,
414{
415    #[inline]
416    fn mul_assign(&mut self, rhs: UnitComplex<T>) {
417        self.mul_assign(rhs.to_rotation_matrix())
418    }
419}
420
421impl<'b, T: SimdRealField> MulAssign<&'b UnitComplex<T>> for Rotation<T, 2>
422where
423    T::Element: SimdRealField,
424{
425    #[inline]
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
432impl<T: SimdRealField> DivAssign<UnitComplex<T>> for Rotation<T, 2>
433where
434    T::Element: SimdRealField,
435{
436    #[inline]
437    fn div_assign(&mut self, rhs: UnitComplex<T>) {
438        self.div_assign(rhs.to_rotation_matrix())
439    }
440}
441
442impl<'b, T: SimdRealField> DivAssign<&'b UnitComplex<T>> for Rotation<T, 2>
443where
444    T::Element: SimdRealField,
445{
446    #[inline]
447    fn div_assign(&mut self, rhs: &'b UnitComplex<T>) {
448        self.div_assign(rhs.clone().to_rotation_matrix())
449    }
450}