| 301 Self: 'b; |
301 Self: 'b; |
| 302 // () means not (pre)adjointable. |
302 // () means not (pre)adjointable. |
| 303 |
303 |
| 304 fn adjoint(&self) -> Self::Adjoint<'_> { |
304 fn adjoint(&self) -> Self::Adjoint<'_> { |
| 305 SimpleZeroOp |
305 SimpleZeroOp |
| |
306 } |
| |
307 } |
| |
308 |
| |
309 /// A zero operator that can be eitherh dualised or predualised (once). |
| |
310 /// This is achieved by storing an oppropriate zero. |
| |
311 pub struct ZeroOp<X, Y: AXPY<Field = F>, C, O, F: Float = f64> { |
| |
312 codomain_sample: C, |
| |
313 other_sample: O, |
| |
314 _phantoms: PhantomData<(X, Y, F)>, |
| |
315 } |
| |
316 |
| |
317 impl<'b, X, Y, F> ZeroOp<X, Y, &'b Y, &'b X::DualSpace, F> |
| |
318 where |
| |
319 X: HasDual<F>, |
| |
320 Y: HasDual<F>, |
| |
321 Y::Owned: Clone, |
| |
322 F: Float, |
| |
323 { |
| |
324 pub fn new_dualisable(x_dual_sample: &'b X::DualSpace, y_sample: &'b Y) -> Self { |
| |
325 ZeroOp { |
| |
326 codomain_sample: y_sample, |
| |
327 other_sample: x_dual_sample, |
| |
328 _phantoms: PhantomData, |
| |
329 } |
| |
330 } |
| |
331 } |
| |
332 |
| |
333 impl<'b, X, Y, O, F> Mapping<X> for ZeroOp<X, Y, &'b Y, O, F> |
| |
334 where |
| |
335 X: Space + Instance<X>, |
| |
336 Y: AXPY<Field = F>, |
| |
337 F: Float, |
| |
338 { |
| |
339 type Codomain = Y::Owned; |
| |
340 |
| |
341 fn apply<I: Instance<X>>(&self, _x: I) -> Y::Owned { |
| |
342 self.codomain_sample.similar_origin() |
| |
343 } |
| |
344 } |
| |
345 |
| |
346 impl<'b, X, Y, O, F> Linear<X> for ZeroOp<X, Y, &'b Y, O, F> |
| |
347 where |
| |
348 X: Space + Instance<X>, |
| |
349 Y: AXPY<Field = F>, |
| |
350 F: Float, |
| |
351 { |
| |
352 } |
| |
353 |
| |
354 #[replace_float_literals(F::cast_from(literal))] |
| |
355 impl<'b, X, Y, O, F> GEMV<F, X, Y> for ZeroOp<X, Y, &'b Y, O, F> |
| |
356 where |
| |
357 X: Space + Instance<X>, |
| |
358 Y: AXPY<Field = F>, |
| |
359 F: Float, |
| |
360 { |
| |
361 // Computes `y = αAx + βy`, where `A` is `Self`. |
| |
362 fn gemv<I: Instance<X>>(&self, y: &mut Y, _α: F, _x: I, β: F) { |
| |
363 *y *= β; |
| |
364 } |
| |
365 |
| |
366 fn apply_mut<I: Instance<X>>(&self, y: &mut Y, _x: I) { |
| |
367 y.set_zero(); |
| |
368 } |
| |
369 } |
| |
370 |
| |
371 impl<'b, X, Y, O, F, E1, E2> BoundedLinear<X, E1, E2, F> for ZeroOp<X, Y, &'b Y, O, F> |
| |
372 where |
| |
373 X: Space + Instance<X> + Norm<E1, F>, |
| |
374 Y: AXPY<Field = F>, |
| |
375 Y::Owned: Clone, |
| |
376 F: Float, |
| |
377 E1: NormExponent, |
| |
378 E2: NormExponent, |
| |
379 { |
| |
380 fn opnorm_bound(&self, _xexp: E1, _codexp: E2) -> DynResult<F> { |
| |
381 Ok(F::ZERO) |
| |
382 } |
| |
383 } |
| |
384 |
| |
385 impl<'b, X, Y, Xprime, Yprime, F> Adjointable<X, Yprime> for ZeroOp<X, Y, &'b Y, &'b Xprime, F> |
| |
386 where |
| |
387 X: HasDual<F, DualSpace = Xprime>, |
| |
388 Y: HasDual<F, DualSpace = Yprime>, |
| |
389 F: Float, |
| |
390 Xprime: AXPY<Field = F, Owned = Xprime>, |
| |
391 Xprime::Owned: AXPY<Field = F>, |
| |
392 Yprime: Space + Instance<Yprime>, |
| |
393 { |
| |
394 type AdjointCodomain = Xprime; |
| |
395 type Adjoint<'c> |
| |
396 = ZeroOp<Yprime, Xprime, &'b Xprime, (), F> |
| |
397 where |
| |
398 Self: 'c; |
| |
399 // () means not (pre)adjointable. |
| |
400 |
| |
401 fn adjoint(&self) -> Self::Adjoint<'_> { |
| |
402 ZeroOp { |
| |
403 codomain_sample: self.other_sample, |
| |
404 other_sample: (), |
| |
405 _phantoms: PhantomData, |
| |
406 } |
| 306 } |
407 } |
| 307 } |
408 } |
| 308 |
409 |
| 309 /* |
410 /* |
| 310 /// Trait for forming origins (zeroes) in vector spaces |
411 /// Trait for forming origins (zeroes) in vector spaces |