argmin_math/nalgebra_m/
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::{Allocator, ArgminMinMax};
9
10use crate::ClosedMul;
11use nalgebra::{
12    base::{dimension::Dim, Scalar},
13    DefaultAllocator, OMatrix,
14};
15
16impl<N, R, C> ArgminMinMax for OMatrix<N, R, C>
17where
18    N: Scalar + Copy + ClosedMul + PartialOrd,
19    R: Dim,
20    C: Dim,
21    DefaultAllocator: Allocator<N, R, C>,
22{
23    #[inline]
24    fn max(a: &OMatrix<N, R, C>, b: &OMatrix<N, R, C>) -> OMatrix<N, R, C> {
25        a.zip_map(b, |aa, bb| if aa > bb { aa } else { bb })
26    }
27
28    #[inline]
29    fn min(a: &OMatrix<N, R, C>, b: &OMatrix<N, R, C>) -> OMatrix<N, R, C> {
30        a.zip_map(b, |aa, bb| if aa < bb { aa } else { bb })
31    }
32}
33
34#[cfg(test)]
35mod tests {
36    use super::*;
37    use approx::assert_relative_eq;
38    use nalgebra::{Matrix2x3, Vector3};
39    use paste::item;
40
41    macro_rules! make_test {
42        ($t:ty) => {
43            item! {
44                #[test]
45                fn [<test_minmax_vec_vec_ $t>]() {
46                    let a = Vector3::new(1 as $t, 4 as $t, 8 as $t);
47                    let b = Vector3::new(2 as $t, 3 as $t, 4 as $t);
48                    let target_max = Vector3::new(2 as $t, 4 as $t, 8 as $t);
49                    let target_min = Vector3::new(1 as $t, 3 as $t, 4 as $t);
50                    let res_max = <Vector3<$t> as ArgminMinMax>::max(&a, &b);
51                    let res_min = <Vector3<$t> as ArgminMinMax>::min(&a, &b);
52                    for i in 0..3 {
53                        assert_relative_eq!(target_max[i] as f64, res_max[i] as f64, epsilon = f64::EPSILON);
54                        assert_relative_eq!(target_min[i] as f64, res_min[i] as f64, epsilon = f64::EPSILON);
55                    }
56                }
57            }
58
59            item! {
60                #[test]
61                fn [<test_minmax_mat_mat_ $t>]() {
62                    let a = Matrix2x3::new(
63                        1 as $t, 4 as $t, 8 as $t,
64                        2 as $t, 5 as $t, 9 as $t
65                    );
66                    let b = Matrix2x3::new(
67                        2 as $t, 3 as $t, 4 as $t,
68                        3 as $t, 4 as $t, 5 as $t
69                    );
70                    let target_max = Matrix2x3::new(
71                        2 as $t, 4 as $t, 8 as $t,
72                        3 as $t, 5 as $t, 9 as $t
73                    );
74                    let target_min = Matrix2x3::new(
75                        1 as $t, 3 as $t, 4 as $t,
76                        2 as $t, 4 as $t, 5 as $t
77                    );
78                    let res_max = <Matrix2x3<$t> as ArgminMinMax>::max(&a, &b);
79                    let res_min = <Matrix2x3<$t> as ArgminMinMax>::min(&a, &b);
80                    for i in 0..3 {
81                        for j in 0..2 {
82                            assert_relative_eq!(target_max[(j, i)] as f64, res_max[(j, i)] as f64, epsilon = f64::EPSILON);
83                            assert_relative_eq!(target_min[(j, i)] as f64, res_min[(j, i)] as f64, epsilon = f64::EPSILON);
84                        }
85                    }
86                }
87            }
88        };
89    }
90
91    make_test!(i8);
92    make_test!(u8);
93    make_test!(i16);
94    make_test!(u16);
95    make_test!(i32);
96    make_test!(u32);
97    make_test!(i64);
98    make_test!(u64);
99    make_test!(f32);
100    make_test!(f64);
101}