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