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