argmin_math/primitives/
l1norm.rs

1// Copyright 2018-2024 argmin developers
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// http://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8use crate::ArgminL1Norm;
9use num_complex::Complex;
10
11macro_rules! make_l1norm_unsigned {
12    ($t:ty) => {
13        impl ArgminL1Norm<$t> for $t {
14            #[inline]
15            fn l1_norm(&self) -> $t {
16                *self
17            }
18        }
19    };
20}
21
22macro_rules! make_l1norm {
23    ($t:ty) => {
24        impl ArgminL1Norm<$t> for $t {
25            #[inline]
26            fn l1_norm(&self) -> $t {
27                self.abs()
28            }
29        }
30    };
31}
32
33macro_rules! make_l1norm_complex {
34    ($t:ty) => {
35        impl ArgminL1Norm<$t> for Complex<$t> {
36            #[inline]
37            fn l1_norm(&self) -> $t {
38                self.l1_norm()
39            }
40        }
41    };
42}
43
44macro_rules! make_l1norm_complex_unsigned {
45    ($t:ty) => {
46        impl ArgminL1Norm<$t> for Complex<$t> {
47            #[inline]
48            fn l1_norm(&self) -> $t {
49                self.re + self.im
50            }
51        }
52    };
53}
54
55make_l1norm!(i8);
56make_l1norm!(i16);
57make_l1norm!(i32);
58make_l1norm!(i64);
59make_l1norm_unsigned!(u8);
60make_l1norm_unsigned!(u16);
61make_l1norm_unsigned!(u32);
62make_l1norm_unsigned!(u64);
63make_l1norm!(f32);
64make_l1norm!(f64);
65make_l1norm_complex!(i8);
66make_l1norm_complex!(i16);
67make_l1norm_complex!(i32);
68make_l1norm_complex!(i64);
69make_l1norm_complex!(f32);
70make_l1norm_complex!(f64);
71make_l1norm_complex_unsigned!(u8);
72make_l1norm_complex_unsigned!(u16);
73make_l1norm_complex_unsigned!(u32);
74make_l1norm_complex_unsigned!(u64);
75
76#[cfg(test)]
77mod tests {
78    use super::*;
79    use approx::assert_relative_eq;
80    use paste::item;
81
82    macro_rules! make_test {
83        ($t:ty) => {
84            item! {
85                #[test]
86                fn [<test_norm_ $t>]() {
87                    let a = 8 as $t;
88                    let res = <$t as ArgminL1Norm<$t>>::l1_norm(&a);
89                    assert_relative_eq!(a as f64, res as f64, epsilon = f64::EPSILON);
90                }
91            }
92        };
93    }
94
95    macro_rules! make_test_signed {
96        ($t:ty) => {
97            item! {
98                #[test]
99                fn [<test_norm_signed_ $t>]() {
100                    let a = -8 as $t;
101                    let res = <$t as ArgminL1Norm<$t>>::l1_norm(&a);
102                    assert_relative_eq!(8 as f64, res as f64, epsilon = f64::EPSILON);
103                }
104            }
105        };
106    }
107
108    macro_rules! make_test_complex_signed {
109        ($t:ty) => {
110            item! {
111                #[test]
112                fn [<test_norm_complex_signed_ $t>]() {
113                    let a = Complex::new(-8 as $t, -4 as $t);
114                    let res = <Complex<$t> as ArgminL1Norm<$t>>::l1_norm(&a);
115                    assert_relative_eq!((8 as $t + 4 as $t) as f64, res as f64, epsilon = f64::EPSILON);
116                }
117            }
118        };
119    }
120
121    macro_rules! make_test_complex {
122        ($t:ty) => {
123            item! {
124                #[test]
125                fn [<test_norm_complex_ $t>]() {
126                    let a = Complex::new(8 as $t, 4 as $t);
127                    let res = <Complex<$t> as ArgminL1Norm<$t>>::l1_norm(&a);
128                    assert_relative_eq!((8 as $t + 4 as $t) as f64, res as f64, epsilon = f64::EPSILON);
129                }
130            }
131        };
132    }
133
134    make_test!(i8);
135    make_test!(u8);
136    make_test!(i16);
137    make_test!(u16);
138    make_test!(i32);
139    make_test!(u32);
140    make_test!(i64);
141    make_test!(u64);
142    make_test!(f32);
143    make_test!(f64);
144
145    make_test_signed!(i8);
146    make_test_signed!(i16);
147    make_test_signed!(i32);
148    make_test_signed!(i64);
149    make_test_signed!(f32);
150    make_test_signed!(f64);
151
152    make_test_complex_signed!(i8);
153    make_test_complex_signed!(i16);
154    make_test_complex_signed!(i32);
155    make_test_complex_signed!(i64);
156    make_test_complex_signed!(f32);
157    make_test_complex_signed!(f64);
158    make_test_complex!(u8);
159    make_test_complex!(u16);
160    make_test_complex!(u32);
161    make_test_complex!(u64);
162    make_test_complex!(i8);
163    make_test_complex!(i16);
164    make_test_complex!(i32);
165    make_test_complex!(i64);
166    make_test_complex!(f32);
167    make_test_complex!(f64);
168}