--- a/src/loc.rs Mon Sep 01 00:04:22 2025 -0500 +++ b/src/loc.rs Mon Sep 01 13:51:03 2025 -0500 @@ -4,8 +4,8 @@ */ use crate::euclidean::*; -use crate::instance::{BasicDecomposition, Instance}; -use crate::linops::{Linear, Mapping, AXPY}; +use crate::instance::{BasicDecomposition, Instance, Ownable}; +use crate::linops::{Linear, Mapping, VectorSpace, AXPY}; use crate::mapping::Space; use crate::maputil::{map1, map1_mut, map2, map2_mut, FixedLength, FixedLengthMut}; use crate::norms::*; @@ -27,6 +27,21 @@ pub [F; N], ); +/// Trait for ownable-by-consumption objects +impl<const N: usize, F: Copy> Ownable for Loc<N, F> { + type OwnedVariant = Self; + + #[inline] + fn into_owned(self) -> Self::OwnedVariant { + self + } + + /// Returns an owned instance of a reference. + fn clone_owned(&self) -> Self::OwnedVariant { + self.clone() + } +} + impl<F: Display, const N: usize> Display for Loc<N, F> { // Required method fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { @@ -648,6 +663,14 @@ impl<F: Float, const N: usize> Projection<F, Linfinity> for Loc<N, F> { #[inline] + fn proj_ball(mut self, ρ: F, exp: Linfinity) -> Self { + self.proj_ball_mut(ρ, exp); + self + } +} + +impl<F: Float, const N: usize> ProjectionMut<F, Linfinity> for Loc<N, F> { + #[inline] fn proj_ball_mut(&mut self, ρ: F, _: Linfinity) { self.iter_mut() .for_each(|v| *v = num_traits::clamp(*v, -ρ, ρ)) @@ -706,6 +729,7 @@ } impl<F: Num, const N: usize> Space for Loc<N, F> { + type OwnedSpace = Self; type Decomp = BasicDecomposition; } @@ -719,10 +743,32 @@ impl<F: Float, const N: usize> Linear<Loc<N, F>> for Loc<N, F> {} -impl<F: Float, const N: usize> AXPY<Loc<N, F>> for Loc<N, F> { +impl<F: Float, const N: usize> VectorSpace for Loc<N, F> { type Field = F; type Owned = Self; + // #[inline] + // fn make_origin_generator(&self) -> StaticEuclideanOriginGenerator { + // StaticEuclideanOriginGenerator + // } + + #[inline] + fn similar_origin(&self) -> Self::Owned { + Self::ORIGIN + } + + #[inline] + fn similar_origin_inst<I: Instance<Self>>(_: I) -> Self::Owned { + Self::ORIGIN + } + + // #[inline] + // fn into_owned(self) -> Self::Owned { + // self + // } +} + +impl<F: Float, const N: usize> AXPY<Loc<N, F>> for Loc<N, F> { #[inline] fn axpy<I: Instance<Loc<N, F>>>(&mut self, α: F, x: I, β: F) { x.eval(|x̃| { @@ -739,21 +785,6 @@ x.eval(|x̃| map2_mut(self, x̃, |yi, xi| *yi = *xi)) } - // #[inline] - // fn make_origin_generator(&self) -> StaticEuclideanOriginGenerator { - // StaticEuclideanOriginGenerator - // } - - #[inline] - fn similar_origin(&self) -> Self::Owned { - Self::ORIGIN - } - - #[inline] - fn similar_origin_inst<I: Instance<Self>>(_: I) -> Self::Owned { - Self::ORIGIN - } - #[inline] fn set_zero(&mut self) { *self = Self::ORIGIN;