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 }