argmin_math/vec/
add.rs

1// Copyright 2018-2024 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::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!(i8);
76make_add!(i16);
77make_add!(i32);
78make_add!(i64);
79make_add!(u8);
80make_add!(u16);
81make_add!(u32);
82make_add!(u64);
83make_add!(f32);
84make_add!(f64);
85
86#[cfg(test)]
87mod tests {
88    use super::*;
89    use approx::assert_relative_eq;
90    use paste::item;
91
92    macro_rules! make_test {
93        ($t:ty) => {
94            item! {
95                #[test]
96                fn [<test_add_vec_scalar_ $t>]() {
97                    let a = vec![1 as $t, 4 as $t, 8 as $t];
98                    let b = 34 as $t;
99                    let target = vec![35 as $t, 38 as $t, 42 as $t];
100                    let res = <Vec<$t> as ArgminAdd<$t, Vec<$t>>>::add(&a, &b);
101                    for i in 0..3 {
102                        assert_relative_eq!(target[i] as f64, res[i] as f64, epsilon = f64::EPSILON)
103                    }
104                }
105            }
106
107            item! {
108                #[test]
109                fn [<test_add_scalar_vec_ $t>]() {
110                    let a = vec![1 as $t, 4 as $t, 8 as $t];
111                    let b = 34 as $t;
112                    let target = vec![35 as $t, 38 as $t, 42 as $t];
113                    let res = <$t as ArgminAdd<Vec<$t>, Vec<$t>>>::add(&b, &a);
114                    for i in 0..3 {
115                        assert_relative_eq!(target[i] as f64, res[i] as f64, epsilon = f64::EPSILON)
116                    }
117                }
118            }
119
120            item! {
121                #[test]
122                fn [<test_add_vec_vec_ $t>]() {
123                    let a = vec![1 as $t, 4 as $t, 8 as $t];
124                    let b = vec![41 as $t, 38 as $t, 34 as $t];
125                    let target = vec![42 as $t, 42 as $t, 42 as $t];
126                    let res = <Vec<$t> as ArgminAdd<Vec<$t>, Vec<$t>>>::add(&a, &b);
127                    for i in 0..3 {
128                        assert_relative_eq!(target[i] as f64, res[i] as f64, epsilon = f64::EPSILON);
129                    }
130                }
131            }
132
133            item! {
134                #[test]
135                #[should_panic]
136                fn [<test_add_vec_vec_panic_ $t>]() {
137                    let a = vec![1 as $t, 4 as $t];
138                    let b = vec![41 as $t, 38 as $t, 34 as $t];
139                    <Vec<$t> as ArgminAdd<Vec<$t>, Vec<$t>>>::add(&a, &b);
140                }
141            }
142
143            item! {
144                #[test]
145                #[should_panic]
146                fn [<test_add_vec_vec_panic_2_ $t>]() {
147                    let a = vec![];
148                    let b = vec![41 as $t, 38 as $t, 34 as $t];
149                    <Vec<$t> as ArgminAdd<Vec<$t>, Vec<$t>>>::add(&a, &b);
150                }
151            }
152
153            item! {
154                #[test]
155                #[should_panic]
156                fn [<test_add_vec_vec_panic_3_ $t>]() {
157                    let a = vec![41 as $t, 38 as $t, 34 as $t];
158                    let b = vec![];
159                    <Vec<$t> as ArgminAdd<Vec<$t>, Vec<$t>>>::add(&a, &b);
160                }
161            }
162
163            item! {
164                #[test]
165                fn [<test_add_mat_mat_ $t>]() {
166                    let a = vec![
167                        vec![1 as $t, 4 as $t, 8 as $t],
168                        vec![2 as $t, 5 as $t, 9 as $t]
169                    ];
170                    let b = vec![
171                        vec![41 as $t, 38 as $t, 34 as $t],
172                        vec![40 as $t, 37 as $t, 33 as $t]
173                    ];
174                    let target = vec![
175                        vec![42 as $t, 42 as $t, 42 as $t],
176                        vec![42 as $t, 42 as $t, 42 as $t]
177                    ];
178                    let res = <Vec<Vec<$t>> as ArgminAdd<Vec<Vec<$t>>, Vec<Vec<$t>>>>::add(&a, &b);
179                    for i in 0..3 {
180                        for j in 0..2 {
181                            assert_relative_eq!(target[j][i] as f64, res[j][i] as f64, epsilon = f64::EPSILON);
182                        }
183                    }
184                }
185            }
186
187            item! {
188                #[test]
189                fn [<test_add_mat_scalar_ $t>]() {
190                    let a = vec![
191                        vec![1 as $t, 4 as $t, 8 as $t],
192                        vec![2 as $t, 5 as $t, 9 as $t]
193                    ];
194                    let b = 2 as $t;
195                    let target = vec![
196                        vec![3 as $t, 6 as $t, 10 as $t],
197                        vec![4 as $t, 7 as $t, 11 as $t]
198                    ];
199                    let res = <Vec<Vec<$t>> as ArgminAdd<$t, Vec<Vec<$t>>>>::add(&a, &b);
200                    for i in 0..3 {
201                        for j in 0..2 {
202                            assert_relative_eq!(target[j][i] as f64, res[j][i] as f64, epsilon = f64::EPSILON);
203                        }
204                    }
205                }
206            }
207
208            item! {
209                #[test]
210                #[should_panic]
211                fn [<test_add_mat_mat_panic_1_ $t>]() {
212                    let a = vec![
213                        vec![1 as $t, 4 as $t, 8 as $t],
214                        vec![2 as $t, 9 as $t]
215                    ];
216                    let b = vec![
217                        vec![41 as $t, 38 as $t, 34 as $t],
218                        vec![40 as $t, 37 as $t, 33 as $t]
219                    ];
220                    <Vec<Vec<$t>> as ArgminAdd<Vec<Vec<$t>>, Vec<Vec<$t>>>>::add(&a, &b);
221                }
222            }
223
224            item! {
225                #[test]
226                #[should_panic]
227                fn [<test_add_mat_mat_panic_2_ $t>]() {
228                    let a = vec![
229                        vec![1 as $t, 4 as $t, 8 as $t],
230                        vec![2 as $t, 5 as $t, 9 as $t]
231                    ];
232                    let b = vec![
233                        vec![41 as $t, 38 as $t, 34 as $t],
234                    ];
235                    <Vec<Vec<$t>> as ArgminAdd<Vec<Vec<$t>>, Vec<Vec<$t>>>>::add(&a, &b);
236                }
237            }
238
239            item! {
240                #[test]
241                #[should_panic]
242                fn [<test_add_mat_mat_panic_3_ $t>]() {
243                    let a = vec![
244                        vec![1 as $t, 4 as $t, 8 as $t],
245                        vec![2 as $t, 5 as $t, 9 as $t]
246                    ];
247                    let b = vec![];
248                    <Vec<Vec<$t>> as ArgminAdd<Vec<Vec<$t>>, Vec<Vec<$t>>>>::add(&a, &b);
249                }
250            }
251        };
252    }
253
254    make_test!(i8);
255    make_test!(u8);
256    make_test!(i16);
257    make_test!(u16);
258    make_test!(i32);
259    make_test!(u32);
260    make_test!(i64);
261    make_test!(u64);
262    make_test!(f32);
263    make_test!(f64);
264}