| 4 TODO: This could be easily much more generic if `derive_more` could derive arithmetic |
4 TODO: This could be easily much more generic if `derive_more` could derive arithmetic |
| 5 operations on references. |
5 operations on references. |
| 6 */ |
6 */ |
| 7 |
7 |
| 8 use crate::euclidean::Euclidean; |
8 use crate::euclidean::Euclidean; |
| 9 use crate::instance::{Decomposition, DecompositionMut, Instance, InstanceMut, MyCow}; |
9 use crate::instance::{ |
| 10 use crate::linops::AXPY; |
10 ClosedSpace, Decomposition, DecompositionMut, Instance, InstanceMut, MyCow, Ownable, |
| |
11 }; |
| |
12 use crate::linops::{VectorSpace, AXPY}; |
| 11 use crate::loc::Loc; |
13 use crate::loc::Loc; |
| 12 use crate::mapping::Space; |
14 use crate::mapping::Space; |
| 13 use crate::norms::{HasDual, Norm, NormExponent, Normed, PairNorm, L2}; |
15 use crate::norms::{HasDual, Norm, NormExponent, Normed, PairNorm, L2}; |
| 14 use crate::types::{Float, Num}; |
16 use crate::types::{Float, Num}; |
| 15 use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; |
17 use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; |
| 260 } |
262 } |
| 261 |
263 |
| 262 impl_scalar_mut!(MulAssign, mul_assign); |
264 impl_scalar_mut!(MulAssign, mul_assign); |
| 263 impl_scalar_mut!(DivAssign, div_assign); |
265 impl_scalar_mut!(DivAssign, div_assign); |
| 264 |
266 |
| |
267 /// Trait for ownable-by-consumption objects |
| |
268 impl<A, B> Ownable for Pair<A, B> |
| |
269 where |
| |
270 A: Ownable, |
| |
271 B: Ownable, |
| |
272 { |
| |
273 type OwnedVariant = Pair<A::OwnedVariant, B::OwnedVariant>; |
| |
274 |
| |
275 #[inline] |
| |
276 fn into_owned(self) -> Self::OwnedVariant { |
| |
277 Pair(self.0.into_owned(), self.1.into_owned()) |
| |
278 } |
| |
279 |
| |
280 /// Returns an owned instance of a reference. |
| |
281 fn clone_owned(&self) -> Self::OwnedVariant { |
| |
282 Pair(self.0.clone_owned(), self.1.clone_owned()) |
| |
283 } |
| |
284 } |
| |
285 |
| 265 /// We only support 'closed' `Euclidean` `Pair`s, as more general ones cause |
286 /// We only support 'closed' `Euclidean` `Pair`s, as more general ones cause |
| 266 /// compiler overflows. |
287 /// compiler overflows. |
| 267 impl<A, B, F: Float> Euclidean<F> for Pair<A, B> |
288 impl<A, B, F: Float> Euclidean<F> for Pair<A, B> |
| 268 where |
289 where |
| 269 A: Euclidean<F>, |
290 A: Euclidean<F>, |
| 270 B: Euclidean<F>, |
291 B: Euclidean<F>, |
| 271 //Pair<A, B>: Euclidean<F>, |
292 //Pair<A, B>: Euclidean<F>, |
| 272 Self: Sized |
293 Self: Sized |
| 273 + Mul<F, Output = <Self as AXPY>::Owned> |
294 + Mul<F, Output = <Self as VectorSpace>::Owned> |
| 274 + MulAssign<F> |
295 + MulAssign<F> |
| 275 + Div<F, Output = <Self as AXPY>::Owned> |
296 + Div<F, Output = <Self as VectorSpace>::Owned> |
| 276 + DivAssign<F> |
297 + DivAssign<F> |
| 277 + Add<Self, Output = <Self as AXPY>::Owned> |
298 + Add<Self, Output = <Self as VectorSpace>::Owned> |
| 278 + Sub<Self, Output = <Self as AXPY>::Owned> |
299 + Sub<Self, Output = <Self as VectorSpace>::Owned> |
| 279 + for<'b> Add<&'b Self, Output = <Self as AXPY>::Owned> |
300 + for<'b> Add<&'b Self, Output = <Self as VectorSpace>::Owned> |
| 280 + for<'b> Sub<&'b Self, Output = <Self as AXPY>::Owned> |
301 + for<'b> Sub<&'b Self, Output = <Self as VectorSpace>::Owned> |
| 281 + AddAssign<Self> |
302 + AddAssign<Self> |
| 282 + for<'b> AddAssign<&'b Self> |
303 + for<'b> AddAssign<&'b Self> |
| 283 + SubAssign<Self> |
304 + SubAssign<Self> |
| 284 + for<'b> SubAssign<&'b Self> |
305 + for<'b> SubAssign<&'b Self> |
| 285 + Neg<Output = <Self as AXPY>::Owned>, |
306 + Neg<Output = <Self as VectorSpace>::Owned>, |
| 286 { |
307 { |
| 287 fn dot<I: Instance<Self>>(&self, other: I) -> F { |
308 fn dot<I: Instance<Self>>(&self, other: I) -> F { |
| 288 other.eval_decompose(|Pair(u, v)| self.0.dot(u) + self.1.dot(v)) |
309 other.eval_decompose(|Pair(u, v)| self.0.dot(u) + self.1.dot(v)) |
| 289 } |
310 } |
| 290 |
311 |
| 293 } |
314 } |
| 294 |
315 |
| 295 fn dist2_squared<I: Instance<Self>>(&self, other: I) -> F { |
316 fn dist2_squared<I: Instance<Self>>(&self, other: I) -> F { |
| 296 other.eval_decompose(|Pair(u, v)| self.0.dist2_squared(u) + self.1.dist2_squared(v)) |
317 other.eval_decompose(|Pair(u, v)| self.0.dist2_squared(u) + self.1.dist2_squared(v)) |
| 297 } |
318 } |
| |
319 } |
| |
320 |
| |
321 impl<F, A, B, O, P> VectorSpace for Pair<A, B> |
| |
322 where |
| |
323 A: VectorSpace<Field = F, Owned = O, OwnedVariant = O>, |
| |
324 B: VectorSpace<Field = F, Owned = P, OwnedVariant = P>, |
| |
325 O: ClosedSpace + AXPY<A, Field = F, Owned = O, OwnedVariant = O>, |
| |
326 P: ClosedSpace + AXPY<B, Field = F, Owned = P, OwnedVariant = P>, |
| |
327 F: Num, |
| |
328 { |
| |
329 type Field = F; |
| |
330 type Owned = Pair<O, P>; |
| |
331 |
| |
332 /// Return a similar zero as `self`. |
| |
333 fn similar_origin(&self) -> Self::Owned { |
| |
334 Pair(self.0.similar_origin(), self.1.similar_origin()) |
| |
335 } |
| |
336 |
| |
337 // #[inline] |
| |
338 // fn into_owned(self) -> Self::Owned { |
| |
339 // Pair(self.0.into_owned(), self.1.into_owned()) |
| |
340 // } |
| 298 } |
341 } |
| 299 |
342 |
| 300 impl<F, A, B, U, V> AXPY<Pair<U, V>> for Pair<A, B> |
343 impl<F, A, B, U, V> AXPY<Pair<U, V>> for Pair<A, B> |
| 301 where |
344 where |
| 302 U: Space, |
345 U: Space, |
| 304 A: AXPY<U, Field = F>, |
347 A: AXPY<U, Field = F>, |
| 305 B: AXPY<V, Field = F>, |
348 B: AXPY<V, Field = F>, |
| 306 F: Num, |
349 F: Num, |
| 307 Self: MulAssign<F> + DivAssign<F>, |
350 Self: MulAssign<F> + DivAssign<F>, |
| 308 Pair<A, B>: MulAssign<F> + DivAssign<F>, |
351 Pair<A, B>: MulAssign<F> + DivAssign<F>, |
| 309 //A::Owned: MulAssign<F>, |
352 { |
| 310 //B::Owned: MulAssign<F>, |
|
| 311 //Pair<A::Owned, B::Owned>: AXPY<Pair<U, V>, Field = F>, |
|
| 312 { |
|
| 313 type Field = F; |
|
| 314 type Owned = Pair<A::Owned, B::Owned>; |
|
| 315 |
|
| 316 fn axpy<I: Instance<Pair<U, V>>>(&mut self, α: F, x: I, β: F) { |
353 fn axpy<I: Instance<Pair<U, V>>>(&mut self, α: F, x: I, β: F) { |
| 317 x.eval_decompose(|Pair(u, v)| { |
354 x.eval_decompose(|Pair(u, v)| { |
| 318 self.0.axpy(α, u, β); |
355 self.0.axpy(α, u, β); |
| 319 self.1.axpy(α, v, β); |
356 self.1.axpy(α, v, β); |
| 320 }) |
357 }) |
| 330 fn scale_from<I: Instance<Pair<U, V>>>(&mut self, α: F, x: I) { |
367 fn scale_from<I: Instance<Pair<U, V>>>(&mut self, α: F, x: I) { |
| 331 x.eval_decompose(|Pair(u, v)| { |
368 x.eval_decompose(|Pair(u, v)| { |
| 332 self.0.scale_from(α, u); |
369 self.0.scale_from(α, u); |
| 333 self.1.scale_from(α, v); |
370 self.1.scale_from(α, v); |
| 334 }) |
371 }) |
| 335 } |
|
| 336 |
|
| 337 /// Return a similar zero as `self`. |
|
| 338 fn similar_origin(&self) -> Self::Owned { |
|
| 339 Pair(self.0.similar_origin(), self.1.similar_origin()) |
|
| 340 } |
372 } |
| 341 |
373 |
| 342 /// Set self to zero. |
374 /// Set self to zero. |
| 343 fn set_zero(&mut self) { |
375 fn set_zero(&mut self) { |
| 344 self.0.set_zero(); |
376 self.0.set_zero(); |