| 110 /// domain of the adjointed operator. `Self::Preadjoint` should be |
199 /// domain of the adjointed operator. `Self::Preadjoint` should be |
| 111 /// [`Adjointable`]`<'a,Ypre,X>`. |
200 /// [`Adjointable`]`<'a,Ypre,X>`. |
| 112 /// We do not make additional restrictions on `Self::Preadjoint` (in particular, it |
201 /// We do not make additional restrictions on `Self::Preadjoint` (in particular, it |
| 113 /// does not have to be adjointable) to allow `X` to be a subspace yet the preadjoint |
202 /// does not have to be adjointable) to allow `X` to be a subspace yet the preadjoint |
| 114 /// have the full space as the codomain, etc. |
203 /// have the full space as the codomain, etc. |
| 115 pub trait Preadjointable<X : Space, Ypre : Space> : Linear<X> { |
204 pub trait Preadjointable<X: Space, Ypre: Space = <Self as Mapping<X>>::Codomain>: |
| 116 type PreadjointCodomain : Space; |
205 Linear<X> |
| 117 type Preadjoint<'a> : Linear< |
206 { |
| 118 Ypre, Codomain=Self::PreadjointCodomain |
207 type PreadjointCodomain: ClosedSpace; |
| 119 > where Self : 'a; |
208 type Preadjoint<'a>: Linear<Ypre, Codomain = Self::PreadjointCodomain> |
| |
209 where |
| |
210 Self: 'a; |
| 120 |
211 |
| 121 /// Form the adjoint operator of `self`. |
212 /// Form the adjoint operator of `self`. |
| 122 fn preadjoint(&self) -> Self::Preadjoint<'_>; |
213 fn preadjoint(&self) -> Self::Preadjoint<'_>; |
| 123 } |
214 } |
| 124 |
215 |
| 125 /// Adjointable operators $A: X → Y$ between reflexive spaces $X$ and $Y$. |
|
| 126 pub trait SimplyAdjointable<X : Space> : Adjointable<X,<Self as Mapping<X>>::Codomain> {} |
|
| 127 impl<'a,X : Space, T> SimplyAdjointable<X> for T |
|
| 128 where T : Adjointable<X,<Self as Mapping<X>>::Codomain> {} |
|
| 129 |
|
| 130 /// The identity operator |
216 /// The identity operator |
| 131 #[derive(Clone,Copy,Debug,Serialize,Eq,PartialEq)] |
217 #[derive(Clone, Copy, Debug, Serialize, Eq, PartialEq)] |
| 132 pub struct IdOp<X> (PhantomData<X>); |
218 pub struct IdOp<X>(PhantomData<X>); |
| 133 |
219 |
| 134 impl<X> IdOp<X> { |
220 impl<X> IdOp<X> { |
| 135 pub fn new() -> IdOp<X> { IdOp(PhantomData) } |
221 pub fn new() -> IdOp<X> { |
| 136 } |
222 IdOp(PhantomData) |
| 137 |
223 } |
| 138 impl<X : Clone + Space> Mapping<X> for IdOp<X> { |
224 } |
| 139 type Codomain = X; |
225 |
| 140 |
226 impl<X: Space> Mapping<X> for IdOp<X> { |
| 141 fn apply<I : Instance<X>>(&self, x : I) -> X { |
227 type Codomain = X::Principal; |
| |
228 |
| |
229 fn apply<I: Instance<X>>(&self, x: I) -> Self::Codomain { |
| 142 x.own() |
230 x.own() |
| 143 } |
231 } |
| 144 } |
232 } |
| 145 |
233 |
| 146 impl<X : Clone + Space> Linear<X> for IdOp<X> |
234 impl<X: Space> Linear<X> for IdOp<X> {} |
| 147 { } |
|
| 148 |
235 |
| 149 #[replace_float_literals(F::cast_from(literal))] |
236 #[replace_float_literals(F::cast_from(literal))] |
| 150 impl<F : Num, X, Y> GEMV<F, X, Y> for IdOp<X> |
237 impl<F: Num, X, Y> GEMV<F, X, Y> for IdOp<X> |
| 151 where |
238 where |
| 152 Y : AXPY<F, X>, |
239 Y: AXPY<X, Field = F>, |
| 153 X : Clone + Space |
240 X: Space, |
| 154 { |
241 { |
| 155 // Computes `y = αAx + βy`, where `A` is `Self`. |
242 // Computes `y = αAx + βy`, where `A` is `Self`. |
| 156 fn gemv<I : Instance<X>>(&self, y : &mut Y, α : F, x : I, β : F) { |
243 fn gemv<I: Instance<X>>(&self, y: &mut Y, α: F, x: I, β: F) { |
| 157 y.axpy(α, x, β) |
244 y.axpy(α, x, β) |
| 158 } |
245 } |
| 159 |
246 |
| 160 fn apply_mut<I : Instance<X>>(&self, y : &mut Y, x : I){ |
247 fn apply_mut<I: Instance<X>>(&self, y: &mut Y, x: I) { |
| 161 y.copy_from(x); |
248 y.copy_from(x); |
| 162 } |
249 } |
| 163 } |
250 } |
| 164 |
251 |
| 165 impl<F, X, E> BoundedLinear<X, E, E, F> for IdOp<X> |
252 impl<F, X, E> BoundedLinear<X, E, E, F> for IdOp<X> |
| 166 where |
253 where |
| 167 X : Space + Clone + Norm<F, E>, |
254 X: Space + Clone, |
| 168 F : Num, |
255 F: Num, |
| 169 E : NormExponent |
256 E: NormExponent, |
| 170 { |
257 { |
| 171 fn opnorm_bound(&self, _xexp : E, _codexp : E) -> F { F::ONE } |
258 fn opnorm_bound(&self, _xexp: E, _codexp: E) -> DynResult<F> { |
| 172 } |
259 Ok(F::ONE) |
| 173 |
260 } |
| 174 impl<X : Clone + Space> Adjointable<X,X> for IdOp<X> { |
261 } |
| 175 type AdjointCodomain=X; |
262 |
| 176 type Adjoint<'a> = IdOp<X> where X : 'a; |
263 impl<X: Clone + Space> Adjointable<X, X::Principal> for IdOp<X> { |
| 177 |
264 type AdjointCodomain = X::Principal; |
| 178 fn adjoint(&self) -> Self::Adjoint<'_> { IdOp::new() } |
265 type Adjoint<'a> |
| 179 } |
266 = IdOp<X::Principal> |
| 180 |
267 where |
| 181 impl<X : Clone + Space> Preadjointable<X,X> for IdOp<X> { |
268 X: 'a; |
| 182 type PreadjointCodomain=X; |
269 |
| 183 type Preadjoint<'a> = IdOp<X> where X : 'a; |
270 fn adjoint(&self) -> Self::Adjoint<'_> { |
| 184 |
271 IdOp::new() |
| 185 fn preadjoint(&self) -> Self::Preadjoint<'_> { IdOp::new() } |
272 } |
| 186 } |
273 } |
| 187 |
274 |
| 188 |
275 impl<X: Clone + Space> SimplyAdjointable<X, X::Principal> for IdOp<X> { |
| 189 /// The zero operator |
276 type AdjointCodomain = X::Principal; |
| 190 #[derive(Clone,Copy,Debug,Serialize,Eq,PartialEq)] |
277 type SimpleAdjoint = IdOp<X::Principal>; |
| 191 pub struct ZeroOp<'a, X, XD, Y, F> { |
278 |
| 192 zero : &'a Y, // TODO: don't pass this in `new`; maybe not even store. |
279 fn adjoint(&self) -> Self::SimpleAdjoint { |
| 193 dual_or_predual_zero : XD, |
280 IdOp::new() |
| 194 _phantoms : PhantomData<(X, Y, F)>, |
281 } |
| 195 } |
282 } |
| 196 |
283 |
| 197 // TODO: Need to make Zero in Instance. |
284 impl<X: Clone + Space> Preadjointable<X, X::Principal> for IdOp<X> { |
| 198 |
285 type PreadjointCodomain = X::Principal; |
| 199 impl<'a, F : Num, X : Space, XD, Y : Space + Clone> ZeroOp<'a, X, XD, Y, F> { |
286 type Preadjoint<'a> |
| 200 pub fn new(zero : &'a Y, dual_or_predual_zero : XD) -> Self { |
287 = IdOp<X::Principal> |
| 201 ZeroOp{ zero, dual_or_predual_zero, _phantoms : PhantomData } |
288 where |
| 202 } |
289 X: 'a; |
| 203 } |
290 |
| 204 |
291 fn preadjoint(&self) -> Self::Preadjoint<'_> { |
| 205 impl<'a, F : Num, X : Space, XD, Y : AXPY<F> + Clone> Mapping<X> for ZeroOp<'a, X, XD, Y, F> { |
292 IdOp::new() |
| 206 type Codomain = Y; |
293 } |
| 207 |
294 } |
| 208 fn apply<I : Instance<X>>(&self, _x : I) -> Y { |
295 |
| 209 self.zero.clone() |
296 /// The zero operator from a space to itself |
| 210 } |
297 #[derive(Clone, Copy, Debug, Serialize, Eq, PartialEq)] |
| 211 } |
298 pub struct SimpleZeroOp; |
| 212 |
299 |
| 213 impl<'a, F : Num, X : Space, XD, Y : AXPY<F> + Clone> Linear<X> for ZeroOp<'a, X, XD, Y, F> |
300 impl<X: VectorSpace> Mapping<X> for SimpleZeroOp { |
| 214 { } |
301 type Codomain = X::PrincipalV; |
| |
302 |
| |
303 fn apply<I: Instance<X>>(&self, x: I) -> X::PrincipalV { |
| |
304 X::similar_origin_inst(x) |
| |
305 } |
| |
306 } |
| |
307 |
| |
308 impl<X: VectorSpace> Linear<X> for SimpleZeroOp {} |
| 215 |
309 |
| 216 #[replace_float_literals(F::cast_from(literal))] |
310 #[replace_float_literals(F::cast_from(literal))] |
| 217 impl<'a, F, X, XD, Y> GEMV<F, X, Y> for ZeroOp<'a, X, XD, Y, F> |
311 impl<X, Y, F> GEMV<F, X, Y> for SimpleZeroOp |
| 218 where |
312 where |
| 219 F : Num, |
313 F: Num, |
| 220 Y : AXPY<F, Y> + Clone, |
314 Y: AXPY<Field = F>, |
| 221 X : Space |
315 X: VectorSpace<Field = F> + Instance<X>, |
| 222 { |
316 { |
| 223 // Computes `y = αAx + βy`, where `A` is `Self`. |
317 // Computes `y = αAx + βy`, where `A` is `Self`. |
| 224 fn gemv<I : Instance<X>>(&self, y : &mut Y, _α : F, _x : I, β : F) { |
318 fn gemv<I: Instance<X>>(&self, y: &mut Y, _α: F, _x: I, β: F) { |
| 225 *y *= β; |
319 *y *= β; |
| 226 } |
320 } |
| 227 |
321 |
| 228 fn apply_mut<I : Instance<X>>(&self, y : &mut Y, _x : I){ |
322 fn apply_mut<I: Instance<X>>(&self, y: &mut Y, _x: I) { |
| 229 y.set_zero(); |
323 y.set_zero(); |
| 230 } |
324 } |
| 231 } |
325 } |
| 232 |
326 |
| 233 impl<'a, F, X, XD, Y, E1, E2> BoundedLinear<X, E1, E2, F> for ZeroOp<'a, X, XD, Y, F> |
327 impl<X, F, E1, E2> BoundedLinear<X, E1, E2, F> for SimpleZeroOp |
| 234 where |
328 where |
| 235 X : Space + Norm<F, E1>, |
329 F: Num, |
| 236 Y : AXPY<F> + Clone + Norm<F, E2>, |
330 X: VectorSpace<Field = F>, |
| 237 F : Num, |
331 E1: NormExponent, |
| 238 E1 : NormExponent, |
332 E2: NormExponent, |
| 239 E2 : NormExponent, |
333 { |
| 240 { |
334 fn opnorm_bound(&self, _xexp: E1, _codexp: E2) -> DynResult<F> { |
| 241 fn opnorm_bound(&self, _xexp : E1, _codexp : E2) -> F { F::ZERO } |
335 Ok(F::ZERO) |
| 242 } |
336 } |
| 243 |
337 } |
| 244 impl<'a, F : Num, X, XD, Y, Yprime : Space> Adjointable<X, Yprime> for ZeroOp<'a, X, XD, Y, F> |
338 |
| 245 where |
339 impl<X, F> Adjointable<X, X::DualSpace> for SimpleZeroOp |
| 246 X : Space, |
340 where |
| 247 Y : AXPY<F> + Clone + 'static, |
341 F: Num, |
| 248 XD : AXPY<F> + Clone + 'static, |
342 X: VectorSpace<Field = F> + HasDual<F>, |
| 249 { |
343 X::DualSpace: ClosedVectorSpace, |
| 250 type AdjointCodomain = XD; |
344 { |
| 251 type Adjoint<'b> = ZeroOp<'b, Yprime, (), XD, F> where Self : 'b; |
345 type AdjointCodomain = X::DualSpace; |
| 252 // () means not (pre)adjointable. |
346 type Adjoint<'b> |
| |
347 = SimpleZeroOp |
| |
348 where |
| |
349 Self: 'b; |
| |
350 // () means not (pre)adjointable. |
| 253 |
351 |
| 254 fn adjoint(&self) -> Self::Adjoint<'_> { |
352 fn adjoint(&self) -> Self::Adjoint<'_> { |
| 255 ZeroOp::new(&self.dual_or_predual_zero, ()) |
353 SimpleZeroOp |
| 256 } |
354 } |
| 257 } |
355 } |
| 258 |
356 |
| 259 impl<'a, F, X, XD, Y, Ypre> Preadjointable<X, Ypre> for ZeroOp<'a, X, XD, Y, F> |
357 pub trait OriginGenerator<Y: VectorSpace> { |
| 260 where |
358 type Ref<'b>: OriginGenerator<Y> |
| 261 F : Num, |
359 where |
| 262 X : Space, |
360 Self: 'b; |
| 263 Y : AXPY<F> + Clone, |
361 |
| 264 Ypre : Space, |
362 fn origin(&self) -> Y::PrincipalV; |
| 265 XD : AXPY<F> + Clone + 'static, |
363 fn as_ref(&self) -> Self::Ref<'_>; |
| 266 { |
364 } |
| 267 type PreadjointCodomain = XD; |
365 |
| 268 type Preadjoint<'b> = ZeroOp<'b, Ypre, (), XD, F> where Self : 'b; |
366 #[derive(Copy, Clone, Debug)] |
| 269 // () means not (pre)adjointable. |
367 pub struct StaticEuclideanOriginGenerator; |
| 270 |
368 |
| 271 fn preadjoint(&self) -> Self::Preadjoint<'_> { |
369 impl<Y: StaticEuclidean<F, Field = F>, F: Float> OriginGenerator<Y> |
| 272 ZeroOp::new(&self.dual_or_predual_zero, ()) |
370 for StaticEuclideanOriginGenerator |
| |
371 { |
| |
372 type Ref<'b> |
| |
373 = Self |
| |
374 where |
| |
375 Self: 'b; |
| |
376 |
| |
377 #[inline] |
| |
378 fn origin(&self) -> Y::PrincipalV { |
| |
379 return Y::origin(); |
| |
380 } |
| |
381 |
| |
382 #[inline] |
| |
383 fn as_ref(&self) -> Self::Ref<'_> { |
| |
384 *self |
| |
385 } |
| |
386 } |
| |
387 |
| |
388 impl<Y: VectorSpace> OriginGenerator<Y> for Y { |
| |
389 type Ref<'b> |
| |
390 = &'b Y |
| |
391 where |
| |
392 Self: 'b; |
| |
393 |
| |
394 #[inline] |
| |
395 fn origin(&self) -> Y::PrincipalV { |
| |
396 return self.similar_origin(); |
| |
397 } |
| |
398 |
| |
399 #[inline] |
| |
400 fn as_ref(&self) -> Self::Ref<'_> { |
| |
401 self |
| |
402 } |
| |
403 } |
| |
404 |
| |
405 impl<'b, Y: VectorSpace> OriginGenerator<Y> for &'b Y { |
| |
406 type Ref<'c> |
| |
407 = Self |
| |
408 where |
| |
409 Self: 'c; |
| |
410 |
| |
411 #[inline] |
| |
412 fn origin(&self) -> Y::PrincipalV { |
| |
413 return self.similar_origin(); |
| |
414 } |
| |
415 |
| |
416 #[inline] |
| |
417 fn as_ref(&self) -> Self::Ref<'_> { |
| |
418 self |
| |
419 } |
| |
420 } |
| |
421 |
| |
422 /// A zero operator that can be eitherh dualised or predualised (once). |
| |
423 /// This is achieved by storing an oppropriate zero. |
| |
424 pub struct ZeroOp<X, Y: VectorSpace<Field = F>, OY: OriginGenerator<Y>, O, F: Float = f64> { |
| |
425 codomain_origin_generator: OY, |
| |
426 other_origin_generator: O, |
| |
427 _phantoms: PhantomData<(X, Y, F)>, |
| |
428 } |
| |
429 |
| |
430 impl<X, Y, OY, F> ZeroOp<X, Y, OY, (), F> |
| |
431 where |
| |
432 OY: OriginGenerator<Y>, |
| |
433 X: VectorSpace<Field = F>, |
| |
434 Y: VectorSpace<Field = F>, |
| |
435 F: Float, |
| |
436 { |
| |
437 pub fn new(y_og: OY) -> Self { |
| |
438 ZeroOp { |
| |
439 codomain_origin_generator: y_og, |
| |
440 other_origin_generator: (), |
| |
441 _phantoms: PhantomData, |
| |
442 } |
| |
443 } |
| |
444 } |
| |
445 |
| |
446 impl<X, Y, OY, OXprime, Xprime, Yprime, F> ZeroOp<X, Y, OY, OXprime, F> |
| |
447 where |
| |
448 OY: OriginGenerator<Y>, |
| |
449 OXprime: OriginGenerator<Xprime>, |
| |
450 X: HasDual<F, DualSpace = Xprime>, |
| |
451 Y: HasDual<F, DualSpace = Yprime>, |
| |
452 F: Float, |
| |
453 Xprime: VectorSpace<Field = F, PrincipalV = Xprime>, |
| |
454 Xprime::PrincipalV: AXPY<Field = F>, |
| |
455 Yprime: Space + Instance<Yprime>, |
| |
456 { |
| |
457 pub fn new_dualisable(y_og: OY, xprime_og: OXprime) -> Self { |
| |
458 ZeroOp { |
| |
459 codomain_origin_generator: y_og, |
| |
460 other_origin_generator: xprime_og, |
| |
461 _phantoms: PhantomData, |
| |
462 } |
| |
463 } |
| |
464 } |
| |
465 |
| |
466 impl<X, Y, O, OY, F> Mapping<X> for ZeroOp<X, Y, OY, O, F> |
| |
467 where |
| |
468 X: Space, |
| |
469 Y: VectorSpace<Field = F>, |
| |
470 F: Float, |
| |
471 OY: OriginGenerator<Y>, |
| |
472 { |
| |
473 type Codomain = Y::PrincipalV; |
| |
474 |
| |
475 fn apply<I: Instance<X>>(&self, _x: I) -> Y::PrincipalV { |
| |
476 self.codomain_origin_generator.origin() |
| |
477 } |
| |
478 } |
| |
479 |
| |
480 impl<X, Y, OY, O, F> Linear<X> for ZeroOp<X, Y, OY, O, F> |
| |
481 where |
| |
482 X: Space, |
| |
483 Y: VectorSpace<Field = F>, |
| |
484 F: Float, |
| |
485 OY: OriginGenerator<Y>, |
| |
486 { |
| |
487 } |
| |
488 |
| |
489 #[replace_float_literals(F::cast_from(literal))] |
| |
490 impl<X, Y, OY, O, F> GEMV<F, X, Y> for ZeroOp<X, Y, OY, O, F> |
| |
491 where |
| |
492 X: Space, |
| |
493 Y: AXPY<Field = F, PrincipalV = Y>, |
| |
494 F: Float, |
| |
495 OY: OriginGenerator<Y>, |
| |
496 { |
| |
497 // Computes `y = αAx + βy`, where `A` is `Self`. |
| |
498 fn gemv<I: Instance<X>>(&self, y: &mut Y, _α: F, _x: I, β: F) { |
| |
499 *y *= β; |
| |
500 } |
| |
501 |
| |
502 fn apply_mut<I: Instance<X>>(&self, y: &mut Y, _x: I) { |
| |
503 y.set_zero(); |
| |
504 } |
| |
505 } |
| |
506 |
| |
507 impl<X, Y, OY, O, F, E1, E2> BoundedLinear<X, E1, E2, F> for ZeroOp<X, Y, OY, O, F> |
| |
508 where |
| |
509 X: Space + Instance<X>, |
| |
510 Y: VectorSpace<Field = F>, |
| |
511 Y::PrincipalV: Clone, |
| |
512 F: Float, |
| |
513 E1: NormExponent, |
| |
514 E2: NormExponent, |
| |
515 OY: OriginGenerator<Y>, |
| |
516 { |
| |
517 fn opnorm_bound(&self, _xexp: E1, _codexp: E2) -> DynResult<F> { |
| |
518 Ok(F::ZERO) |
| |
519 } |
| |
520 } |
| |
521 |
| |
522 impl<'b, X, Y, OY, OXprime, Xprime, Yprime, F> Adjointable<X, Yprime> |
| |
523 for ZeroOp<X, Y, OY, OXprime, F> |
| |
524 where |
| |
525 X: HasDual<F, DualSpace = Xprime>, |
| |
526 Y: HasDual<F, DualSpace = Yprime>, |
| |
527 F: Float, |
| |
528 Xprime: ClosedVectorSpace<Field = F>, |
| |
529 //Xprime::Owned: AXPY<Field = F>, |
| |
530 Yprime: ClosedSpace, |
| |
531 OY: OriginGenerator<Y>, |
| |
532 OXprime: OriginGenerator<X::DualSpace>, |
| |
533 { |
| |
534 type AdjointCodomain = Xprime; |
| |
535 type Adjoint<'c> |
| |
536 = ZeroOp<Yprime, Xprime, OXprime::Ref<'c>, (), F> |
| |
537 where |
| |
538 Self: 'c; |
| |
539 // () means not (pre)adjointable. |
| |
540 |
| |
541 fn adjoint(&self) -> Self::Adjoint<'_> { |
| |
542 ZeroOp { |
| |
543 codomain_origin_generator: self.other_origin_generator.as_ref(), |
| |
544 other_origin_generator: (), |
| |
545 _phantoms: PhantomData, |
| |
546 } |
| |
547 } |
| |
548 } |
| |
549 |
| |
550 impl<'b, X, Y, OY, OXprime, Xprime, Yprime, F> SimplyAdjointable<X, Yprime> |
| |
551 for ZeroOp<X, Y, OY, OXprime, F> |
| |
552 where |
| |
553 X: HasDual<F, DualSpace = Xprime>, |
| |
554 Y: HasDual<F, DualSpace = Yprime>, |
| |
555 F: Float, |
| |
556 Xprime: ClosedVectorSpace<Field = F>, |
| |
557 //Xprime::Owned: AXPY<Field = F>, |
| |
558 Yprime: ClosedSpace, |
| |
559 OY: OriginGenerator<Y>, |
| |
560 OXprime: OriginGenerator<X::DualSpace> + Clone, |
| |
561 { |
| |
562 type AdjointCodomain = Xprime; |
| |
563 type SimpleAdjoint = ZeroOp<Yprime, Xprime, OXprime, (), F>; |
| |
564 // () means not (pre)adjointable. |
| |
565 |
| |
566 fn adjoint(&self) -> Self::SimpleAdjoint { |
| |
567 ZeroOp { |
| |
568 codomain_origin_generator: self.other_origin_generator.clone(), |
| |
569 other_origin_generator: (), |
| |
570 _phantoms: PhantomData, |
| |
571 } |
| 273 } |
572 } |
| 274 } |
573 } |
| 275 |
574 |
| 276 impl<S, T, E, X> Linear<X> for Composition<S, T, E> |
575 impl<S, T, E, X> Linear<X> for Composition<S, T, E> |
| 277 where |
576 where |
| 278 X : Space, |
577 X: Space, |
| 279 T : Linear<X>, |
578 T: Linear<X>, |
| 280 S : Linear<T::Codomain> |
579 S: Linear<T::Codomain>, |
| 281 { } |
580 { |
| |
581 } |
| 282 |
582 |
| 283 impl<F, S, T, E, X, Y> GEMV<F, X, Y> for Composition<S, T, E> |
583 impl<F, S, T, E, X, Y> GEMV<F, X, Y> for Composition<S, T, E> |
| 284 where |
584 where |
| 285 F : Num, |
585 F: Num, |
| 286 X : Space, |
586 X: Space, |
| 287 T : Linear<X>, |
587 T: Linear<X>, |
| 288 S : GEMV<F, T::Codomain, Y>, |
588 S: GEMV<F, T::Codomain, Y>, |
| 289 { |
589 { |
| 290 fn gemv<I : Instance<X>>(&self, y : &mut Y, α : F, x : I, β : F) { |
590 fn gemv<I: Instance<X>>(&self, y: &mut Y, α: F, x: I, β: F) { |
| 291 self.outer.gemv(y, α, self.inner.apply(x), β) |
591 self.outer.gemv(y, α, self.inner.apply(x), β) |
| 292 } |
592 } |
| 293 |
593 |
| 294 /// Computes `y = Ax`, where `A` is `Self` |
594 /// Computes `y = Ax`, where `A` is `Self` |
| 295 fn apply_mut<I : Instance<X>>(&self, y : &mut Y, x : I){ |
595 fn apply_mut<I: Instance<X>>(&self, y: &mut Y, x: I) { |
| 296 self.outer.apply_mut(y, self.inner.apply(x)) |
596 self.outer.apply_mut(y, self.inner.apply(x)) |
| 297 } |
597 } |
| 298 |
598 |
| 299 /// Computes `y += Ax`, where `A` is `Self` |
599 /// Computes `y += Ax`, where `A` is `Self` |
| 300 fn apply_add<I : Instance<X>>(&self, y : &mut Y, x : I){ |
600 fn apply_add<I: Instance<X>>(&self, y: &mut Y, x: I) { |
| 301 self.outer.apply_add(y, self.inner.apply(x)) |
601 self.outer.apply_add(y, self.inner.apply(x)) |
| 302 } |
602 } |
| 303 } |
603 } |
| 304 |
604 |
| 305 impl<F, S, T, X, Z, Xexp, Yexp, Zexp> BoundedLinear<X, Xexp, Yexp, F> for Composition<S, T, Zexp> |
605 impl<F, S, T, X, Z, Xexp, Yexp, Zexp> BoundedLinear<X, Xexp, Yexp, F> for Composition<S, T, Zexp> |
| 306 where |
606 where |
| 307 F : Num, |
607 F: Num, |
| 308 X : Space + Norm<F, Xexp>, |
608 X: Space, |
| 309 Z : Space + Norm<F, Zexp>, |
609 Z: Space, |
| 310 Xexp : NormExponent, |
610 Xexp: NormExponent, |
| 311 Yexp : NormExponent, |
611 Yexp: NormExponent, |
| 312 Zexp : NormExponent, |
612 Zexp: NormExponent, |
| 313 T : BoundedLinear<X, Xexp, Zexp, F, Codomain=Z>, |
613 T: BoundedLinear<X, Xexp, Zexp, F, Codomain = Z>, |
| 314 S : BoundedLinear<Z, Zexp, Yexp, F>, |
614 S: BoundedLinear<Z, Zexp, Yexp, F>, |
| 315 { |
615 { |
| 316 fn opnorm_bound(&self, xexp : Xexp, yexp : Yexp) -> F { |
616 fn opnorm_bound(&self, xexp: Xexp, yexp: Yexp) -> DynResult<F> { |
| 317 let zexp = self.intermediate_norm_exponent; |
617 let zexp = self.intermediate_norm_exponent; |
| 318 self.outer.opnorm_bound(zexp, yexp) * self.inner.opnorm_bound(xexp, zexp) |
618 Ok(self.outer.opnorm_bound(zexp, yexp)? * self.inner.opnorm_bound(xexp, zexp)?) |
| 319 } |
619 } |
| 320 } |
620 } |
| 321 |
621 |
| 322 /// “Row operator” $(S, T)$; $(S, T)(x, y)=Sx + Ty$. |
622 /// “Row operator” $(S, T)$; $(S, T)(x, y)=Sx + Ty$. |
| |
623 #[derive(Clone, Copy, Debug, Serialize, Eq, PartialEq)] |
| 323 pub struct RowOp<S, T>(pub S, pub T); |
624 pub struct RowOp<S, T>(pub S, pub T); |
| 324 |
625 |
| 325 use std::ops::Add; |
|
| 326 |
|
| 327 impl<A, B, S, T> Mapping<Pair<A, B>> for RowOp<S, T> |
626 impl<A, B, S, T> Mapping<Pair<A, B>> for RowOp<S, T> |
| 328 where |
627 where |
| 329 A : Space, |
628 A: Space, |
| 330 B : Space, |
629 B: Space, |
| 331 S : Mapping<A>, |
630 S: Mapping<A>, |
| 332 T : Mapping<B>, |
631 T: Mapping<B>, |
| 333 S::Codomain : Add<T::Codomain>, |
632 S::Codomain: Add<T::Codomain>, |
| 334 <S::Codomain as Add<T::Codomain>>::Output : Space, |
633 <S::Codomain as Add<T::Codomain>>::Output: ClosedSpace, |
| 335 |
|
| 336 { |
634 { |
| 337 type Codomain = <S::Codomain as Add<T::Codomain>>::Output; |
635 type Codomain = <S::Codomain as Add<T::Codomain>>::Output; |
| 338 |
636 |
| 339 fn apply<I : Instance<Pair<A, B>>>(&self, x : I) -> Self::Codomain { |
637 fn apply<I: Instance<Pair<A, B>>>(&self, x: I) -> Self::Codomain { |
| 340 let Pair(a, b) = x.decompose(); |
638 x.eval_decompose(|Pair(a, b)| self.0.apply(a) + self.1.apply(b)) |
| 341 self.0.apply(a) + self.1.apply(b) |
|
| 342 } |
639 } |
| 343 } |
640 } |
| 344 |
641 |
| 345 impl<A, B, S, T> Linear<Pair<A, B>> for RowOp<S, T> |
642 impl<A, B, S, T> Linear<Pair<A, B>> for RowOp<S, T> |
| 346 where |
643 where |
| 347 A : Space, |
644 A: Space, |
| 348 B : Space, |
645 B: Space, |
| 349 S : Linear<A>, |
646 S: Linear<A>, |
| 350 T : Linear<B>, |
647 T: Linear<B>, |
| 351 S::Codomain : Add<T::Codomain>, |
648 S::Codomain: Add<T::Codomain>, |
| 352 <S::Codomain as Add<T::Codomain>>::Output : Space, |
649 <S::Codomain as Add<T::Codomain>>::Output: ClosedSpace, |
| 353 { } |
650 { |
| 354 |
651 } |
| 355 |
652 |
| 356 impl<'b, F, S, T, Y, U, V> GEMV<F, Pair<U, V>, Y> for RowOp<S, T> |
653 impl<'b, F, S, T, Y, U, V> GEMV<F, Pair<U, V>, Y> for RowOp<S, T> |
| 357 where |
654 where |
| 358 U : Space, |
655 U: Space, |
| 359 V : Space, |
656 V: Space, |
| 360 S : GEMV<F, U, Y>, |
657 S: GEMV<F, U, Y>, |
| 361 T : GEMV<F, V, Y>, |
658 T: GEMV<F, V, Y>, |
| 362 F : Num, |
659 F: Num, |
| 363 Self : Linear<Pair<U, V>, Codomain=Y> |
660 Self: Linear<Pair<U, V>, Codomain = Y>, |
| 364 { |
661 { |
| 365 fn gemv<I : Instance<Pair<U, V>>>(&self, y : &mut Y, α : F, x : I, β : F) { |
662 fn gemv<I: Instance<Pair<U, V>>>(&self, y: &mut Y, α: F, x: I, β: F) { |
| 366 let Pair(u, v) = x.decompose(); |
663 x.eval_decompose(|Pair(u, v)| { |
| 367 self.0.gemv(y, α, u, β); |
664 self.0.gemv(y, α, u, β); |
| 368 self.1.gemv(y, α, v, F::ONE); |
665 self.1.gemv(y, α, v, F::ONE); |
| 369 } |
666 }) |
| 370 |
667 } |
| 371 fn apply_mut<I : Instance<Pair<U, V>>>(&self, y : &mut Y, x : I) { |
668 |
| 372 let Pair(u, v) = x.decompose(); |
669 fn apply_mut<I: Instance<Pair<U, V>>>(&self, y: &mut Y, x: I) { |
| 373 self.0.apply_mut(y, u); |
670 x.eval_decompose(|Pair(u, v)| { |
| 374 self.1.apply_add(y, v); |
671 self.0.apply_mut(y, u); |
| |
672 self.1.apply_add(y, v); |
| |
673 }) |
| 375 } |
674 } |
| 376 |
675 |
| 377 /// Computes `y += Ax`, where `A` is `Self` |
676 /// Computes `y += Ax`, where `A` is `Self` |
| 378 fn apply_add<I : Instance<Pair<U, V>>>(&self, y : &mut Y, x : I) { |
677 fn apply_add<I: Instance<Pair<U, V>>>(&self, y: &mut Y, x: I) { |
| 379 let Pair(u, v) = x.decompose(); |
678 x.eval_decompose(|Pair(u, v)| { |
| 380 self.0.apply_add(y, u); |
679 self.0.apply_add(y, u); |
| 381 self.1.apply_add(y, v); |
680 self.1.apply_add(y, v); |
| |
681 }) |
| 382 } |
682 } |
| 383 } |
683 } |
| 384 |
684 |
| 385 /// “Column operator” $(S; T)$; $(S; T)x=(Sx, Tx)$. |
685 /// “Column operator” $(S; T)$; $(S; T)x=(Sx, Tx)$. |
| |
686 #[derive(Clone, Copy, Debug, Serialize, Eq, PartialEq)] |
| 386 pub struct ColOp<S, T>(pub S, pub T); |
687 pub struct ColOp<S, T>(pub S, pub T); |
| 387 |
688 |
| 388 impl<A, S, T> Mapping<A> for ColOp<S, T> |
689 impl<A, S, T> Mapping<A> for ColOp<S, T> |
| 389 where |
690 where |
| 390 A : Space, |
691 A: Space, |
| 391 S : Mapping<A>, |
692 S: Mapping<A>, |
| 392 T : Mapping<A>, |
693 T: Mapping<A>, |
| 393 { |
694 { |
| 394 type Codomain = Pair<S::Codomain, T::Codomain>; |
695 type Codomain = Pair<S::Codomain, T::Codomain>; |
| 395 |
696 |
| 396 fn apply<I : Instance<A>>(&self, a : I) -> Self::Codomain { |
697 fn apply<I: Instance<A>>(&self, a: I) -> Self::Codomain { |
| 397 Pair(self.0.apply(a.ref_instance()), self.1.apply(a)) |
698 Pair(a.eval_ref(|r| self.0.apply(r)), self.1.apply(a)) |
| 398 } |
699 } |
| 399 } |
700 } |
| 400 |
701 |
| 401 impl<A, S, T> Linear<A> for ColOp<S, T> |
702 impl<A, S, T> Linear<A> for ColOp<S, T> |
| 402 where |
703 where |
| 403 A : Space, |
704 A: Space, |
| 404 S : Mapping<A>, |
705 S: Mapping<A>, |
| 405 T : Mapping<A>, |
706 T: Mapping<A>, |
| 406 { } |
707 { |
| |
708 } |
| 407 |
709 |
| 408 impl<F, S, T, A, B, X> GEMV<F, X, Pair<A, B>> for ColOp<S, T> |
710 impl<F, S, T, A, B, X> GEMV<F, X, Pair<A, B>> for ColOp<S, T> |
| 409 where |
711 where |
| 410 X : Space, |
712 X: Space, |
| 411 S : GEMV<F, X, A>, |
713 S: GEMV<F, X, A>, |
| 412 T : GEMV<F, X, B>, |
714 T: GEMV<F, X, B>, |
| 413 F : Num, |
715 F: Num, |
| 414 Self : Linear<X, Codomain=Pair<A, B>> |
716 Self: Linear<X, Codomain = Pair<A, B>>, |
| 415 { |
717 { |
| 416 fn gemv<I : Instance<X>>(&self, y : &mut Pair<A, B>, α : F, x : I, β : F) { |
718 fn gemv<I: Instance<X>>(&self, y: &mut Pair<A, B>, α: F, x: I, β: F) { |
| 417 self.0.gemv(&mut y.0, α, x.ref_instance(), β); |
719 x.eval_ref(|r| self.0.gemv(&mut y.0, α, r, β)); |
| 418 self.1.gemv(&mut y.1, α, x, β); |
720 self.1.gemv(&mut y.1, α, x, β); |
| 419 } |
721 } |
| 420 |
722 |
| 421 fn apply_mut<I : Instance<X>>(&self, y : &mut Pair<A, B>, x : I){ |
723 fn apply_mut<I: Instance<X>>(&self, y: &mut Pair<A, B>, x: I) { |
| 422 self.0.apply_mut(&mut y.0, x.ref_instance()); |
724 x.eval_ref(|r| self.0.apply_mut(&mut y.0, r)); |
| 423 self.1.apply_mut(&mut y.1, x); |
725 self.1.apply_mut(&mut y.1, x); |
| 424 } |
726 } |
| 425 |
727 |
| 426 /// Computes `y += Ax`, where `A` is `Self` |
728 /// Computes `y += Ax`, where `A` is `Self` |
| 427 fn apply_add<I : Instance<X>>(&self, y : &mut Pair<A, B>, x : I){ |
729 fn apply_add<I: Instance<X>>(&self, y: &mut Pair<A, B>, x: I) { |
| 428 self.0.apply_add(&mut y.0, x.ref_instance()); |
730 x.eval_ref(|r| self.0.apply_add(&mut y.0, r)); |
| 429 self.1.apply_add(&mut y.1, x); |
731 self.1.apply_add(&mut y.1, x); |
| 430 } |
732 } |
| 431 } |
733 } |
| 432 |
734 |
| 433 |
735 impl<A, B, Yʹ, S, T> Adjointable<Pair<A, B>, Yʹ> for RowOp<S, T> |
| 434 impl<A, B, Yʹ, S, T> Adjointable<Pair<A,B>, Yʹ> for RowOp<S, T> |
736 where |
| 435 where |
737 A: Space, |
| 436 A : Space, |
738 B: Space, |
| 437 B : Space, |
739 Yʹ: Space, |
| 438 Yʹ : Space, |
740 S: Adjointable<A, Yʹ>, |
| 439 S : Adjointable<A, Yʹ>, |
741 T: Adjointable<B, Yʹ>, |
| 440 T : Adjointable<B, Yʹ>, |
742 Self: Linear<Pair<A, B>>, |
| 441 Self : Linear<Pair<A, B>>, |
|
| 442 // for<'a> ColOp<S::Adjoint<'a>, T::Adjoint<'a>> : Linear< |
743 // for<'a> ColOp<S::Adjoint<'a>, T::Adjoint<'a>> : Linear< |
| 443 // Yʹ, |
744 // Yʹ, |
| 444 // Codomain=Pair<S::AdjointCodomain, T::AdjointCodomain> |
745 // Codomain=Pair<S::AdjointCodomain, T::AdjointCodomain> |
| 445 // >, |
746 // >, |
| 446 { |
747 { |
| 447 type AdjointCodomain = Pair<S::AdjointCodomain, T::AdjointCodomain>; |
748 type AdjointCodomain = Pair<S::AdjointCodomain, T::AdjointCodomain>; |
| 448 type Adjoint<'a> = ColOp<S::Adjoint<'a>, T::Adjoint<'a>> where Self : 'a; |
749 type Adjoint<'a> |
| |
750 = ColOp<S::Adjoint<'a>, T::Adjoint<'a>> |
| |
751 where |
| |
752 Self: 'a; |
| 449 |
753 |
| 450 fn adjoint(&self) -> Self::Adjoint<'_> { |
754 fn adjoint(&self) -> Self::Adjoint<'_> { |
| 451 ColOp(self.0.adjoint(), self.1.adjoint()) |
755 ColOp(self.0.adjoint(), self.1.adjoint()) |
| 452 } |
756 } |
| 453 } |
757 } |
| 454 |
758 |
| 455 impl<A, B, Yʹ, S, T> Preadjointable<Pair<A,B>, Yʹ> for RowOp<S, T> |
759 impl<A, B, Yʹ, S, T> SimplyAdjointable<Pair<A, B>, Yʹ> for RowOp<S, T> |
| 456 where |
760 where |
| 457 A : Space, |
761 A: Space, |
| 458 B : Space, |
762 B: Space, |
| 459 Yʹ : Space, |
763 Yʹ: Space, |
| 460 S : Preadjointable<A, Yʹ>, |
764 S: SimplyAdjointable<A, Yʹ>, |
| 461 T : Preadjointable<B, Yʹ>, |
765 T: SimplyAdjointable<B, Yʹ>, |
| 462 Self : Linear<Pair<A, B>>, |
766 Self: Linear<Pair<A, B>>, |
| 463 for<'a> ColOp<S::Preadjoint<'a>, T::Preadjoint<'a>> : Linear< |
767 // for<'a> ColOp<S::Adjoint<'a>, T::Adjoint<'a>> : Linear< |
| 464 Yʹ, Codomain=Pair<S::PreadjointCodomain, T::PreadjointCodomain>, |
768 // Yʹ, |
| 465 >, |
769 // Codomain=Pair<S::AdjointCodomain, T::AdjointCodomain> |
| |
770 // >, |
| |
771 { |
| |
772 type AdjointCodomain = Pair<S::AdjointCodomain, T::AdjointCodomain>; |
| |
773 type SimpleAdjoint = ColOp<S::SimpleAdjoint, T::SimpleAdjoint>; |
| |
774 |
| |
775 fn adjoint(&self) -> Self::SimpleAdjoint { |
| |
776 ColOp(self.0.adjoint(), self.1.adjoint()) |
| |
777 } |
| |
778 } |
| |
779 |
| |
780 impl<A, B, Yʹ, S, T> Preadjointable<Pair<A, B>, Yʹ> for RowOp<S, T> |
| |
781 where |
| |
782 A: Space, |
| |
783 B: Space, |
| |
784 Yʹ: Space, |
| |
785 S: Preadjointable<A, Yʹ>, |
| |
786 T: Preadjointable<B, Yʹ>, |
| |
787 Self: Linear<Pair<A, B>>, |
| |
788 for<'a> ColOp<S::Preadjoint<'a>, T::Preadjoint<'a>>: |
| |
789 Linear<Yʹ, Codomain = Pair<S::PreadjointCodomain, T::PreadjointCodomain>>, |
| 466 { |
790 { |
| 467 type PreadjointCodomain = Pair<S::PreadjointCodomain, T::PreadjointCodomain>; |
791 type PreadjointCodomain = Pair<S::PreadjointCodomain, T::PreadjointCodomain>; |
| 468 type Preadjoint<'a> = ColOp<S::Preadjoint<'a>, T::Preadjoint<'a>> where Self : 'a; |
792 type Preadjoint<'a> |
| |
793 = ColOp<S::Preadjoint<'a>, T::Preadjoint<'a>> |
| |
794 where |
| |
795 Self: 'a; |
| 469 |
796 |
| 470 fn preadjoint(&self) -> Self::Preadjoint<'_> { |
797 fn preadjoint(&self) -> Self::Preadjoint<'_> { |
| 471 ColOp(self.0.preadjoint(), self.1.preadjoint()) |
798 ColOp(self.0.preadjoint(), self.1.preadjoint()) |
| 472 } |
799 } |
| 473 } |
800 } |
| 474 |
801 |
| 475 |
802 impl<A, Xʹ, Yʹ, R, S, T> Adjointable<A, Pair<Xʹ, Yʹ>> for ColOp<S, T> |
| 476 impl<A, Xʹ, Yʹ, R, S, T> Adjointable<A,Pair<Xʹ,Yʹ>> for ColOp<S, T> |
803 where |
| 477 where |
804 A: Space, |
| 478 A : Space, |
805 Xʹ: Space, |
| 479 Xʹ : Space, |
806 Yʹ: Space, |
| 480 Yʹ : Space, |
807 R: ClosedSpace + ClosedAdd, |
| 481 R : Space + ClosedAdd, |
808 S: Adjointable<A, Xʹ, AdjointCodomain = R>, |
| 482 S : Adjointable<A, Xʹ, AdjointCodomain = R>, |
809 T: Adjointable<A, Yʹ, AdjointCodomain = R>, |
| 483 T : Adjointable<A, Yʹ, AdjointCodomain = R>, |
810 Self: Linear<A>, |
| 484 Self : Linear<A>, |
|
| 485 // for<'a> RowOp<S::Adjoint<'a>, T::Adjoint<'a>> : Linear< |
811 // for<'a> RowOp<S::Adjoint<'a>, T::Adjoint<'a>> : Linear< |
| 486 // Pair<Xʹ,Yʹ>, |
812 // Pair<Xʹ,Yʹ>, |
| 487 // Codomain=R, |
813 // Codomain=R, |
| 488 // >, |
814 // >, |
| 489 { |
815 { |
| 490 type AdjointCodomain = R; |
816 type AdjointCodomain = R; |
| 491 type Adjoint<'a> = RowOp<S::Adjoint<'a>, T::Adjoint<'a>> where Self : 'a; |
817 type Adjoint<'a> |
| |
818 = RowOp<S::Adjoint<'a>, T::Adjoint<'a>> |
| |
819 where |
| |
820 Self: 'a; |
| 492 |
821 |
| 493 fn adjoint(&self) -> Self::Adjoint<'_> { |
822 fn adjoint(&self) -> Self::Adjoint<'_> { |
| 494 RowOp(self.0.adjoint(), self.1.adjoint()) |
823 RowOp(self.0.adjoint(), self.1.adjoint()) |
| 495 } |
824 } |
| 496 } |
825 } |
| 497 |
826 |
| 498 impl<A, Xʹ, Yʹ, R, S, T> Preadjointable<A,Pair<Xʹ,Yʹ>> for ColOp<S, T> |
827 impl<A, Xʹ, Yʹ, R, S, T> SimplyAdjointable<A, Pair<Xʹ, Yʹ>> for ColOp<S, T> |
| 499 where |
828 where |
| 500 A : Space, |
829 A: Space, |
| 501 Xʹ : Space, |
830 Xʹ: Space, |
| 502 Yʹ : Space, |
831 Yʹ: Space, |
| 503 R : Space + ClosedAdd, |
832 R: ClosedSpace + ClosedAdd, |
| 504 S : Preadjointable<A, Xʹ, PreadjointCodomain = R>, |
833 S: SimplyAdjointable<A, Xʹ, AdjointCodomain = R>, |
| 505 T : Preadjointable<A, Yʹ, PreadjointCodomain = R>, |
834 T: SimplyAdjointable<A, Yʹ, AdjointCodomain = R>, |
| 506 Self : Linear<A>, |
835 Self: Linear<A>, |
| 507 for<'a> RowOp<S::Preadjoint<'a>, T::Preadjoint<'a>> : Linear< |
836 // for<'a> RowOp<S::Adjoint<'a>, T::Adjoint<'a>> : Linear< |
| 508 Pair<Xʹ,Yʹ>, Codomain = R, |
837 // Pair<Xʹ,Yʹ>, |
| 509 >, |
838 // Codomain=R, |
| |
839 // >, |
| |
840 { |
| |
841 type AdjointCodomain = R; |
| |
842 type SimpleAdjoint = RowOp<S::SimpleAdjoint, T::SimpleAdjoint>; |
| |
843 |
| |
844 fn adjoint(&self) -> Self::SimpleAdjoint { |
| |
845 RowOp(self.0.adjoint(), self.1.adjoint()) |
| |
846 } |
| |
847 } |
| |
848 |
| |
849 impl<A, Xʹ, Yʹ, R, S, T> Preadjointable<A, Pair<Xʹ, Yʹ>> for ColOp<S, T> |
| |
850 where |
| |
851 A: Space, |
| |
852 Xʹ: Space, |
| |
853 Yʹ: Space, |
| |
854 R: ClosedSpace + ClosedAdd, |
| |
855 S: Preadjointable<A, Xʹ, PreadjointCodomain = R>, |
| |
856 T: Preadjointable<A, Yʹ, PreadjointCodomain = R>, |
| |
857 Self: Linear<A>, |
| |
858 for<'a> RowOp<S::Preadjoint<'a>, T::Preadjoint<'a>>: Linear<Pair<Xʹ, Yʹ>, Codomain = R>, |
| 510 { |
859 { |
| 511 type PreadjointCodomain = R; |
860 type PreadjointCodomain = R; |
| 512 type Preadjoint<'a> = RowOp<S::Preadjoint<'a>, T::Preadjoint<'a>> where Self : 'a; |
861 type Preadjoint<'a> |
| |
862 = RowOp<S::Preadjoint<'a>, T::Preadjoint<'a>> |
| |
863 where |
| |
864 Self: 'a; |
| 513 |
865 |
| 514 fn preadjoint(&self) -> Self::Preadjoint<'_> { |
866 fn preadjoint(&self) -> Self::Preadjoint<'_> { |
| 515 RowOp(self.0.preadjoint(), self.1.preadjoint()) |
867 RowOp(self.0.preadjoint(), self.1.preadjoint()) |
| 516 } |
868 } |
| 517 } |
869 } |
| 518 |
870 |
| 519 /// Diagonal operator |
871 /// Diagonal operator |
| |
872 #[derive(Clone, Copy, Debug, Serialize, Eq, PartialEq)] |
| 520 pub struct DiagOp<S, T>(pub S, pub T); |
873 pub struct DiagOp<S, T>(pub S, pub T); |
| 521 |
874 |
| 522 impl<A, B, S, T> Mapping<Pair<A, B>> for DiagOp<S, T> |
875 impl<A, B, S, T> Mapping<Pair<A, B>> for DiagOp<S, T> |
| 523 where |
876 where |
| 524 A : Space, |
877 A: Space, |
| 525 B : Space, |
878 B: Space, |
| 526 S : Mapping<A>, |
879 S: Mapping<A>, |
| 527 T : Mapping<B>, |
880 T: Mapping<B>, |
| 528 { |
881 { |
| 529 type Codomain = Pair<S::Codomain, T::Codomain>; |
882 type Codomain = Pair<S::Codomain, T::Codomain>; |
| 530 |
883 |
| 531 fn apply<I : Instance<Pair<A, B>>>(&self, x : I) -> Self::Codomain { |
884 fn apply<I: Instance<Pair<A, B>>>(&self, x: I) -> Self::Codomain { |
| 532 let Pair(a, b) = x.decompose(); |
885 x.eval_decompose(|Pair(a, b)| Pair(self.0.apply(a), self.1.apply(b))) |
| 533 Pair(self.0.apply(a), self.1.apply(b)) |
|
| 534 } |
886 } |
| 535 } |
887 } |
| 536 |
888 |
| 537 impl<A, B, S, T> Linear<Pair<A, B>> for DiagOp<S, T> |
889 impl<A, B, S, T> Linear<Pair<A, B>> for DiagOp<S, T> |
| 538 where |
890 where |
| 539 A : Space, |
891 A: Space, |
| 540 B : Space, |
892 B: Space, |
| 541 S : Linear<A>, |
893 S: Linear<A>, |
| 542 T : Linear<B>, |
894 T: Linear<B>, |
| 543 { } |
895 { |
| |
896 } |
| 544 |
897 |
| 545 impl<F, S, T, A, B, U, V> GEMV<F, Pair<U, V>, Pair<A, B>> for DiagOp<S, T> |
898 impl<F, S, T, A, B, U, V> GEMV<F, Pair<U, V>, Pair<A, B>> for DiagOp<S, T> |
| 546 where |
899 where |
| 547 A : Space, |
900 A: Space, |
| 548 B : Space, |
901 B: Space, |
| 549 U : Space, |
902 U: Space, |
| 550 V : Space, |
903 V: Space, |
| 551 S : GEMV<F, U, A>, |
904 S: GEMV<F, U, A>, |
| 552 T : GEMV<F, V, B>, |
905 T: GEMV<F, V, B>, |
| 553 F : Num, |
906 F: Num, |
| 554 Self : Linear<Pair<U, V>, Codomain=Pair<A, B>>, |
907 Self: Linear<Pair<U, V>, Codomain = Pair<A, B>>, |
| 555 { |
908 { |
| 556 fn gemv<I : Instance<Pair<U, V>>>(&self, y : &mut Pair<A, B>, α : F, x : I, β : F) { |
909 fn gemv<I: Instance<Pair<U, V>>>(&self, y: &mut Pair<A, B>, α: F, x: I, β: F) { |
| 557 let Pair(u, v) = x.decompose(); |
910 x.eval_decompose(|Pair(u, v)| { |
| 558 self.0.gemv(&mut y.0, α, u, β); |
911 self.0.gemv(&mut y.0, α, u, β); |
| 559 self.1.gemv(&mut y.1, α, v, β); |
912 self.1.gemv(&mut y.1, α, v, β); |
| 560 } |
913 }) |
| 561 |
914 } |
| 562 fn apply_mut<I : Instance<Pair<U, V>>>(&self, y : &mut Pair<A, B>, x : I){ |
915 |
| 563 let Pair(u, v) = x.decompose(); |
916 fn apply_mut<I: Instance<Pair<U, V>>>(&self, y: &mut Pair<A, B>, x: I) { |
| 564 self.0.apply_mut(&mut y.0, u); |
917 x.eval_decompose(|Pair(u, v)| { |
| 565 self.1.apply_mut(&mut y.1, v); |
918 self.0.apply_mut(&mut y.0, u); |
| |
919 self.1.apply_mut(&mut y.1, v); |
| |
920 }) |
| 566 } |
921 } |
| 567 |
922 |
| 568 /// Computes `y += Ax`, where `A` is `Self` |
923 /// Computes `y += Ax`, where `A` is `Self` |
| 569 fn apply_add<I : Instance<Pair<U, V>>>(&self, y : &mut Pair<A, B>, x : I){ |
924 fn apply_add<I: Instance<Pair<U, V>>>(&self, y: &mut Pair<A, B>, x: I) { |
| 570 let Pair(u, v) = x.decompose(); |
925 x.eval_decompose(|Pair(u, v)| { |
| 571 self.0.apply_add(&mut y.0, u); |
926 self.0.apply_add(&mut y.0, u); |
| 572 self.1.apply_add(&mut y.1, v); |
927 self.1.apply_add(&mut y.1, v); |
| 573 } |
928 }) |
| 574 } |
929 } |
| 575 |
930 } |
| 576 impl<A, B, Xʹ, Yʹ, R, S, T> Adjointable<Pair<A,B>, Pair<Xʹ,Yʹ>> for DiagOp<S, T> |
931 |
| 577 where |
932 impl<A, B, Xʹ, Yʹ, R, S, T> Adjointable<Pair<A, B>, Pair<Xʹ, Yʹ>> for DiagOp<S, T> |
| 578 A : Space, |
933 where |
| 579 B : Space, |
934 A: Space, |
| |
935 B: Space, |
| 580 Xʹ: Space, |
936 Xʹ: Space, |
| 581 Yʹ : Space, |
937 Yʹ: Space, |
| 582 R : Space, |
938 R: ClosedSpace, |
| 583 S : Adjointable<A, Xʹ>, |
939 S: Adjointable<A, Xʹ>, |
| 584 T : Adjointable<B, Yʹ>, |
940 T: Adjointable<B, Yʹ>, |
| 585 Self : Linear<Pair<A, B>>, |
941 Self: Linear<Pair<A, B>>, |
| 586 for<'a> DiagOp<S::Adjoint<'a>, T::Adjoint<'a>> : Linear< |
942 for<'a> DiagOp<S::Adjoint<'a>, T::Adjoint<'a>>: Linear<Pair<Xʹ, Yʹ>, Codomain = R>, |
| 587 Pair<Xʹ,Yʹ>, Codomain=R, |
|
| 588 >, |
|
| 589 { |
943 { |
| 590 type AdjointCodomain = R; |
944 type AdjointCodomain = R; |
| 591 type Adjoint<'a> = DiagOp<S::Adjoint<'a>, T::Adjoint<'a>> where Self : 'a; |
945 type Adjoint<'a> |
| |
946 = DiagOp<S::Adjoint<'a>, T::Adjoint<'a>> |
| |
947 where |
| |
948 Self: 'a; |
| 592 |
949 |
| 593 fn adjoint(&self) -> Self::Adjoint<'_> { |
950 fn adjoint(&self) -> Self::Adjoint<'_> { |
| 594 DiagOp(self.0.adjoint(), self.1.adjoint()) |
951 DiagOp(self.0.adjoint(), self.1.adjoint()) |
| 595 } |
952 } |
| 596 } |
953 } |
| 597 |
954 |
| 598 impl<A, B, Xʹ, Yʹ, R, S, T> Preadjointable<Pair<A,B>, Pair<Xʹ,Yʹ>> for DiagOp<S, T> |
955 impl<A, B, Xʹ, Yʹ, R, S, T> SimplyAdjointable<Pair<A, B>, Pair<Xʹ, Yʹ>> for DiagOp<S, T> |
| 599 where |
956 where |
| 600 A : Space, |
957 A: Space, |
| 601 B : Space, |
958 B: Space, |
| 602 Xʹ: Space, |
959 Xʹ: Space, |
| 603 Yʹ : Space, |
960 Yʹ: Space, |
| 604 R : Space, |
961 R: ClosedSpace, |
| 605 S : Preadjointable<A, Xʹ>, |
962 S: SimplyAdjointable<A, Xʹ>, |
| 606 T : Preadjointable<B, Yʹ>, |
963 T: SimplyAdjointable<B, Yʹ>, |
| 607 Self : Linear<Pair<A, B>>, |
964 Self: Linear<Pair<A, B>>, |
| 608 for<'a> DiagOp<S::Preadjoint<'a>, T::Preadjoint<'a>> : Linear< |
965 for<'a> DiagOp<S::SimpleAdjoint, T::SimpleAdjoint>: Linear<Pair<Xʹ, Yʹ>, Codomain = R>, |
| 609 Pair<Xʹ,Yʹ>, Codomain=R, |
966 { |
| 610 >, |
967 type AdjointCodomain = R; |
| |
968 type SimpleAdjoint = DiagOp<S::SimpleAdjoint, T::SimpleAdjoint>; |
| |
969 |
| |
970 fn adjoint(&self) -> Self::SimpleAdjoint { |
| |
971 DiagOp(self.0.adjoint(), self.1.adjoint()) |
| |
972 } |
| |
973 } |
| |
974 |
| |
975 impl<A, B, Xʹ, Yʹ, R, S, T> Preadjointable<Pair<A, B>, Pair<Xʹ, Yʹ>> for DiagOp<S, T> |
| |
976 where |
| |
977 A: Space, |
| |
978 B: Space, |
| |
979 Xʹ: Space, |
| |
980 Yʹ: Space, |
| |
981 R: ClosedSpace, |
| |
982 S: Preadjointable<A, Xʹ>, |
| |
983 T: Preadjointable<B, Yʹ>, |
| |
984 Self: Linear<Pair<A, B>>, |
| |
985 for<'a> DiagOp<S::Preadjoint<'a>, T::Preadjoint<'a>>: Linear<Pair<Xʹ, Yʹ>, Codomain = R>, |
| 611 { |
986 { |
| 612 type PreadjointCodomain = R; |
987 type PreadjointCodomain = R; |
| 613 type Preadjoint<'a> = DiagOp<S::Preadjoint<'a>, T::Preadjoint<'a>> where Self : 'a; |
988 type Preadjoint<'a> |
| |
989 = DiagOp<S::Preadjoint<'a>, T::Preadjoint<'a>> |
| |
990 where |
| |
991 Self: 'a; |
| 614 |
992 |
| 615 fn preadjoint(&self) -> Self::Preadjoint<'_> { |
993 fn preadjoint(&self) -> Self::Preadjoint<'_> { |
| 616 DiagOp(self.0.preadjoint(), self.1.preadjoint()) |
994 DiagOp(self.0.preadjoint(), self.1.preadjoint()) |
| 617 } |
995 } |
| 618 } |
996 } |
| 619 |
997 |
| 620 /// Block operator |
998 /// Block operator |
| 621 pub type BlockOp<S11, S12, S21, S22> = ColOp<RowOp<S11, S12>, RowOp<S21, S22>>; |
999 pub type BlockOp<S11, S12, S21, S22> = ColOp<RowOp<S11, S12>, RowOp<S21, S22>>; |
| 622 |
|
| 623 |
1000 |
| 624 macro_rules! pairnorm { |
1001 macro_rules! pairnorm { |
| 625 ($expj:ty) => { |
1002 ($expj:ty) => { |
| 626 impl<F, A, B, S, T, ExpA, ExpB, ExpR> |
1003 impl<F, A, B, S, T, ExpA, ExpB, ExpR> |
| 627 BoundedLinear<Pair<A, B>, PairNorm<ExpA, ExpB, $expj>, ExpR, F> |
1004 BoundedLinear<Pair<A, B>, PairNorm<ExpA, ExpB, $expj>, ExpR, F> for RowOp<S, T> |
| 628 for RowOp<S, T> |
|
| 629 where |
1005 where |
| 630 F : Float, |
1006 F: Float, |
| 631 A : Space + Norm<F, ExpA>, |
1007 A: Space, |
| 632 B : Space + Norm<F, ExpB>, |
1008 B: Space, |
| 633 S : BoundedLinear<A, ExpA, ExpR, F>, |
1009 S: BoundedLinear<A, ExpA, ExpR, F>, |
| 634 T : BoundedLinear<B, ExpB, ExpR, F>, |
1010 T: BoundedLinear<B, ExpB, ExpR, F>, |
| 635 S::Codomain : Add<T::Codomain>, |
1011 S::Codomain: Add<T::Codomain>, |
| 636 <S::Codomain as Add<T::Codomain>>::Output : Space, |
1012 <S::Codomain as Add<T::Codomain>>::Output: ClosedSpace, |
| 637 ExpA : NormExponent, |
1013 ExpA: NormExponent, |
| 638 ExpB : NormExponent, |
1014 ExpB: NormExponent, |
| 639 ExpR : NormExponent, |
1015 ExpR: NormExponent, |
| 640 { |
1016 { |
| 641 fn opnorm_bound( |
1017 fn opnorm_bound( |
| 642 &self, |
1018 &self, |
| 643 PairNorm(expa, expb, _) : PairNorm<ExpA, ExpB, $expj>, |
1019 PairNorm(expa, expb, _): PairNorm<ExpA, ExpB, $expj>, |
| 644 expr : ExpR |
1020 expr: ExpR, |
| 645 ) -> F { |
1021 ) -> DynResult<F> { |
| 646 // An application of the triangle inequality bounds the norm by the maximum |
1022 // An application of the triangle inequality bounds the norm by the maximum |
| 647 // of the individual norms. A simple observation shows this to be exact. |
1023 // of the individual norms. A simple observation shows this to be exact. |
| 648 let na = self.0.opnorm_bound(expa, expr); |
1024 let na = self.0.opnorm_bound(expa, expr)?; |
| 649 let nb = self.1.opnorm_bound(expb, expr); |
1025 let nb = self.1.opnorm_bound(expb, expr)?; |
| 650 na.max(nb) |
1026 Ok(na.max(nb)) |
| 651 } |
1027 } |
| 652 } |
1028 } |
| 653 |
1029 |
| 654 impl<F, A, S, T, ExpA, ExpS, ExpT> |
1030 impl<F, A, S, T, ExpA, ExpS, ExpT> BoundedLinear<A, ExpA, PairNorm<ExpS, ExpT, $expj>, F> |
| 655 BoundedLinear<A, ExpA, PairNorm<ExpS, ExpT, $expj>, F> |
1031 for ColOp<S, T> |
| 656 for ColOp<S, T> |
|
| 657 where |
1032 where |
| 658 F : Float, |
1033 F: Float, |
| 659 A : Space + Norm<F, ExpA>, |
1034 A: Space, |
| 660 S : BoundedLinear<A, ExpA, ExpS, F>, |
1035 S: BoundedLinear<A, ExpA, ExpS, F>, |
| 661 T : BoundedLinear<A, ExpA, ExpT, F>, |
1036 T: BoundedLinear<A, ExpA, ExpT, F>, |
| 662 ExpA : NormExponent, |
1037 ExpA: NormExponent, |
| 663 ExpS : NormExponent, |
1038 ExpS: NormExponent, |
| 664 ExpT : NormExponent, |
1039 ExpT: NormExponent, |
| 665 { |
1040 { |
| 666 fn opnorm_bound( |
1041 fn opnorm_bound( |
| 667 &self, |
1042 &self, |
| 668 expa : ExpA, |
1043 expa: ExpA, |
| 669 PairNorm(exps, expt, _) : PairNorm<ExpS, ExpT, $expj> |
1044 PairNorm(exps, expt, _): PairNorm<ExpS, ExpT, $expj>, |
| 670 ) -> F { |
1045 ) -> DynResult<F> { |
| 671 // This is based on the rule for RowOp and ‖A^*‖ = ‖A‖, hence, |
1046 // This is based on the rule for RowOp and ‖A^*‖ = ‖A‖, hence, |
| 672 // for A=[S; T], ‖A‖=‖[S^*, T^*]‖ ≤ max{‖S^*‖, ‖T^*‖} = max{‖S‖, ‖T‖} |
1047 // for A=[S; T], ‖A‖=‖[S^*, T^*]‖ ≤ max{‖S^*‖, ‖T^*‖} = max{‖S‖, ‖T‖} |
| 673 let ns = self.0.opnorm_bound(expa, exps); |
1048 let ns = self.0.opnorm_bound(expa, exps)?; |
| 674 let nt = self.1.opnorm_bound(expa, expt); |
1049 let nt = self.1.opnorm_bound(expa, expt)?; |
| 675 ns.max(nt) |
1050 Ok(ns.max(nt)) |
| 676 } |
1051 } |
| 677 } |
1052 } |
| 678 } |
1053 }; |
| 679 } |
1054 } |
| 680 |
1055 |
| 681 pairnorm!(L1); |
1056 pairnorm!(L1); |
| 682 pairnorm!(L2); |
1057 pairnorm!(L2); |
| 683 pairnorm!(Linfinity); |
1058 pairnorm!(Linfinity); |
| 684 |
1059 |
| |
1060 /// The simplest linear mapping, scaling by a scalar. |
| |
1061 /// |
| |
1062 /// TODO: redefined/replace `Weighted` by composition with [`Scaled`]. |
| |
1063 pub struct Scaled<F: Float>(pub F); |
| |
1064 |
| |
1065 impl<Domain, F> Mapping<Domain> for Scaled<F> |
| |
1066 where |
| |
1067 F: Float, |
| |
1068 Domain: Space, |
| |
1069 Domain::Principal: Mul<F>, |
| |
1070 <Domain::Principal as Mul<F>>::Output: ClosedSpace, |
| |
1071 { |
| |
1072 type Codomain = <Domain::Principal as Mul<F>>::Output; |
| |
1073 |
| |
1074 /// Compute the value of `self` at `x`. |
| |
1075 fn apply<I: Instance<Domain>>(&self, x: I) -> Self::Codomain { |
| |
1076 x.own() * self.0 |
| |
1077 } |
| |
1078 } |
| |
1079 |
| |
1080 impl<Domain, F> Linear<Domain> for Scaled<F> |
| |
1081 where |
| |
1082 F: Float, |
| |
1083 Domain: Space, |
| |
1084 Domain::Principal: Mul<F>, |
| |
1085 <Domain::Principal as Mul<F>>::Output: ClosedSpace, |
| |
1086 { |
| |
1087 } |