Tue, 06 Dec 2022 08:58:49 +0200
README improvements
5 | 1 | /*! |
2 | Euclidean spaces. | |
3 | */ | |
4 | ||
5 | use crate::types::*; | |
6 | use std::ops::{Mul, MulAssign, Div, DivAssign, Add, Sub, AddAssign, SubAssign, Neg}; | |
7 | ||
8 | /// Space (type) with a defined dot product. | |
9 | /// | |
10 | /// `U` is the space of the multiplier, and `F` the space of scalars. | |
11 | /// Since `U` ≠ `Self`, this trait can also implement dual products. | |
12 | pub trait Dot<U, F> { | |
13 | fn dot(&self, other : &U) -> F; | |
14 | } | |
15 | ||
16 | /// Space (type) with Euclidean and vector space structure | |
17 | /// | |
18 | /// The type should implement vector space operations (addition, subtraction, scalar | |
19 | /// multiplication and scalar division) along with their assignment versions, as well | |
20 | /// as the [`Dot`] product with respect to `Self`. | |
21 | pub trait Euclidean<F : Float> : Sized + Dot<Self,F> | |
22 | + Mul<F, Output=<Self as Euclidean<F>>::Output> + MulAssign<F> | |
23 | + Div<F, Output=<Self as Euclidean<F>>::Output> + DivAssign<F> | |
24 | + Add<Self, Output=<Self as Euclidean<F>>::Output> | |
25 | + Sub<Self, Output=<Self as Euclidean<F>>::Output> | |
26 | + for<'b> Add<&'b Self, Output=<Self as Euclidean<F>>::Output> | |
27 | + for<'b> Sub<&'b Self, Output=<Self as Euclidean<F>>::Output> | |
28 | + AddAssign<Self> + for<'b> AddAssign<&'b Self> | |
29 | + SubAssign<Self> + for<'b> SubAssign<&'b Self> | |
30 | + Neg<Output=<Self as Euclidean<F>>::Output> { | |
31 | type Output : Euclidean<F>; | |
32 | ||
33 | /// Returns origin of same dimensions as `self`. | |
34 | fn similar_origin(&self) -> <Self as Euclidean<F>>::Output; | |
35 | ||
36 | /// Calculate the square of the 2-norm, $\frac{1}{2}\\|x\\|_2^2$, where `self` is $x$. | |
37 | #[inline] | |
38 | fn norm2_squared(&self) -> F { | |
39 | self.dot(self) | |
40 | } | |
41 | ||
42 | /// Calculate the square of the 2-norm divided by 2, $\frac{1}{2}\\|x\\|_2^2$, | |
43 | /// where `self` is $x$. | |
44 | #[inline] | |
45 | fn norm2_squared_div2(&self) -> F { | |
46 | self.norm2_squared()/F::TWO | |
47 | } | |
48 | ||
49 | /// Calculate the 2-norm $‖x‖_2$, where `self` is $x$. | |
50 | #[inline] | |
51 | fn norm2(&self) -> F { | |
52 | self.norm2_squared().sqrt() | |
53 | } | |
54 | ||
55 | /// Calculate the 2-distance squared $\\|x-y\\|_2^2$, where `self` is $x$. | |
56 | fn dist2_squared(&self, y : &Self) -> F; | |
57 | ||
58 | /// Calculate the 2-distance $\\|x-y\\|_2$, where `self` is $x$. | |
59 | #[inline] | |
60 | fn dist2(&self, y : &Self) -> F { | |
61 | self.dist2_squared(y).sqrt() | |
62 | } | |
63 | ||
64 | /// Projection to the 2-ball. | |
65 | #[inline] | |
66 | fn proj_ball2(mut self, ρ : F) -> Self { | |
67 | self.proj_ball2_mut(ρ); | |
68 | self | |
69 | } | |
70 | ||
71 | /// In-place projection to the 2-ball. | |
72 | #[inline] | |
73 | fn proj_ball2_mut(&mut self, ρ : F) { | |
74 | let r = self.norm2(); | |
75 | if r>ρ { | |
76 | *self *= ρ/r | |
77 | } | |
78 | } | |
79 | } | |
80 | ||
81 | /// Trait for [`Euclidean`] spaces with dimensions known at compile time. | |
82 | pub trait StaticEuclidean<F : Float> : Euclidean<F> { | |
83 | /// Returns the origin | |
84 | fn origin() -> <Self as Euclidean<F>>::Output; | |
85 | } |