1use std::cmp;
2
3#[derive(Clone, Copy, Debug)]
6pub struct Splitter {
7 splits: usize,
8}
9
10impl Splitter {
11 #[inline]
12 pub fn new(splits: usize) -> Self {
13 Self { splits }
14 }
15
16 #[inline]
17 pub fn try_split(&mut self) -> bool {
18 if self.splits > 1 {
19 self.splits /= 2;
20
21 true
22 } else {
23 false
24 }
25 }
26}
27
28#[derive(Clone, Copy, Debug)]
31pub struct IndexedSplitter {
32 inner: Splitter,
33 min: usize,
34}
35
36impl IndexedSplitter {
37 #[inline]
38 pub fn new(splits: usize, len: usize, min: Option<usize>, max: Option<usize>) -> Self {
39 let min = min.unwrap_or_default();
40 let mut ret = Self {
41 inner: Splitter::new(splits),
42 min: cmp::max(min, 1),
43 };
44
45 if let Some(max) = max {
46 let mut min_splits = len / cmp::max(max, 1);
47
48 min_splits -= 1;
50 min_splits |= min_splits >> 1;
51 min_splits |= min_splits >> 2;
52 min_splits |= min_splits >> 4;
53 min_splits |= min_splits >> 8;
54 min_splits |= min_splits >> 16;
55 min_splits += 1;
56
57 if min_splits > ret.inner.splits {
58 ret.inner.splits = min_splits;
59 }
60 }
61
62 ret
63 }
64
65 #[inline]
66 pub fn try_split(&mut self, len: usize) -> bool {
67 len / 2 >= self.min && self.inner.try_split()
68 }
69}