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}