diff -r 2f1798c65fd6 -r c4e394a9c84c src/linops.rs --- 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: - Space - + MulAssign - + DivAssign - + AddAssign - + AddAssign - + SubAssign - + SubAssign +pub trait VectorSpace: + Space + Mul + Div + Add @@ -42,12 +36,42 @@ + Sub + Sub + 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>(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: + VectorSpace + + MulAssign + + DivAssign + + AddAssign + + AddAssign + + SubAssign + + SubAssign where X: Space, { - type Field: Num; - type Owned: AXPY; - /// Computes `y = βy + αx`, where `y` is `Self`. fn axpy>(&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>(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 Mapping for IdOp { - type Codomain = X; +impl Mapping for IdOp { + type Codomain = X::OwnedVariant; fn apply>(&self, x: I) -> X { x.own() } } -impl Linear for IdOp {} +impl Linear for IdOp {} #[replace_float_literals(F::cast_from(literal))] impl GEMV for IdOp where Y: AXPY, - X: Clone + Space, + X: Space, { // Computes `y = αAx + βy`, where `A` is `Self`. fn gemv>(&self, y: &mut Y, α: F, x: I, β: F) { @@ -243,10 +254,7 @@ #[derive(Clone, Copy, Debug, Serialize, Eq, PartialEq)] pub struct SimpleZeroOp; -impl Mapping for SimpleZeroOp -where - X: AXPY + Instance, -{ +impl Mapping for SimpleZeroOp { type Codomain = X::Owned; fn apply>(&self, x: I) -> X::Owned { @@ -254,14 +262,14 @@ } } -impl Linear for SimpleZeroOp where X: AXPY + Instance {} +impl Linear for SimpleZeroOp {} #[replace_float_literals(F::cast_from(literal))] impl GEMV for SimpleZeroOp where F: Num, Y: AXPY, - X: AXPY + Instance, + X: VectorSpace + Instance, { // Computes `y = αAx + βy`, where `A` is `Self`. fn gemv>(&self, y: &mut Y, _α: F, _x: I, β: F) { @@ -276,7 +284,7 @@ impl BoundedLinear for SimpleZeroOp where F: Num, - X: AXPY + Instance + Norm, + X: VectorSpace + Norm, E1: NormExponent, E2: NormExponent, { @@ -288,8 +296,8 @@ impl Adjointable for SimpleZeroOp where F: Num, - X: AXPY + Instance + HasDual, - X::DualSpace: AXPY, + X: VectorSpace + HasDual, + X::DualSpace: VectorSpace, { type AdjointCodomain = X::DualSpace; type Adjoint<'b> @@ -303,7 +311,7 @@ } } -pub trait OriginGenerator { +pub trait OriginGenerator { type Ref<'b>: OriginGenerator where Self: 'b; @@ -312,7 +320,7 @@ fn as_ref(&self) -> Self::Ref<'_>; } -impl OriginGenerator for Y { +impl OriginGenerator for Y { type Ref<'b> = &'b Y where @@ -329,7 +337,7 @@ } } -impl<'b, Y: AXPY> OriginGenerator for &'b Y { +impl<'b, Y: VectorSpace> OriginGenerator 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, OY: OriginGenerator, O, F: Float = f64> { +pub struct ZeroOp, OY: OriginGenerator, O, F: Float = f64> { codomain_origin_generator: OY, other_origin_generator: O, _phantoms: PhantomData<(X, Y, F)>, @@ -357,8 +365,8 @@ impl ZeroOp where OY: OriginGenerator, - X: AXPY, - Y: AXPY, + X: VectorSpace, + Y: VectorSpace, F: Float, { pub fn new(y_og: OY) -> Self { @@ -377,7 +385,7 @@ X: HasDual, Y: HasDual, F: Float, - Xprime: AXPY, + Xprime: VectorSpace, Xprime::Owned: AXPY, Yprime: Space + Instance, { @@ -392,8 +400,8 @@ impl Mapping for ZeroOp where - X: Space + Instance, - Y: AXPY, + X: Space, + Y: VectorSpace, F: Float, OY: OriginGenerator, { @@ -406,8 +414,8 @@ impl Linear for ZeroOp where - X: Space + Instance, - Y: AXPY, + X: Space, + Y: VectorSpace, F: Float, OY: OriginGenerator, { @@ -416,7 +424,7 @@ #[replace_float_literals(F::cast_from(literal))] impl GEMV for ZeroOp where - X: Space + Instance, + X: Space, Y: AXPY, F: Float, OY: OriginGenerator, @@ -434,7 +442,7 @@ impl BoundedLinear for ZeroOp where X: Space + Instance + Norm, - Y: AXPY, + Y: VectorSpace, Y::Owned: Clone, F: Float, E1: NormExponent, @@ -452,7 +460,7 @@ X: HasDual, Y: HasDual, F: Float, - Xprime: AXPY, + Xprime: VectorSpace, Xprime::Owned: AXPY, Yprime: Space + Instance, OY: OriginGenerator,