@@ -39,13 +39,44 @@ pub trait Norm<T: SimdComplexField> {
3939 ShapeConstraint : SameNumberOfRows < R1 , R2 > + SameNumberOfColumns < C1 , C2 > ;
4040}
4141
42- /// Euclidean norm.
42+ /// Euclidean norm of a vector, or Frobenius norm of a matrix.
43+ ///
44+ /// Computes sqrt(sum |a_ij|^2) over all elements.
45+ ///
46+ /// <div class="warning">
47+ /// For matrices, this is the Frobenius norm, not the matrix 2-norm (spectral norm).
48+ /// </div>
4349#[ derive( Copy , Clone , Debug ) ]
4450pub struct EuclideanNorm ;
45- /// Lp norm.
51+
52+ /// Entrywise Lp norm of a matrix or vector.
53+ ///
54+ /// Computes (sum |a_ij|^p)^(1/p) over all elements.
55+ ///
56+ /// <div class="warning">
57+ /// This does not match the standard mathematical definition of the matrix Lp norm.
58+ /// </div>
4659#[ derive( Copy , Clone , Debug ) ]
4760pub struct LpNorm ( pub i32 ) ;
48- /// L-infinite norm aka. Chebytchev norm aka. uniform norm aka. suppremum norm.
61+
62+ /// Induced matrix 1-norm (maximum absolute column sum).
63+ ///
64+ /// Computes max_j sum_i |a_ij|.
65+ ///
66+ /// For a column vector, this is the L1 norm.
67+ /// For a row vector, this is the L-infinity norm.
68+ #[ derive( Copy , Clone , Debug ) ]
69+ pub struct OneNorm ;
70+
71+ /// Entrywise L-infinity norm of a matrix or vector.
72+ ///
73+ /// Computes max |a_ij| over all elements.
74+ ///
75+ /// For a vector this is the standard L-infinity norm.
76+ ///
77+ /// <div class="warning">
78+ /// For matrices, this is the entrywise maximum, not the induced matrix infinity-norm.
79+ /// </div>
4980#[ derive( Copy , Clone , Debug ) ]
5081pub struct UniformNorm ;
5182
@@ -120,6 +151,45 @@ impl<T: SimdComplexField> Norm<T> for LpNorm {
120151 }
121152}
122153
154+ impl < T : SimdComplexField > Norm < T > for OneNorm {
155+ #[ inline]
156+ fn norm < R , C , S > ( & self , m : & Matrix < T , R , C , S > ) -> T :: SimdRealField
157+ where
158+ R : Dim ,
159+ C : Dim ,
160+ S : Storage < T , R , C > ,
161+ {
162+ m. column_iter ( )
163+ . map ( |col| col. fold ( T :: SimdRealField :: zero ( ) , |a, b| a + b. simd_modulus ( ) ) )
164+ . fold ( T :: SimdRealField :: zero ( ) , T :: SimdRealField :: simd_max)
165+ }
166+
167+ #[ inline]
168+ fn metric_distance < R1 , C1 , S1 , R2 , C2 , S2 > (
169+ & self ,
170+ m1 : & Matrix < T , R1 , C1 , S1 > ,
171+ m2 : & Matrix < T , R2 , C2 , S2 > ,
172+ ) -> T :: SimdRealField
173+ where
174+ R1 : Dim ,
175+ C1 : Dim ,
176+ S1 : Storage < T , R1 , C1 > ,
177+ R2 : Dim ,
178+ C2 : Dim ,
179+ S2 : Storage < T , R2 , C2 > ,
180+ ShapeConstraint : SameNumberOfRows < R1 , R2 > + SameNumberOfColumns < C1 , C2 > ,
181+ {
182+ m1. column_iter ( )
183+ . zip ( m2. column_iter ( ) )
184+ . map ( |( c1, c2) | {
185+ c1. zip_fold ( & c2, T :: SimdRealField :: zero ( ) , |acc, a, b| {
186+ acc + ( a - b) . simd_modulus ( )
187+ } )
188+ } )
189+ . fold ( T :: SimdRealField :: zero ( ) , T :: SimdRealField :: simd_max)
190+ }
191+ }
192+
123193impl < T : SimdComplexField > Norm < T > for UniformNorm {
124194 #[ inline]
125195 fn norm < R , C , S > ( & self , m : & Matrix < T , R , C , S > ) -> T :: SimdRealField
@@ -158,8 +228,11 @@ impl<T: SimdComplexField> Norm<T> for UniformNorm {
158228}
159229
160230/// # Magnitude and norms
231+ ///
232+ /// Unless otherwise noted, the norm used throughout is the L2 norm for vectors and
233+ /// the Frobenius norm for matrices.
161234impl < T : Scalar , R : Dim , C : Dim , S : Storage < T , R , C > > Matrix < T , R , C , S > {
162- /// The squared L2 norm of this vector.
235+ /// Squared L2 norm of this vector, or squared Frobenius norm of this matrix .
163236 #[ inline]
164237 #[ must_use]
165238 pub fn norm_squared ( & self ) -> T :: SimdRealField
@@ -176,7 +249,7 @@ impl<T: Scalar, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
176249 res
177250 }
178251
179- /// The L2 norm of this matrix.
252+ /// L2 norm of this vector, or Frobenius norm of this matrix.
180253 ///
181254 /// Use `.apply_norm` to apply a custom norm.
182255 #[ inline]
@@ -188,7 +261,7 @@ impl<T: Scalar, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
188261 self . norm_squared ( ) . simd_sqrt ( )
189262 }
190263
191- /// Compute the distance between `self` and `rhs` using the metric induced by the euclidean norm .
264+ /// Distance between `self` and `rhs` using the L2 norm for vectors, or the Frobenius for matrices .
192265 ///
193266 /// Use `.apply_metric_distance` to apply a custom norm.
194267 #[ inline]
@@ -306,7 +379,13 @@ impl<T: Scalar, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
306379 self . unscale ( self . norm ( ) )
307380 }
308381
309- /// The Lp norm of this matrix.
382+ /// Entrywise Lp norm of this matrix or vector.
383+ ///
384+ /// Computes (sum |a_ij|^p)^(1/p) over all elements.
385+ ///
386+ /// <div class="warning">
387+ /// For matrices, this does not match the standard mathematical definition of the matrix Lp norm.
388+ /// </div>
310389 #[ inline]
311390 #[ must_use]
312391 pub fn lp_norm ( & self , p : i32 ) -> T :: SimdRealField
@@ -316,6 +395,21 @@ impl<T: Scalar, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
316395 self . apply_norm ( & LpNorm ( p) )
317396 }
318397
398+ /// Induced matrix 1-norm (maximum absolute column sum).
399+ ///
400+ /// Computes max_j sum_i |a_ij|.
401+ ///
402+ /// For a column vector, this is the L1 norm.
403+ /// For a row vector, this is the L-infinity norm.
404+ #[ inline]
405+ #[ must_use]
406+ pub fn one_norm ( & self ) -> T :: SimdRealField
407+ where
408+ T : SimdComplexField ,
409+ {
410+ self . apply_norm ( & OneNorm )
411+ }
412+
319413 /// Attempts to normalize `self`.
320414 ///
321415 /// The components of this matrix can be SIMD types.
0 commit comments