concision_core/traits/
norm.rs1pub trait L1Norm {
7 type Output;
8
9 fn l1_norm(&self) -> Self::Output;
10}
11pub trait L2Norm {
13 type Output;
14
15 fn l2_norm(&self) -> Self::Output;
16}
17
18pub trait Norm {
19 type Output;
20 fn l1_norm(&self) -> Self::Output;
22 fn l2_norm(&self) -> Self::Output;
24}
25
26use ndarray::{ArrayBase, Data, Dimension, ScalarOperand};
30use num_traits::Float;
31
32impl<U, V> Norm for U
33where
34 U: L1Norm<Output = V> + L2Norm<Output = V>,
35{
36 type Output = V;
37
38 fn l1_norm(&self) -> Self::Output {
39 <Self as L1Norm>::l1_norm(self)
40 }
41
42 fn l2_norm(&self) -> Self::Output {
43 <Self as L2Norm>::l2_norm(self)
44 }
45}
46
47macro_rules! impl_norm {
48 ($trait:ident::$method:ident($($param:ident: $type:ty),*) => $self:ident$(.$call:ident())*) => {
49 impl<A, S, D> $trait for ArrayBase<S, D>
50 where
51 A: Float + ScalarOperand,
52 D: Dimension,
53 S: Data<Elem = A>,
54 {
55 type Output = A;
56
57 fn $method(&self, $($param: $type),*) -> Self::Output {
58 self$(.$call())*
59 }
60 }
61
62 impl<'a, A, S, D> $trait for &'a ArrayBase<S, D>
63 where
64 A: Float + ScalarOperand,
65 D: Dimension,
66 S: Data<Elem = A>,
67 {
68 type Output = A;
69
70 fn $method(&self, $($param: $type),*) -> Self::Output {
71 self$(.$call())*
72 }
73 }
74
75 impl<'a, A, S, D> $trait for &'a mut ArrayBase<S, D>
76 where
77 A: Float + ScalarOperand,
78 D: Dimension,
79 S: Data<Elem = A>,
80 {
81 type Output = A;
82
83 fn $method(&self, $($param: $type),*) -> Self::Output {
84 self$(.$call())*
85 }
86 }
87 };
88}
89
90impl_norm! { L2Norm::l2_norm() => self.pow2().sum().sqrt() }
91
92impl_norm! { L1Norm::l1_norm() => self.abs().sum() }