argmin/core/math/
norm_vec.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::integer::Roots;
10use num_complex::Complex;
11
12macro_rules! make_norm_float {
13    ($t:ty) => {
14        impl ArgminNorm<$t> for Vec<$t> {
15            #[inline]
16            fn norm(&self) -> $t {
17                self.iter().map(|a| a.powi(2)).sum::<$t>().sqrt()
18            }
19        }
20    };
21}
22
23macro_rules! make_norm_complex_float {
24    ($t:ty) => {
25        impl ArgminNorm<Complex<$t>> for Vec<Complex<$t>> {
26            #[inline]
27            fn norm(&self) -> Complex<$t> {
28                self.iter().map(|a| a.powf(2.0)).sum::<Complex<$t>>().sqrt()
29            }
30        }
31    };
32}
33
34macro_rules! make_norm_integer {
35    ($t:ty) => {
36        impl ArgminNorm<$t> for Vec<$t> {
37            #[inline]
38            fn norm(&self) -> $t {
39                self.iter().map(|a| a.pow(2)).sum::<$t>().sqrt()
40            }
41        }
42    };
43}
44
45make_norm_integer!(isize);
46make_norm_integer!(usize);
47make_norm_integer!(i8);
48make_norm_integer!(i16);
49make_norm_integer!(i32);
50make_norm_integer!(i64);
51make_norm_integer!(u8);
52make_norm_integer!(u16);
53make_norm_integer!(u32);
54make_norm_integer!(u64);
55make_norm_float!(f32);
56make_norm_float!(f64);
57make_norm_complex_float!(f32);
58make_norm_complex_float!(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 = vec![4 as $t, 3 as $t];
71                    let res = <Vec<$t> as ArgminNorm<$t>>::norm(&a);
72                    let target = 5 as $t;
73                    assert!(((target - res) as f64).abs() < std::f64::EPSILON);
74                }
75            }
76        };
77    }
78
79    macro_rules! make_test_signed {
80        ($t:ty) => {
81            item! {
82                #[test]
83                fn [<test_norm_signed_ $t>]() {
84                    let a = vec![-4 as $t, -3 as $t];
85                    let res = <Vec<$t> as ArgminNorm<$t>>::norm(&a);
86                    let target = 5 as $t;
87                    assert!(((target - res) as f64).abs() < std::f64::EPSILON);
88                }
89            }
90        };
91    }
92
93    make_test!(isize);
94    make_test!(usize);
95    make_test!(i8);
96    make_test!(u8);
97    make_test!(i16);
98    make_test!(u16);
99    make_test!(i32);
100    make_test!(u32);
101    make_test!(i64);
102    make_test!(u64);
103    make_test!(f32);
104    make_test!(f64);
105
106    make_test_signed!(isize);
107    make_test_signed!(i8);
108    make_test_signed!(i16);
109    make_test_signed!(i32);
110    make_test_signed!(i64);
111    make_test_signed!(f32);
112    make_test_signed!(f64);
113}