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
77 macro_rules! assert_eq_f64 {
78 ($l:expr, $r:expr) => { assert_eq_f64!($l, $r,) };
79 ($l:expr, $r:expr, $($t:tt)*) => {
80 ::std::assert!(($l - $r).abs() < f64::EPSILON, $($t)*);
81 };
82 }
83
84 #[test]
85 fn test_min() {
86 assert_eq!(min!(1), 1);
87 assert_eq!(min!(1, 2), 1);
88 assert_eq_f64!(min!(4.0f64, 1., 2.), 1.0f64);
89 assert_eq!(min!(4, 9, 2, 3,), 2);
90 }
91
92 #[test]
93 fn test_chmin() {
94 let mut x = 100;
95 chmin!(x, 101);
96 assert_eq!(x, 100);
97 chmin!(x, 91, 78);
98 assert_eq!(x, 78);
99 chmin!(x, 61, 42, 51);
100 assert_eq!(x, 42);
101
102 let mut v = [31, 12];
103 chmin!(v[0], v[1], 14);
104 assert_eq!(v[0], v[1]);
105 }
106
107 #[test]
108 fn test_max() {
109 assert_eq!(max!(1), 1);
110 assert_eq!(max!(1, 2), 2);
111 assert_eq_f64!(max!(4.0f64, 1., 2.), 4.0f64);
112 assert_eq!(max!(4, 9, 2, 3,), 9);
113 }
114
115 #[test]
116 fn test_chmax() {
117 let mut x = 100;
118 chmax!(x, 91);
119 assert_eq!(x, 100);
120 chmax!(x, 191, 178);
121 assert_eq!(x, 191);
122 chmax!(x, 261, 242, 251);
123 assert_eq!(x, 261);
124
125 let mut v = [31, 42];
126 chmax!(v[0], v[1], 14);
127 assert_eq!(v[0], v[1]);
128 }
129
130 #[test]
131 fn test_minmax() {
132 assert_eq!(minmax!(1), (1, 1));
133 assert_eq!(minmax!(1, 2), (1, 2));
134 assert_eq_f64!(minmax!(4.0f64, 1., 2.).0, 1.0f64);
135 assert_eq_f64!(minmax!(4.0f64, 1., 2.).1, 4.0f64);
136 assert_eq!(minmax!(4, 9, 2, 3,), (2, 9));
137 }
138
139 #[test]
140 fn test_partial_ord_ext() {
141 let mut x = 100;
142 x.chmin(91);
143 assert_eq!(x, 91);
144 x.chmax(101);
145 assert_eq!(x, 101);
146 assert_eq!(100.minmax(91), (91, 100));
147 }
148}