diff -r 2f1798c65fd6 -r c4e394a9c84c src/euclidean.rs --- a/src/euclidean.rs Mon Sep 01 00:04:22 2025 -0500 +++ b/src/euclidean.rs Mon Sep 01 13:51:03 2025 -0500 @@ -3,13 +3,15 @@ */ use crate::instance::Instance; -use crate::linops::AXPY; +use crate::linops::{VectorSpace, AXPY}; use crate::norms::{HasDual, Reflexive}; use crate::types::*; use std::ops::{Add, AddAssign, Sub, SubAssign}; pub mod wrap; +// TODO: Euclidean & EuclideanMut +// /// Space (type) with Euclidean and vector space structure /// /// The type should implement vector space operations (addition, subtraction, scalar @@ -18,11 +20,11 @@ // TODO: remove F parameter, use AXPY::Field pub trait Euclidean: HasDual - + AXPY + + VectorSpace + Reflexive // TODO: move the following to AXPY - + for<'b> Add<&'b Self, Output = ::Owned> - + for<'b> Sub<&'b Self, Output = ::Owned> + + for<'b> Add<&'b Self, Output = ::Owned> + + for<'b> Sub<&'b Self, Output = ::Owned> + for<'b> AddAssign<&'b Self> + for<'b> SubAssign<&'b Self> { @@ -59,11 +61,20 @@ /// Projection to the 2-ball. #[inline] - fn proj_ball2(mut self, ρ: F) -> Self { - self.proj_ball2_mut(ρ); - self + fn proj_ball2(self, ρ: F) -> Self::Owned { + let r = self.norm2(); + if r > ρ { + self * (ρ / r) + } else { + self.into_owned() + } } +} +// TODO: remove F parameter, use AXPY::Field +pub trait EuclideanMut: + Euclidean + AXPY + for<'b> AddAssign<&'b Self> + for<'b> SubAssign<&'b Self> +{ /// In-place projection to the 2-ball. #[inline] fn proj_ball2_mut(&mut self, ρ: F) { @@ -74,8 +85,13 @@ } } +impl EuclideanMut for X where + X: Euclidean + AXPY + for<'b> AddAssign<&'b Self> + for<'b> SubAssign<&'b Self> +{ +} + /// Trait for [`Euclidean`] spaces with dimensions known at compile time. pub trait StaticEuclidean: Euclidean { /// Returns the origin - fn origin() -> ::Owned; + fn origin() -> ::Owned; }