competitive/tools/
ord_tools.rs

1pub trait PartialOrdExt: Sized {
2    fn chmin(&mut self, other: Self);
3    fn chmax(&mut self, other: Self);
4    fn minmax(self, other: Self) -> (Self, Self);
5}
6impl<T> PartialOrdExt for T
7where
8    T: PartialOrd,
9{
10    #[inline]
11    fn chmin(&mut self, other: Self) {
12        if *self > other {
13            *self = other;
14        }
15    }
16    #[inline]
17    fn chmax(&mut self, other: Self) {
18        if *self < other {
19            *self = other;
20        }
21    }
22    #[inline]
23    fn minmax(self, other: Self) -> (Self, Self) {
24        if self < other {
25            (self, other)
26        } else {
27            (other, self)
28        }
29    }
30}
31
32#[macro_export]
33macro_rules! min {
34    ($l:expr) => { $l };
35    ($l:expr,) => { $crate::min!($l) };
36    ($l:expr, $r:expr) => { ($l).min($r) };
37    ($l:expr, $r:expr,) => { $crate::min!($l, $r) };
38    ($l:expr, $r:expr, $($t:tt)*) => { $crate::min!($crate::min!($l, $r), $($t)*) };
39}
40
41#[macro_export]
42macro_rules! chmin {
43    ($l:expr) => {};
44    ($l:expr,) => {};
45    ($l:expr, $r:expr) => {{ let r = $r; if $l > r { $l = r; } }};
46    ($l:expr, $r:expr,) => { $crate::chmin!($l, $r) };
47    ($l:expr, $r:expr, $($t:tt)*) => { $crate::chmin!($l, $r); $crate::chmin!($l, $($t)*) };
48}
49
50#[macro_export]
51macro_rules! max {
52    ($l:expr) => { $l };
53    ($l:expr,) => { $crate::max!($l) };
54    ($l:expr, $r:expr) => { ($l).max($r) };
55    ($l:expr, $r:expr,) => { $crate::max!($l, $r) };
56    ($l:expr, $r:expr, $($t:tt)*) => { $crate::max!($crate::max!($l, $r), $($t)*) };
57}
58
59#[macro_export]
60macro_rules! chmax {
61    ($l:expr) => {};
62    ($l:expr,) => {};
63    ($l:expr, $r:expr) => {{ let r = $r; if $l < r { $l = r; } }};
64    ($l:expr, $r:expr,) => { $crate::chmax!($l, $r) };
65    ($l:expr, $r:expr, $($t:tt)*) => { $crate::chmax!($l, $r); $crate::chmax!($l, $($t)*) };
66}
67
68#[macro_export]
69macro_rules! minmax {
70    ($($t:tt)*) => { ($crate::min!($($t)*), $crate::max!($($t)*)) };
71}
72
73#[cfg(test)]
74mod tests {
75    #![allow(clippy::eq_op)]
76    use super::*;
77    use crate::{chmax, chmin, max, min, minmax};
78
79    macro_rules! assert_eq_f64 {
80        ($l:expr, $r:expr) => { assert_eq_f64!($l, $r,) };
81        ($l:expr, $r:expr, $($t:tt)*) => {
82            ::std::assert!(($l - $r).abs() < f64::EPSILON, $($t)*);
83        };
84    }
85
86    #[test]
87    fn test_min() {
88        assert_eq!(min!(1), 1);
89        assert_eq!(min!(1, 2), 1);
90        assert_eq_f64!(min!(4.0f64, 1., 2.), 1.0f64);
91        assert_eq!(min!(4, 9, 2, 3,), 2);
92    }
93
94    #[test]
95    fn test_chmin() {
96        let mut x = 100;
97        chmin!(x, 101);
98        assert_eq!(x, 100);
99        chmin!(x, 91, 78);
100        assert_eq!(x, 78);
101        chmin!(x, 61, 42, 51);
102        assert_eq!(x, 42);
103
104        let mut v = [31, 12];
105        chmin!(v[0], v[1], 14);
106        assert_eq!(v[0], v[1]);
107    }
108
109    #[test]
110    fn test_max() {
111        assert_eq!(max!(1), 1);
112        assert_eq!(max!(1, 2), 2);
113        assert_eq_f64!(max!(4.0f64, 1., 2.), 4.0f64);
114        assert_eq!(max!(4, 9, 2, 3,), 9);
115    }
116
117    #[test]
118    fn test_chmax() {
119        let mut x = 100;
120        chmax!(x, 91);
121        assert_eq!(x, 100);
122        chmax!(x, 191, 178);
123        assert_eq!(x, 191);
124        chmax!(x, 261, 242, 251);
125        assert_eq!(x, 261);
126
127        let mut v = [31, 42];
128        chmax!(v[0], v[1], 14);
129        assert_eq!(v[0], v[1]);
130    }
131
132    #[test]
133    fn test_minmax() {
134        assert_eq!(minmax!(1), (1, 1));
135        assert_eq!(minmax!(1, 2), (1, 2));
136        assert_eq_f64!(minmax!(4.0f64, 1., 2.).0, 1.0f64);
137        assert_eq_f64!(minmax!(4.0f64, 1., 2.).1, 4.0f64);
138        assert_eq!(minmax!(4, 9, 2, 3,), (2, 9));
139    }
140
141    #[test]
142    fn test_partial_ord_ext() {
143        let mut x = 100;
144        x.chmin(91);
145        assert_eq!(x, 91);
146        x.chmax(101);
147        assert_eq!(x, 101);
148        assert_eq!(100.minmax(91), (91, 100));
149    }
150}