--- a/src/norms.rs Sun Nov 10 09:02:57 2024 -0500 +++ b/src/norms.rs Tue Dec 31 09:12:43 2024 -0500 @@ -5,6 +5,7 @@ use serde::Serialize; use crate::types::*; use crate::euclidean::*; +pub use crate::types::{HasScalarField, HasRealField}; // // Abstract norms @@ -53,7 +54,6 @@ pub struct HuberL21<F : Float>(pub F); impl<F : Float> NormExponent for HuberL21<F> {} - /// A normed space (type) with exponent or other type `Exponent` for the norm. /// /// Use as @@ -64,27 +64,28 @@ /// /// println!("{}, {} {}", x.norm(L1), x.norm(L2), x.norm(Linfinity)) /// ``` -pub trait Norm<F : Num, Exponent : NormExponent> { +pub trait Norm<Exponent : NormExponent> : HasScalarField { /// Calculate the norm. - fn norm(&self, _p : Exponent) -> F; + fn norm(&self, _p : Exponent) -> Self::Field; } /// Indicates that the `Self`-[`Norm`] is dominated by the `Exponent`-`Norm` on the space /// `Elem` with the corresponding field `F`. -pub trait Dominated<F : Num, Exponent : NormExponent, Elem> { +pub trait Dominated<Exponent : NormExponent, Elem> +where Elem : HasScalarField { /// Indicates the factor $c$ for the inequality $‖x‖ ≤ C ‖x‖_p$. - fn norm_factor(&self, p : Exponent) -> F; + fn norm_factor(&self, p : Exponent) -> Elem::Field; /// Given a norm-value $‖x‖_p$, calculates $C‖x‖_p$ such that $‖x‖ ≤ C‖x‖_p$ #[inline] - fn from_norm(&self, p_norm : F, p : Exponent) -> F { + fn from_norm(&self, p_norm : Elem::Field, p : Exponent) -> Elem::Field { p_norm * self.norm_factor(p) } } /// Trait for distances with respect to a norm. -pub trait Dist<F : Num, Exponent : NormExponent> : Norm<F, Exponent> { +pub trait Dist<Exponent : NormExponent> : Norm<Exponent> { /// Calculate the distance - fn dist(&self, other : &Self, _p : Exponent) -> F; + fn dist(&self, other : &Self, _p : Exponent) -> Self::Field; } /// Trait for Euclidean projections to the `Exponent`-[`Norm`]-ball. @@ -97,16 +98,15 @@ /// /// println!("{:?}, {:?}", x.proj_ball(1.0, L2), x.proj_ball(0.5, Linfinity)); /// ``` -pub trait Projection<F : Num, Exponent : NormExponent> : Norm<F, Exponent> + Euclidean<F> -where F : Float { +pub trait Projection<Exponent : NormExponent> : Norm<Exponent> + Euclidean { /// Projection of `self` to the `q`-norm-ball of radius ρ. - fn proj_ball(mut self, ρ : F, q : Exponent) -> Self { + fn proj_ball(mut self, ρ : Self::Field, q : Exponent) -> Self { self.proj_ball_mut(ρ, q); self } /// In-place projection of `self` to the `q`-norm-ball of radius ρ. - fn proj_ball_mut(&mut self, ρ : F, _q : Exponent); + fn proj_ball_mut(&mut self, ρ : Self::Field, _q : Exponent); } /*impl<F : Float, E : Euclidean<F>> Norm<F, L2> for E { @@ -116,12 +116,12 @@ fn dist(&self, other : &Self, _p : L2) -> F { self.dist2(other) } }*/ -impl<F : Float, E : Euclidean<F> + Norm<F, L2>> Projection<F, L2> for E { +impl<E : Norm<L2> + Euclidean> Projection<L2> for E { #[inline] - fn proj_ball(self, ρ : F, _p : L2) -> Self { self.proj_ball2(ρ) } + fn proj_ball(self, ρ : Self::Field, _p : L2) -> Self { self.proj_ball2(ρ) } #[inline] - fn proj_ball_mut(&mut self, ρ : F, _p : L2) { self.proj_ball2_mut(ρ) } + fn proj_ball_mut(&mut self, ρ : Self::Field, _p : L2) { self.proj_ball2_mut(ρ) } } impl<F : Float> HuberL1<F> { @@ -142,13 +142,13 @@ } } -impl<F : Float, E : Euclidean<F>> Norm<F, HuberL1<F>> for E { +impl<F : Float, E : Euclidean<RealField=F>> Norm<HuberL1<F>> for E { fn norm(&self, huber : HuberL1<F>) -> F { huber.apply(self.norm2_squared()) } } -impl<F : Float, E : Euclidean<F>> Dist<F, HuberL1<F>> for E { +impl<F : Float, E : Euclidean<RealField=F>> Dist<HuberL1<F>> for E { fn dist(&self, other : &Self, huber : HuberL1<F>) -> F { huber.apply(self.dist2_squared(other)) }