src/norms.rs

branch
dev
changeset 81
d2acaaddd9af
parent 33
75d65fa74eba
--- 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))
     }

mercurial