1use std::marker::PhantomData;
2use derive_more::{Deref, Display, From, Neg};
3
4use crate::{approx, num};
5
6#[cfg(feature = "derive_serdes")]
7use serde::{Deserialize, Serialize};
8
9use crate::traits::*;
10
11pub mod coordinate;
12pub mod frame;
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, Display)]
160pub struct Positive <S> (S);
161
162#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
164#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, PartialOrd, Display)]
165pub struct NonNegative <S> (S);
166
167#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
169#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd, Display)]
170pub struct NonZero <S> (S);
171
172#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
174#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd, Display)]
175pub struct Normalized <S> (S);
176
177#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
179#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd, Display)]
180pub struct NormalSigned <S> (S);
181
182#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
184#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, PartialOrd, Display)]
185pub struct Unit <S> (S);
186
187#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
193#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
194pub struct Angles3 <S> {
195 pub yaw : AngleWrapped <S>,
196 pub pitch : AngleWrapped <S>,
197 pub roll : AngleWrapped <S>
198}
199
200#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
202#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
203pub struct Pose3 <S> {
204 pub position : Point3 <S>,
205 pub angles : Angles3 <S>
206}
207
208#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Display)]
210#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
211#[display("{}", _0)]
212pub struct LinearIso <S, V, W, M> (M, PhantomData <(S, V, W)>);
213
214#[derive(Clone, Copy, Debug, Default, PartialEq, Deref, Display, From)]
216#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
217#[display("{}", _0)]
218pub struct LinearAuto <S, V> (pub LinearIso <S, V, V, V::LinearEndo>) where
219 V : Module <S>,
220 V::LinearEndo : MaybeSerDes,
221 S : Ring;
222
223#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
226#[cfg_attr(feature = "derive_serdes", serde(bound = "S : MaybeSerDes"))]
227#[derive(Clone, Copy, Debug, Default, PartialEq)]
228pub struct Rotation2 <S> (LinearAuto <S, Vector2 <S>>) where S : Ring + MaybeSerDes;
229
230#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
233#[cfg_attr(feature = "derive_serdes", serde(bound = "S : MaybeSerDes"))]
234#[derive(Clone, Copy, Debug, Default, PartialEq)]
235pub struct Rotation3 <S> (LinearAuto <S, Vector3 <S>>) where S : Ring + MaybeSerDes;
236
237#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
239#[derive(Clone, Copy, Debug, Eq, PartialEq)]
240pub struct Versor <S> (Quaternion <S>);
241
242#[derive(Clone, Copy, Debug, Default, Eq, 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 A : AffineSpace <S>,
248 B : AffineSpace <S>,
249 S : Field,
250 M : LinearMap <S, A::Translation, B::Translation>
251{
252 pub linear_map : M,
253 pub translation : B::Translation,
254 pub _phantom : PhantomData <(A, S)>
255}
256
257#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Display)]
259#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
260#[display("({}, {})", linear_iso, translation)]
261pub struct Affinity <S, A, B, M> where
262 S : Field,
263 A : AffineSpace <S>,
264 B : AffineSpace <S>,
265 M : LinearMap <S, A::Translation, B::Translation>
266{
267 pub linear_iso : LinearIso <S, A::Translation, B::Translation, M>,
268 pub translation : B::Translation
269}
270
271#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Display)]
273#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
274#[display("{}", _0)]
275pub struct Projectivity <S, P, Q, M> (
276 pub LinearIso <S, P::Translation, Q::Translation, M>
277) where
278 S : Field,
279 P : ProjectiveSpace <S>,
280 Q : ProjectiveSpace <S>;
281
282impl <S : OrderedField> Angle <S> for Deg <S> {
290 fn full_turn() -> Self {
291 Deg (S::ten() * S::nine() * S::two() * S::two())
292 }
293 fn half_turn() -> Self {
294 Deg (S::ten() * S::nine() * S::two())
295 }
296}
297impl <S : Real> Trig for Deg <S> {
298 fn sin (self) -> Self {
299 Rad::from (self).sin().into()
300 }
301 fn sin_cos (self) -> (Self, Self) {
302 let (sin, cos) = Rad::from (self).sin_cos();
303 (sin.into(), cos.into())
304 }
305 fn cos (self) -> Self {
306 Rad::from (self).cos().into()
307 }
308 fn tan (self) -> Self {
309 Rad::from (self).tan().into()
310 }
311 fn asin (self) -> Self {
312 Rad::from (self).asin().into()
313 }
314 fn acos (self) -> Self {
315 Rad::from (self).acos().into()
316 }
317 fn atan (self) -> Self {
318 Rad::from (self).atan().into()
319 }
320 fn atan2 (self, other : Self) -> Self {
321 Rad::from (self).atan2 (Rad::from (other)).into()
322 }
323}
324impl <S : Real> From <Rad <S>> for Deg <S> {
325 fn from (radians : Rad <S>) -> Self {
326 let full_turns = radians / Rad::full_turn();
327 Deg::full_turn() * full_turns
328 }
329}
330impl <S : OrderedField> From <Turn <S>> for Deg <S> {
331 fn from (turns : Turn <S>) -> Self {
332 Deg (turns.0 * Deg::full_turn().0)
333 }
334}
335
336impl <S : Real> Angle <S> for Rad <S> {
340 fn full_turn() -> Self {
341 Rad (S::pi() * S::two())
342 }
343}
344impl <S : Trig> Trig for Rad <S> {
345 fn sin (self) -> Self {
346 Rad (self.0.sin())
347 }
348 fn sin_cos (self) -> (Self, Self) {
349 let (sin, cos) = self.0.sin_cos();
350 (Rad (sin), Rad (cos))
351 }
352 fn cos (self) -> Self {
353 Rad (self.0.cos())
354 }
355 fn tan (self) -> Self {
356 Rad (self.0.tan())
357 }
358 fn asin (self) -> Self {
359 Rad (self.0.asin())
360 }
361 fn acos (self) -> Self {
362 Rad (self.0.acos())
363 }
364 fn atan (self) -> Self {
365 Rad (self.0.atan())
366 }
367 fn atan2 (self, other : Self) -> Self {
368 Rad (self.0.atan2 (other.0))
369 }
370}
371impl <S : Real> From <Deg <S>> for Rad <S> {
372 fn from (degrees : Deg <S>) -> Self {
373 let full_turns = degrees / Deg::full_turn();
374 Rad::full_turn() * full_turns
375 }
376}
377impl <S : Real> From <Turn <S>> for Rad <S> {
378 fn from (turns : Turn <S>) -> Self {
379 Rad (turns.0 * Rad::full_turn().0)
380 }
381}
382
383impl <S : OrderedField> Angle <S> for Turn <S> {
387 fn full_turn() -> Self {
388 Turn (S::one())
389 }
390 fn half_turn() -> Self {
391 Turn (S::half())
392 }
393}
394impl <S : Real> Trig for Turn <S> {
395 fn sin (self) -> Self {
396 Rad::from (self).sin().into()
397 }
398 fn sin_cos (self) -> (Self, Self) {
399 let (sin, cos) = Rad::from (self).sin_cos();
400 (sin.into(), cos.into())
401 }
402 fn cos (self) -> Self {
403 Rad::from (self).cos().into()
404 }
405 fn tan (self) -> Self {
406 Rad::from (self).tan().into()
407 }
408 fn asin (self) -> Self {
409 Rad::from (self).asin().into()
410 }
411 fn acos (self) -> Self {
412 Rad::from (self).acos().into()
413 }
414 fn atan (self) -> Self {
415 Rad::from (self).atan().into()
416 }
417 fn atan2 (self, other : Self) -> Self {
418 Rad::from (self).atan2 (Rad::from (other)).into()
419 }
420}
421impl <S : Real> From <Rad <S>> for Turn <S> {
422 fn from (radians : Rad <S>) -> Self {
423 Turn (radians.0 / Rad::full_turn().0)
424 }
425}
426impl <S : OrderedField> From <Deg <S>> for Turn <S> {
427 fn from (degrees : Deg <S>) -> Self {
428 Turn (degrees.0 / Deg::full_turn().0)
429 }
430}
431
432impl <S : Real> AngleWrapped <S> {
436 pub fn wrap (angle : Rad <S>) -> Self {
437 AngleWrapped (angle.wrap_unsigned())
438 }
439
440 #[must_use]
441 pub fn map <F> (self, mut f : F) -> Self where F : FnMut (Rad <S>) -> Rad <S> {
442 AngleWrapped (f (self.0).wrap_unsigned())
443 }
444}
445
446impl <S : Real> AngleWrappedSigned <S> {
450 pub fn wrap (angle : Rad <S>) -> Self {
451 AngleWrappedSigned (angle.wrap_signed())
452 }
453
454 #[must_use]
455 pub fn map <F> (self, mut f : F) -> Self where F : FnMut (Rad <S>) -> Rad <S> {
456 AngleWrappedSigned (f (self.0).wrap_signed())
457 }
458}
459
460impl <S> Angles3 <S> {
465 pub const fn new (
466 yaw : AngleWrapped <S>,
467 pitch : AngleWrapped <S>,
468 roll : AngleWrapped <S>
469 ) -> Self {
470 Angles3 { yaw, pitch, roll }
471 }
472
473 pub fn zero() -> Self where S : Real {
474 use num::Zero;
475 Angles3::new (
476 AngleWrapped::zero(),
477 AngleWrapped::zero(),
478 AngleWrapped::zero())
479 }
480
481 pub fn wrap (yaw : Rad <S>, pitch : Rad <S>, roll : Rad <S>) -> Self where S : Real {
482 let yaw = AngleWrapped::wrap (yaw);
483 let pitch = AngleWrapped::wrap (pitch);
484 let roll = AngleWrapped::wrap (roll);
485 Angles3 { yaw, pitch, roll }
486 }
487}
488
489impl <S> From <Rotation3 <S>> for Angles3 <S> where S : Real + MaybeSerDes {
490 fn from (rotation : Rotation3 <S>) -> Self {
491 let (yaw, pitch, roll) = {
492 let (yaw, pitch, roll) = rotation.intrinsic_angles();
493 ( AngleWrapped::wrap (yaw),
494 AngleWrapped::wrap (pitch),
495 AngleWrapped::wrap (roll)
496 )
497 };
498 Angles3 { yaw, pitch, roll }
499 }
500}
501
502impl Axis2 {
506 #[inline]
507 pub const fn component (self) -> usize {
508 self as usize
509 }
510}
511
512impl Axis3 {
516 #[inline]
517 pub const fn component (self) -> usize {
518 self as usize
519 }
520}
521
522impl SignedAxis3 {
526 pub fn to_vec <S : Field> (self) -> Vector3 <S> {
527 match self {
528 SignedAxis3::NegX => [-S::one(), S::zero(), S::zero()].into(),
529 SignedAxis3::PosX => [ S::one(), S::zero(), S::zero()].into(),
530 SignedAxis3::NegY => [ S::zero(), -S::one(), S::zero()].into(),
531 SignedAxis3::PosY => [ S::zero(), S::one(), S::zero()].into(),
532 SignedAxis3::NegZ => [ S::zero(), S::zero(), -S::one() ].into(),
533 SignedAxis3::PosZ => [ S::zero(), S::zero(), S::one() ].into()
534 }
535 }
536 #[inline]
537 pub fn to_unit <S> (self) -> Unit3 <S> where S : Real + std::fmt::Debug {
538 Unit3::unchecked (self.to_vec())
539 }
540}
541impl <S : Field> TryFrom <Vector3 <S>> for SignedAxis3 {
542 type Error = Vector3 <S>;
543 fn try_from (vector : Vector3 <S>) -> Result <Self, Self::Error> {
544 let axis = if vector == Vector3::unit_x() {
545 SignedAxis3::PosX
546 } else if vector == -Vector3::unit_x() {
547 SignedAxis3::NegX
548 } else if vector == Vector3::unit_y() {
549 SignedAxis3::PosY
550 } else if vector == -Vector3::unit_y() {
551 SignedAxis3::NegY
552 } else if vector == Vector3::unit_z() {
553 SignedAxis3::PosZ
554 } else if vector == -Vector3::unit_z() {
555 SignedAxis3::NegZ
556 } else {
557 return Err (vector)
558 };
559 Ok (axis)
560 }
561}
562
563impl Quadrant {
567 pub fn from_vec_strict <S> (vector : Vector2 <S>) -> Option <Quadrant> where
570 S : Ring + SignedExt
571 {
572 let sign_x = vector.x.sign();
573 let sign_y = vector.y.sign();
574 let quadrant = match (sign_x, sign_y) {
575 (Sign::Zero, _) | (_, Sign::Zero) => return None,
576 (Sign::Positive, Sign::Positive) => Quadrant::PosPos,
577 (Sign::Negative, Sign::Positive) => Quadrant::NegPos,
578 (Sign::Positive, Sign::Negative) => Quadrant::PosNeg,
579 (Sign::Negative, Sign::Negative) => Quadrant::NegNeg
580 };
581 Some (quadrant)
582 }
583 #[inline]
585 pub fn from_point_strict <S> (point : Point2 <S>) -> Option <Quadrant> where
586 S : Ring + SignedExt
587 {
588 Quadrant::from_vec_strict (point.to_vector())
589 }
590}
591impl Octant {
597 pub fn from_vec_strict <S> (vector : Vector3 <S>) -> Option <Octant> where
600 S : Ring + SignedExt
601 {
602 let sign_x = vector.x.sign();
603 let sign_y = vector.y.sign();
604 let sign_z = vector.z.sign();
605 let octant = match (sign_x, sign_y, sign_z) {
606 (Sign::Zero, _, _) |
607 ( _, Sign::Zero, _) |
608 ( _, _, Sign::Zero) => return None,
609 (Sign::Positive, Sign::Positive, Sign::Positive) => Octant::PosPosPos,
610 (Sign::Negative, Sign::Positive, Sign::Positive) => Octant::NegPosPos,
611 (Sign::Positive, Sign::Negative, Sign::Positive) => Octant::PosNegPos,
612 (Sign::Negative, Sign::Negative, Sign::Positive) => Octant::NegNegPos,
613 (Sign::Positive, Sign::Positive, Sign::Negative) => Octant::PosPosNeg,
614 (Sign::Negative, Sign::Positive, Sign::Negative) => Octant::NegPosNeg,
615 (Sign::Positive, Sign::Negative, Sign::Negative) => Octant::PosNegNeg,
616 (Sign::Negative, Sign::Negative, Sign::Negative) => Octant::NegNegNeg
617 };
618 Some (octant)
619 }
620 #[inline]
622 pub fn from_point_strict <S> (point : Point3 <S>) -> Option <Octant> where
623 S : Ring + SignedExt
624 {
625 Octant::from_vec_strict (point.to_vector())
626 }
627}
628impl <S> Positive <S> where S : PartialOrd + num::Zero {
634 pub fn new (value : S) -> Option <Self> {
645 if value > S::zero() {
646 Some (Positive (value))
647 } else {
648 None
649 }
650 }
651 pub fn noisy (value : S) -> Self {
660 assert!(value > S::zero());
661 Positive (value)
662 }
663 pub fn unchecked (value : S) -> Self {
672 debug_assert!(value > S::zero());
673 Positive (value)
674 }
675 #[must_use]
696 pub fn map_noisy <F> (self, mut fun : F) -> Self where F : FnMut (S) -> S {
697 Self::noisy (fun (self.0))
698 }
699}
700impl <S> Positive <S> where S : num::float::FloatCore {
701 pub fn infinity() -> Self {
703 Positive (S::infinity())
704 }
705}
706impl Positive <f32> {
707 pub const fn new_f32 (value : f32) -> Option <Self> {
709 if 0.0 < value {
710 Some (Positive (value))
711 } else {
712 None
713 }
714 }
715 pub const fn noisy_f32 (value : f32) -> Self {
717 assert!(0.0 < value);
718 Positive (value)
719 }
720 pub const fn unchecked_f32 (value : f32) -> Self {
722 debug_assert!(0.0 < value);
723 Positive (value)
724 }
725}
726impl Positive <f64> {
727 pub const fn new_f64 (value : f64) -> Option <Self> {
729 if 0.0 < value {
730 Some (Positive (value))
731 } else {
732 None
733 }
734 }
735 pub const fn noisy_f64 (value : f64) -> Self {
737 assert!(0.0 < value);
738 Positive (value)
739 }
740 pub const fn unchecked_f64 (value : f64) -> Self {
742 debug_assert!(0.0 < value);
743 Positive (value)
744 }
745}
746impl <S : Ring> num::One for Positive <S> {
747 fn one() -> Self {
748 Positive (S::one())
749 }
750}
751impl <S> std::ops::Deref for Positive <S> {
752 type Target = S;
753 fn deref (&self) -> &S {
754 &self.0
755 }
756}
757impl <S : Ring> std::ops::Mul <Positive <S>> for Positive <S> {
758 type Output = Positive <S>;
759 fn mul (self, rhs : Positive <S>) -> Self::Output {
760 Positive (self.0 * *rhs)
761 }
762}
763impl <S : Ring> std::ops::MulAssign <Positive <S>> for Positive <S> {
764 fn mul_assign (&mut self, rhs : Positive <S>) {
765 self.0 *= *rhs
766 }
767}
768impl <S : Ring> std::ops::Mul <NonNegative <S>> for Positive <S> {
769 type Output = NonNegative <S>;
770 fn mul (self, rhs : NonNegative <S>) -> Self::Output {
771 NonNegative (self.0 * *rhs)
772 }
773}
774impl <S : Ring> std::ops::MulAssign <NonNegative <S>> for Positive <S> {
775 fn mul_assign (&mut self, rhs : NonNegative <S>) {
776 self.0 *= *rhs
777 }
778}
779impl <S : Field> std::ops::Div for Positive <S> {
780 type Output = Self;
781 fn div (self, rhs : Self) -> Self::Output {
782 Positive (self.0 / rhs.0)
783 }
784}
785impl <S : Field> std::ops::DivAssign for Positive <S> {
786 fn div_assign (&mut self, rhs : Self) {
787 self.0 /= rhs.0
788 }
789}
790impl <S : Ring> std::ops::Add for Positive <S> {
791 type Output = Self;
792 fn add (self, rhs : Self) -> Self::Output {
793 Positive (self.0 + rhs.0)
794 }
795}
796impl <S : Ring> std::ops::AddAssign for Positive <S> {
797 fn add_assign (&mut self, rhs : Self) {
798 self.0 += rhs.0
799 }
800}
801impl <S : Ring> std::ops::Add <NonNegative <S>> for Positive <S> {
802 type Output = Self;
803 fn add (self, rhs : NonNegative <S>) -> Self::Output {
804 Positive (self.0 + rhs.0)
805 }
806}
807impl <S : Ring> std::ops::AddAssign <NonNegative <S>> for Positive <S> {
808 fn add_assign (&mut self, rhs : NonNegative <S>) {
809 self.0 += rhs.0
810 }
811}
812impl <S> NonNegative <S> where S : PartialOrd + num::Zero {
818 pub fn new (value : S) -> Option <Self> {
829 if value >= S::zero() {
830 Some (NonNegative (value))
831 } else {
832 None
833 }
834 }
835 pub fn noisy (value : S) -> Self {
844 assert!(S::zero() <= value);
845 NonNegative (value)
846 }
847 pub fn unchecked (value : S) -> Self {
857 debug_assert!(value >= S::zero());
858 NonNegative (value)
859 }
860 #[must_use]
878 pub fn map_noisy <F> (self, mut fun : F) -> Self where F : FnMut (S) -> S {
879 Self::noisy (fun (self.0))
880 }
881}
882impl <S> NonNegative <S> where S : num::Signed {
883 pub fn abs (value : S) -> Self {
893 NonNegative (value.abs())
894 }
895 #[must_use]
905 pub fn map_abs <F> (self, mut fun : F) -> Self where F : FnMut (S) -> S {
906 Self::abs (fun (self.0))
907 }
908}
909impl <S : Sqrt> Sqrt for NonNegative <S> {
910 fn sqrt (self) -> Self {
911 NonNegative (self.0.sqrt())
912 }
913}
914impl <S : MinMax> MinMax for NonNegative <S> {
915 fn min (self, other : Self) -> Self {
916 NonNegative (S::min (self.0, other.0))
917 }
918 fn max (self, other : Self) -> Self {
919 NonNegative (S::max (self.0, other.0))
920 }
921 fn clamp (self, min : Self, max : Self) -> Self {
922 NonNegative (self.0.clamp (min.0, max.0))
923 }
924}
925impl NonNegative <f32> {
926 pub const fn new_f32 (value : f32) -> Option <Self> {
928 if 0.0 <= value {
929 Some (NonNegative (value))
930 } else {
931 None
932 }
933 }
934 pub const fn noisy_f32 (value : f32) -> Self {
936 assert!(0.0 <= value);
937 NonNegative (value)
938 }
939 pub const fn unchecked_f32 (value : f32) -> Self {
941 debug_assert!(0.0 <= value);
942 NonNegative (value)
943 }
944}
945impl NonNegative <f64> {
946 pub const fn new_f64 (value : f64) -> Option <Self> {
948 if 0.0 <= value {
949 Some (NonNegative (value))
950 } else {
951 None
952 }
953 }
954 pub const fn noisy_f64 (value : f64) -> Self {
956 assert!(0.0 <= value);
957 NonNegative (value)
958 }
959 pub const fn unchecked_f64 (value : f64) -> Self {
961 debug_assert!(0.0 <= value);
962 NonNegative (value)
963 }
964}
965impl <S : Ring> From <Positive <S>> for NonNegative <S> {
966 fn from (positive : Positive <S>) -> Self {
967 NonNegative (*positive)
968 }
969}
970impl <S : Ring> num::Zero for NonNegative <S> {
971 fn zero() -> Self {
972 NonNegative (S::zero())
973 }
974 fn is_zero (&self) -> bool {
975 self.0.is_zero()
976 }
977}
978impl <S : Field> num::One for NonNegative <S> {
979 fn one() -> Self {
980 NonNegative (S::one())
981 }
982}
983impl <S> std::ops::Deref for NonNegative <S> {
984 type Target = S;
985 fn deref (&self) -> &S {
986 &self.0
987 }
988}
989impl <S : Ring> std::ops::Mul for NonNegative <S> {
990 type Output = Self;
991 fn mul (self, rhs : Self) -> Self::Output {
992 NonNegative (self.0 * rhs.0)
993 }
994}
995impl <S : Ring> std::ops::Mul <Positive <S>> for NonNegative <S> {
996 type Output = Self;
997 fn mul (self, rhs : Positive <S>) -> Self::Output {
998 NonNegative (self.0 * rhs.0)
999 }
1000}
1001impl <S : Field> std::ops::Div for NonNegative <S> {
1002 type Output = Self;
1003 fn div (self, rhs : Self) -> Self::Output {
1004 NonNegative (self.0 / rhs.0)
1005 }
1006}
1007impl <S : Ring> std::ops::Add for NonNegative <S> {
1008 type Output = Self;
1009 fn add (self, rhs : Self) -> Self::Output {
1010 NonNegative (self.0 + rhs.0)
1011 }
1012}
1013impl <S> NonZero <S> where S : PartialEq + num::Zero {
1019 #[inline]
1030 pub fn new (value : S) -> Option <Self> {
1031 if S::zero() != value {
1032 Some (NonZero (value))
1033 } else {
1034 None
1035 }
1036 }
1037 #[inline]
1046 pub fn noisy (value : S) -> Self where S : std::fmt::Debug {
1047 assert_ne!(S::zero(), value);
1048 NonZero (value)
1049 }
1050 #[inline]
1059 pub fn unchecked (value : S) -> Self where S : std::fmt::Debug {
1060 debug_assert_ne!(S::zero(), value);
1061 NonZero (value)
1062 }
1063 #[inline]
1083 #[must_use]
1084 pub fn map_noisy <F> (self, mut fun : F) -> Self where
1085 S : std::fmt::Debug,
1086 F : FnMut (S) -> S
1087 {
1088 Self::noisy (fun (self.0))
1089 }
1090}
1091impl NonZero <f32> {
1092 pub const fn new_f32 (value : f32) -> Option <Self> {
1094 if value != 0.0 {
1095 Some (NonZero (value))
1096 } else {
1097 None
1098 }
1099 }
1100 pub const fn noisy_f32 (value : f32) -> Self {
1102 assert!(value != 0.0);
1103 NonZero (value)
1104 }
1105 pub const fn unchecked_f32 (value : f32) -> Self {
1107 debug_assert!(value != 0.0);
1108 NonZero (value)
1109 }
1110}
1111impl NonZero <f64> {
1112 pub const fn new_f64 (value : f64) -> Option <Self> {
1114 if value != 0.0 {
1115 Some (NonZero (value))
1116 } else {
1117 None
1118 }
1119 }
1120 pub const fn noisy_f64 (value : f64) -> Self {
1122 assert!(value != 0.0);
1123 NonZero (value)
1124 }
1125 pub const fn unchecked_f64 (value : f64) -> Self {
1127 debug_assert!(value != 0.0);
1128 NonZero (value)
1129 }
1130}
1131impl <S : MultiplicativeMonoid> num::One for NonZero <S> {
1132 fn one() -> Self {
1133 NonZero (S::one())
1134 }
1135}
1136impl <S> std::ops::Deref for NonZero <S> {
1137 type Target = S;
1138 fn deref (&self) -> &S {
1139 &self.0
1140 }
1141}
1142impl <S : MultiplicativeMonoid> std::ops::Mul for NonZero <S> {
1143 type Output = Self;
1144 fn mul (self, rhs : Self) -> Self::Output {
1145 NonZero (self.0 * rhs.0)
1146 }
1147}
1148impl <S : PartialEq> Eq for NonZero <S> { }
1149impl <S> Normalized <S> where S : num::One + num::Zero {
1155 #[inline]
1157 pub fn zero() -> Self {
1158 Normalized (S::zero())
1159 }
1160 #[inline]
1161 pub fn is_zero (&self) -> bool {
1162 self.0.is_zero()
1163 }
1164 #[inline]
1178 pub fn new (value : S) -> Option <Self> where S : PartialOrd {
1179 if S::zero() <= value && value <= S::one() {
1180 Some (Normalized (value))
1181 } else {
1182 None
1183 }
1184 }
1185 #[inline]
1196 #[expect(clippy::same_name_method)]
1197 pub fn clamp (value : S) -> Self where S : MinMax {
1198 Normalized (value.clamp (S::zero(), S::one()))
1199 }
1200 #[inline]
1214 pub fn noisy (value : S) -> Self where S : PartialOrd {
1215 assert!(value <= S::one());
1216 assert!(S::zero() <= value);
1217 Normalized (value)
1218 }
1219 pub fn unchecked (value : S) -> Self where S : PartialOrd {
1229 debug_assert!(value <= S::one());
1230 debug_assert!(S::zero() <= value);
1231 Normalized (value)
1232 }
1233 #[inline]
1245 #[must_use]
1246 pub fn map_clamp <F> (self, mut fun : F) -> Self where
1247 S : MinMax,
1248 F : FnMut (S) -> S
1249 {
1250 Self::clamp (fun (self.0))
1251 }
1252 #[inline]
1279 #[must_use]
1280 pub fn map_noisy <F> (self, mut fun : F) -> Self where
1281 S : PartialOrd,
1282 F : FnMut (S) -> S
1283 {
1284 Self::noisy (fun (self.0))
1285 }
1286}
1287impl Normalized <f32> {
1288 pub const fn new_f32 (value : f32) -> Option <Self> {
1290 if 0.0 <= value && value <= 1.0 {
1291 Some (Normalized (value))
1292 } else {
1293 None
1294 }
1295 }
1296 pub const fn noisy_f32 (value : f32) -> Self {
1298 assert!(value <= 1.0);
1299 assert!(0.0 <= value);
1300 Normalized (value)
1301 }
1302 pub const fn unchecked_f32 (value : f32) -> Self {
1304 debug_assert!(value <= 1.0);
1305 debug_assert!(0.0 <= value);
1306 Normalized (value)
1307 }
1308}
1309impl Normalized <f64> {
1310 pub const fn new_f64 (value : f64) -> Option <Self> {
1312 if 0.0 <= value && value <= 1.0 {
1313 Some (Normalized (value))
1314 } else {
1315 None
1316 }
1317 }
1318 pub const fn noisy_f64 (value : f64) -> Self {
1320 assert!(value <= 1.0);
1321 assert!(0.0 <= value);
1322 Normalized (value)
1323 }
1324 pub const fn unchecked_f64 (value : f64) -> Self {
1326 debug_assert!(value <= 1.0);
1327 debug_assert!(0.0 <= value);
1328 Normalized (value)
1329 }
1330}
1331impl <S : Ring> num::One for Normalized <S> {
1332 fn one() -> Self {
1333 Normalized (S::one())
1334 }
1335}
1336impl <S> std::ops::Deref for Normalized <S> {
1337 type Target = S;
1338 fn deref (&self) -> &S {
1339 &self.0
1340 }
1341}
1342impl <S : Ring> std::ops::Mul for Normalized <S> {
1343 type Output = Self;
1344 fn mul (self, rhs : Self) -> Self::Output {
1345 Normalized (self.0 * rhs.0)
1346 }
1347}
1348impl <S : PartialEq> Eq for Normalized <S> { }
1349#[expect(clippy::derive_ord_xor_partial_ord)]
1350impl <S : PartialOrd> Ord for Normalized <S> {
1351 fn cmp (&self, other : &Self) -> std::cmp::Ordering {
1352 self.partial_cmp (other).unwrap()
1354 }
1355}
1356impl <S> NormalSigned <S> {
1362 #[inline]
1364 pub fn zero() -> Self where S : num::Zero {
1365 NormalSigned (S::zero())
1366 }
1367 #[inline]
1368 pub fn is_zero (&self) -> bool where S : num::Zero {
1369 self.0.is_zero()
1370 }
1371 #[inline]
1385 pub fn new (value : S) -> Option <Self> where S : OrderedRing {
1386 if -S::one() <= value && value <= S::one() {
1387 Some (NormalSigned (value))
1388 } else {
1389 None
1390 }
1391 }
1392 #[inline]
1403 #[expect(clippy::same_name_method)]
1404 pub fn clamp (value : S) -> Self where S : Ring + MinMax {
1405 NormalSigned (value.clamp (-S::one(), S::one()))
1406 }
1407 #[inline]
1421 pub fn noisy (value : S) -> Self where S : OrderedRing {
1422 assert!(value <= S::one());
1423 assert!(-S::one() <= value);
1424 NormalSigned (value)
1425 }
1426 #[inline]
1438 #[must_use]
1439 pub fn map_clamp <F> (self, mut fun : F) -> Self where
1440 S : Ring + MinMax,
1441 F : FnMut (S) -> S
1442 {
1443 Self::clamp (fun (self.0))
1444 }
1445 #[inline]
1472 #[must_use]
1473 pub fn map_noisy <F> (self, mut fun : F) -> Self where
1474 S : OrderedRing,
1475 F : FnMut (S) -> S
1476 {
1477 Self::noisy (fun (self.0))
1478 }
1479}
1480impl NormalSigned <f32> {
1481 pub const fn new_f32 (value : f32) -> Option <Self> {
1483 if -1.0 <= value && value <= 1.0 {
1484 Some (NormalSigned (value))
1485 } else {
1486 None
1487 }
1488 }
1489 pub const fn noisy_f32 (value : f32) -> Self {
1491 assert!(value <= 1.0);
1492 assert!(-1.0 <= value);
1493 NormalSigned (value)
1494 }
1495 pub const fn unchecked_f32 (value : f32) -> Self {
1497 debug_assert!(value <= 1.0);
1498 debug_assert!(-1.0 <= value);
1499 NormalSigned (value)
1500 }
1501}
1502impl NormalSigned <f64> {
1503 pub const fn new_f64 (value : f64) -> Option <Self> {
1505 if -1.0 <= value && value <= 1.0 {
1506 Some (NormalSigned (value))
1507 } else {
1508 None
1509 }
1510 }
1511 pub const fn noisy_f64 (value : f64) -> Self {
1513 assert!(value <= 1.0);
1514 assert!(-1.0 <= value);
1515 NormalSigned (value)
1516 }
1517 pub const fn unchecked_f64 (value : f64) -> Self {
1519 debug_assert!(value <= 1.0);
1520 debug_assert!(-1.0 <= value);
1521 NormalSigned (value)
1522 }
1523}
1524impl <S : OrderedField> From <Normalized <S>> for NormalSigned <S> {
1525 fn from (Normalized (value) : Normalized <S>) -> Self {
1526 debug_assert!(S::zero() <= value);
1527 debug_assert!(value <= S::one());
1528 NormalSigned (value)
1529 }
1530}
1531impl <S : Field> num::One for NormalSigned <S> {
1532 fn one() -> Self {
1533 NormalSigned (S::one())
1534 }
1535}
1536impl <S> std::ops::Deref for NormalSigned <S> {
1537 type Target = S;
1538 fn deref (&self) -> &S {
1539 &self.0
1540 }
1541}
1542impl <S : Field> std::ops::Mul for NormalSigned <S> {
1543 type Output = Self;
1544 fn mul (self, rhs : Self) -> Self::Output {
1545 NormalSigned (self.0 * rhs.0)
1546 }
1547}
1548impl <S : Field> Eq for NormalSigned <S> { }
1549#[expect(clippy::derive_ord_xor_partial_ord)]
1550impl <S : OrderedField> Ord for NormalSigned <S> {
1551 fn cmp (&self, other : &Self) -> std::cmp::Ordering {
1552 self.partial_cmp (other).unwrap()
1554 }
1555}
1556impl <S : Field> std::ops::Neg for NormalSigned <S> {
1557 type Output = Self;
1558 fn neg (self) -> Self {
1559 NormalSigned (-self.0)
1560 }
1561}
1562impl <S : Ring> Vector2Ext <S> for Vector2 <S> {
1568 fn exterior_product (self, rhs : Vector2 <S>) -> S {
1570 self.x * rhs.y - self.y * rhs.x
1571 }
1572}
1573fn ortho_vec2 <S> (vector : Vector2 <S>) -> Vector2 <S> {
1574 vector.yx()
1575}
1576
1577fn ortho_vec3 <S> (vector : Vector3 <S>) -> Vector3 <S> where
1581 S : Ring + approx::AbsDiffEq <Epsilon = S>
1582{
1583 let mut ortho = vector.cross (Vector3::unit_x());
1587 if approx::abs_diff_eq!(ortho, Vector3::zero()) {
1588 ortho = vector.cross (Vector3::unit_y())
1589 }
1590 ortho
1591}
1592
1593fn ortho_vec4 <S> (_vector : Vector4 <S>) -> Vector4 <S> {
1597 unimplemented!("TODO")
1598}
1599
1600impl <S> std::ops::Deref for Unit <S> {
1604 type Target = S;
1605 fn deref (&self) -> &S {
1606 &self.0
1607 }
1608}
1609
1610impl <S> Rotation2 <S> where S : Ring + MaybeSerDes {
1614 pub fn identity() -> Self {
1616 use num::One;
1617 Self::one()
1618 }
1619 pub fn new (mat : Matrix2 <S>) -> Option <Self> {
1624 let transform = LinearAuto (LinearIso::new (mat)?);
1625 if !transform.is_rotation() {
1626 None
1627 } else {
1628 Some (Rotation2 (transform))
1629 }
1630 }
1631 pub fn new_approx (mat : Matrix2 <S>) -> Option <Self> where
1637 S : approx::RelativeEq <Epsilon=S>
1638 {
1639 let four = S::one() + S::one() + S::one() + S::one();
1640 let thirtytwo = four * four * (S::one() + S::one());
1641 let epsilon = S::default_epsilon() * thirtytwo;
1642 let max_relative = S::default_max_relative() * four;
1643 if approx::relative_ne!(mat * mat.transposed(), Matrix2::identity(),
1644 max_relative=max_relative, epsilon=epsilon
1645 ) || approx::relative_ne!(mat.determinant(), S::one(), max_relative=max_relative) {
1646 None
1647 } else {
1648 Some (Rotation2 (LinearAuto (LinearIso (mat, PhantomData))))
1649 }
1650 }
1651 pub fn from_angle (angle : Rad <S>) -> Self where S : num::real::Real {
1653 Rotation2 (LinearAuto (LinearIso (Matrix2::rotation_z (angle.0), PhantomData)))
1654 }
1655 pub fn noisy (mat : Matrix2 <S>) -> Self where S : std::fmt::Debug {
1659 assert_eq!(mat * mat.transposed(), Matrix2::identity());
1660 assert_eq!(mat.determinant(), S::one());
1661 Rotation2 (LinearAuto (LinearIso (mat, PhantomData)))
1662 }
1663 pub fn noisy_approx (mat : Matrix2 <S>) -> Self where
1668 S : approx::RelativeEq <Epsilon=S> + std::fmt::Debug
1669 {
1670 let four = S::one() + S::one() + S::one() + S::one();
1671 let epsilon = S::default_epsilon() * four;
1672 let max_relative = S::default_max_relative() * four;
1673 approx::assert_relative_eq!(mat * mat.transposed(), Matrix2::identity(),
1674 epsilon=epsilon, max_relative=max_relative);
1675 approx::assert_relative_eq!(mat.determinant(), S::one(), max_relative=max_relative);
1676 Rotation2 (LinearAuto (LinearIso (mat, PhantomData)))
1677 }
1678 pub fn unchecked (mat : Matrix2 <S>) -> Self where S : std::fmt::Debug {
1682 debug_assert!(mat * mat.transposed() == Matrix2::identity());
1683 debug_assert!(mat.determinant() == S::one());
1684 Rotation2 (LinearAuto (LinearIso (mat, PhantomData)))
1685 }
1686 pub fn unchecked_approx (mat : Matrix2 <S>) -> Self where
1691 S : approx::RelativeEq <Epsilon=S> + std::fmt::Debug
1692 {
1693 if cfg!(debug_assertions) {
1694 let four = S::one() + S::one() + S::one() + S::one();
1695 let epsilon = S::default_epsilon() * four;
1696 let max_relative = S::default_max_relative() * four;
1697 approx::assert_relative_eq!(mat * mat.transposed(), Matrix2::identity(),
1698 max_relative=max_relative, epsilon=epsilon);
1699 approx::assert_relative_eq!(mat.determinant(), S::one(),
1700 max_relative=max_relative);
1701 }
1702 Rotation2 (LinearAuto (LinearIso (mat, PhantomData)))
1703 }
1704 pub const fn mat (self) -> Matrix2 <S> {
1706 self.0.0.0
1707 }
1708 pub fn rotate (self, point : Point2 <S>) -> Point2 <S> {
1710 Point2::from (self * point.0)
1711 }
1712 pub fn rotate_around (self, point : Point2 <S>, center : Point2 <S>) -> Point2 <S> {
1714 self.rotate (point - center.0) + center.0
1715 }
1716}
1717impl <S> std::ops::Deref for Rotation2 <S> where S : Ring + MaybeSerDes {
1718 type Target = LinearAuto <S, Vector2 <S>>;
1719 fn deref (&self) -> &Self::Target {
1720 &self.0
1721 }
1722}
1723impl <S> num::Inv for Rotation2 <S> where S : Ring + MaybeSerDes {
1724 type Output = Self;
1725 fn inv (self) -> Self::Output {
1726 Rotation2 (LinearAuto (LinearIso (self.0.0.0.transpose(), PhantomData)))
1727 }
1728}
1729impl <S> std::ops::Mul <Vector2 <S>> for Rotation2 <S> where S : Ring + MaybeSerDes {
1730 type Output = Vector2 <S>;
1731 fn mul (self, rhs : Vector2 <S>) -> Self::Output {
1732 self.0 * rhs
1733 }
1734}
1735impl <S> std::ops::Mul <NonZero2 <S>> for Rotation2 <S> where S : Ring + MaybeSerDes {
1736 type Output = NonZero2 <S>;
1737 fn mul (self, rhs : NonZero2 <S>) -> Self::Output {
1738 NonZero2 (self.0 * rhs.0)
1739 }
1740}
1741impl <S> std::ops::Mul <Unit2 <S>> for Rotation2 <S> where S : Ring + MaybeSerDes {
1742 type Output = Unit2 <S>;
1743 fn mul (self, rhs : Unit2 <S>) -> Self::Output {
1744 Unit2 (self.0 * rhs.0)
1745 }
1746}
1747impl <S> std::ops::Mul <Rotation2 <S>> for Vector2 <S> where S : Ring + MaybeSerDes {
1748 type Output = Vector2 <S>;
1749 fn mul (self, rhs : Rotation2 <S>) -> Self::Output {
1750 self * rhs.0
1751 }
1752}
1753impl <S> std::ops::Mul for Rotation2 <S> where S : Ring + MaybeSerDes {
1754 type Output = Self;
1755 fn mul (self, rhs : Self) -> Self::Output {
1756 Rotation2 (self.0 * rhs.0)
1757 }
1758}
1759impl <S> std::ops::MulAssign <Self> for Rotation2 <S> where S : Ring + MaybeSerDes {
1760 fn mul_assign (&mut self, rhs : Self) {
1761 self.0 *= rhs.0
1762 }
1763}
1764impl <S> std::ops::Div for Rotation2 <S> where S : Ring + MaybeSerDes {
1765 type Output = Self;
1766 #[expect(clippy::suspicious_arithmetic_impl)]
1767 fn div (self, rhs : Self) -> Self::Output {
1768 use num::Inv;
1769 self * rhs.inv()
1770 }
1771}
1772impl <S> std::ops::DivAssign <Self> for Rotation2 <S> where S : Ring + MaybeSerDes {
1773 #[expect(clippy::suspicious_op_assign_impl)]
1774 fn div_assign (&mut self, rhs : Self) {
1775 use num::Inv;
1776 *self *= rhs.inv()
1777 }
1778}
1779impl <S> num::One for Rotation2 <S> where S : Ring + MaybeSerDes + num::Zero + num::One {
1780 fn one() -> Self {
1781 Rotation2 (LinearAuto (LinearIso (Matrix2::identity(), PhantomData)))
1782 }
1783}
1784
1785impl <S> Rotation3 <S> where S : Ring + MaybeSerDes {
1789 pub fn identity() -> Self {
1791 use num::One;
1792 Self::one()
1793 }
1794 pub fn new (mat : Matrix3 <S>) -> Option <Self> {
1799 if mat * mat.transposed() != Matrix3::identity() || mat.determinant() != S::one() {
1800 None
1801 } else {
1802 Some (Rotation3 (LinearAuto (LinearIso (mat, PhantomData))))
1803 }
1804 }
1805 pub fn new_approx (mat : Matrix3 <S>) -> Option <Self> where
1811 S : approx::RelativeEq <Epsilon=S>
1812 {
1813 let four = S::one() + S::one() + S::one() + S::one();
1814 let thirtytwo = four * four * (S::one() + S::one());
1815 let epsilon = S::default_epsilon() * thirtytwo;
1816 let max_relative = S::default_max_relative() * four;
1817 if approx::relative_ne!(mat * mat.transposed(), Matrix3::identity(),
1818 max_relative=max_relative, epsilon=epsilon
1819 ) || approx::relative_ne!(mat.determinant(), S::one(), max_relative=max_relative) {
1820 None
1821 } else {
1822 Some (Rotation3 (LinearAuto (LinearIso (mat, PhantomData))))
1823 }
1824 }
1825 pub fn noisy (mat : Matrix3 <S>) -> Self {
1829 assert!(mat * mat.transposed() == Matrix3::identity());
1830 assert!(mat.determinant() == S::one());
1831 Rotation3 (LinearAuto (LinearIso (mat, PhantomData)))
1832 }
1833 pub fn noisy_approx (mat : Matrix3 <S>) -> Self where
1838 S : approx::RelativeEq <Epsilon=S> + std::fmt::Debug
1839 {
1840 let four = S::one() + S::one() + S::one() + S::one();
1841 let eight = four + S::one() + S::one() + S::one() + S::one();
1842 let epsilon = S::default_epsilon() * four;
1843 let max_relative = S::default_max_relative() * eight;
1844 approx::assert_relative_eq!(mat * mat.transposed(), Matrix3::identity(),
1845 max_relative=max_relative, epsilon=epsilon);
1846 approx::assert_relative_eq!(mat.determinant(), S::one(), max_relative=max_relative);
1847 Rotation3 (LinearAuto (LinearIso (mat, PhantomData)))
1848 }
1849 pub fn unchecked (mat : Matrix3 <S>) -> Self where S : std::fmt::Debug {
1853 debug_assert!(mat * mat.transposed() == Matrix3::identity());
1854 debug_assert!(mat.determinant() == S::one());
1855 Rotation3 (LinearAuto (LinearIso (mat, PhantomData)))
1856 }
1857 pub fn unchecked_approx (mat : Matrix3 <S>) -> Self where
1862 S : approx::RelativeEq <Epsilon=S> + std::fmt::Debug
1863 {
1864 if cfg!(debug_assertions) {
1865 let four = S::one() + S::one() + S::one() + S::one();
1866 let epsilon = S::default_epsilon() * four;
1867 let max_relative = S::default_max_relative() * four;
1868 approx::assert_relative_eq!(mat * mat.transposed(), Matrix3::identity(),
1869 max_relative=max_relative, epsilon=epsilon);
1870 approx::assert_relative_eq!(mat.determinant(), S::one(),
1871 max_relative=max_relative);
1872 }
1873 Rotation3 (LinearAuto (LinearIso (mat, PhantomData)))
1874 }
1875 pub fn from_angle_x (angle : Rad <S>) -> Self where S : num::real::Real {
1879 Rotation3 (LinearAuto (LinearIso (Matrix3::rotation_x (angle.0), PhantomData)))
1880 }
1881 pub fn from_angle_y (angle : Rad <S>) -> Self where S : num::real::Real {
1885 Rotation3 (LinearAuto (LinearIso (Matrix3::rotation_y (angle.0), PhantomData)))
1886 }
1887 pub fn from_angle_z (angle : Rad <S>) -> Self where S : num::real::Real {
1891 Rotation3 (LinearAuto (LinearIso (Matrix3::rotation_z (angle.0), PhantomData)))
1892 }
1893 pub fn from_angles_intrinsic (yaw : Rad <S>, pitch : Rad <S>, roll : Rad <S>)
1899 -> Self where S : num::real::Real
1900 {
1901 let rotation1 = Rotation3::from_angle_z (yaw);
1902 let rotation2 = Rotation3::from_axis_angle (rotation1.cols.x, pitch) * rotation1;
1903 Rotation3::from_axis_angle (rotation2.cols.y, roll) * rotation2
1904 }
1905 pub fn from_axis_angle (axis : Vector3 <S>, angle : Rad <S>) -> Self where
1907 S : num::real::Real
1908 {
1909 Rotation3 (LinearAuto (LinearIso (
1910 Matrix3::rotation_3d (angle.0, axis), PhantomData)))
1911 }
1912 pub fn orthonormalize (v1 : Vector3 <S>, v2 : Vector3 <S>, v3 : Vector3 <S>)
1915 -> Option <Self> where S : OrderedField + Sqrt
1916 {
1917 if Matrix3::from_col_arrays ([v1, v2, v3].map (Vector3::into_array)).determinant()
1918 == S::zero()
1919 {
1920 None
1921 } else {
1922 let project = |u : Vector3 <S>, v : Vector3 <S>| u * (u.dot (v) / *u.self_dot());
1923 let u1 = v1;
1924 let u2 = v2 - project (u1, v2);
1925 let u3 = v3 - project (u1, v3) - project (u2, v3);
1926 Some (Rotation3 (LinearAuto (LinearIso (Matrix3::from_col_arrays ([
1927 u1.normalize().into_array(),
1928 u2.normalize().into_array(),
1929 u3.normalize().into_array()
1930 ]), PhantomData))))
1931 }
1932 }
1933
1934 pub fn look_at (point : Point3 <S>) -> Self where
1938 S : num::Float + num::FloatConst + approx::RelativeEq <Epsilon=S> + std::fmt::Debug
1939 {
1940 if point == Point::origin() {
1941 Self::identity()
1942 } else {
1943 use num::Zero;
1944 let forward = point.0.normalized();
1945 let right = {
1946 let projected = forward.with_z (S::zero());
1947 if !projected.is_zero() {
1948 Self::from_angle_z (-Rad (S::FRAC_PI_2())) * projected.normalized()
1949 } else {
1950 Vector3::unit_x()
1951 }
1952 };
1953 let up = right.cross (forward);
1954 let mat =
1955 Matrix3::from_col_arrays ([right, forward, up].map (Vector3::into_array));
1956 Self::noisy_approx (mat)
1957 }
1958 }
1959
1960 pub fn intrinsic_angles (&self) -> (Rad <S>, Rad <S>, Rad <S>) where S : Real {
1965 let cols = &self.cols;
1966 let yaw = Rad (S::atan2 (-cols.y.x, cols.y.y));
1967 let pitch = Rad (S::atan2 (cols.y.z, S::sqrt (S::one() - cols.y.z * cols.y.z)));
1968 let roll = Rad (S::atan2 (-cols.x.z, cols.z.z));
1969 (yaw, pitch, roll)
1970 }
1971
1972 pub fn versor (self) -> Versor <S> where
1976 S : Real + MaybeSerDes + num::real::Real + approx::RelativeEq <Epsilon=S>
1977 {
1978 let diagonal = self.diagonal();
1979 let t = diagonal.sum();
1980 let m =
1981 MinMax::max (MinMax::max (MinMax::max (diagonal.x, diagonal.y), diagonal.z), t);
1982 let qmax = S::half() * Sqrt::sqrt (S::one() - t + S::two() * m);
1983 let qmax4_recip = (S::four() * qmax).recip();
1984 let [qx, qy, qz, qw] : [S; 4];
1985 let cols = self.cols;
1986 if m == diagonal.x {
1987 qx = qmax;
1988 qy = qmax4_recip * (cols.x.y + cols.y.x);
1989 qz = qmax4_recip * (cols.x.z + cols.z.x);
1990 qw = -qmax4_recip * (cols.z.y - cols.y.z);
1991 } else if m == diagonal.y {
1992 qx = qmax4_recip * (cols.x.y + cols.y.x);
1993 qy = qmax;
1994 qz = qmax4_recip * (cols.y.z + cols.z.y);
1995 qw = -qmax4_recip * (cols.x.z - cols.z.x);
1996 } else if m == diagonal.z {
1997 qx = qmax4_recip * (cols.x.z + cols.z.x);
1998 qy = qmax4_recip * (cols.y.z + cols.z.y);
1999 qz = qmax;
2000 qw = -qmax4_recip * (cols.y.x - cols.x.y);
2001 } else {
2002 qx = -qmax4_recip * (cols.z.y - cols.y.z);
2003 qy = -qmax4_recip * (cols.x.z - cols.z.x);
2004 qz = -qmax4_recip * (cols.y.x - cols.x.y);
2005 qw = qmax;
2006 }
2007 let quat = Quaternion::from_xyzw (qx, qy, qz, qw);
2008 Versor::unchecked_approx (quat)
2009 }
2010 pub const fn mat (self) -> Matrix3 <S> {
2012 self.0.0.0
2013 }
2014 pub fn rotate (self, point : Point3 <S>) -> Point3 <S> {
2016 Point3::from (self * point.0)
2017 }
2018 pub fn rotate_around (self, point : Point3 <S>, center : Point3 <S>) -> Point3 <S> {
2020 self.rotate (point - center.0) + center.0
2021 }
2022}
2023impl <S> std::ops::Deref for Rotation3 <S> where S : Ring + MaybeSerDes {
2024 type Target = LinearAuto <S, Vector3 <S>>;
2025 fn deref (&self) -> &Self::Target {
2026 &self.0
2027 }
2028}
2029impl <S> num::Inv for Rotation3 <S> where S : Ring + MaybeSerDes {
2030 type Output = Self;
2031 fn inv (self) -> Self::Output {
2032 Rotation3 (LinearAuto (LinearIso (self.0.0.0.transpose(), PhantomData)))
2033 }
2034}
2035impl <S> std::ops::Mul <Vector3 <S>> for Rotation3 <S> where S : Ring + MaybeSerDes {
2036 type Output = Vector3 <S>;
2037 fn mul (self, rhs : Vector3 <S>) -> Self::Output {
2038 self.0 * rhs
2039 }
2040}
2041impl <S> std::ops::Mul <NonZero3 <S>> for Rotation3 <S> where S : Ring + MaybeSerDes {
2042 type Output = NonZero3 <S>;
2043 fn mul (self, rhs : NonZero3 <S>) -> Self::Output {
2044 NonZero3 (self.0 * rhs.0)
2045 }
2046}
2047impl <S> std::ops::Mul <Unit3 <S>> for Rotation3 <S> where S : Ring + MaybeSerDes {
2048 type Output = Unit3 <S>;
2049 fn mul (self, rhs : Unit3 <S>) -> Self::Output {
2050 Unit3 (self.0 * rhs.0)
2051 }
2052}
2053impl <S> std::ops::Mul <Rotation3 <S>> for Vector3 <S> where S : Ring + MaybeSerDes {
2054 type Output = Vector3 <S>;
2055 fn mul (self, rhs : Rotation3 <S>) -> Self::Output {
2056 self * rhs.0
2057 }
2058}
2059impl <S> std::ops::Mul for Rotation3 <S> where S : Ring + MaybeSerDes {
2060 type Output = Self;
2061 fn mul (self, rhs : Self) -> Self::Output {
2062 Rotation3 (self.0 * rhs.0)
2063 }
2064}
2065impl <S> std::ops::MulAssign <Self> for Rotation3 <S> where S : Ring + MaybeSerDes {
2066 fn mul_assign (&mut self, rhs : Self) {
2067 self.0 *= rhs.0
2068 }
2069}
2070impl <S> std::ops::Div for Rotation3 <S> where S : Ring + MaybeSerDes {
2071 type Output = Self;
2072 #[expect(clippy::suspicious_arithmetic_impl)]
2073 fn div (self, rhs : Self) -> Self::Output {
2074 use num::Inv;
2075 self * rhs.inv()
2076 }
2077}
2078impl <S> std::ops::DivAssign <Self> for Rotation3 <S> where S : Ring + MaybeSerDes {
2079 #[expect(clippy::suspicious_op_assign_impl)]
2080 fn div_assign (&mut self, rhs : Self) {
2081 use num::Inv;
2082 *self *= rhs.inv()
2083 }
2084}
2085impl <S> num::One for Rotation3 <S> where S : Ring + MaybeSerDes + num::Zero + num::One {
2086 fn one() -> Self {
2087 Rotation3 (LinearAuto (LinearIso (Matrix3::identity(), PhantomData)))
2088 }
2089}
2090impl <S> From <Angles3 <S>> for Rotation3 <S> where
2091 S : Real + num::real::Real + MaybeSerDes
2092{
2093 fn from (angles : Angles3 <S>) -> Self {
2094 Rotation3::from_angles_intrinsic (
2095 angles.yaw.angle(), angles.pitch.angle(), angles.roll.angle())
2096 }
2097}
2098
2099impl <S : Real> Versor <S> {
2103 pub fn normalize (quaternion : Quaternion <S>) -> Self where S : std::fmt::Debug {
2107 assert_ne!(quaternion, Quaternion::zero());
2108 Versor (normalize_quaternion (quaternion))
2109 }
2110 pub fn noisy (unit_quaternion : Quaternion <S>) -> Self where
2114 S : num::real::Real + std::fmt::Debug
2115 {
2116 assert_eq!(unit_quaternion, normalize_quaternion (unit_quaternion));
2117 Versor (unit_quaternion)
2118 }
2119 pub fn noisy_approx (unit_quaternion : Quaternion <S>) -> Self where
2123 S : num::real::Real + approx::RelativeEq <Epsilon=S>
2124 {
2125 assert!(unit_quaternion.into_vec4().is_normalized());
2126 Versor (unit_quaternion)
2127 }
2128 pub fn unchecked (unit_quaternion : Quaternion <S>) -> Self where S : std::fmt::Debug {
2132 debug_assert_eq!(unit_quaternion, normalize_quaternion (unit_quaternion));
2133 Versor (unit_quaternion)
2134 }
2135 pub fn unchecked_approx (unit_quaternion : Quaternion <S>) -> Self where
2139 S : num::real::Real + approx::RelativeEq <Epsilon=S>
2140 {
2141 debug_assert!(unit_quaternion.into_vec4().is_normalized());
2142 Versor (unit_quaternion)
2143 }
2144 pub fn from_scaled_axis (scaled_axis : Vector3 <S>) -> Self where
2147 S : std::fmt::Debug + num::Float
2148 {
2149 if scaled_axis == Vector3::zero() {
2150 let versor = Quaternion::rotation_3d (S::zero(), scaled_axis);
2151 debug_assert_eq!(versor.magnitude(), S::one());
2152 Versor (versor)
2153 } else {
2154 let angle = scaled_axis.magnitude();
2155 debug_assert!(S::zero() < angle);
2156 let axis = scaled_axis / angle;
2157 Versor (Quaternion::rotation_3d (angle, axis))
2158 }
2159 }
2160}
2161impl <S> Default for Versor <S> where S : num::One + num::Zero {
2162 fn default() -> Self {
2163 Versor (Quaternion::default())
2164 }
2165}
2166impl <S> std::ops::Mul <Vector3 <S>> for Versor <S> where S : Real + num::Float {
2167 type Output = Vector3 <S>;
2168 fn mul (self, rhs : Vector3 <S>) -> Self::Output {
2169 self.0 * rhs
2170 }
2171}
2172impl <S> From <Rotation3 <S>> for Versor <S> where
2173 S : Real + MaybeSerDes + num::real::Real + approx::RelativeEq <Epsilon=S>
2174{
2175 fn from (rot : Rotation3 <S>) -> Self {
2176 rot.versor()
2177 }
2178}
2179impl <S> std::ops::Deref for Versor <S> {
2180 type Target = Quaternion <S>;
2181 fn deref (&self) -> &Quaternion <S> {
2182 &self.0
2183 }
2184}
2185impl <S, V, W, M> LinearIso <S, V, W, M> where
2191 M : LinearMap <S, V, W> + Copy,
2192 V : Module <S>,
2193 W : Module <S>,
2194 S : Ring
2195{
2196 pub fn mat (self) -> M {
2197 *self
2198 }
2199 pub fn is_invertible (linear_map : M) -> bool {
2201 linear_map.determinant() != S::zero()
2202 }
2203 pub fn is_invertible_approx (linear_map : M, epsilon : Option <S>) -> bool where
2205 S : approx::AbsDiffEq <Epsilon=S>
2206 {
2207 let epsilon = epsilon.unwrap_or_else (||{
2208 let four = S::one() + S::one() + S::one() + S::one();
2209 S::default_epsilon() * four
2210 });
2211 approx::abs_diff_ne!(linear_map.determinant(), S::zero(), epsilon=epsilon)
2212 }
2213 pub fn new (linear_map : M) -> Option <Self> {
2215 if Self::is_invertible (linear_map) {
2216 Some (LinearIso (linear_map, PhantomData))
2217 } else {
2218 None
2219 }
2220 }
2221 pub fn new_approx (linear_map : M, epsilon : Option <S>) -> Option <Self> where
2223 S : approx::RelativeEq <Epsilon=S>
2224 {
2225 if Self::is_invertible_approx (linear_map, epsilon) {
2226 Some (LinearIso (linear_map, PhantomData))
2227 } else {
2228 None
2229 }
2230 }
2231}
2232impl <S, V, W, M> std::ops::Deref for LinearIso <S, V, W, M> where
2233 M : LinearMap <S, V, W>,
2234 V : Module <S>,
2235 W : Module <S>,
2236 S : Ring
2237{
2238 type Target = M;
2239 fn deref (&self) -> &Self::Target {
2240 &self.0
2241 }
2242}
2243impl <S, V> num::One for LinearIso <S, V, V, V::LinearEndo> where
2244 V : Module <S>,
2245 S : Ring
2246{
2247 fn one () -> Self {
2248 LinearIso (V::LinearEndo::one(), PhantomData)
2249 }
2250}
2251impl <S, V, W, M> std::ops::Mul <V> for LinearIso <S, V, W, M> where
2252 M : LinearMap <S, V, W>,
2253 V : Module <S>,
2254 W : Module <S>,
2255 S : Ring
2256{
2257 type Output = W;
2258 fn mul (self, rhs : V) -> Self::Output {
2259 self.0 * rhs
2260 }
2261}
2262impl <S, V> std::ops::Mul for LinearIso <S, V, V, V::LinearEndo> where
2263 V : Module <S>,
2264 S : Ring
2265{
2266 type Output = Self;
2267 fn mul (self, rhs : Self) -> Self::Output {
2268 LinearIso (self.0 * rhs.0, PhantomData)
2269 }
2270}
2271impl <S, V> std::ops::MulAssign for LinearIso <S, V, V, V::LinearEndo> where
2272 V : Module <S>,
2273 S : Ring
2274{
2275 fn mul_assign (&mut self, rhs : Self) {
2276 self.0 *= rhs.0
2277 }
2278}
2279
2280impl <S, V> LinearAuto <S, V> where
2284 V : Module <S>,
2285 V::LinearEndo : MaybeSerDes,
2286 S : Ring
2287{
2288 pub fn mat (self) -> V::LinearEndo {
2289 **self
2290 }
2291 pub fn is_orthonormal (&self) -> bool {
2296 use num::One;
2297 let determinant = self.0.0.determinant();
2298 self.0.0 * self.0.0.transpose() == V::LinearEndo::one() &&
2299 (determinant == S::one() || determinant == -S::one())
2300 }
2301 pub fn is_orthonormal_approx (&self) -> bool where
2307 S : approx::RelativeEq <Epsilon=S>,
2308 V::LinearEndo : approx::RelativeEq <Epsilon=S>
2309 {
2310 use num::One;
2311 let four = S::one() + S::one() + S::one() + S::one();
2312 let epsilon = S::default_epsilon() * four;
2313 let max_relative = S::default_max_relative() * four;
2314 let determinant = self.0.0.determinant();
2315 approx::relative_eq!(self.0.0 * self.0.0.transpose(), V::LinearEndo::one(),
2316 max_relative=max_relative, epsilon=epsilon) &&
2317 ( approx::relative_eq!(determinant, S::one(), max_relative=max_relative) ||
2318 approx::relative_eq!(determinant, -S::one(), max_relative=max_relative) )
2319 }
2320 pub fn is_rotation (&self) -> bool {
2324 use num::One;
2325 let determinant = self.0.0.determinant();
2326 self.0.0 * self.0.0.transpose() == V::LinearEndo::one() &&
2327 determinant == S::one()
2328 }
2329 pub fn is_rotation_approx (&self) -> bool where
2334 S : approx::RelativeEq <Epsilon=S>,
2335 V::LinearEndo : approx::RelativeEq <Epsilon=S>
2336 {
2337 use num::One;
2338 let four = S::one() + S::one() + S::one() + S::one();
2339 let epsilon = S::default_epsilon() * four;
2340 let max_relative = S::default_max_relative() * four;
2341 let determinant = self.0.0.determinant();
2342 approx::relative_eq!(self.0.0 * self.0.0.transpose(), V::LinearEndo::one(),
2343 max_relative=max_relative, epsilon=epsilon) &&
2344 approx::relative_eq!(determinant, S::one(), max_relative=max_relative)
2345 }
2346}
2347impl <S, V> std::ops::Mul <V> for LinearAuto <S, V> where
2348 V : Module <S>,
2349 V::LinearEndo : MaybeSerDes,
2350 S : Ring
2351{
2352 type Output = V;
2353 fn mul (self, rhs : V) -> Self::Output {
2354 self.0 * rhs
2355 }
2356}
2357impl <S, V> std::ops::Mul for LinearAuto <S, V> where
2358 V : Module <S>,
2359 V::LinearEndo : MaybeSerDes,
2360 S : Ring
2361{
2362 type Output = Self;
2363 fn mul (self, rhs : Self) -> Self::Output {
2364 LinearAuto (self.0 * rhs.0)
2365 }
2366}
2367impl <S, V> std::ops::MulAssign <Self> for LinearAuto <S, V> where
2368 V : Module <S>,
2369 V::LinearEndo : MaybeSerDes,
2370 S : Ring
2371{
2372 fn mul_assign (&mut self, rhs : Self) {
2373 self.0 *= rhs.0
2374 }
2375}
2376impl <S, V> num::One for LinearAuto <S, V> where
2377 V : Module <S>,
2378 V::LinearEndo : MaybeSerDes,
2379 S : Ring
2380{
2381 fn one() -> Self {
2382 LinearAuto (LinearIso::one())
2383 }
2384}
2385
2386impl <S, A, B, M> AffineMap <S, A, B, M> where
2390 A : AffineSpace <S>,
2391 B : AffineSpace <S>,
2392 M : LinearMap <S, A::Translation, B::Translation>,
2393 S : Field
2394{
2395 pub const fn new (linear_map : M, translation : B::Translation) -> Self {
2396 AffineMap { linear_map, translation, _phantom: PhantomData }
2397 }
2398 pub fn map (self, point : A) -> B {
2399 B::from_vector (self.linear_map * point.to_vector() + self.translation)
2400 }
2401 pub fn transform (self, translation : A::Translation) -> B::Translation {
2402 self.linear_map * translation
2403 }
2404}
2405
2406impl <S, A, B, M> Affinity <S, A, B, M> where
2410 M : LinearMap <S, A::Translation, B::Translation>,
2411 A : AffineSpace <S>,
2412 B : AffineSpace <S>,
2413 S : Field
2414{
2415 pub const fn new (
2416 linear_iso : LinearIso <S, A::Translation, B::Translation, M>,
2417 translation : B::Translation
2418 ) -> Self {
2419 Affinity { linear_iso, translation }
2420 }
2421 pub fn mat (self) -> M {
2422 *self.linear_iso
2423 }
2424 pub fn map (self, point : A) -> B {
2425 B::from_vector (self.linear_iso * point.to_vector() + self.translation)
2426 }
2427 pub fn transform (self, translation : A::Translation) -> B::Translation {
2428 self.linear_iso * translation
2429 }
2430}
2431
2432impl <S, P, Q, M> Projectivity <S, P, Q, M> where
2436 M : LinearMap <S, P::Translation, Q::Translation>,
2437 P : ProjectiveSpace <S>,
2438 Q : ProjectiveSpace <S>,
2439 S : Field
2440{
2441 pub const fn new (linear_iso : LinearIso <S, P::Translation, Q::Translation, M>)
2442 -> Self
2443 {
2444 Projectivity (linear_iso)
2445 }
2446 pub fn mat (self) -> M {
2447 **self
2448 }
2449}
2450impl <S, P, Q, M> std::ops::Deref for Projectivity <S, P, Q, M> where
2451 M : LinearMap <S, P::Translation, Q::Translation>,
2452 P : ProjectiveSpace <S>,
2453 Q : ProjectiveSpace <S>,
2454 S : Field
2455{
2456 type Target = LinearIso <S, P::Translation, Q::Translation, M>;
2457 fn deref (&self) -> &Self::Target {
2458 &self.0
2459 }
2460}
2461impl <S, P, Q, M> std::ops::Mul <P> for Projectivity <S, P, Q, M> where
2462 M : LinearMap <S, P::Translation, Q::Translation>,
2463 P : ProjectiveSpace <S>,
2464 Q : ProjectiveSpace <S>,
2465 S : Field
2466{
2467 type Output = Q;
2468 fn mul (self, rhs : P) -> Q {
2469 Q::from_vector (self.0 * rhs.to_vector())
2470 }
2471}
2472
2473pub macro point {
2474 ($x:expr, $y:expr) => {
2475 $crate::point2 ($x, $y)
2476 },
2477 ($x:expr, $y:expr, $z:expr) => {
2478 $crate::point3 ($x, $y, $z)
2479 },
2480 ($x:expr, $y:expr, $z:expr, $w:expr) => {
2481 $crate::point4 ($x, $y, $z, $w)
2482 }
2483}
2484
2485pub macro vector {
2486 ($x:expr, $y:expr) => {
2487 $crate::vector2 ($x, $y)
2488 },
2489 ($x:expr, $y:expr, $z:expr) => {
2490 $crate::vector3 ($x, $y, $z)
2491 },
2492 ($x:expr, $y:expr, $z:expr, $w:expr) => {
2493 $crate::vector4 ($x, $y, $z, $w)
2494 }
2495}
2496
2497pub macro matrix {
2498 ($v00:expr, $v01:expr; $v10:expr, $v11:expr$(;)?) => {
2499 $crate::Matrix2::new ($v00, $v01, $v10, $v11)
2500 },
2501 ( $v00:expr, $v01:expr, $v02:expr;
2502 $v10:expr, $v11:expr, $v12:expr;
2503 $v20:expr, $v21:expr, $v22:expr$(;)?
2504 ) => {
2505 $crate::Matrix3::new ($v00, $v01, $v02, $v10, $v11, $v12, $v20, $v21, $v22)
2506 },
2507 ( $v00:expr, $v01:expr, $v02:expr, $v03:expr;
2508 $v10:expr, $v11:expr, $v12:expr, $v13:expr;
2509 $v20:expr, $v21:expr, $v22:expr, $v23:expr;
2510 $v30:expr, $v31:expr, $v32:expr, $v33:expr$(;)?
2511 ) => {
2512 $crate::Matrix4::new (
2513 $v00, $v01, $v02, $v03,
2514 $v10, $v11, $v12, $v13,
2515 $v20, $v21, $v22, $v23,
2516 $v30, $v31, $v32, $v33)
2517 }
2518}
2519
2520macro_rules! impl_angle {
2521 ( $angle:ident, $docname:expr ) => {
2522 #[doc = $docname]
2523 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
2524 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, PartialOrd)]
2526 pub struct $angle <S> (pub S);
2527 impl_numcast_primitive_map!($angle);
2528 impl <S : Ring> std::iter::Sum for $angle <S> {
2529 fn sum <I> (iter : I) -> Self where I : Iterator <Item = Self> {
2530 use num::Zero;
2531 iter.fold ($angle::zero(), |acc, item| acc + item)
2532 }
2533 }
2534 impl <S : Ring> std::ops::Neg for $angle <S> {
2535 type Output = Self;
2536 fn neg (self) -> Self {
2537 $angle (-self.0)
2538 }
2539 }
2540 impl <S : Ring> std::ops::Add for $angle <S> {
2541 type Output = Self;
2542 fn add (self, other : Self) -> Self::Output {
2543 $angle (self.0 + other.0)
2544 }
2545 }
2546 impl <S : Ring> std::ops::AddAssign for $angle <S> {
2547 fn add_assign (&mut self, other : Self) {
2548 self.0 += other.0
2549 }
2550 }
2551 impl <S : Ring> std::ops::Sub for $angle <S> {
2552 type Output = Self;
2553 fn sub (self, other : Self) -> Self::Output {
2554 $angle (self.0 - other.0)
2555 }
2556 }
2557 impl <S : Ring> std::ops::SubAssign for $angle <S> {
2558 fn sub_assign (&mut self, other : Self) {
2559 self.0 -= other.0
2560 }
2561 }
2562 impl <S : Ring> std::ops::Mul <S> for $angle <S> {
2563 type Output = Self;
2564 fn mul (self, scalar : S) -> Self::Output {
2565 $angle (scalar * self.0)
2566 }
2567 }
2568 impl <S : Ring> std::ops::MulAssign <S> for $angle <S> {
2569 fn mul_assign (&mut self, scalar : S) {
2570 self.0 *= scalar
2571 }
2572 }
2573 impl <S : Field> std::ops::Div for $angle <S> {
2574 type Output = S;
2575 fn div (self, other : Self) -> Self::Output {
2576 self.0 / other.0
2577 }
2578 }
2579 impl <S : Field> std::ops::Div <S> for $angle <S> {
2580 type Output = Self;
2581 fn div (self, scalar : S) -> Self::Output {
2582 $angle (self.0 / scalar)
2583 }
2584 }
2585 impl <S : Field> std::ops::DivAssign <S> for $angle <S> {
2586 fn div_assign (&mut self, scalar : S) {
2587 self.0 /= scalar
2588 }
2589 }
2590 impl <S : OrderedField> std::ops::Rem for $angle <S> {
2591 type Output = Self;
2592 fn rem (self, other : Self) -> Self::Output {
2593 $angle (self.0 % other.0)
2594 }
2595 }
2596 impl <S : Ring> num::Zero for $angle <S> {
2597 fn zero() -> Self {
2598 $angle (S::zero())
2599 }
2600 fn is_zero (&self) -> bool {
2601 self.0.is_zero()
2602 }
2603 }
2604 impl <S : Ring> From <S> for $angle <S> {
2605 fn from (s : S) -> Self {
2606 $angle (s)
2607 }
2608 }
2609 }
2610}
2611
2612macro_rules! impl_angle_wrapped {
2613 ( $angle:ident, $comment:expr ) => {
2614 #[doc = $comment]
2615 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
2616 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, PartialOrd)]
2617 pub struct $angle <S> (Rad <S>);
2618
2619 impl_numcast!($angle);
2620 impl <S : Copy> $angle <S> {
2621 pub const fn angle (&self) -> Rad <S> {
2622 self.0
2623 }
2624 }
2625 impl <S : Real> std::iter::Sum for $angle <S> {
2626 fn sum <I> (iter : I) -> Self where I : Iterator <Item = Self> {
2627 use num::Zero;
2628 iter.fold ($angle::zero(), |acc, item| acc + item)
2629 }
2630 }
2631 impl <S : Real> std::ops::Neg for $angle <S> {
2632 type Output = Self;
2633 fn neg (self) -> Self {
2634 self.map (Rad::neg)
2635 }
2636 }
2637 impl <S : Real> std::ops::Add for $angle <S> {
2638 type Output = Self;
2639 fn add (self, other : Self) -> Self::Output {
2640 self.map (|angle| angle + other.0)
2641 }
2642 }
2643 impl <S : Real> std::ops::AddAssign for $angle <S> {
2644 fn add_assign (&mut self, other : Self) {
2645 *self = *self + other
2646 }
2647 }
2648 impl <S : Real> std::ops::Add <Rad <S>> for $angle <S> {
2649 type Output = Self;
2650 fn add (self, angle : Rad <S>) -> Self::Output {
2651 self.map (|a| a + angle)
2652 }
2653 }
2654 impl <S : Real> std::ops::AddAssign <Rad <S>> for $angle <S> {
2655 fn add_assign (&mut self, angle : Rad <S>) {
2656 *self = *self + angle
2657 }
2658 }
2659 impl <S : Real> std::ops::Sub for $angle <S> {
2660 type Output = Self;
2661 fn sub (self, other : Self) -> Self::Output {
2662 self.map (|angle| angle - other.0)
2663 }
2664 }
2665 impl <S : Real> std::ops::SubAssign for $angle <S> {
2666 fn sub_assign (&mut self, other : Self) {
2667 *self = *self - other
2668 }
2669 }
2670 impl <S : Real> std::ops::Sub <Rad <S>> for $angle <S> {
2671 type Output = Self;
2672 fn sub (self, angle : Rad <S>) -> Self::Output {
2673 self.map (|a| a - angle)
2674 }
2675 }
2676 impl <S : Real> std::ops::SubAssign <Rad <S>> for $angle <S> {
2677 fn sub_assign (&mut self, angle : Rad <S>) {
2678 *self = *self - angle
2679 }
2680 }
2681 impl <S : Real> std::ops::Mul <S> for $angle <S> {
2682 type Output = Self;
2683 fn mul (self, scalar : S) -> Self::Output {
2684 self.map (|angle| angle * scalar)
2685 }
2686 }
2687 impl <S : Real> std::ops::MulAssign <S> for $angle <S> {
2688 fn mul_assign (&mut self, scalar : S) {
2689 *self = *self * scalar
2690 }
2691 }
2692 impl <S : Real> std::ops::Div for $angle <S> {
2693 type Output = S;
2694 fn div (self, other : Self) -> Self::Output {
2695 self.0 / other.0
2696 }
2697 }
2698 impl <S : Real> std::ops::Div <S> for $angle <S> {
2699 type Output = Self;
2700 fn div (self, scalar : S) -> Self::Output {
2701 self.map (|angle| angle / scalar)
2702 }
2703 }
2704 impl <S : Real> std::ops::DivAssign <S> for $angle <S> {
2705 fn div_assign (&mut self, scalar : S) {
2706 *self = *self / scalar
2707 }
2708 }
2709 impl <S : Real> std::ops::Rem for $angle <S> {
2710 type Output = Self;
2711 fn rem (self, other : Self) -> Self::Output {
2712 self.map (|angle| angle % other.0)
2713 }
2714 }
2715 impl <S : Real> num::Zero for $angle <S> {
2716 fn zero() -> Self {
2717 $angle (Rad::zero())
2718 }
2719 fn is_zero (&self) -> bool {
2720 self.0.is_zero()
2721 }
2722 }
2723 }
2724}
2725
2726macro_rules! impl_dimension {
2727 ( $point:ident, $vector:ident, $nonzero:ident, $unit:ident,
2728 $point_fun:ident, $vector_fun:ident, $matrix_fun:ident, $ortho_fun:ident,
2729 [$($component:ident),+],
2730 [$(($axis_method:ident, $unit_method:ident)),+], [$($patch:ident)?],
2731 [$($projective:ident)?],
2732 $matrix:ident, [$($submatrix:ident)?], $ndims:expr, $dimension:expr
2733 ) => {
2734 #[doc = $dimension]
2735 #[doc = "position"]
2736 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Display, From, Neg)]
2737 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
2738 #[display("{}", _0)]
2739 #[repr(C)]
2740 pub struct $point <S> (pub $vector <S>);
2741
2742 #[doc = $dimension]
2743 #[doc = "non-zero vector"]
2744 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
2745 #[derive(Clone, Copy, Debug, Eq, PartialEq, Display)]
2746 #[display("{}", _0)]
2747 #[repr(C)]
2748 pub struct $nonzero <S> ($vector <S>);
2749
2750 #[doc = $dimension]
2751 #[doc = "unit vector"]
2752 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
2753 #[derive(Clone, Copy, Debug, Eq, PartialEq, Display)]
2754 #[display("{}", _0)]
2755 #[repr(C)]
2756 pub struct $unit <S> ($vector <S>);
2757
2758 #[doc = "Construct a"]
2762 #[doc = $dimension]
2763 #[doc = "point"]
2764 pub const fn $point_fun <S> ($($component : S),+) -> $point <S> {
2765 $point::new ($($component),+)
2766 }
2767 impl_numcast!($point);
2768 impl <S> $point <S> {
2769 pub const fn new ($($component : S),+) -> Self {
2770 $point ($vector::new ($($component),+))
2771 }
2772 $(
2773 pub const fn $component (&self) -> S where S : Copy {
2774 self.0.$component
2775 }
2776 )+
2777 pub fn distance (self, other : $point <S>) -> NonNegative <S> where
2778 S : OrderedField + Sqrt
2779 {
2780 MetricSpace::distance (self.0, other.0)
2781 }
2782 pub fn distance_squared (self, other : $point <S>) -> NonNegative <S> where
2783 S : OrderedField
2784 {
2785 MetricSpace::distance_squared (self.0, other.0)
2786 }
2787 }
2788 $(
2790 impl <S : Field> ProjectiveSpace <S> for $projective <S> {
2791 type Patch = $point <S>;
2792 }
2793 )?
2794 impl <S : Field> AffineSpace <S> for $point <S> {
2795 type Translation = $vector <S>;
2796 }
2797 impl <S : Ring> Point <$vector <S>> for $point <S> {
2798 fn to_vector (self) -> $vector <S> {
2799 self.0
2800 }
2801 fn from_vector (vector : $vector <S>) -> Self {
2802 $point (vector)
2803 }
2804 }
2805 impl <S> From <[S; $ndims]> for $point <S> {
2806 fn from (array : [S; $ndims]) -> Self {
2807 $point (array.into())
2808 }
2809 }
2810 $(
2811 impl <S> From <($patch <S>, S)> for $point <S> {
2812 fn from ((patch, scale) : ($patch <S>, S)) -> Self {
2813 $point ((patch.0, scale).into())
2814 }
2815 }
2816 )?
2817 impl <S> std::cmp::PartialOrd for $point <S> where S : PartialOrd {
2818 fn partial_cmp (&self, other : &Self) -> Option <std::cmp::Ordering> {
2819 self.0.as_slice().partial_cmp (&other.0.as_slice())
2820 }
2821 }
2822 impl <S> std::ops::Add <$vector <S>> for $point <S> where S : AdditiveGroup {
2823 type Output = Self;
2824 fn add (self, displacement : $vector <S>) -> Self::Output {
2825 $point (self.0 + displacement)
2826 }
2827 }
2828 impl <S> std::ops::Add <&$vector <S>> for $point <S> where S : AdditiveGroup + Copy {
2829 type Output = Self;
2830 fn add (self, displacement : &$vector <S>) -> Self::Output {
2831 $point (self.0 + *displacement)
2832 }
2833 }
2834 impl <S> std::ops::Add <$vector <S>> for &$point <S> where S : AdditiveGroup + Copy {
2835 type Output = $point <S>;
2836 fn add (self, displacement : $vector <S>) -> Self::Output {
2837 $point (self.0 + displacement)
2838 }
2839 }
2840 impl <S> std::ops::Add <&$vector <S>> for &$point <S> where
2841 S : AdditiveGroup + Copy
2842 {
2843 type Output = $point <S>;
2844 fn add (self, displacement : &$vector <S>) -> Self::Output {
2845 $point (self.0 + *displacement)
2846 }
2847 }
2848 impl <S> std::ops::AddAssign <$vector <S>> for $point <S> where S : AdditiveGroup {
2849 fn add_assign (&mut self, displacement : $vector <S>) {
2850 self.0 += displacement
2851 }
2852 }
2853 impl <S> std::ops::AddAssign <&$vector <S>> for $point <S> where
2854 S : AdditiveGroup + Copy
2855 {
2856 fn add_assign (&mut self, displacement : &$vector <S>) {
2857 self.0 += *displacement
2858 }
2859 }
2860 impl <S> std::ops::Sub <$vector <S>> for $point <S> where S : AdditiveGroup {
2861 type Output = Self;
2862 fn sub (self, displacement : $vector <S>) -> Self::Output {
2863 $point (self.0 - displacement)
2864 }
2865 }
2866 impl <S> std::ops::Sub <&$vector <S>> for $point <S> where S : AdditiveGroup + Copy {
2867 type Output = Self;
2868 fn sub (self, displacement : &$vector <S>) -> Self::Output {
2869 $point (self.0 - *displacement)
2870 }
2871 }
2872 impl <S> std::ops::Sub <$point <S>> for $point <S> where S : AdditiveGroup {
2873 type Output = $vector <S>;
2874 fn sub (self, other : Self) -> Self::Output {
2875 self.0 - other.0
2876 }
2877 }
2878 impl <S> std::ops::Sub <&$point <S>> for $point <S> where S : AdditiveGroup + Copy {
2879 type Output = $vector <S>;
2880 fn sub (self, other : &Self) -> Self::Output {
2881 self.0 - other.0
2882 }
2883 }
2884 impl <S> std::ops::Sub <$vector <S>> for &$point <S> where S : AdditiveGroup + Copy {
2885 type Output = $point <S>;
2886 fn sub (self, displacement : $vector <S>) -> Self::Output {
2887 $point (self.0 - displacement)
2888 }
2889 }
2890 impl <S> std::ops::Sub <&$vector <S>> for &$point <S> where
2891 S : AdditiveGroup + Copy
2892 {
2893 type Output = $point <S>;
2894 fn sub (self, displacement : &$vector <S>) -> Self::Output {
2895 $point (self.0 - *displacement)
2896 }
2897 }
2898 impl <S> std::ops::Sub <$point <S>> for &$point <S> where S : AdditiveGroup + Copy {
2899 type Output = $vector <S>;
2900 fn sub (self, other : $point <S>) -> Self::Output {
2901 self.0 - other.0
2902 }
2903 }
2904 impl <S> std::ops::Sub <&$point <S>> for &$point <S> where S : AdditiveGroup + Copy {
2905 type Output = $vector <S>;
2906 fn sub (self, other : &$point <S>) -> Self::Output {
2907 self.0 - other.0
2908 }
2909 }
2910 impl <S> std::ops::SubAssign <$vector <S>> for $point <S> where
2911 S : AdditiveGroup
2912 {
2913 fn sub_assign (&mut self, displacement : $vector <S>) {
2914 self.0 -= displacement
2915 }
2916 }
2917 impl <S> std::ops::SubAssign <&$vector <S>> for $point <S> where
2918 S : AdditiveGroup + Copy
2919 {
2920 fn sub_assign (&mut self, displacement : &$vector <S>) {
2921 self.0 -= *displacement
2922 }
2923 }
2924 impl <S> approx::AbsDiffEq for $point <S> where
2925 S : approx::AbsDiffEq,
2926 S::Epsilon : Copy
2927 {
2928 type Epsilon = S::Epsilon;
2929 fn default_epsilon() -> Self::Epsilon {
2930 S::default_epsilon()
2931 }
2932 #[inline]
2933 fn abs_diff_eq (&self, other : &Self, epsilon : Self::Epsilon) -> bool {
2934 self.0.abs_diff_eq (&other.0, epsilon)
2935 }
2936 }
2937 impl <S> approx::RelativeEq for $point <S> where
2938 S : approx::RelativeEq,
2939 S::Epsilon : Copy
2940 {
2941 fn default_max_relative() -> Self::Epsilon {
2942 S::default_max_relative()
2943 }
2944 #[inline]
2945 fn relative_eq (&self,
2946 other : &Self, epsilon : Self::Epsilon, max_relative : Self::Epsilon
2947 ) -> bool {
2948 self.0.relative_eq (&other.0, epsilon, max_relative)
2949 }
2950 }
2951 impl <S> approx::UlpsEq for $point <S> where
2952 S : approx::UlpsEq,
2953 S::Epsilon : Copy
2954 {
2955 fn default_max_ulps() -> u32 {
2956 S::default_max_ulps()
2957 }
2958 #[inline]
2959 fn ulps_eq (&self, other : &Self, epsilon : Self::Epsilon, max_ulps : u32)
2960 -> bool
2961 {
2962 self.0.ulps_eq (&other.0, epsilon, max_ulps)
2963 }
2964 }
2965 #[doc = "Construct a"]
2969 #[doc = $dimension]
2970 #[doc = "vector"]
2971 pub const fn $vector_fun <S> ($($component : S),+) -> $vector <S> {
2972 $vector::new ($($component),+)
2973 }
2974 impl <S> NormedVectorSpace <S> for $vector <S> where S : OrderedField {
2975 type Unit = $unit <S>;
2976 fn norm_squared (self) -> NonNegative <S> {
2977 self.self_dot()
2978 }
2979 fn norm_max (self) -> NonNegative <S> where S : SignedExt {
2980 NonNegative::unchecked (self.map (|x| x.abs()).reduce_partial_max())
2981 }
2982 fn normalize (self) -> Self::Unit where S : Sqrt {
2983 $unit (self / *self.norm())
2984 }
2985 }
2986 impl <S> InnerProductSpace <S> for $vector <S> where S : Field {
2987 fn outer_product (self, rhs : Self) -> $matrix <S> {
2988 let mut cols : $vector <$vector <S>> = [$vector::zero(); $ndims].into();
2989 for col in 0..$ndims {
2990 for row in 0..$ndims {
2991 cols[col][row] = self[row] * rhs[col];
2992 }
2993 }
2994 $matrix { cols }
2995 }
2996 fn orthogonal (self) -> Self where S : approx::AbsDiffEq <Epsilon = S> {
2997 $ortho_fun (self)
2998 }
2999 }
3000 impl <S : Ring> Dot <S> for $vector <S> {
3001 fn dot (self, other : Self) -> S {
3002 self.dot (other)
3003 }
3004 }
3005 impl <S : Field> VectorSpace <S> for $vector <S> {
3006 type NonZero = $nonzero <S>;
3007 fn map <F> (self, f : F) -> Self where F : FnMut (S) -> S {
3008 self.map (f)
3009 }
3010 }
3011 impl <S> Module <S> for $vector <S> where S : Ring + num::MulAdd {
3012 type LinearEndo = $matrix <S>;
3013 }
3014 impl <S> GroupAction <$point <S>> for $vector <S> where S : AdditiveGroup {
3015 fn action (self, point : $point <S>) -> $point <S> {
3016 point + self
3017 }
3018 }
3019 impl <S : AdditiveGroup> Group for $vector <S> {
3020 fn identity() -> Self {
3021 Self::zero()
3022 }
3023 fn operation (a : Self, b : Self) -> Self {
3024 a + b
3025 }
3026 }
3027 impl <S> std::ops::Mul <LinearAuto <S, Self>> for $vector <S> where
3028 S : Ring + MaybeSerDes
3029 {
3030 type Output = Self;
3031 fn mul (self, rhs : LinearAuto <S, Self>) -> Self::Output {
3032 self * rhs.0
3033 }
3034 }
3035 impl <S> std::ops::Mul <LinearIso <S, Self, Self, $matrix <S>>> for $vector <S> where
3036 S : Ring + MaybeSerDes
3037 {
3038 type Output = Self;
3039 fn mul (self, rhs : LinearIso <S, Self, Self, $matrix <S>>) -> Self::Output {
3040 self * rhs.0
3041 }
3042 }
3043 impl <S> num::Inv for LinearAuto <S, $vector <S>> where
3044 S : Ring + num::real::Real + MaybeSerDes
3045 {
3046 type Output = Self;
3047 fn inv (self) -> Self::Output {
3048 LinearAuto (self.0.inv())
3049 }
3050 }
3051 impl <S> std::ops::Div for LinearAuto <S, $vector <S>> where
3052 S : Ring + num::Float + MaybeSerDes
3053 {
3054 type Output = Self;
3055 fn div (self, rhs : Self) -> Self::Output {
3056 LinearAuto (self.0 / rhs.0)
3057 }
3058 }
3059 impl <S> std::ops::DivAssign <Self> for LinearAuto <S, $vector <S>> where
3060 S : Ring + num::Float + MaybeSerDes
3061 {
3062 fn div_assign (&mut self, rhs : Self) {
3063 self.0 /= rhs.0
3064 }
3065 }
3066 impl <S> From <$unit <S>> for $vector <S> where S : Copy {
3067 fn from (unit : $unit <S>) -> Self {
3068 *unit
3069 }
3070 }
3071 #[doc = "Construct a"]
3075 #[doc = $dimension]
3076 #[doc = "matrix"]
3077 pub const fn $matrix_fun <S> ($($component : $vector <S>),+) -> $matrix <S> {
3078 $matrix {
3079 cols: $vector_fun ($($component),+)
3080 }
3081 }
3082 impl <S, V, W> num::Inv for LinearIso <S, V, W, $matrix <S>> where
3083 V : Module <S>,
3084 W : Module <S>,
3085 S : Ring + num::real::Real
3086 {
3087 type Output = LinearIso <S, W, V, $matrix <S>>;
3088 fn inv (self) -> Self::Output {
3089 let mat4 = Matrix4::from (self.0);
3091 LinearIso (mat4.inverted().into(), PhantomData::default())
3092 }
3093 }
3094 impl <S, V> std::ops::Div for LinearIso <S, V, V, $matrix <S>> where
3095 V : Module <S, LinearEndo=$matrix <S>>,
3096 S : Ring + num::real::Real
3097 {
3098 type Output = Self;
3099 #[expect(clippy::suspicious_arithmetic_impl)]
3100 fn div (self, rhs : Self) -> Self::Output {
3101 use num::Inv;
3102 self * rhs.inv()
3103 }
3104 }
3105 impl <S, V> std::ops::DivAssign for LinearIso <S, V, V, $matrix <S>> where
3106 V : Module <S, LinearEndo=$matrix <S>>,
3107 S : Ring + num::real::Real
3108 {
3109 #[expect(clippy::suspicious_op_assign_impl)]
3110 fn div_assign (&mut self, rhs : Self) {
3111 use num::Inv;
3112 *self *= rhs.inv()
3113 }
3114 }
3115 $(
3116 impl <S : Copy> Matrix <S> for $matrix <S> {
3117 type Rows = $vector <$vector <S>>;
3118 type Submatrix = $submatrix <S>;
3119 fn rows (self) -> $vector <$vector <S>> {
3120 self.into_row_arrays().map ($vector::from).into()
3121 }
3122 fn submatrix (self, i : usize, j : usize) -> $submatrix <S> {
3123 let a : [S; ($ndims-1) * ($ndims-1)] = std::array::from_fn (|index|{
3124 let i = (i + 1 + index / ($ndims-1)) % $ndims;
3125 let j = (j + 1 + index % ($ndims-1)) % $ndims;
3126 self.cols[i][j]
3127 });
3128 $submatrix::from_col_array (a)
3129 }
3130 fn fill_zeros (submatrix : $submatrix <S>) -> Self where S : num::Zero{
3132 let cols = $vector::from (
3133 std::array::from_fn (|i| if i < $ndims-1 {
3134 $vector::from (submatrix.cols[i])
3135 } else {
3136 $vector::zero()
3137 })
3138 );
3139 $matrix { cols }
3140 }
3141 }
3142 )?
3143 impl <S : Ring> LinearMap <S, $vector <S>, $vector <S>> for $matrix <S> {
3144 fn determinant (self) -> S {
3145 self.determinant()
3146 }
3147 fn transpose (self) -> Self {
3148 self.transposed()
3149 }
3150 }
3151 impl_numcast!($nonzero);
3155 impl <S> $nonzero <S> {
3156 pub fn new (vector : $vector <S>) -> Option <Self> where S : Ring {
3166 use num::Zero;
3167 if !vector.is_zero() {
3168 Some ($nonzero (vector))
3169 } else {
3170 None
3171 }
3172 }
3173 pub fn noisy (vector : $vector <S>) -> Self where S : Ring {
3182 use num::Zero;
3183 assert!(!vector.is_zero());
3184 $nonzero (vector)
3185 }
3186 #[inline]
3190 pub fn unchecked (vector : $vector <S>) -> Self where S : Ring + std::fmt::Debug {
3191 debug_assert_ne!(vector, $vector::zero());
3192 $nonzero (vector)
3193 }
3194 #[must_use]
3206 pub fn map_noisy (self, fun : fn ($vector <S>) -> $vector <S>) -> Self
3207 where S : Ring
3208 {
3209 Self::noisy (fun (self.0))
3210 }
3211 #[must_use]
3212 pub fn map_unchecked (self, fun : fn ($vector <S>) -> $vector <S>) -> Self
3213 where S : Ring + std::fmt::Debug
3214 {
3215 Self::unchecked (fun (self.0))
3216 }
3217 }
3218 impl <S> std::ops::Deref for $nonzero <S> {
3219 type Target = $vector <S>;
3220 fn deref (&self) -> &$vector <S> {
3221 &self.0
3222 }
3223 }
3224 impl <S : Ring> std::ops::Neg for $nonzero <S> {
3225 type Output = Self;
3226 fn neg (self) -> Self {
3227 $nonzero (-self.0)
3228 }
3229 }
3230 impl <S> From <$unit <S>> for $nonzero <S> where S : Ring + std::fmt::Debug {
3231 fn from (unit : $unit <S>) -> Self {
3232 $nonzero::unchecked (*unit)
3233 }
3234 }
3235
3236 impl_numcast!($unit);
3240 impl <S> $unit <S> {
3241 $(
3247 #[inline]
3248 pub fn $axis_method() -> Self where S : num::One + num::Zero {
3249 $unit ($vector::$unit_method())
3250 }
3251 )+
3252 pub fn new (vector : $vector <S>) -> Option <Self> where S : OrderedField + Sqrt {
3256 if vector == *vector.normalize() {
3257 Some ($unit (vector))
3258 } else {
3259 None
3260 }
3261 }
3262 pub fn new_approx (vector : $vector <S>) -> Option <Self> where
3269 S : num::real::Real + approx::RelativeEq <Epsilon=S>
3270 {
3271 if vector.is_normalized() {
3272 Some ($unit (vector))
3273 } else {
3274 None
3275 }
3276 }
3277 pub fn normalize (vector : $vector <S>) -> Self where S : OrderedField + Sqrt {
3298 use num::Zero;
3299 assert!(!vector.is_zero());
3300 vector.normalize()
3301 }
3302 pub fn normalize_approx (vector : $vector <S>) -> Self where
3306 S : num::real::Real + approx::RelativeEq <Epsilon=S>
3307 {
3308 use num::Zero;
3309 assert!(!vector.is_zero());
3310 let vector = if vector.is_normalized() {
3311 vector
3312 } else {
3313 vector.normalized()
3314 };
3315 $unit (vector)
3316 }
3317 pub fn noisy (vector : $vector <S>) -> Self where
3326 S : OrderedField + Sqrt + std::fmt::Debug
3327 {
3328 assert_eq!(vector, *vector.normalize());
3329 $unit (vector)
3330 }
3331 pub fn noisy_approx (vector : $vector <S>) -> Self where
3340 S : num::real::Real + approx::RelativeEq <Epsilon=S>
3341 {
3342 assert!(vector.is_normalized());
3343 $unit (vector)
3344 }
3345 #[inline]
3349 pub fn unchecked (vector : $vector <S>) -> Self where
3350 S : OrderedField + Sqrt + std::fmt::Debug
3351 {
3352 debug_assert_eq!(vector, *vector.normalize());
3353 $unit (vector)
3354 }
3355 #[inline]
3365 pub fn unchecked_approx (vector : $vector <S>) -> Self where
3366 S : num::real::Real + approx::RelativeEq <Epsilon=S>
3367 {
3368 debug_assert!(vector.is_normalized());
3369 $unit (vector)
3370 }
3371 pub fn random_unit <R : rand::RngExt> (rng : &mut R) -> Self where
3373 S : OrderedField + Sqrt + rand::distr::uniform::SampleUniform
3374 {
3375 let vector = $vector {
3376 $($component: rng.random_range (-S::one()..S::one())),+
3377 };
3378 vector.normalize()
3379 }
3380 pub fn invert (mut self) -> Self where S : Ring {
3383 self.0 = -self.0;
3384 self
3385 }
3386 #[must_use]
3398 pub fn map_noisy (self, fun : fn ($vector <S>) -> $vector <S>) -> Self where
3399 S : OrderedField + Sqrt + std::fmt::Debug
3400 {
3401 Self::noisy (fun (self.0))
3402 }
3403 #[must_use]
3415 pub fn map_noisy_approx (self, fun : fn ($vector <S>) -> $vector <S>) -> Self where
3416 S : num::real::Real + approx::RelativeEq <Epsilon=S>
3417 {
3418 Self::noisy_approx (fun (self.0))
3419 }
3420 }
3421 impl <S> std::ops::Deref for $unit <S> {
3422 type Target = $vector <S>;
3423 fn deref (&self) -> &$vector <S> {
3424 &self.0
3425 }
3426 }
3427 impl <S : Ring> std::ops::Neg for $unit <S> {
3428 type Output = Self;
3429 fn neg (self) -> Self {
3430 $unit (-self.0)
3431 }
3432 }
3433 }
3435}
3436
3437macro_rules! impl_numcast {
3438 ($type:ident) => {
3439 impl <S> $type <S> {
3440 #[inline]
3441 pub fn numcast <T> (self) -> Option <$type <T>> where
3442 S : num::NumCast,
3443 T : num::NumCast
3444 {
3445 self.0.numcast().map ($type)
3446 }
3447 }
3448 }
3449}
3450
3451macro_rules! impl_numcast_primitive {
3452 ($type:ident) => {
3453 impl <S> $type <S> {
3454 #[inline]
3455 pub fn numcast <T> (self) -> Option <$type <T>> where
3456 S : num::NumCast,
3457 T : num::NumCast
3458 {
3459 T::from (self.0).map ($type)
3460 }
3461 }
3462 impl <S> num::ToPrimitive for $type <S> where S : num::ToPrimitive {
3463 fn to_isize (&self) -> Option <isize> {
3464 self.0.to_isize()
3465 }
3466 fn to_i8 (&self) -> Option <i8> {
3467 self.0.to_i8()
3468 }
3469 fn to_i16 (&self) -> Option <i16> {
3470 self.0.to_i16()
3471 }
3472 fn to_i32 (&self) -> Option <i32> {
3473 self.0.to_i32()
3474 }
3475 fn to_i64 (&self) -> Option <i64> {
3476 self.0.to_i64()
3477 }
3478 fn to_usize (&self) -> Option <usize> {
3479 self.0.to_usize()
3480 }
3481 fn to_u8 (&self) -> Option <u8> {
3482 self.0.to_u8()
3483 }
3484 fn to_u16 (&self) -> Option <u16> {
3485 self.0.to_u16()
3486 }
3487 fn to_u32 (&self) -> Option <u32> {
3488 self.0.to_u32()
3489 }
3490 fn to_u64 (&self) -> Option <u64> {
3491 self.0.to_u64()
3492 }
3493 }
3494 }
3495}
3496
3497macro_rules! impl_numcast_primitive_option {
3498 ($type:ident$(, $bound:path)*) => {
3499 impl_numcast_primitive!{$type}
3500 impl <S> num::NumCast for $type <S> where
3501 S : num::NumCast $(+ $bound)*
3502 {
3503 fn from <T : num::ToPrimitive> (n : T) -> Option <$type <S>> {
3504 S::from (n).and_then ($type::new)
3505 }
3506 }
3507 }
3508}
3509
3510macro_rules! impl_numcast_primitive_map {
3511 ($type:ident) => {
3512 impl_numcast_primitive!{$type}
3513 impl <S> num::NumCast for $type <S> where S : num::NumCast {
3514 fn from <T : num::ToPrimitive> (n : T) -> Option <$type <S>> {
3515 S::from (n).map ($type)
3516 }
3517 }
3518 }
3519}
3520
3521#[doc(hidden)]
3522#[macro_export]
3523macro_rules! impl_numcast_fields {
3524 ($type:ident, $($field:ident),+) => {
3525 impl <S> $type <S> {
3526 #[inline]
3527 pub fn numcast <T> (self) -> Option <$type <T>> where
3528 S : num::NumCast + PartialOrd + num::Zero,
3529 T : num::NumCast + PartialOrd + num::Zero
3530 {
3531 Some ($type {
3532 $($field: self.$field.numcast()?),+
3533 })
3534 }
3535 }
3536 }
3537}
3538
3539impl_angle!(Deg, "Degrees");
3540impl_angle!(Rad, "Radians");
3541impl_angle!(Turn, "Turns");
3542impl_angle_wrapped!(AngleWrapped, "Unsigned wrapped angle restricted to $[0, 2\\pi)$");
3543impl_angle_wrapped!(AngleWrappedSigned,
3544 "Signed wrapped angle restricted to $(-\\pi, \\pi]$");
3545
3546impl_dimension!(Point2, Vector2, NonZero2, Unit2, point2, vector2, matrix2, ortho_vec2,
3547 [x, y], [(axis_x, unit_x), (axis_y, unit_y)],
3548 [], [Point3], Matrix2, [], 2, "2D");
3549impl_dimension!(Point3, Vector3, NonZero3, Unit3, point3, vector3, matrix3, ortho_vec3,
3550 [x, y, z], [(axis_x, unit_x), (axis_y, unit_y), (axis_z, unit_z)],
3551 [Point2], [Point4], Matrix3, [Matrix2], 3, "3D");
3552impl_dimension!(Point4, Vector4, NonZero4, Unit4, point4, vector4, matrix4, ortho_vec4,
3553 [x, y, z, w], [(axis_x, unit_x), (axis_y, unit_y), (axis_z, unit_z), (axis_w, unit_w)],
3554 [Point3], [], Matrix4, [Matrix3], 4, "4D");
3555
3556impl_numcast_primitive_option!(Positive, PartialOrd, num::Zero);
3557impl_numcast_primitive_option!(NonNegative, PartialOrd, num::Zero);
3558impl_numcast_primitive_option!(NonZero, PartialEq, num::Zero);
3559impl_numcast_primitive_option!(Normalized, PartialOrd, num::One, num::Zero);
3560impl_numcast_primitive_option!(NormalSigned, OrderedRing);
3561impl_numcast_fields!(Angles3, yaw, pitch, roll);
3562
3563#[inline]
3567fn normalize_quaternion <S : Real> (quaternion : Quaternion <S>) -> Quaternion <S> {
3568 Quaternion::from_vec4 (*quaternion.into_vec4().normalize())
3569}
3570
3571#[cfg(test)]
3572mod tests {
3573 extern crate test;
3574
3575 use super::*;
3576 use crate::num;
3577 use approx;
3578 use rand;
3579 use rand_distr;
3580 use rand_xorshift;
3581
3582 #[expect(clippy::cast_possible_truncation)]
3583 static ORTHO_VEC_BENCH_SEED : std::sync::LazyLock <u64> = std::sync::LazyLock::new (
3584 || std::time::SystemTime::UNIX_EPOCH.elapsed().unwrap().as_nanos() as u64);
3585
3586 #[test]
3587 fn defaults() {
3588 use num::Zero;
3589
3590 assert_eq!(Positive::<f32>::default().0, 0.0);
3591 assert_eq!(NonNegative::<f32>::default().0, 0.0);
3592 assert_eq!(Normalized::<f32>::default().0, 0.0);
3593 assert_eq!(NormalSigned::<f32>::default().0, 0.0);
3594 assert_eq!(Deg::<f32>::default().0, 0.0);
3595 assert_eq!(Rad::<f32>::default().0, 0.0);
3596 assert_eq!(Turn::<f32>::default().0, 0.0);
3597 assert_eq!(
3598 Angles3::<f32>::default(),
3599 Angles3::new (AngleWrapped::zero(), AngleWrapped::zero(), AngleWrapped::zero()));
3600 assert_eq!(
3601 Pose3::<f32>::default(),
3602 Pose3 { position: Point3::origin(), angles: Angles3::default() });
3603 assert_eq!(
3604 LinearIso::<f32, Vector3 <f32>, Vector3 <f32>, Matrix3 <f32>>::default().0,
3605 Matrix3::identity());
3606 assert_eq!(LinearAuto::<f32, Vector3 <f32>>::default().0.0, Matrix3::identity());
3607 assert_eq!(Rotation2::<f32>::default().0.0.0, Matrix2::identity());
3608 assert_eq!(Rotation3::<f32>::default().0.0.0, Matrix3::identity());
3609 assert_eq!(Versor::<f32>::default().0, Quaternion::from_xyzw (0.0, 0.0, 0.0, 1.0));
3610 assert_eq!(
3611 AffineMap::<f32, Point3 <f32>, Point3 <f32>, Matrix3 <f32>>::default(),
3612 AffineMap::new (Matrix3::identity(), Vector3::zero()));
3613 assert_eq!(
3614 Affinity::<f32, Point3 <f32>, Point3 <f32>, Matrix3 <f32>>::default(),
3615 Affinity::new (LinearIso::new (Matrix3::identity()).unwrap(), Vector3::zero()));
3616 assert_eq!(
3617 Projectivity::<f32, Point4 <f32>, Point4 <f32>, Matrix4 <f32>>::default().0,
3618 LinearIso::new (Matrix4::identity()).unwrap());
3619 }
3620
3621 #[test]
3622 fn vector_sum() {
3623 let s = [
3624 [0.0, 1.0],
3625 [1.0, 1.0],
3626 [0.5, 0.5]
3627 ].map (Vector2::<f32>::from);
3628 let _sum = s.iter().copied().sum::<Vector2 <f32>>();
3629 }
3630
3631 #[test]
3632 fn vector_outer_product() {
3633 let v1 = vector3 (1.0, 2.0, 3.0);
3634 let v2 = vector3 (2.0, 3.0, 4.0);
3635 assert_eq!(v1.outer_product (v2).into_row_arrays(), [
3636 [2.0, 3.0, 4.0],
3637 [4.0, 6.0, 8.0],
3638 [6.0, 9.0, 12.0]
3639 ]);
3640 }
3641
3642 #[test]
3643 fn rotation3_noisy_approx() {
3644 use rand::{RngExt, SeedableRng};
3645 let mut rng = rand_xorshift::XorShiftRng::seed_from_u64 (0);
3648 let up = Vector3::unit_z();
3649 for _ in 0..1000 {
3650 let forward = vector3 (
3651 rng.random_range (-1000.0f32..1000.0),
3652 rng.random_range (-1000.0f32..1000.0),
3653 0.0
3654 ).normalized();
3655 let right = forward.cross (up);
3656 let mat = Matrix3::from_col_arrays ([
3657 right.into_array(),
3658 forward.into_array(),
3659 up.into_array()
3660 ]);
3661 let _ = Rotation3::noisy_approx (mat);
3662 }
3663 }
3664
3665 #[test]
3666 fn rotation3_intrinsic_angles() {
3667 use std::f32::consts::PI;
3668 use num::Zero;
3669 use rand::{RngExt, SeedableRng};
3670 let rot = Rotation3::from_angles_intrinsic (
3672 Turn (0.25).into(), Rad::zero(), Rad::zero());
3673 approx::assert_relative_eq!(rot.mat(),
3674 Matrix3::from_col_arrays ([
3675 [ 0.0, 1.0, 0.0],
3676 [-1.0, 0.0, 0.0],
3677 [ 0.0, 0.0, 1.0]
3678 ])
3679 );
3680 assert_eq!((Turn (0.25).into(), Rad::zero(), Rad::zero()), rot.intrinsic_angles());
3681 let rot = Rotation3::from_angles_intrinsic (
3682 Turn (0.5).into(), Rad::zero(), Rad::zero());
3683 approx::assert_relative_eq!(rot.mat(),
3684 Matrix3::from_col_arrays ([
3685 [-1.0, 0.0, 0.0],
3686 [ 0.0, -1.0, 0.0],
3687 [ 0.0, 0.0, 1.0]
3688 ])
3689 );
3690 assert_eq!((Turn (0.5).into(), Rad::zero(), Rad::zero()), rot.intrinsic_angles());
3691 let rot = Rotation3::from_angles_intrinsic (
3693 Rad::zero(), Turn (0.25).into(), Rad::zero());
3694 approx::assert_relative_eq!(rot.mat(),
3695 Matrix3::from_col_arrays ([
3696 [1.0, 0.0, 0.0],
3697 [0.0, 0.0, 1.0],
3698 [0.0, -1.0, 0.0]
3699 ])
3700 );
3701 assert_eq!((Rad::zero(), Turn (0.25).into(), Rad::zero()), rot.intrinsic_angles());
3702 let rot = Rotation3::from_angles_intrinsic (
3704 Rad::zero(), Rad::zero(), Turn (0.25).into());
3705 approx::assert_relative_eq!(rot.mat(),
3706 Matrix3::from_col_arrays ([
3707 [0.0, 0.0, -1.0],
3708 [0.0, 1.0, 0.0],
3709 [1.0, 0.0, 0.0]
3710 ])
3711 );
3712 assert_eq!((Rad::zero(), Rad::zero(), Turn (0.25).into()), rot.intrinsic_angles());
3713 let rot = Rotation3::from_angles_intrinsic (
3715 Turn (0.25).into(), Turn (0.25).into(), Rad::zero());
3716 approx::assert_relative_eq!(rot.mat(),
3717 Matrix3::from_col_arrays ([
3718 [0.0, 1.0, 0.0],
3719 [0.0, 0.0, 1.0],
3720 [1.0, 0.0, 0.0]
3721 ])
3722 );
3723 let angles = rot.intrinsic_angles();
3724 approx::assert_relative_eq!(Rad::from (Turn (0.25)).0, angles.0.0);
3725 approx::assert_relative_eq!(Rad::from (Turn (0.25)).0, angles.1.0);
3726 approx::assert_relative_eq!(0.0, angles.2.0);
3727 let rot = Rotation3::from_angles_intrinsic (
3729 Turn (0.25).into(), Turn (0.25).into(), Turn (0.25).into());
3730 approx::assert_relative_eq!(rot.mat(),
3731 Matrix3::from_col_arrays ([
3732 [-1.0, 0.0, 0.0],
3733 [ 0.0, 0.0, 1.0],
3734 [ 0.0, 1.0, 0.0]
3735 ])
3736 );
3737 let angles = rot.intrinsic_angles();
3738 approx::assert_relative_eq!(Rad::from (Turn (0.25)).0, angles.0.0);
3739 approx::assert_relative_eq!(Rad::from (Turn (0.25)).0, angles.1.0);
3740 approx::assert_relative_eq!(Rad::from (Turn (0.25)).0, angles.2.0);
3741
3742 let mut rng = rand_xorshift::XorShiftRng::seed_from_u64 (0);
3745 let mut random_vector = || vector3 (
3746 rng.random_range (-100.0f32..100.0),
3747 rng.random_range (-100.0f32..100.0),
3748 rng.random_range (-100.0f32..100.0));
3749 for _ in 0..1000 {
3750 let rot = Rotation3::orthonormalize (
3751 random_vector(), random_vector(), random_vector()
3752 ).unwrap();
3753 let (yaw, pitch, roll) = rot.intrinsic_angles();
3754 assert!(yaw.0 < PI);
3755 assert!(yaw.0 > -PI);
3756 assert!(pitch.0 < PI);
3757 assert!(pitch.0 > -PI);
3758 assert!(roll.0 < PI);
3759 assert!(roll.0 > -PI);
3760 }
3761 }
3762
3763 #[test]
3764 fn rotation3_into_versor() {
3765 use std::f32::consts::PI;
3766 let rot = Rotation3::from_angle_x (Rad (0.01));
3767 let quat = rot.versor().0;
3768 approx::assert_relative_eq!(rot.mat(), quat.into());
3769 let rot = Rotation3::from_angle_x (Rad (-0.01));
3770 let quat = rot.versor().0;
3771 approx::assert_relative_eq!(rot.mat(), quat.into());
3772
3773 let rot = Rotation3::from_angle_y (Rad (0.01));
3774 let quat = rot.versor().0;
3775 approx::assert_relative_eq!(rot.mat(), quat.into());
3776 let rot = Rotation3::from_angle_y (Rad (-0.01));
3777 let quat = rot.versor().0;
3778 approx::assert_relative_eq!(rot.mat(), quat.into());
3779
3780 let rot = Rotation3::from_angle_z (Rad (0.01));
3781 let quat = rot.versor().0;
3782 approx::assert_relative_eq!(rot.mat(), quat.into());
3783 let rot = Rotation3::from_angle_z (Rad (-0.01));
3784 let quat = rot.versor().0;
3785 approx::assert_relative_eq!(rot.mat(), quat.into());
3786
3787 let rot = Rotation3::from_angle_x (Rad (PI / 2.0));
3788 let quat = rot.versor().0;
3789 approx::assert_relative_eq!(rot.mat(), quat.into());
3790 let rot = Rotation3::from_angle_x (Rad (-PI / 2.0));
3791 let quat = rot.versor().0;
3792 approx::assert_relative_eq!(rot.mat(), quat.into());
3793
3794 let rot = Rotation3::from_angle_y (Rad (PI / 2.0));
3795 let quat = rot.versor().0;
3796 approx::assert_relative_eq!(rot.mat(), quat.into());
3797 let rot = Rotation3::from_angle_y (Rad (-PI / 2.0));
3798 let quat = rot.versor().0;
3799 approx::assert_relative_eq!(rot.mat(), quat.into());
3800
3801 let rot = Rotation3::from_angle_z (Rad (PI / 2.0));
3802 let quat = rot.versor().0;
3803 approx::assert_relative_eq!(rot.mat(), quat.into());
3804 let rot = Rotation3::from_angle_z (Rad (-PI / 2.0));
3805 let quat = rot.versor().0;
3806 approx::assert_relative_eq!(rot.mat(), quat.into());
3807 }
3808
3809 #[bench]
3813 fn bench_orthogonal_cross_product (b : &mut test::Bencher) {
3814 use approx::AbsDiffEq;
3815 use rand::{RngExt, SeedableRng};
3816 use rand_distr::Distribution;
3817 let epsilon = f64::default_epsilon() * 256.0;
3818 let std_normal = rand_distr::StandardNormal;
3819 println!("ORTHO_VEC_BENCH_SEED: {}", *ORTHO_VEC_BENCH_SEED);
3820 let mut rng = rand_xorshift::XorShiftRng::seed_from_u64 (*ORTHO_VEC_BENCH_SEED);
3821 let randf = |rng : &mut rand_xorshift::XorShiftRng| {
3822 let x : f64 = std_normal.sample (rng);
3823 let y : f64 = std_normal.sample (rng);
3824 x / y
3825 };
3826 b.iter(||{
3827 let vec : Vector3 <f64> = match rng.random_range (0..=10) {
3828 0..=4 => vector3 (randf (&mut rng), randf (&mut rng), randf (&mut rng)),
3829 5 => vector3 (randf (&mut rng), 0.0, 0.0),
3830 6 => vector3 (0.0, randf (&mut rng), 0.0),
3831 7 => vector3 (0.0, 0.0, randf (&mut rng)),
3832 8 => vector3 (0.0, randf (&mut rng), randf (&mut rng)),
3833 9 => vector3 (randf (&mut rng), 0.0, randf (&mut rng)),
3834 10 => vector3 (randf (&mut rng), randf (&mut rng), 0.0),
3835 _ => unreachable!()
3836 };
3837 approx::assert_abs_diff_ne!(vec, Vector3::zero(), epsilon = epsilon);
3838 let mut ortho = vec.cross (Vector3::unit_x());
3839 if approx::abs_diff_eq!(ortho, Vector3::zero(), epsilon = epsilon) {
3840 ortho = vec.cross (Vector3::unit_y())
3841 }
3842 if approx::abs_diff_eq!(ortho, Vector3::zero(), epsilon = epsilon) ||
3843 approx::abs_diff_ne!(vec.dot (ortho), 0.0, epsilon = epsilon)
3844 {
3845 println!("VEC: {vec}");
3846 println!("ORTHO: {ortho}");
3847 println!("DOT: {}", vec.dot (ortho));
3848 }
3849 approx::assert_abs_diff_ne!(ortho, Vector3::zero(), epsilon = epsilon);
3850 approx::assert_abs_diff_eq!(vec.dot (ortho), 0.0, epsilon = epsilon);
3851 });
3852 }
3853
3854 #[bench]
3858 fn bench_orthogonal_copysign (b : &mut test::Bencher) {
3859 use approx::AbsDiffEq;
3860 use rand::{RngExt, SeedableRng};
3861 use rand_distr::Distribution;
3862 let epsilon = f64::default_epsilon() * 2.0.powi (32);
3863 let std_normal = rand_distr::StandardNormal;
3864 println!("ORTHO_VEC_BENCH_SEED: {}", *ORTHO_VEC_BENCH_SEED);
3865 let mut rng = rand_xorshift::XorShiftRng::seed_from_u64 (*ORTHO_VEC_BENCH_SEED);
3866 let randf = |rng : &mut rand_xorshift::XorShiftRng| {
3867 let x : f64 = std_normal.sample (rng);
3868 let y : f64 = std_normal.sample (rng);
3869 x / y
3870 };
3871 b.iter(||{
3872 let vec : Vector3 <f64> = match rng.random_range (0..=10) {
3873 0..=4 => vector3 (randf (&mut rng), randf (&mut rng), randf (&mut rng)),
3874 5 => vector3 (randf (&mut rng), 0.0, 0.0),
3875 6 => vector3 (0.0, randf (&mut rng), 0.0),
3876 7 => vector3 (0.0, 0.0, randf (&mut rng)),
3877 8 => vector3 (0.0, randf (&mut rng), randf (&mut rng)),
3878 9 => vector3 (randf (&mut rng), 0.0, randf (&mut rng)),
3879 10 => vector3 (randf (&mut rng), randf (&mut rng), 0.0),
3880 _ => unreachable!()
3881 };
3882 if approx::abs_diff_eq!(vec, Vector3::zero(), epsilon = epsilon) {
3883 return
3884 }
3885 let ortho = vector3 (
3886 vec.z.copysign (vec.x),
3887 vec.z.copysign (vec.y),
3888 -vec.x.copysign (vec.z) - vec.y.copysign (vec.z)
3890 );
3892 if approx::abs_diff_eq!(ortho, Vector3::zero(), epsilon = epsilon) ||
3893 approx::abs_diff_ne!(vec.dot (ortho), 0.0, epsilon = epsilon)
3894 {
3895 println!("VEC: {vec}");
3896 println!("ORTHO: {ortho}");
3897 println!("DOT: {:.}", vec.dot (ortho));
3898 }
3899 approx::assert_abs_diff_ne!(ortho, Vector3::zero(), epsilon = epsilon);
3900 approx::assert_abs_diff_eq!(vec.dot (ortho), 0.0, epsilon = epsilon);
3901 });
3902 }
3903
3904 #[bench]
3908 fn bench_orthogonal_sign (b : &mut test::Bencher) {
3909 use approx::AbsDiffEq;
3910 use rand::{RngExt, SeedableRng};
3911 use rand_distr::Distribution;
3912 let epsilon = f64::default_epsilon() * 2.0.powi (32);
3913 let std_normal = rand_distr::StandardNormal;
3914 println!("ORTHO_VEC_BENCH_SEED: {}", *ORTHO_VEC_BENCH_SEED);
3915 let mut rng = rand_xorshift::XorShiftRng::seed_from_u64 (*ORTHO_VEC_BENCH_SEED);
3916 let randf = |rng : &mut rand_xorshift::XorShiftRng| {
3917 let x : f64 = std_normal.sample (rng);
3918 let y : f64 = std_normal.sample (rng);
3919 x / y
3920 };
3921 b.iter(||{
3922 let vec : Vector3 <f64> = match rng.random_range (0..=10) {
3923 0..=4 => vector3 (randf (&mut rng), randf (&mut rng), randf (&mut rng)),
3924 5 => vector3 (randf (&mut rng), 0.0, 0.0),
3925 6 => vector3 (0.0, randf (&mut rng), 0.0),
3926 7 => vector3 (0.0, 0.0, randf (&mut rng)),
3927 8 => vector3 (0.0, randf (&mut rng), randf (&mut rng)),
3928 9 => vector3 (randf (&mut rng), 0.0, randf (&mut rng)),
3929 10 => vector3 (randf (&mut rng), randf (&mut rng), 0.0),
3930 _ => unreachable!()
3931 };
3932 if approx::abs_diff_eq!(vec, Vector3::zero(), epsilon = epsilon) {
3933 return
3934 }
3935 let sign = |n : f64| if n == 0.0 {
3936 0.0
3937 } else if n > 0.0 {
3938 1.0
3939 } else {
3940 -1.0
3941 };
3942 let signfn = |n : f64| sign ((sign (n) + 0.5) * (sign (vec.z) + 0.5));
3943 let ortho = vector3 (
3944 signfn (vec.x) * vec.z,
3945 signfn (vec.y) * vec.z,
3946 (-signfn (vec.x)).mul_add (vec.x, -signfn (vec.y) * vec.y)
3947 );
3949 if approx::abs_diff_eq!(ortho, Vector3::zero(), epsilon = epsilon) ||
3950 approx::abs_diff_ne!(vec.dot (ortho), 0.0, epsilon = epsilon)
3951 {
3952 println!("VEC: {vec}");
3953 println!("ORTHO: {ortho}");
3954 println!("DOT: {:.}", vec.dot (ortho));
3955 }
3956 approx::assert_abs_diff_ne!(ortho, Vector3::zero(), epsilon = epsilon);
3957 approx::assert_abs_diff_eq!(vec.dot (ortho), 0.0, epsilon = epsilon);
3958 });
3959 }
3960}