argmin_math/vec/
mul.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::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!(i8);
76make_mul!(u8);
77make_mul!(i16);
78make_mul!(u16);
79make_mul!(i32);
80make_mul!(u32);
81make_mul!(i64);
82make_mul!(u64);
83make_mul!(f32);
84make_mul!(f64);
85make_mul!(Complex<i8>);
86make_mul!(Complex<u8>);
87make_mul!(Complex<i16>);
88make_mul!(Complex<u16>);
89make_mul!(Complex<i32>);
90make_mul!(Complex<u32>);
91make_mul!(Complex<i64>);
92make_mul!(Complex<u64>);
93make_mul!(Complex<f32>);
94make_mul!(Complex<f64>);
95
96#[cfg(test)]
97mod tests {
98    use super::*;
99    use approx::assert_relative_eq;
100    use paste::item;
101
102    macro_rules! make_test {
103        ($t:ty) => {
104            item! {
105                #[test]
106                fn [<test_mul_vec_scalar_ $t>]() {
107                    let a = vec![1 as $t, 4 as $t, 8 as $t];
108                    let b = 2 as $t;
109                    let target = vec![2 as $t, 8 as $t, 16 as $t];
110                    let res = <Vec<$t> as ArgminMul<$t, Vec<$t>>>::mul(&a, &b);
111                    for i in 0..3 {
112                        assert_relative_eq!(target[i] as f64, res[i] as f64, epsilon = f64::EPSILON);
113                    }
114                }
115            }
116
117            item! {
118                #[test]
119                fn [<test_mul_vec_scalar_complex_ $t>]() {
120                    let a = vec![
121                        Complex::new(5 as $t, 3 as $t),
122                        Complex::new(8 as $t, 2 as $t)
123                    ];
124                    let b = Complex::new(2 as $t, 3 as $t);
125                    let target = vec![a[0] * b, a[1] * b];
126                    let res = <Vec<Complex<$t>> as ArgminMul<Complex<$t>, Vec<Complex<$t>>>>::mul(&a, &b);
127                    for i in 0..2 {
128                        assert_relative_eq!(target[i].re as f64, res[i].re as f64, epsilon = f64::EPSILON);
129                        assert_relative_eq!(target[i].im as f64, res[i].im as f64, epsilon = f64::EPSILON);
130                    }
131                }
132            }
133
134            item! {
135                #[test]
136                fn [<test_mul_scalar_vec_ $t>]() {
137                    let a = vec![1 as $t, 4 as $t, 8 as $t];
138                    let b = 2 as $t;
139                    let target = vec![2 as $t, 8 as $t, 16 as $t];
140                    let res = <$t as ArgminMul<Vec<$t>, Vec<$t>>>::mul(&b, &a);
141                    for i in 0..3 {
142                        assert_relative_eq!(target[i] as f64, res[i] as f64, epsilon = f64::EPSILON);
143                    }
144                }
145            }
146
147            item! {
148                #[test]
149                fn [<test_mul_scalar_vec_complex_ $t>]() {
150                    let a = vec![
151                        Complex::new(5 as $t, 3 as $t),
152                        Complex::new(8 as $t, 2 as $t)
153                    ];
154                    let b = Complex::new(2 as $t, 3 as $t);
155                    let target = vec![a[0] * b, a[1] * b];
156                    let res = <Complex<$t> as ArgminMul<Vec<Complex<$t>>, Vec<Complex<$t>>>>::mul(&b, &a);
157                    for i in 0..2 {
158                        assert_relative_eq!(target[i].re as f64, res[i].re as f64, epsilon = f64::EPSILON);
159                        assert_relative_eq!(target[i].im as f64, res[i].im as f64, epsilon = f64::EPSILON);
160                    }
161                }
162            }
163
164            item! {
165                #[test]
166                fn [<test_mul_vec_vec_ $t>]() {
167                    let a = vec![1 as $t, 4 as $t, 8 as $t];
168                    let b = vec![2 as $t, 3 as $t, 4 as $t];
169                    let target = vec![2 as $t, 12 as $t, 32 as $t];
170                    let res = <Vec<$t> as ArgminMul<Vec<$t>, Vec<$t>>>::mul(&a, &b);
171                    for i in 0..3 {
172                        assert_relative_eq!(target[i] as f64, res[i] as f64, epsilon = f64::EPSILON);
173                    }
174                }
175            }
176
177            item! {
178                #[test]
179                fn [<test_mul_vec_vec_complex_ $t>]() {
180                    let a = vec![
181                        Complex::new(5 as $t, 3 as $t),
182                        Complex::new(8 as $t, 2 as $t)
183                    ];
184                    let b = vec![
185                        Complex::new(2 as $t, 3 as $t),
186                        Complex::new(1 as $t, 2 as $t)
187                    ];
188                    let target = vec![a[0]*b[0], a[1]*b[1]];
189                    let res = <Vec<Complex<$t>> as ArgminMul<Vec<Complex<$t>>, Vec<Complex<$t>>>>::mul(&a, &b);
190                    for i in 0..2 {
191                        assert_relative_eq!(target[i].re as f64, res[i].re as f64, epsilon = f64::EPSILON);
192                        assert_relative_eq!(target[i].im as f64, res[i].im as f64, epsilon = f64::EPSILON);
193                    }
194                }
195            }
196
197            item! {
198                #[test]
199                #[should_panic]
200                fn [<test_mul_vec_vec_panic_ $t>]() {
201                    let a = vec![1 as $t, 4 as $t];
202                    let b = vec![41 as $t, 38 as $t, 34 as $t];
203                    <Vec<$t> as ArgminMul<Vec<$t>, Vec<$t>>>::mul(&a, &b);
204                }
205            }
206
207            item! {
208                #[test]
209                #[should_panic]
210                fn [<test_mul_vec_vec_panic_2_ $t>]() {
211                    let a = vec![];
212                    let b = vec![41 as $t, 38 as $t, 34 as $t];
213                    <Vec<$t> as ArgminMul<Vec<$t>, Vec<$t>>>::mul(&a, &b);
214                }
215            }
216
217            item! {
218                #[test]
219                #[should_panic]
220                fn [<test_mul_vec_vec_panic_3_ $t>]() {
221                    let a = vec![41 as $t, 38 as $t, 34 as $t];
222                    let b = vec![];
223                    <Vec<$t> as ArgminMul<Vec<$t>, Vec<$t>>>::mul(&a, &b);
224                }
225            }
226
227            item! {
228                #[test]
229                fn [<test_mul_mat_mat_ $t>]() {
230                    let a = vec![
231                        vec![1 as $t, 4 as $t, 8 as $t],
232                        vec![2 as $t, 5 as $t, 9 as $t]
233                    ];
234                    let b = vec![
235                        vec![2 as $t, 3 as $t, 4 as $t],
236                        vec![3 as $t, 4 as $t, 5 as $t]
237                    ];
238                    let target = vec![
239                        vec![2 as $t, 12 as $t, 32 as $t],
240                        vec![6 as $t, 20 as $t, 45 as $t]
241                    ];
242                    let res = <Vec<Vec<$t>> as ArgminMul<Vec<Vec<$t>>, Vec<Vec<$t>>>>::mul(&a, &b);
243                    for i in 0..3 {
244                        for j in 0..2 {
245                            assert_relative_eq!(target[j][i] as f64, res[j][i] as f64, epsilon = f64::EPSILON);
246                        }
247                    }
248                }
249            }
250
251            item! {
252                #[test]
253                fn [<test_mul_mat_mat_complex_ $t>]() {
254                    let a = vec![
255                        vec![Complex::new(5 as $t, 3 as $t), Complex::new(8 as $t, 2 as $t)],
256                        vec![Complex::new(4 as $t, 2 as $t), Complex::new(7 as $t, 1 as $t)],
257                        vec![Complex::new(3 as $t, 1 as $t), Complex::new(6 as $t, 2 as $t)],
258                    ];
259                    let b = vec![
260                        vec![Complex::new(5 as $t, 3 as $t), Complex::new(8 as $t, 2 as $t)],
261                        vec![Complex::new(4 as $t, 2 as $t), Complex::new(7 as $t, 1 as $t)],
262                        vec![Complex::new(3 as $t, 1 as $t), Complex::new(6 as $t, 2 as $t)],
263                    ];
264                    let target = vec![
265                        vec![a[0][0] * b[0][0], a[0][1] * b[0][1]],
266                        vec![a[1][0] * b[1][0], a[1][1] * b[1][1]],
267                        vec![a[2][0] * b[2][0], a[2][1] * b[2][1]],
268                    ];
269                    let res = <Vec<Vec<Complex<$t>>> as ArgminMul<Vec<Vec<Complex<$t>>>, Vec<Vec<Complex<$t>>>>>::mul(&a, &b);
270                    for i in 0..2 {
271                        for j in 0..3 {
272                            assert_relative_eq!(target[j][i].re as f64, res[j][i].re as f64, epsilon = f64::EPSILON);
273                            assert_relative_eq!(target[j][i].im as f64, res[j][i].im as f64, epsilon = f64::EPSILON);
274                        }
275                    }
276                }
277            }
278
279            item! {
280                #[test]
281                #[should_panic]
282                fn [<test_mul_mat_mat_panic_1_ $t>]() {
283                    let a = vec![
284                        vec![1 as $t, 4 as $t, 8 as $t],
285                        vec![2 as $t, 9 as $t]
286                    ];
287                    let b = vec![
288                        vec![41 as $t, 38 as $t, 34 as $t],
289                        vec![40 as $t, 37 as $t, 33 as $t]
290                    ];
291                    <Vec<Vec<$t>> as ArgminMul<Vec<Vec<$t>>, Vec<Vec<$t>>>>::mul(&a, &b);
292                }
293            }
294
295            item! {
296                #[test]
297                #[should_panic]
298                fn [<test_mul_mat_mat_panic_2_ $t>]() {
299                    let a = vec![
300                        vec![1 as $t, 4 as $t, 8 as $t],
301                        vec![2 as $t, 5 as $t, 9 as $t]
302                    ];
303                    let b = vec![
304                        vec![41 as $t, 38 as $t, 34 as $t],
305                    ];
306                    <Vec<Vec<$t>> as ArgminMul<Vec<Vec<$t>>, Vec<Vec<$t>>>>::mul(&a, &b);
307                }
308            }
309
310            item! {
311                #[test]
312                #[should_panic]
313                fn [<test_mul_mat_mat_panic_3_ $t>]() {
314                    let a = vec![
315                        vec![1 as $t, 4 as $t, 8 as $t],
316                        vec![2 as $t, 5 as $t, 9 as $t]
317                    ];
318                    let b = vec![];
319                    <Vec<Vec<$t>> as ArgminMul<Vec<Vec<$t>>, Vec<Vec<$t>>>>::mul(&a, &b);
320                }
321            }
322
323            item! {
324                #[test]
325                fn [<test_mul_scalar_mat_1_ $t>]() {
326                    let a = vec![
327                        vec![1 as $t, 4 as $t, 8 as $t],
328                        vec![2 as $t, 5 as $t, 9 as $t]
329                    ];
330                    let b = 2 as $t;
331                    let target = vec![
332                        vec![2 as $t, 8 as $t, 16 as $t],
333                        vec![4 as $t, 10 as $t, 18 as $t]
334                    ];
335                    let res = <Vec<Vec<$t>> as ArgminMul<$t, Vec<Vec<$t>>>>::mul(&a, &b);
336                    for i in 0..3 {
337                        for j in 0..2 {
338                            assert_relative_eq!(target[j][i] as f64, res[j][i] as f64, epsilon = f64::EPSILON);
339                        }
340                    }
341                }
342            }
343
344            item! {
345                #[test]
346                fn [<test_mul_scalar_mat_1_complex_ $t>]() {
347                    let a = vec![
348                        vec![Complex::new(5 as $t, 3 as $t), Complex::new(8 as $t, 2 as $t)],
349                        vec![Complex::new(4 as $t, 2 as $t), Complex::new(7 as $t, 1 as $t)],
350                        vec![Complex::new(3 as $t, 1 as $t), Complex::new(6 as $t, 2 as $t)],
351                    ];
352                    let b = Complex::new(3 as $t, 2 as $t);
353                    let target = vec![
354                        vec![a[0][0] * b, a[0][1] * b],
355                        vec![a[1][0] * b, a[1][1] * b],
356                        vec![a[2][0] * b, a[2][1] * b],
357                    ];
358                    let res = <Vec<Vec<Complex<$t>>> as ArgminMul<Complex<$t>, Vec<Vec<Complex<$t>>>>>::mul(&a, &b);
359                    for i in 0..2 {
360                        for j in 0..3 {
361                            assert_relative_eq!(target[j][i].re as f64, res[j][i].re as f64, epsilon = f64::EPSILON);
362                            assert_relative_eq!(target[j][i].im as f64, res[j][i].im as f64, epsilon = f64::EPSILON);
363                        }
364                    }
365                }
366            }
367
368            item! {
369                #[test]
370                fn [<test_mul_scalar_mat_2_ $t>]() {
371                    let b = vec![
372                        vec![1 as $t, 4 as $t, 8 as $t],
373                        vec![2 as $t, 5 as $t, 9 as $t]
374                    ];
375                    let a = 2 as $t;
376                    let target = vec![
377                        vec![2 as $t, 8 as $t, 16 as $t],
378                        vec![4 as $t, 10 as $t, 18 as $t]
379                    ];
380                    let res = <$t as ArgminMul<Vec<Vec<$t>>, Vec<Vec<$t>>>>::mul(&a, &b);
381                    for i in 0..3 {
382                        for j in 0..2 {
383                            assert_relative_eq!(target[j][i] as f64, res[j][i] as f64, epsilon = f64::EPSILON);
384                        }
385                    }
386                }
387            }
388
389            item! {
390                #[test]
391                fn [<test_mul_scalar_mat_2_complex_ $t>]() {
392                    let a = vec![
393                        vec![Complex::new(5 as $t, 3 as $t), Complex::new(8 as $t, 2 as $t)],
394                        vec![Complex::new(4 as $t, 2 as $t), Complex::new(7 as $t, 1 as $t)],
395                        vec![Complex::new(3 as $t, 1 as $t), Complex::new(6 as $t, 2 as $t)],
396                    ];
397                    let b = Complex::new(3 as $t, 2 as $t);
398                    let target = vec![
399                        vec![a[0][0] * b, a[0][1] * b],
400                        vec![a[1][0] * b, a[1][1] * b],
401                        vec![a[2][0] * b, a[2][1] * b],
402                    ];
403                    let res = <Complex<$t> as ArgminMul<Vec<Vec<Complex<$t>>>, Vec<Vec<Complex<$t>>>>>::mul(&b, &a);
404                    for i in 0..2 {
405                        for j in 0..3 {
406                            assert_relative_eq!(target[j][i].re as f64, res[j][i].re as f64, epsilon = f64::EPSILON);
407                            assert_relative_eq!(target[j][i].im as f64, res[j][i].im as f64, epsilon = f64::EPSILON);
408                        }
409                    }
410                }
411            }
412        };
413    }
414
415    make_test!(i8);
416    make_test!(u8);
417    make_test!(i16);
418    make_test!(u16);
419    make_test!(i32);
420    make_test!(u32);
421    make_test!(i64);
422    make_test!(u64);
423    make_test!(f32);
424    make_test!(f64);
425}