1#[inline]
12pub fn recursion_guard(
13 depth: usize,
14 f: impl FnOnce(usize) -> (usize, Option<usize>),
15) -> (usize, Option<usize>) {
16 const MAX_DEPTH: usize = 20;
17 if depth > MAX_DEPTH {
18 (0, None)
19 } else {
20 f(depth + 1)
21 }
22}
23
24#[inline]
26pub fn and(lhs: (usize, Option<usize>), rhs: (usize, Option<usize>)) -> (usize, Option<usize>) {
27 let lower = lhs.0 + rhs.0;
28 let upper = lhs.1.and_then(|lhs| rhs.1.map(|rhs| lhs + rhs));
29 (lower, upper)
30}
31
32#[inline]
37pub fn and_all(hints: &[(usize, Option<usize>)]) -> (usize, Option<usize>) {
38 hints.iter().copied().fold((0, Some(0)), and)
39}
40
41#[inline]
44pub fn or(lhs: (usize, Option<usize>), rhs: (usize, Option<usize>)) -> (usize, Option<usize>) {
45 let lower = std::cmp::min(lhs.0, rhs.0);
46 let upper = lhs
47 .1
48 .and_then(|lhs| rhs.1.map(|rhs| std::cmp::max(lhs, rhs)));
49 (lower, upper)
50}
51
52#[inline]
57pub fn or_all(hints: &[(usize, Option<usize>)]) -> (usize, Option<usize>) {
58 if let Some(head) = hints.first().copied() {
59 hints[1..].iter().copied().fold(head, or)
60 } else {
61 (0, Some(0))
62 }
63}
64
65#[cfg(test)]
66mod tests {
67 #[test]
68 fn and() {
69 assert_eq!((5, Some(5)), super::and((2, Some(2)), (3, Some(3))));
70 assert_eq!((5, None), super::and((2, Some(2)), (3, None)));
71 assert_eq!((5, None), super::and((2, None), (3, Some(3))));
72 assert_eq!((5, None), super::and((2, None), (3, None)));
73 }
74
75 #[test]
76 fn or() {
77 assert_eq!((2, Some(3)), super::or((2, Some(2)), (3, Some(3))));
78 assert_eq!((2, None), super::or((2, Some(2)), (3, None)));
79 assert_eq!((2, None), super::or((2, None), (3, Some(3))));
80 assert_eq!((2, None), super::or((2, None), (3, None)));
81 }
82
83 #[test]
84 fn and_all() {
85 assert_eq!((0, Some(0)), super::and_all(&[]));
86 assert_eq!(
87 (7, Some(7)),
88 super::and_all(&[(1, Some(1)), (2, Some(2)), (4, Some(4))])
89 );
90 assert_eq!(
91 (7, None),
92 super::and_all(&[(1, Some(1)), (2, Some(2)), (4, None)])
93 );
94 assert_eq!(
95 (7, None),
96 super::and_all(&[(1, Some(1)), (2, None), (4, Some(4))])
97 );
98 assert_eq!(
99 (7, None),
100 super::and_all(&[(1, None), (2, Some(2)), (4, Some(4))])
101 );
102 }
103
104 #[test]
105 fn or_all() {
106 assert_eq!((0, Some(0)), super::or_all(&[]));
107 assert_eq!(
108 (1, Some(4)),
109 super::or_all(&[(1, Some(1)), (2, Some(2)), (4, Some(4))])
110 );
111 assert_eq!(
112 (1, None),
113 super::or_all(&[(1, Some(1)), (2, Some(2)), (4, None)])
114 );
115 assert_eq!(
116 (1, None),
117 super::or_all(&[(1, Some(1)), (2, None), (4, Some(4))])
118 );
119 assert_eq!(
120 (1, None),
121 super::or_all(&[(1, None), (2, Some(2)), (4, Some(4))])
122 );
123 }
124}