1use either::Either;
4#[cfg(feature = "derive_serdes")]
5use serde;
6
7use crate::num_traits as num;
8use crate::types::{Affinity, LinearIso, Projectivity, Sign};
9
10pub trait ProjectiveSpace <S : Field> : AffineSpace <S> {
12 type Patch : AffineSpace <S>;
14 #[expect(clippy::type_complexity)]
16 fn homography (affinity :
17 Affinity <S, Self::Patch, Self::Patch,
18 <<Self::Patch as AffineSpace <S>>::Translation as Module <S>>::LinearEndo>
19 ) -> Projectivity <S, Self, Self, <Self::Translation as Module <S>>::LinearEndo> where
20 <Self::Translation as Module <S>>::LinearEndo :
21 From <<<Self::Patch as AffineSpace <S>>::Translation as Module <S>>::LinearEndo>
22 {
23 Projectivity::new (LinearIso::new ((*affinity.linear_iso).into()).unwrap())
24 }
25 fn homogeneous (point_or_vector :
28 Either <Self::Patch, <Self::Patch as AffineSpace <S>>::Translation>
29 ) -> Self where Self : From <(Self::Patch, S)> {
30 match point_or_vector {
31 Either::Left (point) => (point, S::one()).into(),
32 Either::Right (vector) => (Self::Patch::from_vector (vector), S::zero()).into()
33 }
34 }
35}
36
37pub trait EuclideanSpace <S : Real> : AffineSpace <S> + MetricSpace <S> { }
39
40pub trait AffineSpace <S : Field> : Point <Self::Translation> {
42 type Translation : VectorSpace <S> + GroupAction <Self>;
43}
44
45pub trait Point <V> : Sized + std::ops::Sub <Self, Output=V> where
48 V : AdditiveGroup + GroupAction <Self>
49{
50 fn to_vector (self) -> V;
51 fn from_vector (vector : V) -> Self;
52 fn origin() -> Self {
53 Self::from_vector (V::zero())
54 }
55}
56
57pub trait GroupAction <X> : Group {
59 fn action (self, x : X) -> X;
60}
61
62impl <G> GroupAction <G> for G where G : Group {
63 #[expect(clippy::renamed_function_params)]
64 fn action (self, g : Self) -> Self {
65 Self::operation (g, self)
66 }
67}
68
69pub trait InnerProductSpace <S : Field> : VectorSpace <S> + Dot <S> {
71 fn inner_product (self, other : Self) -> S {
72 self.dot (other)
73 }
74 fn outer_product (self, other : Self) -> Self::LinearEndo;
75}
76
77impl <V, S> NormedVectorSpace <S> for V where
78 V : InnerProductSpace <S>,
79 S : Field
80{
81 fn norm_squared (self) -> S {
82 self.self_dot()
83 }
84}
85
86pub trait Dot <S : Ring> : Module <S> {
88 fn dot (self, other : Self) -> S;
89 fn self_dot (self) -> S {
91 self.dot (self)
92 }
93}
94
95pub trait NormedVectorSpace <S : Field> : InnerProductSpace <S> {
97 fn norm_squared (self) -> S;
98 fn norm (self) -> S where S : Sqrt {
99 self.norm_squared().sqrt()
100 }
101 #[must_use]
102 fn normalize (self) -> Self where S : Sqrt {
103 self / self.norm()
104 }
105 fn unit_sigvec (self) -> Self where S : SignedExt + Sqrt {
106 let v = self.sigvec();
107 if v.is_zero() {
108 v
109 } else {
110 v.normalize()
111 }
112 }
113}
114
115pub trait MetricSpace <S : Field> : NormedVectorSpace <S> {
117 fn distance_squared (self, other : Self) -> S {
118 (self - other).norm_squared()
119 }
120 fn distance (self, other : Self) -> S where S : Sqrt {
121 self.distance_squared (other).sqrt()
122 }
123}
124
125pub trait VectorSpace <S : Field> : Module <S> + std::ops::Div <S, Output=Self> + Copy {
127 fn map <F> (self, f : F) -> Self where F : FnMut (S) -> S;
129 fn sigvec (self) -> Self where S : SignedExt {
132 self.map (SignedExt::signum_or_zero)
133 }
134}
135
136pub trait Module <S : Ring> : AdditiveGroup + std::ops::Mul <S, Output=Self> + Copy {
138 type LinearEndo : LinearMap <S, Self, Self> + Ring;
140}
141
142pub trait LinearMap <S, V, W> : std::ops::Mul <V, Output=W> + Copy where
144 S : Ring,
145 V : Module <S>,
146 W : Module <S>
147{
148 fn determinant (self) -> S;
149 fn transpose (self) -> Self;
150}
151
152pub trait Matrix <S> : Copy {
154 type Rows;
155 type Submatrix;
156 fn rows (self) -> Self::Rows;
158 fn submatrix (self, i : usize, j : usize) -> Self::Submatrix;
160 fn fill_zeros (submatrix : Self::Submatrix) -> Self where S : num::Zero;
162 #[inline]
164 fn minor <V, W> (self, i : usize, j : usize) -> S where
165 S : Ring,
166 V : Module <S>,
167 W : Module <S>,
168 Self::Submatrix : LinearMap <S, V, W>
169 {
170 self.submatrix (i, j).determinant()
171 }
172}
173
174pub trait ElementaryReflector {
176 type Vector;
177 fn elementary_reflector (v : Self::Vector, index : usize) -> Self;
179}
180
181pub trait Real : OrderedField + Exp + Powf + Sqrt + Trig {
183 fn pi() -> Self;
185 fn frac_pi_3() -> Self;
186 fn sqrt_3() -> Self;
187 fn frac_1_sqrt_3() -> Self;
188 fn floor (self) -> Self;
189 fn ceil (self) -> Self;
190 fn trunc (self) -> Self;
191 fn fract (self) -> Self;
192}
193
194pub trait OrderedField : Field + OrderedRing { }
196
197pub trait Field : Ring + MultiplicativeGroup + Powi {
199 fn half() -> Self {
200 Self::one() / Self::two()
201 }
202 fn two() -> Self {
203 Self::one() + Self::one()
204 }
205 fn three() -> Self {
206 Self::one() + Self::one() + Self::one()
207 }
208 fn four() -> Self {
209 Self::two() * Self::two()
210 }
211 fn five() -> Self {
212 Self::two() + Self::three()
213 }
214 fn six() -> Self {
215 Self::two() * Self::three()
216 }
217 fn seven() -> Self {
218 Self::three() + Self::four()
219 }
220 fn eight() -> Self {
221 Self::two() * Self::two() * Self::two()
222 }
223 fn nine() -> Self {
224 Self::three() * Self::three()
225 }
226 fn ten() -> Self {
227 Self::two() * Self::five()
228 }
229}
230
231pub trait MultiplicativeGroup : MultiplicativeMonoid +
234 std::ops::Div <Self, Output=Self> + std::ops::DivAssign + num::Inv <Output=Self>
235{ }
236
237pub trait Integer : OrderedRing + SignedExt + num::PrimInt { }
239
240pub trait OrderedRing : Ring + SignedExt + MinMax + PartialOrd + std::ops::Rem { }
242
243pub trait Ring : AdditiveGroup + MultiplicativeMonoid
246 + num::MulAdd <Self, Self, Output=Self> + num::MulAddAssign <Self, Self>
247{ }
248
249pub trait AdditiveGroup : AdditiveMonoid +
252 std::ops::Sub <Self, Output=Self> + std::ops::SubAssign + std::ops::Neg <Output=Self>
253{ }
254
255pub trait Group : PartialEq + std::ops::Neg <Output=Self> {
257 fn identity() -> Self;
258 fn operation (a : Self, b : Self) -> Self;
259}
260
261pub trait MultiplicativeMonoid : Copy + PartialEq +
264 std::ops::Mul <Self, Output=Self> + std::ops::MulAssign + num::One
265{
266 fn squared (self) -> Self {
267 self * self
268 }
269 fn cubed (self) -> Self {
270 self * self * self
271 }
272}
273
274pub trait AdditiveMonoid : Sized + PartialEq + std::iter::Sum
277 + std::ops::Add <Self, Output=Self> + std::ops::AddAssign + num::Zero
278{ }
279
280pub trait Angle <S : Real> : Clone + Copy + PartialEq + PartialOrd + Sized +
282 AdditiveGroup + std::ops::Div <Self, Output=S> + std::ops::Mul <S, Output=Self> +
283 std::ops::Div <S, Output=Self> + std::ops::Rem <Self, Output=Self>
284{
285 fn full_turn() -> Self;
288 fn half_turn() -> Self {
291 Self::full_turn() / S::two()
292 }
293 fn wrap_signed (self) -> Self {
295 if self > Self::half_turn() || self <= -Self::half_turn() {
296 let out = (self + Self::half_turn()).wrap_unsigned() - Self::half_turn();
297 if out == -Self::half_turn() {
298 Self::half_turn()
299 } else {
300 out
301 }
302 } else {
303 self
304 }
305 }
306 fn wrap_unsigned (self) -> Self {
308 if self >= Self::full_turn() {
309 self % Self::full_turn()
310 } else if self < Self::zero() {
311 self + Self::full_turn() * ((self / Self::full_turn()).trunc().abs() + S::one())
312 } else {
313 self
314 }
315 }
316}
317
318pub trait Pow {
320 fn pow (self, exp : u32) -> Self;
321}
322pub trait Powi {
324 fn powi (self, n : i32) -> Self;
325}
326pub trait Powf {
328 fn powf (self, n : Self) -> Self;
329}
330pub trait Exp {
332 fn exp (self) -> Self;
333}
334pub trait Sqrt {
336 fn sqrt (self) -> Self;
337}
338pub trait Cbrt {
340 fn cbrt (self) -> Self;
341}
342pub trait Trig : Sized {
344 fn sin (self) -> Self;
345 fn sin_cos (self) -> (Self, Self);
346 fn cos (self) -> Self;
347 fn tan (self) -> Self;
348 fn asin (self) -> Self;
349 fn acos (self) -> Self;
350 fn atan (self) -> Self;
351 fn atan2 (self, other : Self) -> Self;
352}
353
354pub trait MinMax {
358 fn min (self, other : Self) -> Self;
359 fn max (self, other : Self) -> Self;
360 fn clamp (self, min : Self, max : Self) -> Self;
361}
362
363pub trait SignedExt : num::Signed {
365 #[inline]
366 fn sign (self) -> Sign {
367 if self.is_zero() {
368 Sign::Zero
369 } else if self.is_positive() {
370 Sign::Positive
371 } else {
372 debug_assert!(self.is_negative());
373 Sign::Negative
374 }
375 }
376 #[inline]
379 fn signum_or_zero (self) -> Self where Self : num::Zero {
380 if self.is_zero() {
381 Self::zero()
382 } else {
383 self.signum()
384 }
385 }
386}
387
388#[cfg(not(feature = "derive_serdes"))]
393pub trait MaybeSerDes { }
394#[cfg(feature = "derive_serdes")]
395pub trait MaybeSerDes : serde::Serialize + serde::de::DeserializeOwned { }
396
397impl <S, T> MetricSpace <S> for T where S : Field, T : NormedVectorSpace <S> { }
398impl <T> OrderedField for T where T : Field + OrderedRing { }
399impl <T> Field for T where T : Ring + MultiplicativeGroup + Powi + Powf { }
400impl <T> Integer for T where T : OrderedRing + num::PrimInt { }
401impl <T> OrderedRing for T where
402 T : Ring + SignedExt + MinMax + PartialOrd + std::ops::Rem
403{ }
404impl <T> Ring for T where
405 T : AdditiveGroup + MultiplicativeMonoid
406 + num::MulAdd<Self, Self, Output=Self> + num::MulAddAssign <Self, Self>
407{ }
408impl <T> AdditiveGroup for T where
409 T : AdditiveMonoid + std::ops::Sub <Self, Output=Self> + std::ops::SubAssign
410 + std::ops::Neg <Output=Self>
411{ }
412impl <T> MultiplicativeGroup for T where
413 T : MultiplicativeMonoid + std::ops::Div <Self, Output=Self> + std::ops::DivAssign
414 + num::Inv <Output=Self>
415{ }
416impl <T> AdditiveMonoid for T where
417 T : Sized + PartialEq + std::iter::Sum + std::ops::Add <Self, Output=Self>
418 + std::ops::AddAssign + num::Zero
419{ }
420impl <T> MultiplicativeMonoid for T where
421 T : Copy + PartialEq + std::ops::Mul <Self, Output=Self> + std::ops::MulAssign
422 + num::One
423{ }
424impl <T : num::Signed> SignedExt for T { }
425
426impl <
427 #[cfg(not(feature = "derive_serdes"))]
428 T,
429 #[cfg(feature = "derive_serdes")]
430 T : serde::Serialize + serde::de::DeserializeOwned
431> MaybeSerDes for T { }
432
433macro impl_integer ($type:ty) {
434 impl MinMax for $type {
435 fn min (self, other : Self) -> Self {
436 Ord::min (self, other)
437 }
438 fn max (self, other : Self) -> Self {
439 Ord::max (self, other)
440 }
441 fn clamp (self, min : Self, max : Self) -> Self {
442 Ord::clamp (self, min, max)
443 }
444 }
445 impl Pow for $type {
446 fn pow (self, exp : u32) -> Self {
447 self.pow (exp)
448 }
449 }
450}
451impl_integer!(i8);
452impl_integer!(i16);
453impl_integer!(i32);
454impl_integer!(i64);
455
456macro impl_real_float ($type:ident) {
457 impl VectorSpace <Self> for $type {
458 fn map <F> (self, mut f : F) -> Self where F : FnMut (Self) -> Self {
459 f (self)
460 }
461 }
462 impl Module <Self> for $type {
463 type LinearEndo = Self;
464 }
465 impl LinearMap <Self, Self, Self> for $type {
466 fn determinant (self) -> Self {
467 self
468 }
469 fn transpose (self) -> Self {
470 self
471 }
472 }
473 impl Real for $type {
474 fn pi() -> Self {
475 std::$type::consts::PI
476 }
477 fn frac_pi_3() -> Self {
478 std::$type::consts::FRAC_PI_3
479 }
480 #[expect(clippy::excessive_precision)]
481 #[allow(clippy::allow_attributes)]
482 #[allow(clippy::cast_possible_truncation)]
483 #[allow(trivial_numeric_casts)]
484 fn sqrt_3() -> Self {
485 1.732050807568877293527446341505872366942805253810380628055f64 as $type
486 }
487 #[expect(clippy::excessive_precision)]
488 #[allow(clippy::allow_attributes)]
489 #[allow(clippy::cast_possible_truncation)]
490 #[allow(trivial_numeric_casts)]
491 fn frac_1_sqrt_3() -> Self {
492 (1.0f64 / 1.732050807568877293527446341505872366942805253810380628055f64) as $type
493 }
494 fn floor (self) -> Self {
495 self.floor()
496 }
497 fn ceil (self) -> Self {
498 self.ceil()
499 }
500 fn trunc (self) -> Self {
501 self.trunc()
502 }
503 fn fract (self) -> Self {
504 self.fract()
505 }
506 }
507 impl MinMax for $type {
508 fn min (self, other : Self) -> Self {
509 self.min (other)
510 }
511 fn max (self, other : Self) -> Self {
512 self.max (other)
513 }
514 fn clamp (self, min : Self, max : Self) -> Self {
515 self.clamp (min, max)
516 }
517 }
518 impl Powi for $type {
519 fn powi (self, n : i32) -> Self {
520 self.powi (n)
521 }
522 }
523 impl Powf for $type {
524 fn powf (self, n : Self) -> Self {
525 self.powf (n)
526 }
527 }
528 impl Exp for $type {
529 fn exp (self) -> Self {
530 self.exp()
531 }
532 }
533 impl Sqrt for $type {
534 fn sqrt (self) -> Self {
535 self.sqrt()
536 }
537 }
538 impl Cbrt for $type {
539 fn cbrt (self) -> Self {
540 self.cbrt()
541 }
542 }
543 impl Trig for $type {
544 fn sin (self) -> Self {
545 self.sin()
546 }
547 fn sin_cos (self) -> (Self, Self) {
548 self.sin_cos()
549 }
550 fn cos (self) -> Self {
551 self.cos()
552 }
553 fn tan (self) -> Self {
554 self.tan()
555 }
556 fn asin (self) -> Self {
557 self.asin()
558 }
559 fn acos (self) -> Self {
560 self.acos()
561 }
562 fn atan (self) -> Self {
563 self.atan()
564 }
565 fn atan2 (self, other : Self) -> Self {
566 self.atan2 (other)
567 }
568 }
569}
570
571impl_real_float!(f32);
572impl_real_float!(f64);