src/direct_product.rs

branch
dev
changeset 150
c4e394a9c84c
parent 144
44d859269132
child 151
402d717bb5c0
equal deleted inserted replaced
149:2f1798c65fd6 150:c4e394a9c84c
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();
560 A: HasDual<F>, 592 A: HasDual<F>,
561 B: HasDual<F>, 593 B: HasDual<F>,
562 { 594 {
563 type DualSpace = Pair<A::DualSpace, B::DualSpace>; 595 type DualSpace = Pair<A::DualSpace, B::DualSpace>;
564 596
565 fn dual_origin(&self) -> <Self::DualSpace as AXPY>::Owned { 597 fn dual_origin(&self) -> <Self::DualSpace as VectorSpace>::Owned {
566 Pair(self.0.dual_origin(), self.1.dual_origin()) 598 Pair(self.0.dual_origin(), self.1.dual_origin())
567 } 599 }
568 } 600 }
569 601
570 #[cfg(feature = "pyo3")] 602 #[cfg(feature = "pyo3")]

mercurial