1use std::marker::PhantomData;
2use derive_more::{Deref, Display, From, Neg};
3
4use crate::approx;
5use crate::num_traits as num;
6
7#[cfg(feature = "derive_serdes")]
8use serde::{Deserialize, Serialize};
9
10use crate::traits::*;
11
12pub mod coordinate;
13
14pub use vek::Vec2 as Vector2;
15pub use vek::Vec3 as Vector3;
16pub use vek::Vec4 as Vector4;
17pub use vek::Mat2 as Matrix2;
18pub use vek::Mat3 as Matrix3;
19pub use vek::Mat4 as Matrix4;
20pub use vek::Quaternion as Quaternion;
21
22pub use self::enums::{Axis2, Axis3, Axis4, Octant, Quadrant, Sign, SignedAxis1,
23  SignedAxis2, SignedAxis3, SignedAxis4};
24
25mod enums {
32  use strum::{EnumCount, EnumIter, FromRepr};
33  #[cfg(feature = "derive_serdes")]
34  use serde::{Deserialize, Serialize};
35
36  #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
38  #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
39  #[repr(u8)]
40  pub enum Sign {
41    Negative,
42    Zero,
43    Positive
44  }
45
46  #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
48  #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
49  #[repr(u8)]
50  pub enum Quadrant {
51    PosPos,
53    NegPos,
55    PosNeg,
57    NegNeg
59  }
60
61  #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
63  #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
64  #[repr(u8)]
65  pub enum Octant {
66    PosPosPos,
68    NegPosPos,
70    PosNegPos,
72    NegNegPos,
74    PosPosNeg,
76    NegPosNeg,
78    PosNegNeg,
80    NegNegNeg
82  }
83
84  #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
86  #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
87  #[repr(u8)]
88  pub enum Axis2 {
89    X=0,
90    Y
91  }
92
93  #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
95  #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
96  #[repr(u8)]
97  pub enum Axis3 {
98    X=0,
99    Y,
100    Z
101  }
102
103  #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
105  #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
106  #[repr(u8)]
107  pub enum Axis4 {
108    X=0,
109    Y,
110    Z,
111    W
112  }
113
114  #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
116  #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
117  #[repr(u8)]
118  pub enum SignedAxis1 {
119    NegX, PosX
120  }
121
122  #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
124  #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
125  #[repr(u8)]
126  pub enum SignedAxis2 {
127    NegX, PosX,
128    NegY, PosY
129  }
130
131  #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
133  #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
134  #[repr(u8)]
135  pub enum SignedAxis3 {
136    NegX, PosX,
137    NegY, PosY,
138    NegZ, PosZ
139  }
140
141  #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
143  #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
144  #[repr(u8)]
145  pub enum SignedAxis4 {
146    NegX, PosX,
147    NegY, PosY,
148    NegZ, PosZ,
149    NegW, PosW
150  }
151}
152
153#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
159#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, PartialOrd)]
160pub struct Positive <S> (S);
161
162#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
164#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, PartialOrd)]
165pub struct NonNegative <S> (S);
166
167#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
169#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
170pub struct NonZero <S> (S);
171
172#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
174#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
175pub struct Normalized <S> (S);
176
177#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
179#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
180pub struct NormalSigned <S> (S);
181
182#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
188#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
189pub struct Angles3 <S> {
190  pub yaw   : AngleWrapped <S>,
191  pub pitch : AngleWrapped <S>,
192  pub roll  : AngleWrapped <S>
193}
194
195#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
197#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
198pub struct Pose3 <S> {
199  pub position : Point3  <S>,
200  pub angles   : Angles3 <S>
201}
202
203#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Display)]
205#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
206#[display("{}", _0)]
207pub struct LinearIso <S, V, W, M> (M, PhantomData <(S, V, W)>);
208
209#[derive(Clone, Copy, Debug, Default, PartialEq, Deref, Display, From)]
211#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
212#[display("{}", _0)]
213pub struct LinearAuto <S, V> (pub LinearIso <S, V, V, V::LinearEndo>) where
214  V : Module <S>,
215  V::LinearEndo : MaybeSerDes,
216  S : Ring;
217
218#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
221#[cfg_attr(feature = "derive_serdes", serde(bound = "S : MaybeSerDes"))]
222#[derive(Clone, Copy, Debug, Default, PartialEq)]
223pub struct Rotation2 <S> (LinearAuto <S, Vector2 <S>>) where S : Ring + MaybeSerDes;
224
225#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
228#[cfg_attr(feature = "derive_serdes", serde(bound = "S : MaybeSerDes"))]
229#[derive(Clone, Copy, Debug, Default, PartialEq)]
230pub struct Rotation3 <S> (LinearAuto <S, Vector3 <S>>) where S : Ring + MaybeSerDes;
231
232#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
234#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
235pub struct Versor <S> (Quaternion <S>) where S : num::Zero + num::One;
236
237#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Display)]
239#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
240#[display("({}, {})", linear_map, translation)]
241pub struct AffineMap <S, A, B, M> where
242  A : AffineSpace <S>,
243  B : AffineSpace <S>,
244  S : Field,
245  M : LinearMap <S, A::Translation, B::Translation>
246{
247  pub linear_map  : M,
248  pub translation : B::Translation,
249  pub _phantom    : PhantomData <(A, S)>
250}
251
252#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Display)]
254#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
255#[display("({}, {})", linear_iso, translation)]
256pub struct Affinity <S, A, B, M> where
257  S : Field,
258  A : AffineSpace <S>,
259  B : AffineSpace <S>,
260  M : LinearMap <S, A::Translation, B::Translation>
261{
262  pub linear_iso  : LinearIso <S, A::Translation, B::Translation, M>,
263  pub translation : B::Translation
264}
265
266#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Display)]
268#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
269#[display("{}", _0)]
270pub struct Projectivity <S, P, Q, M> (
271  pub LinearIso <S, P::Translation, Q::Translation, M>
272) where
273  S : Field,
274  P : ProjectiveSpace <S>,
275  Q : ProjectiveSpace <S>;
276
277impl <S : Real> Angle <S> for Deg <S> {
285  fn full_turn() -> Self {
286    Deg (S::ten() * S::nine() * S::two() * S::two())
287  }
288  fn half_turn() -> Self {
289    Deg (S::ten() * S::nine() * S::two())
290  }
291}
292impl <S : Real> Trig for Deg <S> {
293  fn sin     (self) -> Self {
294    Rad::from (self).sin().into()
295  }
296  fn sin_cos (self) -> (Self, Self) {
297    let (sin, cos) = Rad::from (self).sin_cos();
298    (sin.into(), cos.into())
299  }
300  fn cos     (self) -> Self {
301    Rad::from (self).cos().into()
302  }
303  fn tan     (self) -> Self {
304    Rad::from (self).tan().into()
305  }
306  fn asin    (self) -> Self {
307    Rad::from (self).asin().into()
308  }
309  fn acos    (self) -> Self {
310    Rad::from (self).acos().into()
311  }
312  fn atan    (self) -> Self {
313    Rad::from (self).atan().into()
314  }
315  fn atan2   (self, other : Self) -> Self {
316    Rad::from (self).atan2 (Rad::from (other)).into()
317  }
318}
319impl <S : Real> From <Rad <S>> for Deg <S> {
320  fn from (radians : Rad <S>) -> Self {
321    let full_turns = radians / Rad::full_turn();
322    Deg::full_turn() * full_turns
323  }
324}
325impl <S : Real> From <Turn <S>> for Deg <S> {
326  fn from (turns : Turn <S>) -> Self {
327    Deg (turns.0 * Deg::full_turn().0)
328  }
329}
330
331impl <S : Real> Angle <S> for Rad <S> {
335  fn full_turn() -> Self {
336    Rad (S::pi() * S::two())
337  }
338}
339impl <S : Real> Trig for Rad <S> {
340  fn sin     (self) -> Self {
341    Rad (self.0.sin())
342  }
343  fn sin_cos (self) -> (Self, Self) {
344    let (sin, cos) = self.0.sin_cos();
345    (Rad (sin), Rad (cos))
346  }
347  fn cos     (self) -> Self {
348    Rad (self.0.cos())
349  }
350  fn tan     (self) -> Self {
351    Rad (self.0.tan())
352  }
353  fn asin    (self) -> Self {
354    Rad (self.0.asin())
355  }
356  fn acos    (self) -> Self {
357    Rad (self.0.acos())
358  }
359  fn atan    (self) -> Self {
360    Rad (self.0.atan())
361  }
362  fn atan2   (self, other : Self) -> Self {
363    Rad (self.0.atan2 (other.0))
364  }
365}
366impl <S : Real> From <Deg <S>> for Rad <S> {
367  fn from (degrees : Deg <S>) -> Self {
368    let full_turns = degrees / Deg::full_turn();
369    Rad::full_turn() * full_turns
370  }
371}
372impl <S : Real> From <Turn <S>> for Rad <S> {
373  fn from (turns : Turn <S>) -> Self {
374    Rad (turns.0 * Rad::full_turn().0)
375  }
376}
377
378impl <S : Real> Angle <S> for Turn <S> {
382  fn full_turn() -> Self {
383    Turn (S::one())
384  }
385  fn half_turn() -> Self {
386    Turn (S::half())
387  }
388}
389impl <S : Real> Trig for Turn <S> {
390  fn sin     (self) -> Self {
391    Rad::from (self).sin().into()
392  }
393  fn sin_cos (self) -> (Self, Self) {
394    let (sin, cos) = Rad::from (self).sin_cos();
395    (sin.into(), cos.into())
396  }
397  fn cos     (self) -> Self {
398    Rad::from (self).cos().into()
399  }
400  fn tan     (self) -> Self {
401    Rad::from (self).tan().into()
402  }
403  fn asin    (self) -> Self {
404    Rad::from (self).asin().into()
405  }
406  fn acos    (self) -> Self {
407    Rad::from (self).acos().into()
408  }
409  fn atan    (self) -> Self {
410    Rad::from (self).atan().into()
411  }
412  fn atan2   (self, other : Self) -> Self {
413    Rad::from (self).atan2 (Rad::from (other)).into()
414  }
415}
416impl <S : Real> From <Rad <S>> for Turn <S> {
417  fn from (radians : Rad <S>) -> Self {
418    Turn (radians.0 / Rad::full_turn().0)
419  }
420}
421impl <S : Real> From <Deg <S>> for Turn <S> {
422  fn from (degrees : Deg <S>) -> Self {
423    Turn (degrees.0 / Deg::full_turn().0)
424  }
425}
426
427impl <S : Real> AngleWrapped <S> {
431  pub fn wrap (angle : Rad <S>) -> Self {
432    AngleWrapped (angle.wrap_unsigned())
433  }
434
435  pub fn map <F> (self, f : F) -> Self where
436    F : FnOnce (Rad <S>) -> Rad <S>
437  {
438    AngleWrapped (f (self.0).wrap_unsigned())
439  }
440}
441
442impl <S : Real> AngleWrappedSigned <S> {
446  pub fn wrap (angle : Rad <S>) -> Self {
447    AngleWrappedSigned (angle.wrap_signed())
448  }
449
450  pub fn map <F> (self, f : F) -> Self where
451    F : FnOnce (Rad <S>) -> Rad <S>
452  {
453    AngleWrappedSigned (f (self.0).wrap_signed())
454  }
455}
456
457impl <S : Real> Angles3 <S> {
462  pub const fn new (
463    yaw   : AngleWrapped <S>,
464    pitch : AngleWrapped <S>,
465    roll  : AngleWrapped <S>
466  ) -> Self {
467    Angles3 { yaw, pitch, roll }
468  }
469
470  pub fn zero() -> Self {
471    use num::Zero;
472    Angles3::new (
473      AngleWrapped::zero(),
474      AngleWrapped::zero(),
475      AngleWrapped::zero())
476  }
477
478  pub fn wrap (yaw : Rad <S>, pitch : Rad <S>, roll : Rad <S>) -> Self {
479    let yaw   = AngleWrapped::wrap (yaw);
480    let pitch = AngleWrapped::wrap (pitch);
481    let roll  = AngleWrapped::wrap (roll);
482    Angles3 { yaw, pitch, roll }
483  }
484}
485
486impl <S> From <Rotation3 <S>> for Angles3 <S> where S : Real + MaybeSerDes {
487  fn from (rotation : Rotation3 <S>) -> Self {
488    let (yaw, pitch, roll) = {
489      let (yaw, pitch, roll) = rotation.intrinsic_angles();
490      ( AngleWrapped::wrap (yaw),
491        AngleWrapped::wrap (pitch),
492        AngleWrapped::wrap (roll)
493      )
494    };
495    Angles3 { yaw, pitch, roll }
496  }
497}
498
499impl Axis2 {
503  #[inline]
504  pub const fn component (self) -> usize {
505    self as usize
506  }
507}
508
509impl Axis3 {
513  #[inline]
514  pub const fn component (self) -> usize {
515    self as usize
516  }
517}
518
519impl SignedAxis3 {
523  pub fn try_from <S : Field> (vector : &Vector3 <S>) -> Option <Self> {
524    if *vector == [ S::one(),   S::zero(),  S::zero()].into() {
525      Some (SignedAxis3::PosX)
526    } else if *vector == [-S::one(),   S::zero(),  S::zero()].into() {
527      Some (SignedAxis3::NegX)
528    } else if *vector == [ S::zero(),  S::one(),   S::zero()].into() {
529      Some (SignedAxis3::PosY)
530    } else if *vector == [ S::zero(), -S::one(),   S::zero()].into() {
531      Some (SignedAxis3::NegY)
532    } else if *vector == [ S::zero(),  S::zero(),  S::one() ].into() {
533      Some (SignedAxis3::PosZ)
534    } else if *vector == [ S::zero(),  S::zero(), -S::one() ].into() {
535      Some (SignedAxis3::NegZ)
536    } else {
537      None
538    }
539  }
540
541  pub fn to_vec <S : Field> (self) -> Vector3 <S> {
542    match self {
543      SignedAxis3::NegX => [-S::one(),   S::zero(),  S::zero()].into(),
544      SignedAxis3::PosX => [ S::one(),   S::zero(),  S::zero()].into(),
545      SignedAxis3::NegY => [ S::zero(), -S::one(),   S::zero()].into(),
546      SignedAxis3::PosY => [ S::zero(),  S::one(),   S::zero()].into(),
547      SignedAxis3::NegZ => [ S::zero(),  S::zero(), -S::one() ].into(),
548      SignedAxis3::PosZ => [ S::zero(),  S::zero(),  S::one() ].into()
549    }
550  }
551  #[inline]
552  pub fn to_unit <S> (self) -> Unit3 <S> where S : Real + std::fmt::Debug {
553    Unit3::unchecked (self.to_vec())
554  }
555}
556
557impl Quadrant {
561  pub fn from_vec_strict <S> (vector : &Vector2 <S>) -> Option <Quadrant> where
564    S : Ring + SignedExt
565  {
566    let sign_x = vector.x.sign();
567    let sign_y = vector.y.sign();
568    let quadrant = match (sign_x, sign_y) {
569      (Sign::Zero,          _) |
570      (         _, Sign::Zero) => return None,
571      (Sign::Positive, Sign::Positive) => Quadrant::PosPos,
572      (Sign::Negative, Sign::Positive) => Quadrant::NegPos,
573      (Sign::Positive, Sign::Negative) => Quadrant::PosNeg,
574      (Sign::Negative, Sign::Negative) => Quadrant::NegNeg
575    };
576    Some (quadrant)
577  }
578  #[inline]
580  pub fn from_point_strict <S> (point : &Point2 <S>) -> Option <Quadrant> where
581    S : Ring + SignedExt
582  {
583    Quadrant::from_vec_strict (&point.to_vector())
584  }
585}
586impl Octant {
592  pub fn from_vec_strict <S> (vector : &Vector3 <S>) -> Option <Octant> where
595    S : Ring + SignedExt
596  {
597    let sign_x = vector.x.sign();
598    let sign_y = vector.y.sign();
599    let sign_z = vector.z.sign();
600    let octant = match (sign_x, sign_y, sign_z) {
601      (Sign::Zero,          _,          _) |
602      (         _, Sign::Zero,          _) |
603      (         _,          _, Sign::Zero) => return None,
604      (Sign::Positive, Sign::Positive, Sign::Positive) => Octant::PosPosPos,
605      (Sign::Negative, Sign::Positive, Sign::Positive) => Octant::NegPosPos,
606      (Sign::Positive, Sign::Negative, Sign::Positive) => Octant::PosNegPos,
607      (Sign::Negative, Sign::Negative, Sign::Positive) => Octant::NegNegPos,
608      (Sign::Positive, Sign::Positive, Sign::Negative) => Octant::PosPosNeg,
609      (Sign::Negative, Sign::Positive, Sign::Negative) => Octant::NegPosNeg,
610      (Sign::Positive, Sign::Negative, Sign::Negative) => Octant::PosNegNeg,
611      (Sign::Negative, Sign::Negative, Sign::Negative) => Octant::NegNegNeg
612    };
613    Some (octant)
614  }
615  #[inline]
617  pub fn from_point_strict <S> (point : &Point3 <S>) -> Option <Octant> where
618    S : Ring + SignedExt
619  {
620    Octant::from_vec_strict (&point.to_vector())
621  }
622}
623impl <S : OrderedRing> Positive <S> {
629  pub fn new (value : S) -> Option <Self> {
640    if value > S::zero() {
641      Some (Positive (value))
642    } else {
643      None
644    }
645  }
646  pub fn infinity() -> Self where S : num::float::FloatCore {
648    Positive (S::infinity())
649  }
650  pub fn noisy (value : S) -> Self {
659    assert!(value > S::zero());
660    Positive (value)
661  }
662  pub fn unchecked (value : S) -> Self {
672    debug_assert!(value > S::zero());
673    Positive (value)
674  }
675  pub fn map_noisy (self, fun : fn (S) -> S) -> Self {
696    Self::noisy (fun (self.0))
697  }
698}
699impl <S : Field> num::One for Positive <S> {
700  fn one() -> Self {
701    Positive (S::one())
702  }
703}
704impl <S : Ring> std::ops::Deref for Positive <S> {
705  type Target = S;
706  fn deref (&self) -> &S {
707    &self.0
708  }
709}
710impl <S : Ring> std::ops::Mul <Positive <S>> for Positive <S> {
711  type Output = Positive <S>;
712  fn mul (self, rhs : Positive <S>) -> Self::Output {
713    Positive (self.0 * *rhs)
714  }
715}
716impl <S : Ring> std::ops::MulAssign <Positive <S>> for Positive <S> {
717  fn mul_assign (&mut self, rhs : Positive <S>) {
718    self.0 *= *rhs
719  }
720}
721impl <S : Ring> std::ops::Mul <NonNegative <S>> for Positive <S> {
722  type Output = NonNegative <S>;
723  fn mul (self, rhs : NonNegative <S>) -> Self::Output {
724    NonNegative (self.0 * *rhs)
725  }
726}
727impl <S : Ring> std::ops::MulAssign <NonNegative <S>> for Positive <S> {
728  fn mul_assign (&mut self, rhs : NonNegative <S>) {
729    self.0 *= *rhs
730  }
731}
732impl <S : Field> std::ops::Div for Positive <S> {
733  type Output = Self;
734  fn div (self, rhs : Self) -> Self::Output {
735    Positive (self.0 / rhs.0)
736  }
737}
738impl <S : Field> std::ops::DivAssign for Positive <S> {
739  fn div_assign (&mut self, rhs : Self) {
740    self.0 /= rhs.0
741  }
742}
743impl <S : Ring> std::ops::Add for Positive <S> {
744  type Output = Self;
745  fn add (self, rhs : Self) -> Self::Output {
746    Positive (self.0 + rhs.0)
747  }
748}
749impl <S : Ring> std::ops::AddAssign for Positive <S> {
750  fn add_assign (&mut self, rhs : Self) {
751    self.0 += rhs.0
752  }
753}
754impl <S : Ring> std::ops::Add <NonNegative <S>> for Positive <S> {
755  type Output = Self;
756  fn add (self, rhs : NonNegative <S>) -> Self::Output {
757    Positive (self.0 + rhs.0)
758  }
759}
760impl <S : Ring> std::ops::AddAssign <NonNegative <S>> for Positive <S> {
761  fn add_assign (&mut self, rhs : NonNegative <S>) {
762    self.0 += rhs.0
763  }
764}
765impl <S : OrderedRing> NonNegative <S> {
771  pub fn new (value : S) -> Option <Self> {
782    if value >= S::zero() {
783      Some (NonNegative (value))
784    } else {
785      None
786    }
787  }
788  pub fn abs (value : S) -> Self {
798    NonNegative (value.abs())
799  }
800  pub fn noisy (value : S) -> Self {
809    assert!(S::zero() <= value);
810    NonNegative (value)
811  }
812  pub fn unchecked (value : S) -> Self {
822    debug_assert!(value >= S::zero());
823    NonNegative (value)
824  }
825  pub fn map_abs (self, fun : fn (S) -> S) -> Self {
835    Self::abs (fun (self.0))
836  }
837  pub fn map_noisy (self, fun : fn (S) -> S) -> Self {
855    Self::noisy (fun (self.0))
856  }
857}
858impl <S : Ring> From <Positive <S>> for NonNegative <S> {
859  fn from (positive : Positive <S>) -> Self {
860    NonNegative (*positive)
861  }
862}
863impl <S : Ring> num::Zero for NonNegative <S> {
864  fn zero() -> Self {
865    NonNegative (S::zero())
866  }
867  fn is_zero (&self) -> bool {
868    self.0.is_zero()
869  }
870}
871impl <S : Field> num::One for NonNegative <S> {
872  fn one() -> Self {
873    NonNegative (S::one())
874  }
875}
876impl <S : Ring> std::ops::Deref for NonNegative <S> {
877  type Target = S;
878  fn deref (&self) -> &S {
879    &self.0
880  }
881}
882impl <S : Ring> std::ops::Mul for NonNegative <S> {
883  type Output = Self;
884  fn mul (self, rhs : Self) -> Self::Output {
885    NonNegative (self.0 * rhs.0)
886  }
887}
888impl <S : Ring> std::ops::Mul <Positive <S>> for NonNegative <S> {
889  type Output = Self;
890  fn mul (self, rhs : Positive <S>) -> Self::Output {
891    NonNegative (self.0 * rhs.0)
892  }
893}
894impl <S : Field> std::ops::Div for NonNegative <S> {
895  type Output = Self;
896  fn div (self, rhs : Self) -> Self::Output {
897    NonNegative (self.0 / rhs.0)
898  }
899}
900impl <S : Ring> std::ops::Add for NonNegative <S> {
901  type Output = Self;
902  fn add (self, rhs : Self) -> Self::Output {
903    NonNegative (self.0 + rhs.0)
904  }
905}
906impl <S : Field> NonZero <S> {
912  #[inline]
923  pub fn new (value : S) -> Option <Self> {
924    if S::zero() != value {
925      Some (NonZero (value))
926    } else {
927      None
928    }
929  }
930  #[inline]
939  pub fn noisy (value : S) -> Self {
940    assert!(S::zero() != value);
941    NonZero (value)
942  }
943  #[inline]
963  pub fn map_noisy (self, fun : fn (S) -> S) -> Self {
964    Self::noisy (fun (self.0))
965  }
966}
967impl <S : Field> num::One for NonZero <S> {
968  fn one() -> Self {
969    NonZero (S::one())
970  }
971}
972impl <S : Field> std::ops::Deref for NonZero <S> {
973  type Target = S;
974  fn deref (&self) -> &S {
975    &self.0
976  }
977}
978impl <S : Field> std::ops::Mul for NonZero <S> {
979  type Output = Self;
980  fn mul (self, rhs : Self) -> Self::Output {
981    NonZero (self.0 * rhs.0)
982  }
983}
984impl <S : Field> Eq  for NonZero <S> { }
985impl <S : OrderedField> Normalized <S> {
991  #[inline]
993  pub fn zero() -> Self {
994    Normalized (S::zero())
995  }
996  #[inline]
997  pub fn is_zero (&self) -> bool {
998    self.0.is_zero()
999  }
1000  #[inline]
1014  pub fn new (value : S) -> Option <Self> {
1015    if S::zero() <= value && value <= S::one() {
1016      Some (Normalized (value))
1017    } else {
1018      None
1019    }
1020  }
1021  #[inline]
1031  #[expect(clippy::same_name_method)]
1032  pub fn clamp (value : S) -> Self {
1033    let value = S::max (S::zero(), S::min (value, S::one()));
1034    Normalized (value)
1035  }
1036  #[inline]
1050  pub fn noisy (value : S) -> Self {
1051    assert!(value <= S::one());
1052    assert!(S::zero() <= value);
1053    Normalized (value)
1054  }
1055  #[inline]
1067  pub fn map_clamp (self, fun : fn (S) -> S) -> Self {
1068    Self::clamp (fun (self.0))
1069  }
1070  #[inline]
1097  pub fn map_noisy (self, fun : fn (S) -> S) -> Self {
1098    Self::noisy (fun (self.0))
1099  }
1100}
1101impl <S : Field> num::One for Normalized <S> {
1102  fn one() -> Self {
1103    Normalized (S::one())
1104  }
1105}
1106impl <S : Field> std::ops::Deref for Normalized <S> {
1107  type Target = S;
1108  fn deref (&self) -> &S {
1109    &self.0
1110  }
1111}
1112impl <S : Field> std::ops::Mul for Normalized <S> {
1113  type Output = Self;
1114  fn mul (self, rhs : Self) -> Self::Output {
1115    Normalized (self.0 * rhs.0)
1116  }
1117}
1118impl <S : Field> Eq  for Normalized <S> { }
1119#[expect(clippy::derive_ord_xor_partial_ord)]
1120impl <S : OrderedField> Ord for Normalized <S> {
1121  fn cmp (&self, other : &Self) -> std::cmp::Ordering {
1122    self.partial_cmp (other).unwrap()
1124  }
1125}
1126impl <S : OrderedField> NormalSigned <S> {
1132  #[inline]
1134  pub fn zero() -> Self {
1135    NormalSigned (S::zero())
1136  }
1137  #[inline]
1138  pub fn is_zero (&self) -> bool {
1139    self.0.is_zero()
1140  }
1141  #[inline]
1155  pub fn new (value : S) -> Option <Self> {
1156    if -S::one() <= value && value <= S::one() {
1157      Some (NormalSigned (value))
1158    } else {
1159      None
1160    }
1161  }
1162  #[inline]
1172  #[expect(clippy::same_name_method)]
1173  pub fn clamp (value : S) -> Self {
1174    let value = S::max (-S::one(), S::min (value, S::one()));
1175    NormalSigned (value)
1176  }
1177  #[inline]
1191  pub fn noisy (value : S) -> Self {
1192    assert!(value <= S::one());
1193    assert!(-S::one() <= value);
1194    NormalSigned (value)
1195  }
1196  #[inline]
1208  pub fn map_clamp (self, fun : fn (S) -> S) -> Self {
1209    Self::clamp (fun (self.0))
1210  }
1211  #[inline]
1238  pub fn map_noisy (self, fun : fn (S) -> S) -> Self {
1239    Self::noisy (fun (self.0))
1240  }
1241}
1242impl <S : OrderedField> From <Normalized <S>> for NormalSigned <S> {
1243  fn from (Normalized (value) : Normalized <S>) -> Self {
1244    debug_assert!(S::zero() <= value);
1245    debug_assert!(value <= S::one());
1246    NormalSigned (value)
1247  }
1248}
1249impl <S : Field> num::One for NormalSigned <S> {
1250  fn one() -> Self {
1251    NormalSigned (S::one())
1252  }
1253}
1254impl <S : Field> std::ops::Deref for NormalSigned <S> {
1255  type Target = S;
1256  fn deref (&self) -> &S {
1257    &self.0
1258  }
1259}
1260impl <S : Field> std::ops::Mul for NormalSigned <S> {
1261  type Output = Self;
1262  fn mul (self, rhs : Self) -> Self::Output {
1263    NormalSigned (self.0 * rhs.0)
1264  }
1265}
1266impl <S : Field> Eq  for NormalSigned <S> { }
1267#[expect(clippy::derive_ord_xor_partial_ord)]
1268impl <S : OrderedField> Ord for NormalSigned <S> {
1269  fn cmp (&self, other : &Self) -> std::cmp::Ordering {
1270    self.partial_cmp (other).unwrap()
1272  }
1273}
1274impl <S : Field> std::ops::Neg for NormalSigned <S> {
1275  type Output = Self;
1276  fn neg (self) -> Self::Output {
1277    NormalSigned (-self.0)
1278  }
1279}
1280impl <S> Rotation2 <S> where S : Ring + MaybeSerDes {
1286  pub fn identity() -> Self {
1288    use num::One;
1289    Self::one()
1290  }
1291  pub fn new (mat : Matrix2 <S>) -> Option <Self> {
1296    let transform = LinearAuto (LinearIso::new (mat)?);
1297    if !transform.is_rotation() {
1298      None
1299    } else {
1300      Some (Rotation2 (transform))
1301    }
1302  }
1303  pub fn new_approx (mat : Matrix2 <S>) -> Option <Self> where
1309    S : approx::RelativeEq <Epsilon=S>
1310  {
1311    let four         = S::one() + S::one() + S::one() + S::one();
1312    let thirtytwo    = four * four * (S::one() + S::one());
1313    let epsilon      = S::default_epsilon() * thirtytwo;
1314    let max_relative = S::default_max_relative() * four;
1315    if approx::relative_ne!(mat * mat.transposed(), Matrix2::identity(),
1316      max_relative=max_relative, epsilon=epsilon
1317    ) || approx::relative_ne!(mat.determinant(), S::one(), max_relative=max_relative) {
1318      None
1319    } else {
1320      Some (Rotation2 (LinearAuto (LinearIso (mat, PhantomData))))
1321    }
1322  }
1323  pub fn from_angle (angle : Rad <S>) -> Self where S : num::real::Real {
1325    Rotation2 (LinearAuto (LinearIso (Matrix2::rotation_z (angle.0), PhantomData)))
1326  }
1327  pub fn noisy (mat : Matrix2 <S>) -> Self where S : std::fmt::Debug {
1331    assert_eq!(mat * mat.transposed(), Matrix2::identity());
1332    assert_eq!(mat.determinant(), S::one());
1333    Rotation2 (LinearAuto (LinearIso (mat, PhantomData)))
1334  }
1335  pub fn noisy_approx (mat : Matrix2 <S>) -> Self where
1340    S : approx::RelativeEq <Epsilon=S> + std::fmt::Debug
1341  {
1342    let four         = S::one() + S::one() + S::one() + S::one();
1343    let epsilon      = S::default_epsilon() * four;
1344    let max_relative = S::default_max_relative() * four;
1345    approx::assert_relative_eq!(mat * mat.transposed(), Matrix2::identity(),
1346      epsilon=epsilon, max_relative=max_relative);
1347    approx::assert_relative_eq!(mat.determinant(), S::one(), max_relative=max_relative);
1348    Rotation2 (LinearAuto (LinearIso (mat, PhantomData)))
1349  }
1350  pub fn unchecked (mat : Matrix2 <S>) -> Self where S : std::fmt::Debug {
1354    debug_assert!(mat * mat.transposed() == Matrix2::identity());
1355    debug_assert!(mat.determinant() == S::one());
1356    Rotation2 (LinearAuto (LinearIso (mat, PhantomData)))
1357  }
1358  pub fn unchecked_approx (mat : Matrix2 <S>) -> Self where
1363    S : approx::RelativeEq <Epsilon=S> + std::fmt::Debug
1364  {
1365    if cfg!(debug_assertions) {
1366      let four         = S::one() + S::one() + S::one() + S::one();
1367      let epsilon      = S::default_epsilon() * four;
1368      let max_relative = S::default_max_relative() * four;
1369      approx::assert_relative_eq!(mat * mat.transposed(), Matrix2::identity(),
1370        max_relative=max_relative, epsilon=epsilon);
1371      approx::assert_relative_eq!(mat.determinant(), S::one(),
1372        max_relative=max_relative);
1373    }
1374    Rotation2 (LinearAuto (LinearIso (mat, PhantomData)))
1375  }
1376  pub const fn mat (self) -> Matrix2 <S> {
1378    self.0.0.0
1379  }
1380  pub fn rotate (self, point : Point2 <S>) -> Point2 <S> {
1382    Point2::from (self * point.0)
1383  }
1384  pub fn rotate_around (self, point : Point2 <S>, center : Point2 <S>) -> Point2 <S> {
1386    self.rotate (point - center.0) + center.0
1387  }
1388}
1389impl <S> std::ops::Deref for Rotation2 <S> where S : Ring + MaybeSerDes {
1390  type Target = LinearAuto <S, Vector2 <S>>;
1391  fn deref (&self) -> &Self::Target {
1392    &self.0
1393  }
1394}
1395impl <S> num::Inv for Rotation2 <S> where S : Ring + MaybeSerDes {
1396  type Output = Self;
1397  fn inv (self) -> Self::Output {
1398    Rotation2 (LinearAuto (LinearIso (self.0.0.0.transpose(), PhantomData)))
1399  }
1400}
1401impl <S> std::ops::Mul <Vector2 <S>> for Rotation2 <S> where S : Ring + MaybeSerDes {
1402  type Output = Vector2 <S>;
1403  fn mul (self, rhs : Vector2 <S>) -> Self::Output {
1404    self.0 * rhs
1405  }
1406}
1407impl <S> std::ops::Mul <Rotation2 <S>> for Vector2 <S> where S : Ring + MaybeSerDes {
1408  type Output = Vector2 <S>;
1409  fn mul (self, rhs : Rotation2 <S>) -> Self::Output {
1410    self * rhs.0
1411  }
1412}
1413impl <S> std::ops::Mul for Rotation2 <S> where S : Ring + MaybeSerDes {
1414  type Output = Self;
1415  fn mul (self, rhs : Self) -> Self::Output {
1416    Rotation2 (self.0 * rhs.0)
1417  }
1418}
1419impl <S> std::ops::MulAssign <Self> for Rotation2 <S> where S : Ring + MaybeSerDes {
1420  fn mul_assign (&mut self, rhs : Self) {
1421    self.0 *= rhs.0
1422  }
1423}
1424impl <S> std::ops::Div for Rotation2 <S> where S : Ring + MaybeSerDes {
1425  type Output = Self;
1426  #[expect(clippy::suspicious_arithmetic_impl)]
1427  fn div (self, rhs : Self) -> Self::Output {
1428    use num::Inv;
1429    self * rhs.inv()
1430  }
1431}
1432impl <S> std::ops::DivAssign <Self> for Rotation2 <S> where S : Ring + MaybeSerDes {
1433  #[expect(clippy::suspicious_op_assign_impl)]
1434  fn div_assign (&mut self, rhs : Self) {
1435    use num::Inv;
1436    *self *= rhs.inv()
1437  }
1438}
1439impl <S> num::One for Rotation2 <S> where S : Ring + MaybeSerDes + num::Zero + num::One {
1440  fn one() -> Self {
1441    Rotation2 (LinearAuto (LinearIso (Matrix2::identity(), PhantomData)))
1442  }
1443}
1444
1445impl <S> Rotation3 <S> where S : Ring + MaybeSerDes {
1449  pub fn identity() -> Self {
1451    use num::One;
1452    Self::one()
1453  }
1454  pub fn new (mat : Matrix3 <S>) -> Option <Self> {
1459    if mat * mat.transposed() != Matrix3::identity() || mat.determinant() != S::one() {
1460      None
1461    } else {
1462      Some (Rotation3 (LinearAuto (LinearIso (mat, PhantomData))))
1463    }
1464  }
1465  pub fn new_approx (mat : Matrix3 <S>) -> Option <Self> where
1471    S : approx::RelativeEq <Epsilon=S>
1472  {
1473    let four         = S::one() + S::one() + S::one() + S::one();
1474    let thirtytwo    = four * four * (S::one() + S::one());
1475    let epsilon      = S::default_epsilon() * thirtytwo;
1476    let max_relative = S::default_max_relative() * four;
1477    if approx::relative_ne!(mat * mat.transposed(), Matrix3::identity(),
1478      max_relative=max_relative, epsilon=epsilon
1479    ) || approx::relative_ne!(mat.determinant(), S::one(), max_relative=max_relative) {
1480      None
1481    } else {
1482      Some (Rotation3 (LinearAuto (LinearIso (mat, PhantomData))))
1483    }
1484  }
1485  pub fn noisy (mat : Matrix3 <S>) -> Self {
1489    assert!(mat * mat.transposed() == Matrix3::identity());
1490    assert!(mat.determinant() == S::one());
1491    Rotation3 (LinearAuto (LinearIso (mat, PhantomData)))
1492  }
1493  pub fn noisy_approx (mat : Matrix3 <S>) -> Self where
1498    S : approx::RelativeEq <Epsilon=S> + std::fmt::Debug
1499  {
1500    let four         = S::one() + S::one() + S::one() + S::one();
1501    let eight        = four + S::one() + S::one() + S::one() + S::one();
1502    let epsilon      = S::default_epsilon() * four;
1503    let max_relative = S::default_max_relative() * eight;
1504    approx::assert_relative_eq!(mat * mat.transposed(), Matrix3::identity(),
1505      max_relative=max_relative, epsilon=epsilon);
1506    approx::assert_relative_eq!(mat.determinant(), S::one(), max_relative=max_relative);
1507    Rotation3 (LinearAuto (LinearIso (mat, PhantomData)))
1508  }
1509  pub fn unchecked (mat : Matrix3 <S>) -> Self where S : std::fmt::Debug {
1513    debug_assert!(mat * mat.transposed() == Matrix3::identity());
1514    debug_assert!(mat.determinant() == S::one());
1515    Rotation3 (LinearAuto (LinearIso (mat, PhantomData)))
1516  }
1517  pub fn unchecked_approx (mat : Matrix3 <S>) -> Self where
1522    S : approx::RelativeEq <Epsilon=S> + std::fmt::Debug
1523  {
1524    if cfg!(debug_assertions) {
1525      let four         = S::one() + S::one() + S::one() + S::one();
1526      let epsilon      = S::default_epsilon() * four;
1527      let max_relative = S::default_max_relative() * four;
1528      approx::assert_relative_eq!(mat * mat.transposed(), Matrix3::identity(),
1529        max_relative=max_relative, epsilon=epsilon);
1530      approx::assert_relative_eq!(mat.determinant(), S::one(),
1531        max_relative=max_relative);
1532    }
1533    Rotation3 (LinearAuto (LinearIso (mat, PhantomData)))
1534  }
1535  pub fn from_angle_x (angle : Rad <S>) -> Self where S : num::real::Real {
1539    Rotation3 (LinearAuto (LinearIso (Matrix3::rotation_x (angle.0), PhantomData)))
1540  }
1541  pub fn from_angle_y (angle : Rad <S>) -> Self where S : num::real::Real {
1545    Rotation3 (LinearAuto (LinearIso (Matrix3::rotation_y (angle.0), PhantomData)))
1546  }
1547  pub fn from_angle_z (angle : Rad <S>) -> Self where S : num::real::Real {
1551    Rotation3 (LinearAuto (LinearIso (Matrix3::rotation_z (angle.0), PhantomData)))
1552  }
1553  pub fn from_angles_intrinsic (yaw : Rad <S>, pitch : Rad <S>, roll : Rad <S>)
1559    -> Self where S : num::real::Real
1560  {
1561    let rotation1 = Rotation3::from_angle_z (yaw);
1562    let rotation2 = Rotation3::from_axis_angle (rotation1.cols.x, pitch) * rotation1;
1563    Rotation3::from_axis_angle (rotation2.cols.y, roll) * rotation2
1564  }
1565  pub fn from_axis_angle (axis : Vector3 <S>, angle : Rad <S>) -> Self where
1567    S : num::real::Real
1568  {
1569    Rotation3 (LinearAuto (LinearIso (
1570      Matrix3::rotation_3d (angle.0, axis), PhantomData)))
1571  }
1572  pub fn orthonormalize (v1 : Vector3 <S>, v2 : Vector3 <S>, v3 : Vector3 <S>)
1575    -> Option <Self> where S : Field + Sqrt
1576  {
1577    if Matrix3::from_col_arrays ([v1, v2, v3].map (Vector3::into_array)).determinant()
1578      == S::zero()
1579    {
1580      None
1581    } else {
1582      let project = |u : Vector3 <S>, v : Vector3 <S>| u * (u.dot (v) / u.self_dot());
1583      let u1 = v1;
1584      let u2 = v2 - project (u1, v2);
1585      let u3 = v3 - project (u1, v3) - project (u2, v3);
1586      Some (Rotation3 (LinearAuto (LinearIso (Matrix3::from_col_arrays ([
1587        u1.normalize().into_array(),
1588        u2.normalize().into_array(),
1589        u3.normalize().into_array()
1590      ]), PhantomData))))
1591    }
1592  }
1593
1594  pub fn look_at (point : Point3 <S>) -> Self where
1598    S : num::Float + num::FloatConst + approx::RelativeEq <Epsilon=S> + std::fmt::Debug
1599  {
1600    if point == Point::origin() {
1601      Self::identity()
1602    } else {
1603      use num::Zero;
1604      let forward = point.0.normalized();
1605      let right = {
1606        let projected = forward.with_z (S::zero());
1607        if !projected.is_zero() {
1608          Self::from_angle_z (-Rad (S::FRAC_PI_2())) * projected.normalized()
1609        } else {
1610          Vector3::unit_x()
1611        }
1612      };
1613      let up = right.cross (forward);
1614      let mat =
1615        Matrix3::from_col_arrays ([right, forward, up].map (Vector3::into_array));
1616      Self::noisy_approx (mat)
1617    }
1618  }
1619
1620  pub fn intrinsic_angles (&self) -> (Rad <S>, Rad <S>, Rad <S>) where S : Real {
1625    let cols  = &self.cols;
1626    let yaw   = Rad (S::atan2 (-cols.y.x, cols.y.y));
1627    let pitch = Rad (S::atan2 (cols.y.z, S::sqrt (S::one() - cols.y.z * cols.y.z)));
1628    let roll  = Rad (S::atan2 (-cols.x.z, cols.z.z));
1629    (yaw, pitch, roll)
1630  }
1631
1632  pub fn versor (self) -> Versor <S> where
1636    S : Real + MaybeSerDes + num::real::Real + approx::RelativeEq <Epsilon=S>
1637  {
1638    let diagonal = self.diagonal();
1639    let t     = diagonal.sum();
1640    let m     = MinMax::max (MinMax::max (MinMax::max (
1641      diagonal.x, diagonal.y), diagonal.z), t);
1642    let qmax  = S::half() * Sqrt::sqrt (S::one() - t + S::two() * m);
1643    let qmax4_recip = (S::four() * qmax).recip();
1644    let [qx, qy, qz, qw] : [S; 4];
1645    let cols = self.cols;
1646    if m == diagonal.x {
1647      qx = qmax;
1648      qy = qmax4_recip * (cols.x.y + cols.y.x);
1649      qz = qmax4_recip * (cols.x.z + cols.z.x);
1650      qw = -qmax4_recip * (cols.z.y - cols.y.z);
1651    } else if m == diagonal.y {
1652      qx = qmax4_recip * (cols.x.y + cols.y.x);
1653      qy = qmax;
1654      qz = qmax4_recip * (cols.y.z + cols.z.y);
1655      qw = -qmax4_recip * (cols.x.z - cols.z.x);
1656    } else if m == diagonal.z {
1657      qx = qmax4_recip * (cols.x.z + cols.z.x);
1658      qy = qmax4_recip * (cols.y.z + cols.z.y);
1659      qz = qmax;
1660      qw = -qmax4_recip * (cols.y.x - cols.x.y);
1661    } else {
1662      qx = -qmax4_recip * (cols.z.y - cols.y.z);
1663      qy = -qmax4_recip * (cols.x.z - cols.z.x);
1664      qz = -qmax4_recip * (cols.y.x - cols.x.y);
1665      qw = qmax;
1666    }
1667    let quat = Quaternion::from_xyzw (qx, qy, qz, qw);
1668    Versor::unchecked_approx (quat)
1669  }
1670  pub const fn mat (self) -> Matrix3 <S> {
1672    self.0.0.0
1673  }
1674  pub fn rotate (self, point : Point3 <S>) -> Point3 <S> {
1676    Point3::from (self * point.0)
1677  }
1678  pub fn rotate_around (self, point : Point3 <S>, center : Point3 <S>) -> Point3 <S> {
1680    self.rotate (point - center.0) + center.0
1681  }
1682}
1683impl <S> std::ops::Deref for Rotation3 <S> where S : Ring + MaybeSerDes {
1684  type Target = LinearAuto <S, Vector3 <S>>;
1685  fn deref (&self) -> &Self::Target {
1686    &self.0
1687  }
1688}
1689impl <S> num::Inv for Rotation3 <S> where S : Ring + MaybeSerDes {
1690  type Output = Self;
1691  fn inv (self) -> Self::Output {
1692    Rotation3 (LinearAuto (LinearIso (self.0.0.0.transpose(), PhantomData)))
1693  }
1694}
1695impl <S> std::ops::Mul <Vector3 <S>> for Rotation3 <S> where S : Ring + MaybeSerDes {
1696  type Output = Vector3 <S>;
1697  fn mul (self, rhs : Vector3 <S>) -> Self::Output {
1698    self.0 * rhs
1699  }
1700}
1701impl <S> std::ops::Mul <Rotation3 <S>> for Vector3 <S> where S : Ring + MaybeSerDes {
1702  type Output = Vector3 <S>;
1703  fn mul (self, rhs : Rotation3 <S>) -> Self::Output {
1704    self * rhs.0
1705  }
1706}
1707impl <S> std::ops::Mul for Rotation3 <S> where S : Ring + MaybeSerDes {
1708  type Output = Self;
1709  fn mul (self, rhs : Self) -> Self::Output {
1710    Rotation3 (self.0 * rhs.0)
1711  }
1712}
1713impl <S> std::ops::MulAssign <Self> for Rotation3 <S> where S : Ring + MaybeSerDes {
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  #[expect(clippy::suspicious_arithmetic_impl)]
1721  fn div (self, rhs : Self) -> Self::Output {
1722    use num::Inv;
1723    self * rhs.inv()
1724  }
1725}
1726impl <S> std::ops::DivAssign <Self> for Rotation3 <S> where S : Ring + MaybeSerDes {
1727  #[expect(clippy::suspicious_op_assign_impl)]
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 S : Ring + MaybeSerDes + num::Zero + num::One {
1734  fn one() -> Self {
1735    Rotation3 (LinearAuto (LinearIso (Matrix3::identity(), PhantomData)))
1736  }
1737}
1738impl <S> From <Angles3 <S>> for Rotation3 <S> where
1739  S : Real + num::real::Real + MaybeSerDes
1740{
1741  fn from (angles : Angles3 <S>) -> Self {
1742    Rotation3::from_angles_intrinsic (
1743      angles.yaw.angle(), angles.pitch.angle(), angles.roll.angle())
1744  }
1745}
1746
1747impl <S : Real> Versor <S> {
1751  pub fn normalize (quaternion : Quaternion <S>) -> Self where S : std::fmt::Debug {
1755    assert_ne!(quaternion, Quaternion::zero());
1756    Versor (normalize_quaternion (quaternion))
1757  }
1758  pub fn noisy (unit_quaternion : Quaternion <S>) -> Self where
1762    S : num::real::Real + std::fmt::Debug
1763  {
1764    assert_eq!(unit_quaternion, normalize_quaternion (unit_quaternion));
1765    Versor (unit_quaternion)
1766  }
1767  pub fn noisy_approx (unit_quaternion : Quaternion <S>) -> Self where
1771    S : num::real::Real + approx::RelativeEq <Epsilon=S>
1772  {
1773    assert!(unit_quaternion.into_vec4().is_normalized());
1774    Versor (unit_quaternion)
1775  }
1776  pub fn unchecked (unit_quaternion : Quaternion <S>) -> Self where S : std::fmt::Debug {
1780    debug_assert_eq!(unit_quaternion, normalize_quaternion (unit_quaternion));
1781    Versor (unit_quaternion)
1782  }
1783  pub fn unchecked_approx (unit_quaternion : Quaternion <S>) -> Self where
1787    S : num::real::Real + approx::RelativeEq <Epsilon=S>
1788  {
1789    debug_assert!(unit_quaternion.into_vec4().is_normalized());
1790    Versor (unit_quaternion)
1791  }
1792  pub fn from_scaled_axis (scaled_axis : Vector3 <S>) -> Self where
1795    S : std::fmt::Debug + num::Float
1796  {
1797    if scaled_axis == Vector3::zero() {
1798      let versor = Quaternion::rotation_3d (S::zero(), scaled_axis);
1799      debug_assert_eq!(versor.magnitude(), S::one());
1800      Versor (versor)
1801    } else {
1802      let angle = scaled_axis.magnitude();
1803      debug_assert!(S::zero() < angle);
1804      let axis  = scaled_axis / angle;
1805      Versor (Quaternion::rotation_3d (angle, axis))
1806    }
1807  }
1808}
1809impl <S> std::ops::Mul <Vector3 <S>> for Versor <S> where S : Real + num::Float {
1810  type Output = Vector3 <S>;
1811  fn mul (self, rhs : Vector3 <S>) -> Self::Output {
1812    self.0 * rhs
1813  }
1814}
1815impl <S> From <Rotation3 <S>> for Versor <S> where
1816  S : Real + MaybeSerDes + num::real::Real + approx::RelativeEq <Epsilon=S>
1817{
1818  fn from (rot : Rotation3 <S>) -> Self {
1819    rot.versor()
1820  }
1821}
1822impl <S : Real> std::ops::Deref for Versor <S> {
1823  type Target = Quaternion <S>;
1824  fn deref (&self) -> &Quaternion <S> {
1825    &self.0
1826  }
1827}
1828impl <S, V, W, M> LinearIso <S, V, W, M> where
1834  M : LinearMap <S, V, W> + Copy,
1835  V : Module <S>,
1836  W : Module <S>,
1837  S : Ring
1838{
1839  pub fn mat (self) -> M {
1840    *self
1841  }
1842  pub fn is_invertible (linear_map : M) -> bool {
1844    linear_map.determinant() != S::zero()
1845  }
1846  pub fn is_invertible_approx (linear_map : M, epsilon : Option <S>) -> bool where
1848    S : approx::AbsDiffEq <Epsilon=S>
1849  {
1850    let epsilon = epsilon.unwrap_or_else (||{
1851      let four = S::one() + S::one() + S::one() + S::one();
1852      S::default_epsilon() * four
1853    });
1854    approx::abs_diff_ne!(linear_map.determinant(), S::zero(), epsilon=epsilon)
1855  }
1856  pub fn new (linear_map : M) -> Option <Self> {
1858    if Self::is_invertible (linear_map) {
1859      Some (LinearIso (linear_map, PhantomData))
1860    } else {
1861      None
1862    }
1863  }
1864  pub fn new_approx (linear_map : M, epsilon : Option <S>) -> Option <Self> where
1866    S : approx::RelativeEq <Epsilon=S>
1867  {
1868    if Self::is_invertible_approx (linear_map, epsilon) {
1869      Some (LinearIso (linear_map, PhantomData))
1870    } else {
1871      None
1872    }
1873  }
1874}
1875impl <S, V, W, M> std::ops::Deref for LinearIso <S, V, W, M> where
1876  M : LinearMap <S, V, W>,
1877  V : Module <S>,
1878  W : Module <S>,
1879  S : Ring
1880{
1881  type Target = M;
1882  fn deref (&self) -> &Self::Target {
1883    &self.0
1884  }
1885}
1886impl <S, V> num::One for LinearIso <S, V, V, V::LinearEndo> where
1887  V : Module <S>,
1888  S : Ring
1889{
1890  fn one () -> Self {
1891    LinearIso (V::LinearEndo::one(), PhantomData)
1892  }
1893}
1894impl <S, V, W, M> std::ops::Mul <V> 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 Output = W;
1901  fn mul (self, rhs : V) -> Self::Output {
1902    self.0 * rhs
1903  }
1904}
1905impl <S, V> std::ops::Mul for LinearIso <S, V, V, V::LinearEndo> where
1906  V : Module <S>,
1907  S : Ring
1908{
1909  type Output = Self;
1910  fn mul (self, rhs : Self) -> Self::Output {
1911    LinearIso (self.0 * rhs.0, PhantomData)
1912  }
1913}
1914impl <S, V> std::ops::MulAssign for LinearIso <S, V, V, V::LinearEndo> where
1915  V : Module <S>,
1916  S : Ring
1917{
1918  fn mul_assign (&mut self, rhs : Self) {
1919    self.0 *= rhs.0
1920  }
1921}
1922
1923impl <S, V> LinearAuto <S, V> where
1927  V : Module <S>,
1928  V::LinearEndo : MaybeSerDes,
1929  S : Ring
1930{
1931  pub fn mat (self) -> V::LinearEndo {
1932    **self
1933  }
1934  pub fn is_orthonormal (&self) -> bool {
1939    use num::One;
1940    let determinant = self.0.0.determinant();
1941    self.0.0 * self.0.0.transpose() == V::LinearEndo::one() &&
1942    (determinant == S::one() || determinant == -S::one())
1943  }
1944  pub fn is_orthonormal_approx (&self) -> bool where
1950    S : approx::RelativeEq <Epsilon=S>,
1951    V::LinearEndo : approx::RelativeEq <Epsilon=S>
1952  {
1953    use num::One;
1954    let four         = S::one() + S::one() + S::one() + S::one();
1955    let epsilon      = S::default_epsilon() * four;
1956    let max_relative = S::default_max_relative() * four;
1957    let determinant  = self.0.0.determinant();
1958    approx::relative_eq!(self.0.0 * self.0.0.transpose(), V::LinearEndo::one(),
1959      max_relative=max_relative, epsilon=epsilon) &&
1960    ( approx::relative_eq!(determinant,  S::one(), max_relative=max_relative) ||
1961      approx::relative_eq!(determinant, -S::one(), max_relative=max_relative) )
1962  }
1963  pub fn is_rotation (&self) -> bool {
1967    use num::One;
1968    let determinant = self.0.0.determinant();
1969    self.0.0 * self.0.0.transpose() == V::LinearEndo::one() &&
1970    determinant == S::one()
1971  }
1972  pub fn is_rotation_approx (&self) -> bool where
1977    S : approx::RelativeEq <Epsilon=S>,
1978    V::LinearEndo : approx::RelativeEq <Epsilon=S>
1979  {
1980    use num::One;
1981    let four         = S::one() + S::one() + S::one() + S::one();
1982    let epsilon      = S::default_epsilon() * four;
1983    let max_relative = S::default_max_relative() * four;
1984    let determinant  = self.0.0.determinant();
1985    approx::relative_eq!(self.0.0 * self.0.0.transpose(), V::LinearEndo::one(),
1986      max_relative=max_relative, epsilon=epsilon) &&
1987    approx::relative_eq!(determinant,  S::one(), max_relative=max_relative)
1988  }
1989}
1990impl <S, V> std::ops::Mul <V> for LinearAuto <S, V> where
1991  V : Module <S>,
1992  V::LinearEndo : MaybeSerDes,
1993  S : Ring
1994{
1995  type Output = V;
1996  fn mul (self, rhs : V) -> Self::Output {
1997    self.0 * rhs
1998  }
1999}
2000impl <S, V> std::ops::Mul for LinearAuto <S, V> where
2001  V : Module <S>,
2002  V::LinearEndo : MaybeSerDes,
2003  S : Ring
2004{
2005  type Output = Self;
2006  fn mul (self, rhs : Self) -> Self::Output {
2007    LinearAuto (self.0 * rhs.0)
2008  }
2009}
2010impl <S, V> std::ops::MulAssign <Self> for LinearAuto <S, V> where
2011  V : Module <S>,
2012  V::LinearEndo : MaybeSerDes,
2013  S : Ring
2014{
2015  fn mul_assign (&mut self, rhs : Self) {
2016    self.0 *= rhs.0
2017  }
2018}
2019impl <S, V> num::One for LinearAuto <S, V> where
2020  V : Module <S>,
2021  V::LinearEndo : MaybeSerDes,
2022  S : Ring
2023{
2024  fn one() -> Self {
2025    LinearAuto (LinearIso::one())
2026  }
2027}
2028
2029impl <S, A, B, M> AffineMap <S, A, B, M> where
2033  A : AffineSpace <S>,
2034  B : AffineSpace <S>,
2035  M : LinearMap <S, A::Translation, B::Translation>,
2036  S : Field
2037{
2038  pub const fn new (linear_map : M, translation : B::Translation) -> Self {
2039    AffineMap { linear_map, translation, _phantom: PhantomData }
2040  }
2041  pub fn map (self, point : A) -> B {
2042    B::from_vector (self.linear_map * point.to_vector() + self.translation)
2043  }
2044  pub fn transform (self, translation : A::Translation) -> B::Translation {
2045    self.linear_map * translation
2046  }
2047}
2048
2049impl <S, A, B, M> Affinity <S, A, B, M> where
2053  M : LinearMap <S, A::Translation, B::Translation>,
2054  A : AffineSpace <S>,
2055  B : AffineSpace <S>,
2056  S : Field
2057{
2058  pub const fn new (
2059    linear_iso  : LinearIso <S, A::Translation, B::Translation, M>,
2060    translation : B::Translation
2061  ) -> Self {
2062    Affinity { linear_iso, translation }
2063  }
2064  pub fn mat (self) -> M {
2065    *self.linear_iso
2066  }
2067  pub fn map (self, point : A) -> B {
2068    B::from_vector (self.linear_iso * point.to_vector() + self.translation)
2069  }
2070  pub fn transform (self, translation : A::Translation) -> B::Translation {
2071    self.linear_iso * translation
2072  }
2073}
2074
2075impl <S, P, Q, M> Projectivity <S, P, Q, M> where
2079  M : LinearMap <S, P::Translation, Q::Translation>,
2080  P : ProjectiveSpace <S>,
2081  Q : ProjectiveSpace <S>,
2082  S : Field
2083{
2084  pub const fn new (linear_iso : LinearIso <S, P::Translation, Q::Translation, M>)
2085    -> Self
2086  {
2087    Projectivity (linear_iso)
2088  }
2089  pub fn mat (self) -> M {
2090    **self
2091  }
2092}
2093impl <S, P, Q, M> std::ops::Deref for Projectivity <S, P, Q, M> where
2094  M : LinearMap <S, P::Translation, Q::Translation>,
2095  P : ProjectiveSpace <S>,
2096  Q : ProjectiveSpace <S>,
2097  S : Field
2098{
2099  type Target = LinearIso <S, P::Translation, Q::Translation, M>;
2100  fn deref (&self) -> &Self::Target {
2101    &self.0
2102  }
2103}
2104impl <S, P, Q, M> std::ops::Mul <P> for Projectivity <S, P, Q, M> where
2105  M : LinearMap <S, P::Translation, Q::Translation>,
2106  P : ProjectiveSpace <S>,
2107  Q : ProjectiveSpace <S>,
2108  S : Field
2109{
2110  type Output = Q;
2111  fn mul (self, rhs : P) -> Q {
2112    Q::from_vector (self.0 * rhs.to_vector())
2113  }
2114}
2115
2116pub macro vector {
2117  ($x:expr, $y:expr) => {
2118    $crate::vector2 ($x, $y)
2119  },
2120  ($x:expr, $y:expr, $z:expr) => {
2121    $crate::vector3 ($x, $y, $z)
2122  },
2123  ($x:expr, $y:expr, $z:expr, $w:expr) => {
2124    $crate::vector4 ($x, $y, $z, $w)
2125  }
2126}
2127
2128pub macro matrix {
2129  ($v00:expr, $v01:expr; $v10:expr, $v11:expr$(;)?) => {
2130    $crate::Matrix2::new ($v00, $v01, $v10, $v11)
2131  },
2132  ( $v00:expr, $v01:expr, $v02:expr;
2133    $v10:expr, $v11:expr, $v12:expr;
2134    $v20:expr, $v21:expr, $v22:expr$(;)?
2135  ) => {
2136    $crate::Matrix3::new ($v00, $v01, $v02, $v10, $v11, $v12, $v20, $v21, $v22)
2137  },
2138  ( $v00:expr, $v01:expr, $v02:expr, $v03:expr;
2139    $v10:expr, $v11:expr, $v12:expr, $v13:expr;
2140    $v20:expr, $v21:expr, $v22:expr, $v23:expr;
2141    $v30:expr, $v31:expr, $v32:expr, $v33:expr$(;)?
2142  ) => {
2143    $crate::Matrix4::new (
2144      $v00, $v01, $v02, $v03,
2145      $v10, $v11, $v12, $v13,
2146      $v20, $v21, $v22, $v23,
2147      $v30, $v31, $v32, $v33)
2148  }
2149}
2150
2151macro_rules! impl_angle {
2152  ( $angle:ident, $docname:expr ) => {
2153    #[doc = $docname]
2154    #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
2155    #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, PartialOrd)]
2157    pub struct $angle <S> (pub S);
2158    impl_numcast_primitive!($angle);
2159    impl <S : Ring> std::iter::Sum for $angle <S> {
2160      fn sum <I> (iter : I) -> Self where I : Iterator <Item = Self> {
2161        use num::Zero;
2162        iter.fold ($angle::zero(), |acc, item| acc + item)
2163      }
2164    }
2165    impl <S : Ring> std::ops::Neg for $angle <S> {
2166      type Output = Self;
2167      fn neg (self) -> Self::Output {
2168        $angle (-self.0)
2169      }
2170    }
2171    impl <S : Ring> std::ops::Add for $angle <S> {
2172      type Output = Self;
2173      fn add (self, other : Self) -> Self::Output {
2174        $angle (self.0 + other.0)
2175      }
2176    }
2177    impl <S : Ring> std::ops::AddAssign for $angle <S> {
2178      fn add_assign (&mut self, other : Self) {
2179        self.0 += other.0
2180      }
2181    }
2182    impl <S : Ring> std::ops::Sub for $angle <S> {
2183      type Output = Self;
2184      fn sub (self, other : Self) -> Self::Output {
2185        $angle (self.0 - other.0)
2186      }
2187    }
2188    impl <S : Ring> std::ops::SubAssign for $angle <S> {
2189      fn sub_assign (&mut self, other : Self) {
2190        self.0 -= other.0
2191      }
2192    }
2193    impl <S : Ring> std::ops::Mul <S> for $angle <S> {
2194      type Output = Self;
2195      fn mul (self, scalar : S) -> Self::Output {
2196        $angle (scalar * self.0)
2197      }
2198    }
2199    impl <S : Ring> std::ops::MulAssign <S> for $angle <S> {
2200      fn mul_assign (&mut self, scalar : S) {
2201        self.0 *= scalar
2202      }
2203    }
2204    impl <S : Field> std::ops::Div for $angle <S> {
2205      type Output = S;
2206      fn div (self, other : Self) -> Self::Output {
2207        self.0 / other.0
2208      }
2209    }
2210    impl <S : Field> std::ops::Div <S> for $angle <S> {
2211      type Output = Self;
2212      fn div (self, scalar : S) -> Self::Output {
2213        $angle (self.0 / scalar)
2214      }
2215    }
2216    impl <S : Field> std::ops::DivAssign <S> for $angle <S> {
2217      fn div_assign (&mut self, scalar : S) {
2218        self.0 /= scalar
2219      }
2220    }
2221    impl <S : OrderedField> std::ops::Rem for $angle <S> {
2222      type Output = Self;
2223      fn rem (self, other : Self) -> Self::Output {
2224        $angle (self.0 % other.0)
2225      }
2226    }
2227    impl <S : Ring> num::Zero for $angle <S> {
2228      fn zero() -> Self {
2229        $angle (S::zero())
2230      }
2231      fn is_zero (&self) -> bool {
2232        self.0.is_zero()
2233      }
2234    }
2235    impl <S : Ring> From <S> for $angle <S> {
2236      fn from (s : S) -> Self {
2237        $angle (s)
2238      }
2239    }
2240  }
2241}
2242
2243macro_rules! impl_angle_wrapped {
2244  ( $angle:ident, $comment:expr ) => {
2245    #[doc = $comment]
2246    #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
2247    #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, PartialOrd)]
2248    pub struct $angle <S> (Rad <S>);
2249
2250    impl_numcast!($angle);
2251    impl <S : Real> $angle <S> {
2252      pub const fn angle (&self) -> Rad <S> {
2253        self.0
2254      }
2255    }
2256    impl <S : Real> std::iter::Sum for $angle <S> {
2257      fn sum <I> (iter : I) -> Self where I : Iterator <Item = Self> {
2258        use num::Zero;
2259        iter.fold ($angle::zero(), |acc, item| acc + item)
2260      }
2261    }
2262    impl <S : Real> std::ops::Neg for $angle <S> {
2263      type Output = Self;
2264      fn neg (self) -> Self::Output {
2265        self.map (Rad::neg)
2266      }
2267    }
2268    impl <S : Real> std::ops::Add for $angle <S> {
2269      type Output = Self;
2270      fn add (self, other : Self) -> Self::Output {
2271        self.map (|angle| angle + other.0)
2272      }
2273    }
2274    impl <S : Real> std::ops::AddAssign for $angle <S> {
2275      fn add_assign (&mut self, other : Self) {
2276        *self = *self + other
2277      }
2278    }
2279    impl <S : Real> std::ops::Add <Rad <S>> for $angle <S> {
2280      type Output = Self;
2281      fn add (self, angle : Rad <S>) -> Self::Output {
2282        self.map (|a| a + angle)
2283      }
2284    }
2285    impl <S : Real> std::ops::AddAssign <Rad <S>> for $angle <S> {
2286      fn add_assign (&mut self, angle : Rad <S>) {
2287        *self = *self + angle
2288      }
2289    }
2290    impl <S : Real> std::ops::Sub for $angle <S> {
2291      type Output = Self;
2292      fn sub (self, other : Self) -> Self::Output {
2293        self.map (|angle| angle - other.0)
2294      }
2295    }
2296    impl <S : Real> std::ops::SubAssign for $angle <S> {
2297      fn sub_assign (&mut self, other : Self) {
2298        *self = *self - other
2299      }
2300    }
2301    impl <S : Real> std::ops::Sub <Rad <S>> for $angle <S> {
2302      type Output = Self;
2303      fn sub (self, angle : Rad <S>) -> Self::Output {
2304        self.map (|a| a - angle)
2305      }
2306    }
2307    impl <S : Real> std::ops::SubAssign <Rad <S>> for $angle <S> {
2308      fn sub_assign (&mut self, angle : Rad <S>) {
2309        *self = *self - angle
2310      }
2311    }
2312    impl <S : Real> std::ops::Mul <S> for $angle <S> {
2313      type Output = Self;
2314      fn mul (self, scalar : S) -> Self::Output {
2315        self.map (|angle| angle * scalar)
2316      }
2317    }
2318    impl <S : Real> std::ops::MulAssign <S> for $angle <S> {
2319      fn mul_assign (&mut self, scalar : S) {
2320        *self = *self * scalar
2321      }
2322    }
2323    impl <S : Real> std::ops::Div for $angle <S> {
2324      type Output = S;
2325      fn div (self, other : Self) -> Self::Output {
2326        self.0 / other.0
2327      }
2328    }
2329    impl <S : Real> std::ops::Div <S> for $angle <S> {
2330      type Output = Self;
2331      fn div (self, scalar : S) -> Self::Output {
2332        self.map (|angle| angle / scalar)
2333      }
2334    }
2335    impl <S : Real> std::ops::DivAssign <S> for $angle <S> {
2336      fn div_assign (&mut self, scalar : S) {
2337        *self = *self / scalar
2338      }
2339    }
2340    impl <S : Real> std::ops::Rem for $angle <S> {
2341      type Output = Self;
2342      fn rem (self, other : Self) -> Self::Output {
2343        self.map (|angle| angle % other.0)
2344      }
2345    }
2346    impl <S : Real> num::Zero for $angle <S> {
2347      fn zero() -> Self {
2348        $angle (Rad::zero())
2349      }
2350      fn is_zero (&self) -> bool {
2351        self.0.is_zero()
2352      }
2353    }
2354  }
2355}
2356
2357macro_rules! impl_dimension {
2358  ( $point:ident, $vector:ident, $nonzero:ident, $unit:ident,
2359    $point_fun:ident, $vector_fun:ident, $matrix_fun:ident,
2360    [$($component:ident),+],
2361    [$(($axis_method:ident, $unit_method:ident)),+], [$($patch:ident)?],
2362    [$($projective:ident)?],
2363    $matrix:ident, [$($submatrix:ident)?], $ndims:expr, $dimension:expr
2364  ) => {
2365    #[doc = $dimension]
2366    #[doc = "position"]
2367    #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Display, From, Neg)]
2368    #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
2369    #[display("{}", _0)]
2370    #[repr(C)]
2371    pub struct $point <S> (pub $vector <S>);
2372
2373    #[doc = $dimension]
2374    #[doc = "non-zero vector"]
2375    #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
2376    #[derive(Clone, Copy, Debug, Eq, PartialEq, Display)]
2377    #[display("{}", _0)]
2378    #[repr(C)]
2379    pub struct $nonzero <S> ($vector <S>);
2380
2381    #[doc = $dimension]
2382    #[doc = "unit vector"]
2383    #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
2384    #[derive(Clone, Copy, Debug, Eq, PartialEq, Display)]
2385    #[display("{}", _0)]
2386    #[repr(C)]
2387    pub struct $unit <S> ($vector <S>);
2388
2389    #[doc = "Construct a"]
2393    #[doc = $dimension]
2394    #[doc = "point"]
2395    pub const fn $point_fun <S> ($($component : S),+) -> $point <S> {
2396      $point::new ($($component),+)
2397    }
2398    impl_numcast!($point);
2399    impl <S> $point <S> {
2400      pub const fn new ($($component : S),+) -> Self {
2401        $point ($vector::new ($($component),+))
2402      }
2403      $(
2404      pub const fn $component (&self) -> S where S : Copy {
2405        self.0.$component
2406      }
2407      )+
2408      pub fn distance (self, other : $point <S>) -> S where S : num::real::Real {
2409        self.0.distance (other.0)
2410      }
2411      pub fn distance_squared (self, other : $point <S>) -> S where S : Field {
2412        self.0.distance_squared (other.0)
2413      }
2414    }
2415    $(
2417    impl <S : Field> ProjectiveSpace <S> for $projective <S> {
2418      type Patch = $point <S>;
2419    }
2420    )?
2421    impl <S : Field> AffineSpace <S> for $point <S> {
2422      type Translation = $vector <S>;
2423    }
2424    impl <S : Ring> Point <$vector <S>> for $point <S> {
2425      fn to_vector (self) -> $vector <S> {
2426        self.0
2427      }
2428      fn from_vector (vector : $vector <S>) -> Self {
2429        $point (vector)
2430      }
2431    }
2432    impl <S> From <[S; $ndims]> for $point <S> {
2433      fn from (array : [S; $ndims]) -> Self {
2434        $point (array.into())
2435      }
2436    }
2437    $(
2438    impl <S> From <($patch <S>, S)> for $point <S> {
2439      fn from ((patch, scale) : ($patch <S>, S)) -> Self {
2440        $point ((patch.0, scale).into())
2441      }
2442    }
2443    )?
2444    impl <S> std::cmp::PartialOrd for $point <S> where S : PartialOrd {
2445      fn partial_cmp (&self, other : &Self) -> Option <std::cmp::Ordering> {
2446        self.0.as_slice().partial_cmp (&other.0.as_slice())
2447      }
2448    }
2449    impl <S> std::ops::Add <$vector <S>> for $point <S> where S : AdditiveGroup {
2450      type Output = Self;
2451      fn add (self, displacement : $vector <S>) -> Self::Output {
2452        $point (self.0 + displacement)
2453      }
2454    }
2455    impl <S> std::ops::Add <&$vector <S>> for $point <S> where S : AdditiveGroup + Copy {
2456      type Output = Self;
2457      fn add (self, displacement : &$vector <S>) -> Self::Output {
2458        $point (self.0 + *displacement)
2459      }
2460    }
2461    impl <S> std::ops::Add <$vector <S>> for &$point <S> where S : AdditiveGroup + Copy {
2462      type Output = $point <S>;
2463      fn add (self, displacement : $vector <S>) -> Self::Output {
2464        $point (self.0 + displacement)
2465      }
2466    }
2467    impl <S> std::ops::Add <&$vector <S>> for &$point <S> where
2468      S : AdditiveGroup + Copy
2469    {
2470      type Output = $point <S>;
2471      fn add (self, displacement : &$vector <S>) -> Self::Output {
2472        $point (self.0 + *displacement)
2473      }
2474    }
2475    impl <S> std::ops::AddAssign <$vector <S>> for $point <S> where S : AdditiveGroup {
2476      fn add_assign (&mut self, displacement : $vector <S>) {
2477        self.0 += displacement
2478      }
2479    }
2480    impl <S> std::ops::AddAssign <&$vector <S>> for $point <S> where
2481      S : AdditiveGroup + Copy
2482    {
2483      fn add_assign (&mut self, displacement : &$vector <S>) {
2484        self.0 += *displacement
2485      }
2486    }
2487    impl <S> std::ops::Sub <$vector <S>> for $point <S> where S : AdditiveGroup {
2488      type Output = Self;
2489      fn sub (self, displacement : $vector <S>) -> Self::Output {
2490        $point (self.0 - displacement)
2491      }
2492    }
2493    impl <S> std::ops::Sub <&$vector <S>> for $point <S> where S : AdditiveGroup + Copy {
2494      type Output = Self;
2495      fn sub (self, displacement : &$vector <S>) -> Self::Output {
2496        $point (self.0 - *displacement)
2497      }
2498    }
2499    impl <S> std::ops::Sub <$point <S>> for $point <S> where S : AdditiveGroup {
2500      type Output = $vector <S>;
2501      fn sub (self, other : Self) -> Self::Output {
2502        self.0 - other.0
2503      }
2504    }
2505    impl <S> std::ops::Sub <&$point <S>> for $point <S> where S : AdditiveGroup + Copy {
2506      type Output = $vector <S>;
2507      fn sub (self, other : &Self) -> Self::Output {
2508        self.0 - other.0
2509      }
2510    }
2511    impl <S> std::ops::Sub <$vector <S>> for &$point <S> where S : AdditiveGroup + Copy {
2512      type Output = $point <S>;
2513      fn sub (self, displacement : $vector <S>) -> Self::Output {
2514        $point (self.0 - displacement)
2515      }
2516    }
2517    impl <S> std::ops::Sub <&$vector <S>> for &$point <S> where
2518      S : AdditiveGroup + Copy
2519    {
2520      type Output = $point <S>;
2521      fn sub (self, displacement : &$vector <S>) -> Self::Output {
2522        $point (self.0 - *displacement)
2523      }
2524    }
2525    impl <S> std::ops::Sub <$point <S>> for &$point <S> where S : AdditiveGroup + Copy {
2526      type Output = $vector <S>;
2527      fn sub (self, other : $point <S>) -> Self::Output {
2528        self.0 - other.0
2529      }
2530    }
2531    impl <S> std::ops::Sub <&$point <S>> for &$point <S> where S : AdditiveGroup + Copy {
2532      type Output = $vector <S>;
2533      fn sub (self, other : &$point <S>) -> Self::Output {
2534        self.0 - other.0
2535      }
2536    }
2537    impl <S> std::ops::SubAssign <$vector <S>> for $point <S> where
2538      S : AdditiveGroup
2539    {
2540      fn sub_assign (&mut self, displacement : $vector <S>) {
2541        self.0 -= displacement
2542      }
2543    }
2544    impl <S> std::ops::SubAssign <&$vector <S>> for $point <S> where
2545      S : AdditiveGroup + Copy
2546    {
2547      fn sub_assign (&mut self, displacement : &$vector <S>) {
2548        self.0 -= *displacement
2549      }
2550    }
2551    impl <S> approx::AbsDiffEq for $point <S> where
2552      S : approx::AbsDiffEq,
2553      S::Epsilon : Copy
2554    {
2555      type Epsilon = S::Epsilon;
2556      fn default_epsilon() -> Self::Epsilon {
2557        S::default_epsilon()
2558      }
2559      #[inline]
2560      fn abs_diff_eq (&self, other : &Self, epsilon : Self::Epsilon) -> bool {
2561        self.0.abs_diff_eq (&other.0, epsilon)
2562      }
2563    }
2564    impl <S> approx::RelativeEq for $point <S> where
2565      S : approx::RelativeEq,
2566      S::Epsilon : Copy
2567    {
2568      fn default_max_relative() -> Self::Epsilon {
2569        S::default_max_relative()
2570      }
2571      #[inline]
2572      fn relative_eq (&self,
2573        other : &Self, epsilon : Self::Epsilon, max_relative : Self::Epsilon
2574      ) -> bool {
2575        self.0.relative_eq (&other.0, epsilon, max_relative)
2576      }
2577    }
2578    impl <S> approx::UlpsEq for $point <S> where
2579      S : approx::UlpsEq,
2580      S::Epsilon : Copy
2581    {
2582      fn default_max_ulps() -> u32 {
2583        S::default_max_ulps()
2584      }
2585      #[inline]
2586      fn ulps_eq (&self, other : &Self, epsilon : Self::Epsilon, max_ulps : u32)
2587        -> bool
2588      {
2589        self.0.ulps_eq (&other.0, epsilon, max_ulps)
2590      }
2591    }
2592    #[doc = "Construct a"]
2596    #[doc = $dimension]
2597    #[doc = "vector"]
2598    pub const fn $vector_fun <S> ($($component : S),+) -> $vector <S> {
2599      $vector::new ($($component),+)
2600    }
2601    impl <S> InnerProductSpace <S> for $vector <S> where S : Field {
2602      fn outer_product (self, rhs : Self) -> $matrix <S> {
2603        let mut cols : $vector <$vector <S>> = [$vector::zero(); $ndims].into();
2604        for col in 0..$ndims {
2605          for row in 0..$ndims {
2606            cols[col][row] = self[row] * rhs[col];
2607          }
2608        }
2609        $matrix { cols }
2610      }
2611    }
2612    impl <S : Ring> Dot <S> for $vector <S> {
2613      fn dot (self, other : Self) -> S {
2614        self.dot (other)
2615      }
2616    }
2617    impl <S : Field> VectorSpace <S> for $vector <S> {
2618      fn map <F> (self, f : F) -> Self where F : FnMut (S) -> S {
2619        self.map (f)
2620      }
2621    }
2622    impl <S> Module <S> for $vector <S> where S : Ring + num::MulAdd {
2623      type LinearEndo = $matrix <S>;
2624    }
2625    impl <S> GroupAction <$point <S>> for $vector <S> where S : AdditiveGroup {
2626      fn action (self, point : $point <S>) -> $point <S> {
2627        point + self
2628      }
2629    }
2630    impl <S : AdditiveGroup> Group for $vector <S> {
2631      fn identity() -> Self {
2632        Self::zero()
2633      }
2634      fn operation (a : Self, b : Self) -> Self {
2635        a + b
2636      }
2637    }
2638    impl <S> std::ops::Mul <LinearAuto <S, Self>> for $vector <S> where
2639      S : Ring + MaybeSerDes
2640    {
2641      type Output = Self;
2642      fn mul (self, rhs : LinearAuto <S, Self>) -> Self::Output {
2643        self * rhs.0
2644      }
2645    }
2646    impl <S> std::ops::Mul <LinearIso <S, Self, Self, $matrix <S>>> for $vector <S> where
2647      S : Ring + MaybeSerDes
2648    {
2649      type Output = Self;
2650      fn mul (self, rhs : LinearIso <S, Self, Self, $matrix <S>>) -> Self::Output {
2651        self * rhs.0
2652      }
2653    }
2654    impl <S> num::Inv for LinearAuto <S, $vector <S>> where
2655      S : Ring + num::real::Real + MaybeSerDes
2656    {
2657      type Output = Self;
2658      fn inv (self) -> Self::Output {
2659        LinearAuto (self.0.inv())
2660      }
2661    }
2662    impl <S> std::ops::Div for LinearAuto <S, $vector <S>> where
2663      S : Ring + num::Float + MaybeSerDes
2664    {
2665      type Output = Self;
2666      fn div (self, rhs : Self) -> Self::Output {
2667        LinearAuto (self.0 / rhs.0)
2668      }
2669    }
2670    impl <S> std::ops::DivAssign <Self> for LinearAuto <S, $vector <S>> where
2671      S : Ring + num::Float + MaybeSerDes
2672    {
2673      fn div_assign (&mut self, rhs : Self) {
2674        self.0 /= rhs.0
2675      }
2676    }
2677    #[doc = "Construct a"]
2681    #[doc = $dimension]
2682    #[doc = "matrix"]
2683    pub const fn $matrix_fun <S> ($($component : $vector <S>),+) -> $matrix <S> {
2684      $matrix {
2685        cols: $vector_fun ($($component),+)
2686      }
2687    }
2688    impl <S, V, W> num::Inv for LinearIso <S, V, W, $matrix <S>> where
2689      V : Module <S>,
2690      W : Module <S>,
2691      S : Ring + num::real::Real
2692    {
2693      type Output = LinearIso <S, W, V, $matrix <S>>;
2694      fn inv (self) -> Self::Output {
2695        let mat4 = Matrix4::from (self.0);
2697        LinearIso (mat4.inverted().into(), PhantomData::default())
2698      }
2699    }
2700    impl <S, V> std::ops::Div for LinearIso <S, V, V, $matrix <S>> where
2701      V : Module <S, LinearEndo=$matrix <S>>,
2702      S : Ring + num::real::Real
2703    {
2704      type Output = Self;
2705      #[expect(clippy::suspicious_arithmetic_impl)]
2706      fn div (self, rhs : Self) -> Self::Output {
2707        use num::Inv;
2708        self * rhs.inv()
2709      }
2710    }
2711    impl <S, V> std::ops::DivAssign for LinearIso <S, V, V, $matrix <S>> where
2712      V : Module <S, LinearEndo=$matrix <S>>,
2713      S : Ring + num::real::Real
2714    {
2715      #[expect(clippy::suspicious_op_assign_impl)]
2716      fn div_assign (&mut self, rhs : Self) {
2717        use num::Inv;
2718        *self *= rhs.inv()
2719      }
2720    }
2721    $(
2722    impl <S : Copy> Matrix <S> for $matrix <S> {
2723      type Rows = $vector <$vector <S>>;
2724      type Submatrix = $submatrix <S>;
2725      fn rows (self) -> $vector <$vector <S>> {
2726        self.into_row_arrays().map ($vector::from).into()
2727      }
2728      fn submatrix (self, i : usize, j : usize) -> $submatrix <S> {
2729        let a : [S; ($ndims-1) * ($ndims-1)] = std::array::from_fn (|index|{
2730          let i = (i + 1 + index / ($ndims-1)) % $ndims;
2731          let j = (j + 1 + index % ($ndims-1)) % $ndims;
2732          self.cols[i][j]
2733        });
2734        $submatrix::from_col_array (a)
2735      }
2736      fn fill_zeros (submatrix : $submatrix <S>) -> Self where S : num::Zero{
2738        let cols = $vector::from (
2739          std::array::from_fn (|i| if i < $ndims-1 {
2740            $vector::from (submatrix.cols[i])
2741          } else {
2742            $vector::zero()
2743          })
2744        );
2745        $matrix { cols }
2746      }
2747    }
2748    )?
2749    impl <S : Ring> LinearMap <S, $vector <S>, $vector <S>> for $matrix <S> {
2750      fn determinant (self) -> S {
2751        self.determinant()
2752      }
2753      fn transpose (self) -> Self {
2754        self.transposed()
2755      }
2756    }
2757    impl_numcast!($nonzero);
2761    impl <S : Ring> $nonzero <S> {
2762      pub fn new (vector : $vector <S>) -> Option <Self> {
2772        use num::Zero;
2773        if !vector.is_zero() {
2774          Some ($nonzero (vector))
2775        } else {
2776          None
2777        }
2778      }
2779      pub fn noisy (vector : $vector <S>) -> Self {
2788        use num::Zero;
2789        assert!(!vector.is_zero());
2790        $nonzero (vector)
2791      }
2792      pub fn map_noisy (self, fun : fn ($vector <S>) -> $vector <S>) -> Self {
2804        Self::noisy (fun (self.0))
2805      }
2806    }
2807    impl <S : Ring> std::ops::Deref for $nonzero <S> {
2808      type Target = $vector <S>;
2809      fn deref (&self) -> &$vector <S> {
2810        &self.0
2811      }
2812    }
2813    impl_numcast!($unit);
2817    impl <S : Real> $unit <S> {
2818      $(
2824      #[inline]
2825      pub fn $axis_method() -> Self {
2826        $unit ($vector::$unit_method())
2827      }
2828      )+
2829      pub fn new (vector : $vector <S>) -> Option <Self> {
2833        let normalized = vector.normalize();
2834        if vector == normalized {
2835          Some ($unit (vector))
2836        } else {
2837          None
2838        }
2839      }
2840      pub fn new_approx (vector : $vector <S>) -> Option <Self> where
2846        S : num::real::Real + approx::RelativeEq <Epsilon=S>
2847      {
2848        if vector.is_normalized() {
2849          Some ($unit (vector))
2850        } else {
2851          None
2852        }
2853      }
2854      pub fn normalize (vector : $vector <S>) -> Self {
2875        use num::Zero;
2876        assert!(!vector.is_zero());
2877        $unit (vector.normalize())
2878      }
2879      pub fn normalize_approx (vector : $vector <S>) -> Self where
2882        S : num::real::Real + approx::RelativeEq <Epsilon=S>
2883      {
2884        use num::Zero;
2885        assert!(!vector.is_zero());
2886        let vector = if vector.is_normalized() {
2887          vector
2888        } else {
2889          vector.normalize()
2890        };
2891        $unit (vector)
2892      }
2893      pub fn noisy (vector : $vector <S>) -> Self where S : std::fmt::Debug {
2902        assert_eq!(vector, vector.normalize());
2903        $unit (vector)
2904      }
2905      pub fn noisy_approx (vector : $vector <S>) -> Self where
2914        S : num::real::Real + approx::RelativeEq <Epsilon=S>
2915      {
2916        assert!(vector.is_normalized());
2917        $unit (vector)
2918      }
2919      #[inline]
2923      pub fn unchecked (vector : $vector <S>) -> Self where S : std::fmt::Debug {
2924        debug_assert_eq!(vector, vector.normalize());
2925        $unit (vector)
2926      }
2927      #[inline]
2936      pub fn unchecked_approx (vector : $vector <S>) -> Self where
2937        S : num::real::Real + approx::RelativeEq <Epsilon=S>
2938      {
2939        debug_assert!(vector.is_normalized());
2940        $unit (vector)
2941      }
2942      pub fn random_unit <R : rand::Rng> (rng : &mut R) -> Self where
2944        S : rand::distr::uniform::SampleUniform
2945      {
2946        let vector = $vector {
2947          $($component: rng.random_range (-S::one()..S::one())),+
2948        };
2949        $unit (vector.normalize())
2950      }
2951      pub fn invert (mut self) -> Self {
2954        self.0 = -self.0;
2955        self
2956      }
2957      pub fn map_noisy (self, fun : fn ($vector <S>) -> $vector <S>) -> Self where
2969        S : std::fmt::Debug
2970      {
2971        Self::noisy (fun (self.0))
2972      }
2973      pub fn map_noisy_approx (self, fun : fn ($vector <S>) -> $vector <S>) -> Self where
2985        S : num::real::Real + approx::RelativeEq <Epsilon=S>
2986      {
2987        Self::noisy_approx (fun (self.0))
2988      }
2989    }
2990    impl <S : Real> std::ops::Deref for $unit <S> {
2991      type Target = $vector <S>;
2992      fn deref (&self) -> &$vector <S> {
2993        &self.0
2994      }
2995    }
2996    impl <S : Real> std::ops::Neg for $unit <S> {
2997      type Output = Self;
2998      fn neg (self) -> Self::Output {
2999        Self (-self.0)
3000      }
3001    }
3002    }
3004}
3005
3006macro_rules! impl_numcast {
3007  ($type:ident) => {
3008    impl <S> $type <S> {
3009      #[inline]
3010      pub fn numcast <T> (self) -> Option <$type <T>> where
3011        S : num::NumCast,
3012        T : num::NumCast
3013      {
3014        self.0.numcast().map ($type)
3015      }
3016    }
3017  }
3018}
3019
3020macro_rules! impl_numcast_primitive {
3021  ($type:ident) => {
3022    impl <S> $type <S> {
3023      #[inline]
3024      pub fn numcast <T> (self) -> Option <$type <T>> where
3025        S : num::NumCast,
3026        T : num::NumCast
3027      {
3028        T::from (self.0).map ($type)
3029      }
3030    }
3031  }
3032}
3033
3034#[doc(hidden)]
3035#[macro_export]
3036macro_rules! impl_numcast_fields {
3037  ($type:ident, $($field:ident),+) => {
3038    impl <S> $type <S> {
3039      #[inline]
3040      pub fn numcast <T> (self) -> Option <$type <T>> where
3041        S : num::NumCast,
3042        T : num::NumCast
3043      {
3044        Some ($type {
3045          $($field: self.$field.numcast()?),+
3046        })
3047      }
3048    }
3049  }
3050}
3051
3052impl_angle!(Deg, "Degrees");
3053impl_angle!(Rad, "Radians");
3054impl_angle!(Turn, "Turns");
3055impl_angle_wrapped!(AngleWrapped, "Unsigned wrapped angle restricted to $[0, 2\\pi)$");
3056impl_angle_wrapped!(AngleWrappedSigned,
3057  "Signed wrapped angle restricted to $(-\\pi, \\pi]$");
3058
3059impl_dimension!(Point2, Vector2, NonZero2, Unit2, point2, vector2, matrix2, [x, y],
3060  [(axis_x, unit_x), (axis_y, unit_y)],
3061  [], [Point3], Matrix2, [], 2, "2D");
3062impl_dimension!(Point3, Vector3, NonZero3, Unit3, point3, vector3, matrix3, [x, y, z],
3063  [(axis_x, unit_x), (axis_y, unit_y), (axis_z, unit_z)],
3064  [Point2], [Point4], Matrix3, [Matrix2], 3, "3D");
3065impl_dimension!(Point4, Vector4, NonZero4, Unit4, point4, vector4, matrix4, [x, y, z, w],
3066  [(axis_x, unit_x), (axis_y, unit_y), (axis_z, unit_z), (axis_w, unit_w)],
3067  [Point3], [], Matrix4, [Matrix3], 4, "4D");
3068
3069impl_numcast_primitive!(Positive);
3070impl_numcast_primitive!(NonNegative);
3071impl_numcast_primitive!(NonZero);
3072impl_numcast_primitive!(Normalized);
3073impl_numcast_primitive!(NormalSigned);
3074impl_numcast_fields!(Angles3, yaw, pitch, roll);
3075
3076#[inline]
3080fn normalize_quaternion <S : Real> (quaternion : Quaternion <S>) -> Quaternion <S> {
3081  Quaternion::from_vec4 (quaternion.into_vec4().normalize())
3082}
3083
3084#[cfg(test)]
3085mod tests {
3086  use super::*;
3087  use crate::num_traits;
3088  use approx;
3089  use rand;
3090  use rand_xorshift;
3091
3092  #[test]
3093  fn defaults() {
3094    use num_traits::Zero;
3095
3096    assert_eq!(Positive::<f32>::default().0, 0.0);
3097    assert_eq!(NonNegative::<f32>::default().0, 0.0);
3098    assert_eq!(Normalized::<f32>::default().0, 0.0);
3099    assert_eq!(NormalSigned::<f32>::default().0, 0.0);
3100    assert_eq!(Deg::<f32>::default().0, 0.0);
3101    assert_eq!(Rad::<f32>::default().0, 0.0);
3102    assert_eq!(Turn::<f32>::default().0, 0.0);
3103    assert_eq!(
3104      Angles3::<f32>::default(),
3105      Angles3::new (AngleWrapped::zero(), AngleWrapped::zero(), AngleWrapped::zero()));
3106    assert_eq!(
3107      Pose3::<f32>::default(),
3108      Pose3 { position: Point3::origin(), angles: Angles3::default() });
3109    assert_eq!(
3110      LinearIso::<f32, Vector3 <f32>, Vector3 <f32>, Matrix3 <f32>>::default().0,
3111      Matrix3::identity());
3112    assert_eq!(LinearAuto::<f32, Vector3 <f32>>::default().0.0, Matrix3::identity());
3113    assert_eq!(Rotation2::<f32>::default().0.0.0, Matrix2::identity());
3114    assert_eq!(Rotation3::<f32>::default().0.0.0, Matrix3::identity());
3115    assert_eq!(Versor::<f32>::default().0, Quaternion::from_xyzw (0.0, 0.0, 0.0, 1.0));
3116    assert_eq!(
3117      AffineMap::<f32, Point3 <f32>, Point3 <f32>, Matrix3 <f32>>::default(),
3118      AffineMap::new (Matrix3::identity(), Vector3::zero()));
3119    assert_eq!(
3120      Affinity::<f32, Point3 <f32>, Point3 <f32>, Matrix3 <f32>>::default(),
3121      Affinity::new (LinearIso::new (Matrix3::identity()).unwrap(), Vector3::zero()));
3122    assert_eq!(
3123      Projectivity::<f32, Point4 <f32>, Point4 <f32>, Matrix4 <f32>>::default().0,
3124      LinearIso::new (Matrix4::identity()).unwrap());
3125  }
3126
3127  #[test]
3128  fn vector_sum() {
3129    let s = [
3130      [0.0, 1.0],
3131      [1.0, 1.0],
3132      [0.5, 0.5]
3133    ].map (Vector2::<f32>::from);
3134    let _sum = s.iter().copied().sum::<Vector2 <f32>>();
3135  }
3136
3137  #[test]
3138  fn vector_outer_product() {
3139    let v1 = vector3 (1.0, 2.0, 3.0);
3140    let v2 = vector3 (2.0, 3.0, 4.0);
3141    assert_eq!(v1.outer_product (v2).into_row_arrays(), [
3142      [2.0, 3.0,  4.0],
3143      [4.0, 6.0,  8.0],
3144      [6.0, 9.0, 12.0]
3145    ]);
3146  }
3147
3148  #[test]
3149  fn rotation3_noisy_approx() {
3150    use rand::{Rng, SeedableRng};
3151    let mut rng = rand_xorshift::XorShiftRng::seed_from_u64 (0);
3154    let up = Vector3::unit_z();
3155    for _ in 0..1000 {
3156      let forward = vector3 (
3157        rng.random_range (-1000.0f32..1000.0),
3158        rng.random_range (-1000.0f32..1000.0),
3159        0.0
3160      ).normalized();
3161      let right = forward.cross (up);
3162      let mat = Matrix3::from_col_arrays ([
3163        right.into_array(),
3164        forward.into_array(),
3165        up.into_array()
3166      ]);
3167      let _ = Rotation3::noisy_approx (mat);
3168    }
3169  }
3170
3171  #[test]
3172  fn rotation3_intrinsic_angles() {
3173    use std::f32::consts::PI;
3174    use num_traits::Zero;
3175    use rand::{Rng, SeedableRng};
3176    let rot = Rotation3::from_angles_intrinsic (
3178      Turn (0.25).into(), Rad::zero(), Rad::zero());
3179    approx::assert_relative_eq!(rot.mat(),
3180      Matrix3::from_col_arrays ([
3181        [ 0.0, 1.0, 0.0],
3182        [-1.0, 0.0, 0.0],
3183        [ 0.0, 0.0, 1.0]
3184      ])
3185    );
3186    assert_eq!((Turn (0.25).into(), Rad::zero(), Rad::zero()), rot.intrinsic_angles());
3187    let rot = Rotation3::from_angles_intrinsic (
3188      Turn (0.5).into(), Rad::zero(), Rad::zero());
3189    approx::assert_relative_eq!(rot.mat(),
3190      Matrix3::from_col_arrays ([
3191        [-1.0,  0.0, 0.0],
3192        [ 0.0, -1.0, 0.0],
3193        [ 0.0,  0.0, 1.0]
3194      ])
3195    );
3196    assert_eq!((Turn (0.5).into(), Rad::zero(), Rad::zero()), rot.intrinsic_angles());
3197    let rot = Rotation3::from_angles_intrinsic (
3199      Rad::zero(), Turn (0.25).into(), Rad::zero());
3200    approx::assert_relative_eq!(rot.mat(),
3201      Matrix3::from_col_arrays ([
3202        [1.0,  0.0, 0.0],
3203        [0.0,  0.0, 1.0],
3204        [0.0, -1.0, 0.0]
3205      ])
3206    );
3207    assert_eq!((Rad::zero(), Turn (0.25).into(), Rad::zero()), rot.intrinsic_angles());
3208    let rot = Rotation3::from_angles_intrinsic (
3210      Rad::zero(), Rad::zero(), Turn (0.25).into());
3211    approx::assert_relative_eq!(rot.mat(),
3212      Matrix3::from_col_arrays ([
3213        [0.0, 0.0, -1.0],
3214        [0.0, 1.0,  0.0],
3215        [1.0, 0.0,  0.0]
3216      ])
3217    );
3218    assert_eq!((Rad::zero(), Rad::zero(), Turn (0.25).into()), rot.intrinsic_angles());
3219    let rot = Rotation3::from_angles_intrinsic (
3221      Turn (0.25).into(), Turn (0.25).into(), Rad::zero());
3222    approx::assert_relative_eq!(rot.mat(),
3223      Matrix3::from_col_arrays ([
3224        [0.0, 1.0, 0.0],
3225        [0.0, 0.0, 1.0],
3226        [1.0, 0.0, 0.0]
3227      ])
3228    );
3229    let angles = rot.intrinsic_angles();
3230    approx::assert_relative_eq!(Rad::from (Turn (0.25)).0, angles.0.0);
3231    approx::assert_relative_eq!(Rad::from (Turn (0.25)).0, angles.1.0);
3232    approx::assert_relative_eq!(0.0, angles.2.0);
3233    let rot = Rotation3::from_angles_intrinsic (
3235      Turn (0.25).into(), Turn (0.25).into(), Turn (0.25).into());
3236    approx::assert_relative_eq!(rot.mat(),
3237      Matrix3::from_col_arrays ([
3238        [-1.0, 0.0, 0.0],
3239        [ 0.0, 0.0, 1.0],
3240        [ 0.0, 1.0, 0.0]
3241      ])
3242    );
3243    let angles = rot.intrinsic_angles();
3244    approx::assert_relative_eq!(Rad::from (Turn (0.25)).0, angles.0.0);
3245    approx::assert_relative_eq!(Rad::from (Turn (0.25)).0, angles.1.0);
3246    approx::assert_relative_eq!(Rad::from (Turn (0.25)).0, angles.2.0);
3247
3248    let mut rng = rand_xorshift::XorShiftRng::seed_from_u64 (0);
3251    let mut random_vector = || vector3 (
3252      rng.random_range (-100.0f32..100.0),
3253      rng.random_range (-100.0f32..100.0),
3254      rng.random_range (-100.0f32..100.0));
3255    for _ in 0..1000 {
3256      let rot = Rotation3::orthonormalize (
3257        random_vector(), random_vector(), random_vector()
3258      ).unwrap();
3259      let (yaw, pitch, roll) = rot.intrinsic_angles();
3260      assert!(yaw.0   <  PI);
3261      assert!(yaw.0   > -PI);
3262      assert!(pitch.0 <  PI);
3263      assert!(pitch.0 > -PI);
3264      assert!(roll.0  <  PI);
3265      assert!(roll.0  > -PI);
3266    }
3267  }
3268
3269  #[test]
3270  fn rotation3_into_versor() {
3271    use std::f32::consts::PI;
3272    let rot  = Rotation3::from_angle_x (Rad (0.01));
3273    let quat = rot.versor().0;
3274    approx::assert_relative_eq!(rot.mat(), quat.into());
3275    let rot  = Rotation3::from_angle_x (Rad (-0.01));
3276    let quat = rot.versor().0;
3277    approx::assert_relative_eq!(rot.mat(), quat.into());
3278
3279    let rot  = Rotation3::from_angle_y (Rad (0.01));
3280    let quat = rot.versor().0;
3281    approx::assert_relative_eq!(rot.mat(), quat.into());
3282    let rot  = Rotation3::from_angle_y (Rad (-0.01));
3283    let quat = rot.versor().0;
3284    approx::assert_relative_eq!(rot.mat(), quat.into());
3285
3286    let rot  = Rotation3::from_angle_z (Rad (0.01));
3287    let quat = rot.versor().0;
3288    approx::assert_relative_eq!(rot.mat(), quat.into());
3289    let rot  = Rotation3::from_angle_z (Rad (-0.01));
3290    let quat = rot.versor().0;
3291    approx::assert_relative_eq!(rot.mat(), quat.into());
3292
3293    let rot  = Rotation3::from_angle_x (Rad (PI / 2.0));
3294    let quat = rot.versor().0;
3295    approx::assert_relative_eq!(rot.mat(), quat.into());
3296    let rot  = Rotation3::from_angle_x (Rad (-PI / 2.0));
3297    let quat = rot.versor().0;
3298    approx::assert_relative_eq!(rot.mat(), quat.into());
3299
3300    let rot  = Rotation3::from_angle_y (Rad (PI / 2.0));
3301    let quat = rot.versor().0;
3302    approx::assert_relative_eq!(rot.mat(), quat.into());
3303    let rot  = Rotation3::from_angle_y (Rad (-PI / 2.0));
3304    let quat = rot.versor().0;
3305    approx::assert_relative_eq!(rot.mat(), quat.into());
3306
3307    let rot  = Rotation3::from_angle_z (Rad (PI / 2.0));
3308    let quat = rot.versor().0;
3309    approx::assert_relative_eq!(rot.mat(), quat.into());
3310    let rot  = Rotation3::from_angle_z (Rad (-PI / 2.0));
3311    let quat = rot.versor().0;
3312    approx::assert_relative_eq!(rot.mat(), quat.into());
3313  }
3314}