Tue, 13 May 2025 00:24:51 -0500
new ZeroOp
| src/linops.rs | file | annotate | diff | comparison | revisions |
--- 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<X, Y: AXPY<Field = F>, C, O, F: Float = f64> { + codomain_sample: C, + other_sample: O, + _phantoms: PhantomData<(X, Y, F)>, +} + +impl<'b, X, Y, F> ZeroOp<X, Y, &'b Y, &'b X::DualSpace, F> +where + X: HasDual<F>, + Y: HasDual<F>, + 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<X> for ZeroOp<X, Y, &'b Y, O, F> +where + X: Space + Instance<X>, + Y: AXPY<Field = F>, + F: Float, +{ + type Codomain = Y::Owned; + + fn apply<I: Instance<X>>(&self, _x: I) -> Y::Owned { + self.codomain_sample.similar_origin() + } +} + +impl<'b, X, Y, O, F> Linear<X> for ZeroOp<X, Y, &'b Y, O, F> +where + X: Space + Instance<X>, + Y: AXPY<Field = F>, + F: Float, +{ +} + +#[replace_float_literals(F::cast_from(literal))] +impl<'b, X, Y, O, F> GEMV<F, X, Y> for ZeroOp<X, Y, &'b Y, O, F> +where + X: Space + Instance<X>, + Y: AXPY<Field = F>, + F: Float, +{ + // Computes `y = αAx + βy`, where `A` is `Self`. + fn gemv<I: Instance<X>>(&self, y: &mut Y, _α: F, _x: I, β: F) { + *y *= β; + } + + fn apply_mut<I: Instance<X>>(&self, y: &mut Y, _x: I) { + y.set_zero(); + } +} + +impl<'b, X, Y, O, F, E1, E2> BoundedLinear<X, E1, E2, F> for ZeroOp<X, Y, &'b Y, O, F> +where + X: Space + Instance<X> + Norm<E1, F>, + Y: AXPY<Field = F>, + Y::Owned: Clone, + F: Float, + E1: NormExponent, + E2: NormExponent, +{ + fn opnorm_bound(&self, _xexp: E1, _codexp: E2) -> DynResult<F> { + Ok(F::ZERO) + } +} + +impl<'b, X, Y, Xprime, Yprime, F> Adjointable<X, Yprime> for ZeroOp<X, Y, &'b Y, &'b Xprime, F> +where + X: HasDual<F, DualSpace = Xprime>, + Y: HasDual<F, DualSpace = Yprime>, + F: Float, + Xprime: AXPY<Field = F, Owned = Xprime>, + Xprime::Owned: AXPY<Field = F>, + Yprime: Space + Instance<Yprime>, +{ + type AdjointCodomain = Xprime; + type Adjoint<'c> + = ZeroOp<Yprime, Xprime, &'b Xprime, (), F> + 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<X, F: Num = f64> {