argmin/core/math/
norm.rs

1// Copyright 2018-2020 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::core::math::ArgminNorm;
9use num_complex::Complex;
10
11macro_rules! make_norm_unsigned {
12    ($t:ty) => {
13        impl ArgminNorm<$t> for $t {
14            #[inline]
15            fn norm(&self) -> $t {
16                *self
17            }
18        }
19    };
20}
21
22macro_rules! make_norm {
23    ($t:ty) => {
24        impl ArgminNorm<$t> for $t {
25            #[inline]
26            fn norm(&self) -> $t {
27                (*self).abs()
28            }
29        }
30    };
31}
32
33macro_rules! make_norm_complex {
34    ($t:ty) => {
35        impl ArgminNorm<$t> for Complex<$t> {
36            #[inline]
37            fn norm(&self) -> $t {
38                (*self).re.hypot((*self).im)
39            }
40        }
41    };
42}
43
44make_norm!(isize);
45make_norm_unsigned!(usize);
46make_norm!(i8);
47make_norm!(i16);
48make_norm!(i32);
49make_norm!(i64);
50make_norm_unsigned!(u8);
51make_norm_unsigned!(u16);
52make_norm_unsigned!(u32);
53make_norm_unsigned!(u64);
54make_norm!(f32);
55make_norm!(f64);
56
57make_norm_complex!(f32);
58make_norm_complex!(f64);
59
60#[cfg(test)]
61mod tests {
62    use super::*;
63    use paste::item;
64
65    macro_rules! make_test {
66        ($t:ty) => {
67            item! {
68                #[test]
69                fn [<test_norm_ $t>]() {
70                    let a = 8 as $t;
71                    let res = <$t as ArgminNorm<$t>>::norm(&a);
72                    assert!(((a - res) as f64).abs() < std::f64::EPSILON);
73                }
74            }
75        };
76    }
77
78    macro_rules! make_test_signed {
79        ($t:ty) => {
80            item! {
81                #[test]
82                fn [<test_norm_signed_ $t>]() {
83                    let a = -8 as $t;
84                    let res = <$t as ArgminNorm<$t>>::norm(&a);
85                    assert!(((8 as $t - res) as f64).abs() < std::f64::EPSILON);
86                }
87            }
88        };
89    }
90
91    make_test!(isize);
92    make_test!(usize);
93    make_test!(i8);
94    make_test!(u8);
95    make_test!(i16);
96    make_test!(u16);
97    make_test!(i32);
98    make_test!(u32);
99    make_test!(i64);
100    make_test!(u64);
101    make_test!(f32);
102    make_test!(f64);
103
104    make_test_signed!(isize);
105    make_test_signed!(i8);
106    make_test_signed!(i16);
107    make_test_signed!(i32);
108    make_test_signed!(i64);
109    make_test_signed!(f32);
110    make_test_signed!(f64);
111}