| 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 |
| 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 } |
| 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 } |
| 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 |