lots of space changes dev

Mon, 01 Sep 2025 20:55:34 -0500

author
Tuomo Valkonen <tuomov@iki.fi>
date
Mon, 01 Sep 2025 20:55:34 -0500
branch
dev
changeset 151
402d717bb5c0
parent 150
c4e394a9c84c
child 152
dab30b331f49
child 153
829c07ea584d

lots of space changes

src/bisection_tree/support.rs file | annotate | diff | comparison | revisions
src/convex.rs file | annotate | diff | comparison | revisions
src/direct_product.rs file | annotate | diff | comparison | revisions
src/euclidean.rs file | annotate | diff | comparison | revisions
src/linops.rs file | annotate | diff | comparison | revisions
src/loc.rs file | annotate | diff | comparison | revisions
src/mapping.rs file | annotate | diff | comparison | revisions
src/nalgebra_support.rs file | annotate | diff | comparison | revisions
src/norms.rs file | annotate | diff | comparison | revisions
src/operator_arithmetic.rs file | annotate | diff | comparison | revisions
--- a/src/bisection_tree/support.rs	Mon Sep 01 13:51:03 2025 -0500
+++ b/src/bisection_tree/support.rs	Mon Sep 01 20:55:34 2025 -0500
@@ -4,9 +4,7 @@
 use super::aggregator::Bounds;
 pub use crate::bounds::{GlobalAnalysis, LocalAnalysis};
 use crate::loc::Loc;
-use crate::mapping::{
-    ClosedSpace, DifferentiableImpl, DifferentiableMapping, Instance, Mapping, Space,
-};
+use crate::mapping::{ClosedSpace, DifferentiableImpl, DifferentiableMapping, Instance, Mapping};
 use crate::maputil::map2;
 use crate::norms::{Linfinity, Norm, L1, L2};
 pub use crate::operator_arithmetic::{Constant, Weighted};
--- a/src/convex.rs	Mon Sep 01 13:51:03 2025 -0500
+++ b/src/convex.rs	Mon Sep 01 20:55:34 2025 -0500
@@ -395,7 +395,7 @@
 impl<X, F> Prox<X> for Norm222<F>
 where
     F: Float,
-    X: Euclidean<F, Owned = X> + ClosedMul<F>,
+    X: Euclidean<F>,
 {
     type Prox<'a>
         = Scaled<F>
@@ -415,7 +415,7 @@
     type Derivative = X::Owned;
 
     fn differential_impl<I: Instance<X>>(&self, x: I) -> Self::Derivative {
-        x.own()
+        x.own().into_owned()
     }
 }
 
--- a/src/direct_product.rs	Mon Sep 01 13:51:03 2025 -0500
+++ b/src/direct_product.rs	Mon Sep 01 20:55:34 2025 -0500
@@ -6,9 +6,7 @@
 */
 
 use crate::euclidean::Euclidean;
-use crate::instance::{
-    ClosedSpace, Decomposition, DecompositionMut, Instance, InstanceMut, MyCow, Ownable,
-};
+use crate::instance::{Decomposition, DecompositionMut, Instance, InstanceMut, MyCow, Ownable};
 use crate::linops::{VectorSpace, AXPY};
 use crate::loc::Loc;
 use crate::mapping::Space;
@@ -289,22 +287,24 @@
 where
     A: Euclidean<F>,
     B: Euclidean<F>,
-    //Pair<A, B>: Euclidean<F>,
-    Self: Sized
-        + Mul<F, Output = <Self as VectorSpace>::Owned>
-        + MulAssign<F>
-        + Div<F, Output = <Self as VectorSpace>::Owned>
-        + DivAssign<F>
-        + Add<Self, Output = <Self as VectorSpace>::Owned>
-        + Sub<Self, Output = <Self as VectorSpace>::Owned>
-        + for<'b> Add<&'b Self, Output = <Self as VectorSpace>::Owned>
-        + for<'b> Sub<&'b Self, Output = <Self as VectorSpace>::Owned>
-        + AddAssign<Self>
-        + for<'b> AddAssign<&'b Self>
-        + SubAssign<Self>
-        + for<'b> SubAssign<&'b Self>
-        + Neg<Output = <Self as VectorSpace>::Owned>,
+    // //Pair<A, B>: Euclidean<F>,
+    // Self: Sized
+    //     + Mul<F, Output = Self::OwnedEuclidean>
+    //     + MulAssign<F>
+    //     + Div<F, Output = Self::OwnedEuclidean>
+    //     + DivAssign<F>
+    //     + Add<Self, Output = Self::OwnedEuclidean>
+    //     + Sub<Self, Output = Self::OwnedEuclidean>
+    //     + for<'b> Add<&'b Self, Output = Self::OwnedEuclidean>
+    //     + for<'b> Sub<&'b Self, Output = Self::OwnedEuclidean>
+    //     + AddAssign<Self>
+    //     + for<'b> AddAssign<&'b Self>
+    //     + SubAssign<Self>
+    //     + for<'b> SubAssign<&'b Self>
+    //     + Neg<Output = Self::OwnedEuclidean>,
 {
+    type OwnedEuclidean = Pair<A::OwnedEuclidean, B::OwnedEuclidean>;
+
     fn dot<I: Instance<Self>>(&self, other: I) -> F {
         other.eval_decompose(|Pair(u, v)| self.0.dot(u) + self.1.dot(v))
     }
@@ -318,16 +318,14 @@
     }
 }
 
-impl<F, A, B, O, P> VectorSpace for Pair<A, B>
+impl<F, A, B> VectorSpace for Pair<A, B>
 where
-    A: VectorSpace<Field = F, Owned = O, OwnedVariant = O>,
-    B: VectorSpace<Field = F, Owned = P, OwnedVariant = P>,
-    O: ClosedSpace + AXPY<A, Field = F, Owned = O, OwnedVariant = O>,
-    P: ClosedSpace + AXPY<B, Field = F, Owned = P, OwnedVariant = P>,
+    A: VectorSpace<Field = F>,
+    B: VectorSpace<Field = F>,
     F: Num,
 {
     type Field = F;
-    type Owned = Pair<O, P>;
+    type Owned = Pair<A::Owned, B::Owned>;
 
     /// Return a similar zero as `self`.
     fn similar_origin(&self) -> Self::Owned {
@@ -347,8 +345,8 @@
     A: AXPY<U, Field = F>,
     B: AXPY<V, Field = F>,
     F: Num,
-    Self: MulAssign<F> + DivAssign<F>,
-    Pair<A, B>: MulAssign<F> + DivAssign<F>,
+    // Self: MulAssign<F> + DivAssign<F>,
+    // Pair<A, B>: MulAssign<F> + DivAssign<F>,
 {
     fn axpy<I: Instance<Pair<U, V>>>(&mut self, α: F, x: I, β: F) {
         x.eval_decompose(|Pair(u, v)| {
@@ -383,6 +381,7 @@
 pub struct PairDecomposition<D, Q>(D, Q);
 
 impl<A: Space, B: Space> Space for Pair<A, B> {
+    type OwnedSpace = Pair<A::OwnedSpace, B::OwnedSpace>;
     type Decomp = PairDecomposition<A::Decomp, B::Decomp>;
 }
 
--- a/src/euclidean.rs	Mon Sep 01 13:51:03 2025 -0500
+++ b/src/euclidean.rs	Mon Sep 01 20:55:34 2025 -0500
@@ -4,9 +4,8 @@
 
 use crate::instance::Instance;
 use crate::linops::{VectorSpace, AXPY};
-use crate::norms::{HasDual, Reflexive};
+use crate::norms::Reflexive;
 use crate::types::*;
-use std::ops::{Add, AddAssign, Sub, SubAssign};
 
 pub mod wrap;
 
@@ -17,17 +16,13 @@
 /// The type should implement vector space operations (addition, subtraction, scalar
 /// multiplication and scalar division) along with their assignment versions, as well
 /// as an inner product.
-// TODO: remove F parameter, use AXPY::Field
+// TODO: remove F parameter, use VectorSpace::Field
 pub trait Euclidean<F: Float = f64>:
-    HasDual<F, DualSpace = Self>
-    + VectorSpace<Field = F>
-    + Reflexive<F>
-    // TODO: move the following to AXPY
-    + for<'b> Add<&'b Self, Output = <Self as VectorSpace>::Owned>
-    + for<'b> Sub<&'b Self, Output = <Self as VectorSpace>::Owned>
-    + for<'b> AddAssign<&'b Self>
-    + for<'b> SubAssign<&'b Self>
+    VectorSpace<Field = F, Owned = Self::OwnedEuclidean>
+    + Reflexive<F, DualSpace = Self::OwnedEuclidean>
 {
+    type OwnedEuclidean: ClosedEuclidean<F>;
+
     // Inner product
     fn dot<I: Instance<Self>>(&self, other: I) -> F;
 
@@ -71,10 +66,14 @@
     }
 }
 
+pub trait ClosedEuclidean<F: Float = f64>:
+    Instance<Self> + Euclidean<F, OwnedEuclidean = Self>
+{
+}
+impl<F: Float, X: Instance<X> + Euclidean<F, OwnedEuclidean = Self>> ClosedEuclidean<F> for X {}
+
 // TODO: remove F parameter, use AXPY::Field
-pub trait EuclideanMut<F: Float = f64>:
-    Euclidean<F> + AXPY<Field = F> + for<'b> AddAssign<&'b Self> + for<'b> SubAssign<&'b Self>
-{
+pub trait EuclideanMut<F: Float = f64>: Euclidean<F> + AXPY<Field = F> {
     /// In-place projection to the 2-ball.
     #[inline]
     fn proj_ball2_mut(&mut self, ρ: F) {
@@ -85,10 +84,7 @@
     }
 }
 
-impl<X, F: Float> EuclideanMut<F> for X where
-    X: Euclidean<F> + AXPY<Field = F> + for<'b> AddAssign<&'b Self> + for<'b> SubAssign<&'b Self>
-{
-}
+impl<X, F: Float> EuclideanMut<F> for X where X: Euclidean<F> + AXPY<Field = F> {}
 
 /// Trait for [`Euclidean`] spaces with dimensions known at compile time.
 pub trait StaticEuclidean<F: Float = f64>: Euclidean<F> {
--- a/src/linops.rs	Mon Sep 01 13:51:03 2025 -0500
+++ b/src/linops.rs	Mon Sep 01 20:55:34 2025 -0500
@@ -36,6 +36,8 @@
     + Sub<Self, Output = Self::Owned>
     + Sub<Self::Owned, Output = Self::Owned>
     + Neg
+    + for<'b> Add<&'b Self, Output = <Self as VectorSpace>::Owned>
+    + for<'b> Sub<&'b Self, Output = <Self as VectorSpace>::Owned>
 {
     type Field: Num;
     type Owned: ClosedSpace
@@ -69,6 +71,8 @@
     + AddAssign<Self::Owned>
     + SubAssign<Self>
     + SubAssign<Self::Owned>
+    + for<'b> AddAssign<&'b Self>
+    + for<'b> SubAssign<&'b Self>
 where
     X: Space,
 {
@@ -89,6 +93,9 @@
     fn set_zero(&mut self);
 }
 
+pub trait ClosedVectorSpace: Instance<Self> + VectorSpace<Owned = Self> {}
+impl<X: Instance<X> + VectorSpace<Owned = Self>> ClosedVectorSpace for X {}
+
 /// Efficient in-place application for [`Linear`] operators.
 #[replace_float_literals(F::cast_from(literal))]
 pub trait GEMV<F: Num, X: Space, Y = <Self as Mapping<X>>::Codomain>: Linear<X> {
@@ -141,7 +148,7 @@
     X: Space,
     Yʹ: Space,
 {
-    type AdjointCodomain: Space;
+    type AdjointCodomain: ClosedSpace;
     type Adjoint<'a>: Linear<Yʹ, Codomain = Self::AdjointCodomain>
     where
         Self: 'a;
@@ -163,7 +170,7 @@
 pub trait Preadjointable<X: Space, Ypre: Space = <Self as Mapping<X>>::Codomain>:
     Linear<X>
 {
-    type PreadjointCodomain: Space;
+    type PreadjointCodomain: ClosedSpace;
     type Preadjoint<'a>: Linear<Ypre, Codomain = Self::PreadjointCodomain>
     where
         Self: 'a;
@@ -190,10 +197,10 @@
 }
 
 impl<X: Space> Mapping<X> for IdOp<X> {
-    type Codomain = X::OwnedVariant;
+    type Codomain = X::OwnedSpace;
 
-    fn apply<I: Instance<X>>(&self, x: I) -> X {
-        x.own()
+    fn apply<I: Instance<X>>(&self, x: I) -> Self::Codomain {
+        x.own().into_owned()
     }
 }
 
@@ -226,10 +233,10 @@
     }
 }
 
-impl<X: Clone + Space> Adjointable<X, X> for IdOp<X> {
-    type AdjointCodomain = X;
+impl<X: Clone + Space> Adjointable<X, X::OwnedSpace> for IdOp<X> {
+    type AdjointCodomain = X::OwnedSpace;
     type Adjoint<'a>
-        = IdOp<X>
+        = IdOp<X::OwnedSpace>
     where
         X: 'a;
 
@@ -238,10 +245,10 @@
     }
 }
 
-impl<X: Clone + Space> Preadjointable<X, X> for IdOp<X> {
-    type PreadjointCodomain = X;
+impl<X: Clone + Space> Preadjointable<X, X::OwnedSpace> for IdOp<X> {
+    type PreadjointCodomain = X::OwnedSpace;
     type Preadjoint<'a>
-        = IdOp<X>
+        = IdOp<X::OwnedSpace>
     where
         X: 'a;
 
@@ -297,7 +304,7 @@
 where
     F: Num,
     X: VectorSpace<Field = F> + HasDual<F>,
-    X::DualSpace: VectorSpace<Owned = X::DualSpace>,
+    X::DualSpace: ClosedVectorSpace,
 {
     type AdjointCodomain = X::DualSpace;
     type Adjoint<'b>
@@ -460,9 +467,9 @@
     X: HasDual<F, DualSpace = Xprime>,
     Y: HasDual<F, DualSpace = Yprime>,
     F: Float,
-    Xprime: VectorSpace<Field = F, Owned = Xprime>,
-    Xprime::Owned: AXPY<Field = F>,
-    Yprime: Space + Instance<Yprime>,
+    Xprime: ClosedVectorSpace<Field = F>,
+    //Xprime::Owned: AXPY<Field = F>,
+    Yprime: ClosedSpace,
     OY: OriginGenerator<Y>,
     OXprime: OriginGenerator<X::DualSpace>,
 {
@@ -540,7 +547,7 @@
     S: Mapping<A>,
     T: Mapping<B>,
     S::Codomain: Add<T::Codomain>,
-    <S::Codomain as Add<T::Codomain>>::Output: Space,
+    <S::Codomain as Add<T::Codomain>>::Output: ClosedSpace,
 {
     type Codomain = <S::Codomain as Add<T::Codomain>>::Output;
 
@@ -556,7 +563,7 @@
     S: Linear<A>,
     T: Linear<B>,
     S::Codomain: Add<T::Codomain>,
-    <S::Codomain as Add<T::Codomain>>::Output: Space,
+    <S::Codomain as Add<T::Codomain>>::Output: ClosedSpace,
 {
 }
 
@@ -693,7 +700,7 @@
     A: Space,
     Xʹ: Space,
     Yʹ: Space,
-    R: Space + ClosedAdd,
+    R: ClosedSpace + ClosedAdd,
     S: Adjointable<A, Xʹ, AdjointCodomain = R>,
     T: Adjointable<A, Yʹ, AdjointCodomain = R>,
     Self: Linear<A>,
@@ -718,7 +725,7 @@
     A: Space,
     Xʹ: Space,
     Yʹ: Space,
-    R: Space + ClosedAdd,
+    R: ClosedSpace + ClosedAdd,
     S: Preadjointable<A, Xʹ, PreadjointCodomain = R>,
     T: Preadjointable<A, Yʹ, PreadjointCodomain = R>,
     Self: Linear<A>,
@@ -802,7 +809,7 @@
     B: Space,
     Xʹ: Space,
     Yʹ: Space,
-    R: Space,
+    R: ClosedSpace,
     S: Adjointable<A, Xʹ>,
     T: Adjointable<B, Yʹ>,
     Self: Linear<Pair<A, B>>,
@@ -825,7 +832,7 @@
     B: Space,
     Xʹ: Space,
     Yʹ: Space,
-    R: Space,
+    R: ClosedSpace,
     S: Preadjointable<A, Xʹ>,
     T: Preadjointable<B, Yʹ>,
     Self: Linear<Pair<A, B>>,
@@ -856,7 +863,7 @@
             S: BoundedLinear<A, ExpA, ExpR, F>,
             T: BoundedLinear<B, ExpB, ExpR, F>,
             S::Codomain: Add<T::Codomain>,
-            <S::Codomain as Add<T::Codomain>>::Output: Space,
+            <S::Codomain as Add<T::Codomain>>::Output: ClosedSpace,
             ExpA: NormExponent,
             ExpB: NormExponent,
             ExpR: NormExponent,
@@ -912,7 +919,8 @@
 impl<Domain, F> Mapping<Domain> for Scaled<F>
 where
     F: Float,
-    Domain: Space + ClosedMul<F>,
+    Domain: Space + Mul<F>,
+    <Domain as Mul<F>>::Output: ClosedSpace,
 {
     type Codomain = <Domain as Mul<F>>::Output;
 
@@ -925,6 +933,7 @@
 impl<Domain, F> Linear<Domain> for Scaled<F>
 where
     F: Float,
-    Domain: Space + ClosedMul<F>,
+    Domain: Space + Mul<F>,
+    <Domain as Mul<F>>::Output: ClosedSpace,
 {
 }
--- a/src/loc.rs	Mon Sep 01 13:51:03 2025 -0500
+++ b/src/loc.rs	Mon Sep 01 20:55:34 2025 -0500
@@ -448,6 +448,8 @@
 domination!(L2, L1);
 
 impl<F: Float, const N: usize> Euclidean<F> for Loc<N, F> {
+    type OwnedEuclidean = Self;
+
     /// This implementation is not stabilised as it's meant to be used for very small vectors.
     /// Use [`nalgebra`] for larger vectors.
     #[inline]
--- a/src/mapping.rs	Mon Sep 01 13:51:03 2025 -0500
+++ b/src/mapping.rs	Mon Sep 01 20:55:34 2025 -0500
@@ -166,8 +166,9 @@
     _phantoms: PhantomData<(X, F)>,
 }
 
-impl<F: Space, X, G> Mapping<X> for FlattenedCodomain<X, F, G>
+impl<F, X, G> Mapping<X> for FlattenedCodomain<X, F, G>
 where
+    F: ClosedSpace,
     X: Space,
     G: Mapping<X, Codomain = Loc<1, F>>,
 {
@@ -200,7 +201,7 @@
 impl<'a, X, F, G, const N: usize> Mapping<X> for SlicedCodomain<'a, X, F, G, N>
 where
     X: Space,
-    F: Copy + Space,
+    F: Copy + ClosedSpace,
     G: Mapping<X, Codomain = Loc<N, F>>,
 {
     type Codomain = F;
--- a/src/nalgebra_support.rs	Mon Sep 01 13:51:03 2025 -0500
+++ b/src/nalgebra_support.rs	Mon Sep 01 20:55:34 2025 -0500
@@ -273,10 +273,12 @@
 impl<E, M, S> Euclidean<E> for Vector<E, M, S>
 where
     M: Dim,
-    S: StorageMut<E, M> + Clone,
+    S: Storage<E, M>,
     E: Float + Scalar + Zero + One + RealField,
     DefaultAllocator: Allocator<M>,
 {
+    type OwnedEuclidean = OVector<E, M>;
+
     #[inline]
     fn dot<I: Instance<Self>>(&self, other: I) -> E {
         other.eval_ref_decompose(|r| Vector::<E, M, S>::dot(self, r))
@@ -296,7 +298,7 @@
 impl<E, M, S> StaticEuclidean<E> for Vector<E, M, S>
 where
     M: DimName,
-    S: StorageMut<E, M> + Clone,
+    S: Storage<E, M>,
     E: Float + Scalar + Zero + One + RealField,
     DefaultAllocator: Allocator<M>,
 {
@@ -310,7 +312,7 @@
 impl<E, M, S> Normed<E> for Vector<E, M, S>
 where
     M: Dim,
-    S: Storage<E, M> + Clone,
+    S: Storage<E, M>,
     E: Float + Scalar + Zero + One + RealField,
     DefaultAllocator: Allocator<M>,
 {
@@ -330,12 +332,11 @@
 impl<E, M, S> HasDual<E> for Vector<E, M, S>
 where
     M: Dim,
-    S: StorageMut<E, M> + Clone,
+    S: Storage<E, M>,
     E: Float + Scalar + Zero + One + RealField,
     DefaultAllocator: Allocator<M>,
 {
-    // TODO: Doesn't work with different storage formats.
-    type DualSpace = Vector<E, M, S>;
+    type DualSpace = OVector<E, M>;
 
     fn dual_origin(&self) -> OVector<E, M> {
         OVector::zeros_generic(M::from_usize(self.len()), Const)
--- a/src/norms.rs	Mon Sep 01 13:51:03 2025 -0500
+++ b/src/norms.rs	Mon Sep 01 20:55:34 2025 -0500
@@ -4,7 +4,7 @@
 
 use crate::euclidean::*;
 use crate::instance::Ownable;
-use crate::linops::VectorSpace;
+use crate::linops::{ClosedVectorSpace, VectorSpace};
 use crate::mapping::{Instance, Mapping, Space};
 use crate::types::*;
 use serde::{Deserialize, Serialize};
@@ -229,7 +229,7 @@
 }
 
 pub trait HasDual<F: Num = f64>: Normed<F> + VectorSpace<Field = F> {
-    type DualSpace: Normed<F> + VectorSpace<Field = F>;
+    type DualSpace: Normed<F> + ClosedVectorSpace<Field = F>;
 
     fn dual_origin(&self) -> <Self::DualSpace as VectorSpace>::Owned;
 }
@@ -237,11 +237,14 @@
 /// Automatically implemented trait for reflexive spaces
 pub trait Reflexive<F: Num = f64>: HasDual<F>
 where
-    Self::DualSpace: HasDual<F, DualSpace = Self>,
+    Self::DualSpace: HasDual<F, DualSpace = Self::OwnedSpace>,
 {
 }
 
-impl<F: Num, X: HasDual<F>> Reflexive<F> for X where X::DualSpace: HasDual<F, DualSpace = X> {}
+impl<F: Num, X: HasDual<F>> Reflexive<F> for X where
+    X::DualSpace: HasDual<F, DualSpace = Self::OwnedSpace>
+{
+}
 
 pub trait HasDualExponent: NormExponent {
     type DualExp: NormExponent;
--- a/src/operator_arithmetic.rs	Mon Sep 01 13:51:03 2025 -0500
+++ b/src/operator_arithmetic.rs	Mon Sep 01 20:55:34 2025 -0500
@@ -42,15 +42,15 @@
     }
 }
 
-impl<'a, T, V, D, F, C> Mapping<D> for Weighted<T, C>
+impl<'a, T, D, F, C> Mapping<D> for Weighted<T, C>
 where
     F: Float,
     D: Space,
-    T: Mapping<D, Codomain = V>,
-    V: Space + ClosedMul<F>,
+    T: Mapping<D>,
+    T::Codomain: ClosedMul<F>,
     C: Constant<Type = F>,
 {
-    type Codomain = V;
+    type Codomain = T::Codomain;
 
     #[inline]
     fn apply<I: Instance<D>>(&self, x: I) -> Self::Codomain {

mercurial