| 1 /*! |
1 /*! |
| 2 Euclidean spaces. |
2 Euclidean spaces. |
| 3 */ |
3 */ |
| 4 |
4 |
| |
5 use std::ops::{Mul, MulAssign, Div, DivAssign, Add, Sub, AddAssign, SubAssign, Neg}; |
| 5 use crate::types::*; |
6 use crate::types::*; |
| 6 use std::ops::{Mul, MulAssign, Div, DivAssign, Add, Sub, AddAssign, SubAssign, Neg}; |
7 use crate::instance::Instance; |
| 7 |
8 use crate::norms::{HasDual, Reflexive}; |
| 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 |
9 |
| 16 /// Space (type) with Euclidean and vector space structure |
10 /// Space (type) with Euclidean and vector space structure |
| 17 /// |
11 /// |
| 18 /// The type should implement vector space operations (addition, subtraction, scalar |
12 /// The type should implement vector space operations (addition, subtraction, scalar |
| 19 /// multiplication and scalar division) along with their assignment versions, as well |
13 /// multiplication and scalar division) along with their assignment versions, as well |
| 20 /// as the [`Dot`] product with respect to `Self`. |
14 /// as an inner product. |
| 21 pub trait Euclidean<F : Float> : Sized + Dot<Self,F> |
15 pub trait Euclidean<F : Float> : HasDual<F, DualSpace=Self> + Reflexive<F> |
| 22 + Mul<F, Output=<Self as Euclidean<F>>::Output> + MulAssign<F> |
16 + Mul<F, Output=<Self as Euclidean<F>>::Output> + MulAssign<F> |
| 23 + Div<F, Output=<Self as Euclidean<F>>::Output> + DivAssign<F> |
17 + Div<F, Output=<Self as Euclidean<F>>::Output> + DivAssign<F> |
| 24 + Add<Self, Output=<Self as Euclidean<F>>::Output> |
18 + Add<Self, Output=<Self as Euclidean<F>>::Output> |
| 25 + Sub<Self, Output=<Self as Euclidean<F>>::Output> |
19 + Sub<Self, Output=<Self as Euclidean<F>>::Output> |
| 26 + for<'b> Add<&'b Self, Output=<Self as Euclidean<F>>::Output> |
20 + for<'b> Add<&'b Self, Output=<Self as Euclidean<F>>::Output> |
| 27 + for<'b> Sub<&'b Self, Output=<Self as Euclidean<F>>::Output> |
21 + for<'b> Sub<&'b Self, Output=<Self as Euclidean<F>>::Output> |
| 28 + AddAssign<Self> + for<'b> AddAssign<&'b Self> |
22 + AddAssign<Self> + for<'b> AddAssign<&'b Self> |
| 29 + SubAssign<Self> + for<'b> SubAssign<&'b Self> |
23 + SubAssign<Self> + for<'b> SubAssign<&'b Self> |
| 30 + Neg<Output=<Self as Euclidean<F>>::Output> { |
24 + Neg<Output=<Self as Euclidean<F>>::Output> |
| |
25 { |
| 31 type Output : Euclidean<F>; |
26 type Output : Euclidean<F>; |
| 32 |
27 |
| 33 /// Returns origin of same dimensions as `self`. |
28 // Inner product |
| 34 fn similar_origin(&self) -> <Self as Euclidean<F>>::Output; |
29 fn dot<I : Instance<Self>>(&self, other : I) -> F; |
| 35 |
30 |
| 36 /// Calculate the square of the 2-norm, $\frac{1}{2}\\|x\\|_2^2$, where `self` is $x$. |
31 /// Calculate the square of the 2-norm, $\frac{1}{2}\\|x\\|_2^2$, where `self` is $x$. |
| 37 #[inline] |
32 /// |
| 38 fn norm2_squared(&self) -> F { |
33 /// This is not automatically implemented to avoid imposing |
| 39 self.dot(self) |
34 /// `for <'a> &'a Self : Instance<Self>` trait bound bloat. |
| 40 } |
35 fn norm2_squared(&self) -> F; |
| 41 |
36 |
| 42 /// Calculate the square of the 2-norm divided by 2, $\frac{1}{2}\\|x\\|_2^2$, |
37 /// Calculate the square of the 2-norm divided by 2, $\frac{1}{2}\\|x\\|_2^2$, |
| 43 /// where `self` is $x$. |
38 /// where `self` is $x$. |
| 44 #[inline] |
39 #[inline] |
| 45 fn norm2_squared_div2(&self) -> F { |
40 fn norm2_squared_div2(&self) -> F { |
| 51 fn norm2(&self) -> F { |
46 fn norm2(&self) -> F { |
| 52 self.norm2_squared().sqrt() |
47 self.norm2_squared().sqrt() |
| 53 } |
48 } |
| 54 |
49 |
| 55 /// Calculate the 2-distance squared $\\|x-y\\|_2^2$, where `self` is $x$. |
50 /// Calculate the 2-distance squared $\\|x-y\\|_2^2$, where `self` is $x$. |
| 56 fn dist2_squared(&self, y : &Self) -> F; |
51 fn dist2_squared<I : Instance<Self>>(&self, y : I) -> F; |
| 57 |
52 |
| 58 /// Calculate the 2-distance $\\|x-y\\|_2$, where `self` is $x$. |
53 /// Calculate the 2-distance $\\|x-y\\|_2$, where `self` is $x$. |
| 59 #[inline] |
54 #[inline] |
| 60 fn dist2(&self, y : &Self) -> F { |
55 fn dist2<I : Instance<Self>>(&self, y : I) -> F { |
| 61 self.dist2_squared(y).sqrt() |
56 self.dist2_squared(y).sqrt() |
| 62 } |
57 } |
| 63 |
58 |
| 64 /// Projection to the 2-ball. |
59 /// Projection to the 2-ball. |
| 65 #[inline] |
60 #[inline] |