new ZeroOp dev

Tue, 13 May 2025 00:24:51 -0500

author
Tuomo Valkonen <tuomov@iki.fi>
date
Tue, 13 May 2025 00:24:51 -0500
branch
dev
changeset 139
f78885441218
parent 138
593912dc3293
child 140
26df914dda67

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> {

mercurial