Sun, 22 Dec 2024 17:42:14 -0500
ZeroOp
src/linops.rs | file | annotate | diff | comparison | revisions |
--- a/src/linops.rs Sun Dec 22 17:24:33 2024 -0500 +++ b/src/linops.rs Sun Dec 22 17:42:14 2024 -0500 @@ -184,6 +184,93 @@ } +/// The zero operator +#[derive(Clone,Copy,Debug,Serialize,Eq,PartialEq)] +pub struct ZeroOp<'a, X, XD, Y, F> { + zero : &'a Y, // TODO: don't pass this in `new`; maybe not even store. + dual_or_predual_zero : XD, + _phantoms : PhantomData<(X, Y, F)>, +} + +// TODO: Need to make Zero in Instance. + +impl<'a, F : Num, X : Space, XD, Y : Space + Clone> ZeroOp<'a, X, XD, Y, F> { + pub fn new(zero : &'a Y, dual_or_predual_zero : XD) -> Self { + ZeroOp{ zero, dual_or_predual_zero, _phantoms : PhantomData } + } +} + +impl<'a, F : Num, X : Space, XD, Y : AXPY<F> + Clone> Mapping<X> for ZeroOp<'a, X, XD, Y, F> { + type Codomain = Y; + + fn apply<I : Instance<X>>(&self, _x : I) -> Y { + self.zero.clone() + } +} + +impl<'a, F : Num, X : Space, XD, Y : AXPY<F> + Clone> Linear<X> for ZeroOp<'a, X, XD, Y, F> +{ } + +#[replace_float_literals(F::cast_from(literal))] +impl<'a, F, X, XD, Y> GEMV<F, X, Y> for ZeroOp<'a, X, XD, Y, F> +where + F : Num, + Y : AXPY<F, Y> + Clone, + X : Space +{ + // 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<'a, F, X, XD, Y, E1, E2> BoundedLinear<X, E1, E2, F> for ZeroOp<'a, X, XD, Y, F> +where + X : Space + Norm<F, E1>, + Y : AXPY<F> + Clone + Norm<F, E2>, + F : Num, + E1 : NormExponent, + E2 : NormExponent, +{ + fn opnorm_bound(&self, _xexp : E1, _codexp : E2) -> F { F::ZERO } +} + +impl<'a, F : Num, X, XD, Y, Yprime : Space> Adjointable<X, Yprime> for ZeroOp<'a, X, XD, Y, F> +where + X : Space, + Y : AXPY<F> + Clone + 'static, + XD : AXPY<F> + Clone + 'static, +{ + type AdjointCodomain = XD; + type Adjoint<'b> = ZeroOp<'b, Yprime, (), XD, F> where Self : 'b; + // () means not (pre)adjointable. + + fn adjoint(&self) -> Self::Adjoint<'_> { + ZeroOp::new(&self.dual_or_predual_zero, ()) + } +} + +impl<'a, F, X, XD, Y, Ypre> Preadjointable<X, Ypre> for ZeroOp<'a, X, XD, Y, F> +where + F : Num, + X : Space, + Y : AXPY<F> + Clone, + Ypre : Space, + XD : AXPY<F> + Clone + 'static, +{ + type PreadjointCodomain = XD; + type Preadjoint<'b> = ZeroOp<'b, Ypre, (), XD, F> where Self : 'b; + // () means not (pre)adjointable. + + fn preadjoint(&self) -> Self::Preadjoint<'_> { + ZeroOp::new(&self.dual_or_predual_zero, ()) + } +} + impl<S, T, E, X> Linear<X> for Composition<S, T, E> where X : Space,