competitive/num/
bounded.rs1pub trait Bounded: Sized + PartialOrd {
3 fn maximum() -> Self;
4 fn minimum() -> Self;
5 fn is_maximum(&self) -> bool {
6 self == &Self::maximum()
7 }
8 fn is_minimum(&self) -> bool {
9 self == &Self::minimum()
10 }
11 fn set_maximum(&mut self) {
12 *self = Self::maximum()
13 }
14 fn set_minimum(&mut self) {
15 *self = Self::minimum()
16 }
17}
18
19macro_rules! impl_bounded_num {
20 ($($t:ident)*) => {
21 $(impl Bounded for $t {
22 fn maximum() -> Self { $t::MAX }
23 fn minimum() -> Self { $t::MIN }
24 })*
25 };
26}
27impl_bounded_num!(u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize f32 f64);
28
29macro_rules! impl_bounded_tuple {
30 (@impl $($T:ident)*) => {
31 impl<$($T: Bounded),*> Bounded for ($($T,)*) {
32 fn maximum() -> Self { ($(<$T as Bounded>::maximum(),)*) }
33 fn minimum() -> Self { ($(<$T as Bounded>::minimum(),)*) }
34 }
35 };
36 (@inner $($T:ident)*,) => {
37 impl_bounded_tuple!(@impl $($T)*);
38 };
39 (@inner $($T:ident)*, $U:ident $($Rest:ident)*) => {
40 impl_bounded_tuple!(@impl $($T)*);
41 impl_bounded_tuple!(@inner $($T)* $U, $($Rest)*);
42 };
43 ($T:ident $($Rest:ident)*) => {
44 impl_bounded_tuple!(@inner $T, $($Rest)*);
45 };
46}
47impl_bounded_tuple!(A B C D E F G H I J);
48
49impl Bounded for () {
50 fn maximum() -> Self {}
51 fn minimum() -> Self {}
52}
53impl Bounded for bool {
54 fn maximum() -> Self {
55 true
56 }
57 fn minimum() -> Self {
58 false
59 }
60}
61impl<T> Bounded for Option<T>
62where
63 T: Bounded,
64{
65 fn maximum() -> Self {
66 Some(<T as Bounded>::maximum())
67 }
68 fn minimum() -> Self {
69 None
70 }
71}
72impl<T> Bounded for std::cmp::Reverse<T>
73where
74 T: Bounded,
75{
76 fn maximum() -> Self {
77 std::cmp::Reverse(<T as Bounded>::minimum())
78 }
79 fn minimum() -> Self {
80 std::cmp::Reverse(<T as Bounded>::maximum())
81 }
82}
83
84#[cfg(test)]
85mod tests {
86 use super::*;
87 use std::cmp::Reverse;
88
89 fn assert_bounded<T: Bounded, I: Iterator<Item = T>>(iter: I) {
90 assert!(T::minimum() <= T::maximum());
91 for item in iter {
92 assert!(T::minimum() <= item);
93 assert!(item <= T::maximum());
94 }
95 }
96
97 #[test]
98 fn test_num_bounded() {
99 assert_bounded([0u32, 1, 2, !0].iter().cloned());
100 assert_bounded([0u64, 1, 2, !0].iter().cloned());
101 assert_bounded([0usize, 1, 2, !0].iter().cloned());
102 assert_bounded([0i32, 1, 2, !0].iter().cloned());
103 assert_bounded([0i64, 1, 2, !0].iter().cloned());
104 assert_bounded([0isize, 1, 2, !0].iter().cloned());
105 assert_bounded([false, true].iter().cloned());
106 }
107
108 #[test]
109 fn test_tuple_bounded() {
110 assert_bounded([(1, 0, 3)].iter().cloned());
111 assert_bounded([((), (1,), (2, 3))].iter().cloned());
112 }
113
114 #[test]
115 fn test_option_bounded() {
116 assert_bounded([None, Some((false, 3))].iter().cloned());
117 }
118
119 #[test]
120 fn test_reverse_bounded() {
121 assert_bounded([Reverse(0), Reverse(1), Reverse(!0)].iter().cloned());
122 }
123}