Mon, 01 Dec 2025 19:50:58 -0500
Implement Euclidean for f32 and f64
| 5 | 1 | /*! |
| 2 | Euclidean spaces. | |
| 3 | */ | |
| 4 | ||
|
63
f7b87d84864d
Extra reflexivity and hilbert-like requirements for Euclidean. Fuse Dot into Euclidean.
Tuomo Valkonen <tuomov@iki.fi>
parents:
62
diff
changeset
|
5 | use crate::instance::Instance; |
| 150 | 6 | use crate::linops::{VectorSpace, AXPY}; |
|
192
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
7 | use crate::norms::{HasDual, Norm, Normed, Reflexive, L2}; |
|
124
6aa955ad8122
Transpose loc parameters to allow f64 defaults
Tuomo Valkonen <tuomov@iki.fi>
parents:
64
diff
changeset
|
8 | use crate::types::*; |
| 5 | 9 | |
| 146 | 10 | pub mod wrap; |
| 11 | ||
| 150 | 12 | // TODO: Euclidean & EuclideanMut |
| 13 | // | |
| 5 | 14 | /// Space (type) with Euclidean and vector space structure |
| 15 | /// | |
| 16 | /// The type should implement vector space operations (addition, subtraction, scalar | |
| 17 | /// multiplication and scalar division) along with their assignment versions, as well | |
|
63
f7b87d84864d
Extra reflexivity and hilbert-like requirements for Euclidean. Fuse Dot into Euclidean.
Tuomo Valkonen <tuomov@iki.fi>
parents:
62
diff
changeset
|
18 | /// as an inner product. |
| 151 | 19 | // TODO: remove F parameter, use VectorSpace::Field |
|
124
6aa955ad8122
Transpose loc parameters to allow f64 defaults
Tuomo Valkonen <tuomov@iki.fi>
parents:
64
diff
changeset
|
20 | pub trait Euclidean<F: Float = f64>: |
| 164 | 21 | VectorSpace<Field = F, PrincipalV = Self::PrincipalE> + Reflexive<F, DualSpace = Self::PrincipalE> |
|
63
f7b87d84864d
Extra reflexivity and hilbert-like requirements for Euclidean. Fuse Dot into Euclidean.
Tuomo Valkonen <tuomov@iki.fi>
parents:
62
diff
changeset
|
22 | { |
| 164 | 23 | /// Principal form of the space; always equal to [`Space::Principal`] and |
| 24 | /// [`VectorSpace::PrincipalV`], but with more traits guaranteed. | |
| 25 | type PrincipalE: ClosedEuclidean<F>; | |
| 151 | 26 | |
|
63
f7b87d84864d
Extra reflexivity and hilbert-like requirements for Euclidean. Fuse Dot into Euclidean.
Tuomo Valkonen <tuomov@iki.fi>
parents:
62
diff
changeset
|
27 | // Inner product |
|
124
6aa955ad8122
Transpose loc parameters to allow f64 defaults
Tuomo Valkonen <tuomov@iki.fi>
parents:
64
diff
changeset
|
28 | fn dot<I: Instance<Self>>(&self, other: I) -> F; |
|
63
f7b87d84864d
Extra reflexivity and hilbert-like requirements for Euclidean. Fuse Dot into Euclidean.
Tuomo Valkonen <tuomov@iki.fi>
parents:
62
diff
changeset
|
29 | |
| 5 | 30 | /// Calculate the square of the 2-norm, $\frac{1}{2}\\|x\\|_2^2$, where `self` is $x$. |
|
63
f7b87d84864d
Extra reflexivity and hilbert-like requirements for Euclidean. Fuse Dot into Euclidean.
Tuomo Valkonen <tuomov@iki.fi>
parents:
62
diff
changeset
|
31 | /// |
|
f7b87d84864d
Extra reflexivity and hilbert-like requirements for Euclidean. Fuse Dot into Euclidean.
Tuomo Valkonen <tuomov@iki.fi>
parents:
62
diff
changeset
|
32 | /// This is not automatically implemented to avoid imposing |
|
f7b87d84864d
Extra reflexivity and hilbert-like requirements for Euclidean. Fuse Dot into Euclidean.
Tuomo Valkonen <tuomov@iki.fi>
parents:
62
diff
changeset
|
33 | /// `for <'a> &'a Self : Instance<Self>` trait bound bloat. |
|
f7b87d84864d
Extra reflexivity and hilbert-like requirements for Euclidean. Fuse Dot into Euclidean.
Tuomo Valkonen <tuomov@iki.fi>
parents:
62
diff
changeset
|
34 | fn norm2_squared(&self) -> F; |
| 5 | 35 | |
| 36 | /// Calculate the square of the 2-norm divided by 2, $\frac{1}{2}\\|x\\|_2^2$, | |
| 37 | /// where `self` is $x$. | |
| 38 | #[inline] | |
| 39 | fn norm2_squared_div2(&self) -> F { | |
|
124
6aa955ad8122
Transpose loc parameters to allow f64 defaults
Tuomo Valkonen <tuomov@iki.fi>
parents:
64
diff
changeset
|
40 | self.norm2_squared() / F::TWO |
| 5 | 41 | } |
| 42 | ||
| 43 | /// Calculate the 2-norm $‖x‖_2$, where `self` is $x$. | |
| 44 | #[inline] | |
| 45 | fn norm2(&self) -> F { | |
| 46 | self.norm2_squared().sqrt() | |
| 47 | } | |
| 48 | ||
| 49 | /// Calculate the 2-distance squared $\\|x-y\\|_2^2$, where `self` is $x$. | |
|
124
6aa955ad8122
Transpose loc parameters to allow f64 defaults
Tuomo Valkonen <tuomov@iki.fi>
parents:
64
diff
changeset
|
50 | fn dist2_squared<I: Instance<Self>>(&self, y: I) -> F; |
| 5 | 51 | |
| 52 | /// Calculate the 2-distance $\\|x-y\\|_2$, where `self` is $x$. | |
| 53 | #[inline] | |
|
124
6aa955ad8122
Transpose loc parameters to allow f64 defaults
Tuomo Valkonen <tuomov@iki.fi>
parents:
64
diff
changeset
|
54 | fn dist2<I: Instance<Self>>(&self, y: I) -> F { |
| 5 | 55 | self.dist2_squared(y).sqrt() |
| 56 | } | |
| 57 | ||
| 58 | /// Projection to the 2-ball. | |
| 59 | #[inline] | |
| 164 | 60 | fn proj_ball2(self, ρ: F) -> Self::PrincipalV { |
| 150 | 61 | let r = self.norm2(); |
| 62 | if r > ρ { | |
| 63 | self * (ρ / r) | |
| 64 | } else { | |
| 65 | self.into_owned() | |
| 66 | } | |
| 5 | 67 | } |
| 150 | 68 | } |
| 5 | 69 | |
| 151 | 70 | pub trait ClosedEuclidean<F: Float = f64>: |
| 164 | 71 | Instance<Self> + Euclidean<F, PrincipalE = Self> |
| 151 | 72 | { |
| 73 | } | |
| 164 | 74 | impl<F: Float, X: Instance<X> + Euclidean<F, PrincipalE = Self>> ClosedEuclidean<F> for X {} |
| 151 | 75 | |
| 150 | 76 | // TODO: remove F parameter, use AXPY::Field |
| 151 | 77 | pub trait EuclideanMut<F: Float = f64>: Euclidean<F> + AXPY<Field = F> { |
| 5 | 78 | /// In-place projection to the 2-ball. |
| 79 | #[inline] | |
|
124
6aa955ad8122
Transpose loc parameters to allow f64 defaults
Tuomo Valkonen <tuomov@iki.fi>
parents:
64
diff
changeset
|
80 | fn proj_ball2_mut(&mut self, ρ: F) { |
| 5 | 81 | let r = self.norm2(); |
|
124
6aa955ad8122
Transpose loc parameters to allow f64 defaults
Tuomo Valkonen <tuomov@iki.fi>
parents:
64
diff
changeset
|
82 | if r > ρ { |
|
6aa955ad8122
Transpose loc parameters to allow f64 defaults
Tuomo Valkonen <tuomov@iki.fi>
parents:
64
diff
changeset
|
83 | *self *= ρ / r |
| 5 | 84 | } |
| 85 | } | |
| 86 | } | |
| 87 | ||
| 151 | 88 | impl<X, F: Float> EuclideanMut<F> for X where X: Euclidean<F> + AXPY<Field = F> {} |
| 150 | 89 | |
| 5 | 90 | /// Trait for [`Euclidean`] spaces with dimensions known at compile time. |
|
124
6aa955ad8122
Transpose loc parameters to allow f64 defaults
Tuomo Valkonen <tuomov@iki.fi>
parents:
64
diff
changeset
|
91 | pub trait StaticEuclidean<F: Float = f64>: Euclidean<F> { |
| 5 | 92 | /// Returns the origin |
|
186
afe04e6b4a5b
StaticEuclidean Principal reference fix
Tuomo Valkonen <tuomov@iki.fi>
parents:
164
diff
changeset
|
93 | fn origin() -> <Self as Euclidean<F>>::PrincipalE; |
| 5 | 94 | } |
|
192
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
95 | |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
96 | macro_rules! scalar_euclidean { |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
97 | ($f:ident) => { |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
98 | impl VectorSpace for $f { |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
99 | type Field = $f; |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
100 | type PrincipalV = $f; |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
101 | |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
102 | #[inline] |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
103 | fn similar_origin(&self) -> Self::PrincipalV { |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
104 | 0.0 |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
105 | } |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
106 | } |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
107 | impl AXPY for $f { |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
108 | #[inline] |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
109 | fn axpy<I: Instance<$f>>(&mut self, α: $f, x: I, β: $f) { |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
110 | *self = β * *self + α * x.own() |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
111 | } |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
112 | |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
113 | #[inline] |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
114 | fn set_zero(&mut self) { |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
115 | *self = 0.0 |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
116 | } |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
117 | } |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
118 | |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
119 | impl Norm<L2, $f> for $f { |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
120 | fn norm(&self, _p: L2) -> $f { |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
121 | self.abs() |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
122 | } |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
123 | } |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
124 | |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
125 | impl Normed<$f> for $f { |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
126 | type NormExp = L2; |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
127 | |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
128 | fn norm_exponent(&self) -> Self::NormExp { |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
129 | L2 |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
130 | } |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
131 | } |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
132 | |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
133 | impl HasDual<$f> for $f { |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
134 | type DualSpace = $f; |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
135 | |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
136 | #[inline] |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
137 | fn dual_origin(&self) -> $f { |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
138 | 0.0 |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
139 | } |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
140 | } |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
141 | |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
142 | impl Euclidean<$f> for $f { |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
143 | type PrincipalE = $f; |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
144 | |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
145 | #[inline] |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
146 | fn dot<I: Instance<Self>>(&self, other: I) -> $f { |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
147 | *self * other.own() |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
148 | } |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
149 | |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
150 | #[inline] |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
151 | fn norm2_squared(&self) -> $f { |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
152 | *self * *self |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
153 | } |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
154 | |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
155 | #[inline] |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
156 | fn dist2_squared<I: Instance<Self>>(&self, y: I) -> $f { |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
157 | let d = *self - y.own(); |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
158 | d * d |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
159 | } |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
160 | } |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
161 | }; |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
162 | } |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
163 | |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
164 | scalar_euclidean!(f64); |
|
883b7d010297
Implement Euclidean for f32 and f64
Tuomo Valkonen <tuomov@iki.fi>
parents:
186
diff
changeset
|
165 | scalar_euclidean!(f32); |