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] |