math_utils/types/
mod.rs

1use std::marker::PhantomData;
2use derive_more::{Deref, Display, From, Neg};
3use either::Either;
4use vek;
5
6use crate::approx;
7use crate::num_traits as num;
8
9#[cfg(feature = "derive_serdes")]
10use serde::{Deserialize, Serialize};
11
12use crate::traits::*;
13
14pub mod coordinate;
15
16pub use vek::Vec2 as Vector2;
17pub use vek::Mat2 as Matrix2;
18pub use vek::Vec3 as Vector3;
19pub use vek::Mat3 as Matrix3;
20pub use vek::Vec4 as Vector4;
21pub use vek::Mat4 as Matrix4;
22pub use vek::Quaternion as Quaternion;
23
24pub use self::enums::{Axis2, Axis3, Axis4, Octant, Quadrant, Sign, SignedAxis1,
25  SignedAxis2, SignedAxis3, SignedAxis4};
26
27////////////////////////////////////////////////////////////////////////////////
28//  enums
29////////////////////////////////////////////////////////////////////////////////
30
31// we define enums in a separate module so that the generated iterator types
32// don't pollute the namespace
33mod enums {
34  use strum::{EnumCount, EnumIter, FromRepr};
35  #[cfg(feature = "derive_serdes")]
36  use serde::{Deserialize, Serialize};
37
38  /// Negative, zero, or positive
39  #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
40  #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
41  #[repr(u8)]
42  pub enum Sign {
43    Negative,
44    Zero,
45    Positive
46  }
47
48  /// 2D quadrant
49  #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
50  #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
51  #[repr(u8)]
52  pub enum Quadrant {
53    /// +X, +Y
54    PosPos,
55    /// -X, +Y
56    NegPos,
57    /// +X, -Y
58    PosNeg,
59    /// -X, -Y
60    NegNeg
61  }
62
63  /// 3D octant
64  #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
65  #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
66  #[repr(u8)]
67  pub enum Octant {
68    /// +X, +Y, +Z
69    PosPosPos,
70    /// -X, +Y, +Z
71    NegPosPos,
72    /// +X, -Y, +Z
73    PosNegPos,
74    /// -X, -Y, +Z
75    NegNegPos,
76    /// +X, +Y, -Z
77    PosPosNeg,
78    /// -X, +Y, -Z
79    NegPosNeg,
80    /// +X, -Y, -Z
81    PosNegNeg,
82    /// -X, -Y, -Z
83    NegNegNeg
84  }
85
86  /// X or Y axis
87  #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
88  #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
89  #[repr(u8)]
90  pub enum Axis2 {
91    X=0,
92    Y
93  }
94
95  /// X, Y, or Z axis
96  #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
97  #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
98  #[repr(u8)]
99  pub enum Axis3 {
100    X=0,
101    Y,
102    Z
103  }
104
105  /// X, Y, Z, or W axis
106  #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
107  #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
108  #[repr(u8)]
109  pub enum Axis4 {
110    X=0,
111    Y,
112    Z,
113    W
114  }
115
116  /// Positive or negative X axis
117  #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
118  #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
119  #[repr(u8)]
120  pub enum SignedAxis1 {
121    NegX, PosX
122  }
123
124  /// Positive or negative X or Y axis
125  #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
126  #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
127  #[repr(u8)]
128  pub enum SignedAxis2 {
129    NegX, PosX,
130    NegY, PosY
131  }
132
133  /// Positive or negative X, Y, or Z axis
134  #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
135  #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
136  #[repr(u8)]
137  pub enum SignedAxis3 {
138    NegX, PosX,
139    NegY, PosY,
140    NegZ, PosZ
141  }
142
143  /// Positive or negative X, Y, Z, or W axis
144  #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
145  #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
146  #[repr(u8)]
147  pub enum SignedAxis4 {
148    NegX, PosX,
149    NegY, PosY,
150    NegZ, PosZ,
151    NegW, PosW
152  }
153}
154
155////////////////////////////////////////////////////////////////////////////////
156//  structs
157////////////////////////////////////////////////////////////////////////////////
158
159/// Strictly positive scalars (non-zero)
160#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
161#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
162pub struct Positive <S> (S);
163
164/// Non-negative scalars (may be zero)
165#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
166#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
167pub struct NonNegative <S> (S);
168
169/// Non-zero scalars
170#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
171#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
172pub struct NonZero <S> (S);
173
174/// Scalars in the closed unit interval [0, 1]
175#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
176#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
177pub struct Normalized <S> (S);
178
179/// Scalars in the closed interval [-1, 1]
180#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
181#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
182pub struct NormalSigned <S> (S);
183
184/// (Euler angles) representation of a 3D orientation. Internally the angles are
185/// wrapped to $[0, 2\pi)$.
186///
187/// Throughout this library this is usually interpreted as intrinsic ZX'Y''
188/// Euler angles.
189#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
190#[derive(Clone, Copy, Debug, Default, PartialEq)]
191pub struct Angles3 <S> {
192  pub yaw   : AngleWrapped <S>,
193  pub pitch : AngleWrapped <S>,
194  pub roll  : AngleWrapped <S>
195}
196
197/// Representation of a 3D position + orientation
198#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
199#[derive(Clone, Copy, Debug, Default, PartialEq)]
200pub struct Pose3 <S> {
201  pub position : Point3  <S>,
202  pub angles   : Angles3 <S>
203}
204
205/// Invertible linear map
206#[derive(Clone, Copy, Debug, Default, PartialEq, Display)]
207#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
208#[display("{}", _0)]
209pub struct LinearIso <S, V, W, M> (M, PhantomData <(S, V, W)>);
210
211/// Invertible linear endomorphism
212#[derive(Clone, Copy, Debug, Default, PartialEq, Deref, Display, From)]
213#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
214#[display("{}", _0)]
215pub struct LinearAuto <S, V> (pub LinearIso <S, V, V, V::LinearEndo>) where
216  V : Module <S>,
217  V::LinearEndo : MaybeSerDes,
218  S : Ring;
219
220/// Orthogonal 2x2 matrix with determinant +1, i.e. a member of the circle group
221/// $SO(2)$ of special orthogonal matrices
222#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
223#[cfg_attr(feature = "derive_serdes", serde(bound = "S : MaybeSerDes"))]
224#[derive(Clone, Copy, Debug, Default, PartialEq)]
225pub struct Rotation2 <S> (LinearAuto <S, Vector2 <S>>) where
226  S : Ring + MaybeSerDes;
227
228/// Orthogonal 3x3 matrix with determinant +1, i.e. a member of the 3D rotation
229/// group $SO(3)$ of special orthogonal matrices
230#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
231#[cfg_attr(feature = "derive_serdes", serde(bound = "S : MaybeSerDes"))]
232#[derive(Clone, Copy, Debug, Default, PartialEq)]
233pub struct Rotation3 <S> (LinearAuto <S, Vector3 <S>>) where
234  S : Ring + MaybeSerDes;
235
236/// Unit quaternion representing an orientation in $\mathbb{R}^3$
237#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
238#[derive(Clone, Copy, Debug, Default, PartialEq)]
239pub struct Versor <S> (Quaternion <S>) where S : num::Zero + num::One;
240
241/// Homomorphism of an affine spaces: a combination of a linear map and a
242/// translation
243#[derive(Clone, Copy, Debug, Default, PartialEq, Display)]
244#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
245#[display("({}, {})", linear_map, translation)]
246pub struct AffineMap <S, A, B, M> where
247  B : AffineSpace <S>,
248  S : Field + std::fmt::Display,
249  B::Vector : std::fmt::Display
250{
251  pub linear_map  : M,
252  pub translation : B::Vector,
253  pub _phantom    : PhantomData <A>
254}
255
256/// Affine isomorphism
257#[derive(Clone, Copy, Debug, Default, PartialEq, Display)]
258#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
259#[display("({}, {})", linear_iso, translation)]
260pub struct Affinity <S, A, B, M> where
261  A : AffineSpace <S>,
262  B : AffineSpace <S>,
263  S : Field + std::fmt::Display,
264  B::Vector : std::fmt::Display
265{
266  pub linear_iso  : LinearIso <S, A::Vector, B::Vector, M>,
267  pub translation : B::Vector,
268  pub _phantom    : PhantomData <A>
269}
270
271/// Isomorphism of projective spaces (a.k.a. homography or projective
272/// collineation)
273#[derive(Clone, Copy, Debug, Default, PartialEq, Display)]
274#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
275#[display("{}", _0)]
276pub struct Projectivity <S, V, W, P, Q, M> (
277  pub LinearIso <S, P, Q, M>,
278  pub PhantomData <(V, W)>
279);
280
281////////////////////////////////////////////////////////////////////////////////
282//  impls
283////////////////////////////////////////////////////////////////////////////////
284
285//
286//  impl Deg
287//
288impl <S : Real> Angle <S> for Deg <S> {
289  fn full_turn() -> Self {
290    Deg (S::ten() * S::nine() * S::two() * S::two())
291  }
292  fn half_turn() -> Self {
293    Deg (S::ten() * S::nine() * S::two())
294  }
295}
296impl <S : Real> Trig for Deg <S> {
297  fn sin     (self) -> Self {
298    Rad::from (self).sin().into()
299  }
300  fn sin_cos (self) -> (Self, Self) {
301    let (sin, cos) = Rad::from (self).sin_cos();
302    (sin.into(), cos.into())
303  }
304  fn cos     (self) -> Self {
305    Rad::from (self).cos().into()
306  }
307  fn tan     (self) -> Self {
308    Rad::from (self).tan().into()
309  }
310  fn asin    (self) -> Self {
311    Rad::from (self).asin().into()
312  }
313  fn acos    (self) -> Self {
314    Rad::from (self).acos().into()
315  }
316  fn atan    (self) -> Self {
317    Rad::from (self).atan().into()
318  }
319  fn atan2   (self, other : Self) -> Self {
320    Rad::from (self).atan2 (Rad::from (other)).into()
321  }
322}
323impl <S : Real> From <Rad <S>> for Deg <S> {
324  fn from (radians : Rad <S>) -> Self {
325    let full_turns = radians / Rad::full_turn();
326    Deg::full_turn() * full_turns
327  }
328}
329impl <S : Real> From <Turn <S>> for Deg <S> {
330  fn from (turns : Turn <S>) -> Self {
331    Deg (turns.0 * Deg::full_turn().0)
332  }
333}
334
335//
336//  impl Rad
337//
338impl <S : Real> Angle <S> for Rad <S> {
339  fn full_turn() -> Self {
340    Rad (S::pi() * S::two())
341  }
342}
343impl <S : Real> Trig for Rad <S> {
344  fn sin     (self) -> Self {
345    Rad (self.0.sin())
346  }
347  fn sin_cos (self) -> (Self, Self) {
348    let (sin, cos) = self.0.sin_cos();
349    (Rad (sin), Rad (cos))
350  }
351  fn cos     (self) -> Self {
352    Rad (self.0.cos())
353  }
354  fn tan     (self) -> Self {
355    Rad (self.0.tan())
356  }
357  fn asin    (self) -> Self {
358    Rad (self.0.asin())
359  }
360  fn acos    (self) -> Self {
361    Rad (self.0.acos())
362  }
363  fn atan    (self) -> Self {
364    Rad (self.0.atan())
365  }
366  fn atan2   (self, other : Self) -> Self {
367    Rad (self.0.atan2 (other.0))
368  }
369}
370impl <S : Real> From <Deg <S>> for Rad <S> {
371  fn from (degrees : Deg <S>) -> Self {
372    let full_turns = degrees / Deg::full_turn();
373    Rad::full_turn() * full_turns
374  }
375}
376impl <S : Real> From <Turn <S>> for Rad <S> {
377  fn from (turns : Turn <S>) -> Self {
378    Rad (turns.0 * Rad::full_turn().0)
379  }
380}
381
382//
383//  impl Turn
384//
385impl <S : Real> Angle <S> for Turn <S> {
386  fn full_turn() -> Self {
387    Turn (S::one())
388  }
389  fn half_turn() -> Self {
390    Turn (S::one() / S::two())
391  }
392}
393impl <S : Real> Trig for Turn <S> {
394  fn sin     (self) -> Self {
395    Rad::from (self).sin().into()
396  }
397  fn sin_cos (self) -> (Self, Self) {
398    let (sin, cos) = Rad::from (self).sin_cos();
399    (sin.into(), cos.into())
400  }
401  fn cos     (self) -> Self {
402    Rad::from (self).cos().into()
403  }
404  fn tan     (self) -> Self {
405    Rad::from (self).tan().into()
406  }
407  fn asin    (self) -> Self {
408    Rad::from (self).asin().into()
409  }
410  fn acos    (self) -> Self {
411    Rad::from (self).acos().into()
412  }
413  fn atan    (self) -> Self {
414    Rad::from (self).atan().into()
415  }
416  fn atan2   (self, other : Self) -> Self {
417    Rad::from (self).atan2 (Rad::from (other)).into()
418  }
419}
420impl <S : Real> From <Rad <S>> for Turn <S> {
421  fn from (radians : Rad <S>) -> Self {
422    Turn (radians.0 / Rad::full_turn().0)
423  }
424}
425impl <S : Real> From <Deg <S>> for Turn <S> {
426  fn from (degrees : Deg <S>) -> Self {
427    Turn (degrees.0 / Deg::full_turn().0)
428  }
429}
430
431//
432//  impl AngleWrapped
433//
434impl <S : Real> AngleWrapped <S> {
435  pub fn wrap (angle : Rad <S>) -> Self {
436    AngleWrapped (angle.wrap_unsigned())
437  }
438
439  pub fn map <F> (self, f : F) -> Self where
440    F : FnOnce (Rad <S>) -> Rad <S>
441  {
442    AngleWrapped (f (self.0).wrap_unsigned())
443  }
444}
445
446//
447//  impl AngleWrappedSigned
448//
449impl <S : Real> AngleWrappedSigned <S> {
450  pub fn wrap (angle : Rad <S>) -> Self {
451    AngleWrappedSigned (angle.wrap_signed())
452  }
453
454  pub fn map <F> (self, f : F) -> Self where
455    F : FnOnce (Rad <S>) -> Rad <S>
456  {
457    AngleWrappedSigned (f (self.0).wrap_signed())
458  }
459}
460
461//
462//  impl Angles3
463//
464
465impl <S : Real> Angles3 <S> {
466  pub const fn new (
467    yaw   : AngleWrapped <S>,
468    pitch : AngleWrapped <S>,
469    roll  : AngleWrapped <S>
470  ) -> Self {
471    Angles3 { yaw, pitch, roll }
472  }
473
474  pub fn wrap (yaw : Rad <S>, pitch : Rad <S>, roll : Rad <S>) -> Self {
475    let yaw   = AngleWrapped::wrap (yaw);
476    let pitch = AngleWrapped::wrap (pitch);
477    let roll  = AngleWrapped::wrap (roll);
478    Angles3 { yaw, pitch, roll }
479  }
480}
481
482impl <S> From <Rotation3 <S>> for Angles3 <S> where S : Real + MaybeSerDes {
483  fn from (rotation : Rotation3 <S>) -> Self {
484    let (yaw, pitch, roll) = {
485      let (yaw, pitch, roll) = rotation.intrinsic_angles();
486      ( AngleWrapped::wrap (yaw),
487        AngleWrapped::wrap (pitch),
488        AngleWrapped::wrap (roll)
489      )
490    };
491    Angles3 { yaw, pitch, roll }
492  }
493}
494
495//
496//  impl Axis2
497//
498impl Axis2 {
499  #[inline]
500  pub fn component (self) -> usize {
501    self as usize
502  }
503}
504
505//
506//  impl Axis3
507//
508impl Axis3 {
509  #[inline]
510  pub fn component (self) -> usize {
511    self as usize
512  }
513}
514
515//
516//  impl SignedAxis3
517//
518impl SignedAxis3 {
519  pub fn try_from <S : Field> (vector : &Vector3 <S>) -> Option <Self> {
520    return if *vector == [ S::one(),   S::zero(),  S::zero()].into() {
521      Some (SignedAxis3::PosX)
522    } else if *vector == [-S::one(),   S::zero(),  S::zero()].into() {
523      Some (SignedAxis3::NegX)
524    } else if *vector == [ S::zero(),  S::one(),   S::zero()].into() {
525      Some (SignedAxis3::PosY)
526    } else if *vector == [ S::zero(), -S::one(),   S::zero()].into() {
527      Some (SignedAxis3::NegY)
528    } else if *vector == [ S::zero(),  S::zero(),  S::one() ].into() {
529      Some (SignedAxis3::PosZ)
530    } else if *vector == [ S::zero(),  S::zero(), -S::one() ].into() {
531      Some (SignedAxis3::NegZ)
532    } else {
533      None
534    }
535  }
536
537  pub fn to_vec <S : Field> (self) -> Vector3 <S> {
538    match self {
539      SignedAxis3::NegX => [-S::one(),   S::zero(),  S::zero()].into(),
540      SignedAxis3::PosX => [ S::one(),   S::zero(),  S::zero()].into(),
541      SignedAxis3::NegY => [ S::zero(), -S::one(),   S::zero()].into(),
542      SignedAxis3::PosY => [ S::zero(),  S::one(),   S::zero()].into(),
543      SignedAxis3::NegZ => [ S::zero(),  S::zero(), -S::one() ].into(),
544      SignedAxis3::PosZ => [ S::zero(),  S::zero(),  S::one() ].into()
545    }
546  }
547  #[inline]
548  pub fn to_unit <S : Real> (self) -> Unit3 <S> where S : std::fmt::Debug {
549    Unit3::unchecked (self.to_vec())
550  }
551}
552
553//
554//  impl Quadrant
555//
556impl Quadrant {
557  /// Returns some 'Some (quadrant)' if the vector is strictly contained with an
558  /// quadrant and returns 'None' otherwise
559  pub fn from_vec_strict <S> (vector : &Vector2 <S>) -> Option <Quadrant> where
560    S : Ring + SignedExt
561  {
562    let sign_x = vector.x.sign();
563    let sign_y = vector.y.sign();
564    let quadrant = match (sign_x, sign_y) {
565      (Sign::Zero,          _) |
566      (         _, Sign::Zero) => return None,
567      (Sign::Positive, Sign::Positive) => Quadrant::PosPos,
568      (Sign::Negative, Sign::Positive) => Quadrant::NegPos,
569      (Sign::Positive, Sign::Negative) => Quadrant::PosNeg,
570      (Sign::Negative, Sign::Negative) => Quadrant::NegNeg
571    };
572    Some (quadrant)
573  }
574  /// Same as `from_vec_strict` for a point
575  #[inline]
576  pub fn from_point_strict <S> (point : &Point2 <S>) -> Option <Quadrant> where
577    S : Ring + SignedExt
578  {
579    Quadrant::from_vec_strict (&point.to_vector())
580  }
581}
582//  end impl Quadrant
583
584//
585//  impl Octant
586//
587impl Octant {
588  /// Returns some 'Some (octant)' if the vector is strictly contained with an
589  /// octant and returns 'None' otherwise
590  pub fn from_vec_strict <S> (vector : &Vector3 <S>) -> Option <Octant> where
591    S : Ring + SignedExt
592  {
593    let sign_x = vector.x.sign();
594    let sign_y = vector.y.sign();
595    let sign_z = vector.z.sign();
596    let octant = match (sign_x, sign_y, sign_z) {
597      (Sign::Zero,          _,          _) |
598      (         _, Sign::Zero,          _) |
599      (         _,          _, Sign::Zero) => return None,
600      (Sign::Positive, Sign::Positive, Sign::Positive) => Octant::PosPosPos,
601      (Sign::Negative, Sign::Positive, Sign::Positive) => Octant::NegPosPos,
602      (Sign::Positive, Sign::Negative, Sign::Positive) => Octant::PosNegPos,
603      (Sign::Negative, Sign::Negative, Sign::Positive) => Octant::NegNegPos,
604      (Sign::Positive, Sign::Positive, Sign::Negative) => Octant::PosPosNeg,
605      (Sign::Negative, Sign::Positive, Sign::Negative) => Octant::NegPosNeg,
606      (Sign::Positive, Sign::Negative, Sign::Negative) => Octant::PosNegNeg,
607      (Sign::Negative, Sign::Negative, Sign::Negative) => Octant::NegNegNeg
608    };
609    Some (octant)
610  }
611  /// Same as `from_vec_strict` for a point
612  #[inline]
613  pub fn from_point_strict <S> (point : &Point3 <S>) -> Option <Octant> where
614    S : Ring + SignedExt
615  {
616    Octant::from_vec_strict (&point.to_vector())
617  }
618}
619//  end impl Octant
620
621//
622//  impl Positive
623//
624impl <S : Ring> Positive <S> {
625  /// Returns 'None' when called with a negative or zero value.
626  ///
627  /// # Example
628  ///
629  /// ```
630  /// # use math_utils::Positive;
631  /// assert!(Positive::new (1.0).is_some());
632  /// assert!(Positive::new (0.0).is_none());
633  /// assert!(Positive::new (-1.0).is_none());
634  /// ```
635  pub fn new (value : S) -> Option <Self> {
636    if value > S::zero() {
637      Some (Positive (value))
638    } else {
639      None
640    }
641  }
642  /// Positive infinity
643  pub fn infinity() -> Self where S : num::float::FloatCore {
644    Positive (S::infinity())
645  }
646  /// Panics if negative or zero.
647  ///
648  /// # Panics
649  ///
650  /// ```should_panic
651  /// # use math_utils::Positive;
652  /// let x = Positive::noisy (0.0);  // panic!
653  /// ```
654  pub fn noisy (value : S) -> Self {
655    assert!(value > S::zero());
656    Positive (value)
657  }
658  /// Create a new positive number without checking the value.
659  ///
660  /// In debug builds this will fail with a debug assertion if the value is
661  /// negative:
662  ///
663  /// ```should_panic
664  /// # use math_utils::Positive;
665  /// let negative = Positive::unchecked (-1.0);  // panic!
666  /// ```
667  pub fn unchecked (value : S) -> Self {
668    debug_assert!(value > S::zero());
669    Positive (value)
670  }
671  /// Map an operation on the underlying scalar, panicking if the result is zero
672  /// or negative.
673  ///
674  /// # Example
675  ///
676  /// ```
677  /// # use math_utils::Positive;
678  /// # use math_utils::num_traits::One;
679  /// assert_eq!(*Positive::<f64>::one().map_noisy (|x| 2.0 * x), 2.0);
680  /// ```
681  ///
682  /// # Panics
683  ///
684  /// Panics of the result is negative or zero:
685  ///
686  /// ```should_panic
687  /// # use math_utils::Positive;
688  /// # use math_utils::num_traits::One;
689  /// let v = Positive::<f64>::one().map_noisy (|_| 0.0);  // panic!
690  /// ```
691  pub fn map_noisy (self, fun : fn (S) -> S) -> Self {
692    Self::noisy (fun (self.0))
693  }
694}
695impl <S : Field> num::One for Positive <S> {
696  fn one() -> Self {
697    Positive (S::one())
698  }
699}
700impl <S : Ring> std::ops::Deref for Positive <S> {
701  type Target = S;
702  fn deref (&self) -> &S {
703    &self.0
704  }
705}
706impl <S : Ring> std::ops::Mul for Positive <S> {
707  type Output = Self;
708  fn mul (self, rhs : Self) -> Self::Output {
709    Positive (self.0 * rhs.0)
710  }
711}
712impl <S : Ring> std::ops::Mul <NonNegative <S>> for Positive <S> {
713  type Output = NonNegative <S>;
714  fn mul (self, rhs : NonNegative <S>) -> Self::Output {
715    NonNegative (self.0 * *rhs)
716  }
717}
718impl <S : Field> std::ops::Div for Positive <S> {
719  type Output = Self;
720  fn div (self, rhs : Self) -> Self::Output {
721    Positive (self.0 / rhs.0)
722  }
723}
724impl <S : Ring> std::ops::Add for Positive <S> {
725  type Output = Self;
726  fn add (self, rhs : Self) -> Self::Output {
727    Positive (self.0 + rhs.0)
728  }
729}
730impl <S : Ring> std::ops::Add <NonNegative <S>> for Positive <S> {
731  type Output = Self;
732  fn add (self, rhs : NonNegative <S>) -> Self::Output {
733    Positive (self.0 + rhs.0)
734  }
735}
736//  end impl Positive
737
738//
739//  impl NonNegative
740//
741impl <S : Ring> NonNegative <S> {
742  /// Returns 'None' when called with a negative value.
743  ///
744  /// # Example
745  ///
746  /// ```
747  /// # use math_utils::NonNegative;
748  /// assert!(NonNegative::new (1.0).is_some());
749  /// assert!(NonNegative::new (0.0).is_some());
750  /// assert!(NonNegative::new (-1.0).is_none());
751  /// ```
752  pub fn new (value : S) -> Option <Self> {
753    if value >= S::zero() {
754      Some (NonNegative (value))
755    } else {
756      None
757    }
758  }
759  /// Converts negative input to absolute value.
760  ///
761  /// # Example
762  ///
763  /// ```
764  /// # use math_utils::NonNegative;
765  /// assert_eq!(*NonNegative::abs (1.0), 1.0);
766  /// assert_eq!(*NonNegative::abs (-1.0), 1.0);
767  /// ```
768  pub fn abs (value : S) -> Self {
769    NonNegative (value.abs())
770  }
771  /// Panics if negative.
772  ///
773  /// # Panics
774  ///
775  /// ```should_panic
776  /// # use math_utils::NonNegative;
777  /// let x = NonNegative::noisy (-1.0);  // panic!
778  /// ```
779  pub fn noisy (value : S) -> Self {
780    assert!(S::zero() <= value);
781    NonNegative (value)
782  }
783  /// Create a new non-negative number without checking the value.
784  ///
785  /// This method is completely unchecked for release builds.  Debug builds will
786  /// panic if the value is negative:
787  ///
788  /// ```should_panic
789  /// # use math_utils::NonNegative;
790  /// let negative = NonNegative::unchecked (-1.0);   // panic!
791  /// ```
792  pub fn unchecked (value : S) -> Self {
793    debug_assert!(value >= S::zero());
794    NonNegative (value)
795  }
796  /// Map an operation on the underlying scalar, converting negative result to
797  /// an absolute value.
798  ///
799  /// # Example
800  ///
801  /// ```
802  /// # use math_utils::NonNegative;
803  /// assert_eq!(*NonNegative::abs (1.0).map_abs (|x| -2.0 * x), 2.0);
804  /// ```
805  pub fn map_abs (self, fun : fn (S) -> S) -> Self {
806    Self::abs (fun (self.0))
807  }
808  /// Map an operation on the underlying scalar, panicking if the result is
809  /// negative
810  ///
811  /// # Example
812  ///
813  /// ```
814  /// # use math_utils::NonNegative;
815  /// assert_eq!(*NonNegative::abs (1.0).map_noisy (|x| 2.0 * x), 2.0);
816  /// ```
817  ///
818  /// # Panics
819  ///
820  /// Panics of the result is negative:
821  ///
822  /// ```should_panic
823  /// # use math_utils::NonNegative;
824  /// let v = NonNegative::abs (1.0).map_noisy (|x| -1.0 * x);  // panic!
825  /// ```
826  pub fn map_noisy (self, fun : fn (S) -> S) -> Self {
827    Self::noisy (fun (self.0))
828  }
829}
830impl <S : Ring> From <Positive <S>> for NonNegative <S> {
831  fn from (positive : Positive <S>) -> Self {
832    NonNegative (*positive)
833  }
834}
835impl <S : Ring> num::Zero for NonNegative <S> {
836  fn zero() -> Self {
837    NonNegative (S::zero())
838  }
839  fn is_zero (&self) -> bool {
840    self.0.is_zero()
841  }
842}
843impl <S : Field> num::One for NonNegative <S> {
844  fn one() -> Self {
845    NonNegative (S::one())
846  }
847}
848impl <S : Ring> std::ops::Deref for NonNegative <S> {
849  type Target = S;
850  fn deref (&self) -> &S {
851    &self.0
852  }
853}
854impl <S : Ring> std::ops::Mul for NonNegative <S> {
855  type Output = Self;
856  fn mul (self, rhs : Self) -> Self::Output {
857    NonNegative (self.0 * rhs.0)
858  }
859}
860impl <S : Ring> std::ops::Mul <Positive <S>> for NonNegative <S> {
861  type Output = Self;
862  fn mul (self, rhs : Positive <S>) -> Self::Output {
863    NonNegative (self.0 * rhs.0)
864  }
865}
866impl <S : Field> std::ops::Div for NonNegative <S> {
867  type Output = Self;
868  fn div (self, rhs : Self) -> Self::Output {
869    NonNegative (self.0 / rhs.0)
870  }
871}
872impl <S : Ring> std::ops::Add for NonNegative <S> {
873  type Output = Self;
874  fn add (self, rhs : Self) -> Self::Output {
875    NonNegative (self.0 + rhs.0)
876  }
877}
878//  end impl NonNegative
879
880//
881//  impl NonZero
882//
883impl <S : Field> NonZero <S> {
884  /// Returns 'None' when called with zero
885  ///
886  /// # Example
887  ///
888  /// ```
889  /// # use math_utils::NonZero;
890  /// assert!(NonZero::new (2.0).is_some());
891  /// assert!(NonZero::new (0.0).is_none());
892  /// assert!(NonZero::new (-2.0).is_some());
893  /// ```
894  #[inline]
895  pub fn new (value : S) -> Option <Self> {
896    if S::zero() != value {
897      Some (NonZero (value))
898    } else {
899      None
900    }
901  }
902  /// Panics if called with zero
903  ///
904  /// # Panics
905  ///
906  /// ```should_panic
907  /// # use math_utils::NonZero;
908  /// let x = NonZero::noisy (0.0);  // panic!
909  /// ```
910  #[inline]
911  pub fn noisy (value : S) -> Self {
912    assert!(S::zero() != value);
913    NonZero (value)
914  }
915  /// Map an operation on the underlying scalar, panicking if the result is
916  /// zero
917  ///
918  /// # Example
919  ///
920  /// ```
921  /// # use math_utils::NonZero;
922  /// # use math_utils::num_traits::One;
923  /// assert_eq!(*NonZero::<f64>::one().map_noisy (|x| 0.5 * x), 0.5);
924  /// ```
925  ///
926  /// # Panics
927  ///
928  /// Panics of the result is zero
929  ///
930  /// ```should_panic
931  /// # use math_utils::NonZero;
932  /// # use math_utils::num_traits::One;
933  /// let v = NonZero::<f64>::one().map_noisy (|x| 0.0 * x);  // panic!
934  /// ```
935  #[inline]
936  pub fn map_noisy (self, fun : fn (S) -> S) -> Self {
937    Self::noisy (fun (self.0))
938  }
939}
940impl <S : Field> num::One for NonZero <S> {
941  fn one() -> Self {
942    NonZero (S::one())
943  }
944}
945impl <S : Field> std::ops::Deref for NonZero <S> {
946  type Target = S;
947  fn deref (&self) -> &S {
948    &self.0
949  }
950}
951impl <S : Field> std::ops::Mul for NonZero <S> {
952  type Output = Self;
953  fn mul (self, rhs : Self) -> Self::Output {
954    NonZero (self.0 * rhs.0)
955  }
956}
957impl <S : Field> Eq  for NonZero <S> { }
958//  end impl NonZero
959
960//
961//  impl Normalized
962//
963impl <S : Field> Normalized <S> {
964  // NOTE: num::Zero requires std::ops::Add which Normalized does not implement
965  #[inline]
966  pub fn zero() -> Self {
967    Normalized (S::zero())
968  }
969  #[inline]
970  pub fn is_zero (&self) -> bool {
971    self.0.is_zero()
972  }
973  /// Returns 'None' when called with a value outside of the closed unit
974  /// interval \[0,1\].
975  ///
976  /// # Example
977  ///
978  /// ```
979  /// # use math_utils::Normalized;
980  /// assert!(Normalized::new (2.0).is_none());
981  /// assert!(Normalized::new (1.0).is_some());
982  /// assert!(Normalized::new (0.5).is_some());
983  /// assert!(Normalized::new (0.0).is_some());
984  /// assert!(Normalized::new (-1.0).is_none());
985  /// ```
986  #[inline]
987  pub fn new (value : S) -> Option <Self> {
988    if S::zero() <= value && value <= S::one() {
989      Some (Normalized (value))
990    } else {
991      None
992    }
993  }
994  /// Clamps to the closed unit interval \[0,1\]
995  ///
996  /// # Example
997  ///
998  /// ```
999  /// # use math_utils::Normalized;
1000  /// assert_eq!(*Normalized::clamp (2.0), 1.0);
1001  /// assert_eq!(*Normalized::clamp (-1.0), 0.0);
1002  /// ```
1003  #[inline]
1004  pub fn clamp (value : S) -> Self {
1005    let value = S::max (S::zero(), S::min (value, S::one()));
1006    Normalized (value)
1007  }
1008  /// Panics if outside the closed unit interval \[0,1\]
1009  ///
1010  /// # Panics
1011  ///
1012  /// ```should_panic
1013  /// # use math_utils::Normalized;
1014  /// let x = Normalized::noisy (-1.0);  // panic!
1015  /// ```
1016  ///
1017  /// ```should_panic
1018  /// # use math_utils::Normalized;
1019  /// let x = Normalized::noisy (2.0);  // panic!
1020  /// ```
1021  #[inline]
1022  pub fn noisy (value : S) -> Self {
1023    assert!(value <= S::one());
1024    assert!(S::zero() <= value);
1025    Normalized (value)
1026  }
1027  /// Map an operation on the underlying scalar, clamping results to the closed
1028  /// unit interval \[0,1\].
1029  ///
1030  /// # Example
1031  ///
1032  /// ```
1033  /// # use math_utils::Normalized;
1034  /// # use math_utils::num_traits::One;
1035  /// assert_eq!(*Normalized::<f64>::one().map_clamp (|x|  2.0 * x), 1.0);
1036  /// assert_eq!(*Normalized::<f64>::one().map_clamp (|x| -2.0 * x), 0.0);
1037  /// ```
1038  #[inline]
1039  pub fn map_clamp (self, fun : fn (S) -> S) -> Self {
1040    Self::clamp (fun (self.0))
1041  }
1042  /// Map an operation on the underlying scalar, panicking if the result is
1043  /// outside the unit interval \[0,1\]
1044  ///
1045  /// # Example
1046  ///
1047  /// ```
1048  /// # use math_utils::Normalized;
1049  /// # use math_utils::num_traits::One;
1050  /// assert_eq!(*Normalized::<f64>::one().map_noisy (|x| 0.5 * x), 0.5);
1051  /// ```
1052  ///
1053  /// # Panics
1054  ///
1055  /// Panics of the result is outside \[0,1\]:
1056  ///
1057  /// ```should_panic
1058  /// # use math_utils::Normalized;
1059  /// # use math_utils::num_traits::One;
1060  /// let v = Normalized::<f64>::one().map_noisy (|x| -1.0 * x);  // panic!
1061  /// ```
1062  ///
1063  /// ```should_panic
1064  /// # use math_utils::Normalized;
1065  /// # use math_utils::num_traits::One;
1066  /// let v = Normalized::<f64>::one().map_noisy (|x|  2.0 * x);  // panic!
1067  /// ```
1068  #[inline]
1069  pub fn map_noisy (self, fun : fn (S) -> S) -> Self {
1070    Self::noisy (fun (self.0))
1071  }
1072}
1073impl <S : Field> num::One for Normalized <S> {
1074  fn one() -> Self {
1075    Normalized (S::one())
1076  }
1077}
1078impl <S : Field> std::ops::Deref for Normalized <S> {
1079  type Target = S;
1080  fn deref (&self) -> &S {
1081    &self.0
1082  }
1083}
1084impl <S : Field> std::ops::Mul for Normalized <S> {
1085  type Output = Self;
1086  fn mul (self, rhs : Self) -> Self::Output {
1087    Normalized (self.0 * rhs.0)
1088  }
1089}
1090impl <S : Field> Eq  for Normalized <S> { }
1091impl <S : Field> Ord for Normalized <S> {
1092  fn cmp (&self, rhs : &Self) -> std::cmp::Ordering {
1093    // safe to unwrap: normalized values are never NaN
1094    self.partial_cmp (rhs).unwrap()
1095  }
1096}
1097//  end impl Normalized
1098
1099//
1100//  impl NormalSigned
1101//
1102impl <S : Field> NormalSigned <S> {
1103  // NOTE: num::Zero requires std::ops::Add which Normalized does not implement
1104  #[inline]
1105  pub fn zero() -> Self {
1106    NormalSigned (S::zero())
1107  }
1108  #[inline]
1109  pub fn is_zero (&self) -> bool {
1110    self.0.is_zero()
1111  }
1112  /// Returns 'None' when called with a value outside of the closed interval
1113  /// \[-1,1\].
1114  ///
1115  /// # Example
1116  ///
1117  /// ```
1118  /// # use math_utils::NormalSigned;
1119  /// assert!(NormalSigned::new (2.0).is_none());
1120  /// assert!(NormalSigned::new (1.0).is_some());
1121  /// assert!(NormalSigned::new (0.5).is_some());
1122  /// assert!(NormalSigned::new (0.0).is_some());
1123  /// assert!(NormalSigned::new (-1.0).is_some());
1124  /// assert!(NormalSigned::new (-2.0).is_none());
1125  /// ```
1126  #[inline]
1127  pub fn new (value : S) -> Option <Self> {
1128    if -S::one() <= value && value <= S::one() {
1129      Some (NormalSigned (value))
1130    } else {
1131      None
1132    }
1133  }
1134  /// Clamps to the closed interval [-1,1]
1135  ///
1136  /// # Example
1137  ///
1138  /// ```
1139  /// # use math_utils::NormalSigned;
1140  /// assert_eq!(*NormalSigned::clamp (2.0), 1.0);
1141  /// assert_eq!(*NormalSigned::clamp (-2.0), -1.0);
1142  /// ```
1143  #[inline]
1144  pub fn clamp (value : S) -> Self {
1145    let value = S::max (-S::one(), S::min (value, S::one()));
1146    NormalSigned (value)
1147  }
1148  /// Panics if outside the closed interval [-1,1]
1149  ///
1150  /// # Panics
1151  ///
1152  /// ```should_panic
1153  /// # use math_utils::NormalSigned;
1154  /// let x = NormalSigned::noisy (-2.0);   // panic!
1155  /// ```
1156  ///
1157  /// ```should_panic
1158  /// # use math_utils::NormalSigned;
1159  /// let x = NormalSigned::noisy (2.0);    // panic!
1160  /// ```
1161  #[inline]
1162  pub fn noisy (value : S) -> Self {
1163    assert!(value <= S::one());
1164    assert!(-S::one() <= value);
1165    NormalSigned (value)
1166  }
1167  /// Map an operation on the underlying scalar, clamping results to the closed
1168  /// interval [-1,1].
1169  ///
1170  /// # Example
1171  ///
1172  /// ```
1173  /// # use math_utils::NormalSigned;
1174  /// # use math_utils::num_traits::One;
1175  /// assert_eq!(*NormalSigned::<f64>::one().map_clamp (|x|  2.0 * x),  1.0);
1176  /// assert_eq!(*NormalSigned::<f64>::one().map_clamp (|x| -2.0 * x), -1.0);
1177  /// ```
1178  #[inline]
1179  pub fn map_clamp (self, fun : fn (S) -> S) -> Self {
1180    Self::clamp (fun (self.0))
1181  }
1182  /// Map an operation on the underlying scalar, panicking if the result
1183  /// is outside the interval [-1, 1]
1184  ///
1185  /// # Example
1186  ///
1187  /// ```
1188  /// # use math_utils::NormalSigned;
1189  /// # use math_utils::num_traits::One;
1190  /// assert_eq!(*NormalSigned::<f64>::one().map_noisy (|x| 0.5 * x), 0.5);
1191  /// ```
1192  ///
1193  /// # Panics
1194  ///
1195  /// Panics of the result is outside [-1, 1]:
1196  ///
1197  /// ```should_panic
1198  /// # use math_utils::NormalSigned;
1199  /// # use math_utils::num_traits::One;
1200  /// let v = NormalSigned::<f64>::one().map_noisy (|x| -2.0 * x);  // panic!
1201  /// ```
1202  ///
1203  /// ```should_panic
1204  /// # use math_utils::NormalSigned;
1205  /// # use math_utils::num_traits::One;
1206  /// let v = NormalSigned::<f64>::one().map_noisy (|x|  2.0 * x);  // panic!
1207  /// ```
1208  #[inline]
1209  pub fn map_noisy (self, fun : fn (S) -> S) -> Self {
1210    Self::noisy (fun (self.0))
1211  }
1212}
1213impl <S : Field> From <Normalized <S>> for NormalSigned <S> {
1214  fn from (Normalized (value) : Normalized <S>) -> Self {
1215    debug_assert!(S::zero() <= value);
1216    debug_assert!(value <= S::one());
1217    NormalSigned (value)
1218  }
1219}
1220impl <S : Field> num::One for NormalSigned <S> {
1221  fn one() -> Self {
1222    NormalSigned (S::one())
1223  }
1224}
1225impl <S : Field> std::ops::Deref for NormalSigned <S> {
1226  type Target = S;
1227  fn deref (&self) -> &S {
1228    &self.0
1229  }
1230}
1231impl <S : Field> std::ops::Mul for NormalSigned <S> {
1232  type Output = Self;
1233  fn mul (self, rhs : Self) -> Self::Output {
1234    NormalSigned (self.0 * rhs.0)
1235  }
1236}
1237impl <S : Field> Eq  for NormalSigned <S> { }
1238impl <S : Field> Ord for NormalSigned <S> {
1239  fn cmp (&self, rhs : &Self) -> std::cmp::Ordering {
1240    // safe to unwrap: normalized values are never NaN
1241    self.partial_cmp (rhs).unwrap()
1242  }
1243}
1244impl <S : Field> std::ops::Neg for NormalSigned <S> {
1245  type Output = Self;
1246  fn neg (self) -> Self::Output {
1247    NormalSigned (-self.0)
1248  }
1249}
1250//  end impl NormalSigned
1251
1252//
1253//  impl Rotation2
1254//
1255impl <S> Rotation2 <S> where S : Ring + MaybeSerDes {
1256  /// Identity rotation
1257  pub fn identity() -> Self {
1258    use num::One;
1259    Self::one()
1260  }
1261  /// Returns `None` if called with a matrix that is not orthonormal with
1262  /// determinant +1.
1263  ///
1264  /// This method checks whether `mat * mat^T == I` and
1265  /// `mat.determinant() == 1`.
1266  pub fn new (mat : Matrix2 <S>) -> Option <Self> {
1267    let transform = LinearAuto (LinearIso::new (mat)?);
1268    if !transform.is_rotation() {
1269      None
1270    } else {
1271      Some (Rotation2 (transform))
1272    }
1273  }
1274  /// Returns `None` if called with a matrix that is not orthonormal with
1275  /// determinant +1.
1276  ///
1277  /// This method checks whether `mat * mat^T == I` and
1278  /// `mat.determinant() == 1` (approximately using relative equality).
1279  pub fn new_approx (mat : Matrix2 <S>) -> Option <Self> where
1280    S : approx::RelativeEq <Epsilon=S>
1281  {
1282    let four         = S::one() + S::one() + S::one() + S::one();
1283    let epsilon      = S::default_epsilon() * four;
1284    let max_relative = S::default_max_relative() * four;
1285    if approx::relative_ne!(mat * mat.transposed(), Matrix2::identity(),
1286      max_relative=max_relative, epsilon=epsilon
1287    ) || approx::relative_ne!(mat.determinant(), S::one(),
1288      max_relative=max_relative
1289    ) {
1290      None
1291    } else {
1292      Some (Rotation2 (LinearAuto (LinearIso (mat, PhantomData::default()))))
1293    }
1294  }
1295  /// Create a rotation for the given angle
1296  pub fn from_angle (angle : Rad <S>) -> Self where S : num::real::Real {
1297    Rotation2 (LinearAuto (LinearIso (
1298      Matrix2::rotation_z (angle.0), PhantomData::default())))
1299  }
1300  /// Panic if the given matrix is not orthogonal with determinant +1.
1301  ///
1302  /// This method checks whether `mat * mat^T == I` and
1303  /// `mat.determinant() == 1`.
1304  pub fn noisy (mat : Matrix2 <S>) -> Self where S : std::fmt::Debug {
1305    assert_eq!(mat * mat.transposed(), Matrix2::identity());
1306    assert_eq!(mat.determinant(), S::one());
1307    Rotation2 (LinearAuto (LinearIso (mat, PhantomData::default())))
1308  }
1309  /// Panic if the given matrix is not orthogonal with determinant +1.
1310  ///
1311  /// This method checks whether `mat * mat^T == I` and
1312  /// `mat.determinant() == 1` (approximately using relative equality).
1313  pub fn noisy_approx (mat : Matrix2 <S>) -> Self where
1314    S : approx::RelativeEq <Epsilon=S> + std::fmt::Debug
1315  {
1316    let four         = S::one() + S::one() + S::one() + S::one();
1317    let epsilon      = S::default_epsilon() * four;
1318    let max_relative = S::default_max_relative() * four;
1319    approx::assert_relative_eq!(mat * mat.transposed(), Matrix2::identity(),
1320      epsilon=epsilon, max_relative=max_relative);
1321    approx::assert_relative_eq!(mat.determinant(), S::one(),
1322      max_relative=max_relative);
1323    Rotation2 (LinearAuto (LinearIso (mat, PhantomData::default())))
1324  }
1325  /// It is a debug panic if the given matrix is not orthogonal with determinant
1326  /// +1.
1327  ///
1328  /// This method checks whether `mat * mat^T == I` and
1329  /// `mat.determinant() == 1`.
1330  pub fn unchecked (mat : Matrix2 <S>) -> Self where S : std::fmt::Debug {
1331    debug_assert!(mat * mat.transposed() == Matrix2::identity());
1332    debug_assert!(mat.determinant() == S::one());
1333    Rotation2 (LinearAuto (LinearIso (mat, PhantomData::default())))
1334  }
1335  /// It is a debug panic if the given matrix is not orthogonal with determinant
1336  /// +1.
1337  ///
1338  /// This method checks whether `mat * mat^T == I` and
1339  /// `mat.determinant() == 1` (approximately using relative equality).
1340  pub fn unchecked_approx (mat : Matrix2 <S>) -> Self where
1341    S : approx::RelativeEq <Epsilon=S> + std::fmt::Debug
1342  {
1343    if cfg!(debug_assertions) {
1344      let four         = S::one() + S::one() + S::one() + S::one();
1345      let epsilon      = S::default_epsilon() * four;
1346      let max_relative = S::default_max_relative() * four;
1347      approx::assert_relative_eq!(mat * mat.transposed(), Matrix2::identity(),
1348        max_relative=max_relative, epsilon=epsilon);
1349      approx::assert_relative_eq!(mat.determinant(), S::one(),
1350        max_relative=max_relative);
1351    }
1352    Rotation2 (LinearAuto (LinearIso (mat, PhantomData::default())))
1353  }
1354}
1355impl <S> std::ops::Deref for Rotation2 <S> where S : Ring + MaybeSerDes {
1356  type Target = Matrix2 <S>;
1357  fn deref (&self) -> &Self::Target {
1358    &self.0
1359  }
1360}
1361impl <S> MultiplicativeGroup for Rotation2 <S> where
1362  S : Ring + MaybeSerDes
1363{ }
1364impl <S> MultiplicativeMonoid for Rotation2 <S> where
1365  S : Ring + MaybeSerDes
1366{ }
1367impl <S> num::Inv for Rotation2 <S> where S : Ring + MaybeSerDes {
1368  type Output = Self;
1369  fn inv (self) -> Self::Output {
1370    Rotation2 (LinearAuto (LinearIso (
1371      self.0.0.0.transpose(), PhantomData::default()
1372    )))
1373  }
1374}
1375impl <S> std::ops::Mul <Vector2 <S>> for Rotation2 <S> where
1376  S : Ring + MaybeSerDes
1377{
1378  type Output = Vector2 <S>;
1379  fn mul (self, rhs : Vector2 <S>) -> Self::Output {
1380    self.0 * rhs
1381  }
1382}
1383impl <S> std::ops::Mul <Rotation2 <S>> for Vector2 <S> where
1384  S : Ring + MaybeSerDes
1385{
1386  type Output = Vector2 <S>;
1387  fn mul (self, rhs : Rotation2 <S>) -> Self::Output {
1388    self * rhs.0
1389  }
1390}
1391impl <S> std::ops::Mul for Rotation2 <S> where S : Ring + MaybeSerDes {
1392  type Output = Self;
1393  fn mul (self, rhs : Self) -> Self::Output {
1394    Rotation2 (self.0 * rhs.0)
1395  }
1396}
1397impl <S> std::ops::MulAssign <Self> for Rotation2 <S> where
1398  S : Ring + MaybeSerDes
1399{
1400  fn mul_assign (&mut self, rhs : Self) {
1401    self.0 *= rhs.0
1402  }
1403}
1404impl <S> std::ops::Div for Rotation2 <S> where S : Ring + MaybeSerDes {
1405  type Output = Self;
1406  fn div (self, rhs : Self) -> Self::Output {
1407    use num::Inv;
1408    self * rhs.inv()
1409  }
1410}
1411impl <S> std::ops::DivAssign <Self> for Rotation2 <S> where
1412  S : Ring + MaybeSerDes
1413{
1414  fn div_assign (&mut self, rhs : Self) {
1415    use num::Inv;
1416    *self *= rhs.inv()
1417  }
1418}
1419impl <S> num::One for Rotation2 <S> where
1420  S : Ring + MaybeSerDes + num::Zero + num::One
1421{
1422  fn one() -> Self {
1423    Rotation2 (LinearAuto (
1424      LinearIso (Matrix2::identity(), PhantomData::default())))
1425  }
1426}
1427
1428//
1429//  impl Rotation3
1430//
1431impl <S> Rotation3 <S> where S : Ring + MaybeSerDes {
1432  /// Identity rotation
1433  pub fn identity() -> Self {
1434    use num::One;
1435    Self::one()
1436  }
1437  /// Construct a rotation around the X axis.
1438  ///
1439  /// Positive angles are counter-clockwise.
1440  pub fn from_angle_x (angle : Rad <S>) -> Self where S : num::real::Real {
1441    Rotation3 (LinearAuto (LinearIso (
1442      Matrix3::rotation_x (angle.0), PhantomData::default())))
1443  }
1444  /// Construct a rotation around the Y axis
1445  ///
1446  /// Positive angles are counter-clockwise.
1447  pub fn from_angle_y (angle : Rad <S>) -> Self where S : num::real::Real {
1448    Rotation3 (LinearAuto (LinearIso (
1449      Matrix3::rotation_y (angle.0), PhantomData::default())))
1450  }
1451  /// Construct a rotation around the Z axis
1452  ///
1453  /// Positive angles are counter-clockwise.
1454  pub fn from_angle_z (angle : Rad <S>) -> Self where S : num::real::Real {
1455    Rotation3 (LinearAuto (LinearIso (
1456      Matrix3::rotation_z (angle.0), PhantomData::default())))
1457  }
1458  /// Construct a rotation from intrinsic ZX'Y'' Euler angles:
1459  ///
1460  /// - yaw: rotation around Z axis
1461  /// - pitch: rotation around X' axis
1462  /// - roll: rotation around Y'' axis
1463  pub fn from_angles_intrinsic (yaw : Rad <S>, pitch : Rad <S>, roll : Rad <S>)
1464    -> Self where S : num::real::Real
1465  {
1466    let rotation1 = Rotation3::from_angle_z (yaw);
1467    let rotation2 =
1468      Rotation3::from_axis_angle (rotation1.cols.x.into(), pitch) * rotation1;
1469    Rotation3::from_axis_angle (rotation2.cols.y.into(), roll) * rotation2
1470  }
1471  /// Construct a rotation around the given axis vector with the given angle
1472  pub fn from_axis_angle (axis : Vector3 <S>, angle : Rad <S>) -> Self where
1473    S : num::real::Real
1474  {
1475    Rotation3 (LinearAuto (LinearIso (
1476      Matrix3::rotation_3d (angle.0, axis), PhantomData::default())))
1477  }
1478  /// Construct an orthonormal matrix from a set of linearly-independent vectors
1479  /// using the Gram-Schmidt process
1480  pub fn orthonormalize (v1 : Vector3 <S>, v2 : Vector3 <S>, v3 : Vector3 <S>)
1481    -> Option <Self> where S : Field + Sqrt
1482  {
1483    if Matrix3::from_col_arrays ([v1, v2, v3].map (Vector3::into_array))
1484      .determinant() == S::zero()
1485    {
1486      None
1487    } else {
1488      let project =
1489        |u : Vector3 <S>, v : Vector3 <S>| u * (u.dot (v) / u.self_dot());
1490      let u1 = v1;
1491      let u2 = v2 - project (u1, v2);
1492      let u3 = v3 - project (u1, v3) - project (u2, v3);
1493      Some (Rotation3 (LinearAuto (LinearIso (Matrix3::from_col_arrays ([
1494        u1.normalize().into_array(),
1495        u2.normalize().into_array(),
1496        u3.normalize().into_array()
1497      ]), PhantomData::default()))))
1498    }
1499  }
1500
1501  /// Returns a rotation with zero roll and oriented towards the target point.
1502  ///
1503  /// Returns the identity rotation if `point` is the origin.
1504  pub fn look_at (point : Point3 <S>) -> Self where
1505    S : num::Float + num::FloatConst + approx::RelativeEq <Epsilon=S> +
1506      std::fmt::Debug
1507  {
1508    if point == Point::origin() {
1509      Self::identity()
1510    } else {
1511      use num::Zero;
1512      let forward = point.0.normalized();
1513      let right   = {
1514        let projected = forward.with_z (S::zero());
1515        if !projected.is_zero() {
1516          Self::from_angle_z (-Rad (S::FRAC_PI_2())) * projected.normalized()
1517        } else {
1518          Vector3::unit_x()
1519        }
1520      };
1521      let up      = right.cross (forward);
1522      let mat     = Matrix3::from_col_arrays (
1523        [right, forward, up].map (Vector3::into_array));
1524      Self::noisy_approx (mat)
1525    }
1526  }
1527
1528  /// Returns `None` if called with a matrix that is not orthonormal with
1529  /// determinant +1.
1530  ///
1531  /// This method checks whether `mat * mat^T == I` and
1532  /// `mat.determinant() == 1`.
1533  pub fn new (mat : Matrix3 <S>) -> Option <Self> {
1534    if mat * mat.transposed() != Matrix3::identity() ||
1535      mat.determinant() != S::one()
1536    {
1537      None
1538    } else {
1539      Some (Rotation3 (LinearAuto (LinearIso (mat, PhantomData::default()))))
1540    }
1541  }
1542  /// Returns `None` if called with a matrix that is not orthonormal with
1543  /// determinant +1.
1544  ///
1545  /// This method checks whether `mat * mat^T == I` and
1546  /// `mat.determinant() == 1` (approximately using relative equality).
1547  pub fn new_approx (mat : Matrix3 <S>) -> Option <Self> where
1548    S : approx::RelativeEq <Epsilon=S>
1549  {
1550    let four         = S::one() + S::one() + S::one() + S::one();
1551    let epsilon      = S::default_epsilon() * four;
1552    let max_relative = S::default_max_relative() * four;
1553    if approx::relative_ne!(mat * mat.transposed(), Matrix3::identity(),
1554      max_relative=max_relative, epsilon=epsilon
1555    ) || approx::relative_ne!(mat.determinant(), S::one(),
1556      max_relative=max_relative
1557    ) {
1558      None
1559    } else {
1560      Some (Rotation3 (LinearAuto (LinearIso (mat, PhantomData::default()))))
1561    }
1562  }
1563  /// Panic if the given matrix is not orthogonal with determinant +1.
1564  ///
1565  /// This method checks whether `mat * mat^T == I` and
1566  /// `mat.determinant() == 1`.
1567  pub fn noisy (mat : Matrix3 <S>) -> Self {
1568    assert!(mat * mat.transposed() == Matrix3::identity());
1569    assert!(mat.determinant() == S::one());
1570    Rotation3 (LinearAuto (LinearIso (mat, PhantomData::default())))
1571  }
1572  /// Panic if the given matrix is not orthogonal with determinant +1.
1573  ///
1574  /// This method checks whether `mat * mat^T == I` and
1575  /// `mat.determinant() == 1` (approximately using relative equality).
1576  pub fn noisy_approx (mat : Matrix3 <S>) -> Self where
1577    S : approx::RelativeEq <Epsilon=S> + std::fmt::Debug
1578  {
1579    let four         = S::one() + S::one() + S::one() + S::one();
1580    let eight        = four + S::one() + S::one() + S::one() + S::one();
1581    let epsilon      = S::default_epsilon() * four;
1582    let max_relative = S::default_max_relative() * eight;
1583    approx::assert_relative_eq!(mat * mat.transposed(), Matrix3::identity(),
1584      max_relative=max_relative, epsilon=epsilon);
1585    approx::assert_relative_eq!(mat.determinant(), S::one(),
1586      max_relative=max_relative);
1587    Rotation3 (LinearAuto (LinearIso (mat, PhantomData::default())))
1588  }
1589  /// It is a debug panic if the given matrix is not orthogonal with determinant
1590  /// +1.
1591  ///
1592  /// This method checks whether `mat * mat^T == I` and
1593  /// `mat.determinant() == 1`.
1594  pub fn unchecked (mat : Matrix3 <S>) -> Self where S : std::fmt::Debug {
1595    debug_assert!(mat * mat.transposed() == Matrix3::identity());
1596    debug_assert!(mat.determinant() == S::one());
1597    Rotation3 (LinearAuto (LinearIso (mat, PhantomData::default())))
1598  }
1599  /// It is a debug panic if the given matrix is not orthogonal with determinant
1600  /// +1.
1601  ///
1602  /// This method checks whether `mat * mat^T == I` and
1603  /// `mat.determinant() == 1` (approximately using relative equality).
1604  pub fn unchecked_approx (mat : Matrix3 <S>) -> Self where
1605    S : approx::RelativeEq <Epsilon=S> + std::fmt::Debug
1606  {
1607    if cfg!(debug_assertions) {
1608      let four         = S::one() + S::one() + S::one() + S::one();
1609      let epsilon      = S::default_epsilon() * four;
1610      let max_relative = S::default_max_relative() * four;
1611      approx::assert_relative_eq!(mat * mat.transposed(), Matrix3::identity(),
1612        max_relative=max_relative, epsilon=epsilon);
1613      approx::assert_relative_eq!(mat.determinant(), S::one(),
1614        max_relative=max_relative);
1615    }
1616    Rotation3 (LinearAuto (LinearIso (mat, PhantomData::default())))
1617  }
1618  /// Return intrinsic yaw (Z), pitch (X'), roll (Y'') angles.
1619  ///
1620  /// NOTE: this function returns the raw output of the `atan2` operations used
1621  /// to compute the angles. This function returns values in the range
1622  /// `[-\pi, \pi]`.
1623  pub fn intrinsic_angles (&self) -> (Rad <S>, Rad <S>, Rad <S>) where S : Real {
1624    let cols  = &self.cols;
1625    let yaw   = Rad (S::atan2 (-cols.y.x, cols.y.y));
1626    let pitch = Rad (
1627      S::atan2 (cols.y.z, S::sqrt (S::one() - cols.y.z * cols.y.z))
1628    );
1629    let roll  = Rad (S::atan2 (-cols.x.z, cols.z.z));
1630
1631    (yaw, pitch, roll)
1632  }
1633
1634  /// Convert to versor (unit quaternion) representation.
1635  ///
1636  /// <https://stackoverflow.com/a/63745757>
1637  pub fn versor (self) -> Versor <S> where
1638    S : Real + MaybeSerDes + num::real::Real + approx::RelativeEq <Epsilon=S>
1639  {
1640    let diagonal = self.diagonal();
1641    let t     = diagonal.sum();
1642    let m     = MinMax::max (MinMax::max (MinMax::max (
1643      diagonal.x, diagonal.y), diagonal.z), t);
1644    let qmax  = (S::one() / S::two()) * Sqrt::sqrt (S::one() - t + S::two() * m);
1645    let qmax4_recip = (S::four() * qmax).recip();
1646    let [qx, qy, qz, qw] : [S; 4];
1647    let cols = self.cols;
1648    if m == diagonal.x {
1649      qx = qmax;
1650      qy = qmax4_recip * (cols.x.y + cols.y.x);
1651      qz = qmax4_recip * (cols.x.z + cols.z.x);
1652      qw = -qmax4_recip * (cols.z.y - cols.y.z);
1653    } else if m == diagonal.y {
1654      qx = qmax4_recip * (cols.x.y + cols.y.x);
1655      qy = qmax;
1656      qz = qmax4_recip * (cols.y.z + cols.z.y);
1657      qw = -qmax4_recip * (cols.x.z - cols.z.x);
1658    } else if m == diagonal.z {
1659      qx = qmax4_recip * (cols.x.z + cols.z.x);
1660      qy = qmax4_recip * (cols.y.z + cols.z.y);
1661      qz = qmax;
1662      qw = -qmax4_recip * (cols.y.x - cols.x.y);
1663    } else {
1664      qx = -qmax4_recip * (cols.z.y - cols.y.z);
1665      qy = -qmax4_recip * (cols.x.z - cols.z.x);
1666      qz = -qmax4_recip * (cols.y.x - cols.x.y);
1667      qw = qmax;
1668    }
1669    let quat = Quaternion::from_xyzw (qx, qy, qz, qw);
1670    Versor::unchecked_approx (quat)
1671  }
1672}
1673impl <S> std::ops::Deref for Rotation3 <S> where S : Ring + MaybeSerDes {
1674  type Target = Matrix3 <S>;
1675  fn deref (&self) -> &Self::Target {
1676    &self.0
1677  }
1678}
1679impl <S> MultiplicativeGroup  for Rotation3 <S> where S : Ring + MaybeSerDes { }
1680impl <S> MultiplicativeMonoid for Rotation3 <S> where S : Ring + MaybeSerDes { }
1681impl <S> num::Inv for Rotation3 <S> where S : Ring + MaybeSerDes {
1682  type Output = Self;
1683  fn inv (self) -> Self::Output {
1684    Rotation3 (LinearAuto (LinearIso (
1685      self.0.0.0.transpose(), PhantomData::default()
1686    )))
1687  }
1688}
1689impl <S> std::ops::Mul <Vector3 <S>> for Rotation3 <S> where
1690  S : Ring + MaybeSerDes
1691{
1692  type Output = Vector3 <S>;
1693  fn mul (self, rhs : Vector3 <S>) -> Self::Output {
1694    self.0 * rhs
1695  }
1696}
1697impl <S> std::ops::Mul <Rotation3 <S>> for Vector3 <S> where
1698  S : Ring + MaybeSerDes
1699{
1700  type Output = Vector3 <S>;
1701  fn mul (self, rhs : Rotation3 <S>) -> Self::Output {
1702    self * rhs.0
1703  }
1704}
1705impl <S> std::ops::Mul for Rotation3 <S> where S : Ring + MaybeSerDes {
1706  type Output = Self;
1707  fn mul (self, rhs : Self) -> Self::Output {
1708    Rotation3 (self.0 * rhs.0)
1709  }
1710}
1711impl <S> std::ops::MulAssign <Self> for Rotation3 <S> where
1712  S : Ring + MaybeSerDes
1713{
1714  fn mul_assign (&mut self, rhs : Self) {
1715    self.0 *= rhs.0
1716  }
1717}
1718impl <S> std::ops::Div for Rotation3 <S> where S : Ring + MaybeSerDes {
1719  type Output = Self;
1720  fn div (self, rhs : Self) -> Self::Output {
1721    use num::Inv;
1722    self * rhs.inv()
1723  }
1724}
1725impl <S> std::ops::DivAssign <Self> for Rotation3 <S> where
1726  S : Ring + MaybeSerDes
1727{
1728  fn div_assign (&mut self, rhs : Self) {
1729    use num::Inv;
1730    *self *= rhs.inv()
1731  }
1732}
1733impl <S> num::One for Rotation3 <S> where
1734  S : Ring + MaybeSerDes + num::Zero + num::One
1735{
1736  fn one() -> Self {
1737    Rotation3 (LinearAuto (
1738      LinearIso (Matrix3::identity(), PhantomData::default())))
1739  }
1740}
1741impl <S> From <Angles3 <S>> for Rotation3 <S> where
1742  S : Real + MaybeSerDes + num::real::Real
1743{
1744  fn from (angles : Angles3 <S>) -> Self {
1745    Rotation3::from_angles_intrinsic (
1746      angles.yaw.angle(), angles.pitch.angle(), angles.roll.angle())
1747  }
1748}
1749
1750
1751//
1752//  impl Versor
1753//
1754impl <S : Real> Versor <S> {
1755  /// Normalizes the given quaternion.
1756  ///
1757  /// Panics if the zero quaternion is given.
1758  pub fn normalize (quaternion : Quaternion <S>) -> Self where
1759    S : std::fmt::Debug
1760  {
1761    assert_ne!(quaternion, Quaternion::zero());
1762    Versor (normalize_quaternion (quaternion))
1763  }
1764  /// Panic if the given quaternion is not a unit quaternion.
1765  ///
1766  /// This method checks whether `quaternion == quaternion.normalized()`.
1767  pub fn noisy (unit_quaternion : Quaternion <S>) -> Self where
1768    S : std::fmt::Debug
1769  {
1770    assert_eq!(unit_quaternion, normalize_quaternion (unit_quaternion));
1771    Versor (unit_quaternion)
1772  }
1773  /// Panic if the given quaternion is not a unit quaternion.
1774  ///
1775  /// Checks if the magnitude is approximately one.
1776  pub fn noisy_approx (unit_quaternion : Quaternion <S>) -> Self where
1777    S : num::real::Real + approx::RelativeEq <Epsilon=S>
1778  {
1779    assert!(unit_quaternion.into_vec4().is_normalized());
1780    Versor (unit_quaternion)
1781  }
1782  /// It is a debug panic if the given quaternion is not a unit quaternion.
1783  ///
1784  /// This method checks whether `quaternion == quaternion.normalized()`.
1785  pub fn unchecked (unit_quaternion : Quaternion <S>) -> Self where
1786    S : std::fmt::Debug
1787  {
1788    debug_assert_eq!(unit_quaternion, normalize_quaternion (unit_quaternion));
1789    Versor (unit_quaternion)
1790  }
1791  /// It is a debug panic if the given quaternion is not a unit quaternion.
1792  ///
1793  /// Checks if the magnitude is approximately one.
1794  pub fn unchecked_approx (unit_quaternion : Quaternion <S>) -> Self where
1795    S : num::real::Real + approx::RelativeEq <Epsilon=S>
1796  {
1797    debug_assert!(unit_quaternion.into_vec4().is_normalized());
1798    Versor (unit_quaternion)
1799  }
1800  /// Constructs the rotation using the direction and magnitude of the given
1801  /// vector
1802  // TODO: work around rotation_3d Float constraint
1803  pub fn from_scaled_axis (scaled_axis : &Vector3 <S>) -> Self where
1804    S : std::fmt::Debug + num::Float
1805  {
1806    if *scaled_axis == Vector3::zero() {
1807      let versor = Quaternion::rotation_3d (S::zero(), *scaled_axis);
1808      debug_assert_eq!(versor.magnitude(), S::one());
1809      Versor (versor)
1810    } else {
1811      let angle = scaled_axis.magnitude();
1812      debug_assert!(S::zero() < angle);
1813      let axis  = *scaled_axis / angle;
1814      Versor (Quaternion::rotation_3d (angle, axis))
1815    }
1816  }
1817}
1818impl <S> From <Rotation3 <S>> for Versor <S> where
1819  S : Real + MaybeSerDes + num::real::Real + approx::RelativeEq <Epsilon=S>
1820{
1821  fn from (rot : Rotation3 <S>) -> Self {
1822    rot.versor()
1823  }
1824}
1825impl <S : Real> std::ops::Deref for Versor <S> {
1826  type Target = Quaternion <S>;
1827  fn deref (&self) -> &Quaternion <S> {
1828    &self.0
1829  }
1830}
1831//  end impl Versor
1832
1833//
1834//  impl AffineMap
1835//
1836impl <S, A, B, M> AffineMap <S, A, B, M> where
1837  A : AffineSpace <S>,
1838  B : AffineSpace <S>,
1839  M : LinearMap <S, A::Vector, B::Vector>,
1840  S : Field + std::fmt::Display,
1841  B::Vector : std::fmt::Display
1842{
1843  pub fn new (linear_map : M, translation : B::Vector) -> Self {
1844    AffineMap { linear_map, translation, _phantom: PhantomData::default() }
1845  }
1846  pub fn transform (self, point : A::Point) -> B::Point {
1847    B::Point::from_vector (
1848      self.linear_map * point.to_vector() + self.translation)
1849  }
1850}
1851
1852//
1853//  impl LinearIso
1854//
1855impl <S, V, W, M> LinearIso <S, V, W, M> where
1856  M : LinearMap <S, V, W> + Copy,
1857  V : Module <S>,
1858  W : Module <S>,
1859  S : Ring
1860{
1861  /// Checks whether the determinant is non-zero
1862  pub fn is_invertible (linear_map : M) -> bool {
1863    linear_map.determinant() != S::zero()
1864  }
1865  /// Checks whether the determinant is non-zero with approximate equality
1866  pub fn is_invertible_approx (linear_map : M) -> bool where
1867    S : approx::RelativeEq <Epsilon=S>
1868  {
1869    let four         = S::one() + S::one() + S::one() + S::one();
1870    let epsilon      = S::default_epsilon() * four;
1871    let max_relative = S::default_max_relative() * four;
1872    approx::relative_ne!(linear_map.determinant(), S::zero(),
1873      max_relative=max_relative, epsilon=epsilon)
1874  }
1875  /// Checks if map is invertible
1876  pub fn new (linear_map : M) -> Option <Self> {
1877    if Self::is_invertible (linear_map) {
1878      Some (LinearIso (linear_map, PhantomData::default()))
1879    } else {
1880      None
1881    }
1882  }
1883  /// Checks if map is invertible with approximate equality
1884  pub fn new_approx (linear_map : M) -> Option <Self> where
1885    S : approx::RelativeEq <Epsilon=S>
1886  {
1887    if Self::is_invertible_approx (linear_map) {
1888      Some (LinearIso (linear_map, PhantomData::default()))
1889    } else {
1890      None
1891    }
1892  }
1893}
1894impl <S, V, W, M> std::ops::Deref for LinearIso <S, V, W, M> where
1895  M : LinearMap <S, V, W>,
1896  V : Module <S>,
1897  W : Module <S>,
1898  S : Ring
1899{
1900  type Target = M;
1901  fn deref (&self) -> &Self::Target {
1902    &self.0
1903  }
1904}
1905impl <S, V> num::One for LinearIso <S, V, V, V::LinearEndo> where
1906  V : Module <S>,
1907  S : Ring
1908{
1909  fn one () -> Self {
1910    LinearIso (V::LinearEndo::one(), PhantomData::default())
1911  }
1912}
1913impl <S, V, W, M> std::ops::Mul <V> for LinearIso <S, V, W, M> where
1914  M : LinearMap <S, V, W>,
1915  V : Module <S>,
1916  W : Module <S>,
1917  S : Ring
1918{
1919  type Output = W;
1920  fn mul (self, rhs : V) -> Self::Output {
1921    self.0 * rhs
1922  }
1923}
1924impl <S, V> std::ops::Mul for LinearIso <S, V, V, V::LinearEndo> where
1925  V : Module <S>,
1926  S : Ring
1927{
1928  type Output = Self;
1929  fn mul (self, rhs : Self) -> Self::Output {
1930    LinearIso (self.0 * rhs.0, PhantomData::default())
1931  }
1932}
1933impl <S, V> std::ops::MulAssign for LinearIso <S, V, V, V::LinearEndo> where
1934  V : Module <S>,
1935  S : Ring
1936{
1937  fn mul_assign (&mut self, rhs : Self) {
1938    self.0 *= rhs.0
1939  }
1940}
1941
1942//
1943//  impl LinearAuto
1944//
1945impl <S, V> LinearAuto <S, V> where
1946  V : Module <S>,
1947  V::LinearEndo : MaybeSerDes,
1948  S : Ring
1949{
1950  /// Returns false if called with a matrix that is not orthogonal with
1951  /// determinant +/-1.
1952  ///
1953  /// This method checks whether `mat * mat^T == I` and
1954  /// `mat.determinant() == +/-1`.
1955  pub fn is_orthonormal (&self) -> bool {
1956    use num::One;
1957    let determinant = self.0.0.determinant();
1958    self.0.0 * self.0.0.transpose() == V::LinearEndo::one() &&
1959    (determinant == S::one() || determinant == -S::one())
1960  }
1961  /// Returns `None` if called with a matrix that is not orthogonal with
1962  /// determinant +/-1.
1963  ///
1964  /// This method checks whether `mat * mat^T == I` and
1965  /// `mat.determinant() == +/-1` (approximately using relative equality).
1966  pub fn is_orthonormal_approx (&self) -> bool where
1967    S : approx::RelativeEq <Epsilon=S>,
1968    V::LinearEndo : approx::RelativeEq <Epsilon=S>
1969  {
1970    use num::One;
1971    let four         = S::one() + S::one() + S::one() + S::one();
1972    let epsilon      = S::default_epsilon() * four;
1973    let max_relative = S::default_max_relative() * four;
1974    let determinant  = self.0.0.determinant();
1975    approx::relative_eq!(self.0.0 * self.0.0.transpose(), V::LinearEndo::one(),
1976      max_relative=max_relative, epsilon=epsilon) &&
1977    ( approx::relative_eq!(determinant,  S::one(), max_relative=max_relative) ||
1978      approx::relative_eq!(determinant, -S::one(), max_relative=max_relative) )
1979  }
1980  /// Checks whether the transformation is a special orthogonal matrix.
1981  ///
1982  /// This method checks whether `mat * mat^T == I` and
1983  /// `mat.determinant() == 1`.
1984  pub fn is_rotation (&self) -> bool {
1985    use num::One;
1986    let determinant = self.0.0.determinant();
1987    self.0.0 * self.0.0.transpose() == V::LinearEndo::one() &&
1988    determinant == S::one()
1989  }
1990  /// Checks whether the transformation is a special orthogonal matrix.
1991  ///
1992  /// This method checks whether `mat * mat^T == I` and
1993  /// `mat.determinant() == 1` (approximately using relative equality).
1994  pub fn is_rotation_approx (&self) -> bool where
1995    S : approx::RelativeEq <Epsilon=S>,
1996    V::LinearEndo : approx::RelativeEq <Epsilon=S>
1997  {
1998    use num::One;
1999    let four         = S::one() + S::one() + S::one() + S::one();
2000    let epsilon      = S::default_epsilon() * four;
2001    let max_relative = S::default_max_relative() * four;
2002    let determinant  = self.0.0.determinant();
2003    approx::relative_eq!(self.0.0 * self.0.0.transpose(), V::LinearEndo::one(),
2004      max_relative=max_relative, epsilon=epsilon) &&
2005    approx::relative_eq!(determinant,  S::one(), max_relative=max_relative)
2006  }
2007}
2008impl <S, V> MultiplicativeMonoid for LinearAuto <S, V> where
2009  V : Module <S>,
2010  V::LinearEndo : MaybeSerDes + PartialEq,
2011  S : Ring
2012{ }
2013impl <S, V> std::ops::Mul <V> for LinearAuto <S, V> where
2014  V : Module <S>,
2015  V::LinearEndo : MaybeSerDes,
2016  S : Ring
2017{
2018  type Output = V;
2019  fn mul (self, rhs : V) -> Self::Output {
2020    self.0 * rhs
2021  }
2022}
2023impl <S, V> std::ops::Mul for LinearAuto <S, V> where
2024  V : Module <S>,
2025  V::LinearEndo : MaybeSerDes,
2026  S : Ring
2027{
2028  type Output = Self;
2029  fn mul (self, rhs : Self) -> Self::Output {
2030    LinearAuto (self.0 * rhs.0)
2031  }
2032}
2033impl <S, V> std::ops::MulAssign <Self> for LinearAuto <S, V> where
2034  V : Module <S>,
2035  V::LinearEndo : MaybeSerDes,
2036  S : Ring
2037{
2038  fn mul_assign (&mut self, rhs : Self) {
2039    self.0 *= rhs.0
2040  }
2041}
2042impl <S, V> num::One for LinearAuto <S, V> where
2043  V : Module <S>,
2044  V::LinearEndo : MaybeSerDes,
2045  S : Ring
2046{
2047  fn one() -> Self {
2048    LinearAuto (LinearIso::one())
2049  }
2050}
2051
2052//
2053//  impl Affinity
2054//
2055impl <S, A, B, M> Affinity <S, A, B, M> where
2056  M : LinearMap <S, A::Vector, B::Vector>,
2057  A : AffineSpace <S>,
2058  B : AffineSpace <S>,
2059  S : Field + std::fmt::Display,
2060  B::Vector : std::fmt::Display
2061{
2062  pub fn new (
2063    linear_iso  : LinearIso <S, A::Vector, B::Vector, M>,
2064    translation : B::Vector
2065  ) -> Self {
2066    Affinity { linear_iso, translation, _phantom: PhantomData::default() }
2067  }
2068}
2069
2070//
2071//  impl Projectivity
2072//
2073impl <S, V, W, P, Q, M> Projectivity <S, V, W, P, Q, M> where
2074  M : LinearMap <S, P, Q>,
2075  P : ProjectiveSpace <S, V>,
2076  Q : ProjectiveSpace <S, W>,
2077  V : VectorSpace <S> + std::fmt::Display,
2078  W : VectorSpace <S> + std::fmt::Display,
2079  S : Field + std::fmt::Display
2080{
2081  pub fn new (linear_iso : LinearIso <S, P, Q, M>) -> Self {
2082    Projectivity (linear_iso, PhantomData::default())
2083  }
2084  pub fn transform (self, vector : P) -> Q {
2085    **self * vector
2086  }
2087}
2088impl <S, V, W, P, Q, M> std::ops::Deref for Projectivity <S, V, W, P, Q, M> where
2089  M : LinearMap <S, P, Q>,
2090  P : ProjectiveSpace <S, V>,
2091  Q : ProjectiveSpace <S, W>,
2092  V : VectorSpace <S> + std::fmt::Display,
2093  W : VectorSpace <S> + std::fmt::Display,
2094  S : Field + std::fmt::Display
2095{
2096  type Target = LinearIso <S, P, Q, M>;
2097  fn deref (&self) -> &Self::Target {
2098    &self.0
2099  }
2100}
2101
2102macro_rules! impl_angle {
2103  ( $angle:ident, $docname:expr ) => {
2104    #[doc = $docname]
2105    #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
2106    // TODO: derive From here causes a test failure in the intrinsic angles test
2107    #[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
2108    pub struct $angle <S> (pub S);
2109    impl_numcast_primitive!($angle);
2110    impl <S : Real> AdditiveGroup  for $angle <S> { }
2111    impl <S : Real> AdditiveMonoid for $angle <S> { }
2112    impl <S : Ring> std::ops::Neg for $angle <S> {
2113      type Output = Self;
2114      fn neg (self) -> Self::Output {
2115        $angle (-self.0)
2116      }
2117    }
2118    impl <S : Ring> std::ops::Add for $angle <S> {
2119      type Output = Self;
2120      fn add (self, other : Self) -> Self::Output {
2121        $angle (self.0 + other.0)
2122      }
2123    }
2124    impl <S : Ring> std::ops::AddAssign for $angle <S> {
2125      fn add_assign (&mut self, other : Self) {
2126        self.0 += other.0
2127      }
2128    }
2129    impl <S : Ring> std::ops::Sub for $angle <S> {
2130      type Output = Self;
2131      fn sub (self, other : Self) -> Self::Output {
2132        $angle (self.0 - other.0)
2133      }
2134    }
2135    impl <S : Ring> std::ops::SubAssign for $angle <S> {
2136      fn sub_assign (&mut self, other : Self) {
2137        self.0 -= other.0
2138      }
2139    }
2140    impl <S : Ring> std::ops::Mul <S> for $angle <S> {
2141      type Output = Self;
2142      fn mul (self, scalar : S) -> Self::Output {
2143        $angle (scalar * self.0)
2144      }
2145    }
2146    impl <S : Ring> std::ops::MulAssign <S> for $angle <S> {
2147      fn mul_assign (&mut self, scalar : S) {
2148        self.0 *= scalar
2149      }
2150    }
2151    impl <S : Ring> std::ops::Div for $angle <S> {
2152      type Output = S;
2153      fn div (self, other : Self) -> Self::Output {
2154        self.0 / other.0
2155      }
2156    }
2157    impl <S : Ring> std::ops::Div <S> for $angle <S> {
2158      type Output = Self;
2159      fn div (self, scalar : S) -> Self::Output {
2160        $angle (self.0 / scalar)
2161      }
2162    }
2163    impl <S : Field> std::ops::DivAssign <S> for $angle <S> {
2164      fn div_assign (&mut self, scalar : S) {
2165        self.0 /= scalar
2166      }
2167    }
2168    impl <S : Ring> std::ops::Rem for $angle <S> {
2169      type Output = Self;
2170      fn rem (self, other : Self) -> Self::Output {
2171        $angle (self.0 % other.0)
2172      }
2173    }
2174    impl <S : Ring> num::Zero for $angle <S> {
2175      fn zero() -> Self {
2176        $angle (S::zero())
2177      }
2178      fn is_zero (&self) -> bool {
2179        self.0.is_zero()
2180      }
2181    }
2182  }
2183}
2184
2185macro_rules! impl_angle_wrapped {
2186  ( $angle:ident, $comment:expr ) => {
2187    #[doc = $comment]
2188    #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
2189    #[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
2190    pub struct $angle <S> (Rad <S>);
2191
2192    impl_numcast!($angle);
2193    impl <S : Real> $angle <S> {
2194      pub fn angle (&self) -> Rad <S> {
2195        self.0
2196      }
2197    }
2198    impl <S : Real> AdditiveGroup  for $angle <S> { }
2199    impl <S : Real> AdditiveMonoid for $angle <S> { }
2200    impl <S : Real> std::ops::Neg for $angle <S> {
2201      type Output = Self;
2202      fn neg (self) -> Self::Output {
2203        self.map (Rad::neg)
2204      }
2205    }
2206    impl <S : Real> std::ops::Add for $angle <S> {
2207      type Output = Self;
2208      fn add (self, other : Self) -> Self::Output {
2209        self.map (|angle| angle + other.0)
2210      }
2211    }
2212    impl <S : Real> std::ops::AddAssign for $angle <S> {
2213      fn add_assign (&mut self, other : Self) {
2214        *self = *self + other
2215      }
2216    }
2217    impl <S : Real> std::ops::Add <Rad <S>> for $angle <S> {
2218      type Output = Self;
2219      fn add (self, angle : Rad <S>) -> Self::Output {
2220        self.map (|a| a + angle)
2221      }
2222    }
2223    impl <S : Real> std::ops::AddAssign <Rad <S>> for $angle <S> {
2224      fn add_assign (&mut self, angle : Rad <S>) {
2225        *self = *self + angle
2226      }
2227    }
2228    impl <S : Real> std::ops::Sub for $angle <S> {
2229      type Output = Self;
2230      fn sub (self, other : Self) -> Self::Output {
2231        self.map (|angle| angle - other.0)
2232      }
2233    }
2234    impl <S : Real> std::ops::SubAssign for $angle <S> {
2235      fn sub_assign (&mut self, other : Self) {
2236        *self = *self - other
2237      }
2238    }
2239    impl <S : Real> std::ops::Sub <Rad <S>> for $angle <S> {
2240      type Output = Self;
2241      fn sub (self, angle : Rad <S>) -> Self::Output {
2242        self.map (|a| a - angle)
2243      }
2244    }
2245    impl <S : Real> std::ops::SubAssign <Rad <S>> for $angle <S> {
2246      fn sub_assign (&mut self, angle : Rad <S>) {
2247        *self = *self - angle
2248      }
2249    }
2250    impl <S : Real> std::ops::Mul <S> for $angle <S> {
2251      type Output = Self;
2252      fn mul (self, scalar : S) -> Self::Output {
2253        self.map (|angle| angle * scalar)
2254      }
2255    }
2256    impl <S : Real> std::ops::MulAssign <S> for $angle <S> {
2257      fn mul_assign (&mut self, scalar : S) {
2258        *self = *self * scalar
2259      }
2260    }
2261    impl <S : Real> std::ops::Div for $angle <S> {
2262      type Output = S;
2263      fn div (self, other : Self) -> Self::Output {
2264        self.0 / other.0
2265      }
2266    }
2267    impl <S : Real> std::ops::Div <S> for $angle <S> {
2268      type Output = Self;
2269      fn div (self, scalar : S) -> Self::Output {
2270        self.map (|angle| angle / scalar)
2271      }
2272    }
2273    impl <S : Real> std::ops::DivAssign <S> for $angle <S> {
2274      fn div_assign (&mut self, scalar : S) {
2275        *self = *self / scalar
2276      }
2277    }
2278    impl <S : Real> std::ops::Rem for $angle <S> {
2279      type Output = Self;
2280      fn rem (self, other : Self) -> Self::Output {
2281        self.map (|angle| angle % other.0)
2282      }
2283    }
2284    impl <S : Real> num::Zero for $angle <S> {
2285      fn zero() -> Self {
2286        $angle (Rad::zero())
2287      }
2288      fn is_zero (&self) -> bool {
2289        self.0.is_zero()
2290      }
2291    }
2292  }
2293}
2294
2295macro_rules! impl_dimension {
2296  ( $point:ident, $vector:ident, $nonzero:ident, $unit:ident,
2297    [$($component:ident),+],
2298    [$(($axis_method:ident, $unit_method:ident)),+], [$($projective:ident)?],
2299    $matrix:ident, $affine:ident, $euclidean:ident, $ndims:expr, $dimension:expr
2300  ) => {
2301    #[doc = $dimension]
2302    #[doc = "position"]
2303    #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Display, From, Neg)]
2304    #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
2305    #[display("{}", _0)]
2306    #[repr(C)]
2307    pub struct $point <S> (pub $vector <S>);
2308
2309    #[doc = $dimension]
2310    #[doc = "affine space"]
2311    #[derive(Debug)]
2312    pub struct $affine <S> (PhantomData <S>);
2313    impl <S : Field> AffineSpace <S> for $affine <S> {
2314      type Point  = $point  <S>;
2315      type Vector = $vector <S>;
2316    }
2317
2318    #[doc = $dimension]
2319    #[doc = "euclidean space"]
2320    #[derive(Debug)]
2321    pub struct $euclidean <S> (PhantomData <S>);
2322    impl <S : Real> EuclideanSpace <S> for $euclidean <S> { }
2323    impl <S : Real> AffineSpace <S> for $euclidean <S> {
2324      type Point  = $point  <S>;
2325      type Vector = $vector <S>;
2326    }
2327
2328    #[doc = $dimension]
2329    #[doc = "non-zero vector"]
2330    #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
2331    #[derive(Clone, Copy, Debug, PartialEq, Display)]
2332    #[display("{}", _0)]
2333    #[repr(C)]
2334    pub struct $nonzero <S> ($vector <S>);
2335
2336    #[doc = $dimension]
2337    #[doc = "unit vector"]
2338    #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
2339    #[derive(Clone, Copy, Debug, PartialEq, Display)]
2340    #[display("{}", _0)]
2341    #[repr(C)]
2342    pub struct $unit <S> ($vector <S>);
2343
2344    //
2345    //  impl PointN
2346    //
2347    impl_numcast!($point);
2348    impl <S> $point <S> {
2349      pub const fn new ($($component : S),+) -> Self {
2350        $point ($vector::new ($($component),+))
2351      }
2352    }
2353    impl <S> Point <$vector <S>> for $point <S> where S : Ring {
2354      fn to_vector (self) -> $vector <S> {
2355        self.0
2356      }
2357      fn from_vector (vector : $vector <S>) -> Self {
2358        $point (vector)
2359      }
2360    }
2361    impl <S> From<[S; $ndims]> for $point <S> {
2362      fn from (array : [S; $ndims]) -> Self {
2363        $point (array.into())
2364      }
2365    }
2366    impl <S> std::ops::Add <$vector <S>> for $point <S> where S : AdditiveGroup {
2367      type Output = Self;
2368      fn add (self, displacement : $vector <S>) -> Self::Output {
2369        $point (self.0 + displacement)
2370      }
2371    }
2372    impl <S> std::ops::Add <&$vector <S>> for $point <S> where
2373      S : AdditiveGroup + Copy
2374    {
2375      type Output = Self;
2376      fn add (self, displacement : &$vector <S>) -> Self::Output {
2377        $point (self.0 + *displacement)
2378      }
2379    }
2380    impl <S> std::ops::Add <$vector <S>> for &$point <S> where
2381      S : AdditiveGroup + Copy
2382    {
2383      type Output = $point <S>;
2384      fn add (self, displacement : $vector <S>) -> Self::Output {
2385        $point (self.0 + displacement)
2386      }
2387    }
2388    impl <S> std::ops::Add <&$vector <S>> for &$point <S> where
2389      S : AdditiveGroup + Copy
2390    {
2391      type Output = $point <S>;
2392      fn add (self, displacement : &$vector <S>) -> Self::Output {
2393        $point (self.0 + *displacement)
2394      }
2395    }
2396    impl <S> std::ops::AddAssign <$vector <S>> for $point <S> where
2397      S : AdditiveGroup
2398    {
2399      fn add_assign (&mut self, displacement : $vector <S>) {
2400        self.0 += displacement
2401      }
2402    }
2403    impl <S> std::ops::AddAssign <&$vector <S>> for $point <S> where
2404      S : AdditiveGroup + Copy
2405    {
2406      fn add_assign (&mut self, displacement : &$vector <S>) {
2407        self.0 += *displacement
2408      }
2409    }
2410    impl <S> std::ops::Sub <$vector <S>> for $point <S> where S : AdditiveGroup {
2411      type Output = Self;
2412      fn sub (self, displacement : $vector <S>) -> Self::Output {
2413        $point (self.0 - displacement)
2414      }
2415    }
2416    impl <S> std::ops::Sub <&$vector <S>> for $point <S> where
2417      S : AdditiveGroup + Copy
2418    {
2419      type Output = Self;
2420      fn sub (self, displacement : &$vector <S>) -> Self::Output {
2421        $point (self.0 - *displacement)
2422      }
2423    }
2424    impl <S> std::ops::Sub <$point <S>> for $point <S> where S : AdditiveGroup {
2425      type Output = $vector <S>;
2426      fn sub (self, other : Self) -> Self::Output {
2427        self.0 - other.0
2428      }
2429    }
2430    impl <S> std::ops::Sub <&$point <S>> for $point <S> where
2431      S : AdditiveGroup + Copy
2432    {
2433      type Output = $vector <S>;
2434      fn sub (self, other : &Self) -> Self::Output {
2435        self.0 - other.0
2436      }
2437    }
2438    impl <S> std::ops::Sub <$vector <S>> for &$point <S> where
2439      S : AdditiveGroup + Copy
2440    {
2441      type Output = $point <S>;
2442      fn sub (self, displacement : $vector <S>) -> Self::Output {
2443        $point (self.0 - displacement)
2444      }
2445    }
2446    impl <S> std::ops::Sub <&$vector <S>> for &$point <S> where
2447      S : AdditiveGroup + Copy
2448    {
2449      type Output = $point <S>;
2450      fn sub (self, displacement : &$vector <S>) -> Self::Output {
2451        $point (self.0 - *displacement)
2452      }
2453    }
2454    impl <S> std::ops::Sub <$point <S>> for &$point <S> where
2455      S : AdditiveGroup + Copy
2456    {
2457      type Output = $vector <S>;
2458      fn sub (self, other : $point <S>) -> Self::Output {
2459        self.0 - other.0
2460      }
2461    }
2462    impl <S> std::ops::Sub <&$point <S>> for &$point <S> where
2463      S : AdditiveGroup + Copy
2464    {
2465      type Output = $vector <S>;
2466      fn sub (self, other : &$point <S>) -> Self::Output {
2467        self.0 - other.0
2468      }
2469    }
2470    impl <S> std::ops::SubAssign <$vector <S>> for $point <S> where
2471      S : AdditiveGroup
2472    {
2473      fn sub_assign (&mut self, displacement : $vector <S>) {
2474        self.0 -= displacement
2475      }
2476    }
2477    impl <S> std::ops::SubAssign <&$vector <S>> for $point <S> where
2478      S : AdditiveGroup + Copy
2479    {
2480      fn sub_assign (&mut self, displacement : &$vector <S>) {
2481        self.0 -= *displacement
2482      }
2483    }
2484    impl <S> approx::AbsDiffEq for $point <S> where
2485      S : approx::AbsDiffEq,
2486      S::Epsilon : Copy
2487    {
2488      type Epsilon = S::Epsilon;
2489      fn default_epsilon() -> Self::Epsilon {
2490        S::default_epsilon()
2491      }
2492      #[inline]
2493      fn abs_diff_eq (&self, other : &Self, epsilon : Self::Epsilon) -> bool {
2494        self.0.abs_diff_eq (&other.0, epsilon)
2495      }
2496    }
2497    impl <S> approx::RelativeEq for $point <S> where
2498      S : approx::RelativeEq,
2499      S::Epsilon : Copy
2500    {
2501      fn default_max_relative() -> Self::Epsilon {
2502        S::default_max_relative()
2503      }
2504      #[inline]
2505      fn relative_eq (&self,
2506        other : &Self, epsilon : Self::Epsilon, max_relative : Self::Epsilon
2507      ) -> bool {
2508        self.0.relative_eq (&other.0, epsilon, max_relative)
2509      }
2510    }
2511    impl <S> approx::UlpsEq for $point <S> where
2512      S : approx::UlpsEq,
2513      S::Epsilon : Copy
2514    {
2515      fn default_max_ulps() -> u32 {
2516        S::default_max_ulps()
2517      }
2518      #[inline]
2519      fn ulps_eq (&self, other : &Self, epsilon : Self::Epsilon, max_ulps : u32)
2520        -> bool
2521      {
2522        self.0.ulps_eq (&other.0, epsilon, max_ulps)
2523      }
2524    }
2525    //
2526    //  impl VectorN
2527    //
2528    impl <S : Field> InnerProductSpace <S> for $vector <S> { }
2529    impl <S : Ring> Dot <S> for $vector <S> {
2530      fn dot (self, other : Self) -> S {
2531        self.dot (other)
2532      }
2533    }
2534    impl <S : Field> VectorSpace <S> for $vector <S> {
2535      fn map <F> (self, f : F) -> Self where F : FnMut (S) -> S {
2536        self.map (f)
2537      }
2538    }
2539    impl <S : Ring> Module <S> for $vector <S> {
2540      type LinearEndo = $matrix <S>;
2541    }
2542    impl <S : Ring> LinearMap <S, $vector <S>, $vector <S>> for $matrix <S> {
2543      fn determinant (self) -> S {
2544        self.determinant()
2545      }
2546      fn transpose (self) -> Self {
2547        self.transposed()
2548      }
2549    }
2550    impl <S : Ring> MultiplicativeMonoid for $matrix <S> { }
2551    impl <S> GroupAction <$point <S>> for $vector <S> where S : AdditiveGroup {
2552      fn action (self, point : $point <S>) -> $point <S> {
2553        point + self
2554      }
2555    }
2556    impl <S : Ring> AdditiveGroup  for $vector <S> { }
2557    impl <S : Ring> AdditiveMonoid for $vector <S> { }
2558    impl <S : AdditiveGroup> Group for $vector <S> {
2559      fn identity() -> Self {
2560        Self::zero()
2561      }
2562      fn operation (a : Self, b : Self) -> Self {
2563        a + b
2564      }
2565    }
2566    impl <S> Point <$vector <S>> for $vector <S> where S : Ring {
2567      fn to_vector (self) -> $vector <S> {
2568        self
2569      }
2570      fn from_vector (vector : $vector <S>) -> Self {
2571        vector
2572      }
2573    }
2574    impl <S> std::ops::Mul <LinearAuto <S, Self>> for $vector <S> where
2575      S : Ring + MaybeSerDes
2576    {
2577      type Output = Self;
2578      fn mul (self, rhs : LinearAuto <S, Self>) -> Self::Output {
2579        self * rhs.0
2580      }
2581    }
2582    impl <S> std::ops::Mul <LinearIso <S, Self, Self, $matrix <S>>> for
2583      $vector <S>
2584    where
2585      S : Ring + MaybeSerDes
2586    {
2587      type Output = Self;
2588      fn mul (self, rhs : LinearIso <S, Self, Self, $matrix <S>>)
2589        -> Self::Output
2590      {
2591        self * rhs.0
2592      }
2593    }
2594    impl <S> num::Inv for LinearAuto <S, $vector <S>> where
2595      S : Ring + num::Float + MaybeSerDes
2596    {
2597      type Output = Self;
2598      fn inv (self) -> Self::Output {
2599        LinearAuto (self.0.inv())
2600      }
2601    }
2602    impl <S> std::ops::Div for LinearAuto <S, $vector <S>> where
2603      S : Ring + num::Float + MaybeSerDes
2604    {
2605      type Output = Self;
2606      fn div (self, rhs : Self) -> Self::Output {
2607        LinearAuto (self.0 / rhs.0)
2608      }
2609    }
2610    impl <S> std::ops::DivAssign <Self> for LinearAuto <S, $vector <S>> where
2611      S : Ring + num::Float + MaybeSerDes
2612    {
2613      fn div_assign (&mut self, rhs : Self) {
2614        self.0 /= rhs.0
2615      }
2616    }
2617    impl <S> MultiplicativeGroup for LinearAuto <S, $vector <S>> where
2618      S : Ring + num::Float + MaybeSerDes
2619    { }
2620    // projective completion
2621    $(
2622      impl <S> ProjectiveSpace <S, $vector <S>> for $projective <S> where
2623        S : Field + std::fmt::Display
2624      {
2625        fn homography <A> (
2626          affinity : Affinity <S, A, A, <A::Vector as Module <S>>::LinearEndo>
2627        ) -> Projectivity <
2628          S, $vector <S>, $vector <S>, Self, Self, Self::LinearEndo
2629        > where
2630          A : AffineSpace <S, Vector=$vector <S>>
2631        {
2632          Projectivity::new (
2633            LinearIso::<S, Self, Self, Self::LinearEndo>::new (
2634              (*affinity.linear_iso).into()
2635            ).unwrap()
2636          )
2637        }
2638        fn homogeneous <A> (point_or_vector : Either <A::Point, A::Vector>)
2639          -> Self
2640        where
2641          A : AffineSpace <S, Vector=$vector <S>>,
2642          $vector <S> : GroupAction <A::Point>
2643        {
2644          match point_or_vector {
2645            Either::Left  (point)  => (point.to_vector(), S::one()).into(),
2646            Either::Right (vector) => (vector, S::zero()).into(),
2647          }
2648        }
2649      }
2650    )?
2651    //
2652    //  impl MatrixN
2653    //
2654    impl <S, V, W> num::Inv for LinearIso <S, V, W, $matrix <S>> where
2655      V : Module <S>,
2656      W : Module <S>,
2657      S : Ring + num::Float
2658    {
2659      type Output = LinearIso <S, W, V, $matrix <S>>;
2660      fn inv (self) -> Self::Output {
2661        // TODO: currently the vek crate only implements invert for Mat4
2662        let mat4 = Matrix4::from (self.0);
2663        LinearIso (mat4.inverted().into(), PhantomData::default())
2664      }
2665    }
2666    impl <S, V> std::ops::Div for LinearIso <S, V, V, $matrix <S>> where
2667      V : Module <S, LinearEndo=$matrix <S>>,
2668      S : Ring + num::Float
2669    {
2670      type Output = Self;
2671      fn div (self, rhs : Self) -> Self::Output {
2672        use num::Inv;
2673        self * rhs.inv()
2674      }
2675    }
2676    impl <S, V> std::ops::DivAssign for LinearIso <S, V, V, $matrix <S>> where
2677      V : Module <S, LinearEndo=$matrix <S>>,
2678      S : Ring + num::Float
2679    {
2680      fn div_assign (&mut self, rhs : Self) {
2681        use num::Inv;
2682        *self *= rhs.inv()
2683      }
2684    }
2685    //
2686    //  impl NonZeroN
2687    //
2688    impl_numcast!($nonzero);
2689    impl <S : Ring> $nonzero <S> {
2690      /// Returns 'None' if called with the zero vector
2691      // TODO: move broken doctests to unit tests
2692      // # Example
2693      //
2694      // ```
2695      // # use math_utils::$nonzero;
2696      // assert!($nonzero::new ([1.0, 0.0].into()).is_some());
2697      // assert!($nonzero::new ([0.0, 0.0].into()).is_none());
2698      // ```
2699      pub fn new (vector : $vector <S>) -> Option <Self> {
2700        use num::Zero;
2701        if !vector.is_zero() {
2702          Some ($nonzero (vector))
2703        } else {
2704          None
2705        }
2706      }
2707      /// Panics if zero vector is given.
2708      // TODO: move broken doctests to unit tests
2709      // # Panics
2710      //
2711      // ```should_panic
2712      // # use math_utils::$nonzero;
2713      // let x = $nonzero::noisy ([0.0, 0.0].into());  // panic!
2714      // ```
2715      pub fn noisy (vector : $vector <S>) -> Self {
2716        use num::Zero;
2717        assert!(!vector.is_zero());
2718        $nonzero (vector)
2719      }
2720      /// Map an operation on the underlying vector, panicking if the result is
2721      /// zero
2722      // TODO: move broken doctests to unit tests
2723      // # Panics
2724      //
2725      // Panics of the result is zero:
2726      //
2727      // ```should_panic
2728      // # use math_utils::$nonzero;
2729      // let v = $nonzero::noisy ([1.0, 1.0].into())
2730      //   .map_noisy (|x| 0.0 * x);  // panic!
2731      // ```
2732      pub fn map_noisy (self, fun : fn ($vector <S>) -> $vector <S>) -> Self {
2733        Self::noisy (fun (self.0))
2734      }
2735    }
2736    impl <S : Ring> std::ops::Deref for $nonzero <S> {
2737      type Target = $vector <S>;
2738      fn deref (&self) -> &$vector <S> {
2739        &self.0
2740      }
2741    }
2742    //
2743    //  impl UnitN
2744    //
2745    impl_numcast!($unit);
2746    impl <S : Real> $unit <S> {
2747      // TODO: move broken doc tests to unit tests
2748      // ```
2749      // # use math_utils::$unit;
2750      // assert_eq!($unit::axis_x(), $unit::new ([1.0, 0.0].into()).unwrap());
2751      // ```
2752      $(
2753      #[inline]
2754      pub fn $axis_method() -> Self {
2755        $unit ($vector::$unit_method())
2756      }
2757      )+
2758      /// Returns 'None' if called with a non-normalized vector.
2759      ///
2760      /// This method checks whether `vector == vector.normalize()`.
2761      pub fn new (vector : $vector <S>) -> Option <Self> {
2762        let normalized = vector.normalize();
2763        if vector == normalized {
2764          Some ($unit (vector))
2765        } else {
2766          None
2767        }
2768      }
2769      /// Returns 'None' if called with an non-normalized vector determined by
2770      /// checking if the magnitude is approximately one.
2771      ///
2772      /// Note the required `RelativeEq` trait is only implemented for
2773      /// floating-point types.
2774      pub fn new_approx (vector : $vector <S>) -> Option <Self> where
2775        S : num::real::Real + approx::RelativeEq <Epsilon=S>
2776      {
2777        if vector.is_normalized() {
2778          Some ($unit (vector))
2779        } else {
2780          None
2781        }
2782      }
2783      /// Normalizes a given non-zero vector.
2784      // TODO: move broken doc tests to unit tests
2785      // # Example
2786      //
2787      // ```
2788      // # use math_utils::$unit;
2789      // assert_eq!(
2790      //   *$unit::normalize ([2.0, 0.0].into()),
2791      //   [1.0, 0.0].into()
2792      // );
2793      // ```
2794      //
2795      // # Panics
2796      //
2797      // Panics if the zero vector is given:
2798      //
2799      // ```should_panic
2800      // # use math_utils::$unit;
2801      // let x = $unit::normalize ([0.0, 0.0].into());  // panic!
2802      // ```
2803      pub fn normalize (vector : $vector <S>) -> Self {
2804        use num::Zero;
2805        assert!(!vector.is_zero());
2806        $unit (vector.normalize())
2807      }
2808      /// Normalizes a given non-zero vector only if the vector is not already
2809      /// normalized.
2810      pub fn normalize_approx (vector : $vector <S>) -> Self where
2811        S : num::real::Real + approx::RelativeEq <Epsilon=S>
2812      {
2813        use num::Zero;
2814        assert!(!vector.is_zero());
2815        let vector = if vector.is_normalized() {
2816          vector
2817        } else {
2818          vector.normalize()
2819        };
2820        $unit (vector)
2821      }
2822      /// Panics if a non-normalized vector is given.
2823      ///
2824      /// This method checks whether `vector == vector.normalize()`.
2825      // TODO: move broken doc tests to unit tests
2826      // ```should_panic
2827      // # use math_utils::$unit;
2828      // let x = $unit::noisy ([2.0, 0.0].into());  // panic!
2829      // ```
2830      pub fn noisy (vector : $vector <S>) -> Self where S : std::fmt::Debug {
2831        assert_eq!(vector, vector.normalize());
2832        $unit (vector)
2833      }
2834      /// Panics if a non-normalized vector is given.
2835      ///
2836      /// Checks if the magnitude is approximately one.
2837      // TODO: move broken doc tests to unit tests
2838      // ```should_panic
2839      // # use math_utils::$unit;
2840      // let x = $unit::noisy ([2.0, 0.0].into());  // panic!
2841      // ```
2842      pub fn noisy_approx (vector : $vector <S>) -> Self where
2843        S : num::real::Real + approx::RelativeEq <Epsilon=S>
2844      {
2845        assert!(vector.is_normalized());
2846        $unit (vector)
2847      }
2848      /// It is a debug assertion if the given vector is not normalized.
2849      ///
2850      /// In debug builds, method checks that `vector == vector.normalize()`.
2851      #[inline]
2852      pub fn unchecked (vector : $vector <S>) -> Self where
2853        S : std::fmt::Debug
2854      {
2855        debug_assert_eq!(vector, vector.normalize());
2856        $unit (vector)
2857      }
2858      /// It is a debug assertion if the given vector is not normalized.
2859      ///
2860      /// In debug builds, checks if the magnitude is approximately one.
2861      // TODO: move broken doc tests to unit tests
2862      // ```should_panic
2863      // # use math_utils::$unit;
2864      // let n = $unit::unchecked ([2.0, 0.0].into());  // panic!
2865      // ```
2866      #[inline]
2867      pub fn unchecked_approx (vector : $vector <S>) -> Self where
2868        S : num::real::Real + approx::RelativeEq <Epsilon=S>
2869      {
2870        debug_assert!(vector.is_normalized());
2871        $unit (vector)
2872      }
2873      /// Generate a random unit vector. Uses naive algorithm.
2874      pub fn random_unit <R : rand::Rng> (rng : &mut R) -> Self where
2875        S : rand::distr::uniform::SampleUniform
2876      {
2877        let vector = $vector {
2878          $($component: rng.random_range (-S::one()..S::one())),+
2879        };
2880        $unit (vector.normalize())
2881      }
2882      /// Return the unit vector pointing in the opposite direction
2883      // TODO: implement num::Inv ?
2884      pub fn invert (mut self) -> Self {
2885        self.0 = -self.0;
2886        self
2887      }
2888      /// Map an operation on the underlying vector, panicking if the result is
2889      /// zero.
2890      ///
2891      /// # Panics
2892      ///
2893      /// Panics of the result is not normalized.
2894      // TODO: move broken doc tests to unit tests
2895      // ```should_panic
2896      // # use math_utils::$unit;
2897      // // panic!
2898      // let v = $unit::noisy ([1.0, 0.0].into()).map_noisy (|x| 2.0 * x);
2899      // ```
2900      pub fn map_noisy (self, fun : fn ($vector <S>) -> $vector <S>)
2901        -> Self
2902      where
2903        S : std::fmt::Debug
2904      {
2905        Self::noisy (fun (self.0))
2906      }
2907      /// Map an operation on the underlying vector, panicking if the result is
2908      /// zero.
2909      ///
2910      /// # Panics
2911      ///
2912      /// Panics of the result is not normalized.
2913      // TODO: move broken doc tests to unit tests
2914      // ```should_panic
2915      // # use math_utils::$unit;
2916      // // panic!
2917      // let v = $unit::noisy ([1.0, 0.0].into()).map_noisy (|x| 2.0 * x);
2918      // ```
2919      pub fn map_noisy_approx (self, fun : fn ($vector <S>) -> $vector <S>)
2920        -> Self
2921      where
2922        S : num::real::Real + approx::RelativeEq <Epsilon=S>
2923      {
2924        Self::noisy_approx (fun (self.0))
2925      }
2926    }
2927    impl <S : Real> std::ops::Deref for $unit <S> {
2928      type Target = $vector <S>;
2929      fn deref (&self) -> &$vector <S> {
2930        &self.0
2931      }
2932    }
2933    impl <S : Real> std::ops::Neg for $unit <S> {
2934      type Output = Self;
2935      fn neg (self) -> Self::Output {
2936        Self (-self.0)
2937      }
2938    }
2939    //  end UnitN
2940  }
2941}
2942
2943macro_rules! impl_numcast {
2944  ($type:ident) => {
2945    impl <S> $type <S> {
2946      #[inline]
2947      pub fn numcast <T> (self) -> Option <$type <T>> where
2948        S : num::NumCast,
2949        T : num::NumCast
2950      {
2951        self.0.numcast().map ($type)
2952      }
2953    }
2954  }
2955}
2956
2957macro_rules! impl_numcast_primitive {
2958  ($type:ident) => {
2959    impl <S> $type <S> {
2960      #[inline]
2961      pub fn numcast <T> (self) -> Option <$type <T>> where
2962        S : num::NumCast,
2963        T : num::NumCast
2964      {
2965        T::from (self.0).map ($type)
2966      }
2967    }
2968  }
2969}
2970
2971#[macro_export]
2972macro_rules! impl_numcast_fields {
2973  ($type:ident, $($field:ident),+) => {
2974    impl <S> $type <S> {
2975      #[inline]
2976      pub fn numcast <T> (self) -> Option <$type <T>> where
2977        S : num::NumCast,
2978        T : num::NumCast
2979      {
2980        Some ($type {
2981          $(
2982          $field: self.$field.numcast()?
2983          ),+
2984        })
2985      }
2986    }
2987  }
2988}
2989
2990impl_angle!(Deg, "Degrees");
2991impl_angle!(Rad, "Radians");
2992impl_angle!(Turn, "Turns");
2993impl_angle_wrapped!(AngleWrapped,
2994  "Unsigned wrapped angle restricted to $[0, 2\\pi)$");
2995impl_angle_wrapped!(AngleWrappedSigned,
2996  "Signed wrapped angle restricted to $(-\\pi, \\pi]$");
2997
2998impl_dimension!(Point2, Vector2, NonZero2, Unit2,
2999  [x, y],
3000  [(axis_x, unit_x), (axis_y, unit_y)], [Vector3], Matrix2, Affine2, Euclidean2,
3001  2, "2D");
3002impl_dimension!(Point3, Vector3, NonZero3, Unit3,
3003  [x, y, z],
3004  [(axis_x, unit_x), (axis_y, unit_y), (axis_z, unit_z)],
3005  [Vector4], Matrix3, Affine3, Euclidean3, 3, "3D");
3006impl_dimension!(Point4, Vector4, NonZero4, Unit4,
3007  [x, y, z, w],
3008  [(axis_x, unit_x), (axis_y, unit_y), (axis_z, unit_z), (axis_w, unit_w)],
3009  [], Matrix4, Affine4, Euclidean4, 4, "4D");
3010
3011impl_numcast_primitive!(Positive);
3012impl_numcast_primitive!(NonNegative);
3013impl_numcast_primitive!(NonZero);
3014impl_numcast_primitive!(Normalized);
3015impl_numcast_primitive!(NormalSigned);
3016
3017//
3018//  private
3019//
3020#[inline]
3021fn normalize_quaternion <S : Real> (quaternion : Quaternion <S>)
3022  -> Quaternion <S>
3023{
3024  Quaternion::from_vec4 (quaternion.into_vec4().normalize())
3025}
3026
3027#[cfg(test)]
3028mod tests {
3029  use super::*;
3030  use crate::num_traits;
3031  use approx;
3032  use rand;
3033  use rand_xorshift;
3034
3035  #[test]
3036  fn defaults() {
3037    use num_traits::Zero;
3038
3039    assert_eq!(Positive::<f32>::default().0, 0.0);
3040    assert_eq!(NonNegative::<f32>::default().0, 0.0);
3041    assert_eq!(Normalized::<f32>::default().0, 0.0);
3042    assert_eq!(NormalSigned::<f32>::default().0, 0.0);
3043    assert_eq!(Deg::<f32>::default().0, 0.0);
3044    assert_eq!(Rad::<f32>::default().0, 0.0);
3045    assert_eq!(Turn::<f32>::default().0, 0.0);
3046    assert_eq!(
3047      Angles3::<f32>::default(),
3048      Angles3::new (
3049        AngleWrapped::zero(), AngleWrapped::zero(), AngleWrapped::zero())
3050    );
3051    assert_eq!(
3052      Pose3::<f32>::default(),
3053      Pose3 { position: Point3::origin(), angles: Angles3::default() });
3054    assert_eq!(
3055      LinearIso::<f32, Vector3 <f32>, Vector3 <f32>, Matrix3 <f32>>::default().0,
3056      Matrix3::identity());
3057    assert_eq!(
3058      LinearAuto::<f32, Vector3 <f32>>::default().0.0, Matrix3::identity());
3059    assert_eq!(Rotation2::<f32>::default().0.0.0, Matrix2::identity());
3060    assert_eq!(Rotation3::<f32>::default().0.0.0, Matrix3::identity());
3061    assert_eq!(
3062      Versor::<f32>::default().0, Quaternion::from_xyzw (0.0, 0.0, 0.0, 1.0));
3063    assert_eq!(
3064      AffineMap::<f32, Vector3 <f32>, Vector3 <f32>, Matrix3 <f32>>::default(),
3065      AffineMap::new (Matrix3::identity(), Vector3::zero()));
3066    assert_eq!(
3067      Affinity::<f32, Vector3 <f32>, Vector3 <f32>, Matrix3 <f32>>::default(),
3068      Affinity::new (
3069        LinearIso::new (Matrix3::identity()).unwrap(), Vector3::zero()));
3070    assert_eq!(
3071      Projectivity::<
3072        f32, Vector3 <f32>, Vector3 <f32>, Vector4 <f32>, Vector4 <f32>,
3073        Matrix4 <f32>
3074      >::default().0,
3075      LinearIso::new (Matrix4::identity()).unwrap());
3076  }
3077
3078  #[test]
3079  fn rotation3_noisy_approx() {
3080    use rand::{Rng, SeedableRng};
3081    // construct orthonormal matrices and verify they are orthonormal using
3082    // noisy_approx constructor
3083    let mut rng = rand_xorshift::XorShiftRng::seed_from_u64 (0);
3084    let up = Vector3::unit_z();
3085    for _ in 0..1000 {
3086      let forward = Vector3::new (
3087        rng.random_range (-1000.0f32..1000.0),
3088        rng.random_range (-1000.0f32..1000.0),
3089        0.0
3090      ).normalized();
3091      let right = forward.cross (up);
3092      let mat = Matrix3::from_col_arrays ([
3093        right.into_array(),
3094        forward.into_array(),
3095        up.into_array()
3096      ]);
3097      let _ = Rotation3::noisy_approx (mat);
3098    }
3099  }
3100
3101  #[test]
3102  fn rotation3_intrinsic_angles() {
3103    use std::f32::consts::PI;
3104    use num_traits::Zero;
3105    use rand::{Rng, SeedableRng};
3106    // yaw: CCW quarter turn around Z (world up) axis
3107    let rot = Rotation3::from_angles_intrinsic (
3108      Turn (0.25).into(), Rad::zero(), Rad::zero());
3109    approx::assert_relative_eq!(*rot,
3110      Matrix3::from_col_arrays ([
3111        [ 0.0, 1.0, 0.0],
3112        [-1.0, 0.0, 0.0],
3113        [ 0.0, 0.0, 1.0]
3114      ])
3115    );
3116    assert_eq!((Turn (0.25).into(), Rad::zero(), Rad::zero()),
3117      rot.intrinsic_angles());
3118    let rot = Rotation3::from_angles_intrinsic (
3119      Turn (0.5).into(), Rad::zero(), Rad::zero());
3120    approx::assert_relative_eq!(*rot,
3121      Matrix3::from_col_arrays ([
3122        [-1.0,  0.0, 0.0],
3123        [ 0.0, -1.0, 0.0],
3124        [ 0.0,  0.0, 1.0]
3125      ])
3126    );
3127    assert_eq!((Turn (0.5).into(), Rad::zero(), Rad::zero()),
3128      rot.intrinsic_angles());
3129    // pitch: CCW quarter turn around X (world right) axis
3130    let rot = Rotation3::from_angles_intrinsic (
3131      Rad::zero(), Turn (0.25).into(), Rad::zero());
3132    approx::assert_relative_eq!(*rot,
3133      Matrix3::from_col_arrays ([
3134        [1.0,  0.0, 0.0],
3135        [0.0,  0.0, 1.0],
3136        [0.0, -1.0, 0.0]
3137      ])
3138    );
3139    assert_eq!((Rad::zero(), Turn (0.25).into(), Rad::zero()),
3140      rot.intrinsic_angles());
3141    // roll: CCW quarter turn around Y (world forward) axis
3142    let rot = Rotation3::from_angles_intrinsic (
3143      Rad::zero(), Rad::zero(), Turn (0.25).into());
3144    approx::assert_relative_eq!(*rot,
3145      Matrix3::from_col_arrays ([
3146        [0.0, 0.0, -1.0],
3147        [0.0, 1.0,  0.0],
3148        [1.0, 0.0,  0.0]
3149      ])
3150    );
3151    assert_eq!((Rad::zero(), Rad::zero(), Turn (0.25).into()),
3152      rot.intrinsic_angles());
3153    // pitch after yaw
3154    let rot = Rotation3::from_angles_intrinsic (
3155      Turn (0.25).into(), Turn (0.25).into(), Rad::zero());
3156    approx::assert_relative_eq!(*rot,
3157      Matrix3::from_col_arrays ([
3158        [0.0, 1.0, 0.0],
3159        [0.0, 0.0, 1.0],
3160        [1.0, 0.0, 0.0]
3161      ])
3162    );
3163    let angles = rot.intrinsic_angles();
3164    approx::assert_relative_eq!(Rad::from (Turn (0.25)).0, angles.0.0);
3165    approx::assert_relative_eq!(Rad::from (Turn (0.25)).0, angles.1.0);
3166    approx::assert_relative_eq!(0.0, angles.2.0);
3167    // roll after pitch after yaw
3168    let rot = Rotation3::from_angles_intrinsic (
3169      Turn (0.25).into(), Turn (0.25).into(), Turn (0.25).into());
3170    approx::assert_relative_eq!(*rot,
3171      Matrix3::from_col_arrays ([
3172        [-1.0, 0.0, 0.0],
3173        [ 0.0, 0.0, 1.0],
3174        [ 0.0, 1.0, 0.0]
3175      ])
3176    );
3177    let angles = rot.intrinsic_angles();
3178    approx::assert_relative_eq!(Rad::from (Turn (0.25)).0, angles.0.0);
3179    approx::assert_relative_eq!(Rad::from (Turn (0.25)).0, angles.1.0);
3180    approx::assert_relative_eq!(Rad::from (Turn (0.25)).0, angles.2.0);
3181
3182    // construct random orthonormal matrices and verify the intrinsic angles are
3183    // in the range [-pi, pi]
3184    let mut rng = rand_xorshift::XorShiftRng::seed_from_u64 (0);
3185    let mut random_vector = || Vector3::new (
3186      rng.random_range (-100.0f32..100.0),
3187      rng.random_range (-100.0f32..100.0),
3188      rng.random_range (-100.0f32..100.0)
3189    );
3190    for _ in 0..1000 {
3191      let rot = Rotation3::orthonormalize (
3192        random_vector(), random_vector(), random_vector()
3193      ).unwrap();
3194      let (yaw, pitch, roll) = rot.intrinsic_angles();
3195      assert!(yaw.0   <  PI);
3196      assert!(yaw.0   > -PI);
3197      assert!(pitch.0 <  PI);
3198      assert!(pitch.0 > -PI);
3199      assert!(roll.0  <  PI);
3200      assert!(roll.0  > -PI);
3201    }
3202  }
3203
3204  #[test]
3205  fn rotation3_into_versor() {
3206    use std::f32::consts::PI;
3207    let rot  = Rotation3::from_angle_x (Rad (0.01));
3208    let quat = rot.versor().0;
3209    approx::assert_relative_eq!(*rot, quat.into());
3210    let rot  = Rotation3::from_angle_x (Rad (-0.01));
3211    let quat = rot.versor().0;
3212    approx::assert_relative_eq!(*rot, quat.into());
3213
3214    let rot  = Rotation3::from_angle_y (Rad (0.01));
3215    let quat = rot.versor().0;
3216    approx::assert_relative_eq!(*rot, quat.into());
3217    let rot  = Rotation3::from_angle_y (Rad (-0.01));
3218    let quat = rot.versor().0;
3219    approx::assert_relative_eq!(*rot, quat.into());
3220
3221    let rot  = Rotation3::from_angle_z (Rad (0.01));
3222    let quat = rot.versor().0;
3223    approx::assert_relative_eq!(*rot, quat.into());
3224    let rot  = Rotation3::from_angle_z (Rad (-0.01));
3225    let quat = rot.versor().0;
3226    approx::assert_relative_eq!(*rot, quat.into());
3227
3228    let rot  = Rotation3::from_angle_x (Rad (PI / 2.0));
3229    let quat = rot.versor().0;
3230    approx::assert_relative_eq!(*rot, quat.into());
3231    let rot  = Rotation3::from_angle_x (Rad (-PI / 2.0));
3232    let quat = rot.versor().0;
3233    approx::assert_relative_eq!(*rot, quat.into());
3234
3235    let rot  = Rotation3::from_angle_y (Rad (PI / 2.0));
3236    let quat = rot.versor().0;
3237    approx::assert_relative_eq!(*rot, quat.into());
3238    let rot  = Rotation3::from_angle_y (Rad (-PI / 2.0));
3239    let quat = rot.versor().0;
3240    approx::assert_relative_eq!(*rot, quat.into());
3241
3242    let rot  = Rotation3::from_angle_z (Rad (PI / 2.0));
3243    let quat = rot.versor().0;
3244    approx::assert_relative_eq!(*rot, quat.into());
3245    let rot  = Rotation3::from_angle_z (Rad (-PI / 2.0));
3246    let quat = rot.versor().0;
3247    approx::assert_relative_eq!(*rot, quat.into());
3248  }
3249}