1use either::Either;
4#[cfg(feature = "derive_serdes")]
5use serde;
6
7use crate::num_traits as num;
8use crate::types::{Affinity, Projectivity, Sign};
9
10pub trait ProjectiveSpace <S, V> : VectorSpace <S> where
12 V : VectorSpace <S> + std::fmt::Display,
13 S : Field + std::fmt::Display
14{
15 fn homography <A> (
17 affinity : Affinity <S, A, A, <A::Vector as Module <S>>::LinearEndo>
18 ) -> Projectivity <S, V, V, Self, Self, Self::LinearEndo> where
19 A : AffineSpace <S, Vector=V>;
20 fn homogeneous <A> (point_or_vector : Either <A::Point, A::Vector>) -> Self where
23 A : AffineSpace <S, Vector=V>,
24 V : GroupAction <A::Point>;
25}
26
27pub trait EuclideanSpace <S : Real> : AffineSpace <S> where
29 Self::Vector : InnerProductSpace <S>
30{
31 fn origin() -> Self::Point {
32 use num::Zero;
33 Self::Point::from_vector (Self::Vector::zero())
34 }
35}
36
37pub trait AffineSpace <S : Field> {
39 type Point : Point <Self::Vector>;
40 type Vector : VectorSpace <S> + GroupAction <Self::Point>;
41}
42
43impl <S, V> AffineSpace <S> for V where
44 S : Field,
45 V : VectorSpace <S> + GroupAction <V> + Point <V>
46{
47 type Point = Self;
48 type Vector = Self;
49}
50
51pub trait Point <V> : Sized + std::ops::Sub <Self, Output=V> where
54 V : AdditiveGroup + GroupAction <Self>
55{
56 fn to_vector (self) -> V;
57 fn from_vector (vector : V) -> Self;
58 fn origin() -> Self {
59 Self::from_vector (V::zero())
60 }
61}
62
63pub trait GroupAction <X> : Group {
65 fn action (self, x : X) -> X;
66}
67
68impl <G> GroupAction <G> for G where G : Group {
69 #[expect(clippy::renamed_function_params)]
70 fn action (self, g : Self) -> Self {
71 Self::operation (g, self)
72 }
73}
74
75pub trait InnerProductSpace <S : Field> : VectorSpace <S> + Dot <S> {
77 fn inner_product (self, other : Self) -> S {
78 self.dot (other)
79 }
80}
81
82impl <V, S> NormedVectorSpace <S> for V where
83 V : InnerProductSpace <S>,
84 S : Field
85{
86 fn norm_squared (self) -> S {
87 self.self_dot()
88 }
89}
90
91pub trait Dot <S : Ring> : Module <S> {
93 fn dot (self, other : Self) -> S;
94 fn self_dot (self) -> S {
96 self.dot (self)
97 }
98}
99
100pub trait NormedVectorSpace <S : Field> : VectorSpace <S> {
102 fn norm_squared (self) -> S;
103 fn norm (self) -> S where S : Sqrt {
104 self.norm_squared().sqrt()
105 }
106 fn normalize (self) -> Self where S : Sqrt {
107 self / self.norm()
108 }
109 fn unit_sigvec (self) -> Self where S : SignedExt + Sqrt {
110 let v = self.sigvec();
111 if v.is_zero() {
112 v
113 } else {
114 v.normalize()
115 }
116 }
117}
118
119impl <V, S> MetricSpace <S> for V where
120 V : NormedVectorSpace <S>,
121 S : Field
122{
123 fn distance_squared (self, other : Self) -> S {
124 (self - other).norm_squared()
125 }
126}
127
128pub trait MetricSpace <S> : Sized {
130 fn distance_squared (self, other : Self) -> S;
131 fn distance (self, other : Self) -> S where S : Sqrt {
132 self.distance_squared (other).sqrt()
133 }
134}
135
136pub trait VectorSpace <S : Field> : Module <S> + std::ops::Div <S, Output=Self> + Copy {
138 fn map <F> (self, f : F) -> Self where F : FnMut (S) -> S;
140 fn sigvec (self) -> Self where S : SignedExt {
143 self.map (SignedExt::signum_or_zero)
144 }
145}
146
147pub trait Module <S : Ring> : AdditiveGroup + std::ops::Mul <S, Output=Self> + Copy {
149 type LinearEndo : LinearMap <S, Self, Self> + MultiplicativeMonoid;
151}
152
153pub trait LinearMap <S, V, W> : std::ops::Mul <V, Output=W> + Copy where
155 S : Ring,
156 V : Module <S>,
157 W : Module <S>
158{
159 fn determinant (self) -> S;
160 fn transpose (self) -> Self;
161}
162
163pub trait Real : Field + SignedExt + Exp + Sqrt + Trig + MinMax {
165 fn pi() -> Self;
167 fn frac_pi_3() -> Self;
168 fn sqrt_3() -> Self;
169 fn frac_1_sqrt_3() -> Self;
170 fn floor (self) -> Self;
171 fn ceil (self) -> Self;
172 fn trunc (self) -> Self;
173 fn fract (self) -> Self;
174}
175
176pub trait Field : Ring + MultiplicativeGroup + Powi + Powf {
178 fn half() -> Self {
180 Self::one() / Self::two()
181 }
182 fn two() -> Self {
183 Self::one() + Self::one()
184 }
185 fn three() -> Self {
186 Self::one() + Self::one() + Self::one()
187 }
188 fn four() -> Self {
189 Self::two() * Self::two()
190 }
191 fn five() -> Self {
192 Self::two() + Self::three()
193 }
194 fn six() -> Self {
195 Self::two() * Self::three()
196 }
197 fn seven() -> Self {
198 Self::three() + Self::four()
199 }
200 fn eight() -> Self {
201 Self::two() * Self::two() * Self::two()
202 }
203 fn nine() -> Self {
204 Self::three() * Self::three()
205 }
206 fn ten() -> Self {
207 Self::two() * Self::five()
208 }
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 : Ring + num::PrimInt + num::Signed { }
219
220pub trait Ring : Copy + PartialOrd + MinMax + AdditiveGroup +
223 std::ops::Mul <Self, Output=Self> + std::ops::MulAssign + num::Signed +
224 num::MulAdd <Self, Self, Output=Self> + num::MulAddAssign <Self, Self>
225{
226 fn squared (self) -> Self {
227 self * self
228 }
229 fn cubed (self) -> Self {
230 self * self * self
231 }
232}
233
234pub trait AdditiveGroup : AdditiveMonoid +
237 std::ops::Sub <Self, Output=Self> + std::ops::SubAssign + std::ops::Neg <Output=Self>
238{ }
239
240pub trait Group : PartialEq + std::ops::Neg <Output=Self> {
242 fn identity() -> Self;
243 fn operation (a : Self, b : Self) -> Self;
244}
245
246pub trait MultiplicativeMonoid : Sized + PartialEq +
249 std::ops::Mul <Self, Output=Self> + std::ops::MulAssign + num::One
250{ }
251
252pub trait AdditiveMonoid : Sized + PartialEq +
255 std::ops::Add <Self, Output=Self> + std::ops::AddAssign + num::Zero
256{ }
257
258pub trait Angle <S : Real> : Clone + Copy + PartialEq + PartialOrd + Sized +
260 AdditiveGroup + std::ops::Div <Self, Output=S> + std::ops::Mul <S, Output=Self> +
261 std::ops::Div <S, Output=Self> + std::ops::Rem <Self, Output=Self>
262{
263 fn full_turn() -> Self;
266 fn half_turn() -> Self {
269 Self::full_turn() / S::two()
270 }
271 fn wrap_signed (self) -> Self {
273 let out = (self + Self::half_turn()).wrap_unsigned() - Self::half_turn();
274 if out == -Self::half_turn() {
275 Self::half_turn()
276 } else {
277 out
278 }
279 }
280 fn wrap_unsigned (self) -> Self {
282 if self >= Self::full_turn() {
283 self % Self::full_turn()
284 } else if self < Self::zero() {
285 self + Self::full_turn() * ((self / Self::full_turn()).trunc().abs() + S::one())
286 } else {
287 self
288 }
289 }
290}
291
292pub trait Pow {
294 fn pow (self, exp : u32) -> Self;
295}
296pub trait Powi {
298 fn powi (self, n : i32) -> Self;
299}
300pub trait Powf {
302 fn powf (self, n : Self) -> Self;
303}
304pub trait Exp {
306 fn exp (self) -> Self;
307}
308pub trait Sqrt {
310 fn sqrt (self) -> Self;
311}
312pub trait Trig : Sized {
314 fn sin (self) -> Self;
315 fn sin_cos (self) -> (Self, Self);
316 fn cos (self) -> Self;
317 fn tan (self) -> Self;
318 fn asin (self) -> Self;
319 fn acos (self) -> Self;
320 fn atan (self) -> Self;
321 fn atan2 (self, other : Self) -> Self;
322}
323
324pub trait MinMax {
328 fn min (self, other : Self) -> Self;
329 fn max (self, other : Self) -> Self;
330 fn clamp (self, min : Self, max : Self) -> Self;
331}
332
333pub trait SignedExt : num::Signed {
335 #[inline]
336 fn sign (self) -> Sign {
337 if self.is_zero() {
338 Sign::Zero
339 } else if self.is_positive() {
340 Sign::Positive
341 } else {
342 debug_assert!(self.is_negative());
343 Sign::Negative
344 }
345 }
346 #[inline]
349 fn signum_or_zero (self) -> Self where Self : num::Zero {
350 if self.is_zero() {
351 Self::zero()
352 } else {
353 self.signum()
354 }
355 }
356}
357
358#[cfg(not(feature = "derive_serdes"))]
363pub trait MaybeSerDes { }
364#[cfg(feature = "derive_serdes")]
365pub trait MaybeSerDes : serde::Serialize + serde::de::DeserializeOwned { }
366
367impl <
368 #[cfg(not(feature = "derive_serdes"))]
369 T,
370 #[cfg(feature = "derive_serdes")]
371 T : serde::Serialize + serde::de::DeserializeOwned
372> MaybeSerDes for T { }
373
374macro impl_integer ($type:ty) {
375 impl Integer for $type { }
376 impl Ring for $type { }
377 impl AdditiveGroup for $type { }
378 impl AdditiveMonoid for $type { }
379 impl SignedExt for $type { }
380 impl MinMax for $type {
381 fn min (self, other : Self) -> Self {
382 Ord::min (self, other)
383 }
384 fn max (self, other : Self) -> Self {
385 Ord::max (self, other)
386 }
387 fn clamp (self, min : Self, max : Self) -> Self {
388 Ord::clamp (self, min, max)
389 }
390 }
391 impl Pow for $type {
392 fn pow (self, exp : u32) -> Self {
393 self.pow (exp)
394 }
395 }
396}
397impl_integer!(i8);
398impl_integer!(i16);
399impl_integer!(i32);
400impl_integer!(i64);
401
402macro impl_real_float ($type:ident) {
403 impl VectorSpace <Self> for $type {
404 fn map <F> (self, mut f : F) -> Self where F : FnMut (Self) -> Self {
405 f (self)
406 }
407 }
408 impl Module <Self> for $type {
409 type LinearEndo = Self;
410 }
411 impl LinearMap <Self, Self, Self> for $type {
412 fn determinant (self) -> Self {
413 self
414 }
415 fn transpose (self) -> Self {
416 self
417 }
418 }
419 impl Real for $type {
420 fn pi() -> Self {
421 std::$type::consts::PI
422 }
423 fn frac_pi_3() -> Self {
424 std::$type::consts::FRAC_PI_3
425 }
426 #[expect(clippy::excessive_precision)]
427 #[allow(clippy::allow_attributes)]
428 #[allow(clippy::cast_possible_truncation)]
429 fn sqrt_3() -> Self {
430 1.732050807568877293527446341505872366942805253810380628055f64 as $type
431 }
432 #[expect(clippy::excessive_precision)]
433 #[allow(clippy::allow_attributes)]
434 #[allow(clippy::cast_possible_truncation)]
435 fn frac_1_sqrt_3() -> Self {
436 (1.0f64 / 1.732050807568877293527446341505872366942805253810380628055f64) as $type
437 }
438 fn floor (self) -> Self {
439 self.floor()
440 }
441 fn ceil (self) -> Self {
442 self.ceil()
443 }
444 fn trunc (self) -> Self {
445 self.trunc()
446 }
447 fn fract (self) -> Self {
448 self.fract()
449 }
450 }
451 impl Field for $type { }
452 impl MultiplicativeGroup for $type { }
453 impl MultiplicativeMonoid for $type { }
454 impl Ring for $type { }
455 impl AdditiveGroup for $type { }
456 impl AdditiveMonoid for $type { }
457 impl SignedExt for $type { }
458 impl MinMax for $type {
459 fn min (self, other : Self) -> Self {
460 self.min (other)
461 }
462 fn max (self, other : Self) -> Self {
463 self.max (other)
464 }
465 fn clamp (self, min : Self, max : Self) -> Self {
466 self.clamp (min, max)
467 }
468 }
469 impl Powi for $type {
470 fn powi (self, n : i32) -> Self {
471 self.powi (n as i32)
472 }
473 }
474 impl Powf for $type {
475 fn powf (self, n : Self) -> Self {
476 self.powf (n)
477 }
478 }
479 impl Exp for $type {
480 fn exp (self) -> Self {
481 self.exp()
482 }
483 }
484 impl Sqrt for $type {
485 fn sqrt (self) -> Self {
486 self.sqrt()
487 }
488 }
489 impl Trig for $type {
490 fn sin (self) -> Self {
491 self.sin()
492 }
493 fn sin_cos (self) -> (Self, Self) {
494 self.sin_cos()
495 }
496 fn cos (self) -> Self {
497 self.cos()
498 }
499 fn tan (self) -> Self {
500 self.tan()
501 }
502 fn asin (self) -> Self {
503 self.asin()
504 }
505 fn acos (self) -> Self {
506 self.acos()
507 }
508 fn atan (self) -> Self {
509 self.atan()
510 }
511 fn atan2 (self, other : Self) -> Self {
512 self.atan2 (other)
513 }
514 }
515}
516
517impl_real_float!(f32);
518impl_real_float!(f64);