src/euclidean.rs

branch
dev
changeset 124
6aa955ad8122
parent 64
4f6ca107ccb1
child 131
8264d72aa347
child 132
89371dc4d637
equal deleted inserted replaced
122:495448cca603 124:6aa955ad8122
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};
6 use crate::types::*;
7 use crate::instance::Instance; 5 use crate::instance::Instance;
8 use crate::norms::{HasDual, Reflexive}; 6 use crate::norms::{HasDual, Reflexive};
7 use crate::types::*;
8 use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
9 9
10 /// Space (type) with Euclidean and vector space structure 10 /// Space (type) with Euclidean and vector space structure
11 /// 11 ///
12 /// The type should implement vector space operations (addition, subtraction, scalar 12 /// The type should implement vector space operations (addition, subtraction, scalar
13 /// multiplication and scalar division) along with their assignment versions, as well 13 /// multiplication and scalar division) along with their assignment versions, as well
14 /// as an inner product. 14 /// as an inner product.
15 pub trait Euclidean<F : Float> : HasDual<F, DualSpace=Self> + Reflexive<F> 15 pub trait Euclidean<F: Float = f64>:
16 + Mul<F, Output=<Self as Euclidean<F>>::Output> + MulAssign<F> 16 HasDual<F, DualSpace = Self>
17 + Div<F, Output=<Self as Euclidean<F>>::Output> + DivAssign<F> 17 + Reflexive<F>
18 + Add<Self, Output=<Self as Euclidean<F>>::Output> 18 + Mul<F, Output = <Self as Euclidean<F>>::Output>
19 + Sub<Self, Output=<Self as Euclidean<F>>::Output> 19 + MulAssign<F>
20 + for<'b> Add<&'b Self, Output=<Self as Euclidean<F>>::Output> 20 + Div<F, Output = <Self as Euclidean<F>>::Output>
21 + for<'b> Sub<&'b Self, Output=<Self as Euclidean<F>>::Output> 21 + DivAssign<F>
22 + AddAssign<Self> + for<'b> AddAssign<&'b Self> 22 + Add<Self, Output = <Self as Euclidean<F>>::Output>
23 + SubAssign<Self> + for<'b> SubAssign<&'b Self> 23 + Sub<Self, Output = <Self as Euclidean<F>>::Output>
24 + Neg<Output=<Self as Euclidean<F>>::Output> 24 + for<'b> Add<&'b Self, Output = <Self as Euclidean<F>>::Output>
25 + for<'b> Sub<&'b Self, Output = <Self as Euclidean<F>>::Output>
26 + AddAssign<Self>
27 + for<'b> AddAssign<&'b Self>
28 + SubAssign<Self>
29 + for<'b> SubAssign<&'b Self>
30 + Neg<Output = <Self as Euclidean<F>>::Output>
25 { 31 {
26 type Output : Euclidean<F>; 32 type Output: Euclidean<F>;
27 33
28 // Inner product 34 // Inner product
29 fn dot<I : Instance<Self>>(&self, other : I) -> F; 35 fn dot<I: Instance<Self>>(&self, other: I) -> F;
30 36
31 /// Calculate the square of the 2-norm, $\frac{1}{2}\\|x\\|_2^2$, where `self` is $x$. 37 /// Calculate the square of the 2-norm, $\frac{1}{2}\\|x\\|_2^2$, where `self` is $x$.
32 /// 38 ///
33 /// This is not automatically implemented to avoid imposing 39 /// This is not automatically implemented to avoid imposing
34 /// `for <'a> &'a Self : Instance<Self>` trait bound bloat. 40 /// `for <'a> &'a Self : Instance<Self>` trait bound bloat.
36 42
37 /// Calculate the square of the 2-norm divided by 2, $\frac{1}{2}\\|x\\|_2^2$, 43 /// Calculate the square of the 2-norm divided by 2, $\frac{1}{2}\\|x\\|_2^2$,
38 /// where `self` is $x$. 44 /// where `self` is $x$.
39 #[inline] 45 #[inline]
40 fn norm2_squared_div2(&self) -> F { 46 fn norm2_squared_div2(&self) -> F {
41 self.norm2_squared()/F::TWO 47 self.norm2_squared() / F::TWO
42 } 48 }
43 49
44 /// Calculate the 2-norm $‖x‖_2$, where `self` is $x$. 50 /// Calculate the 2-norm $‖x‖_2$, where `self` is $x$.
45 #[inline] 51 #[inline]
46 fn norm2(&self) -> F { 52 fn norm2(&self) -> F {
47 self.norm2_squared().sqrt() 53 self.norm2_squared().sqrt()
48 } 54 }
49 55
50 /// Calculate the 2-distance squared $\\|x-y\\|_2^2$, where `self` is $x$. 56 /// Calculate the 2-distance squared $\\|x-y\\|_2^2$, where `self` is $x$.
51 fn dist2_squared<I : Instance<Self>>(&self, y : I) -> F; 57 fn dist2_squared<I: Instance<Self>>(&self, y: I) -> F;
52 58
53 /// Calculate the 2-distance $\\|x-y\\|_2$, where `self` is $x$. 59 /// Calculate the 2-distance $\\|x-y\\|_2$, where `self` is $x$.
54 #[inline] 60 #[inline]
55 fn dist2<I : Instance<Self>>(&self, y : I) -> F { 61 fn dist2<I: Instance<Self>>(&self, y: I) -> F {
56 self.dist2_squared(y).sqrt() 62 self.dist2_squared(y).sqrt()
57 } 63 }
58 64
59 /// Projection to the 2-ball. 65 /// Projection to the 2-ball.
60 #[inline] 66 #[inline]
61 fn proj_ball2(mut self, ρ : F) -> Self { 67 fn proj_ball2(mut self, ρ: F) -> Self {
62 self.proj_ball2_mut(ρ); 68 self.proj_ball2_mut(ρ);
63 self 69 self
64 } 70 }
65 71
66 /// In-place projection to the 2-ball. 72 /// In-place projection to the 2-ball.
67 #[inline] 73 #[inline]
68 fn proj_ball2_mut(&mut self, ρ : F) { 74 fn proj_ball2_mut(&mut self, ρ: F) {
69 let r = self.norm2(); 75 let r = self.norm2();
70 if r>ρ { 76 if r > ρ {
71 *self *= ρ/r 77 *self *= ρ / r
72 } 78 }
73 } 79 }
74 } 80 }
75 81
76 /// Trait for [`Euclidean`] spaces with dimensions known at compile time. 82 /// Trait for [`Euclidean`] spaces with dimensions known at compile time.
77 pub trait StaticEuclidean<F : Float> : Euclidean<F> { 83 pub trait StaticEuclidean<F: Float = f64>: Euclidean<F> {
78 /// Returns the origin 84 /// Returns the origin
79 fn origin() -> <Self as Euclidean<F>>::Output; 85 fn origin() -> <Self as Euclidean<F>>::Output;
80 } 86 }

mercurial