src/loc.rs

branch
dev
changeset 124
6aa955ad8122
parent 64
4f6ca107ccb1
child 129
d2994e34a5f5
equal deleted inserted replaced
122:495448cca603 124:6aa955ad8122
1 /*! 1 /*!
2 Array containers that support vector space operations on floats. 2 Array containers that support vector space operations on floats.
3 For working with small vectors in $ℝ^2$ or $ℝ^3$. 3 For working with small vectors in $ℝ^2$ or $ℝ^3$.
4 */ 4 */
5 5
6 use std::ops::{Add,Sub,AddAssign,SubAssign,Mul,Div,MulAssign,DivAssign,Neg,Index,IndexMut}; 6 use crate::euclidean::*;
7 use std::slice::{Iter,IterMut}; 7 use crate::instance::{BasicDecomposition, Instance};
8 use crate::linops::{Linear, Mapping, AXPY};
9 use crate::mapping::Space;
10 use crate::maputil::{map1, map1_mut, map2, map2_mut, FixedLength, FixedLengthMut};
11 use crate::norms::*;
12 use crate::types::{Float, Num, SignedNum};
13 use serde::ser::{Serialize, SerializeSeq, Serializer};
8 use std::fmt::{Display, Formatter}; 14 use std::fmt::{Display, Formatter};
9 use crate::types::{Float,Num,SignedNum}; 15 use std::ops::{
10 use crate::maputil::{FixedLength,FixedLengthMut,map1,map2,map1_mut,map2_mut}; 16 Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign,
11 use crate::euclidean::*; 17 };
12 use crate::norms::*; 18 use std::slice::{Iter, IterMut};
13 use crate::linops::{AXPY, Mapping, Linear};
14 use crate::instance::{Instance, BasicDecomposition};
15 use crate::mapping::Space;
16 use serde::ser::{Serialize, Serializer, SerializeSeq};
17
18 19
19 /// A container type for (short) `N`-dimensional vectors of element type `F`. 20 /// A container type for (short) `N`-dimensional vectors of element type `F`.
20 /// 21 ///
21 /// Supports basic operations of an [`Euclidean`] space, several [`Norm`]s, and 22 /// Supports basic operations of an [`Euclidean`] space, several [`Norm`]s, and
22 /// fused [`AXPY`] operations, among others. 23 /// fused [`AXPY`] operations, among others.
23 #[derive(Copy,Clone,Debug,PartialEq,Eq)] 24 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
24 pub struct Loc<F, const N : usize>( 25 pub struct Loc<const N: usize, F = f64>(
25 /// An array of the elements of the vector 26 /// An array of the elements of the vector
26 pub [F; N] 27 pub [F; N],
27 ); 28 );
28 29
29 impl<F : Display, const N : usize> Display for Loc<F, N>{ 30 impl<F: Display, const N: usize> Display for Loc<N, F> {
30 // Required method 31 // Required method
31 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { 32 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
32 write!(f, "[")?; 33 write!(f, "[")?;
33 let mut comma = ""; 34 let mut comma = "";
34 for e in self.iter() { 35 for e in self.iter() {
35 write!(f, "{comma}{e}")?; 36 write!(f, "{comma}{e}")?;
36 comma = ", "; 37 comma = ", ";
37 } 38 }
38 write!(f, "]") 39 write!(f, "]")
39 } 40 }
40 } 41 }
41 42
42 // Need to manually implement as [F; N] serialisation is provided only for some N. 43 // Need to manually implement as [F; N] serialisation is provided only for some N.
43 impl<F, const N : usize> Serialize for Loc<F, N> 44 impl<F, const N: usize> Serialize for Loc<N, F>
44 where 45 where
45 F: Serialize, 46 F: Serialize,
46 { 47 {
47 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 48 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
48 where 49 where
54 } 55 }
55 seq.end() 56 seq.end()
56 } 57 }
57 } 58 }
58 59
59 impl<F, const N : usize> Loc<F, N> { 60 impl<F, const N: usize> Loc<N, F> {
60 /// Creates a new `Loc` vector from an array. 61 /// Creates a new `Loc` vector from an array.
61 #[inline] 62 #[inline]
62 pub fn new(arr : [F; N]) -> Self { 63 pub fn new(arr: [F; N]) -> Self {
63 Loc(arr) 64 Loc(arr)
64 } 65 }
65 66
66 /// Returns an iterator over the elements of the vector 67 /// Returns an iterator over the elements of the vector
67 #[inline] 68 #[inline]
74 pub fn iter_mut(&mut self) -> IterMut<'_, F> { 75 pub fn iter_mut(&mut self) -> IterMut<'_, F> {
75 self.0.iter_mut() 76 self.0.iter_mut()
76 } 77 }
77 } 78 }
78 79
79 impl<F : Copy, const N : usize> Loc<F, N> { 80 impl<F: Copy, const N: usize> Loc<N, F> {
80 /// Maps `g` over the elements of the vector, returning a new [`Loc`] vector 81 /// Maps `g` over the elements of the vector, returning a new [`Loc`] vector
81 #[inline] 82 #[inline]
82 pub fn map<H>(&self, g : impl Fn(F) -> H) -> Loc<H, N> { 83 pub fn map<H>(&self, g: impl Fn(F) -> H) -> Loc<N, H> {
83 Loc::new(map1(self, |u| g(*u))) 84 Loc::new(map1(self, |u| g(*u)))
84 } 85 }
85 86
86 /// Maps `g` over pairs of elements of two vectors, retuning a new one. 87 /// Maps `g` over pairs of elements of two vectors, retuning a new one.
87 #[inline] 88 #[inline]
88 pub fn map2<H>(&self, other : &Self, g : impl Fn(F, F) -> H) -> Loc<H, N> { 89 pub fn map2<H>(&self, other: &Self, g: impl Fn(F, F) -> H) -> Loc<N, H> {
89 Loc::new(map2(self, other, |u, v| g(*u, *v))) 90 Loc::new(map2(self, other, |u, v| g(*u, *v)))
90 } 91 }
91 92
92 /// Maps `g` over mutable references to elements of the vector. 93 /// Maps `g` over mutable references to elements of the vector.
93 #[inline] 94 #[inline]
94 pub fn map_mut(&mut self, g : impl Fn(&mut F)) { 95 pub fn map_mut(&mut self, g: impl Fn(&mut F)) {
95 map1_mut(self, g) 96 map1_mut(self, g)
96 } 97 }
97 98
98 /// Maps `g` over pairs of mutable references to elements of `self, and elements 99 /// Maps `g` over pairs of mutable references to elements of `self, and elements
99 /// of `other` vector. 100 /// of `other` vector.
100 #[inline] 101 #[inline]
101 pub fn map2_mut(&mut self, other : &Self, g : impl Fn(&mut F, F)) { 102 pub fn map2_mut(&mut self, other: &Self, g: impl Fn(&mut F, F)) {
102 map2_mut(self, other, |u, v| g(u, *v)) 103 map2_mut(self, other, |u, v| g(u, *v))
103 } 104 }
104 105
105 /// Maps `g` over the elements of `self` and returns the product of the results. 106 /// Maps `g` over the elements of `self` and returns the product of the results.
106 #[inline] 107 #[inline]
107 pub fn product_map<A : Num>(&self, g : impl Fn(F) -> A) -> A { 108 pub fn product_map<A: Num>(&self, g: impl Fn(F) -> A) -> A {
108 match N { 109 match N {
109 1 => g(unsafe { *self.0.get_unchecked(0) }), 110 1 => g(unsafe { *self.0.get_unchecked(0) }),
110 2 => g(unsafe { *self.0.get_unchecked(0) }) * 111 2 => g(unsafe { *self.0.get_unchecked(0) }) * g(unsafe { *self.0.get_unchecked(1) }),
111 g(unsafe { *self.0.get_unchecked(1) }), 112 3 => {
112 3 => g(unsafe { *self.0.get_unchecked(0) }) * 113 g(unsafe { *self.0.get_unchecked(0) })
113 g(unsafe { *self.0.get_unchecked(1) }) * 114 * g(unsafe { *self.0.get_unchecked(1) })
114 g(unsafe { *self.0.get_unchecked(2) }), 115 * g(unsafe { *self.0.get_unchecked(2) })
115 _ => self.iter().fold(A::ONE, |m, &x| m * g(x)) 116 }
117 _ => self.iter().fold(A::ONE, |m, &x| m * g(x)),
116 } 118 }
117 } 119 }
118 } 120 }
119 121
120 /// Construct a [`Loc`]. 122 /// Construct a [`Loc`].
128 #[macro_export] 130 #[macro_export]
129 macro_rules! loc { 131 macro_rules! loc {
130 ($($x:expr),+ $(,)?) => { Loc::new([$($x),+]) } 132 ($($x:expr),+ $(,)?) => { Loc::new([$($x),+]) }
131 } 133 }
132 134
133 135 impl<F, const N: usize> From<[F; N]> for Loc<N, F> {
134 impl<F, const N : usize> From<[F; N]> for Loc<F, N> { 136 #[inline]
135 #[inline] 137 fn from(other: [F; N]) -> Loc<N, F> {
136 fn from(other: [F; N]) -> Loc<F, N> {
137 Loc(other) 138 Loc(other)
138 } 139 }
139 } 140 }
140 141
141 /*impl<F : Copy, const N : usize> From<&[F; N]> for Loc<F, N> { 142 /*impl<F : Copy, const N : usize> From<&[F; N]> for Loc<N, F> {
142 #[inline] 143 #[inline]
143 fn from(other: &[F; N]) -> Loc<F, N> { 144 fn from(other: &[F; N]) -> Loc<N, F> {
144 Loc(*other) 145 Loc(*other)
145 } 146 }
146 }*/ 147 }*/
147 148
148 impl<F> From<F> for Loc<F, 1> { 149 impl<F> From<F> for Loc<1, F> {
149 #[inline] 150 #[inline]
150 fn from(other: F) -> Loc<F, 1> { 151 fn from(other: F) -> Loc<1, F> {
151 Loc([other]) 152 Loc([other])
152 } 153 }
153 } 154 }
154 155
155 impl<F> Loc<F, 1> { 156 impl<F> Loc<1, F> {
156 #[inline] 157 #[inline]
157 pub fn flatten1d(self) -> F { 158 pub fn flatten1d(self) -> F {
158 let Loc([v]) = self; 159 let Loc([v]) = self;
159 v 160 v
160 } 161 }
161 } 162 }
162 163
163 impl<F, const N : usize> From<Loc<F, N>> for [F; N] { 164 impl<F, const N: usize> From<Loc<N, F>> for [F; N] {
164 #[inline] 165 #[inline]
165 fn from(other : Loc<F, N>) -> [F; N] { 166 fn from(other: Loc<N, F>) -> [F; N] {
166 other.0 167 other.0
167 } 168 }
168 } 169 }
169 170
170 /*impl<F : Copy, const N : usize> From<&Loc<F, N>> for [F; N] { 171 /*impl<F : Copy, const N : usize> From<&Loc<N, F>> for [F; N] {
171 #[inline] 172 #[inline]
172 fn from(other : &Loc<F, N>) -> [F; N] { 173 fn from(other : &Loc<N, F>) -> [F; N] {
173 other.0 174 other.0
174 } 175 }
175 }*/ 176 }*/
176 177
177 178 impl<F, const N: usize> IntoIterator for Loc<N, F> {
178 impl<F, const N : usize> IntoIterator for Loc<F, N> {
179 type Item = <[F; N] as IntoIterator>::Item; 179 type Item = <[F; N] as IntoIterator>::Item;
180 type IntoIter = <[F; N] as IntoIterator>::IntoIter; 180 type IntoIter = <[F; N] as IntoIterator>::IntoIter;
181 181
182 #[inline] 182 #[inline]
183 fn into_iter(self) -> Self::IntoIter { 183 fn into_iter(self) -> Self::IntoIter {
185 } 185 }
186 } 186 }
187 187
188 // Indexing 188 // Indexing
189 189
190 impl<F, Ix, const N : usize> Index<Ix> for Loc<F,N> 190 impl<F, Ix, const N: usize> Index<Ix> for Loc<N, F>
191 where [F; N] : Index<Ix> { 191 where
192 [F; N]: Index<Ix>,
193 {
192 type Output = <[F; N] as Index<Ix>>::Output; 194 type Output = <[F; N] as Index<Ix>>::Output;
193 195
194 #[inline] 196 #[inline]
195 fn index(&self, ix : Ix) -> &Self::Output { 197 fn index(&self, ix: Ix) -> &Self::Output {
196 self.0.index(ix) 198 self.0.index(ix)
197 } 199 }
198 } 200 }
199 201
200 impl<F, Ix, const N : usize> IndexMut<Ix> for Loc<F,N> 202 impl<F, Ix, const N: usize> IndexMut<Ix> for Loc<N, F>
201 where [F; N] : IndexMut<Ix> { 203 where
202 #[inline] 204 [F; N]: IndexMut<Ix>,
203 fn index_mut(&mut self, ix : Ix) -> &mut Self::Output { 205 {
206 #[inline]
207 fn index_mut(&mut self, ix: Ix) -> &mut Self::Output {
204 self.0.index_mut(ix) 208 self.0.index_mut(ix)
205 } 209 }
206 } 210 }
207 211
208 // Arithmetic 212 // Arithmetic
209 213
210 macro_rules! make_binop { 214 macro_rules! make_binop {
211 ($trait:ident, $fn:ident, $trait_assign:ident, $fn_assign:ident) => { 215 ($trait:ident, $fn:ident, $trait_assign:ident, $fn_assign:ident) => {
212 impl<F : Num, const N : usize> $trait<Loc<F,N>> for Loc<F, N> { 216 impl<F: Num, const N: usize> $trait<Loc<N, F>> for Loc<N, F> {
213 type Output = Loc<F, N>; 217 type Output = Loc<N, F>;
214 #[inline] 218 #[inline]
215 fn $fn(mut self, other : Loc<F, N>) -> Self::Output { 219 fn $fn(mut self, other: Loc<N, F>) -> Self::Output {
216 self.$fn_assign(other); 220 self.$fn_assign(other);
217 self 221 self
218 } 222 }
219 } 223 }
220 224
221 impl<'a, F : Num, const N : usize> $trait<&'a Loc<F,N>> for Loc<F, N> { 225 impl<'a, F: Num, const N: usize> $trait<&'a Loc<N, F>> for Loc<N, F> {
222 type Output = Loc<F, N>; 226 type Output = Loc<N, F>;
223 #[inline] 227 #[inline]
224 fn $fn(mut self, other : &'a Loc<F, N>) -> Self::Output { 228 fn $fn(mut self, other: &'a Loc<N, F>) -> Self::Output {
225 self.$fn_assign(other); 229 self.$fn_assign(other);
226 self 230 self
227 } 231 }
228 } 232 }
229 233
230 impl<'b, F : Num, const N : usize> $trait<Loc<F,N>> for &'b Loc<F, N> { 234 impl<'b, F: Num, const N: usize> $trait<Loc<N, F>> for &'b Loc<N, F> {
231 type Output = Loc<F, N>; 235 type Output = Loc<N, F>;
232 #[inline] 236 #[inline]
233 fn $fn(self, other : Loc<F, N>) -> Self::Output { 237 fn $fn(self, other: Loc<N, F>) -> Self::Output {
234 self.map2(&other, |a, b| a.$fn(b)) 238 self.map2(&other, |a, b| a.$fn(b))
235 } 239 }
236 } 240 }
237 241
238 impl<'a, 'b, F : Num, const N : usize> $trait<&'a Loc<F,N>> for &'b Loc<F, N> { 242 impl<'a, 'b, F: Num, const N: usize> $trait<&'a Loc<N, F>> for &'b Loc<N, F> {
239 type Output = Loc<F, N>; 243 type Output = Loc<N, F>;
240 #[inline] 244 #[inline]
241 fn $fn(self, other : &'a Loc<F, N>) -> Self::Output { 245 fn $fn(self, other: &'a Loc<N, F>) -> Self::Output {
242 self.map2(other, |a, b| a.$fn(b)) 246 self.map2(other, |a, b| a.$fn(b))
243 } 247 }
244 } 248 }
245 249
246 impl<F : Num, const N : usize> $trait_assign<Loc<F,N>> for Loc<F, N> { 250 impl<F: Num, const N: usize> $trait_assign<Loc<N, F>> for Loc<N, F> {
247 #[inline] 251 #[inline]
248 fn $fn_assign(&mut self, other : Loc<F, N>) { 252 fn $fn_assign(&mut self, other: Loc<N, F>) {
249 self.map2_mut(&other, |a, b| a.$fn_assign(b)) 253 self.map2_mut(&other, |a, b| a.$fn_assign(b))
250 } 254 }
251 } 255 }
252 256
253 impl<'a, F : Num, const N : usize> $trait_assign<&'a Loc<F,N>> for Loc<F, N> { 257 impl<'a, F: Num, const N: usize> $trait_assign<&'a Loc<N, F>> for Loc<N, F> {
254 #[inline] 258 #[inline]
255 fn $fn_assign(&mut self, other : &'a Loc<F, N>) { 259 fn $fn_assign(&mut self, other: &'a Loc<N, F>) {
256 self.map2_mut(other, |a, b| a.$fn_assign(b)) 260 self.map2_mut(other, |a, b| a.$fn_assign(b))
257 } 261 }
258 } 262 }
259 } 263 };
260 } 264 }
261 265
262 make_binop!(Add, add, AddAssign, add_assign); 266 make_binop!(Add, add, AddAssign, add_assign);
263 make_binop!(Sub, sub, SubAssign, sub_assign); 267 make_binop!(Sub, sub, SubAssign, sub_assign);
264 268
265 impl<F : Float, const N : usize> std::iter::Sum for Loc<F, N> { 269 impl<F: Float, const N: usize> std::iter::Sum for Loc<N, F> {
266 fn sum<I: Iterator<Item = Loc<F, N>>>(mut iter: I) -> Self { 270 fn sum<I: Iterator<Item = Loc<N, F>>>(mut iter: I) -> Self {
267 match iter.next() { 271 match iter.next() {
268 None => Self::ORIGIN, 272 None => Self::ORIGIN,
269 Some(mut v) => { 273 Some(mut v) => {
270 for w in iter { 274 for w in iter {
271 v += w 275 v += w
276 } 280 }
277 } 281 }
278 282
279 macro_rules! make_scalarop_rhs { 283 macro_rules! make_scalarop_rhs {
280 ($trait:ident, $fn:ident, $trait_assign:ident, $fn_assign:ident) => { 284 ($trait:ident, $fn:ident, $trait_assign:ident, $fn_assign:ident) => {
281 impl<F : Num, const N : usize> $trait<F> for Loc<F, N> { 285 impl<F: Num, const N: usize> $trait<F> for Loc<N, F> {
282 type Output = Loc<F, N>; 286 type Output = Loc<N, F>;
283 #[inline] 287 #[inline]
284 fn $fn(self, b : F) -> Self::Output { 288 fn $fn(self, b: F) -> Self::Output {
285 self.map(|a| a.$fn(b)) 289 self.map(|a| a.$fn(b))
286 } 290 }
287 } 291 }
288 292
289 impl<'a, F : Num, const N : usize> $trait<&'a F> for Loc<F, N> { 293 impl<'a, F: Num, const N: usize> $trait<&'a F> for Loc<N, F> {
290 type Output = Loc<F, N>; 294 type Output = Loc<N, F>;
291 #[inline] 295 #[inline]
292 fn $fn(self, b : &'a F) -> Self::Output { 296 fn $fn(self, b: &'a F) -> Self::Output {
293 self.map(|a| a.$fn(*b)) 297 self.map(|a| a.$fn(*b))
294 } 298 }
295 } 299 }
296 300
297 impl<'b, F : Num, const N : usize> $trait<F> for &'b Loc<F, N> { 301 impl<'b, F: Num, const N: usize> $trait<F> for &'b Loc<N, F> {
298 type Output = Loc<F, N>; 302 type Output = Loc<N, F>;
299 #[inline] 303 #[inline]
300 fn $fn(self, b : F) -> Self::Output { 304 fn $fn(self, b: F) -> Self::Output {
301 self.map(|a| a.$fn(b)) 305 self.map(|a| a.$fn(b))
302 } 306 }
303 } 307 }
304 308
305 impl<'a, 'b, F : Float, const N : usize> $trait<&'a F> for &'b Loc<F, N> { 309 impl<'a, 'b, F: Float, const N: usize> $trait<&'a F> for &'b Loc<N, F> {
306 type Output = Loc<F, N>; 310 type Output = Loc<N, F>;
307 #[inline] 311 #[inline]
308 fn $fn(self, b : &'a F) -> Self::Output { 312 fn $fn(self, b: &'a F) -> Self::Output {
309 self.map(|a| a.$fn(*b)) 313 self.map(|a| a.$fn(*b))
310 } 314 }
311 } 315 }
312 316
313 impl<F : Num, const N : usize> $trait_assign<F> for Loc<F, N> { 317 impl<F: Num, const N: usize> $trait_assign<F> for Loc<N, F> {
314 #[inline] 318 #[inline]
315 fn $fn_assign(&mut self, b : F) { 319 fn $fn_assign(&mut self, b: F) {
316 self.map_mut(|a| a.$fn_assign(b)); 320 self.map_mut(|a| a.$fn_assign(b));
317 } 321 }
318 } 322 }
319 323
320 impl<'a, F : Num, const N : usize> $trait_assign<&'a F> for Loc<F, N> { 324 impl<'a, F: Num, const N: usize> $trait_assign<&'a F> for Loc<N, F> {
321 #[inline] 325 #[inline]
322 fn $fn_assign(&mut self, b : &'a F) { 326 fn $fn_assign(&mut self, b: &'a F) {
323 self.map_mut(|a| a.$fn_assign(*b)); 327 self.map_mut(|a| a.$fn_assign(*b));
324 } 328 }
325 } 329 }
326 } 330 };
327 } 331 }
328
329 332
330 make_scalarop_rhs!(Mul, mul, MulAssign, mul_assign); 333 make_scalarop_rhs!(Mul, mul, MulAssign, mul_assign);
331 make_scalarop_rhs!(Div, div, DivAssign, div_assign); 334 make_scalarop_rhs!(Div, div, DivAssign, div_assign);
332 335
333 macro_rules! make_unaryop { 336 macro_rules! make_unaryop {
334 ($trait:ident, $fn:ident) => { 337 ($trait:ident, $fn:ident) => {
335 impl<F : SignedNum, const N : usize> $trait for Loc<F, N> { 338 impl<F: SignedNum, const N: usize> $trait for Loc<N, F> {
336 type Output = Loc<F, N>; 339 type Output = Loc<N, F>;
337 #[inline] 340 #[inline]
338 fn $fn(mut self) -> Self::Output { 341 fn $fn(mut self) -> Self::Output {
339 self.map_mut(|a| *a = (*a).$fn()); 342 self.map_mut(|a| *a = (*a).$fn());
340 self 343 self
341 } 344 }
342 } 345 }
343 346
344 impl<'a, F : SignedNum, const N : usize> $trait for &'a Loc<F, N> { 347 impl<'a, F: SignedNum, const N: usize> $trait for &'a Loc<N, F> {
345 type Output = Loc<F, N>; 348 type Output = Loc<N, F>;
346 #[inline] 349 #[inline]
347 fn $fn(self) -> Self::Output { 350 fn $fn(self) -> Self::Output {
348 self.map(|a| a.$fn()) 351 self.map(|a| a.$fn())
349 } 352 }
350 } 353 }
351 } 354 };
352 } 355 }
353 356
354 make_unaryop!(Neg, neg); 357 make_unaryop!(Neg, neg);
355 358
356 macro_rules! make_scalarop_lhs { 359 macro_rules! make_scalarop_lhs {
357 ($trait:ident, $fn:ident; $($f:ident)+) => { $( 360 ($trait:ident, $fn:ident; $($f:ident)+) => { $(
358 impl<const N : usize> $trait<Loc<$f,N>> for $f { 361 impl<const N : usize> $trait<Loc<N, $f>> for $f {
359 type Output = Loc<$f, N>; 362 type Output = Loc<N, $f>;
360 #[inline] 363 #[inline]
361 fn $fn(self, v : Loc<$f,N>) -> Self::Output { 364 fn $fn(self, v : Loc<N, $f>) -> Self::Output {
362 v.map(|b| self.$fn(b)) 365 v.map(|b| self.$fn(b))
363 } 366 }
364 } 367 }
365 368
366 impl<'a, const N : usize> $trait<&'a Loc<$f,N>> for $f { 369 impl<'a, const N : usize> $trait<&'a Loc<N, $f>> for $f {
367 type Output = Loc<$f, N>; 370 type Output = Loc<N, $f>;
368 #[inline] 371 #[inline]
369 fn $fn(self, v : &'a Loc<$f,N>) -> Self::Output { 372 fn $fn(self, v : &'a Loc<N, $f>) -> Self::Output {
370 v.map(|b| self.$fn(b)) 373 v.map(|b| self.$fn(b))
371 } 374 }
372 } 375 }
373 376
374 impl<'b, const N : usize> $trait<Loc<$f,N>> for &'b $f { 377 impl<'b, const N : usize> $trait<Loc<N, $f>> for &'b $f {
375 type Output = Loc<$f, N>; 378 type Output = Loc<N, $f>;
376 #[inline] 379 #[inline]
377 fn $fn(self, v : Loc<$f,N>) -> Self::Output { 380 fn $fn(self, v : Loc<N, $f>) -> Self::Output {
378 v.map(|b| self.$fn(b)) 381 v.map(|b| self.$fn(b))
379 } 382 }
380 } 383 }
381 384
382 impl<'a, 'b, const N : usize> $trait<&'a Loc<$f,N>> for &'b $f { 385 impl<'a, 'b, const N : usize> $trait<&'a Loc<N, $f>> for &'b $f {
383 type Output = Loc<$f, N>; 386 type Output = Loc<N, $f>;
384 #[inline] 387 #[inline]
385 fn $fn(self, v : &'a Loc<$f, N>) -> Self::Output { 388 fn $fn(self, v : &'a Loc<N, $f>) -> Self::Output {
386 v.map(|b| self.$fn(b)) 389 v.map(|b| self.$fn(b))
387 } 390 }
388 } 391 }
389 )+ } 392 )+ }
390 } 393 }
394 397
395 // Norms 398 // Norms
396 399
397 macro_rules! domination { 400 macro_rules! domination {
398 ($norm:ident, $dominates:ident) => { 401 ($norm:ident, $dominates:ident) => {
399 impl<F : Float, const N : usize> Dominated<F, $dominates, Loc<F, N>> for $norm { 402 impl<F: Float, const N: usize> Dominated<F, $dominates, Loc<N, F>> for $norm {
400 #[inline] 403 #[inline]
401 fn norm_factor(&self, _p : $dominates) -> F { 404 fn norm_factor(&self, _p: $dominates) -> F {
402 F::ONE 405 F::ONE
403 } 406 }
404 #[inline] 407 #[inline]
405 fn from_norm(&self, p_norm : F, _p : $dominates) -> F { 408 fn from_norm(&self, p_norm: F, _p: $dominates) -> F {
406 p_norm 409 p_norm
407 } 410 }
408 } 411 }
409 }; 412 };
410 ($norm:ident, $dominates:ident, $fn:path) => { 413 ($norm:ident, $dominates:ident, $fn:path) => {
411 impl<F : Float, const N : usize> Dominated<F, $dominates, Loc<F, N>> for $norm { 414 impl<F: Float, const N: usize> Dominated<F, $dominates, Loc<N, F>> for $norm {
412 #[inline] 415 #[inline]
413 fn norm_factor(&self, _p : $dominates) -> F { 416 fn norm_factor(&self, _p: $dominates) -> F {
414 $fn(F::cast_from(N)) 417 $fn(F::cast_from(N))
415 } 418 }
416 } 419 }
417 }; 420 };
418 } 421 }
427 430
428 domination!(Linfinity, L1); 431 domination!(Linfinity, L1);
429 domination!(Linfinity, L2); 432 domination!(Linfinity, L2);
430 domination!(L2, L1); 433 domination!(L2, L1);
431 434
432 impl<F : Float,const N : usize> Euclidean<F> for Loc<F, N> { 435 impl<F: Float, const N: usize> Euclidean<F> for Loc<N, F> {
433 type Output = Self; 436 type Output = Self;
434 437
435 /// This implementation is not stabilised as it's meant to be used for very small vectors. 438 /// This implementation is not stabilised as it's meant to be used for very small vectors.
436 /// Use [`nalgebra`] for larger vectors. 439 /// Use [`nalgebra`] for larger vectors.
437 #[inline] 440 #[inline]
438 fn dot<I : Instance<Self>>(&self, other : I) -> F { 441 fn dot<I: Instance<Self>>(&self, other: I) -> F {
439 self.0.iter() 442 self.0
440 .zip(other.ref_instance().0.iter()) 443 .iter()
441 .fold(F::ZERO, |m, (&v, &w)| m + v * w) 444 .zip(other.ref_instance().0.iter())
445 .fold(F::ZERO, |m, (&v, &w)| m + v * w)
442 } 446 }
443 447
444 /// This implementation is not stabilised as it's meant to be used for very small vectors. 448 /// This implementation is not stabilised as it's meant to be used for very small vectors.
445 /// Use [`nalgebra`] for larger vectors. 449 /// Use [`nalgebra`] for larger vectors.
446 #[inline] 450 #[inline]
447 fn norm2_squared(&self) -> F { 451 fn norm2_squared(&self) -> F {
448 self.iter().fold(F::ZERO, |m, &v| m + v * v) 452 self.iter().fold(F::ZERO, |m, &v| m + v * v)
449 } 453 }
450 454
451 fn dist2_squared<I : Instance<Self>>(&self, other : I) -> F { 455 fn dist2_squared<I: Instance<Self>>(&self, other: I) -> F {
452 self.iter() 456 self.iter()
453 .zip(other.ref_instance().iter()) 457 .zip(other.ref_instance().iter())
454 .fold(F::ZERO, |m, (&v, &w)| { let d = v - w; m + d * d }) 458 .fold(F::ZERO, |m, (&v, &w)| {
459 let d = v - w;
460 m + d * d
461 })
455 } 462 }
456 463
457 #[inline] 464 #[inline]
458 fn norm2(&self) -> F { 465 fn norm2(&self) -> F {
459 // Optimisation for N==1 that avoids squaring and square rooting. 466 // Optimisation for N==1 that avoids squaring and square rooting.
460 if N==1 { 467 if N == 1 {
461 unsafe { self.0.get_unchecked(0) }.abs() 468 unsafe { self.0.get_unchecked(0) }.abs()
462 } else { 469 } else {
463 self.norm2_squared().sqrt() 470 self.norm2_squared().sqrt()
464 } 471 }
465 } 472 }
466 473
467 #[inline] 474 #[inline]
468 fn dist2<I : Instance<Self>>(&self, other : I) -> F { 475 fn dist2<I: Instance<Self>>(&self, other: I) -> F {
469 // Optimisation for N==1 that avoids squaring and square rooting. 476 // Optimisation for N==1 that avoids squaring and square rooting.
470 let otherr = other.ref_instance(); 477 let otherr = other.ref_instance();
471 if N==1 { 478 if N == 1 {
472 unsafe { *self.0.get_unchecked(0) - *otherr.0.get_unchecked(0) }.abs() 479 unsafe { *self.0.get_unchecked(0) - *otherr.0.get_unchecked(0) }.abs()
473 } else { 480 } else {
474 self.dist2_squared(other).sqrt() 481 self.dist2_squared(other).sqrt()
475 } 482 }
476 } 483 }
477 } 484 }
478 485
479 impl<F : Num, const N : usize> Loc<F, N> { 486 impl<F: Num, const N: usize> Loc<N, F> {
480 /// Origin point 487 /// Origin point
481 pub const ORIGIN : Self = Loc([F::ZERO; N]); 488 pub const ORIGIN: Self = Loc([F::ZERO; N]);
482 } 489 }
483 490
484 impl<F : Num + std::ops::Neg<Output=F>, const N : usize> Loc<F, N> { 491 impl<F: Num + std::ops::Neg<Output = F>, const N: usize> Loc<N, F> {
485 /// Reflects along the given coordinate 492 /// Reflects along the given coordinate
486 pub fn reflect(mut self, i : usize) -> Self { 493 pub fn reflect(mut self, i: usize) -> Self {
487 self[i] = -self[i]; 494 self[i] = -self[i];
488 self 495 self
489 } 496 }
490 497
491 /// Reflects along the given coordinate sequences 498 /// Reflects along the given coordinate sequences
492 pub fn reflect_many<I : IntoIterator<Item=usize>>(mut self, idxs : I) -> Self { 499 pub fn reflect_many<I: IntoIterator<Item = usize>>(mut self, idxs: I) -> Self {
493 for i in idxs { 500 for i in idxs {
494 self[i]=-self[i] 501 self[i] = -self[i]
495 } 502 }
496 self 503 self
497 } 504 }
498 } 505 }
499 506
500 impl<F : std::ops::Neg<Output=F>> Loc<F, 2> { 507 impl<F: std::ops::Neg<Output = F>> Loc<2, F> {
501 /// Reflect x coordinate 508 /// Reflect x coordinate
502 pub fn reflect_x(self) -> Self { 509 pub fn reflect_x(self) -> Self {
503 let Loc([x, y]) = self; 510 let Loc([x, y]) = self;
504 [-x, y].into() 511 [-x, y].into()
505 } 512 }
509 let Loc([x, y]) = self; 516 let Loc([x, y]) = self;
510 [x, -y].into() 517 [x, -y].into()
511 } 518 }
512 } 519 }
513 520
514 impl<F : Float> Loc<F, 2> { 521 impl<F: Float> Loc<2, F> {
515 /// Rotate by angle φ 522 /// Rotate by angle φ
516 pub fn rotate(self, φ : F) -> Self { 523 pub fn rotate(self, φ: F) -> Self {
517 let Loc([x, y]) = self; 524 let Loc([x, y]) = self;
518 let sin_φ = φ.sin(); 525 let sin_φ = φ.sin();
519 let cos_φ = φ.cos(); 526 let cos_φ = φ.cos();
520 [cos_φ * x - sin_φ * y, 527 [cos_φ * x - sin_φ * y, sin_φ * x + cos_φ * y].into()
521 sin_φ * x + cos_φ * y].into() 528 }
522 } 529 }
523 } 530
524 531 impl<F: std::ops::Neg<Output = F>> Loc<3, F> {
525 impl<F : std::ops::Neg<Output=F>> Loc<F, 3> {
526 /// Reflect x coordinate 532 /// Reflect x coordinate
527 pub fn reflect_x(self) -> Self { 533 pub fn reflect_x(self) -> Self {
528 let Loc([x, y, z]) = self; 534 let Loc([x, y, z]) = self;
529 [-x, y, z].into() 535 [-x, y, z].into()
530 } 536 }
540 let Loc([x, y, z]) = self; 546 let Loc([x, y, z]) = self;
541 [x, y, -z].into() 547 [x, y, -z].into()
542 } 548 }
543 } 549 }
544 550
545 impl<F : Float> Loc<F, 3> { 551 impl<F: Float> Loc<3, F> {
546 /// Rotate by angles (yaw, pitch, roll) 552 /// Rotate by angles (yaw, pitch, roll)
547 pub fn rotate(self, Loc([φ, ψ, θ]) : Self) -> Self { 553 pub fn rotate(self, Loc([φ, ψ, θ]): Self) -> Self {
548 let Loc([mut x, mut y, mut z]) = self; 554 let Loc([mut x, mut y, mut z]) = self;
549 let sin_φ = φ.sin(); 555 let sin_φ = φ.sin();
550 let cos_φ = φ.cos(); 556 let cos_φ = φ.cos();
551 [x, y, z] = [cos_φ * x - sin_φ *y, 557 [x, y, z] = [cos_φ * x - sin_φ * y, sin_φ * x + cos_φ * y, z];
552 sin_φ * x + cos_φ * y,
553 z];
554 let sin_ψ = ψ.sin(); 558 let sin_ψ = ψ.sin();
555 let cos_ψ = ψ.cos(); 559 let cos_ψ = ψ.cos();
556 [x, y, z] = [cos_ψ * x + sin_ψ * z, 560 [x, y, z] = [cos_ψ * x + sin_ψ * z, y, -sin_ψ * x + cos_ψ * z];
557 y,
558 -sin_ψ * x + cos_ψ * z];
559 let sin_θ = θ.sin(); 561 let sin_θ = θ.sin();
560 let cos_θ = θ.cos(); 562 let cos_θ = θ.cos();
561 [x, y, z] = [x, 563 [x, y, z] = [x, cos_θ * y - sin_θ * z, sin_θ * y + cos_θ * z];
562 cos_θ * y - sin_θ * z,
563 sin_θ * y + cos_θ * z];
564 [x, y, z].into() 564 [x, y, z].into()
565 } 565 }
566 } 566 }
567 567
568 impl<F : Float,const N : usize> StaticEuclidean<F> for Loc<F, N> { 568 impl<F: Float, const N: usize> StaticEuclidean<F> for Loc<N, F> {
569 #[inline] 569 #[inline]
570 fn origin() -> Self { 570 fn origin() -> Self {
571 Self::ORIGIN 571 Self::ORIGIN
572 } 572 }
573 } 573 }
574 574
575
576 /// The default norm for `Loc` is [`L2`]. 575 /// The default norm for `Loc` is [`L2`].
577 impl<F : Float, const N : usize> Normed<F> for Loc<F, N> { 576 impl<F: Float, const N: usize> Normed<F> for Loc<N, F> {
578 type NormExp = L2; 577 type NormExp = L2;
579 578
580 #[inline] 579 #[inline]
581 fn norm_exponent(&self) -> Self::NormExp { 580 fn norm_exponent(&self) -> Self::NormExp {
582 L2 581 L2
591 fn is_zero(&self) -> bool { 590 fn is_zero(&self) -> bool {
592 self.norm2_squared() == F::ZERO 591 self.norm2_squared() == F::ZERO
593 } 592 }
594 } 593 }
595 594
596 impl<F : Float, const N : usize> HasDual<F> for Loc<F, N> { 595 impl<F: Float, const N: usize> HasDual<F> for Loc<N, F> {
597 type DualSpace = Self; 596 type DualSpace = Self;
598 } 597 }
599 598
600 impl<F : Float, const N : usize> Norm<F, L2> for Loc<F, N> { 599 impl<F: Float, const N: usize> Norm<L2, F> for Loc<N, F> {
601 #[inline] 600 #[inline]
602 fn norm(&self, _ : L2) -> F { self.norm2() } 601 fn norm(&self, _: L2) -> F {
603 } 602 self.norm2()
604 603 }
605 impl<F : Float, const N : usize> Dist<F, L2> for Loc<F, N> { 604 }
606 #[inline] 605
607 fn dist<I : Instance<Self>>(&self, other : I, _ : L2) -> F { self.dist2(other) } 606 impl<F: Float, const N: usize> Dist<F, L2> for Loc<N, F> {
607 #[inline]
608 fn dist<I: Instance<Self>>(&self, other: I, _: L2) -> F {
609 self.dist2(other)
610 }
608 } 611 }
609 612
610 /* Implemented automatically as Euclidean. 613 /* Implemented automatically as Euclidean.
611 impl<F : Float, const N : usize> Projection<F, L2> for Loc<F, N> { 614 impl<F : Float, const N : usize> Projection<F, L2> for Loc<N, F> {
612 #[inline] 615 #[inline]
613 fn proj_ball_mut(&mut self, ρ : F, nrm : L2) { 616 fn proj_ball_mut(&mut self, ρ : F, nrm : L2) {
614 let n = self.norm(nrm); 617 let n = self.norm(nrm);
615 if n > ρ { 618 if n > ρ {
616 *self *= ρ/n; 619 *self *= ρ/n;
617 } 620 }
618 } 621 }
619 }*/ 622 }*/
620 623
621 impl<F : Float, const N : usize> Norm<F, L1> for Loc<F, N> { 624 impl<F: Float, const N: usize> Norm<L1, F> for Loc<N, F> {
622 /// This implementation is not stabilised as it's meant to be used for very small vectors. 625 /// This implementation is not stabilised as it's meant to be used for very small vectors.
623 /// Use [`nalgebra`] for larger vectors. 626 /// Use [`nalgebra`] for larger vectors.
624 #[inline] 627 #[inline]
625 fn norm(&self, _ : L1) -> F { 628 fn norm(&self, _: L1) -> F {
626 self.iter().fold(F::ZERO, |m, v| m + v.abs()) 629 self.iter().fold(F::ZERO, |m, v| m + v.abs())
627 } 630 }
628 } 631 }
629 632
630 impl<F : Float, const N : usize> Dist<F, L1> for Loc<F, N> { 633 impl<F: Float, const N: usize> Dist<F, L1> for Loc<N, F> {
631 #[inline] 634 #[inline]
632 fn dist<I : Instance<Self>>(&self, other : I, _ : L1) -> F { 635 fn dist<I: Instance<Self>>(&self, other: I, _: L1) -> F {
633 self.iter() 636 self.iter()
634 .zip(other.ref_instance().iter()) 637 .zip(other.ref_instance().iter())
635 .fold(F::ZERO, |m, (&v, &w)| m + (v-w).abs() ) 638 .fold(F::ZERO, |m, (&v, &w)| m + (v - w).abs())
636 } 639 }
637 } 640 }
638 641
639 impl<F : Float, const N : usize> Projection<F, Linfinity> for Loc<F, N> { 642 impl<F: Float, const N: usize> Projection<F, Linfinity> for Loc<N, F> {
640 #[inline] 643 #[inline]
641 fn proj_ball_mut(&mut self, ρ : F, _ : Linfinity) { 644 fn proj_ball_mut(&mut self, ρ: F, _: Linfinity) {
642 self.iter_mut().for_each(|v| *v = num_traits::clamp(*v, -ρ, ρ)) 645 self.iter_mut()
643 } 646 .for_each(|v| *v = num_traits::clamp(*v, -ρ, ρ))
644 } 647 }
645 648 }
646 impl<F : Float, const N : usize> Norm<F, Linfinity> for Loc<F, N> { 649
650 impl<F: Float, const N: usize> Norm<Linfinity, F> for Loc<N, F> {
647 /// This implementation is not stabilised as it's meant to be used for very small vectors. 651 /// This implementation is not stabilised as it's meant to be used for very small vectors.
648 /// Use [`nalgebra`] for larger vectors. 652 /// Use [`nalgebra`] for larger vectors.
649 #[inline] 653 #[inline]
650 fn norm(&self, _ : Linfinity) -> F { 654 fn norm(&self, _: Linfinity) -> F {
651 self.iter().fold(F::ZERO, |m, v| m.max(v.abs())) 655 self.iter().fold(F::ZERO, |m, v| m.max(v.abs()))
652 } 656 }
653 } 657 }
654 658
655 impl<F : Float, const N : usize> Dist<F, Linfinity> for Loc<F, N> { 659 impl<F: Float, const N: usize> Dist<F, Linfinity> for Loc<N, F> {
656 #[inline] 660 #[inline]
657 fn dist<I : Instance<Self>>(&self, other : I, _ : Linfinity) -> F { 661 fn dist<I: Instance<Self>>(&self, other: I, _: Linfinity) -> F {
658 self.iter() 662 self.iter()
659 .zip(other.ref_instance().iter()) 663 .zip(other.ref_instance().iter())
660 .fold(F::ZERO, |m, (&v, &w)| m.max((v-w).abs())) 664 .fold(F::ZERO, |m, (&v, &w)| m.max((v - w).abs()))
661 } 665 }
662 } 666 }
663
664 667
665 // Misc. 668 // Misc.
666 669
667 impl<A, const N : usize> FixedLength<N> for Loc<A,N> { 670 impl<A, const N: usize> FixedLength<N> for Loc<N, A> {
668 type Iter = std::array::IntoIter<A, N>; 671 type Iter = std::array::IntoIter<A, N>;
669 type Elem = A; 672 type Elem = A;
670 #[inline] 673 #[inline]
671 fn fl_iter(self) -> Self::Iter { 674 fn fl_iter(self) -> Self::Iter {
672 self.into_iter() 675 self.into_iter()
673 } 676 }
674 } 677 }
675 678
676 impl<A, const N : usize> FixedLengthMut<N> for Loc<A,N> { 679 impl<A, const N: usize> FixedLengthMut<N> for Loc<N, A> {
677 type IterMut<'a> = std::slice::IterMut<'a, A> where A : 'a; 680 type IterMut<'a>
681 = std::slice::IterMut<'a, A>
682 where
683 A: 'a;
678 #[inline] 684 #[inline]
679 fn fl_iter_mut(&mut self) -> Self::IterMut<'_> { 685 fn fl_iter_mut(&mut self) -> Self::IterMut<'_> {
680 self.iter_mut() 686 self.iter_mut()
681 } 687 }
682 } 688 }
683 689
684 impl<'a, A, const N : usize> FixedLength<N> for &'a Loc<A,N> { 690 impl<'a, A, const N: usize> FixedLength<N> for &'a Loc<N, A> {
685 type Iter = std::slice::Iter<'a, A>; 691 type Iter = std::slice::Iter<'a, A>;
686 type Elem = &'a A; 692 type Elem = &'a A;
687 #[inline] 693 #[inline]
688 fn fl_iter(self) -> Self::Iter { 694 fn fl_iter(self) -> Self::Iter {
689 self.iter() 695 self.iter()
690 } 696 }
691 } 697 }
692 698
693 699 impl<F: Num, const N: usize> Space for Loc<N, F> {
694 impl<F : Num, const N : usize> Space for Loc<F, N> {
695 type Decomp = BasicDecomposition; 700 type Decomp = BasicDecomposition;
696 } 701 }
697 702
698 impl<F : Float, const N : usize> Mapping<Loc<F, N>> for Loc<F, N> { 703 impl<F: Float, const N: usize> Mapping<Loc<N, F>> for Loc<N, F> {
699 type Codomain = F; 704 type Codomain = F;
700 705
701 fn apply<I : Instance<Loc<F, N>>>(&self, x : I) -> Self::Codomain { 706 fn apply<I: Instance<Loc<N, F>>>(&self, x: I) -> Self::Codomain {
702 x.eval(|x̃| self.dot(x̃)) 707 x.eval(|x̃| self.dot(x̃))
703 } 708 }
704 } 709 }
705 710
706 impl<F : Float, const N : usize> Linear<Loc<F, N>> for Loc<F, N> { } 711 impl<F: Float, const N: usize> Linear<Loc<N, F>> for Loc<N, F> {}
707 712
708 impl<F : Float, const N : usize> AXPY<F, Loc<F, N>> for Loc<F, N> { 713 impl<F: Float, const N: usize> AXPY<F, Loc<N, F>> for Loc<N, F> {
709 type Owned = Self; 714 type Owned = Self;
710 715
711 #[inline] 716 #[inline]
712 fn axpy<I : Instance<Loc<F, N>>>(&mut self, α : F, x : I, β : F) { 717 fn axpy<I: Instance<Loc<N, F>>>(&mut self, α: F, x: I, β: F) {
713 x.eval(|x̃| { 718 x.eval(|x̃| {
714 if β == F::ZERO { 719 if β == F::ZERO {
715 map2_mut(self, x̃, |yi, xi| { *yi = α * (*xi) }) 720 map2_mut(self, x̃, |yi, xi| *yi = α * (*xi))
716 } else { 721 } else {
717 map2_mut(self, x̃, |yi, xi| { *yi = β * (*yi) + α * (*xi) }) 722 map2_mut(self, x̃, |yi, xi| *yi = β * (*yi) + α * (*xi))
718 } 723 }
719 }) 724 })
720 } 725 }
721 726
722 #[inline] 727 #[inline]
723 fn copy_from<I : Instance<Loc<F, N>>>(&mut self, x : I) { 728 fn copy_from<I: Instance<Loc<N, F>>>(&mut self, x: I) {
724 x.eval(|x̃| map2_mut(self, x̃, |yi, xi| *yi = *xi )) 729 x.eval(|x̃| map2_mut(self, x̃, |yi, xi| *yi = *xi))
725 } 730 }
726 731
727 #[inline] 732 #[inline]
728 fn similar_origin(&self) -> Self::Owned { 733 fn similar_origin(&self) -> Self::Owned {
729 Self::ORIGIN 734 Self::ORIGIN
732 #[inline] 737 #[inline]
733 fn set_zero(&mut self) { 738 fn set_zero(&mut self) {
734 *self = Self::ORIGIN; 739 *self = Self::ORIGIN;
735 } 740 }
736 } 741 }
737

mercurial