// The macros break if the references are taken out, for some reason. #![allow(clippy::op_ref)] use num::{One, Zero}; use std::ops::{Div, DivAssign, Index, IndexMut, Mul, MulAssign}; use simba::scalar::{ClosedAdd, ClosedMul, RealField, SubsetOf}; use crate::base::allocator::Allocator; use crate::base::dimension::{DimNameAdd, DimNameSum, U1}; use crate::base::{Const, DefaultAllocator, OMatrix, SVector, Scalar}; use crate::storage::InnerOwned; use crate::geometry::{ Isometry, Point, Rotation, Similarity, SubTCategoryOf, SuperTCategoryOf, TAffine, TCategory, TCategoryMul, TGeneral, TProjective, Transform, Translation, UnitQuaternion, }; /* * * In the following, we provide: * ========================= * * Index<(usize, usize)> * IndexMut<(usize, usize)> (where TCategory == TGeneral) * * (Operators) * * Transform × Isometry * Transform × Rotation * Transform × Similarity * Transform × Transform * Transform × UnitQuaternion * TODO: Transform × UnitComplex * Transform × Translation * Transform × Vector * Transform × Point * * Isometry × Transform * Rotation × Transform * Similarity × Transform * Translation × Transform * UnitQuaternion × Transform * TODO: UnitComplex × Transform * * TODO: Transform ÷ Isometry * Transform ÷ Rotation * TODO: Transform ÷ Similarity * Transform ÷ Transform * Transform ÷ UnitQuaternion * Transform ÷ Translation * * TODO: Isometry ÷ Transform * Rotation ÷ Transform * TODO: Similarity ÷ Transform * Translation ÷ Transform * UnitQuaternion ÷ Transform * TODO: UnitComplex ÷ Transform * * * (Assignment Operators) * * * Transform ×= Transform * Transform ×= Similarity * Transform ×= Isometry * Transform ×= Rotation * Transform ×= UnitQuaternion * TODO: Transform ×= UnitComplex * Transform ×= Translation * * Transform ÷= Transform * TODO: Transform ÷= Similarity * TODO: Transform ÷= Isometry * Transform ÷= Rotation * Transform ÷= UnitQuaternion * TODO: Transform ÷= UnitComplex * */ /* * * Indexing. * */ impl Index<(usize, usize)> for Transform where Const: DimNameAdd, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>, { type Output = T; #[inline] fn index(&self, ij: (usize, usize)) -> &T { self.matrix().index(ij) } } // Only general transformations are mutably indexable. impl IndexMut<(usize, usize)> for Transform where Const: DimNameAdd, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>, { #[inline] fn index_mut(&mut self, ij: (usize, usize)) -> &mut T { self.matrix_mut().index_mut(ij) } } // Transform × Vector md_impl_all!( Mul, mul where T: RealField; (DimNameSum, U1>, DimNameSum, U1>), (Const, U1) const D; for C; where Const: DimNameAdd, C: TCategory, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>; self: Transform, rhs: SVector, Output = SVector; [val val] => &self * &rhs; [ref val] => self * &rhs; [val ref] => &self * rhs; [ref ref] => { let transform = self.matrix().fixed_slice::(0, 0); if C::has_normalizer() { let normalizer = self.matrix().fixed_slice::<1, D>(D, 0); let n = normalizer.tr_dot(rhs); if !n.is_zero() { return transform * (rhs / n); } } transform * rhs }; ); // Transform × Point md_impl_all!( Mul, mul where T: RealField; (DimNameSum, U1>, DimNameSum, U1>), (Const, U1) const D; for C; where Const: DimNameAdd, C: TCategory, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>; self: Transform, rhs: Point, Output = Point; [val val] => &self * &rhs; [ref val] => self * &rhs; [val ref] => &self * rhs; [ref ref] => { let transform = self.matrix().fixed_slice::(0, 0); let translation = self.matrix().fixed_slice::(0, D); if C::has_normalizer() { let normalizer = self.matrix().fixed_slice::<1, D>(D, 0); #[allow(clippy::suspicious_arithmetic_impl)] let n = normalizer.tr_dot(&rhs.coords) + unsafe { *self.matrix().get_unchecked((D, D)) }; if !n.is_zero() { return (transform * rhs + translation) / n; } } transform * rhs + translation }; ); // Transform × Transform md_impl_all!( Mul, mul where T: RealField; (DimNameSum, U1>, DimNameSum, U1>), (DimNameSum, U1>, DimNameSum, U1>) const D; for CA, CB; where Const: DimNameAdd, CA: TCategoryMul, CB: TCategory, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>; self: Transform, rhs: Transform, Output = Transform; [val val] => Self::Output::from_matrix_unchecked(self.into_inner() * rhs.into_inner()); [ref val] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.into_inner()); [val ref] => Self::Output::from_matrix_unchecked(self.into_inner() * rhs.matrix()); [ref ref] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.matrix()); ); // Transform × Rotation md_impl_all!( Mul, mul where T: RealField; (DimNameSum, U1>, DimNameSum, U1>), (Const, Const) const D; for C; where Const: DimNameAdd, C: TCategoryMul, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>; self: Transform, rhs: Rotation, Output = Transform; [val val] => Self::Output::from_matrix_unchecked(self.into_inner() * rhs.to_homogeneous()); [ref val] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.to_homogeneous()); [val ref] => Self::Output::from_matrix_unchecked(self.into_inner() * rhs.to_homogeneous()); [ref ref] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.to_homogeneous()); ); // Rotation × Transform md_impl_all!( Mul, mul where T: RealField; (Const, Const), (DimNameSum, U1>, DimNameSum, U1>) const D; for C; where Const: DimNameAdd, C: TCategoryMul, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>; self: Rotation, rhs: Transform, Output = Transform; [val val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.into_inner()); [ref val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.into_inner()); [val ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); [ref ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); ); // Transform × UnitQuaternion md_impl_all!( Mul, mul where T: RealField; (U4, U4), (U4, U1) const; for C; where C: TCategoryMul; self: Transform, rhs: UnitQuaternion, Output = Transform; [val val] => Self::Output::from_matrix_unchecked(self.into_inner() * rhs.to_homogeneous()); [ref val] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.to_homogeneous()); [val ref] => Self::Output::from_matrix_unchecked(self.into_inner() * rhs.to_homogeneous()); [ref ref] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.to_homogeneous()); ); // UnitQuaternion × Transform md_impl_all!( Mul, mul where T: RealField; (U4, U1), (U4, U4) const; for C; where C: TCategoryMul; self: UnitQuaternion, rhs: Transform, Output = Transform; [val val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.into_inner()); [ref val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.into_inner()); [val ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); [ref ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); ); // Transform × Isometry md_impl_all!( Mul, mul where T: RealField; (DimNameSum, U1>, DimNameSum, U1>), (Const, U1) const D; for C, R; where Const: DimNameAdd, C: TCategoryMul, R: SubsetOf, U1>, DimNameSum, U1>> >, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>; self: Transform, rhs: Isometry, Output = Transform; [val val] => Self::Output::from_matrix_unchecked(self.into_inner() * rhs.to_homogeneous()); [ref val] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.to_homogeneous()); [val ref] => Self::Output::from_matrix_unchecked(self.into_inner() * rhs.to_homogeneous()); [ref ref] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.to_homogeneous()); ); // Isometry × Transform md_impl_all!( Mul, mul where T: RealField; (Const, U1), (DimNameSum, U1>, DimNameSum, U1>) const D; for C, R; where Const: DimNameAdd, C: TCategoryMul, R: SubsetOf, U1>, DimNameSum, U1>> >, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>; self: Isometry, rhs: Transform, Output = Transform; [val val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.into_inner()); [ref val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.into_inner()); [val ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); [ref ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); ); // Transform × Similarity md_impl_all!( Mul, mul where T: RealField; (DimNameSum, U1>, DimNameSum, U1>), (Const, U1) const D; for C, R; where Const: DimNameAdd, C: TCategoryMul, R: SubsetOf, U1>, DimNameSum, U1>> >, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>; self: Transform, rhs: Similarity, Output = Transform; [val val] => Self::Output::from_matrix_unchecked(self.into_inner() * rhs.to_homogeneous()); [ref val] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.to_homogeneous()); [val ref] => Self::Output::from_matrix_unchecked(self.into_inner() * rhs.to_homogeneous()); [ref ref] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.to_homogeneous()); ); // Similarity × Transform md_impl_all!( Mul, mul where T: RealField; (Const, U1), (DimNameSum, U1>, DimNameSum, U1>) const D; for C, R; where Const: DimNameAdd, C: TCategoryMul, R: SubsetOf, U1>, DimNameSum, U1>> >, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>; self: Similarity, rhs: Transform, Output = Transform; [val val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.into_inner()); [ref val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.into_inner()); [val ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); [ref ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); ); /* * * TODO: don't explicitly build the homogeneous translation matrix. * Directly apply the translation, just as in `Matrix::{append,prepend}_translation`. This has not * been done yet because of the `DimNameDiff` requirement (which is not automatically deduced from * `DimNameAdd` requirement). * */ // Transform × Translation md_impl_all!( Mul, mul where T: RealField; (DimNameSum, U1>, DimNameSum, U1>), (Const, U1) const D; for C; where Const: DimNameAdd, C: TCategoryMul, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>; self: Transform, rhs: Translation, Output = Transform; [val val] => Self::Output::from_matrix_unchecked(self.into_inner() * rhs.to_homogeneous()); [ref val] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.to_homogeneous()); [val ref] => Self::Output::from_matrix_unchecked(self.into_inner() * rhs.to_homogeneous()); [ref ref] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.to_homogeneous()); ); // Translation × Transform md_impl_all!( Mul, mul where T: RealField; (Const, U1), (DimNameSum, U1>, DimNameSum, U1>) const D; for C; where Const: DimNameAdd, C: TCategoryMul, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>; self: Translation, rhs: Transform, Output = Transform; [val val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.into_inner()); [ref val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.into_inner()); [val ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); [ref ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); ); // Transform ÷ Transform md_impl_all!( Div, div where T: RealField; (DimNameSum, U1>, DimNameSum, U1>), (DimNameSum, U1>, DimNameSum, U1>) const D; for CA, CB; where Const: DimNameAdd, CA: TCategoryMul, CB: SubTCategoryOf, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>, Transform: Clone; // There's probably a better bound here. self: Transform, rhs: Transform, Output = Transform; [val val] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() }; [ref val] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() }; [val ref] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.clone().inverse() }; [ref ref] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.clone().inverse() }; ); // Transform ÷ Rotation md_impl_all!( Div, div where T: RealField; (DimNameSum, U1>, DimNameSum, U1>), (Const, Const) const D; for C; where Const: DimNameAdd, C: TCategoryMul, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>; self: Transform, rhs: Rotation, Output = Transform; [val val] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() }; [ref val] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() }; [val ref] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() }; [ref ref] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() }; ); // Rotation ÷ Transform md_impl_all!( Div, div where T: RealField; (Const, Const), (DimNameSum, U1>, DimNameSum, U1>) const D; for C; where Const: DimNameAdd, C: TCategoryMul, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>; self: Rotation, rhs: Transform, Output = Transform; [val val] => #[allow(clippy::suspicious_arithmetic_impl)] { self.inverse() * rhs }; [ref val] => #[allow(clippy::suspicious_arithmetic_impl)] { self.inverse() * rhs }; [val ref] => #[allow(clippy::suspicious_arithmetic_impl)] { self.inverse() * rhs }; [ref ref] => #[allow(clippy::suspicious_arithmetic_impl)] { self.inverse() * rhs }; ); // Transform ÷ UnitQuaternion md_impl_all!( Div, div where T: RealField; (U4, U4), (U4, U1) const; for C; where C: TCategoryMul; self: Transform, rhs: UnitQuaternion, Output = Transform; [val val] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() }; [ref val] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() }; [val ref] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() }; [ref ref] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() }; ); // UnitQuaternion ÷ Transform md_impl_all!( Div, div where T: RealField; (U4, U1), (U4, U4) const; for C; where C: TCategoryMul; self: UnitQuaternion, rhs: Transform, Output = Transform; [val val] => #[allow(clippy::suspicious_arithmetic_impl)] { self.inverse() * rhs }; [ref val] => #[allow(clippy::suspicious_arithmetic_impl)] { self.inverse() * rhs }; [val ref] => #[allow(clippy::suspicious_arithmetic_impl)] { self.inverse() * rhs }; [ref ref] => #[allow(clippy::suspicious_arithmetic_impl)] { self.inverse() * rhs }; ); // // Transform ÷ Isometry // md_impl_all!( // Div, div where T: RealField; // (DimNameSum, U1>, DimNameSum, U1>), (Const, U1) // for Const: DimNameAdd, C: TCategoryMul, R: SubsetOf, U1>, DimNameSum, U1>> > // where SB::Alloc: Allocator, U1>, DimNameSum, U1> >; // self: Transform, rhs: Isometry, Output = Transform; // [val val] => Self::Output::from_matrix_unchecked(self.into_inner() * rhs.inverse().to_homogeneous()); // [ref val] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.inverse().to_homogeneous()); // [val ref] => Self::Output::from_matrix_unchecked(self.into_inner() * rhs.inverse().to_homogeneous()); // [ref ref] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.inverse().to_homogeneous()); // ); // // Isometry ÷ Transform // md_impl_all!( // Div, div where T: RealField; // (Const, U1), (DimNameSum, U1>, DimNameSum, U1>) // for Const: DimNameAdd, C: TCategoryMul, R: SubsetOf, U1>, DimNameSum, U1>> > // where SA::Alloc: Allocator, U1>, DimNameSum, U1> >; // self: Isometry, rhs: Transform, Output = Transform; // [val val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.into_inner()); // [ref val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.into_inner()); // [val ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); // [ref ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); // ); // // Transform ÷ Similarity // md_impl_all!( // Div, div where T: RealField; // (DimNameSum, U1>, DimNameSum, U1>), (Const, U1) // for Const: DimNameAdd, C: TCategoryMul, R: SubsetOf, U1>, DimNameSum, U1>> > // where SB::Alloc: Allocator // where SB::Alloc: Allocator, U1>, DimNameSum, U1> >; // self: Transform, rhs: Similarity, Output = Transform; // [val val] => Self::Output::from_matrix_unchecked(self.into_inner() * rhs.to_homogeneous()); // [ref val] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.to_homogeneous()); // [val ref] => Self::Output::from_matrix_unchecked(self.into_inner() * rhs.to_homogeneous()); // [ref ref] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.to_homogeneous()); // ); // // Similarity ÷ Transform // md_impl_all!( // Div, div where T: RealField; // (Const, U1), (DimNameSum, U1>, DimNameSum, U1>) // for Const: DimNameAdd, C: TCategoryMul, R: SubsetOf, U1>, DimNameSum, U1>> > // where SA::Alloc: Allocator // where SA::Alloc: Allocator, U1>, DimNameSum, U1> >; // self: Similarity, rhs: Transform, Output = Transform; // [val val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.into_inner()); // [ref val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.into_inner()); // [val ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); // [ref ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); // ); // Transform ÷ Translation md_impl_all!( Div, div where T: RealField; (DimNameSum, U1>, DimNameSum, U1>), (Const, U1) const D; for C; where Const: DimNameAdd, C: TCategoryMul, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>; self: Transform, rhs: Translation, Output = Transform; [val val] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() }; [ref val] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() }; [val ref] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() }; [ref ref] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() }; ); // Translation ÷ Transform md_impl_all!( Div, div where T: RealField; (Const, U1), (DimNameSum, U1>, DimNameSum, U1>) const D; for C; where Const: DimNameAdd, C: TCategoryMul, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>; self: Translation, rhs: Transform, Output = Transform; [val val] => #[allow(clippy::suspicious_arithmetic_impl)] { self.inverse() * rhs }; [ref val] => #[allow(clippy::suspicious_arithmetic_impl)] { self.inverse() * rhs }; [val ref] => #[allow(clippy::suspicious_arithmetic_impl)] { self.inverse() * rhs }; [ref ref] => #[allow(clippy::suspicious_arithmetic_impl)] { self.inverse() * rhs }; ); // Transform ×= Transform md_assign_impl_all!( MulAssign, mul_assign where T: RealField; (DimNameSum, U1>, DimNameSum, U1>), (DimNameSum, U1>, DimNameSum, U1>) const D; for CA, CB; where Const: DimNameAdd, CA: TCategory, CB: SubTCategoryOf, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>; self: Transform, rhs: Transform; [val] => *self.matrix_mut_unchecked() *= rhs.into_inner(); [ref] => *self.matrix_mut_unchecked() *= rhs.matrix(); ); // Transform ×= Similarity md_assign_impl_all!( MulAssign, mul_assign where T: RealField; (DimNameSum, U1>, DimNameSum, U1>), (Const, U1) const D; for C, R; where Const: DimNameAdd, C: TCategory, R: SubsetOf, U1>, DimNameSum, U1>> >, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>; self: Transform, rhs: Similarity; [val] => *self.matrix_mut_unchecked() *= rhs.to_homogeneous(); [ref] => *self.matrix_mut_unchecked() *= rhs.to_homogeneous(); ); // Transform ×= Isometry md_assign_impl_all!( MulAssign, mul_assign where T: RealField; (DimNameSum, U1>, DimNameSum, U1>), (Const, U1) const D; for C, R; where Const: DimNameAdd, C: TCategory, R: SubsetOf, U1>, DimNameSum, U1>> >, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>; self: Transform, rhs: Isometry; [val] => *self.matrix_mut_unchecked() *= rhs.to_homogeneous(); [ref] => *self.matrix_mut_unchecked() *= rhs.to_homogeneous(); ); /* * * TODO: don't explicitly build the homogeneous translation matrix. * Directly apply the translation, just as in `Matrix::{append,prepend}_translation`. This has not * been done yet because of the `DimNameDiff` requirement (which is not automatically deduced from * `DimNameAdd` requirement). * */ // Transform ×= Translation md_assign_impl_all!( MulAssign, mul_assign where T: RealField; (DimNameSum, U1>, DimNameSum, U1>), (Const, U1) const D; for C; where Const: DimNameAdd, C: TCategory, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>; self: Transform, rhs: Translation; [val] => *self.matrix_mut_unchecked() *= rhs.to_homogeneous(); [ref] => *self.matrix_mut_unchecked() *= rhs.to_homogeneous(); ); // Transform ×= Rotation md_assign_impl_all!( MulAssign, mul_assign where T: RealField; (DimNameSum, U1>, DimNameSum, U1>), (Const, Const) const D; for C; where Const: DimNameAdd, C: TCategory, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>; self: Transform, rhs: Rotation; [val] => *self.matrix_mut_unchecked() *= rhs.to_homogeneous(); [ref] => *self.matrix_mut_unchecked() *= rhs.to_homogeneous(); ); // Transform ×= UnitQuaternion md_assign_impl_all!( MulAssign, mul_assign where T: RealField; (U4, U4), (U4, U1) const; for C; where C: TCategory; self: Transform, rhs: UnitQuaternion; [val] => *self.matrix_mut_unchecked() *= rhs.to_homogeneous(); [ref] => *self.matrix_mut_unchecked() *= rhs.to_homogeneous(); ); // Transform ÷= Transform md_assign_impl_all!( DivAssign, div_assign where T: RealField; (DimNameSum, U1>, DimNameSum, U1>), (DimNameSum, U1>, DimNameSum, U1>) const D; for CA, CB; where Const: DimNameAdd, CA: SuperTCategoryOf, CB: SubTCategoryOf, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>, InnerOwned, U1>, DimNameSum, U1>>: Clone; self: Transform, rhs: Transform; [val] => #[allow(clippy::suspicious_op_assign_impl)] { *self *= rhs.inverse() }; [ref] => #[allow(clippy::suspicious_op_assign_impl)] { *self *= rhs.clone().inverse() }; ); // // Transform ÷= Similarity // md_assign_impl_all!( // DivAssign, div_assign; // (DimNameSum, U1>, DimNameSum, U1>), (Const, U1) // for Const: DimNameAdd, C: TCategory, R: SubsetOf, U1>, DimNameSum, U1>> >; // self: Transform, rhs: Similarity; // [val] => *self *= rhs.inverse(); // [ref] => *self *= rhs.inverse(); // ); // // // // Transform ÷= Isometry // md_assign_impl_all!( // DivAssign, div_assign; // (DimNameSum, U1>, DimNameSum, U1>), (Const, U1) // for Const: DimNameAdd, C: TCategory, R: SubsetOf, U1>, DimNameSum, U1>> >; // self: Transform, rhs: Isometry; // [val] => *self *= rhs.inverse(); // [ref] => *self *= rhs.inverse(); // ); // Transform ÷= Translation md_assign_impl_all!( DivAssign, div_assign where T: RealField; (DimNameSum, U1>, DimNameSum, U1>), (Const, U1) const D; for C; where Const: DimNameAdd, C: TCategory, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>; self: Transform, rhs: Translation; [val] => #[allow(clippy::suspicious_op_assign_impl)] { *self *= rhs.inverse() }; [ref] => #[allow(clippy::suspicious_op_assign_impl)] { *self *= rhs.inverse() }; ); // Transform ÷= Rotation md_assign_impl_all!( DivAssign, div_assign where T: RealField; (DimNameSum, U1>, DimNameSum, U1>), (Const, Const) const D; for C; where Const: DimNameAdd, C: TCategory, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>; self: Transform, rhs: Rotation; [val] => #[allow(clippy::suspicious_op_assign_impl)] { *self *= rhs.inverse() }; [ref] => #[allow(clippy::suspicious_op_assign_impl)] { *self *= rhs.inverse() }; ); // Transform ÷= UnitQuaternion md_assign_impl_all!( DivAssign, div_assign where T: RealField; (U4, U4), (U4, U1) const; for C; where C: TCategory; self: Transform, rhs: UnitQuaternion; [val] => #[allow(clippy::suspicious_op_assign_impl)] { *self *= rhs.inverse() }; [ref] => #[allow(clippy::suspicious_op_assign_impl)] { *self *= rhs.inverse() }; );