argmin_math/vec/
div.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::ArgminDiv;
9use num_complex::Complex;
10
11macro_rules! make_div {
12    ($t:ty) => {
13        impl ArgminDiv<$t, Vec<$t>> for Vec<$t> {
14            #[inline]
15            fn div(&self, other: &$t) -> Vec<$t> {
16                self.iter().map(|a| a / other).collect()
17            }
18        }
19
20        impl ArgminDiv<Vec<$t>, Vec<$t>> for $t {
21            #[inline]
22            fn div(&self, other: &Vec<$t>) -> Vec<$t> {
23                other.iter().map(|a| self / a).collect()
24            }
25        }
26
27        impl ArgminDiv<Vec<$t>, Vec<$t>> for Vec<$t> {
28            #[inline]
29            fn div(&self, other: &Vec<$t>) -> Vec<$t> {
30                let n1 = self.len();
31                let n2 = other.len();
32                assert!(n1 > 0);
33                assert_eq!(n1, n2);
34                self.iter().zip(other.iter()).map(|(a, b)| a / b).collect()
35            }
36        }
37
38        impl ArgminDiv<Vec<Vec<$t>>, Vec<Vec<$t>>> for Vec<Vec<$t>> {
39            #[inline]
40            fn div(&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 ArgminDiv<Vec<$t>, Vec<$t>>>::div(&a, &b)
53                    })
54                    .collect()
55            }
56        }
57    };
58}
59
60make_div!(i8);
61make_div!(u8);
62make_div!(i16);
63make_div!(u16);
64make_div!(i32);
65make_div!(u32);
66make_div!(i64);
67make_div!(u64);
68make_div!(f32);
69make_div!(f64);
70make_div!(Complex<i8>);
71make_div!(Complex<u8>);
72make_div!(Complex<i16>);
73make_div!(Complex<u16>);
74make_div!(Complex<i32>);
75make_div!(Complex<u32>);
76make_div!(Complex<i64>);
77make_div!(Complex<u64>);
78make_div!(Complex<f32>);
79make_div!(Complex<f64>);
80
81#[cfg(test)]
82mod tests {
83    use super::*;
84    use approx::assert_relative_eq;
85    use paste::item;
86
87    macro_rules! make_test {
88        ($t:ty) => {
89            item! {
90                #[test]
91                fn [<test_div_vec_scalar_ $t>]() {
92                    let a = vec![2 as $t, 4 as $t, 8 as $t];
93                    let b = 2 as $t;
94                    let target = vec![1 as $t, 2 as $t, 4 as $t];
95                    let res = <Vec<$t> as ArgminDiv<$t, Vec<$t>>>::div(&a, &b);
96                    for i in 0..3 {
97                        assert_relative_eq!(target[i] as f64, res[i] as f64, epsilon = f64::EPSILON);
98                    }
99                }
100            }
101
102            item! {
103                #[test]
104                fn [<test_div_vec_scalar_complex_ $t>]() {
105                    let a = vec![
106                        Complex::new(2 as $t, 4 as $t),
107                        Complex::new(4 as $t, 8 as $t),
108                        Complex::new(3 as $t, 9 as $t),
109                    ];
110                    let b = Complex::new(2 as $t, 4 as $t);
111                    let target = vec![a[0]/b, a[1]/b, a[2]/b];
112                    let res = <Vec<Complex<$t>> as ArgminDiv<Complex<$t>, Vec<Complex<$t>>>>::div(&a, &b);
113                    for i in 0..3 {
114                        assert_relative_eq!(target[i].re as f64, res[i].re as f64, epsilon = f64::EPSILON);
115                        assert_relative_eq!(target[i].im as f64, res[i].im as f64, epsilon = f64::EPSILON);
116                    }
117                }
118            }
119
120            item! {
121                #[test]
122                fn [<test_div_scalar_vec_ $t>]() {
123                    let a = vec![2 as $t, 4 as $t, 8 as $t];
124                    let b = 64 as $t;
125                    let target = vec![32 as $t, 16 as $t, 8 as $t];
126                    let res = <$t as ArgminDiv<Vec<$t>, Vec<$t>>>::div(&b, &a);
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                fn [<test_div_scalar_vec_complex_ $t>]() {
136                    let a = vec![
137                        Complex::new(2 as $t, 1 as $t),
138                        Complex::new(2 as $t, 2 as $t),
139                        Complex::new(3 as $t, 2 as $t),
140                    ];
141                    let b = Complex::new(10 as $t, 12 as $t);
142                    let target = vec![b/a[0], b/a[1], b/a[2]];
143                    let res = <Complex<$t> as ArgminDiv<Vec<Complex<$t>>, Vec<Complex<$t>>>>::div(&b, &a);
144                    for i in 0..3 {
145                        assert_relative_eq!(target[i].re as f64, res[i].re as f64, epsilon = f64::EPSILON);
146                        assert_relative_eq!(target[i].im as f64, res[i].im as f64, epsilon = f64::EPSILON);
147                    }
148                }
149            }
150
151            item! {
152                #[test]
153                fn [<test_div_vec_vec_ $t>]() {
154                    let a = vec![4 as $t, 9 as $t, 8 as $t];
155                    let b = vec![2 as $t, 3 as $t, 4 as $t];
156                    let target = vec![2 as $t, 3 as $t, 2 as $t];
157                    let res = <Vec<$t> as ArgminDiv<Vec<$t>, Vec<$t>>>::div(&a, &b);
158                    for i in 0..3 {
159                        assert_relative_eq!(target[i] as f64, res[i] as f64, epsilon = f64::EPSILON);
160                    }
161                }
162            }
163
164            item! {
165                #[test]
166                fn [<test_div_vec_vec_complex_ $t>]() {
167                    let a = vec![
168                        Complex::new(8 as $t, 7 as $t),
169                        Complex::new(7 as $t, 6 as $t),
170                        Complex::new(6 as $t, 5 as $t),
171                    ];
172                    let b = vec![
173                        Complex::new(4 as $t, 2 as $t),
174                        Complex::new(4 as $t, 3 as $t),
175                        Complex::new(3 as $t, 2 as $t),
176                    ];
177                    let target = vec![a[0]/b[0], a[1]/b[1], a[2]/b[2]];
178                    let res = <Vec<Complex<$t>> as ArgminDiv<Vec<Complex<$t>>, Vec<Complex<$t>>>>::div(&a, &b);
179                    for i in 0..3 {
180                        assert_relative_eq!(target[i].re as f64, res[i].re as f64, epsilon = f64::EPSILON);
181                        assert_relative_eq!(target[i].im as f64, res[i].im as f64, epsilon = f64::EPSILON);
182                    }
183                }
184            }
185
186            item! {
187                #[test]
188                #[should_panic]
189                fn [<test_div_vec_vec_panic_ $t>]() {
190                    let a = vec![1 as $t, 4 as $t];
191                    let b = vec![41 as $t, 38 as $t, 34 as $t];
192                    <Vec<$t> as ArgminDiv<Vec<$t>, Vec<$t>>>::div(&a, &b);
193                }
194            }
195
196            item! {
197                #[test]
198                #[should_panic]
199                fn [<test_div_vec_vec_panic_2_ $t>]() {
200                    let a = vec![];
201                    let b = vec![41 as $t, 38 as $t, 34 as $t];
202                    <Vec<$t> as ArgminDiv<Vec<$t>, Vec<$t>>>::div(&a, &b);
203                }
204            }
205
206            item! {
207                #[test]
208                #[should_panic]
209                fn [<test_div_vec_vec_panic_3_ $t>]() {
210                    let a = vec![41 as $t, 38 as $t, 34 as $t];
211                    let b = vec![];
212                    <Vec<$t> as ArgminDiv<Vec<$t>, Vec<$t>>>::div(&a, &b);
213                }
214            }
215
216            item! {
217                #[test]
218                fn [<test_div_mat_mat_ $t>]() {
219                    let a = vec![
220                        vec![4 as $t, 12 as $t, 8 as $t],
221                        vec![9 as $t, 20 as $t, 45 as $t]
222                    ];
223                    let b = vec![
224                        vec![2 as $t, 3 as $t, 4 as $t],
225                        vec![3 as $t, 4 as $t, 5 as $t]
226                    ];
227                    let target = vec![
228                        vec![2 as $t, 4 as $t, 2 as $t],
229                        vec![3 as $t, 5 as $t, 9 as $t]
230                    ];
231                    let res = <Vec<Vec<$t>> as ArgminDiv<Vec<Vec<$t>>, Vec<Vec<$t>>>>::div(&a, &b);
232                    for i in 0..3 {
233                        for j in 0..2 {
234                            assert_relative_eq!(target[j][i] as f64, res[j][i] as f64, epsilon = f64::EPSILON);
235                        }
236                    }
237                }
238            }
239
240            item! {
241                #[test]
242                fn [<test_div_mat_mat_complex_ $t>]() {
243                    let a = vec![
244                        vec![
245                            Complex::new(8 as $t, 7 as $t),
246                            Complex::new(7 as $t, 6 as $t),
247                            Complex::new(6 as $t, 5 as $t)
248                        ],
249                        vec![
250                            Complex::new(9 as $t, 6 as $t),
251                            Complex::new(7 as $t, 6 as $t),
252                            Complex::new(6 as $t, 4 as $t)
253                        ],
254                    ];
255                    let b = vec![
256                        vec![
257                            Complex::new(4 as $t, 2 as $t),
258                            Complex::new(4 as $t, 3 as $t),
259                            Complex::new(3 as $t, 2 as $t),
260                        ],
261                        vec![
262                            Complex::new(3 as $t, 2 as $t),
263                            Complex::new(4 as $t, 3 as $t),
264                            Complex::new(3 as $t, 1 as $t),
265                        ],
266                    ];
267                    let target = vec![
268                        vec![a[0][0]/b[0][0], a[0][1]/b[0][1], a[0][2]/b[0][2]],
269                        vec![a[1][0]/b[1][0], a[1][1]/b[1][1], a[1][2]/b[1][2]]
270                    ];
271                    let res = <Vec<Vec<Complex<$t>>> as ArgminDiv<Vec<Vec<Complex<$t>>>, Vec<Vec<Complex<$t>>>>>::div(&a, &b);
272                    for i in 0..3 {
273                        for j in 0..2 {
274                            assert_relative_eq!(target[j][i].re as f64, res[j][i].re as f64, epsilon = f64::EPSILON);
275                            assert_relative_eq!(target[j][i].im as f64, res[j][i].im as f64, epsilon = f64::EPSILON);
276                        }
277                    }
278                }
279            }
280
281            item! {
282                #[test]
283                #[should_panic]
284                fn [<test_div_mat_mat_panic_1_ $t>]() {
285                    let a = vec![
286                        vec![1 as $t, 4 as $t, 8 as $t],
287                        vec![2 as $t, 9 as $t]
288                    ];
289                    let b = vec![
290                        vec![41 as $t, 38 as $t, 34 as $t],
291                        vec![40 as $t, 37 as $t, 33 as $t]
292                    ];
293                    <Vec<Vec<$t>> as ArgminDiv<Vec<Vec<$t>>, Vec<Vec<$t>>>>::div(&a, &b);
294                }
295            }
296
297            item! {
298                #[test]
299                #[should_panic]
300                fn [<test_div_mat_mat_panic_2_ $t>]() {
301                    let a = vec![
302                        vec![1 as $t, 4 as $t, 8 as $t],
303                        vec![2 as $t, 5 as $t, 9 as $t]
304                    ];
305                    let b = vec![
306                        vec![41 as $t, 38 as $t, 34 as $t],
307                    ];
308                    <Vec<Vec<$t>> as ArgminDiv<Vec<Vec<$t>>, Vec<Vec<$t>>>>::div(&a, &b);
309                }
310            }
311
312            item! {
313                #[test]
314                #[should_panic]
315                fn [<test_div_mat_mat_panic_3_ $t>]() {
316                    let a = vec![
317                        vec![1 as $t, 4 as $t, 8 as $t],
318                        vec![2 as $t, 5 as $t, 9 as $t]
319                    ];
320                    let b = vec![];
321                    <Vec<Vec<$t>> as ArgminDiv<Vec<Vec<$t>>, Vec<Vec<$t>>>>::div(&a, &b);
322                }
323            }
324        };
325    }
326
327    make_test!(i8);
328    make_test!(u8);
329    make_test!(i16);
330    make_test!(u16);
331    make_test!(i32);
332    make_test!(u32);
333    make_test!(i64);
334    make_test!(u64);
335    make_test!(f32);
336    make_test!(f64);
337}