# HG changeset patch # User Tuomo Valkonen # Date 1747113891 18000 # Node ID f78885441218cbb08af89f7566f581a53c51983c # Parent 593912dc3293332fb68179c625ea6e545295e07b new ZeroOp diff -r 593912dc3293 -r f78885441218 src/linops.rs --- a/src/linops.rs Mon May 12 23:29:17 2025 -0500 +++ b/src/linops.rs Tue May 13 00:24:51 2025 -0500 @@ -306,6 +306,107 @@ } } +/// A zero operator that can be eitherh dualised or predualised (once). +/// This is achieved by storing an oppropriate zero. +pub struct ZeroOp, C, O, F: Float = f64> { + codomain_sample: C, + other_sample: O, + _phantoms: PhantomData<(X, Y, F)>, +} + +impl<'b, X, Y, F> ZeroOp +where + X: HasDual, + Y: HasDual, + Y::Owned: Clone, + F: Float, +{ + pub fn new_dualisable(x_dual_sample: &'b X::DualSpace, y_sample: &'b Y) -> Self { + ZeroOp { + codomain_sample: y_sample, + other_sample: x_dual_sample, + _phantoms: PhantomData, + } + } +} + +impl<'b, X, Y, O, F> Mapping for ZeroOp +where + X: Space + Instance, + Y: AXPY, + F: Float, +{ + type Codomain = Y::Owned; + + fn apply>(&self, _x: I) -> Y::Owned { + self.codomain_sample.similar_origin() + } +} + +impl<'b, X, Y, O, F> Linear for ZeroOp +where + X: Space + Instance, + Y: AXPY, + F: Float, +{ +} + +#[replace_float_literals(F::cast_from(literal))] +impl<'b, X, Y, O, F> GEMV for ZeroOp +where + X: Space + Instance, + Y: AXPY, + F: Float, +{ + // Computes `y = αAx + βy`, where `A` is `Self`. + fn gemv>(&self, y: &mut Y, _α: F, _x: I, β: F) { + *y *= β; + } + + fn apply_mut>(&self, y: &mut Y, _x: I) { + y.set_zero(); + } +} + +impl<'b, X, Y, O, F, E1, E2> BoundedLinear for ZeroOp +where + X: Space + Instance + Norm, + Y: AXPY, + Y::Owned: Clone, + F: Float, + E1: NormExponent, + E2: NormExponent, +{ + fn opnorm_bound(&self, _xexp: E1, _codexp: E2) -> DynResult { + Ok(F::ZERO) + } +} + +impl<'b, X, Y, Xprime, Yprime, F> Adjointable for ZeroOp +where + X: HasDual, + Y: HasDual, + F: Float, + Xprime: AXPY, + Xprime::Owned: AXPY, + Yprime: Space + Instance, +{ + type AdjointCodomain = Xprime; + type Adjoint<'c> + = ZeroOp + where + Self: 'c; + // () means not (pre)adjointable. + + fn adjoint(&self) -> Self::Adjoint<'_> { + ZeroOp { + codomain_sample: self.other_sample, + other_sample: (), + _phantoms: PhantomData, + } + } +} + /* /// Trait for forming origins (zeroes) in vector spaces pub trait OriginGenerator {