2 Abstract linear operators. |
2 Abstract linear operators. |
3 */ |
3 */ |
4 |
4 |
5 use numeric_literals::replace_float_literals; |
5 use numeric_literals::replace_float_literals; |
6 use std::marker::PhantomData; |
6 use std::marker::PhantomData; |
|
7 use serde::Serialize; |
7 use crate::types::*; |
8 use crate::types::*; |
8 use serde::Serialize; |
9 pub use crate::mapping::{Mapping, Space}; |
9 pub use crate::mapping::Apply; |
|
10 use crate::direct_product::Pair; |
10 use crate::direct_product::Pair; |
|
11 use crate::instance::Instance; |
|
12 use crate::norms::{NormExponent, PairNorm, L1, L2, Linfinity}; |
11 |
13 |
12 /// Trait for linear operators on `X`. |
14 /// Trait for linear operators on `X`. |
13 pub trait Linear<X> : Apply<X, Output=Self::Codomain> |
15 pub trait Linear<X : Space> : Mapping<X> |
14 + for<'a> Apply<&'a X, Output=Self::Codomain> { |
16 { } |
15 type Codomain; |
|
16 } |
|
17 |
17 |
18 /// Efficient in-place summation. |
18 /// Efficient in-place summation. |
19 #[replace_float_literals(F::cast_from(literal))] |
19 #[replace_float_literals(F::cast_from(literal))] |
20 pub trait AXPY<F : Num, X = Self> { |
20 pub trait AXPY<F, X = Self> : Space |
|
21 where |
|
22 F : Num, |
|
23 X : Space, |
|
24 { |
21 /// Computes `y = βy + αx`, where `y` is `Self`. |
25 /// Computes `y = βy + αx`, where `y` is `Self`. |
22 fn axpy(&mut self, α : F, x : &X, β : F); |
26 fn axpy<I : Instance<X>>(&mut self, α : F, x : I, β : F); |
23 |
27 |
24 /// Copies `x` to `self`. |
28 /// Copies `x` to `self`. |
25 fn copy_from(&mut self, x : &X) { |
29 fn copy_from<I : Instance<X>>(&mut self, x : I) { |
26 self.axpy(1.0, x, 0.0) |
30 self.axpy(1.0, x, 0.0) |
27 } |
31 } |
28 |
32 |
29 /// Computes `y = αx`, where `y` is `Self`. |
33 /// Computes `y = αx`, where `y` is `Self`. |
30 fn scale_from(&mut self, α : F, x : &X) { |
34 fn scale_from<I : Instance<X>>(&mut self, α : F, x : I) { |
31 self.axpy(α, x, 0.0) |
35 self.axpy(α, x, 0.0) |
32 } |
36 } |
33 } |
37 } |
34 |
38 |
35 /// Efficient in-place application for [`Linear`] operators. |
39 /// Efficient in-place application for [`Linear`] operators. |
36 #[replace_float_literals(F::cast_from(literal))] |
40 #[replace_float_literals(F::cast_from(literal))] |
37 pub trait GEMV<F : Num, X, Y = <Self as Linear<X>>::Codomain> : Linear<X> { |
41 pub trait GEMV<F : Num, X : Space, Y = <Self as Mapping<X>>::Codomain> : Linear<X> { |
38 /// Computes `y = αAx + βy`, where `A` is `Self`. |
42 /// Computes `y = αAx + βy`, where `A` is `Self`. |
39 fn gemv(&self, y : &mut Y, α : F, x : &X, β : F); |
43 fn gemv<I : Instance<X>>(&self, y : &mut Y, α : F, x : I, β : F); |
40 |
44 |
41 /// Computes `y = Ax`, where `A` is `Self` |
45 /// Computes `y = Ax`, where `A` is `Self` |
42 fn apply_mut(&self, y : &mut Y, x : &X){ |
46 fn apply_mut<I : Instance<X>>(&self, y : &mut Y, x : I){ |
43 self.gemv(y, 1.0, x, 0.0) |
47 self.gemv(y, 1.0, x, 0.0) |
44 } |
48 } |
45 |
49 |
46 /// Computes `y += Ax`, where `A` is `Self` |
50 /// Computes `y += Ax`, where `A` is `Self` |
47 fn apply_add(&self, y : &mut Y, x : &X){ |
51 fn apply_add<I : Instance<X>>(&self, y : &mut Y, x : I){ |
48 self.gemv(y, 1.0, x, 1.0) |
52 self.gemv(y, 1.0, x, 1.0) |
49 } |
53 } |
50 } |
54 } |
51 |
55 |
52 |
56 |
53 /// Bounded linear operators |
57 /// Bounded linear operators |
54 pub trait BoundedLinear<X> : Linear<X> { |
58 pub trait BoundedLinear<X, XExp, CodExp, F = f64> : Linear<X> |
55 type FloatType : Float; |
59 where |
|
60 F : Num, |
|
61 X : Space, |
|
62 XExp : NormExponent, |
|
63 CodExp : NormExponent |
|
64 { |
56 /// A bound on the operator norm $\|A\|$ for the linear operator $A$=`self`. |
65 /// A bound on the operator norm $\|A\|$ for the linear operator $A$=`self`. |
57 /// This is not expected to be the norm, just any bound on it that can be |
66 /// This is not expected to be the norm, just any bound on it that can be |
58 /// reasonably implemented. |
67 /// reasonably implemented. The [`NormExponent`] `xexp` indicates the norm |
59 fn opnorm_bound(&self) -> Self::FloatType; |
68 /// in `X`, and `codexp` in the codomain. |
|
69 fn opnorm_bound(&self, xexp : XExp, codexp : CodExp) -> F; |
60 } |
70 } |
61 |
71 |
62 // Linear operator application into mutable target. The [`AsRef`] bound |
72 // Linear operator application into mutable target. The [`AsRef`] bound |
63 // is used to guarantee compatibility with `Yʹ` and `Self::Codomain`; |
73 // is used to guarantee compatibility with `Yʹ` and `Self::Codomain`; |
64 // the former is assumed to be e.g. a view into the latter. |
74 // the former is assumed to be e.g. a view into the latter. |
68 self.apply(x) |
78 self.apply(x) |
69 } |
79 } |
70 }*/ |
80 }*/ |
71 |
81 |
72 /// Trait for forming the adjoint operator of `Self`. |
82 /// Trait for forming the adjoint operator of `Self`. |
73 pub trait Adjointable<X,Yʹ> : Linear<X> { |
83 pub trait Adjointable<X, Yʹ> : Linear<X> |
74 type AdjointCodomain; |
84 where |
|
85 X : Space, |
|
86 Yʹ : Space, |
|
87 { |
|
88 type AdjointCodomain : Space; |
75 type Adjoint<'a> : Linear<Yʹ, Codomain=Self::AdjointCodomain> where Self : 'a; |
89 type Adjoint<'a> : Linear<Yʹ, Codomain=Self::AdjointCodomain> where Self : 'a; |
76 |
90 |
77 /// Form the adjoint operator of `self`. |
91 /// Form the adjoint operator of `self`. |
78 fn adjoint(&self) -> Self::Adjoint<'_>; |
92 fn adjoint(&self) -> Self::Adjoint<'_>; |
79 |
|
80 /*fn adjoint_apply(&self, y : &Yʹ) -> Self::AdjointCodomain { |
|
81 self.adjoint().apply(y) |
|
82 }*/ |
|
83 } |
93 } |
84 |
94 |
85 /// Trait for forming a preadjoint of an operator. |
95 /// Trait for forming a preadjoint of an operator. |
86 /// |
96 /// |
87 /// For an operator $A$ this is an operator $A\_\*$ |
97 /// For an operator $A$ this is an operator $A\_\*$ |
88 /// such that its adjoint $(A\_\*)^\*=A$. The space `X` is the domain of the `Self` |
98 /// such that its adjoint $(A\_\*)^\*=A$. The space `X` is the domain of the `Self` |
89 /// operator. The space `Ypre` is the predual of its codomain, and should be the |
99 /// operator. The space `Ypre` is the predual of its codomain, and should be the |
90 /// domain of the adjointed operator. `Self::Preadjoint` should be |
100 /// domain of the adjointed operator. `Self::Preadjoint` should be |
91 /// [`Adjointable`]`<'a,Ypre,X>`. |
101 /// [`Adjointable`]`<'a,Ypre,X>`. |
92 pub trait Preadjointable<X,Ypre> : Linear<X> { |
102 |
93 type PreadjointCodomain; |
103 pub trait Preadjointable<X : Space, Ypre : Space> : Linear<X> { |
94 type Preadjoint<'a> : Adjointable<Ypre, X, Codomain=Self::PreadjointCodomain> where Self : 'a; |
104 type PreadjointCodomain : Space; |
95 |
105 type Preadjoint<'a> : Adjointable< |
96 /// Form the preadjoint operator of `self`. |
106 Ypre, X, AdjointCodomain=Self::Codomain, Codomain=Self::PreadjointCodomain |
|
107 > where Self : 'a; |
|
108 |
|
109 /// Form the adjoint operator of `self`. |
97 fn preadjoint(&self) -> Self::Preadjoint<'_>; |
110 fn preadjoint(&self) -> Self::Preadjoint<'_>; |
98 } |
111 } |
99 |
112 |
100 /// Adjointable operators $A: X → Y$ between reflexive spaces $X$ and $Y$. |
113 /// Adjointable operators $A: X → Y$ between reflexive spaces $X$ and $Y$. |
101 pub trait SimplyAdjointable<X> : Adjointable<X,<Self as Linear<X>>::Codomain> {} |
114 pub trait SimplyAdjointable<X : Space> : Adjointable<X,<Self as Mapping<X>>::Codomain> {} |
102 impl<'a,X,T> SimplyAdjointable<X> for T where T : Adjointable<X,<Self as Linear<X>>::Codomain> {} |
115 impl<'a,X : Space, T> SimplyAdjointable<X> for T |
|
116 where T : Adjointable<X,<Self as Mapping<X>>::Codomain> {} |
103 |
117 |
104 /// The identity operator |
118 /// The identity operator |
105 #[derive(Clone,Copy,Debug,Serialize,Eq,PartialEq)] |
119 #[derive(Clone,Copy,Debug,Serialize,Eq,PartialEq)] |
106 pub struct IdOp<X> (PhantomData<X>); |
120 pub struct IdOp<X> (PhantomData<X>); |
107 |
121 |
108 impl<X> IdOp<X> { |
122 impl<X> IdOp<X> { |
109 fn new() -> IdOp<X> { IdOp(PhantomData) } |
123 pub fn new() -> IdOp<X> { IdOp(PhantomData) } |
110 } |
124 } |
111 |
125 |
112 impl<X> Apply<X> for IdOp<X> { |
126 impl<X : Clone + Space> Mapping<X> for IdOp<X> { |
113 type Output = X; |
|
114 |
|
115 fn apply(&self, x : X) -> X { |
|
116 x |
|
117 } |
|
118 } |
|
119 |
|
120 impl<'a, X> Apply<&'a X> for IdOp<X> where X : Clone { |
|
121 type Output = X; |
|
122 |
|
123 fn apply(&self, x : &'a X) -> X { |
|
124 x.clone() |
|
125 } |
|
126 } |
|
127 |
|
128 impl<X> Linear<X> for IdOp<X> where X : Clone { |
|
129 type Codomain = X; |
127 type Codomain = X; |
130 } |
128 |
131 |
129 fn apply<I : Instance<X>>(&self, x : I) -> X { |
|
130 x.own() |
|
131 } |
|
132 } |
|
133 |
|
134 impl<X : Clone + Space> Linear<X> for IdOp<X> |
|
135 { } |
132 |
136 |
133 #[replace_float_literals(F::cast_from(literal))] |
137 #[replace_float_literals(F::cast_from(literal))] |
134 impl<F : Num, X, Y> GEMV<F, X, Y> for IdOp<X> where Y : AXPY<F, X>, X : Clone { |
138 impl<F : Num, X, Y> GEMV<F, X, Y> for IdOp<X> |
|
139 where |
|
140 Y : AXPY<F, X>, |
|
141 X : Clone + Space |
|
142 { |
135 // Computes `y = αAx + βy`, where `A` is `Self`. |
143 // Computes `y = αAx + βy`, where `A` is `Self`. |
136 fn gemv(&self, y : &mut Y, α : F, x : &X, β : F) { |
144 fn gemv<I : Instance<X>>(&self, y : &mut Y, α : F, x : I, β : F) { |
137 y.axpy(α, x, β) |
145 y.axpy(α, x, β) |
138 } |
146 } |
139 |
147 |
140 fn apply_mut(&self, y : &mut Y, x : &X){ |
148 fn apply_mut<I : Instance<X>>(&self, y : &mut Y, x : I){ |
141 y.copy_from(x); |
149 y.copy_from(x); |
142 } |
150 } |
143 } |
151 } |
144 |
152 |
145 impl<X> BoundedLinear<X> for IdOp<X> where X : Clone { |
153 impl<F, X, E> BoundedLinear<X, E, E, F> for IdOp<X> |
146 type FloatType = float; |
154 where |
147 fn opnorm_bound(&self) -> float { 1.0 } |
155 X : Space + Clone, |
148 } |
156 F : Num, |
149 |
157 E : NormExponent |
150 impl<X> Adjointable<X,X> for IdOp<X> where X : Clone { |
158 { |
|
159 fn opnorm_bound(&self, _xexp : E, _codexp : E) -> F { F::ONE } |
|
160 } |
|
161 |
|
162 impl<X : Clone + Space> Adjointable<X,X> for IdOp<X> { |
151 type AdjointCodomain=X; |
163 type AdjointCodomain=X; |
152 type Adjoint<'a> = IdOp<X> where X : 'a; |
164 type Adjoint<'a> = IdOp<X> where X : 'a; |
|
165 |
153 fn adjoint(&self) -> Self::Adjoint<'_> { IdOp::new() } |
166 fn adjoint(&self) -> Self::Adjoint<'_> { IdOp::new() } |
|
167 } |
|
168 |
|
169 impl<X : Clone + Space> Preadjointable<X,X> for IdOp<X> { |
|
170 type PreadjointCodomain=X; |
|
171 type Preadjoint<'a> = IdOp<X> where X : 'a; |
|
172 |
|
173 fn preadjoint(&self) -> Self::Preadjoint<'_> { IdOp::new() } |
154 } |
174 } |
155 |
175 |
156 /// “Row operator” $(S, T)$; $(S, T)(x, y)=Sx + Ty$. |
176 /// “Row operator” $(S, T)$; $(S, T)(x, y)=Sx + Ty$. |
157 pub struct RowOp<S, T>(pub S, pub T); |
177 pub struct RowOp<S, T>(pub S, pub T); |
158 |
178 |
159 use std::ops::Add; |
179 use std::ops::Add; |
160 |
180 |
161 impl<A, B, S, T> Apply<Pair<A, B>> for RowOp<S, T> |
181 impl<A, B, S, T> Mapping<Pair<A, B>> for RowOp<S, T> |
162 where |
182 where |
163 S : Apply<A>, |
183 A : Space, |
164 T : Apply<B>, |
184 B : Space, |
165 S::Output : Add<T::Output> |
185 S : Mapping<A>, |
166 { |
186 T : Mapping<B>, |
167 type Output = <S::Output as Add<T::Output>>::Output; |
187 S::Codomain : Add<T::Codomain>, |
168 |
188 <S::Codomain as Add<T::Codomain>>::Output : Space, |
169 fn apply(&self, Pair(a, b) : Pair<A, B>) -> Self::Output { |
189 |
|
190 { |
|
191 type Codomain = <S::Codomain as Add<T::Codomain>>::Output; |
|
192 |
|
193 fn apply<I : Instance<Pair<A, B>>>(&self, x : I) -> Self::Codomain { |
|
194 let Pair(a, b) = x.decompose(); |
170 self.0.apply(a) + self.1.apply(b) |
195 self.0.apply(a) + self.1.apply(b) |
171 } |
196 } |
172 } |
197 } |
173 |
198 |
174 impl<'a, A, B, S, T> Apply<&'a Pair<A, B>> for RowOp<S, T> |
199 impl<A, B, S, T> Linear<Pair<A, B>> for RowOp<S, T> |
175 where |
200 where |
176 S : Apply<&'a A>, |
201 A : Space, |
177 T : Apply<&'a B>, |
202 B : Space, |
178 S::Output : Add<T::Output> |
203 S : Linear<A>, |
179 { |
204 T : Linear<B>, |
180 type Output = <S::Output as Add<T::Output>>::Output; |
205 S::Codomain : Add<T::Codomain>, |
181 |
206 <S::Codomain as Add<T::Codomain>>::Output : Space, |
182 fn apply(&self, Pair(ref a, ref b) : &'a Pair<A, B>) -> Self::Output { |
207 { } |
183 self.0.apply(a) + self.1.apply(b) |
208 |
184 } |
209 |
185 } |
210 impl<'b, F, S, T, Y, U, V> GEMV<F, Pair<U, V>, Y> for RowOp<S, T> |
186 |
211 where |
187 impl<A, B, S, T, D> Linear<Pair<A, B>> for RowOp<S, T> |
212 U : Space, |
188 where |
213 V : Space, |
189 RowOp<S, T> : Apply<Pair<A, B>, Output=D> + for<'a> Apply<&'a Pair<A, B>, Output=D>, |
|
190 { |
|
191 type Codomain = D; |
|
192 } |
|
193 |
|
194 impl<F, S, T, Y, U, V> GEMV<F, Pair<U, V>, Y> for RowOp<S, T> |
|
195 where |
|
196 S : GEMV<F, U, Y>, |
214 S : GEMV<F, U, Y>, |
197 T : GEMV<F, V, Y>, |
215 T : GEMV<F, V, Y>, |
198 F : Num, |
216 F : Num, |
199 Self : Linear<Pair<U, V>, Codomain=Y> |
217 Self : Linear<Pair<U, V>, Codomain=Y> |
200 { |
218 { |
201 fn gemv(&self, y : &mut Y, α : F, x : &Pair<U, V>, β : F) { |
219 fn gemv<I : Instance<Pair<U, V>>>(&self, y : &mut Y, α : F, x : I, β : F) { |
202 self.0.gemv(y, α, &x.0, β); |
220 let Pair(u, v) = x.decompose(); |
203 self.1.gemv(y, α, &x.1, β); |
221 self.0.gemv(y, α, u, β); |
204 } |
222 self.1.gemv(y, α, v, F::ONE); |
205 |
223 } |
206 fn apply_mut(&self, y : &mut Y, x : &Pair<U, V>){ |
224 |
207 self.0.apply_mut(y, &x.0); |
225 fn apply_mut<I : Instance<Pair<U, V>>>(&self, y : &mut Y, x : I) { |
208 self.1.apply_mut(y, &x.1); |
226 let Pair(u, v) = x.decompose(); |
|
227 self.0.apply_mut(y, u); |
|
228 self.1.apply_mut(y, v); |
209 } |
229 } |
210 |
230 |
211 /// Computes `y += Ax`, where `A` is `Self` |
231 /// Computes `y += Ax`, where `A` is `Self` |
212 fn apply_add(&self, y : &mut Y, x : &Pair<U, V>){ |
232 fn apply_add<I : Instance<Pair<U, V>>>(&self, y : &mut Y, x : I) { |
213 self.0.apply_add(y, &x.0); |
233 let Pair(u, v) = x.decompose(); |
214 self.1.apply_add(y, &x.1); |
234 self.0.apply_add(y, u); |
215 } |
235 self.1.apply_add(y, v); |
216 } |
236 } |
217 |
237 } |
218 |
238 |
219 /// “Column operator” $(S; T)$; $(S; T)x=(Sx, Tx)$. |
239 /// “Column operator” $(S; T)$; $(S; T)x=(Sx, Tx)$. |
220 pub struct ColOp<S, T>(pub S, pub T); |
240 pub struct ColOp<S, T>(pub S, pub T); |
221 |
241 |
222 impl<A, S, T, O> Apply<A> for ColOp<S, T> |
242 impl<A, S, T> Mapping<A> for ColOp<S, T> |
223 where |
243 where |
224 S : for<'a> Apply<&'a A, Output=O>, |
244 A : Space, |
225 T : Apply<A>, |
245 S : Mapping<A>, |
226 A : std::borrow::Borrow<A>, |
246 T : Mapping<A>, |
227 { |
247 { |
228 type Output = Pair<O, T::Output>; |
248 type Codomain = Pair<S::Codomain, T::Codomain>; |
229 |
249 |
230 fn apply(&self, a : A) -> Self::Output { |
250 fn apply<I : Instance<A>>(&self, a : I) -> Self::Codomain { |
231 Pair(self.0.apply(a.borrow()), self.1.apply(a)) |
251 Pair(self.0.apply(a.ref_instance()), self.1.apply(a)) |
232 } |
252 } |
233 } |
253 } |
234 |
254 |
235 impl<A, S, T, D> Linear<A> for ColOp<S, T> |
255 impl<A, S, T> Linear<A> for ColOp<S, T> |
236 where |
256 where |
237 ColOp<S, T> : Apply<A, Output=D> + for<'a> Apply<&'a A, Output=D>, |
257 A : Space, |
238 { |
258 S : Mapping<A>, |
239 type Codomain = D; |
259 T : Mapping<A>, |
240 } |
260 { } |
241 |
261 |
242 impl<F, S, T, A, B, X> GEMV<F, X, Pair<A, B>> for ColOp<S, T> |
262 impl<F, S, T, A, B, X> GEMV<F, X, Pair<A, B>> for ColOp<S, T> |
243 where |
263 where |
|
264 X : Space, |
244 S : GEMV<F, X, A>, |
265 S : GEMV<F, X, A>, |
245 T : GEMV<F, X, B>, |
266 T : GEMV<F, X, B>, |
246 F : Num, |
267 F : Num, |
247 Self : Linear<X, Codomain=Pair<A, B>> |
268 Self : Linear<X, Codomain=Pair<A, B>> |
248 { |
269 { |
249 fn gemv(&self, y : &mut Pair<A, B>, α : F, x : &X, β : F) { |
270 fn gemv<I : Instance<X>>(&self, y : &mut Pair<A, B>, α : F, x : I, β : F) { |
250 self.0.gemv(&mut y.0, α, x, β); |
271 self.0.gemv(&mut y.0, α, x.ref_instance(), β); |
251 self.1.gemv(&mut y.1, α, x, β); |
272 self.1.gemv(&mut y.1, α, x, β); |
252 } |
273 } |
253 |
274 |
254 fn apply_mut(&self, y : &mut Pair<A, B>, x : &X){ |
275 fn apply_mut<I : Instance<X>>(&self, y : &mut Pair<A, B>, x : I){ |
255 self.0.apply_mut(&mut y.0, x); |
276 self.0.apply_mut(&mut y.0, x.ref_instance()); |
256 self.1.apply_mut(&mut y.1, x); |
277 self.1.apply_mut(&mut y.1, x); |
257 } |
278 } |
258 |
279 |
259 /// Computes `y += Ax`, where `A` is `Self` |
280 /// Computes `y += Ax`, where `A` is `Self` |
260 fn apply_add(&self, y : &mut Pair<A, B>, x : &X){ |
281 fn apply_add<I : Instance<X>>(&self, y : &mut Pair<A, B>, x : I){ |
261 self.0.apply_add(&mut y.0, x); |
282 self.0.apply_add(&mut y.0, x.ref_instance()); |
262 self.1.apply_add(&mut y.1, x); |
283 self.1.apply_add(&mut y.1, x); |
263 } |
284 } |
264 } |
285 } |
265 |
286 |
266 |
287 |
267 impl<A, B, Yʹ, R, S, T> Adjointable<Pair<A,B>,Yʹ> for RowOp<S, T> |
288 impl<A, B, Yʹ, S, T> Adjointable<Pair<A,B>, Yʹ> for RowOp<S, T> |
268 where |
289 where |
|
290 A : Space, |
|
291 B : Space, |
|
292 Yʹ : Space, |
269 S : Adjointable<A, Yʹ>, |
293 S : Adjointable<A, Yʹ>, |
270 T : Adjointable<B, Yʹ>, |
294 T : Adjointable<B, Yʹ>, |
271 Self : Linear<Pair<A, B>>, |
295 Self : Linear<Pair<A, B>>, |
272 for<'a> ColOp<S::Adjoint<'a>, T::Adjoint<'a>> : Linear<Yʹ, Codomain=R>, |
296 // for<'a> ColOp<S::Adjoint<'a>, T::Adjoint<'a>> : Linear< |
273 { |
297 // Yʹ, |
274 type AdjointCodomain = R; |
298 // Codomain=Pair<S::AdjointCodomain, T::AdjointCodomain> |
|
299 // >, |
|
300 { |
|
301 type AdjointCodomain = Pair<S::AdjointCodomain, T::AdjointCodomain>; |
275 type Adjoint<'a> = ColOp<S::Adjoint<'a>, T::Adjoint<'a>> where Self : 'a; |
302 type Adjoint<'a> = ColOp<S::Adjoint<'a>, T::Adjoint<'a>> where Self : 'a; |
276 |
303 |
277 fn adjoint(&self) -> Self::Adjoint<'_> { |
304 fn adjoint(&self) -> Self::Adjoint<'_> { |
278 ColOp(self.0.adjoint(), self.1.adjoint()) |
305 ColOp(self.0.adjoint(), self.1.adjoint()) |
279 } |
306 } |
280 } |
307 } |
281 |
308 |
282 impl<A, B, Yʹ, R, S, T> Preadjointable<Pair<A,B>,Yʹ> for RowOp<S, T> |
309 impl<A, B, Yʹ, S, T> Preadjointable<Pair<A,B>, Yʹ> for RowOp<S, T> |
283 where |
310 where |
|
311 A : Space, |
|
312 B : Space, |
|
313 Yʹ : Space, |
284 S : Preadjointable<A, Yʹ>, |
314 S : Preadjointable<A, Yʹ>, |
285 T : Preadjointable<B, Yʹ>, |
315 T : Preadjointable<B, Yʹ>, |
286 Self : Linear<Pair<A, B>>, |
316 Self : Linear<Pair<A, B>>, |
287 for<'a> ColOp<S::Preadjoint<'a>, T::Preadjoint<'a>> : Adjointable<Yʹ, Pair<A,B>, Codomain=R>, |
317 for<'a> ColOp<S::Preadjoint<'a>, T::Preadjoint<'a>> : Adjointable< |
288 { |
318 Yʹ, Pair<A,B>, |
289 type PreadjointCodomain = R; |
319 Codomain=Pair<S::PreadjointCodomain, T::PreadjointCodomain>, |
|
320 AdjointCodomain = Self::Codomain, |
|
321 >, |
|
322 { |
|
323 type PreadjointCodomain = Pair<S::PreadjointCodomain, T::PreadjointCodomain>; |
290 type Preadjoint<'a> = ColOp<S::Preadjoint<'a>, T::Preadjoint<'a>> where Self : 'a; |
324 type Preadjoint<'a> = ColOp<S::Preadjoint<'a>, T::Preadjoint<'a>> where Self : 'a; |
291 |
325 |
292 fn preadjoint(&self) -> Self::Preadjoint<'_> { |
326 fn preadjoint(&self) -> Self::Preadjoint<'_> { |
293 ColOp(self.0.preadjoint(), self.1.preadjoint()) |
327 ColOp(self.0.preadjoint(), self.1.preadjoint()) |
294 } |
328 } |
295 } |
329 } |
296 |
330 |
297 |
331 |
298 impl<A, Xʹ, Yʹ, R, S, T> Adjointable<A,Pair<Xʹ,Yʹ>> for ColOp<S, T> |
332 impl<A, Xʹ, Yʹ, R, S, T> Adjointable<A,Pair<Xʹ,Yʹ>> for ColOp<S, T> |
299 where |
333 where |
300 S : Adjointable<A, Xʹ>, |
334 A : Space, |
301 T : Adjointable<A, Yʹ>, |
335 Xʹ : Space, |
|
336 Yʹ : Space, |
|
337 R : Space + ClosedAdd, |
|
338 S : Adjointable<A, Xʹ, AdjointCodomain = R>, |
|
339 T : Adjointable<A, Yʹ, AdjointCodomain = R>, |
302 Self : Linear<A>, |
340 Self : Linear<A>, |
303 for<'a> RowOp<S::Adjoint<'a>, T::Adjoint<'a>> : Linear<Pair<Xʹ,Yʹ>, Codomain=R>, |
341 // for<'a> RowOp<S::Adjoint<'a>, T::Adjoint<'a>> : Linear< |
|
342 // Pair<Xʹ,Yʹ>, |
|
343 // Codomain=R, |
|
344 // >, |
304 { |
345 { |
305 type AdjointCodomain = R; |
346 type AdjointCodomain = R; |
306 type Adjoint<'a> = RowOp<S::Adjoint<'a>, T::Adjoint<'a>> where Self : 'a; |
347 type Adjoint<'a> = RowOp<S::Adjoint<'a>, T::Adjoint<'a>> where Self : 'a; |
307 |
348 |
308 fn adjoint(&self) -> Self::Adjoint<'_> { |
349 fn adjoint(&self) -> Self::Adjoint<'_> { |
326 } |
375 } |
327 |
376 |
328 /// Diagonal operator |
377 /// Diagonal operator |
329 pub struct DiagOp<S, T>(pub S, pub T); |
378 pub struct DiagOp<S, T>(pub S, pub T); |
330 |
379 |
331 impl<A, B, S, T> Apply<Pair<A, B>> for DiagOp<S, T> |
380 impl<A, B, S, T> Mapping<Pair<A, B>> for DiagOp<S, T> |
332 where |
381 where |
333 S : Apply<A>, |
382 A : Space, |
334 T : Apply<B>, |
383 B : Space, |
335 { |
384 S : Mapping<A>, |
336 type Output = Pair<S::Output, T::Output>; |
385 T : Mapping<B>, |
337 |
386 { |
338 fn apply(&self, Pair(a, b) : Pair<A, B>) -> Self::Output { |
387 type Codomain = Pair<S::Codomain, T::Codomain>; |
|
388 |
|
389 fn apply<I : Instance<Pair<A, B>>>(&self, x : I) -> Self::Codomain { |
|
390 let Pair(a, b) = x.decompose(); |
339 Pair(self.0.apply(a), self.1.apply(b)) |
391 Pair(self.0.apply(a), self.1.apply(b)) |
340 } |
392 } |
341 } |
393 } |
342 |
394 |
343 impl<'a, A, B, S, T> Apply<&'a Pair<A, B>> for DiagOp<S, T> |
395 impl<A, B, S, T> Linear<Pair<A, B>> for DiagOp<S, T> |
344 where |
396 where |
345 S : Apply<&'a A>, |
397 A : Space, |
346 T : Apply<&'a B>, |
398 B : Space, |
347 { |
399 S : Linear<A>, |
348 type Output = Pair<S::Output, T::Output>; |
400 T : Linear<B>, |
349 |
401 { } |
350 fn apply(&self, Pair(ref a, ref b) : &'a Pair<A, B>) -> Self::Output { |
|
351 Pair(self.0.apply(a), self.1.apply(b)) |
|
352 } |
|
353 } |
|
354 |
|
355 impl<A, B, S, T, D> Linear<Pair<A, B>> for DiagOp<S, T> |
|
356 where |
|
357 DiagOp<S, T> : Apply<Pair<A, B>, Output=D> + for<'a> Apply<&'a Pair<A, B>, Output=D>, |
|
358 { |
|
359 type Codomain = D; |
|
360 } |
|
361 |
402 |
362 impl<F, S, T, A, B, U, V> GEMV<F, Pair<U, V>, Pair<A, B>> for DiagOp<S, T> |
403 impl<F, S, T, A, B, U, V> GEMV<F, Pair<U, V>, Pair<A, B>> for DiagOp<S, T> |
363 where |
404 where |
|
405 A : Space, |
|
406 B : Space, |
|
407 U : Space, |
|
408 V : Space, |
364 S : GEMV<F, U, A>, |
409 S : GEMV<F, U, A>, |
365 T : GEMV<F, V, B>, |
410 T : GEMV<F, V, B>, |
366 F : Num, |
411 F : Num, |
367 Self : Linear<Pair<U, V>, Codomain=Pair<A, B>> |
412 Self : Linear<Pair<U, V>, Codomain=Pair<A, B>>, |
368 { |
413 { |
369 fn gemv(&self, y : &mut Pair<A, B>, α : F, x : &Pair<U, V>, β : F) { |
414 fn gemv<I : Instance<Pair<U, V>>>(&self, y : &mut Pair<A, B>, α : F, x : I, β : F) { |
370 self.0.gemv(&mut y.0, α, &x.0, β); |
415 let Pair(u, v) = x.decompose(); |
371 self.1.gemv(&mut y.1, α, &x.1, β); |
416 self.0.gemv(&mut y.0, α, u, β); |
372 } |
417 self.1.gemv(&mut y.1, α, v, β); |
373 |
418 } |
374 fn apply_mut(&self, y : &mut Pair<A, B>, x : &Pair<U, V>){ |
419 |
375 self.0.apply_mut(&mut y.0, &x.0); |
420 fn apply_mut<I : Instance<Pair<U, V>>>(&self, y : &mut Pair<A, B>, x : I){ |
376 self.1.apply_mut(&mut y.1, &x.1); |
421 let Pair(u, v) = x.decompose(); |
|
422 self.0.apply_mut(&mut y.0, u); |
|
423 self.1.apply_mut(&mut y.1, v); |
377 } |
424 } |
378 |
425 |
379 /// Computes `y += Ax`, where `A` is `Self` |
426 /// Computes `y += Ax`, where `A` is `Self` |
380 fn apply_add(&self, y : &mut Pair<A, B>, x : &Pair<U, V>){ |
427 fn apply_add<I : Instance<Pair<U, V>>>(&self, y : &mut Pair<A, B>, x : I){ |
381 self.0.apply_add(&mut y.0, &x.0); |
428 let Pair(u, v) = x.decompose(); |
382 self.1.apply_add(&mut y.1, &x.1); |
429 self.0.apply_add(&mut y.0, u); |
383 } |
430 self.1.apply_add(&mut y.1, v); |
384 } |
431 } |
385 |
432 } |
386 impl<A, B, Xʹ, Yʹ, R, S, T> Adjointable<Pair<A,B>,Pair<Xʹ,Yʹ>> for DiagOp<S, T> |
433 |
387 where |
434 impl<A, B, Xʹ, Yʹ, R, S, T> Adjointable<Pair<A,B>, Pair<Xʹ,Yʹ>> for DiagOp<S, T> |
|
435 where |
|
436 A : Space, |
|
437 B : Space, |
|
438 Xʹ: Space, |
|
439 Yʹ : Space, |
|
440 R : Space, |
388 S : Adjointable<A, Xʹ>, |
441 S : Adjointable<A, Xʹ>, |
389 T : Adjointable<B, Yʹ>, |
442 T : Adjointable<B, Yʹ>, |
390 Self : Linear<Pair<A, B>>, |
443 Self : Linear<Pair<A, B>>, |
391 for<'a> DiagOp<S::Adjoint<'a>, T::Adjoint<'a>> : Linear<Pair<Xʹ,Yʹ>, Codomain=R>, |
444 for<'a> DiagOp<S::Adjoint<'a>, T::Adjoint<'a>> : Linear< |
|
445 Pair<Xʹ,Yʹ>, Codomain=R, |
|
446 >, |
392 { |
447 { |
393 type AdjointCodomain = R; |
448 type AdjointCodomain = R; |
394 type Adjoint<'a> = DiagOp<S::Adjoint<'a>, T::Adjoint<'a>> where Self : 'a; |
449 type Adjoint<'a> = DiagOp<S::Adjoint<'a>, T::Adjoint<'a>> where Self : 'a; |
395 |
450 |
396 fn adjoint(&self) -> Self::Adjoint<'_> { |
451 fn adjoint(&self) -> Self::Adjoint<'_> { |
397 DiagOp(self.0.adjoint(), self.1.adjoint()) |
452 DiagOp(self.0.adjoint(), self.1.adjoint()) |
398 } |
453 } |
399 } |
454 } |
400 |
455 |
401 impl<A, B, Xʹ, Yʹ, R, S, T> Preadjointable<Pair<A,B>,Pair<Xʹ,Yʹ>> for DiagOp<S, T> |
456 impl<A, B, Xʹ, Yʹ, R, S, T> Preadjointable<Pair<A,B>, Pair<Xʹ,Yʹ>> for DiagOp<S, T> |
402 where |
457 where |
|
458 A : Space, |
|
459 B : Space, |
|
460 Xʹ: Space, |
|
461 Yʹ : Space, |
|
462 R : Space, |
403 S : Preadjointable<A, Xʹ>, |
463 S : Preadjointable<A, Xʹ>, |
404 T : Preadjointable<B, Yʹ>, |
464 T : Preadjointable<B, Yʹ>, |
405 Self : Linear<Pair<A, B>>, |
465 Self : Linear<Pair<A, B>>, |
406 for<'a> DiagOp<S::Preadjoint<'a>, T::Preadjoint<'a>> : Adjointable<Pair<Xʹ,Yʹ>, Pair<A, B>, Codomain=R>, |
466 for<'a> DiagOp<S::Preadjoint<'a>, T::Preadjoint<'a>> : Adjointable< |
|
467 Pair<Xʹ,Yʹ>, Pair<A, B>, |
|
468 Codomain=R, |
|
469 AdjointCodomain = Self::Codomain, |
|
470 >, |
407 { |
471 { |
408 type PreadjointCodomain = R; |
472 type PreadjointCodomain = R; |
409 type Preadjoint<'a> = DiagOp<S::Preadjoint<'a>, T::Preadjoint<'a>> where Self : 'a; |
473 type Preadjoint<'a> = DiagOp<S::Preadjoint<'a>, T::Preadjoint<'a>> where Self : 'a; |
410 |
474 |
411 fn preadjoint(&self) -> Self::Preadjoint<'_> { |
475 fn preadjoint(&self) -> Self::Preadjoint<'_> { |