nalgebra/geometry/
similarity_ops.rs

1// The macros break if the references are taken out, for some reason.
2#![allow(clippy::op_ref)]
3
4use num::{One, Zero};
5use std::ops::{Div, DivAssign, Mul, MulAssign};
6
7use simba::scalar::{ClosedAddAssign, ClosedMulAssign};
8use simba::simd::SimdRealField;
9
10use crate::base::{SVector, Scalar};
11
12use crate::geometry::{
13    AbstractRotation, Isometry, Point, Rotation, Similarity, Translation, UnitComplex,
14    UnitQuaternion,
15};
16
17// TODO: there are several cloning of rotations that we could probably get rid of (but we didn't
18// yet because that would require to add a bound like `where for<'a, 'b> &'a R: Mul<&'b R, Output = R>`
19// which is quite ugly.
20
21/*
22 *
23 * In this file, we provide:
24 * =========================
25 *
26 *
27 * (Operators)
28 *
29 * Similarity × Similarity
30 * Similarity × R
31 * Similarity × Isometry
32 *
33 * Isometry × Similarity
34 * Isometry ÷ Similarity
35 *
36 *
37 * Similarity ÷ Similarity
38 * Similarity ÷ R
39 * Similarity ÷ Isometry
40 *
41 * Similarity × Point
42 * Similarity × Vector
43 *
44 *
45 * Similarity  × Translation
46 * Translation × Similarity
47 *
48 * NOTE: The following are provided explicitly because we can't have R × Similarity.
49 * Rotation   × Similarity<Rotation>
50 * UnitQuaternion × Similarity<UnitQuaternion>
51 *
52 * Rotation   ÷ Similarity<Rotation>
53 * UnitQuaternion ÷ Similarity<UnitQuaternion>
54 *
55 * (Assignment Operators)
56 *
57 * Similarity ×= Translation
58 *
59 * Similarity ×= Similarity
60 * Similarity ×= Isometry
61 * Similarity ×= R
62 *
63 * Similarity ÷= Similarity
64 * Similarity ÷= Isometry
65 * Similarity ÷= R
66 *
67 */
68
69// XXX: code duplication: those macros are the same as for the isometry.
70macro_rules! similarity_binop_impl(
71    ($Op: ident, $op: ident;
72     $lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty, Output = $Output: ty;
73     $action: expr; $($lives: tt),*) => {
74        impl<$($lives ,)* T: SimdRealField, R, const D: usize> $Op<$Rhs> for $Lhs
75            where T::Element: SimdRealField,
76                  R: AbstractRotation<T, D> {
77            type Output = $Output;
78
79            #[inline]
80            fn $op($lhs, $rhs: $Rhs) -> Self::Output {
81                $action
82            }
83        }
84    }
85);
86
87macro_rules! similarity_binop_impl_all(
88    ($Op: ident, $op: ident;
89     $lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty, Output = $Output: ty;
90     [val val] => $action_val_val: expr;
91     [ref val] => $action_ref_val: expr;
92     [val ref] => $action_val_ref: expr;
93     [ref ref] => $action_ref_ref: expr;) => {
94        similarity_binop_impl!(
95            $Op, $op;
96            $lhs: $Lhs, $rhs: $Rhs, Output = $Output;
97            $action_val_val; );
98
99        similarity_binop_impl!(
100            $Op, $op;
101            $lhs: &'a $Lhs, $rhs: $Rhs, Output = $Output;
102            $action_ref_val; 'a);
103
104        similarity_binop_impl!(
105            $Op, $op;
106            $lhs: $Lhs, $rhs: &'b $Rhs, Output = $Output;
107            $action_val_ref; 'b);
108
109        similarity_binop_impl!(
110            $Op, $op;
111            $lhs: &'a $Lhs, $rhs: &'b $Rhs, Output = $Output;
112            $action_ref_ref; 'a, 'b);
113    }
114);
115
116macro_rules! similarity_binop_assign_impl_all(
117    ($OpAssign: ident, $op_assign: ident;
118     $lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty;
119     [val] => $action_val: expr;
120     [ref] => $action_ref: expr;) => {
121        impl<T: SimdRealField, R, const D: usize> $OpAssign<$Rhs> for $Lhs
122            where T::Element: SimdRealField,
123                  R: AbstractRotation<T, D>{
124            #[inline]
125            fn $op_assign(&mut $lhs, $rhs: $Rhs) {
126                $action_val
127            }
128        }
129
130        impl<'b, T: SimdRealField, R, const D: usize> $OpAssign<&'b $Rhs> for $Lhs
131            where T::Element: SimdRealField,
132                  R: AbstractRotation<T, D> {
133            #[inline]
134            fn $op_assign(&mut $lhs, $rhs: &'b $Rhs) {
135                $action_ref
136            }
137        }
138    }
139);
140
141// Similarity × Similarity
142// Similarity ÷ Similarity
143similarity_binop_impl_all!(
144    Mul, mul;
145    self: Similarity<T, R, D>, rhs: Similarity<T, R, D>, Output = Similarity<T, R, D>;
146    [val val] => &self * &rhs;
147    [ref val] =>  self * &rhs;
148    [val ref] => &self *  rhs;
149    [ref ref] => {
150        let mut res = self * &rhs.isometry;
151        res.prepend_scaling_mut(rhs.scaling());
152        res
153    };
154);
155
156similarity_binop_impl_all!(
157    Div, div;
158    self: Similarity<T, R, D>, rhs: Similarity<T, R, D>, Output = Similarity<T, R, D>;
159    [val val] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() };
160    [ref val] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() };
161    [val ref] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() };
162    [ref ref] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() };
163);
164
165// Similarity ×= Translation
166similarity_binop_assign_impl_all!(
167    MulAssign, mul_assign;
168    self: Similarity<T, R, D>, rhs: Translation<T, D>;
169    [val] => *self *= &rhs;
170    [ref] => {
171        let shift = self.isometry.rotation.transform_vector(&rhs.vector) * self.scaling();
172        self.isometry.translation.vector += shift;
173    };
174);
175
176// Similarity ×= Similarity
177// Similarity ÷= Similarity
178similarity_binop_assign_impl_all!(
179    MulAssign, mul_assign;
180    self: Similarity<T, R, D>, rhs: Similarity<T, R, D>;
181    [val] => *self *= &rhs;
182    [ref] => {
183        *self *= &rhs.isometry;
184        self.prepend_scaling_mut(rhs.scaling());
185    };
186);
187
188similarity_binop_assign_impl_all!(
189    DivAssign, div_assign;
190    self: Similarity<T, R, D>, rhs: Similarity<T, R, D>;
191    [val] => *self /= &rhs;
192    // TODO: don't invert explicitly.
193    [ref] => #[allow(clippy::suspicious_op_assign_impl)] { *self *= rhs.inverse() };
194);
195
196// Similarity ×= Isometry
197// Similarity ÷= Isometry
198similarity_binop_assign_impl_all!(
199    MulAssign, mul_assign;
200    self: Similarity<T, R, D>, rhs: Isometry<T, R, D>;
201    [val] => *self *= &rhs;
202    [ref] => {
203        let shift = self.isometry.rotation.transform_vector(&rhs.translation.vector) * self.scaling();
204        self.isometry.translation.vector += shift;
205        self.isometry.rotation *= rhs.rotation.clone();
206    };
207);
208
209similarity_binop_assign_impl_all!(
210    DivAssign, div_assign;
211    self: Similarity<T, R, D>, rhs: Isometry<T, R, D>;
212    [val] => *self /= &rhs;
213    // TODO: don't invert explicitly.
214    [ref] => #[allow(clippy::suspicious_op_assign_impl)] { *self *= rhs.inverse() };
215);
216
217// Similarity ×= R
218// Similarity ÷= R
219md_assign_impl_all!(
220    MulAssign, mul_assign where T: SimdRealField for T::Element: SimdRealField;
221    (Const<D>, U1), (Const<D>, Const<D>)
222    const D; for; where;
223    self: Similarity<T, Rotation<T, D>, D>, rhs: Rotation<T, D>;
224    [val] => self.isometry.rotation *= rhs;
225    [ref] => self.isometry.rotation *= rhs.clone();
226);
227
228md_assign_impl_all!(
229    DivAssign, div_assign where T: SimdRealField for T::Element: SimdRealField;
230    (Const<D>, U1), (Const<D>, Const<D>)
231    const D; for; where;
232    self: Similarity<T, Rotation<T, D>, D>, rhs: Rotation<T, D>;
233    // TODO: don't invert explicitly?
234    [val] => #[allow(clippy::suspicious_op_assign_impl)] { *self *= rhs.inverse() };
235    [ref] => #[allow(clippy::suspicious_op_assign_impl)] { *self *= rhs.inverse() };
236);
237
238md_assign_impl_all!(
239    MulAssign, mul_assign where T: SimdRealField for T::Element: SimdRealField;
240    (U3, U3), (U3, U3)
241    const; for; where;
242    self: Similarity<T, UnitQuaternion<T>, 3>, rhs: UnitQuaternion<T>;
243    [val] => self.isometry.rotation *= rhs;
244    [ref] => self.isometry.rotation *= rhs.clone();
245);
246
247md_assign_impl_all!(
248    DivAssign, div_assign where T: SimdRealField for T::Element: SimdRealField;
249    (U3, U3), (U3, U3)
250    const; for; where;
251    self: Similarity<T, UnitQuaternion<T>, 3>, rhs: UnitQuaternion<T>;
252    // TODO: don't invert explicitly?
253    [val] => #[allow(clippy::suspicious_op_assign_impl)] { *self *= rhs.inverse() };
254    [ref] => #[allow(clippy::suspicious_op_assign_impl)] { *self *= rhs.inverse() };
255);
256
257md_assign_impl_all!(
258    MulAssign, mul_assign where T: SimdRealField for T::Element: SimdRealField;
259    (U2, U2), (U2, U2)
260    const; for; where;
261    self: Similarity<T, UnitComplex<T>, 2>, rhs: UnitComplex<T>;
262    [val] => self.isometry.rotation *= rhs;
263    [ref] => self.isometry.rotation *= rhs.clone();
264);
265
266md_assign_impl_all!(
267    DivAssign, div_assign where T: SimdRealField for T::Element: SimdRealField;
268    (U2, U2), (U2, U2)
269    const; for; where;
270    self: Similarity<T, UnitComplex<T>, 2>, rhs: UnitComplex<T>;
271    // TODO: don't invert explicitly?
272    [val] => #[allow(clippy::suspicious_op_assign_impl)] { *self *= rhs.inverse() };
273    [ref] => #[allow(clippy::suspicious_op_assign_impl)] { *self *= rhs.inverse() };
274);
275
276// Similarity × Isometry
277// Similarity ÷ Isometry
278similarity_binop_impl_all!(
279    Mul, mul;
280    self: Similarity<T, R, D>, rhs: Isometry<T, R, D>, Output = Similarity<T, R, D>;
281    [val val] => &self * &rhs;
282    [ref val] => self * &rhs;
283    [val ref] => &self * rhs;
284    [ref ref] => {
285        let shift = self.isometry.rotation.transform_vector(&rhs.translation.vector) * self.scaling();
286        Similarity::from_parts(
287            #[allow(clippy::suspicious_arithmetic_impl)]
288            Translation::from(&self.isometry.translation.vector + shift),
289            self.isometry.rotation.clone() * rhs.rotation.clone(),
290            self.scaling())
291    };
292);
293
294similarity_binop_impl_all!(
295    Div, div;
296    self: Similarity<T, R, D>, rhs: Isometry<T, R, D>, Output = Similarity<T, R, D>;
297    [val val] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() };
298    [ref val] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() };
299    [val ref] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() };
300    [ref ref] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() };
301);
302
303// Isometry × Similarity
304// Isometry ÷ Similarity
305similarity_binop_impl_all!(
306    Mul, mul;
307    self: Isometry<T, R, D>, rhs: Similarity<T, R, D>, Output = Similarity<T, R, D>;
308    [val val] => {
309        let scaling = rhs.scaling();
310        Similarity::from_isometry(self * rhs.isometry, scaling)
311    };
312    [ref val] => {
313        let scaling = rhs.scaling();
314        Similarity::from_isometry(self * rhs.isometry, scaling)
315    };
316    [val ref] => {
317        let scaling = rhs.scaling();
318        Similarity::from_isometry(self * &rhs.isometry, scaling)
319    };
320    [ref ref] => {
321        let scaling = rhs.scaling();
322        Similarity::from_isometry(self * &rhs.isometry, scaling)
323    };
324);
325
326similarity_binop_impl_all!(
327    Div, div;
328    self: Isometry<T, R, D>, rhs: Similarity<T, R, D>, Output = Similarity<T, R, D>;
329    [val val] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() };
330    [ref val] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() };
331    [val ref] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() };
332    [ref ref] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() };
333);
334
335// Similarity × Point
336similarity_binop_impl_all!(
337    Mul, mul;
338    self: Similarity<T, R, D>, right: Point<T, D>, Output = Point<T, D>;
339    [val val] => {
340        let scaling = self.scaling();
341        self.isometry.translation * (self.isometry.rotation.transform_point(&right) * scaling)
342    };
343    [ref val] => &self.isometry.translation * (self.isometry.rotation.transform_point(&right) * self.scaling());
344    [val ref] => {
345        let scaling = self.scaling();
346        self.isometry.translation * (self.isometry.rotation.transform_point(right) * scaling)
347    };
348    [ref ref] => &self.isometry.translation * (self.isometry.rotation.transform_point(right) * self.scaling());
349);
350
351// Similarity × Vector
352similarity_binop_impl_all!(
353    Mul, mul;
354    self: Similarity<T, R, D>, right: SVector<T, D>, Output = SVector<T, D>;
355    [val val] => self.isometry.rotation.transform_vector(&right) * self.scaling();
356    [ref val] => self.isometry.rotation.transform_vector(&right) * self.scaling();
357    [val ref] => self.isometry.rotation.transform_vector(right) * self.scaling();
358    [ref ref] => self.isometry.rotation.transform_vector(right) * self.scaling();
359);
360
361// Similarity × Translation
362similarity_binop_impl_all!(
363    Mul, mul;
364    self: Similarity<T, R, D>, right: Translation<T, D>, Output = Similarity<T, R, D>;
365    [val val] => &self * &right;
366    [ref val] => self * &right;
367    [val ref] => &self * right;
368    [ref ref] => {
369        let shift = self.isometry.rotation.transform_vector(&right.vector) * self.scaling();
370        Similarity::from_parts(
371            #[allow(clippy::suspicious_arithmetic_impl)]
372            Translation::from(&self.isometry.translation.vector + shift),
373            self.isometry.rotation.clone(),
374            self.scaling())
375    };
376);
377
378// Translation × Similarity
379similarity_binop_impl_all!(
380    Mul, mul;
381    self: Translation<T, D>, right: Similarity<T, R, D>, Output = Similarity<T, R, D>;
382    [val val] => {
383        let scaling = right.scaling();
384        Similarity::from_isometry(self * right.isometry, scaling)
385    };
386    [ref val] => {
387        let scaling = right.scaling();
388        Similarity::from_isometry(self * right.isometry, scaling)
389    };
390    [val ref] => Similarity::from_isometry(self * &right.isometry, right.scaling());
391    [ref ref] => Similarity::from_isometry(self * &right.isometry, right.scaling());
392);
393
394macro_rules! similarity_from_composition_impl(
395    ($Op: ident, $op: ident;
396     $($Dims: ident),*;
397     $lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty, Output = $Output: ty;
398     $action: expr; $($lives: tt),*) => {
399        impl<$($lives ,)* T: SimdRealField $(, const $Dims: usize)*> $Op<$Rhs> for $Lhs
400            where T::Element: SimdRealField {
401            type Output = $Output;
402
403            #[inline]
404            fn $op($lhs, $rhs: $Rhs) -> Self::Output {
405                $action
406            }
407        }
408    }
409);
410
411macro_rules! similarity_from_composition_impl_all(
412    ($Op: ident, $op: ident;
413     $($Dims: ident),*;
414     $lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty, Output = $Output: ty;
415     [val val] => $action_val_val: expr;
416     [ref val] => $action_ref_val: expr;
417     [val ref] => $action_val_ref: expr;
418     [ref ref] => $action_ref_ref: expr;) => {
419
420        similarity_from_composition_impl!(
421            $Op, $op;
422            $($Dims),*;
423            $lhs: $Lhs, $rhs: $Rhs, Output = $Output;
424            $action_val_val; );
425
426        similarity_from_composition_impl!(
427            $Op, $op;
428            $($Dims),*;
429            $lhs: &'a $Lhs, $rhs: $Rhs, Output = $Output;
430            $action_ref_val; 'a);
431
432        similarity_from_composition_impl!(
433            $Op, $op;
434            $($Dims),*;
435            $lhs: $Lhs, $rhs: &'b $Rhs, Output = $Output;
436            $action_val_ref; 'b);
437
438        similarity_from_composition_impl!(
439            $Op, $op;
440            $($Dims),*;
441            $lhs: &'a $Lhs, $rhs: &'b $Rhs, Output = $Output;
442            $action_ref_ref; 'a, 'b);
443    }
444);
445
446// Similarity × Rotation
447similarity_from_composition_impl_all!(
448    Mul, mul;
449    D;
450    self: Similarity<T, Rotation<T, D>, D>, rhs: Rotation<T, D>,
451    Output = Similarity<T, Rotation<T, D>, D>;
452    [val val] => {
453        let scaling = self.scaling();
454        Similarity::from_isometry(self.isometry * rhs, scaling)
455    };
456    [ref val] => Similarity::from_isometry(&self.isometry * rhs, self.scaling());
457    [val ref] => {
458        let scaling = self.scaling();
459        Similarity::from_isometry(self.isometry * rhs, scaling)
460    };
461    [ref ref] => Similarity::from_isometry(&self.isometry * rhs, self.scaling());
462);
463
464// Rotation × Similarity
465similarity_from_composition_impl_all!(
466    Mul, mul;
467    D;
468    self: Rotation<T, D>, right: Similarity<T, Rotation<T, D>, D>,
469    Output = Similarity<T, Rotation<T, D>, D>;
470    [val val] => &self * &right;
471    [ref val] =>  self * &right;
472    [val ref] => &self *  right;
473    [ref ref] => Similarity::from_isometry(self * &right.isometry, right.scaling());
474);
475
476// Similarity ÷ Rotation
477similarity_from_composition_impl_all!(
478    Div, div;
479    D;
480    self: Similarity<T, Rotation<T, D>, D>, rhs: Rotation<T, D>,
481    Output = Similarity<T, Rotation<T, D>, D>;
482    [val val] => {
483        let scaling = self.scaling();
484        Similarity::from_isometry(self.isometry / rhs, scaling)
485    };
486    [ref val] => Similarity::from_isometry(&self.isometry / rhs, self.scaling());
487    [val ref] => {
488        let scaling = self.scaling();
489        Similarity::from_isometry(self.isometry / rhs, scaling)
490    };
491    [ref ref] => Similarity::from_isometry(&self.isometry / rhs, self.scaling());
492);
493
494// Rotation ÷ Similarity
495similarity_from_composition_impl_all!(
496    Div, div;
497    D;
498    self: Rotation<T, D>, right: Similarity<T, Rotation<T, D>, D>,
499    Output = Similarity<T, Rotation<T, D>, D>;
500    // TODO: don't call inverse explicitly?
501    [val val] => #[allow(clippy::suspicious_arithmetic_impl)] { self * right.inverse() };
502    [ref val] => #[allow(clippy::suspicious_arithmetic_impl)] { self * right.inverse() };
503    [val ref] => #[allow(clippy::suspicious_arithmetic_impl)] { self * right.inverse() };
504    [ref ref] => #[allow(clippy::suspicious_arithmetic_impl)] { self * right.inverse() };
505);
506
507// Similarity × UnitQuaternion
508similarity_from_composition_impl_all!(
509    Mul, mul;
510    ;
511    self: Similarity<T, UnitQuaternion<T>, 3>, rhs: UnitQuaternion<T>,
512    Output = Similarity<T, UnitQuaternion<T>, 3>;
513    [val val] => {
514        let scaling = self.scaling();
515        Similarity::from_isometry(self.isometry * rhs, scaling)
516    };
517    [ref val] => Similarity::from_isometry(&self.isometry * rhs, self.scaling());
518    [val ref] => {
519        let scaling = self.scaling();
520        Similarity::from_isometry(self.isometry * rhs, scaling)
521    };
522    [ref ref] => Similarity::from_isometry(&self.isometry * rhs, self.scaling());
523);
524
525// UnitQuaternion × Similarity
526similarity_from_composition_impl_all!(
527    Mul, mul;
528    ;
529    self: UnitQuaternion<T>, right: Similarity<T, UnitQuaternion<T>, 3>,
530    Output = Similarity<T, UnitQuaternion<T>, 3>;
531    [val val] => &self * &right;
532    [ref val] =>  self * &right;
533    [val ref] => &self *  right;
534    [ref ref] => Similarity::from_isometry(self * &right.isometry, right.scaling());
535);
536
537// Similarity ÷ UnitQuaternion
538similarity_from_composition_impl_all!(
539    Div, div;
540    ;
541    self: Similarity<T, UnitQuaternion<T>, 3>, rhs: UnitQuaternion<T>,
542    Output = Similarity<T, UnitQuaternion<T>, 3>;
543    [val val] => {
544        let scaling = self.scaling();
545        Similarity::from_isometry(self.isometry / rhs, scaling)
546    };
547    [ref val] => Similarity::from_isometry(&self.isometry / rhs, self.scaling());
548    [val ref] => {
549        let scaling = self.scaling();
550        Similarity::from_isometry(self.isometry / rhs, scaling)
551    };
552    [ref ref] => Similarity::from_isometry(&self.isometry / rhs, self.scaling());
553);
554
555// UnitQuaternion ÷ Similarity
556similarity_from_composition_impl_all!(
557    Div, div;
558    ;
559    self: UnitQuaternion<T>, right: Similarity<T, UnitQuaternion<T>, 3>,
560    Output = Similarity<T, UnitQuaternion<T>, 3>;
561    // TODO: don't call inverse explicitly?
562    [val val] => #[allow(clippy::suspicious_arithmetic_impl)] { self * right.inverse() };
563    [ref val] => #[allow(clippy::suspicious_arithmetic_impl)] { self * right.inverse() };
564    [val ref] => #[allow(clippy::suspicious_arithmetic_impl)] { self * right.inverse() };
565    [ref ref] => #[allow(clippy::suspicious_arithmetic_impl)] { self * right.inverse() };
566);
567
568// Similarity × UnitComplex
569similarity_from_composition_impl_all!(
570    Mul, mul;
571    ;
572    self: Similarity<T, UnitComplex<T>, 2>, rhs: UnitComplex<T>,
573    Output = Similarity<T, UnitComplex<T>, 2>;
574    [val val] => {
575        let scaling = self.scaling();
576        Similarity::from_isometry(self.isometry * rhs, scaling)
577    };
578    [ref val] => Similarity::from_isometry(&self.isometry * rhs, self.scaling());
579    [val ref] => {
580        let scaling = self.scaling();
581        Similarity::from_isometry(self.isometry * rhs, scaling)
582    };
583    [ref ref] => Similarity::from_isometry(&self.isometry * rhs, self.scaling());
584);
585
586// Similarity ÷ UnitComplex
587similarity_from_composition_impl_all!(
588    Div, div;
589    ;
590    self: Similarity<T, UnitComplex<T>, 2>, rhs: UnitComplex<T>,
591    Output = Similarity<T, UnitComplex<T>, 2>;
592    [val val] => {
593        let scaling = self.scaling();
594        Similarity::from_isometry(self.isometry / rhs, scaling)
595    };
596    [ref val] => Similarity::from_isometry(&self.isometry / rhs, self.scaling());
597    [val ref] => {
598        let scaling = self.scaling();
599        Similarity::from_isometry(self.isometry / rhs, scaling)
600    };
601    [ref ref] => Similarity::from_isometry(&self.isometry / rhs, self.scaling());
602);