use num::{Zero, One}; use std::ops::{Index, IndexMut, Mul, MulAssign, Div, DivAssign}; use approx::ApproxEq; use alga::general::{Field, Real, ClosedAdd, ClosedMul, ClosedNeg, SubsetOf}; use core::{Scalar, ColumnVector, OwnedColumnVector, OwnedSquareMatrix}; use core::storage::{Storage, StorageMut, OwnedStorage}; use core::allocator::{Allocator, OwnedAllocator}; use core::dimension::{DimName, DimNameAdd, DimNameSum, U1, U3, U4}; use geometry::{PointBase, OwnedPoint, TransformBase, OwnedTransform, TCategory, TCategoryMul, SubTCategoryOf, SuperTCategoryOf, TGeneral, TProjective, TAffine, RotationBase, UnitQuaternionBase, IsometryBase, SimilarityBase, TranslationBase}; /* * * Indexing. * */ impl Index<(usize, usize)> for TransformBase where N: Scalar, D: DimName + DimNameAdd, S: Storage, DimNameSum> { type Output = N; #[inline] fn index(&self, ij: (usize, usize)) -> &N { self.matrix().index(ij) } } // Only general transformations are mutably indexable. impl IndexMut<(usize, usize)> for TransformBase where N: Scalar, D: DimName + DimNameAdd, S: StorageMut, DimNameSum> { #[inline] fn index_mut(&mut self, ij: (usize, usize)) -> &mut N { self.matrix_mut().index_mut(ij) } } /* * * In the following, we provide: * ========================= * * * (Operators) * * [OK] TransformBase × IsometryBase * [OK] TransformBase × RotationBase * [OK] TransformBase × SimilarityBase * [OK] TransformBase × TransformBase * [OK] TransformBase × UnitQuaternion * [OK] TransformBase × TranslationBase * [OK] TransformBase × ColumnVector * [OK] TransformBase × PointBase * * [OK] IsometryBase × TransformBase * [OK] RotationBase × TransformBase * [OK] SimilarityBase × TransformBase * [OK] TranslationBase × TransformBase * [OK] UnitQuaternionBase × TransformBase * * TransformBase ÷ IsometryBase * [OK] TransformBase ÷ RotationBase * TransformBase ÷ SimilarityBase * [OK] TransformBase ÷ TransformBase * [OK] TransformBase ÷ UnitQuaternion * [OK] TransformBase ÷ TranslationBase * * IsometryBase ÷ TransformBase * [OK] RotationBase ÷ TransformBase * SimilarityBase ÷ TransformBase * [OK] TranslationBase ÷ TransformBase * [OK] UnitQuaternionBase ÷ TransformBase * * * (Assignment Operators) * * * [OK] TransformBase ×= TransformBase * [OK] TransformBase ×= SimilarityBase * [OK] TransformBase ×= IsometryBase * [OK] TransformBase ×= RotationBase * [OK] TransformBase ×= UnitQuaternionBase * [OK] TransformBase ×= TranslationBase * * [OK] TransformBase ÷= TransformBase * TransformBase ÷= SimilarityBase * TransformBase ÷= IsometryBase * [OK] TransformBase ÷= RotationBase * [OK] TransformBase ÷= UnitQuaternionBase * */ // TransformBase × ColumnVector md_impl_all!( Mul, mul where N: Field; (DimNameSum, DimNameSum), (D, U1) for D: DimNameAdd, C: TCategory where SA::Alloc: Allocator where SA::Alloc: Allocator where SA::Alloc: Allocator; self: TransformBase, rhs: ColumnVector, Output = OwnedColumnVector; [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::(D::dim(), 0); let n = normalizer.tr_dot(&rhs); if !n.is_zero() { return transform * (rhs / n); } } transform * rhs }; ); // TransformBase × PointBase md_impl_all!( Mul, mul where N: Field; (DimNameSum, DimNameSum), (D, U1) for D: DimNameAdd, C: TCategory where SA::Alloc: Allocator where SA::Alloc: Allocator where SA::Alloc: Allocator; self: TransformBase, rhs: PointBase, Output = OwnedPoint; [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::dim()); if C::has_normalizer() { let normalizer = self.matrix().fixed_slice::(D::dim(), 0); let n = normalizer.tr_dot(&rhs.coords) + unsafe { *self.matrix().get_unchecked(D::dim(), D::dim()) }; if !n.is_zero() { return transform * (rhs / n) + translation; } } transform * rhs + translation }; ); // TransformBase × TransformBase md_impl_all!( Mul, mul; (DimNameSum, DimNameSum), (DimNameSum, DimNameSum) for D: DimNameAdd, CA: TCategoryMul, CB: TCategory; self: TransformBase, rhs: TransformBase, Output = OwnedTransform; [val val] => Self::Output::from_matrix_unchecked(self.unwrap() * rhs.unwrap()); [ref val] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.unwrap()); [val ref] => Self::Output::from_matrix_unchecked(self.unwrap() * rhs.matrix()); [ref ref] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.matrix()); ); // TransformBase × RotationBase md_impl_all!( Mul, mul where N: One; (DimNameSum, DimNameSum), (D, D) for D: DimNameAdd, C: TCategoryMul where SB::Alloc: Allocator, DimNameSum >; self: TransformBase, rhs: RotationBase, Output = OwnedTransform; [val val] => Self::Output::from_matrix_unchecked(self.unwrap() * rhs.to_homogeneous()); [ref val] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.to_homogeneous()); [val ref] => Self::Output::from_matrix_unchecked(self.unwrap() * rhs.to_homogeneous()); [ref ref] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.to_homogeneous()); ); // RotationBase × TransformBase md_impl_all!( Mul, mul where N: One; (D, D), (DimNameSum, DimNameSum) for D: DimNameAdd, C: TCategoryMul where SA::Alloc: Allocator, DimNameSum >; self: RotationBase, rhs: TransformBase, Output = OwnedTransform; [val val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.unwrap()); [ref val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.unwrap()); [val ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); [ref ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); ); // TransformBase × UnitQuaternionBase md_impl_all!( Mul, mul where N: Real; (U4, U4), (U4, U1) for C: TCategoryMul where SB::Alloc: Allocator where SB::Alloc: Allocator; self: TransformBase, rhs: UnitQuaternionBase, Output = OwnedTransform; [val val] => Self::Output::from_matrix_unchecked(self.unwrap() * rhs.to_homogeneous()); [ref val] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.to_homogeneous()); [val ref] => Self::Output::from_matrix_unchecked(self.unwrap() * rhs.to_homogeneous()); [ref ref] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.to_homogeneous()); ); // UnitQuaternionBase × TransformBase md_impl_all!( Mul, mul where N: Real; (U4, U1), (U4, U4) for C: TCategoryMul where SA::Alloc: Allocator where SA::Alloc: Allocator; self: UnitQuaternionBase, rhs: TransformBase, Output = OwnedTransform; [val val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.unwrap()); [ref val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.unwrap()); [val ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); [ref ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); ); // TransformBase × IsometryBase md_impl_all!( Mul, mul where N: Real; (DimNameSum, DimNameSum), (D, U1) for D: DimNameAdd, C: TCategoryMul, R: SubsetOf, SB::Alloc> > where SB::Alloc: Allocator, DimNameSum >; self: TransformBase, rhs: IsometryBase, Output = OwnedTransform; [val val] => Self::Output::from_matrix_unchecked(self.unwrap() * rhs.to_homogeneous()); [ref val] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.to_homogeneous()); [val ref] => Self::Output::from_matrix_unchecked(self.unwrap() * rhs.to_homogeneous()); [ref ref] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.to_homogeneous()); ); // IsometryBase × TransformBase md_impl_all!( Mul, mul where N: Real; (D, U1), (DimNameSum, DimNameSum) for D: DimNameAdd, C: TCategoryMul, R: SubsetOf, SA::Alloc> > where SA::Alloc: Allocator, DimNameSum >; self: IsometryBase, rhs: TransformBase, Output = OwnedTransform; [val val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.unwrap()); [ref val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.unwrap()); [val ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); [ref ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); ); // TransformBase × SimilarityBase md_impl_all!( Mul, mul where N: Real; (DimNameSum, DimNameSum), (D, U1) for D: DimNameAdd, C: TCategoryMul, R: SubsetOf, SB::Alloc> > where SB::Alloc: Allocator where SB::Alloc: Allocator, DimNameSum >; self: TransformBase, rhs: SimilarityBase, Output = OwnedTransform; [val val] => Self::Output::from_matrix_unchecked(self.unwrap() * rhs.to_homogeneous()); [ref val] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.to_homogeneous()); [val ref] => Self::Output::from_matrix_unchecked(self.unwrap() * rhs.to_homogeneous()); [ref ref] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.to_homogeneous()); ); // SimilarityBase × TransformBase md_impl_all!( Mul, mul where N: Real; (D, U1), (DimNameSum, DimNameSum) for D: DimNameAdd, C: TCategoryMul, R: SubsetOf, SA::Alloc> > where SA::Alloc: Allocator where SA::Alloc: Allocator, DimNameSum >; self: SimilarityBase, rhs: TransformBase, Output = OwnedTransform; [val val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.unwrap()); [ref val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.unwrap()); [val ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); [ref ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); ); /* * * FIXME: 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). * */ // TransformBase × TranslationBase md_impl_all!( Mul, mul where N: Real; (DimNameSum, DimNameSum), (D, U1) for D: DimNameAdd, C: TCategoryMul where SB::Alloc: Allocator, DimNameSum >; self: TransformBase, rhs: TranslationBase, Output = OwnedTransform; [val val] => Self::Output::from_matrix_unchecked(self.unwrap() * rhs.to_homogeneous()); [ref val] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.to_homogeneous()); [val ref] => Self::Output::from_matrix_unchecked(self.unwrap() * rhs.to_homogeneous()); [ref ref] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.to_homogeneous()); ); // TranslationBase × TransformBase md_impl_all!( Mul, mul where N: Real; (D, U1), (DimNameSum, DimNameSum) for D: DimNameAdd, C: TCategoryMul where SA::Alloc: Allocator, DimNameSum >; self: TranslationBase, rhs: TransformBase, Output = OwnedTransform; [val val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.unwrap()); [ref val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.unwrap()); [val ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); [ref ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); ); // TransformBase ÷ TransformBase md_impl_all!( Div, div where N: ApproxEq, Field; (DimNameSum, DimNameSum), (DimNameSum, DimNameSum) for D: DimNameAdd, CA: TCategoryMul, CB: SubTCategoryOf; self: TransformBase, rhs: TransformBase, Output = OwnedTransform; [val val] => self * rhs.inverse(); [ref val] => self * rhs.inverse(); [val ref] => self * rhs.clone_owned().inverse(); [ref ref] => self * rhs.clone_owned().inverse(); ); // TransformBase ÷ RotationBase md_impl_all!( Div, div where N: One; (DimNameSum, DimNameSum), (D, D) for D: DimNameAdd, C: TCategoryMul where SB::Alloc: Allocator, DimNameSum >; self: TransformBase, rhs: RotationBase, Output = OwnedTransform; [val val] => self * rhs.inverse(); [ref val] => self * rhs.inverse(); [val ref] => self * rhs.inverse(); [ref ref] => self * rhs.inverse(); ); // RotationBase ÷ TransformBase md_impl_all!( Div, div where N: One; (D, D), (DimNameSum, DimNameSum) for D: DimNameAdd, C: TCategoryMul where SA::Alloc: Allocator, DimNameSum >; self: RotationBase, rhs: TransformBase, Output = OwnedTransform; [val val] => self.inverse() * rhs; [ref val] => self.inverse() * rhs; [val ref] => self.inverse() * rhs; [ref ref] => self.inverse() * rhs; ); // TransformBase ÷ UnitQuaternionBase md_impl_all!( Div, div where N: Real; (U4, U4), (U4, U1) for C: TCategoryMul where SB::Alloc: Allocator where SB::Alloc: Allocator; self: TransformBase, rhs: UnitQuaternionBase, Output = OwnedTransform; [val val] => self * rhs.inverse(); [ref val] => self * rhs.inverse(); [val ref] => self * rhs.inverse(); [ref ref] => self * rhs.inverse(); ); // UnitQuaternionBase ÷ TransformBase md_impl_all!( Div, div where N: Real; (U4, U1), (U4, U4) for C: TCategoryMul where SA::Alloc: Allocator where SA::Alloc: Allocator; self: UnitQuaternionBase, rhs: TransformBase, Output = OwnedTransform; [val val] => self.inverse() * rhs; [ref val] => self.inverse() * rhs; [val ref] => self.inverse() * rhs; [ref ref] => self.inverse() * rhs; ); // // TransformBase ÷ IsometryBase // md_impl_all!( // Div, div where N: Real; // (DimNameSum, DimNameSum), (D, U1) // for D: DimNameAdd, C: TCategoryMul, R: SubsetOf, SB::Alloc> > // where SB::Alloc: Allocator, DimNameSum >; // self: TransformBase, rhs: IsometryBase, Output = OwnedTransform; // [val val] => Self::Output::from_matrix_unchecked(self.unwrap() * 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.unwrap() * rhs.inverse().to_homogeneous()); // [ref ref] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.inverse().to_homogeneous()); // ); // // IsometryBase ÷ TransformBase // md_impl_all!( // Div, div where N: Real; // (D, U1), (DimNameSum, DimNameSum) // for D: DimNameAdd, C: TCategoryMul, R: SubsetOf, SA::Alloc> > // where SA::Alloc: Allocator, DimNameSum >; // self: IsometryBase, rhs: TransformBase, Output = OwnedTransform; // [val val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.unwrap()); // [ref val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.unwrap()); // [val ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); // [ref ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); // ); // // TransformBase ÷ SimilarityBase // md_impl_all!( // Div, div where N: Real; // (DimNameSum, DimNameSum), (D, U1) // for D: DimNameAdd, C: TCategoryMul, R: SubsetOf, SB::Alloc> > // where SB::Alloc: Allocator // where SB::Alloc: Allocator, DimNameSum >; // self: TransformBase, rhs: SimilarityBase, Output = OwnedTransform; // [val val] => Self::Output::from_matrix_unchecked(self.unwrap() * rhs.to_homogeneous()); // [ref val] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.to_homogeneous()); // [val ref] => Self::Output::from_matrix_unchecked(self.unwrap() * rhs.to_homogeneous()); // [ref ref] => Self::Output::from_matrix_unchecked(self.matrix() * rhs.to_homogeneous()); // ); // // SimilarityBase ÷ TransformBase // md_impl_all!( // Div, div where N: Real; // (D, U1), (DimNameSum, DimNameSum) // for D: DimNameAdd, C: TCategoryMul, R: SubsetOf, SA::Alloc> > // where SA::Alloc: Allocator // where SA::Alloc: Allocator, DimNameSum >; // self: SimilarityBase, rhs: TransformBase, Output = OwnedTransform; // [val val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.unwrap()); // [ref val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.unwrap()); // [val ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); // [ref ref] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.matrix()); // ); // TransformBase ÷ TranslationBase md_impl_all!( Div, div where N: Real; (DimNameSum, DimNameSum), (D, U1) for D: DimNameAdd, C: TCategoryMul where SB::Alloc: Allocator, DimNameSum >; self: TransformBase, rhs: TranslationBase, Output = OwnedTransform; [val val] => self * rhs.inverse(); [ref val] => self * rhs.inverse(); [val ref] => self * rhs.inverse(); [ref ref] => self * rhs.inverse(); ); // TranslationBase ÷ TransformBase md_impl_all!( Div, div where N: Real; (D, U1), (DimNameSum, DimNameSum) for D: DimNameAdd, C: TCategoryMul where SA::Alloc: Allocator, DimNameSum >; self: TranslationBase, rhs: TransformBase, Output = OwnedTransform; [val val] => self.inverse() * rhs; [ref val] => self.inverse() * rhs; [val ref] => self.inverse() * rhs; [ref ref] => self.inverse() * rhs; ); // TransformBase ×= TransformBase md_assign_impl_all!( MulAssign, mul_assign; (DimNameSum, DimNameSum), (DimNameSum, DimNameSum) for D: DimNameAdd, CA: TCategory, CB: SubTCategoryOf; self: TransformBase, rhs: TransformBase; [val] => *self.matrix_mut_unchecked() *= rhs.unwrap(); [ref] => *self.matrix_mut_unchecked() *= rhs.matrix(); ); // TransformBase ×= SimilarityBase md_assign_impl_all!( MulAssign, mul_assign; (DimNameSum, DimNameSum), (D, U1) for D: DimNameAdd, C: TCategory, R: SubsetOf, SB::Alloc> > where SB::Alloc: Allocator, DimNameSum > where SB::Alloc: Allocator; self: TransformBase, rhs: SimilarityBase; [val] => *self.matrix_mut_unchecked() *= rhs.to_homogeneous(); [ref] => *self.matrix_mut_unchecked() *= rhs.to_homogeneous(); ); // TransformBase ×= IsometryBase md_assign_impl_all!( MulAssign, mul_assign; (DimNameSum, DimNameSum), (D, U1) for D: DimNameAdd, C: TCategory, R: SubsetOf, SB::Alloc> > where SB::Alloc: Allocator, DimNameSum >; self: TransformBase, rhs: IsometryBase; [val] => *self.matrix_mut_unchecked() *= rhs.to_homogeneous(); [ref] => *self.matrix_mut_unchecked() *= rhs.to_homogeneous(); ); /* * * FIXME: 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). * */ // TransformBase ×= TranslationBase md_assign_impl_all!( MulAssign, mul_assign where N: One; (DimNameSum, DimNameSum), (D, U1) for D: DimNameAdd, C: TCategory where SB::Alloc: Allocator, DimNameSum >; self: TransformBase, rhs: TranslationBase; [val] => *self.matrix_mut_unchecked() *= rhs.to_homogeneous(); [ref] => *self.matrix_mut_unchecked() *= rhs.to_homogeneous(); ); // TransformBase ×= RotationBase md_assign_impl_all!( MulAssign, mul_assign where N: One; (DimNameSum, DimNameSum), (D, D) for D: DimNameAdd, C: TCategory where SB::Alloc: Allocator, DimNameSum >; self: TransformBase, rhs: RotationBase; [val] => *self.matrix_mut_unchecked() *= rhs.to_homogeneous(); [ref] => *self.matrix_mut_unchecked() *= rhs.to_homogeneous(); ); // TransformBase ×= UnitQuaternionBase md_assign_impl_all!( MulAssign, mul_assign where N: Real; (U4, U4), (U4, U1) for C: TCategory where SB::Alloc: Allocator where SB::Alloc: Allocator; self: TransformBase, rhs: UnitQuaternionBase; [val] => *self.matrix_mut_unchecked() *= rhs.to_homogeneous(); [ref] => *self.matrix_mut_unchecked() *= rhs.to_homogeneous(); ); // TransformBase ÷= TransformBase md_assign_impl_all!( DivAssign, div_assign where N: Field, ApproxEq; (DimNameSum, DimNameSum), (DimNameSum, DimNameSum) for D: DimNameAdd, CA: SuperTCategoryOf, CB: SubTCategoryOf; self: TransformBase, rhs: TransformBase; [val] => *self *= rhs.clone_owned().inverse(); [ref] => *self *= rhs.clone_owned().inverse(); ); // // TransformBase ÷= SimilarityBase // md_assign_impl_all!( // DivAssign, div_assign; // (DimNameSum, DimNameSum), (D, U1) // for D: DimNameAdd, C: TCategory, R: SubsetOf, SB::Alloc> > // where SB::Alloc: Allocator, DimNameSum > // where SB::Alloc: Allocator; // self: TransformBase, rhs: SimilarityBase; // [val] => *self *= rhs.inverse(); // [ref] => *self *= rhs.inverse(); // ); // // // // TransformBase ÷= IsometryBase // md_assign_impl_all!( // DivAssign, div_assign; // (DimNameSum, DimNameSum), (D, U1) // for D: DimNameAdd, C: TCategory, R: SubsetOf, SB::Alloc> > // where SB::Alloc: Allocator, DimNameSum >; // self: TransformBase, rhs: IsometryBase; // [val] => *self *= rhs.inverse(); // [ref] => *self *= rhs.inverse(); // ); // TransformBase ÷= TranslationBase md_assign_impl_all!( DivAssign, div_assign where N: One, ClosedNeg; (DimNameSum, DimNameSum), (D, U1) for D: DimNameAdd, C: TCategory where SB::Alloc: Allocator, DimNameSum >; self: TransformBase, rhs: TranslationBase; [val] => *self *= rhs.inverse(); [ref] => *self *= rhs.inverse(); ); // TransformBase ÷= RotationBase md_assign_impl_all!( DivAssign, div_assign where N: One; (DimNameSum, DimNameSum), (D, D) for D: DimNameAdd, C: TCategory where SB::Alloc: Allocator, DimNameSum >; self: TransformBase, rhs: RotationBase; [val] => *self *= rhs.inverse(); [ref] => *self *= rhs.inverse(); ); // TransformBase ÷= UnitQuaternionBase md_assign_impl_all!( DivAssign, div_assign where N: Real; (U4, U4), (U4, U1) for C: TCategory where SB::Alloc: Allocator where SB::Alloc: Allocator; self: TransformBase, rhs: UnitQuaternionBase; [val] => *self *= rhs.inverse(); [ref] => *self *= rhs.inverse(); );