use std::ops::{Div, DivAssign, Mul, MulAssign}; use alga::general::Real; use crate::base::allocator::Allocator; use crate::base::dimension::{U1, U2}; use crate::base::storage::Storage; use crate::base::{DefaultAllocator, Unit, Vector, Vector2}; use crate::geometry::{Isometry, Point2, Rotation, Similarity, Translation, UnitComplex}; /* * This file provides: * =================== * * UnitComplex × UnitComplex * UnitComplex × Rotation -> UnitComplex * Rotation × UnitComplex -> UnitComplex * * UnitComplex ÷ UnitComplex * UnitComplex ÷ Rotation -> UnitComplex * Rotation ÷ UnitComplex -> UnitComplex * * * UnitComplex × Point * UnitComplex × Vector * UnitComplex × Unit * * UnitComplex × Isometry * UnitComplex × Similarity * UnitComplex × Translation -> Isometry * * NOTE: -UnitComplex is already provided by `Unit`. * * (Assignment Operators) * * UnitComplex ×= UnitComplex * UnitComplex ×= Rotation * * UnitComplex ÷= UnitComplex * UnitComplex ÷= Rotation * * Rotation ×= UnitComplex * Rotation ÷= UnitComplex * */ // UnitComplex × UnitComplex impl Mul for UnitComplex { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self { Unit::new_unchecked(self.into_inner() * rhs.into_inner()) } } impl<'a, N: Real> Mul> for &'a UnitComplex { type Output = UnitComplex; #[inline] fn mul(self, rhs: UnitComplex) -> Self::Output { Unit::new_unchecked(self.complex() * rhs.into_inner()) } } impl<'b, N: Real> Mul<&'b UnitComplex> for UnitComplex { type Output = Self; #[inline] fn mul(self, rhs: &'b UnitComplex) -> Self::Output { Unit::new_unchecked(self.into_inner() * rhs.complex()) } } impl<'a, 'b, N: Real> Mul<&'b UnitComplex> for &'a UnitComplex { type Output = UnitComplex; #[inline] fn mul(self, rhs: &'b UnitComplex) -> Self::Output { Unit::new_unchecked(self.complex() * rhs.complex()) } } // UnitComplex ÷ UnitComplex impl Div for UnitComplex { type Output = Self; #[inline] fn div(self, rhs: Self) -> Self::Output { Unit::new_unchecked(self.into_inner() * rhs.conjugate().into_inner()) } } impl<'a, N: Real> Div> for &'a UnitComplex { type Output = UnitComplex; #[inline] fn div(self, rhs: UnitComplex) -> Self::Output { Unit::new_unchecked(self.complex() * rhs.conjugate().into_inner()) } } impl<'b, N: Real> Div<&'b UnitComplex> for UnitComplex { type Output = Self; #[inline] fn div(self, rhs: &'b UnitComplex) -> Self::Output { Unit::new_unchecked(self.into_inner() * rhs.conjugate().into_inner()) } } impl<'a, 'b, N: Real> Div<&'b UnitComplex> for &'a UnitComplex { type Output = UnitComplex; #[inline] fn div(self, rhs: &'b UnitComplex) -> Self::Output { Unit::new_unchecked(self.complex() * rhs.conjugate().into_inner()) } } macro_rules! complex_op_impl( ($Op: ident, $op: ident; ($RDim: ident, $CDim: ident) $(for $Storage: ident: $StoragesBound: ident $(<$($BoundParam: ty),*>)*),*; $lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty, Output = $Result: ty; $action: expr; $($lives: tt),*) => { impl<$($lives ,)* N: Real $(, $Storage: $StoragesBound $(<$($BoundParam),*>)*)*> $Op<$Rhs> for $Lhs where DefaultAllocator: Allocator { type Output = $Result; #[inline] fn $op($lhs, $rhs: $Rhs) -> Self::Output { $action } } } ); macro_rules! complex_op_impl_all( ($Op: ident, $op: ident; ($RDim: ident, $CDim: ident) $(for $Storage: ident: $StoragesBound: ident $(<$($BoundParam: ty),*>)*),*; $lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty, Output = $Result: ty; [val val] => $action_val_val: expr; [ref val] => $action_ref_val: expr; [val ref] => $action_val_ref: expr; [ref ref] => $action_ref_ref: expr;) => { complex_op_impl!($Op, $op; ($RDim, $CDim) $(for $Storage: $StoragesBound $(<$($BoundParam),*>)*),*; $lhs: $Lhs, $rhs: $Rhs, Output = $Result; $action_val_val; ); complex_op_impl!($Op, $op; ($RDim, $CDim) $(for $Storage: $StoragesBound $(<$($BoundParam),*>)*),*; $lhs: &'a $Lhs, $rhs: $Rhs, Output = $Result; $action_ref_val; 'a); complex_op_impl!($Op, $op; ($RDim, $CDim) $(for $Storage: $StoragesBound $(<$($BoundParam),*>)*),*; $lhs: $Lhs, $rhs: &'b $Rhs, Output = $Result; $action_val_ref; 'b); complex_op_impl!($Op, $op; ($RDim, $CDim) $(for $Storage: $StoragesBound $(<$($BoundParam),*>)*),*; $lhs: &'a $Lhs, $rhs: &'b $Rhs, Output = $Result; $action_ref_ref; 'a, 'b); } ); // UnitComplex × Rotation complex_op_impl_all!( Mul, mul; (U2, U2); self: UnitComplex, rhs: Rotation, Output = UnitComplex; [val val] => &self * &rhs; [ref val] => self * &rhs; [val ref] => &self * rhs; [ref ref] => self * UnitComplex::from_rotation_matrix(rhs); ); // UnitComplex ÷ Rotation complex_op_impl_all!( Div, div; (U2, U2); self: UnitComplex, rhs: Rotation, Output = UnitComplex; [val val] => &self / &rhs; [ref val] => self / &rhs; [val ref] => &self / rhs; [ref ref] => self * UnitComplex::from_rotation_matrix(rhs).inverse(); ); // Rotation × UnitComplex complex_op_impl_all!( Mul, mul; (U2, U2); self: Rotation, rhs: UnitComplex, Output = UnitComplex; [val val] => &self * &rhs; [ref val] => self * &rhs; [val ref] => &self * rhs; [ref ref] => UnitComplex::from_rotation_matrix(self) * rhs; ); // Rotation ÷ UnitComplex complex_op_impl_all!( Div, div; (U2, U2); self: Rotation, rhs: UnitComplex, Output = UnitComplex; [val val] => &self / &rhs; [ref val] => self / &rhs; [val ref] => &self / rhs; [ref ref] => UnitComplex::from_rotation_matrix(self) * rhs.inverse(); ); // UnitComplex × Point complex_op_impl_all!( Mul, mul; (U2, U1); self: UnitComplex, rhs: Point2, Output = Point2; [val val] => &self * &rhs; [ref val] => self * &rhs; [val ref] => &self * rhs; [ref ref] => Point2::from(self * &rhs.coords); ); // UnitComplex × Vector complex_op_impl_all!( Mul, mul; (U2, U1) for S: Storage; self: UnitComplex, rhs: Vector, Output = Vector2; [val val] => &self * &rhs; [ref val] => self * &rhs; [val ref] => &self * rhs; [ref ref] => { let i = self.as_ref().im; let r = self.as_ref().re; Vector2::new(r * rhs[0] - i * rhs[1], i * rhs[0] + r * rhs[1]) }; ); // UnitComplex × Unit complex_op_impl_all!( Mul, mul; (U2, U1) for S: Storage; self: UnitComplex, rhs: Unit>, Output = Unit>; [val val] => &self * &rhs; [ref val] => self * &rhs; [val ref] => &self * rhs; [ref ref] => Unit::new_unchecked(self * rhs.as_ref()); ); // UnitComplex × Isometry complex_op_impl_all!( Mul, mul; (U2, U1); self: UnitComplex, rhs: Isometry>, Output = Isometry>; [val val] => &self * &rhs; [ref val] => self * &rhs; [val ref] => &self * rhs; [ref ref] => { let shift = self * &rhs.translation.vector; Isometry::from_parts(Translation::from(shift), self * &rhs.rotation) }; ); // UnitComplex × Similarity complex_op_impl_all!( Mul, mul; (U2, U1); self: UnitComplex, rhs: Similarity>, Output = Similarity>; [val val] => &self * &rhs; [ref val] => self * &rhs; [val ref] => &self * rhs; [ref ref] => Similarity::from_isometry(self * &rhs.isometry, rhs.scaling()); ); // UnitComplex × Translation complex_op_impl_all!( Mul, mul; (U2, U1); self: UnitComplex, rhs: Translation, Output = Isometry>; [val val] => Isometry::from_parts(Translation::from(&self * rhs.vector), self); [ref val] => Isometry::from_parts(Translation::from( self * rhs.vector), self.clone()); [val ref] => Isometry::from_parts(Translation::from(&self * &rhs.vector), self); [ref ref] => Isometry::from_parts(Translation::from( self * &rhs.vector), self.clone()); ); // Translation × UnitComplex complex_op_impl_all!( Mul, mul; (U2, U1); self: Translation, right: UnitComplex, Output = Isometry>; [val val] => Isometry::from_parts(self, right); [ref val] => Isometry::from_parts(self.clone(), right); [val ref] => Isometry::from_parts(self, right.clone()); [ref ref] => Isometry::from_parts(self.clone(), right.clone()); ); // UnitComplex ×= UnitComplex impl MulAssign> for UnitComplex { #[inline] fn mul_assign(&mut self, rhs: UnitComplex) { *self = &*self * rhs } } impl<'b, N: Real> MulAssign<&'b UnitComplex> for UnitComplex { #[inline] fn mul_assign(&mut self, rhs: &'b UnitComplex) { *self = &*self * rhs } } // UnitComplex /= UnitComplex impl DivAssign> for UnitComplex { #[inline] fn div_assign(&mut self, rhs: UnitComplex) { *self = &*self / rhs } } impl<'b, N: Real> DivAssign<&'b UnitComplex> for UnitComplex { #[inline] fn div_assign(&mut self, rhs: &'b UnitComplex) { *self = &*self / rhs } } // UnitComplex ×= Rotation impl MulAssign> for UnitComplex where DefaultAllocator: Allocator { #[inline] fn mul_assign(&mut self, rhs: Rotation) { *self = &*self * rhs } } impl<'b, N: Real> MulAssign<&'b Rotation> for UnitComplex where DefaultAllocator: Allocator { #[inline] fn mul_assign(&mut self, rhs: &'b Rotation) { *self = &*self * rhs } } // UnitComplex ÷= Rotation impl DivAssign> for UnitComplex where DefaultAllocator: Allocator { #[inline] fn div_assign(&mut self, rhs: Rotation) { *self = &*self / rhs } } impl<'b, N: Real> DivAssign<&'b Rotation> for UnitComplex where DefaultAllocator: Allocator { #[inline] fn div_assign(&mut self, rhs: &'b Rotation) { *self = &*self / rhs } } // Rotation ×= UnitComplex impl MulAssign> for Rotation where DefaultAllocator: Allocator { #[inline] fn mul_assign(&mut self, rhs: UnitComplex) { self.mul_assign(rhs.to_rotation_matrix()) } } impl<'b, N: Real> MulAssign<&'b UnitComplex> for Rotation where DefaultAllocator: Allocator { #[inline] fn mul_assign(&mut self, rhs: &'b UnitComplex) { self.mul_assign(rhs.to_rotation_matrix()) } } // Rotation ÷= UnitComplex impl DivAssign> for Rotation where DefaultAllocator: Allocator { #[inline] fn div_assign(&mut self, rhs: UnitComplex) { self.div_assign(rhs.to_rotation_matrix()) } } impl<'b, N: Real> DivAssign<&'b UnitComplex> for Rotation where DefaultAllocator: Allocator { #[inline] fn div_assign(&mut self, rhs: &'b UnitComplex) { self.div_assign(rhs.to_rotation_matrix()) } }