150 type AdjointCodomain=X; |
151 type AdjointCodomain=X; |
151 type Adjoint<'a> = IdOp<X> where X : 'a; |
152 type Adjoint<'a> = IdOp<X> where X : 'a; |
152 fn adjoint(&self) -> Self::Adjoint<'_> { IdOp::new() } |
153 fn adjoint(&self) -> Self::Adjoint<'_> { IdOp::new() } |
153 } |
154 } |
154 |
155 |
|
156 /// “Row operator” $(S, T)$; $(S, T)(x, y)=Sx + Ty$. |
|
157 pub struct RowOp<S, T>(pub S, pub T); |
|
158 |
|
159 use std::ops::Add; |
|
160 |
|
161 impl<A, B, S, T> Apply<Pair<A, B>> for RowOp<S, T> |
|
162 where |
|
163 S : Apply<A>, |
|
164 T : Apply<B>, |
|
165 S::Output : Add<T::Output> |
|
166 { |
|
167 type Output = <S::Output as Add<T::Output>>::Output; |
|
168 |
|
169 fn apply(&self, Pair(a, b) : Pair<A, B>) -> Self::Output { |
|
170 self.0.apply(a) + self.1.apply(b) |
|
171 } |
|
172 } |
|
173 |
|
174 impl<'a, A, B, S, T> Apply<&'a Pair<A, B>> for RowOp<S, T> |
|
175 where |
|
176 S : Apply<&'a A>, |
|
177 T : Apply<&'a B>, |
|
178 S::Output : Add<T::Output> |
|
179 { |
|
180 type Output = <S::Output as Add<T::Output>>::Output; |
|
181 |
|
182 fn apply(&self, Pair(ref a, ref b) : &'a Pair<A, B>) -> Self::Output { |
|
183 self.0.apply(a) + self.1.apply(b) |
|
184 } |
|
185 } |
|
186 |
|
187 impl<A, B, S, T, D> Linear<Pair<A, B>> for RowOp<S, T> |
|
188 where |
|
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>, |
|
197 T : GEMV<F, V, Y>, |
|
198 F : Num, |
|
199 Self : Linear<Pair<U, V>, Codomain=Y> |
|
200 { |
|
201 fn gemv(&self, y : &mut Y, α : F, x : &Pair<U, V>, β : F) { |
|
202 self.0.gemv(y, α, &x.0, β); |
|
203 self.1.gemv(y, α, &x.1, β); |
|
204 } |
|
205 |
|
206 fn apply_mut(&self, y : &mut Y, x : &Pair<U, V>){ |
|
207 self.0.apply_mut(y, &x.0); |
|
208 self.1.apply_mut(y, &x.1); |
|
209 } |
|
210 |
|
211 /// Computes `y += Ax`, where `A` is `Self` |
|
212 fn apply_add(&self, y : &mut Y, x : &Pair<U, V>){ |
|
213 self.0.apply_add(y, &x.0); |
|
214 self.1.apply_add(y, &x.1); |
|
215 } |
|
216 } |
|
217 |
|
218 |
|
219 /// “Column operator” $(S; T)$; $(S; T)x=(Sx, Tx)$. |
|
220 pub struct ColOp<S, T>(pub S, pub T); |
|
221 |
|
222 impl<A, S, T, O> Apply<A> for ColOp<S, T> |
|
223 where |
|
224 S : for<'a> Apply<&'a A, Output=O>, |
|
225 T : Apply<A>, |
|
226 A : std::borrow::Borrow<A>, |
|
227 { |
|
228 type Output = Pair<O, T::Output>; |
|
229 |
|
230 fn apply(&self, a : A) -> Self::Output { |
|
231 Pair(self.0.apply(a.borrow()), self.1.apply(a)) |
|
232 } |
|
233 } |
|
234 |
|
235 impl<A, S, T, D> Linear<A> for ColOp<S, T> |
|
236 where |
|
237 ColOp<S, T> : Apply<A, Output=D> + for<'a> Apply<&'a A, Output=D>, |
|
238 { |
|
239 type Codomain = D; |
|
240 } |
|
241 |
|
242 impl<F, S, T, A, B, X> GEMV<F, X, Pair<A, B>> for ColOp<S, T> |
|
243 where |
|
244 S : GEMV<F, X, A>, |
|
245 T : GEMV<F, X, B>, |
|
246 F : Num, |
|
247 Self : Linear<X, Codomain=Pair<A, B>> |
|
248 { |
|
249 fn gemv(&self, y : &mut Pair<A, B>, α : F, x : &X, β : F) { |
|
250 self.0.gemv(&mut y.0, α, x, β); |
|
251 self.1.gemv(&mut y.1, α, x, β); |
|
252 } |
|
253 |
|
254 fn apply_mut(&self, y : &mut Pair<A, B>, x : &X){ |
|
255 self.0.apply_mut(&mut y.0, x); |
|
256 self.1.apply_mut(&mut y.1, x); |
|
257 } |
|
258 |
|
259 /// Computes `y += Ax`, where `A` is `Self` |
|
260 fn apply_add(&self, y : &mut Pair<A, B>, x : &X){ |
|
261 self.0.apply_add(&mut y.0, x); |
|
262 self.1.apply_add(&mut y.1, x); |
|
263 } |
|
264 } |
|
265 |
|
266 |
|
267 impl<A, B, Yʹ, R, S, T> Adjointable<Pair<A,B>,Yʹ> for RowOp<S, T> |
|
268 where |
|
269 S : Adjointable<A, Yʹ>, |
|
270 T : Adjointable<B, Yʹ>, |
|
271 Self : Linear<Pair<A, B>>, |
|
272 for<'a> ColOp<S::Adjoint<'a>, T::Adjoint<'a>> : Linear<Yʹ, Codomain=R>, |
|
273 { |
|
274 type AdjointCodomain = R; |
|
275 type Adjoint<'a> = ColOp<S::Adjoint<'a>, T::Adjoint<'a>> where Self : 'a; |
|
276 |
|
277 fn adjoint(&self) -> Self::Adjoint<'_> { |
|
278 ColOp(self.0.adjoint(), self.1.adjoint()) |
|
279 } |
|
280 } |
|
281 |
|
282 impl<A, B, Yʹ, R, S, T> Preadjointable<Pair<A,B>,Yʹ> for RowOp<S, T> |
|
283 where |
|
284 S : Preadjointable<A, Yʹ>, |
|
285 T : Preadjointable<B, Yʹ>, |
|
286 Self : Linear<Pair<A, B>>, |
|
287 for<'a> ColOp<S::Preadjoint<'a>, T::Preadjoint<'a>> : Adjointable<Yʹ, Pair<A,B>, Codomain=R>, |
|
288 { |
|
289 type PreadjointCodomain = R; |
|
290 type Preadjoint<'a> = ColOp<S::Preadjoint<'a>, T::Preadjoint<'a>> where Self : 'a; |
|
291 |
|
292 fn preadjoint(&self) -> Self::Preadjoint<'_> { |
|
293 ColOp(self.0.preadjoint(), self.1.preadjoint()) |
|
294 } |
|
295 } |
|
296 |
|
297 |
|
298 impl<A, Xʹ, Yʹ, R, S, T> Adjointable<A,Pair<Xʹ,Yʹ>> for ColOp<S, T> |
|
299 where |
|
300 S : Adjointable<A, Xʹ>, |
|
301 T : Adjointable<A, Yʹ>, |
|
302 Self : Linear<A>, |
|
303 for<'a> RowOp<S::Adjoint<'a>, T::Adjoint<'a>> : Linear<Pair<Xʹ,Yʹ>, Codomain=R>, |
|
304 { |
|
305 type AdjointCodomain = R; |
|
306 type Adjoint<'a> = RowOp<S::Adjoint<'a>, T::Adjoint<'a>> where Self : 'a; |
|
307 |
|
308 fn adjoint(&self) -> Self::Adjoint<'_> { |
|
309 RowOp(self.0.adjoint(), self.1.adjoint()) |
|
310 } |
|
311 } |
|
312 |
|
313 impl<A, Xʹ, Yʹ, R, S, T> Preadjointable<A,Pair<Xʹ,Yʹ>> for ColOp<S, T> |
|
314 where |
|
315 S : Preadjointable<A, Xʹ>, |
|
316 T : Preadjointable<A, Yʹ>, |
|
317 Self : Linear<A>, |
|
318 for<'a> RowOp<S::Preadjoint<'a>, T::Preadjoint<'a>> : Adjointable<Pair<Xʹ,Yʹ>, A, Codomain=R>, |
|
319 { |
|
320 type PreadjointCodomain = R; |
|
321 type Preadjoint<'a> = RowOp<S::Preadjoint<'a>, T::Preadjoint<'a>> where Self : 'a; |
|
322 |
|
323 fn preadjoint(&self) -> Self::Preadjoint<'_> { |
|
324 RowOp(self.0.preadjoint(), self.1.preadjoint()) |
|
325 } |
|
326 } |
|
327 |
|
328 /// Diagonal operator |
|
329 pub struct DiagOp<S, T>(pub S, pub T); |
|
330 |
|
331 impl<A, B, S, T> Apply<Pair<A, B>> for DiagOp<S, T> |
|
332 where |
|
333 S : Apply<A>, |
|
334 T : Apply<B>, |
|
335 { |
|
336 type Output = Pair<S::Output, T::Output>; |
|
337 |
|
338 fn apply(&self, Pair(a, b) : Pair<A, B>) -> Self::Output { |
|
339 Pair(self.0.apply(a), self.1.apply(b)) |
|
340 } |
|
341 } |
|
342 |
|
343 impl<'a, A, B, S, T> Apply<&'a Pair<A, B>> for DiagOp<S, T> |
|
344 where |
|
345 S : Apply<&'a A>, |
|
346 T : Apply<&'a B>, |
|
347 { |
|
348 type Output = Pair<S::Output, T::Output>; |
|
349 |
|
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 |
|
362 impl<F, S, T, A, B, U, V> GEMV<F, Pair<U, V>, Pair<A, B>> for DiagOp<S, T> |
|
363 where |
|
364 S : GEMV<F, U, A>, |
|
365 T : GEMV<F, V, B>, |
|
366 F : Num, |
|
367 Self : Linear<Pair<U, V>, Codomain=Pair<A, B>> |
|
368 { |
|
369 fn gemv(&self, y : &mut Pair<A, B>, α : F, x : &Pair<U, V>, β : F) { |
|
370 self.0.gemv(&mut y.0, α, &x.0, β); |
|
371 self.1.gemv(&mut y.1, α, &x.1, β); |
|
372 } |
|
373 |
|
374 fn apply_mut(&self, y : &mut Pair<A, B>, x : &Pair<U, V>){ |
|
375 self.0.apply_mut(&mut y.0, &x.0); |
|
376 self.1.apply_mut(&mut y.1, &x.1); |
|
377 } |
|
378 |
|
379 /// Computes `y += Ax`, where `A` is `Self` |
|
380 fn apply_add(&self, y : &mut Pair<A, B>, x : &Pair<U, V>){ |
|
381 self.0.apply_add(&mut y.0, &x.0); |
|
382 self.1.apply_add(&mut y.1, &x.1); |
|
383 } |
|
384 } |
|
385 |
|
386 impl<A, B, Xʹ, Yʹ, R, S, T> Adjointable<Pair<A,B>,Pair<Xʹ,Yʹ>> for DiagOp<S, T> |
|
387 where |
|
388 S : Adjointable<A, Xʹ>, |
|
389 T : Adjointable<B, Yʹ>, |
|
390 Self : Linear<Pair<A, B>>, |
|
391 for<'a> DiagOp<S::Adjoint<'a>, T::Adjoint<'a>> : Linear<Pair<Xʹ,Yʹ>, Codomain=R>, |
|
392 { |
|
393 type AdjointCodomain = R; |
|
394 type Adjoint<'a> = DiagOp<S::Adjoint<'a>, T::Adjoint<'a>> where Self : 'a; |
|
395 |
|
396 fn adjoint(&self) -> Self::Adjoint<'_> { |
|
397 DiagOp(self.0.adjoint(), self.1.adjoint()) |
|
398 } |
|
399 } |
|
400 |
|
401 impl<A, B, Xʹ, Yʹ, R, S, T> Preadjointable<Pair<A,B>,Pair<Xʹ,Yʹ>> for DiagOp<S, T> |
|
402 where |
|
403 S : Preadjointable<A, Xʹ>, |
|
404 T : Preadjointable<B, Yʹ>, |
|
405 Self : Linear<Pair<A, B>>, |
|
406 for<'a> DiagOp<S::Preadjoint<'a>, T::Preadjoint<'a>> : Adjointable<Pair<Xʹ,Yʹ>, Pair<A, B>, Codomain=R>, |
|
407 { |
|
408 type PreadjointCodomain = R; |
|
409 type Preadjoint<'a> = DiagOp<S::Preadjoint<'a>, T::Preadjoint<'a>> where Self : 'a; |
|
410 |
|
411 fn preadjoint(&self) -> Self::Preadjoint<'_> { |
|
412 DiagOp(self.0.preadjoint(), self.1.preadjoint()) |
|
413 } |
|
414 } |
|
415 |
|
416 /// Block operator |
|
417 pub type BlockOp<S11, S12, S21, S22> = ColOp<RowOp<S11, S12>, RowOp<S21, S22>>; |
|
418 |