argmin/core/math/
div_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::ArgminDiv;
9use num_complex::Complex;
10
11macro_rules! make_div {
12    ($t:ty) => {
13        impl ArgminDiv<$t, Vec<$t>> for Vec<$t> {
14            #[inline]
15            fn div(&self, other: &$t) -> Vec<$t> {
16                self.iter().map(|a| a / other).collect()
17            }
18        }
19
20        impl ArgminDiv<Vec<$t>, Vec<$t>> for $t {
21            #[inline]
22            fn div(&self, other: &Vec<$t>) -> Vec<$t> {
23                other.iter().map(|a| self / a).collect()
24            }
25        }
26
27        impl ArgminDiv<Vec<$t>, Vec<$t>> for Vec<$t> {
28            #[inline]
29            fn div(&self, other: &Vec<$t>) -> Vec<$t> {
30                let n1 = self.len();
31                let n2 = other.len();
32                assert!(n1 > 0);
33                assert!(n2 > 0);
34                assert_eq!(n1, n2);
35                self.iter().zip(other.iter()).map(|(a, b)| a / b).collect()
36            }
37        }
38
39        impl ArgminDiv<Vec<Vec<$t>>, Vec<Vec<$t>>> for Vec<Vec<$t>> {
40            #[inline]
41            fn div(&self, other: &Vec<Vec<$t>>) -> Vec<Vec<$t>> {
42                let sr = self.len();
43                let or = other.len();
44                assert!(sr > 0);
45                // implicitly, or > 0
46                assert_eq!(sr, or);
47                let sc = self[0].len();
48                self.iter()
49                    .zip(other.iter())
50                    .map(|(a, b)| {
51                        assert_eq!(a.len(), sc);
52                        assert_eq!(b.len(), sc);
53                        <Vec<$t> as ArgminDiv<Vec<$t>, Vec<$t>>>::div(&a, &b)
54                    })
55                    .collect()
56            }
57        }
58    };
59}
60
61make_div!(isize);
62make_div!(usize);
63make_div!(i8);
64make_div!(u8);
65make_div!(i16);
66make_div!(u16);
67make_div!(i32);
68make_div!(u32);
69make_div!(i64);
70make_div!(u64);
71make_div!(f32);
72make_div!(f64);
73make_div!(Complex<isize>);
74make_div!(Complex<usize>);
75make_div!(Complex<i8>);
76make_div!(Complex<u8>);
77make_div!(Complex<i16>);
78make_div!(Complex<u16>);
79make_div!(Complex<i32>);
80make_div!(Complex<u32>);
81make_div!(Complex<i64>);
82make_div!(Complex<u64>);
83make_div!(Complex<f32>);
84make_div!(Complex<f64>);
85
86#[cfg(test)]
87mod tests {
88    use super::*;
89    use paste::item;
90
91    macro_rules! make_test {
92        ($t:ty) => {
93            item! {
94                #[test]
95                fn [<test_div_vec_scalar_ $t>]() {
96                    let a = vec![2 as $t, 4 as $t, 8 as $t];
97                    let b = 2 as $t;
98                    let target = vec![1 as $t, 2 as $t, 4 as $t];
99                    let res = <Vec<$t> as ArgminDiv<$t, Vec<$t>>>::div(&a, &b);
100                    for i in 0..3 {
101                        assert!(((target[i] - res[i]) as f64).abs() < std::f64::EPSILON);
102                    }
103                }
104            }
105
106            item! {
107                #[test]
108                fn [<test_div_scalar_vec_ $t>]() {
109                    let a = vec![2 as $t, 4 as $t, 8 as $t];
110                    let b = 64 as $t;
111                    let target = vec![32 as $t, 16 as $t, 8 as $t];
112                    let res = <$t as ArgminDiv<Vec<$t>, Vec<$t>>>::div(&b, &a);
113                    for i in 0..3 {
114                        assert!(((target[i] - res[i]) as f64).abs() < std::f64::EPSILON);
115                    }
116                }
117            }
118
119            item! {
120                #[test]
121                fn [<test_div_vec_vec_ $t>]() {
122                    let a = vec![4 as $t, 9 as $t, 8 as $t];
123                    let b = vec![2 as $t, 3 as $t, 4 as $t];
124                    let target = vec![2 as $t, 3 as $t, 2 as $t];
125                    let res = <Vec<$t> as ArgminDiv<Vec<$t>, Vec<$t>>>::div(&a, &b);
126                    for i in 0..3 {
127                        assert!(((target[i] - res[i]) as f64).abs() < std::f64::EPSILON);
128                    }
129                }
130            }
131
132            item! {
133                #[test]
134                #[should_panic]
135                fn [<test_div_vec_vec_panic_ $t>]() {
136                    let a = vec![1 as $t, 4 as $t];
137                    let b = vec![41 as $t, 38 as $t, 34 as $t];
138                    <Vec<$t> as ArgminDiv<Vec<$t>, Vec<$t>>>::div(&a, &b);
139                }
140            }
141
142            item! {
143                #[test]
144                #[should_panic]
145                fn [<test_div_vec_vec_panic_2_ $t>]() {
146                    let a = vec![];
147                    let b = vec![41 as $t, 38 as $t, 34 as $t];
148                    <Vec<$t> as ArgminDiv<Vec<$t>, Vec<$t>>>::div(&a, &b);
149                }
150            }
151
152            item! {
153                #[test]
154                #[should_panic]
155                fn [<test_div_vec_vec_panic_3_ $t>]() {
156                    let a = vec![41 as $t, 38 as $t, 34 as $t];
157                    let b = vec![];
158                    <Vec<$t> as ArgminDiv<Vec<$t>, Vec<$t>>>::div(&a, &b);
159                }
160            }
161
162            item! {
163                #[test]
164                fn [<test_div_mat_mat_ $t>]() {
165                    let a = vec![
166                        vec![4 as $t, 12 as $t, 8 as $t],
167                        vec![9 as $t, 20 as $t, 45 as $t]
168                    ];
169                    let b = vec![
170                        vec![2 as $t, 3 as $t, 4 as $t],
171                        vec![3 as $t, 4 as $t, 5 as $t]
172                    ];
173                    let target = vec![
174                        vec![2 as $t, 4 as $t, 2 as $t],
175                        vec![3 as $t, 5 as $t, 9 as $t]
176                    ];
177                    let res = <Vec<Vec<$t>> as ArgminDiv<Vec<Vec<$t>>, Vec<Vec<$t>>>>::div(&a, &b);
178                    for i in 0..3 {
179                        for j in 0..2 {
180                        assert!(((target[j][i] - res[j][i]) as f64).abs() < std::f64::EPSILON);
181                        }
182                    }
183                }
184            }
185
186            item! {
187                #[test]
188                #[should_panic]
189                fn [<test_div_mat_mat_panic_1_ $t>]() {
190                    let a = vec![
191                        vec![1 as $t, 4 as $t, 8 as $t],
192                        vec![2 as $t, 9 as $t]
193                    ];
194                    let b = vec![
195                        vec![41 as $t, 38 as $t, 34 as $t],
196                        vec![40 as $t, 37 as $t, 33 as $t]
197                    ];
198                    <Vec<Vec<$t>> as ArgminDiv<Vec<Vec<$t>>, Vec<Vec<$t>>>>::div(&a, &b);
199                }
200            }
201
202            item! {
203                #[test]
204                #[should_panic]
205                fn [<test_div_mat_mat_panic_2_ $t>]() {
206                    let a = vec![
207                        vec![1 as $t, 4 as $t, 8 as $t],
208                        vec![2 as $t, 5 as $t, 9 as $t]
209                    ];
210                    let b = vec![
211                        vec![41 as $t, 38 as $t, 34 as $t],
212                    ];
213                    <Vec<Vec<$t>> as ArgminDiv<Vec<Vec<$t>>, Vec<Vec<$t>>>>::div(&a, &b);
214                }
215            }
216
217            item! {
218                #[test]
219                #[should_panic]
220                fn [<test_div_mat_mat_panic_3_ $t>]() {
221                    let a = vec![
222                        vec![1 as $t, 4 as $t, 8 as $t],
223                        vec![2 as $t, 5 as $t, 9 as $t]
224                    ];
225                    let b = vec![];
226                    <Vec<Vec<$t>> as ArgminDiv<Vec<Vec<$t>>, Vec<Vec<$t>>>>::div(&a, &b);
227                }
228            }
229        };
230    }
231
232    make_test!(isize);
233    make_test!(usize);
234    make_test!(i8);
235    make_test!(u8);
236    make_test!(i16);
237    make_test!(u16);
238    make_test!(i32);
239    make_test!(u32);
240    make_test!(i64);
241    make_test!(u64);
242    make_test!(f32);
243    make_test!(f64);
244}