argmin_math/vec/
minmax.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::ArgminMinMax;
9
10macro_rules! make_minmax {
11    ($t:ty) => {
12        impl ArgminMinMax for Vec<$t> {
13            fn min(x: &Self, y: &Self) -> Self {
14                assert!(!x.is_empty());
15                assert_eq!(x.len(), y.len());
16
17                x.iter()
18                    .zip(y.iter())
19                    .map(|(a, b)| if a < b { a.clone() } else { b.clone() })
20                    .collect()
21            }
22
23            fn max(x: &Self, y: &Self) -> Self {
24                assert!(!x.is_empty());
25                assert_eq!(x.len(), y.len());
26
27                x.iter()
28                    .zip(y.iter())
29                    .map(|(a, b)| if a > b { a.clone() } else { b.clone() })
30                    .collect()
31            }
32        }
33
34        impl ArgminMinMax for Vec<Vec<$t>> {
35            fn min(x: &Self, y: &Self) -> Self {
36                assert!(!x.is_empty());
37                assert_eq!(x.len(), y.len());
38
39                x.iter()
40                    .zip(y.iter())
41                    .map(|(a, b)| <Vec<$t> as ArgminMinMax>::min(&a, &b))
42                    .collect()
43            }
44
45            fn max(x: &Self, y: &Self) -> Self {
46                assert!(!x.is_empty());
47                assert_eq!(x.len(), y.len());
48
49                x.iter()
50                    .zip(y.iter())
51                    .map(|(a, b)| <Vec<$t> as ArgminMinMax>::max(&a, &b))
52                    .collect()
53            }
54        }
55    };
56}
57
58make_minmax!(i8);
59make_minmax!(u8);
60make_minmax!(i16);
61make_minmax!(u16);
62make_minmax!(i32);
63make_minmax!(u32);
64make_minmax!(i64);
65make_minmax!(u64);
66make_minmax!(f32);
67make_minmax!(f64);
68
69#[cfg(test)]
70mod tests {
71    use super::*;
72    use approx::assert_relative_eq;
73    use paste::item;
74
75    macro_rules! make_test {
76        ($t:ty) => {
77            item! {
78                #[test]
79                fn [<test_minmax_vec_vec_ $t>]() {
80                    let a = vec![1 as $t, 4 as $t, 8 as $t];
81                    let b = vec![2 as $t, 3 as $t, 4 as $t];
82                    let target_max = vec![2 as $t, 4 as $t, 8 as $t];
83                    let target_min = vec![1 as $t, 3 as $t, 4 as $t];
84                    let res_max = <Vec<$t> as ArgminMinMax>::max(&a, &b);
85                    let res_min = <Vec<$t> as ArgminMinMax>::min(&a, &b);
86                    for i in 0..3 {
87                        assert_relative_eq!(target_max[i] as f64, res_max[i] as f64, epsilon = f64::EPSILON);
88                        assert_relative_eq!(target_min[i] as f64, res_min[i] as f64, epsilon = f64::EPSILON);
89                    }
90                }
91            }
92
93            item! {
94                #[test]
95                fn [<test_minmax_mat_mat_ $t>]() {
96                    let a = vec![
97                        vec![1 as $t, 4 as $t, 8 as $t],
98                        vec![2 as $t, 5 as $t, 9 as $t]
99                    ];
100                    let b = vec![
101                        vec![2 as $t, 3 as $t, 4 as $t],
102                        vec![3 as $t, 4 as $t, 5 as $t]
103                    ];
104                    let target_max = vec![
105                        vec![2 as $t, 4 as $t, 8 as $t],
106                        vec![3 as $t, 5 as $t, 9 as $t]
107                    ];
108                    let target_min = vec![
109                        vec![1 as $t, 3 as $t, 4 as $t],
110                        vec![2 as $t, 4 as $t, 5 as $t]
111                    ];
112                    let res_max = <Vec<Vec<$t>> as ArgminMinMax>::max(&a, &b);
113                    let res_min = <Vec<Vec<$t>> as ArgminMinMax>::min(&a, &b);
114                    for i in 0..3 {
115                        for j in 0..2 {
116                            assert_relative_eq!(target_max[j][i] as f64, res_max[j][i] as f64, epsilon = f64::EPSILON);
117                            assert_relative_eq!(target_min[j][i] as f64, res_min[j][i] as f64, epsilon = f64::EPSILON);
118                        }
119                    }
120                }
121            }
122        };
123    }
124
125    make_test!(i8);
126    make_test!(u8);
127    make_test!(i16);
128    make_test!(u16);
129    make_test!(i32);
130    make_test!(u32);
131    make_test!(i64);
132    make_test!(u64);
133    make_test!(f32);
134    make_test!(f64);
135}