src/linops.rs

branch
dev
changeset 150
c4e394a9c84c
parent 140
26df914dda67
child 151
402d717bb5c0
--- a/src/linops.rs	Mon Sep 01 00:04:22 2025 -0500
+++ b/src/linops.rs	Mon Sep 01 13:51:03 2025 -0500
@@ -5,7 +5,7 @@
 use crate::direct_product::Pair;
 use crate::error::DynResult;
 use crate::instance::Instance;
-pub use crate::mapping::{Composition, DifferentiableImpl, Mapping, Space};
+pub use crate::mapping::{ClosedSpace, Composition, DifferentiableImpl, Mapping, Space};
 use crate::norms::{HasDual, Linfinity, Norm, NormExponent, PairNorm, L1, L2};
 use crate::types::*;
 use numeric_literals::replace_float_literals;
@@ -25,16 +25,10 @@
 //     }
 // }
 
-/// Efficient in-place summation.
+/// Vector spaces
 #[replace_float_literals(Self::Field::cast_from(literal))]
-pub trait AXPY<X = Self>:
-    Space
-    + MulAssign<Self::Field>
-    + DivAssign<Self::Field>
-    + AddAssign<Self>
-    + AddAssign<Self::Owned>
-    + SubAssign<Self>
-    + SubAssign<Self::Owned>
+pub trait VectorSpace:
+    Space<OwnedSpace = Self::Owned>
     + Mul<Self::Field, Output = Self::Owned>
     + Div<Self::Field, Output = Self::Owned>
     + Add<Self, Output = Self::Owned>
@@ -42,12 +36,42 @@
     + Sub<Self, Output = Self::Owned>
     + Sub<Self::Owned, Output = Self::Owned>
     + Neg
+{
+    type Field: Num;
+    type Owned: ClosedSpace
+        + AXPY<
+            Self,
+            Field = Self::Field,
+            Owned = Self::Owned,
+            OwnedVariant = Self::Owned,
+            OwnedSpace = Self::Owned,
+        >;
+
+    /// Return a similar zero as `self`.
+    fn similar_origin(&self) -> Self::Owned;
+    // {
+    //     self.make_origin_generator().make_origin()
+    // }
+
+    /// Return a similar zero as `x`.
+    fn similar_origin_inst<I: Instance<Self>>(x: I) -> Self::Owned {
+        x.eval(|xr| xr.similar_origin())
+    }
+}
+
+/// Efficient in-place summation.
+#[replace_float_literals(Self::Field::cast_from(literal))]
+pub trait AXPY<X = Self>:
+    VectorSpace
+    + MulAssign<Self::Field>
+    + DivAssign<Self::Field>
+    + AddAssign<Self>
+    + AddAssign<Self::Owned>
+    + SubAssign<Self>
+    + SubAssign<Self::Owned>
 where
     X: Space,
 {
-    type Field: Num;
-    type Owned: AXPY<X, Field = Self::Field>;
-
     /// Computes  `y = βy + αx`, where `y` is `Self`.
     fn axpy<I: Instance<X>>(&mut self, α: Self::Field, x: I, β: Self::Field);
 
@@ -61,21 +85,8 @@
         self.axpy(α, x, 0.0)
     }
 
-    /// Return a similar zero as `self`.
-    fn similar_origin(&self) -> Self::Owned;
-    // {
-    //     self.make_origin_generator().make_origin()
-    // }
-
-    /// Return a similar zero as `x`.
-    fn similar_origin_inst<I: Instance<Self>>(x: I) -> Self::Owned {
-        x.eval(|xr| xr.similar_origin())
-    }
-
     /// Set self to zero.
     fn set_zero(&mut self);
-
-    //fn make_origin_generator(&self) -> Self::OriginGen<'_>;
 }
 
 /// Efficient in-place application for [`Linear`] operators.
@@ -178,21 +189,21 @@
     }
 }
 
-impl<X: Clone + Space> Mapping<X> for IdOp<X> {
-    type Codomain = X;
+impl<X: Space> Mapping<X> for IdOp<X> {
+    type Codomain = X::OwnedVariant;
 
     fn apply<I: Instance<X>>(&self, x: I) -> X {
         x.own()
     }
 }
 
-impl<X: Clone + Space> Linear<X> for IdOp<X> {}
+impl<X: Space> Linear<X> for IdOp<X> {}
 
 #[replace_float_literals(F::cast_from(literal))]
 impl<F: Num, X, Y> GEMV<F, X, Y> for IdOp<X>
 where
     Y: AXPY<X, Field = F>,
-    X: Clone + Space,
+    X: Space,
 {
     // Computes  `y = αAx + βy`, where `A` is `Self`.
     fn gemv<I: Instance<X>>(&self, y: &mut Y, α: F, x: I, β: F) {
@@ -243,10 +254,7 @@
 #[derive(Clone, Copy, Debug, Serialize, Eq, PartialEq)]
 pub struct SimpleZeroOp;
 
-impl<X> Mapping<X> for SimpleZeroOp
-where
-    X: AXPY + Instance<X>,
-{
+impl<X: VectorSpace> Mapping<X> for SimpleZeroOp {
     type Codomain = X::Owned;
 
     fn apply<I: Instance<X>>(&self, x: I) -> X::Owned {
@@ -254,14 +262,14 @@
     }
 }
 
-impl<X> Linear<X> for SimpleZeroOp where X: AXPY + Instance<X> {}
+impl<X: VectorSpace> Linear<X> for SimpleZeroOp {}
 
 #[replace_float_literals(F::cast_from(literal))]
 impl<X, Y, F> GEMV<F, X, Y> for SimpleZeroOp
 where
     F: Num,
     Y: AXPY<Field = F>,
-    X: AXPY<Field = F> + Instance<X>,
+    X: VectorSpace<Field = F> + Instance<X>,
 {
     // Computes  `y = αAx + βy`, where `A` is `Self`.
     fn gemv<I: Instance<X>>(&self, y: &mut Y, _α: F, _x: I, β: F) {
@@ -276,7 +284,7 @@
 impl<X, F, E1, E2> BoundedLinear<X, E1, E2, F> for SimpleZeroOp
 where
     F: Num,
-    X: AXPY<Field = F> + Instance<X> + Norm<E1, F>,
+    X: VectorSpace<Field = F> + Norm<E1, F>,
     E1: NormExponent,
     E2: NormExponent,
 {
@@ -288,8 +296,8 @@
 impl<X, F> Adjointable<X, X::DualSpace> for SimpleZeroOp
 where
     F: Num,
-    X: AXPY<Field = F> + Instance<X> + HasDual<F>,
-    X::DualSpace: AXPY<Owned = X::DualSpace>,
+    X: VectorSpace<Field = F> + HasDual<F>,
+    X::DualSpace: VectorSpace<Owned = X::DualSpace>,
 {
     type AdjointCodomain = X::DualSpace;
     type Adjoint<'b>
@@ -303,7 +311,7 @@
     }
 }
 
-pub trait OriginGenerator<Y: AXPY> {
+pub trait OriginGenerator<Y: VectorSpace> {
     type Ref<'b>: OriginGenerator<Y>
     where
         Self: 'b;
@@ -312,7 +320,7 @@
     fn as_ref(&self) -> Self::Ref<'_>;
 }
 
-impl<Y: AXPY> OriginGenerator<Y> for Y {
+impl<Y: VectorSpace> OriginGenerator<Y> for Y {
     type Ref<'b>
         = &'b Y
     where
@@ -329,7 +337,7 @@
     }
 }
 
-impl<'b, Y: AXPY> OriginGenerator<Y> for &'b Y {
+impl<'b, Y: VectorSpace> OriginGenerator<Y> for &'b Y {
     type Ref<'c>
         = Self
     where
@@ -348,7 +356,7 @@
 
 /// 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>, OY: OriginGenerator<Y>, O, F: Float = f64> {
+pub struct ZeroOp<X, Y: VectorSpace<Field = F>, OY: OriginGenerator<Y>, O, F: Float = f64> {
     codomain_origin_generator: OY,
     other_origin_generator: O,
     _phantoms: PhantomData<(X, Y, F)>,
@@ -357,8 +365,8 @@
 impl<X, Y, OY, F> ZeroOp<X, Y, OY, (), F>
 where
     OY: OriginGenerator<Y>,
-    X: AXPY<Field = F>,
-    Y: AXPY<Field = F>,
+    X: VectorSpace<Field = F>,
+    Y: VectorSpace<Field = F>,
     F: Float,
 {
     pub fn new(y_og: OY) -> Self {
@@ -377,7 +385,7 @@
     X: HasDual<F, DualSpace = Xprime>,
     Y: HasDual<F, DualSpace = Yprime>,
     F: Float,
-    Xprime: AXPY<Field = F, Owned = Xprime>,
+    Xprime: VectorSpace<Field = F, Owned = Xprime>,
     Xprime::Owned: AXPY<Field = F>,
     Yprime: Space + Instance<Yprime>,
 {
@@ -392,8 +400,8 @@
 
 impl<X, Y, O, OY, F> Mapping<X> for ZeroOp<X, Y, OY, O, F>
 where
-    X: Space + Instance<X>,
-    Y: AXPY<Field = F>,
+    X: Space,
+    Y: VectorSpace<Field = F>,
     F: Float,
     OY: OriginGenerator<Y>,
 {
@@ -406,8 +414,8 @@
 
 impl<X, Y, OY, O, F> Linear<X> for ZeroOp<X, Y, OY, O, F>
 where
-    X: Space + Instance<X>,
-    Y: AXPY<Field = F>,
+    X: Space,
+    Y: VectorSpace<Field = F>,
     F: Float,
     OY: OriginGenerator<Y>,
 {
@@ -416,7 +424,7 @@
 #[replace_float_literals(F::cast_from(literal))]
 impl<X, Y, OY, O, F> GEMV<F, X, Y> for ZeroOp<X, Y, OY, O, F>
 where
-    X: Space + Instance<X>,
+    X: Space,
     Y: AXPY<Field = F, Owned = Y>,
     F: Float,
     OY: OriginGenerator<Y>,
@@ -434,7 +442,7 @@
 impl<X, Y, OY, O, F, E1, E2> BoundedLinear<X, E1, E2, F> for ZeroOp<X, Y, OY, O, F>
 where
     X: Space + Instance<X> + Norm<E1, F>,
-    Y: AXPY<Field = F>,
+    Y: VectorSpace<Field = F>,
     Y::Owned: Clone,
     F: Float,
     E1: NormExponent,
@@ -452,7 +460,7 @@
     X: HasDual<F, DualSpace = Xprime>,
     Y: HasDual<F, DualSpace = Yprime>,
     F: Float,
-    Xprime: AXPY<Field = F, Owned = Xprime>,
+    Xprime: VectorSpace<Field = F, Owned = Xprime>,
     Xprime::Owned: AXPY<Field = F>,
     Yprime: Space + Instance<Yprime>,
     OY: OriginGenerator<Y>,

mercurial