1use either::Either;
4#[cfg(feature = "derive_serdes")]
5use serde;
6
7use crate::{approx, num};
8use crate::types::{
9 Addition, Affinity, LinearIso, Multiplication, NonZero, NonNegative, Normalized,
10 Projectivity, Sign
11};
12
13pub trait ProjectiveSpace <S : Field> : AffineSpace <S> {
15 type Patch : AffineSpace <S>;
17 fn homography (affinity :
19 Affinity <S, Self::Patch, Self::Patch,
20 <<Self::Patch as AffineSpace <S>>::Translation as Module <S>>::LinearEndo>
21 ) -> Projectivity <S, Self, Self, <Self::Translation as Module <S>>::LinearEndo> where
22 <Self::Translation as Module <S>>::LinearEndo :
23 From <<<Self::Patch as AffineSpace <S>>::Translation as Module <S>>::LinearEndo>
24 {
25 Projectivity::new (LinearIso::new ((*affinity.linear_iso).into()).unwrap())
26 }
27 fn homogeneous (point_or_vector :
30 Either <Self::Patch, <Self::Patch as AffineSpace <S>>::Translation>
31 ) -> Self where Self : From <(Self::Patch, S)> {
32 match point_or_vector {
33 Either::Left (point) => (point, S::one()).into(),
34 Either::Right (vector) => (Self::Patch::from_vector (vector), S::zero()).into()
35 }
36 }
37}
38
39pub trait EuclideanSpace <S : Real> : AffineSpace <S> + MetricSpace <S> { }
41
42pub trait AffineSpace <S : Field> : Point <Self::Translation> {
44 type Translation : VectorSpace <S> + GroupAction <Addition, Self>;
45}
46
47pub trait Point <V> : Sized + std::ops::Sub <Self, Output=V> where
50 V : AdditiveGroup + GroupAction <Addition, Self>
51{
52 fn to_vector (self) -> V;
53 fn from_vector (vector : V) -> Self;
54 fn origin() -> Self {
55 Self::from_vector (V::zero())
56 }
57}
58
59pub trait MetricSpace <S : Field> : NormedVectorSpace <S> {
61 fn distance_squared (self, other : Self) -> NonNegative <S> {
62 (self - other).norm_squared()
63 }
64 fn distance (self, other : Self) -> NonNegative <S> where S : Sqrt {
65 self.distance_squared (other).sqrt()
66 }
67}
68
69pub trait NormedVectorSpace <S : Field> : InnerProductSpace <S> {
71 type Unit : Into <Self>;
72 fn norm_squared (self) -> NonNegative <S>;
74 fn norm_max (self) -> NonNegative <S> where S : SignedExt;
76 #[must_use]
77 fn normalize (self) -> Self::Unit where S : Sqrt;
78 fn norm (self) -> NonNegative <S> where S : Sqrt {
80 self.norm_squared().sqrt()
81 }
82 fn unit_sigvec (self) -> Self where S : SignedExt + Sqrt {
85 let v = self.sigvec();
86 if v.is_zero() {
87 v
88 } else {
89 v.normalize().into()
90 }
91 }
92}
93
94pub trait InnerProductSpace <S : Field> : VectorSpace <S> + Dot <S> {
96 fn inner_product (self, other : Self) -> S {
97 self.dot (other)
98 }
99 fn outer_product (self, other : Self) -> Self::LinearEndo;
100 fn orthogonal (self) -> Self where S : approx::AbsDiffEq <Epsilon = S>;
101}
102
103pub trait VectorSpace <S : Field> : Module <S> + std::ops::Div <S, Output=Self> + Copy {
105 type NonZero;
106 #[must_use]
108 fn map <F> (self, f : F) -> Self where F : FnMut (S) -> S;
109 fn sigvec (self) -> Self where S : SignedExt {
112 self.map (SignedExt::signum_or_zero)
113 }
114 fn interpolate (a : Self, b : Self, t : Normalized <S>) -> Self {
116 a + (b - a) * *t
117 }
118 fn extrapolate (a : Self, b : Self, t : S) -> Self {
120 a + (b - a) * t
121 }
122}
123
124pub trait Vector2Ext <S> {
126 fn exterior_product (self, rhs : Self) -> S;
128}
129
130pub trait Dot <S : Ring> : Module <S> {
132 fn dot (self, other : Self) -> S;
133 fn self_dot (self) -> NonNegative <S> where S : OrderedRing {
135 NonNegative::unchecked (self.dot (self))
136 }
137}
138
139pub trait Module <S : Ring> : AdditiveGroup + std::ops::Mul <S, Output=Self> + Copy {
141 type LinearEndo : LinearMap <S, Self, Self> + Ring;
143}
144
145pub trait LinearMap <S, V, W> : std::ops::Mul <V, Output=W> + Copy where
147 S : Ring,
148 V : Module <S>,
149 W : Module <S>
150{
151 fn determinant (self) -> S;
152 fn transpose (self) -> Self;
153}
154
155pub trait Matrix <S> : Copy {
157 type Rows;
158 type Submatrix;
159 fn rows (self) -> Self::Rows;
161 fn submatrix (self, i : usize, j : usize) -> Self::Submatrix;
163 fn fill_zeros (submatrix : Self::Submatrix) -> Self where S : num::Zero;
165 #[inline]
167 fn minor <V, W> (self, i : usize, j : usize) -> S where
168 S : Ring,
169 V : Module <S>,
170 W : Module <S>,
171 Self::Submatrix : LinearMap <S, V, W>
172 {
173 self.submatrix (i, j).determinant()
174 }
175}
176
177pub trait ElementaryReflector {
179 type Vector;
180 fn elementary_reflector (v : Self::Vector, index : usize) -> Self;
182}
183
184pub trait Real : OrderedField + Exp + Powf + Sqrt + Trig {
186 fn pi() -> Self;
188 fn frac_pi_3() -> Self;
189 fn sqrt_3() -> Self;
190 fn frac_1_sqrt_3() -> Self;
191}
192
193pub trait OrderedField : Field + OrderedRing { }
195
196pub trait Field : Ring + MultiplicativeGroup + Powi + Rational {
198 fn half() -> Self {
199 Self::one() / Self::two()
200 }
201}
202
203pub trait Rational {
205 fn floor (self) -> Self;
206 fn ceil (self) -> Self;
207 fn trunc (self) -> Self;
208 fn fract (self) -> Self;
209}
210
211pub trait MultiplicativeGroup : MultiplicativeMonoid +
214 std::ops::Div <Self, Output=Self> + std::ops::DivAssign + num::Inv <Output=Self>
215{ }
216
217pub trait Integer : OrderedRing + SignedExt + num::PrimInt { }
219
220pub trait OrderedRing : Ring + SignedExt + MinMax + PartialOrd + std::ops::Rem { }
222
223pub trait Ring : AdditiveGroup + MultiplicativeMonoid
231 + num::MulAdd <Self, Self, Output=Self> + num::MulAddAssign <Self, Self>
232 + std::fmt::Debug
233{
234 fn two() -> Self {
235 Self::one() + Self::one()
236 }
237 fn three() -> Self {
238 Self::one() + Self::one() + Self::one()
239 }
240 fn four() -> Self {
241 Self::two() * Self::two()
242 }
243 fn five() -> Self {
244 Self::two() + Self::three()
245 }
246 fn six() -> Self {
247 Self::two() * Self::three()
248 }
249 fn seven() -> Self {
250 Self::three() + Self::four()
251 }
252 fn eight() -> Self {
253 Self::two() * Self::two() * Self::two()
254 }
255 fn nine() -> Self {
256 Self::three() * Self::three()
257 }
258 fn ten() -> Self {
259 Self::two() * Self::five()
260 }
261}
262
263pub trait AdditiveGroup : AdditiveMonoid +
266 std::ops::Sub <Self, Output=Self> + std::ops::SubAssign + std::ops::Neg <Output=Self>
267{ }
268
269pub trait GroupAction <G, X> : MonoidAction <G, X> where G : Group <Self> { }
271
272pub trait Group <G> : Monoid <G> {
274 fn inverse (elem : G) -> G;
275}
276
277pub trait MultiplicativeMonoid : Copy + PartialEq +
280 std::ops::Mul <Self, Output=Self> + std::ops::MulAssign + num::One
281{
282 fn squared (self) -> Self {
283 self * self
284 }
285 fn cubed (self) -> Self {
286 self * self * self
287 }
288}
289
290pub trait AdditiveMonoid : Sized + PartialEq + std::iter::Sum
293 + std::ops::Add <Self, Output=Self> + std::ops::AddAssign + num::Zero
294{ }
295
296pub trait MonoidAction <M, X> : SemigroupAction <M, X> where M : Monoid <Self> { }
298
299pub trait Monoid <M> : Semigroup <M> {
301 fn identity() -> M;
303}
304
305pub trait SemigroupAction <S, X> : Sized where S : Semigroup <Self> {
307 fn action (self, x : X) -> X;
308}
309
310pub trait Semigroup <S> : PartialEq {
312 fn operation (a : S, b : S) -> S;
314}
315
316pub trait Angle <S : OrderedField> : Clone + Copy + PartialEq + PartialOrd + Sized +
318 AdditiveGroup + std::ops::Div <Self, Output=S> + std::ops::Mul <S, Output=Self> +
319 std::ops::Div <S, Output=Self> + std::ops::Rem <Self, Output=Self>
320{
321 fn full_turn() -> Self;
324 fn half_turn() -> Self {
327 Self::full_turn() / S::two()
328 }
329 fn wrap_signed (self) -> Self {
331 if self > Self::half_turn() || self <= -Self::half_turn() {
332 let out = (self + Self::half_turn()).wrap_unsigned() - Self::half_turn();
333 if out == -Self::half_turn() {
334 Self::half_turn()
335 } else {
336 out
337 }
338 } else {
339 self
340 }
341 }
342 fn wrap_unsigned (self) -> Self {
344 if self >= Self::full_turn() {
345 self % Self::full_turn()
346 } else if self < Self::zero() {
347 self + Self::full_turn() * ((self / Self::full_turn()).trunc().abs() + S::one())
348 } else {
349 self
350 }
351 }
352}
353
354pub trait Pow {
356 fn pow (self, exp : u32) -> Self;
357}
358pub trait Powi {
360 fn powi (self, n : i32) -> Self;
361}
362pub trait Powf {
364 fn powf (self, n : Self) -> Self;
365}
366pub trait Exp {
368 fn exp (self) -> Self;
369}
370pub trait Sqrt {
372 fn sqrt (self) -> Self;
373}
374pub trait Cbrt {
376 fn cbrt (self) -> Self;
377}
378pub trait Trig : Sized {
380 fn sin (self) -> Self;
381 fn sin_cos (self) -> (Self, Self);
382 fn cos (self) -> Self;
383 fn tan (self) -> Self;
384 fn asin (self) -> Self;
385 fn acos (self) -> Self;
386 fn atan (self) -> Self;
387 fn atan2 (self, other : Self) -> Self;
388}
389
390pub trait MinMax {
394 fn min (self, other : Self) -> Self;
395 fn max (self, other : Self) -> Self;
396 fn clamp (self, min : Self, max : Self) -> Self;
397}
398
399pub trait SignedExt : num::Signed {
401 #[inline]
402 fn sign (self) -> Sign {
403 if self.is_zero() {
404 Sign::Zero
405 } else if self.is_positive() {
406 Sign::Positive
407 } else {
408 debug_assert!(self.is_negative());
409 Sign::Negative
410 }
411 }
412 #[inline]
415 fn signum_or_zero (self) -> Self where Self : num::Zero {
416 if self.is_zero() {
417 Self::zero()
418 } else {
419 self.signum()
420 }
421 }
422
423 #[inline]
424 fn signum_or_zero_approx (self) -> Self where
425 Self : OrderedRing + approx::AbsDiffEq <Epsilon = Self>
426 {
427 let one = Self::one();
428 if self.abs() < Self::default_epsilon() * (one + one + one + one) {
429 Self::zero()
430 } else {
431 self.signum()
432 }
433 }
434}
435
436#[cfg(not(feature = "derive_serdes"))]
441pub trait MaybeSerDes { }
442#[cfg(feature = "derive_serdes")]
443pub trait MaybeSerDes : serde::Serialize + serde::de::DeserializeOwned { }
444
445impl <S, T> MetricSpace <S> for T where S : Field, T : NormedVectorSpace <S> { }
446impl <T> OrderedField for T where T : Field + OrderedRing { }
447impl <T> Field for T where
448 T : Ring + MultiplicativeGroup + Powi + Rational { }
449impl <T> Integer for T where T : OrderedRing + num::PrimInt { }
450impl <T> OrderedRing for T where
451 T : Ring + SignedExt + MinMax + PartialOrd + std::ops::Rem
452{ }
453impl <T> Ring for T where
454 T : AdditiveGroup + MultiplicativeMonoid
455 + num::MulAdd<Self, Self, Output=Self> + num::MulAddAssign <Self, Self>
456 + std::fmt::Debug
457{ }
458impl <T> AdditiveGroup for T where
459 T : AdditiveMonoid + std::ops::Sub <Self, Output=Self> + std::ops::SubAssign
460 + std::ops::Neg <Output=Self>
461{ }
462impl <T> MultiplicativeGroup for T where
463 T : MultiplicativeMonoid + std::ops::Div <Self, Output=Self> + std::ops::DivAssign
464 + num::Inv <Output=Self>
465{ }
466impl <T> GroupAction <Multiplication, T> for T where
467 T : MonoidAction <Multiplication, T>,
468 Multiplication : Group <T>
469{ }
470impl <T> MonoidAction <Multiplication, T> for T where
471 T : SemigroupAction <Multiplication, T>,
472 Multiplication : Monoid <T>
473{ }
474impl <T> SemigroupAction <Multiplication, T> for T where Multiplication : Semigroup <T> {
475 #[expect(clippy::renamed_function_params)]
476 fn action (self, g : Self) -> Self {
477 Multiplication::operation (g, self)
478 }
479}
480impl <T> GroupAction <Addition, T> for T where
481 T : MonoidAction <Addition, T>,
482 Addition : Group <T>
483{ }
484impl <T> MonoidAction <Addition, T> for T where
485 T : SemigroupAction <Addition, T>,
486 Addition : Monoid <T>
487{ }
488impl <T> SemigroupAction <Addition, T> for T where Addition : Semigroup <T> {
489 #[expect(clippy::renamed_function_params)]
490 fn action (self, g : Self) -> Self {
491 Addition::operation (g, self)
492 }
493}
494impl <T> AdditiveMonoid for T where
495 T : Sized + PartialEq + std::iter::Sum + std::ops::Add <Self, Output=Self>
496 + std::ops::AddAssign + num::Zero
497{ }
498impl <T> MultiplicativeMonoid for T where
499 T : Copy + PartialEq + std::ops::Mul <Self, Output=Self> + std::ops::MulAssign
500 + num::One
501{ }
502impl <T : num::Signed> SignedExt for T { }
503
504impl <
505 #[cfg(not(feature = "derive_serdes"))]
506 T,
507 #[cfg(feature = "derive_serdes")]
508 T : serde::Serialize + serde::de::DeserializeOwned
509> MaybeSerDes for T { }
510
511macro impl_integer ($type:ty) {
512 impl MinMax for $type {
513 fn min (self, other : Self) -> Self {
514 Ord::min (self, other)
515 }
516 fn max (self, other : Self) -> Self {
517 Ord::max (self, other)
518 }
519 fn clamp (self, min : Self, max : Self) -> Self {
520 Ord::clamp (self, min, max)
521 }
522 }
523 impl Pow for $type {
524 fn pow (self, exp : u32) -> Self {
525 self.pow (exp)
526 }
527 }
528}
529impl_integer!(i8);
530impl_integer!(i16);
531impl_integer!(i32);
532impl_integer!(i64);
533
534macro impl_real_float ($type:ident) {
535 impl AffineSpace <Self> for $type {
536 type Translation = $type;
537 }
538 impl Point <Self> for $type {
539 fn to_vector (self) -> $type {
540 self
541 }
542 fn from_vector (vector : $type) -> Self {
543 vector
544 }
545 }
546 impl VectorSpace <Self> for $type {
547 type NonZero = NonZero <$type>;
548 fn map <F> (self, mut f : F) -> Self where F : FnMut (Self) -> Self {
549 f (self)
550 }
551 }
552 impl Module <Self> for $type {
553 type LinearEndo = Self;
554 }
555 impl LinearMap <Self, Self, Self> for $type {
556 fn determinant (self) -> Self {
557 self
558 }
559 fn transpose (self) -> Self {
560 self
561 }
562 }
563 impl Real for $type {
564 fn pi() -> Self {
565 std::$type::consts::PI
566 }
567 fn frac_pi_3() -> Self {
568 std::$type::consts::FRAC_PI_3
569 }
570 #[expect(clippy::excessive_precision)]
571 #[allow(clippy::allow_attributes)]
572 #[allow(clippy::cast_possible_truncation)]
573 #[allow(trivial_numeric_casts)]
574 fn sqrt_3() -> Self {
575 1.732050807568877293527446341505872366942805253810380628055f64 as $type
576 }
577 #[expect(clippy::excessive_precision)]
578 #[allow(clippy::allow_attributes)]
579 #[allow(clippy::cast_possible_truncation)]
580 #[allow(trivial_numeric_casts)]
581 fn frac_1_sqrt_3() -> Self {
582 (1.0f64 / 1.732050807568877293527446341505872366942805253810380628055f64) as $type
583 }
584 }
585 impl Rational for $type {
586 fn floor (self) -> Self {
587 self.floor()
588 }
589 fn ceil (self) -> Self {
590 self.ceil()
591 }
592 fn trunc (self) -> Self {
593 self.trunc()
594 }
595 fn fract (self) -> Self {
596 self.fract()
597 }
598 }
599 impl MinMax for $type {
600 fn min (self, other : Self) -> Self {
601 self.min (other)
602 }
603 fn max (self, other : Self) -> Self {
604 self.max (other)
605 }
606 fn clamp (self, min : Self, max : Self) -> Self {
607 self.clamp (min, max)
608 }
609 }
610 impl Powi for $type {
611 fn powi (self, n : i32) -> Self {
612 self.powi (n)
613 }
614 }
615 impl Powf for $type {
616 fn powf (self, n : Self) -> Self {
617 self.powf (n)
618 }
619 }
620 impl Exp for $type {
621 fn exp (self) -> Self {
622 self.exp()
623 }
624 }
625 impl Sqrt for $type {
626 fn sqrt (self) -> Self {
627 self.sqrt()
628 }
629 }
630 impl Cbrt for $type {
631 fn cbrt (self) -> Self {
632 self.cbrt()
633 }
634 }
635 impl Trig for $type {
636 fn sin (self) -> Self {
637 self.sin()
638 }
639 fn sin_cos (self) -> (Self, Self) {
640 self.sin_cos()
641 }
642 fn cos (self) -> Self {
643 self.cos()
644 }
645 fn tan (self) -> Self {
646 self.tan()
647 }
648 fn asin (self) -> Self {
649 self.asin()
650 }
651 fn acos (self) -> Self {
652 self.acos()
653 }
654 fn atan (self) -> Self {
655 self.atan()
656 }
657 fn atan2 (self, other : Self) -> Self {
658 self.atan2 (other)
659 }
660 }
661}
662
663impl_real_float!(f32);
664impl_real_float!(f64);