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