| 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::{ |
9 use crate::instance::{Decomposition, DecompositionMut, Instance, InstanceMut, MyCow, Ownable}; |
| 10 ClosedSpace, Decomposition, DecompositionMut, Instance, InstanceMut, MyCow, Ownable, |
|
| 11 }; |
|
| 12 use crate::linops::{VectorSpace, AXPY}; |
10 use crate::linops::{VectorSpace, AXPY}; |
| 13 use crate::loc::Loc; |
11 use crate::loc::Loc; |
| 14 use crate::mapping::Space; |
12 use crate::mapping::Space; |
| 15 use crate::norms::{HasDual, Norm, NormExponent, Normed, PairNorm, L2}; |
13 use crate::norms::{HasDual, Norm, NormExponent, Normed, PairNorm, L2}; |
| 16 use crate::types::{Float, Num}; |
14 use crate::types::{Float, Num}; |
| 287 /// compiler overflows. |
285 /// compiler overflows. |
| 288 impl<A, B, F: Float> Euclidean<F> for Pair<A, B> |
286 impl<A, B, F: Float> Euclidean<F> for Pair<A, B> |
| 289 where |
287 where |
| 290 A: Euclidean<F>, |
288 A: Euclidean<F>, |
| 291 B: Euclidean<F>, |
289 B: Euclidean<F>, |
| 292 //Pair<A, B>: Euclidean<F>, |
290 // //Pair<A, B>: Euclidean<F>, |
| 293 Self: Sized |
291 // Self: Sized |
| 294 + Mul<F, Output = <Self as VectorSpace>::Owned> |
292 // + Mul<F, Output = Self::OwnedEuclidean> |
| 295 + MulAssign<F> |
293 // + MulAssign<F> |
| 296 + Div<F, Output = <Self as VectorSpace>::Owned> |
294 // + Div<F, Output = Self::OwnedEuclidean> |
| 297 + DivAssign<F> |
295 // + DivAssign<F> |
| 298 + Add<Self, Output = <Self as VectorSpace>::Owned> |
296 // + Add<Self, Output = Self::OwnedEuclidean> |
| 299 + Sub<Self, Output = <Self as VectorSpace>::Owned> |
297 // + Sub<Self, Output = Self::OwnedEuclidean> |
| 300 + for<'b> Add<&'b Self, Output = <Self as VectorSpace>::Owned> |
298 // + for<'b> Add<&'b Self, Output = Self::OwnedEuclidean> |
| 301 + for<'b> Sub<&'b Self, Output = <Self as VectorSpace>::Owned> |
299 // + for<'b> Sub<&'b Self, Output = Self::OwnedEuclidean> |
| 302 + AddAssign<Self> |
300 // + AddAssign<Self> |
| 303 + for<'b> AddAssign<&'b Self> |
301 // + for<'b> AddAssign<&'b Self> |
| 304 + SubAssign<Self> |
302 // + SubAssign<Self> |
| 305 + for<'b> SubAssign<&'b Self> |
303 // + for<'b> SubAssign<&'b Self> |
| 306 + Neg<Output = <Self as VectorSpace>::Owned>, |
304 // + Neg<Output = Self::OwnedEuclidean>, |
| 307 { |
305 { |
| |
306 type OwnedEuclidean = Pair<A::OwnedEuclidean, B::OwnedEuclidean>; |
| |
307 |
| 308 fn dot<I: Instance<Self>>(&self, other: I) -> F { |
308 fn dot<I: Instance<Self>>(&self, other: I) -> F { |
| 309 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)) |
| 310 } |
310 } |
| 311 |
311 |
| 312 fn norm2_squared(&self) -> F { |
312 fn norm2_squared(&self) -> F { |
| 316 fn dist2_squared<I: Instance<Self>>(&self, other: I) -> F { |
316 fn dist2_squared<I: Instance<Self>>(&self, other: I) -> F { |
| 317 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)) |
| 318 } |
318 } |
| 319 } |
319 } |
| 320 |
320 |
| 321 impl<F, A, B, O, P> VectorSpace for Pair<A, B> |
321 impl<F, A, B> VectorSpace for Pair<A, B> |
| 322 where |
322 where |
| 323 A: VectorSpace<Field = F, Owned = O, OwnedVariant = O>, |
323 A: VectorSpace<Field = F>, |
| 324 B: VectorSpace<Field = F, Owned = P, OwnedVariant = P>, |
324 B: VectorSpace<Field = F>, |
| 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, |
325 F: Num, |
| 328 { |
326 { |
| 329 type Field = F; |
327 type Field = F; |
| 330 type Owned = Pair<O, P>; |
328 type Owned = Pair<A::Owned, B::Owned>; |
| 331 |
329 |
| 332 /// Return a similar zero as `self`. |
330 /// Return a similar zero as `self`. |
| 333 fn similar_origin(&self) -> Self::Owned { |
331 fn similar_origin(&self) -> Self::Owned { |
| 334 Pair(self.0.similar_origin(), self.1.similar_origin()) |
332 Pair(self.0.similar_origin(), self.1.similar_origin()) |
| 335 } |
333 } |
| 345 U: Space, |
343 U: Space, |
| 346 V: Space, |
344 V: Space, |
| 347 A: AXPY<U, Field = F>, |
345 A: AXPY<U, Field = F>, |
| 348 B: AXPY<V, Field = F>, |
346 B: AXPY<V, Field = F>, |
| 349 F: Num, |
347 F: Num, |
| 350 Self: MulAssign<F> + DivAssign<F>, |
348 // Self: MulAssign<F> + DivAssign<F>, |
| 351 Pair<A, B>: MulAssign<F> + DivAssign<F>, |
349 // Pair<A, B>: MulAssign<F> + DivAssign<F>, |
| 352 { |
350 { |
| 353 fn axpy<I: Instance<Pair<U, V>>>(&mut self, α: F, x: I, β: F) { |
351 fn axpy<I: Instance<Pair<U, V>>>(&mut self, α: F, x: I, β: F) { |
| 354 x.eval_decompose(|Pair(u, v)| { |
352 x.eval_decompose(|Pair(u, v)| { |
| 355 self.0.axpy(α, u, β); |
353 self.0.axpy(α, u, β); |
| 356 self.1.axpy(α, v, β); |
354 self.1.axpy(α, v, β); |
| 381 /// [`Decomposition`] for working with [`Pair`]s. |
379 /// [`Decomposition`] for working with [`Pair`]s. |
| 382 #[derive(Copy, Clone, Debug)] |
380 #[derive(Copy, Clone, Debug)] |
| 383 pub struct PairDecomposition<D, Q>(D, Q); |
381 pub struct PairDecomposition<D, Q>(D, Q); |
| 384 |
382 |
| 385 impl<A: Space, B: Space> Space for Pair<A, B> { |
383 impl<A: Space, B: Space> Space for Pair<A, B> { |
| |
384 type OwnedSpace = Pair<A::OwnedSpace, B::OwnedSpace>; |
| 386 type Decomp = PairDecomposition<A::Decomp, B::Decomp>; |
385 type Decomp = PairDecomposition<A::Decomp, B::Decomp>; |
| 387 } |
386 } |
| 388 |
387 |
| 389 impl<A, B, D, Q> Decomposition<Pair<A, B>> for PairDecomposition<D, Q> |
388 impl<A, B, D, Q> Decomposition<Pair<A, B>> for PairDecomposition<D, Q> |
| 390 where |
389 where |