const BUCKET_BITS: u32 = 26;
const BUCKET: i64 = 1 << BUCKET_BITS;
#[derive(Debug, Clone, PartialEq)]
pub(super) struct Ranked {
values: Vec<i64>,
low: i64,
below: Vec<usize>,
}
impl Ranked {
pub(super) fn new(values: Vec<i64>, low: i64, high: i64) -> Self {
let buckets = usize::try_from(high.saturating_sub(low).max(0) / BUCKET).unwrap_or(0);
let mut below = Vec::with_capacity(buckets.saturating_add(1));
let mut count = 0;
let mut at = low;
for _ in 0..=buckets {
while values.get(count).is_some_and(|value| *value < at) {
count += 1;
}
below.push(count);
at = at.saturating_add(BUCKET);
}
Self { values, low, below }
}
pub(super) fn get(&self, index: usize) -> Option<i64> {
self.values.get(index).copied()
}
fn start(&self, t: i64) -> usize {
let bucket = t.saturating_sub(self.low) >> BUCKET_BITS;
let Ok(bucket) = usize::try_from(bucket) else {
return 0;
};
let last = self.below.len().saturating_sub(1);
self.below.get(bucket.min(last)).copied().unwrap_or(0)
}
pub(super) fn below(&self, t: i64) -> usize {
let mut count = self.start(t);
while self.get(count).is_some_and(|value| value < t) {
count += 1;
}
count
}
pub(super) fn through(&self, t: i64) -> usize {
let mut count = self.start(t);
while self.get(count).is_some_and(|value| value <= t) {
count += 1;
}
count
}
}
#[cfg(test)]
mod tests;