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