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