1use 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 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}