src/euclidean.rs

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

mercurial