| 75 + for<'b> SubAssign<&'b Self> |
75 + for<'b> SubAssign<&'b Self> |
| 76 where |
76 where |
| 77 X: Space, |
77 X: Space, |
| 78 { |
78 { |
| 79 /// Computes `y = βy + αx`, where `y` is `Self`. |
79 /// Computes `y = βy + αx`, where `y` is `Self`. |
| 80 fn axpy<I: Instance<X>>(&mut self, α: Self::Field, x: I, β: Self::Field); |
80 fn axpy<I: Instance<X::OwnedSpace>>(&mut self, α: Self::Field, x: I, β: Self::Field); |
| 81 |
81 |
| 82 /// Copies `x` to `self`. |
82 /// Copies `x` to `self`. |
| 83 fn copy_from<I: Instance<X>>(&mut self, x: I) { |
83 fn copy_from<I: Instance<X::OwnedSpace>>(&mut self, x: I) { |
| 84 self.axpy(1.0, x, 0.0) |
84 self.axpy(1.0, x, 0.0) |
| 85 } |
85 } |
| 86 |
86 |
| 87 /// Computes `y = αx`, where `y` is `Self`. |
87 /// Computes `y = αx`, where `y` is `Self`. |
| 88 fn scale_from<I: Instance<X>>(&mut self, α: Self::Field, x: I) { |
88 fn scale_from<I: Instance<X::OwnedSpace>>(&mut self, α: Self::Field, x: I) { |
| 89 self.axpy(α, x, 0.0) |
89 self.axpy(α, x, 0.0) |
| 90 } |
90 } |
| 91 |
91 |
| 92 /// Set self to zero. |
92 /// Set self to zero. |
| 93 fn set_zero(&mut self); |
93 fn set_zero(&mut self); |
| 98 |
98 |
| 99 /// Efficient in-place application for [`Linear`] operators. |
99 /// Efficient in-place application for [`Linear`] operators. |
| 100 #[replace_float_literals(F::cast_from(literal))] |
100 #[replace_float_literals(F::cast_from(literal))] |
| 101 pub trait GEMV<F: Num, X: Space, Y = <Self as Mapping<X>>::Codomain>: Linear<X> { |
101 pub trait GEMV<F: Num, X: Space, Y = <Self as Mapping<X>>::Codomain>: Linear<X> { |
| 102 /// Computes `y = αAx + βy`, where `A` is `Self`. |
102 /// Computes `y = αAx + βy`, where `A` is `Self`. |
| 103 fn gemv<I: Instance<X>>(&self, y: &mut Y, α: F, x: I, β: F); |
103 fn gemv<I: Instance<X::OwnedSpace>>(&self, y: &mut Y, α: F, x: I, β: F); |
| 104 |
104 |
| 105 #[inline] |
105 #[inline] |
| 106 /// Computes `y = Ax`, where `A` is `Self` |
106 /// Computes `y = Ax`, where `A` is `Self` |
| 107 fn apply_mut<I: Instance<X>>(&self, y: &mut Y, x: I) { |
107 fn apply_mut<I: Instance<X::OwnedSpace>>(&self, y: &mut Y, x: I) { |
| 108 self.gemv(y, 1.0, x, 0.0) |
108 self.gemv(y, 1.0, x, 0.0) |
| 109 } |
109 } |
| 110 |
110 |
| 111 #[inline] |
111 #[inline] |
| 112 /// Computes `y += Ax`, where `A` is `Self` |
112 /// Computes `y += Ax`, where `A` is `Self` |
| 113 fn apply_add<I: Instance<X>>(&self, y: &mut Y, x: I) { |
113 fn apply_add<I: Instance<X::OwnedSpace>>(&self, y: &mut Y, x: I) { |
| 114 self.gemv(y, 1.0, x, 1.0) |
114 self.gemv(y, 1.0, x, 1.0) |
| 115 } |
115 } |
| 116 } |
116 } |
| 117 |
117 |
| 118 /// Bounded linear operators |
118 /// Bounded linear operators |
| 211 where |
211 where |
| 212 Y: AXPY<X, Field = F>, |
212 Y: AXPY<X, Field = F>, |
| 213 X: Space, |
213 X: Space, |
| 214 { |
214 { |
| 215 // Computes `y = αAx + βy`, where `A` is `Self`. |
215 // Computes `y = αAx + βy`, where `A` is `Self`. |
| 216 fn gemv<I: Instance<X>>(&self, y: &mut Y, α: F, x: I, β: F) { |
216 fn gemv<I: Instance<X::OwnedSpace>>(&self, y: &mut Y, α: F, x: I, β: F) { |
| 217 y.axpy(α, x, β) |
217 y.axpy(α, x, β) |
| 218 } |
218 } |
| 219 |
219 |
| 220 fn apply_mut<I: Instance<X>>(&self, y: &mut Y, x: I) { |
220 fn apply_mut<I: Instance<X::OwnedSpace>>(&self, y: &mut Y, x: I) { |
| 221 y.copy_from(x); |
221 y.copy_from(x); |
| 222 } |
222 } |
| 223 } |
223 } |
| 224 |
224 |
| 225 impl<F, X, E> BoundedLinear<X, E, E, F> for IdOp<X> |
225 impl<F, X, E> BoundedLinear<X, E, E, F> for IdOp<X> |
| 262 pub struct SimpleZeroOp; |
262 pub struct SimpleZeroOp; |
| 263 |
263 |
| 264 impl<X: VectorSpace> Mapping<X> for SimpleZeroOp { |
264 impl<X: VectorSpace> Mapping<X> for SimpleZeroOp { |
| 265 type Codomain = X::Owned; |
265 type Codomain = X::Owned; |
| 266 |
266 |
| 267 fn apply<I: Instance<X>>(&self, x: I) -> X::Owned { |
267 fn apply<I: Instance<X::OwnedSpace>>(&self, x: I) -> X::Owned { |
| 268 X::similar_origin_inst(x) |
268 X::similar_origin_inst(x) |
| 269 } |
269 } |
| 270 } |
270 } |
| 271 |
271 |
| 272 impl<X: VectorSpace> Linear<X> for SimpleZeroOp {} |
272 impl<X: VectorSpace> Linear<X> for SimpleZeroOp {} |
| 277 F: Num, |
277 F: Num, |
| 278 Y: AXPY<Field = F>, |
278 Y: AXPY<Field = F>, |
| 279 X: VectorSpace<Field = F> + Instance<X>, |
279 X: VectorSpace<Field = F> + Instance<X>, |
| 280 { |
280 { |
| 281 // Computes `y = αAx + βy`, where `A` is `Self`. |
281 // Computes `y = αAx + βy`, where `A` is `Self`. |
| 282 fn gemv<I: Instance<X>>(&self, y: &mut Y, _α: F, _x: I, β: F) { |
282 fn gemv<I: Instance<X::OwnedSpace>>(&self, y: &mut Y, _α: F, _x: I, β: F) { |
| 283 *y *= β; |
283 *y *= β; |
| 284 } |
284 } |
| 285 |
285 |
| 286 fn apply_mut<I: Instance<X>>(&self, y: &mut Y, _x: I) { |
286 fn apply_mut<I: Instance<X::OwnedSpace>>(&self, y: &mut Y, _x: I) { |
| 287 y.set_zero(); |
287 y.set_zero(); |
| 288 } |
288 } |
| 289 } |
289 } |
| 290 |
290 |
| 291 impl<X, F, E1, E2> BoundedLinear<X, E1, E2, F> for SimpleZeroOp |
291 impl<X, F, E1, E2> BoundedLinear<X, E1, E2, F> for SimpleZeroOp |
| 412 F: Float, |
412 F: Float, |
| 413 OY: OriginGenerator<Y>, |
413 OY: OriginGenerator<Y>, |
| 414 { |
414 { |
| 415 type Codomain = Y::Owned; |
415 type Codomain = Y::Owned; |
| 416 |
416 |
| 417 fn apply<I: Instance<X>>(&self, _x: I) -> Y::Owned { |
417 fn apply<I: Instance<X::OwnedSpace>>(&self, _x: I) -> Y::Owned { |
| 418 self.codomain_origin_generator.origin() |
418 self.codomain_origin_generator.origin() |
| 419 } |
419 } |
| 420 } |
420 } |
| 421 |
421 |
| 422 impl<X, Y, OY, O, F> Linear<X> for ZeroOp<X, Y, OY, O, F> |
422 impl<X, Y, OY, O, F> Linear<X> for ZeroOp<X, Y, OY, O, F> |
| 435 Y: AXPY<Field = F, Owned = Y>, |
435 Y: AXPY<Field = F, Owned = Y>, |
| 436 F: Float, |
436 F: Float, |
| 437 OY: OriginGenerator<Y>, |
437 OY: OriginGenerator<Y>, |
| 438 { |
438 { |
| 439 // Computes `y = αAx + βy`, where `A` is `Self`. |
439 // Computes `y = αAx + βy`, where `A` is `Self`. |
| 440 fn gemv<I: Instance<X>>(&self, y: &mut Y, _α: F, _x: I, β: F) { |
440 fn gemv<I: Instance<X::OwnedSpace>>(&self, y: &mut Y, _α: F, _x: I, β: F) { |
| 441 *y *= β; |
441 *y *= β; |
| 442 } |
442 } |
| 443 |
443 |
| 444 fn apply_mut<I: Instance<X>>(&self, y: &mut Y, _x: I) { |
444 fn apply_mut<I: Instance<X::OwnedSpace>>(&self, y: &mut Y, _x: I) { |
| 445 y.set_zero(); |
445 y.set_zero(); |
| 446 } |
446 } |
| 447 } |
447 } |
| 448 |
448 |
| 449 impl<X, Y, OY, O, F, E1, E2> BoundedLinear<X, E1, E2, F> for ZeroOp<X, Y, OY, O, F> |
449 impl<X, Y, OY, O, F, E1, E2> BoundedLinear<X, E1, E2, F> for ZeroOp<X, Y, OY, O, F> |
| 502 F: Num, |
502 F: Num, |
| 503 X: Space, |
503 X: Space, |
| 504 T: Linear<X>, |
504 T: Linear<X>, |
| 505 S: GEMV<F, T::Codomain, Y>, |
505 S: GEMV<F, T::Codomain, Y>, |
| 506 { |
506 { |
| 507 fn gemv<I: Instance<X>>(&self, y: &mut Y, α: F, x: I, β: F) { |
507 fn gemv<I: Instance<X::OwnedSpace>>(&self, y: &mut Y, α: F, x: I, β: F) { |
| 508 self.outer.gemv(y, α, self.inner.apply(x), β) |
508 self.outer.gemv(y, α, self.inner.apply(x), β) |
| 509 } |
509 } |
| 510 |
510 |
| 511 /// Computes `y = Ax`, where `A` is `Self` |
511 /// Computes `y = Ax`, where `A` is `Self` |
| 512 fn apply_mut<I: Instance<X>>(&self, y: &mut Y, x: I) { |
512 fn apply_mut<I: Instance<X::OwnedSpace>>(&self, y: &mut Y, x: I) { |
| 513 self.outer.apply_mut(y, self.inner.apply(x)) |
513 self.outer.apply_mut(y, self.inner.apply(x)) |
| 514 } |
514 } |
| 515 |
515 |
| 516 /// Computes `y += Ax`, where `A` is `Self` |
516 /// Computes `y += Ax`, where `A` is `Self` |
| 517 fn apply_add<I: Instance<X>>(&self, y: &mut Y, x: I) { |
517 fn apply_add<I: Instance<X::OwnedSpace>>(&self, y: &mut Y, x: I) { |
| 518 self.outer.apply_add(y, self.inner.apply(x)) |
518 self.outer.apply_add(y, self.inner.apply(x)) |
| 519 } |
519 } |
| 520 } |
520 } |
| 521 |
521 |
| 522 impl<F, S, T, X, Z, Xexp, Yexp, Zexp> BoundedLinear<X, Xexp, Yexp, F> for Composition<S, T, Zexp> |
522 impl<F, S, T, X, Z, Xexp, Yexp, Zexp> BoundedLinear<X, Xexp, Yexp, F> for Composition<S, T, Zexp> |
| 549 S::Codomain: Add<T::Codomain>, |
549 S::Codomain: Add<T::Codomain>, |
| 550 <S::Codomain as Add<T::Codomain>>::Output: ClosedSpace, |
550 <S::Codomain as Add<T::Codomain>>::Output: ClosedSpace, |
| 551 { |
551 { |
| 552 type Codomain = <S::Codomain as Add<T::Codomain>>::Output; |
552 type Codomain = <S::Codomain as Add<T::Codomain>>::Output; |
| 553 |
553 |
| 554 fn apply<I: Instance<Pair<A, B>>>(&self, x: I) -> Self::Codomain { |
554 fn apply<I: Instance<Pair<A::OwnedSpace, B::OwnedSpace>>>(&self, x: I) -> Self::Codomain { |
| 555 x.eval_decompose(|Pair(a, b)| self.0.apply(a) + self.1.apply(b)) |
555 x.eval_decompose(|Pair(a, b)| self.0.apply(a) + self.1.apply(b)) |
| 556 } |
556 } |
| 557 } |
557 } |
| 558 |
558 |
| 559 impl<A, B, S, T> Linear<Pair<A, B>> for RowOp<S, T> |
559 impl<A, B, S, T> Linear<Pair<A, B>> for RowOp<S, T> |
| 574 S: GEMV<F, U, Y>, |
574 S: GEMV<F, U, Y>, |
| 575 T: GEMV<F, V, Y>, |
575 T: GEMV<F, V, Y>, |
| 576 F: Num, |
576 F: Num, |
| 577 Self: Linear<Pair<U, V>, Codomain = Y>, |
577 Self: Linear<Pair<U, V>, Codomain = Y>, |
| 578 { |
578 { |
| 579 fn gemv<I: Instance<Pair<U, V>>>(&self, y: &mut Y, α: F, x: I, β: F) { |
579 fn gemv<I: Instance<Pair<U::OwnedSpace, V::OwnedSpace>>>(&self, y: &mut Y, α: F, x: I, β: F) { |
| 580 x.eval_decompose(|Pair(u, v)| { |
580 x.eval_decompose(|Pair(u, v)| { |
| 581 self.0.gemv(y, α, u, β); |
581 self.0.gemv(y, α, u, β); |
| 582 self.1.gemv(y, α, v, F::ONE); |
582 self.1.gemv(y, α, v, F::ONE); |
| 583 }) |
583 }) |
| 584 } |
584 } |
| 585 |
585 |
| 586 fn apply_mut<I: Instance<Pair<U, V>>>(&self, y: &mut Y, x: I) { |
586 fn apply_mut<I: Instance<Pair<U::OwnedSpace, V::OwnedSpace>>>(&self, y: &mut Y, x: I) { |
| 587 x.eval_decompose(|Pair(u, v)| { |
587 x.eval_decompose(|Pair(u, v)| { |
| 588 self.0.apply_mut(y, u); |
588 self.0.apply_mut(y, u); |
| 589 self.1.apply_add(y, v); |
589 self.1.apply_add(y, v); |
| 590 }) |
590 }) |
| 591 } |
591 } |
| 592 |
592 |
| 593 /// Computes `y += Ax`, where `A` is `Self` |
593 /// Computes `y += Ax`, where `A` is `Self` |
| 594 fn apply_add<I: Instance<Pair<U, V>>>(&self, y: &mut Y, x: I) { |
594 fn apply_add<I: Instance<Pair<U::OwnedSpace, V::OwnedSpace>>>(&self, y: &mut Y, x: I) { |
| 595 x.eval_decompose(|Pair(u, v)| { |
595 x.eval_decompose(|Pair(u, v)| { |
| 596 self.0.apply_add(y, u); |
596 self.0.apply_add(y, u); |
| 597 self.1.apply_add(y, v); |
597 self.1.apply_add(y, v); |
| 598 }) |
598 }) |
| 599 } |
599 } |
| 609 S: Mapping<A>, |
609 S: Mapping<A>, |
| 610 T: Mapping<A>, |
610 T: Mapping<A>, |
| 611 { |
611 { |
| 612 type Codomain = Pair<S::Codomain, T::Codomain>; |
612 type Codomain = Pair<S::Codomain, T::Codomain>; |
| 613 |
613 |
| 614 fn apply<I: Instance<A>>(&self, a: I) -> Self::Codomain { |
614 fn apply<I: Instance<A::OwnedSpace>>(&self, a: I) -> Self::Codomain { |
| 615 Pair(a.eval_ref_decompose(|r| self.0.apply(r)), self.1.apply(a)) |
615 Pair(a.eval_ref_decompose(|r| self.0.apply(r)), self.1.apply(a)) |
| 616 } |
616 } |
| 617 } |
617 } |
| 618 |
618 |
| 619 impl<A, S, T> Linear<A> for ColOp<S, T> |
619 impl<A, S, T> Linear<A> for ColOp<S, T> |
| 630 S: GEMV<F, X, A>, |
630 S: GEMV<F, X, A>, |
| 631 T: GEMV<F, X, B>, |
631 T: GEMV<F, X, B>, |
| 632 F: Num, |
632 F: Num, |
| 633 Self: Linear<X, Codomain = Pair<A, B>>, |
633 Self: Linear<X, Codomain = Pair<A, B>>, |
| 634 { |
634 { |
| 635 fn gemv<I: Instance<X>>(&self, y: &mut Pair<A, B>, α: F, x: I, β: F) { |
635 fn gemv<I: Instance<X::OwnedSpace>>(&self, y: &mut Pair<A, B>, α: F, x: I, β: F) { |
| 636 x.eval_ref_decompose(|r| self.0.gemv(&mut y.0, α, r, β)); |
636 x.eval_ref_decompose(|r| self.0.gemv(&mut y.0, α, r, β)); |
| 637 self.1.gemv(&mut y.1, α, x, β); |
637 self.1.gemv(&mut y.1, α, x, β); |
| 638 } |
638 } |
| 639 |
639 |
| 640 fn apply_mut<I: Instance<X>>(&self, y: &mut Pair<A, B>, x: I) { |
640 fn apply_mut<I: Instance<X::OwnedSpace>>(&self, y: &mut Pair<A, B>, x: I) { |
| 641 x.eval_ref_decompose(|r| self.0.apply_mut(&mut y.0, r)); |
641 x.eval_ref_decompose(|r| self.0.apply_mut(&mut y.0, r)); |
| 642 self.1.apply_mut(&mut y.1, x); |
642 self.1.apply_mut(&mut y.1, x); |
| 643 } |
643 } |
| 644 |
644 |
| 645 /// Computes `y += Ax`, where `A` is `Self` |
645 /// Computes `y += Ax`, where `A` is `Self` |
| 646 fn apply_add<I: Instance<X>>(&self, y: &mut Pair<A, B>, x: I) { |
646 fn apply_add<I: Instance<X::OwnedSpace>>(&self, y: &mut Pair<A, B>, x: I) { |
| 647 x.eval_ref_decompose(|r| self.0.apply_add(&mut y.0, r)); |
647 x.eval_ref_decompose(|r| self.0.apply_add(&mut y.0, r)); |
| 648 self.1.apply_add(&mut y.1, x); |
648 self.1.apply_add(&mut y.1, x); |
| 649 } |
649 } |
| 650 } |
650 } |
| 651 |
651 |
| 753 S: Mapping<A>, |
753 S: Mapping<A>, |
| 754 T: Mapping<B>, |
754 T: Mapping<B>, |
| 755 { |
755 { |
| 756 type Codomain = Pair<S::Codomain, T::Codomain>; |
756 type Codomain = Pair<S::Codomain, T::Codomain>; |
| 757 |
757 |
| 758 fn apply<I: Instance<Pair<A, B>>>(&self, x: I) -> Self::Codomain { |
758 fn apply<I: Instance<Pair<A::OwnedSpace, B::OwnedSpace>>>(&self, x: I) -> Self::Codomain { |
| 759 x.eval_decompose(|Pair(a, b)| Pair(self.0.apply(a), self.1.apply(b))) |
759 x.eval_decompose(|Pair(a, b)| Pair(self.0.apply(a), self.1.apply(b))) |
| 760 } |
760 } |
| 761 } |
761 } |
| 762 |
762 |
| 763 impl<A, B, S, T> Linear<Pair<A, B>> for DiagOp<S, T> |
763 impl<A, B, S, T> Linear<Pair<A, B>> for DiagOp<S, T> |
| 778 S: GEMV<F, U, A>, |
778 S: GEMV<F, U, A>, |
| 779 T: GEMV<F, V, B>, |
779 T: GEMV<F, V, B>, |
| 780 F: Num, |
780 F: Num, |
| 781 Self: Linear<Pair<U, V>, Codomain = Pair<A, B>>, |
781 Self: Linear<Pair<U, V>, Codomain = Pair<A, B>>, |
| 782 { |
782 { |
| 783 fn gemv<I: Instance<Pair<U, V>>>(&self, y: &mut Pair<A, B>, α: F, x: I, β: F) { |
783 fn gemv<I: Instance<Pair<U::OwnedSpace, V::OwnedSpace>>>( |
| |
784 &self, |
| |
785 y: &mut Pair<A, B>, |
| |
786 α: F, |
| |
787 x: I, |
| |
788 β: F, |
| |
789 ) { |
| 784 x.eval_decompose(|Pair(u, v)| { |
790 x.eval_decompose(|Pair(u, v)| { |
| 785 self.0.gemv(&mut y.0, α, u, β); |
791 self.0.gemv(&mut y.0, α, u, β); |
| 786 self.1.gemv(&mut y.1, α, v, β); |
792 self.1.gemv(&mut y.1, α, v, β); |
| 787 }) |
793 }) |
| 788 } |
794 } |
| 789 |
795 |
| 790 fn apply_mut<I: Instance<Pair<U, V>>>(&self, y: &mut Pair<A, B>, x: I) { |
796 fn apply_mut<I: Instance<Pair<U::OwnedSpace, V::OwnedSpace>>>(&self, y: &mut Pair<A, B>, x: I) { |
| 791 x.eval_decompose(|Pair(u, v)| { |
797 x.eval_decompose(|Pair(u, v)| { |
| 792 self.0.apply_mut(&mut y.0, u); |
798 self.0.apply_mut(&mut y.0, u); |
| 793 self.1.apply_mut(&mut y.1, v); |
799 self.1.apply_mut(&mut y.1, v); |
| 794 }) |
800 }) |
| 795 } |
801 } |
| 796 |
802 |
| 797 /// Computes `y += Ax`, where `A` is `Self` |
803 /// Computes `y += Ax`, where `A` is `Self` |
| 798 fn apply_add<I: Instance<Pair<U, V>>>(&self, y: &mut Pair<A, B>, x: I) { |
804 fn apply_add<I: Instance<Pair<U::OwnedSpace, V::OwnedSpace>>>(&self, y: &mut Pair<A, B>, x: I) { |
| 799 x.eval_decompose(|Pair(u, v)| { |
805 x.eval_decompose(|Pair(u, v)| { |
| 800 self.0.apply_add(&mut y.0, u); |
806 self.0.apply_add(&mut y.0, u); |
| 801 self.1.apply_add(&mut y.1, v); |
807 self.1.apply_add(&mut y.1, v); |
| 802 }) |
808 }) |
| 803 } |
809 } |
| 923 <Domain as Mul<F>>::Output: ClosedSpace, |
929 <Domain as Mul<F>>::Output: ClosedSpace, |
| 924 { |
930 { |
| 925 type Codomain = <Domain as Mul<F>>::Output; |
931 type Codomain = <Domain as Mul<F>>::Output; |
| 926 |
932 |
| 927 /// Compute the value of `self` at `x`. |
933 /// Compute the value of `self` at `x`. |
| 928 fn apply<I: Instance<Domain>>(&self, x: I) -> Self::Codomain { |
934 fn apply<I: Instance<Domain::OwnedSpace>>(&self, x: I) -> Self::Codomain { |
| 929 x.own() * self.0 |
935 x.own() * self.0 |
| 930 } |
936 } |
| 931 } |
937 } |
| 932 |
938 |
| 933 impl<Domain, F> Linear<Domain> for Scaled<F> |
939 impl<Domain, F> Linear<Domain> for Scaled<F> |