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 use super::*;
76 use crate::tools::Xorshift;
77 use std::array;
78
79 #[test]
80 fn test_order_operations() {
81 let mut rng = Xorshift::default();
82 for _ in 0..10_000 {
83 let values: [i32; 4] = array::from_fn(|_| rng.random(-100..=100));
84 let [a, b, c, d] = values;
85 let lo = *values.iter().min().unwrap();
86 let hi = *values.iter().max().unwrap();
87 assert_eq!(min!(a), a);
88 assert_eq!(max!(a), a);
89 assert_eq!(min!(a, b), a.min(b));
90 assert_eq!(max!(a, b), a.max(b));
91 assert_eq!(min!(a, b, c, d,), lo);
92 assert_eq!(max!(a, b, c, d,), hi);
93 assert_eq!(minmax!(a, b, c, d), (lo, hi));
94 let mut x = a;
95 chmin!(x, b, c, d);
96 assert_eq!(x, lo);
97 let mut x = a;
98 chmax!(x, b, c, d);
99 assert_eq!(x, hi);
100 let mut x = a;
101 x.chmin(b);
102 assert_eq!(x, a.min(b));
103 x.chmax(c);
104 assert_eq!(x, a.min(b).max(c));
105 assert_eq!(a.minmax(b), (a.min(b), a.max(b)));
106 assert_eq!(min!(a as f64, b as f64, c as f64, d as f64), lo as f64);
107 assert_eq!(max!(a as f64, b as f64, c as f64, d as f64), hi as f64);
108 }
109 }
110}