--- a/src/norms.rs Mon Sep 01 00:04:22 2025 -0500 +++ b/src/norms.rs Mon Sep 01 13:51:03 2025 -0500 @@ -3,7 +3,8 @@ */ use crate::euclidean::*; -use crate::linops::AXPY; +use crate::instance::Ownable; +use crate::linops::VectorSpace; use crate::mapping::{Instance, Mapping, Space}; use crate::types::*; use serde::{Deserialize, Serialize}; @@ -123,16 +124,12 @@ /// /// println!("{:?}, {:?}", x.proj_ball(1.0, L2), x.proj_ball(0.5, Linfinity)); /// ``` -pub trait Projection<F: Num, Exponent: NormExponent>: Norm<Exponent, F> + Sized -where - F: Float, -{ +pub trait Projection<F: Num, Exponent: NormExponent>: Ownable + Norm<Exponent, F> { /// Projection of `self` to the `q`-norm-ball of radius ρ. - fn proj_ball(mut self, ρ: F, q: Exponent) -> Self { - self.proj_ball_mut(ρ, q); - self - } + fn proj_ball(self, ρ: F, q: Exponent) -> Self::OwnedVariant; +} +pub trait ProjectionMut<F: Num, Exponent: NormExponent>: Projection<F, Exponent> { /// In-place projection of `self` to the `q`-norm-ball of radius ρ. fn proj_ball_mut(&mut self, ρ: F, q: Exponent); } @@ -146,10 +143,12 @@ impl<F: Float, E: Euclidean<F> + Norm<L2, F>> Projection<F, L2> for E { #[inline] - fn proj_ball(self, ρ: F, _p: L2) -> Self { + fn proj_ball(self, ρ: F, _p: L2) -> Self::OwnedVariant { self.proj_ball2(ρ) } +} +impl<F: Float, E: EuclideanMut<F> + Norm<L2, F>> ProjectionMut<F, L2> for E { #[inline] fn proj_ball_mut(&mut self, ρ: F, _p: L2) { self.proj_ball2_mut(ρ) @@ -229,10 +228,10 @@ } } -pub trait HasDual<F: Num = f64>: Normed<F> + AXPY<Field = F> { - type DualSpace: Normed<F> + AXPY<Field = F>; +pub trait HasDual<F: Num = f64>: Normed<F> + VectorSpace<Field = F> { + type DualSpace: Normed<F> + VectorSpace<Field = F>; - fn dual_origin(&self) -> <Self::DualSpace as AXPY>::Owned; + fn dual_origin(&self) -> <Self::DualSpace as VectorSpace>::Owned; } /// Automatically implemented trait for reflexive spaces