src/euclidean.rs

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

mercurial