use super::log_scale::LogScale;
#[derive(Debug, Clone, Copy)]
pub struct BucketSpan<'a> {
log_scale: &'a LogScale,
index: usize,
}
impl<'a> BucketSpan<'a> {
pub(crate) fn new(log_scale: &'a LogScale, index: usize) -> Self {
Self { log_scale, index }
}
#[inline]
pub fn index(&self) -> usize {
self.index
}
#[inline]
pub fn left(&self) -> u64 {
self.log_scale.bucket_min_values[self.index]
}
#[inline]
pub fn is_last(&self) -> bool {
self.index + 1 == self.log_scale.bucket_min_values.len()
}
#[inline]
pub fn right(&self) -> u64 {
if !self.is_last() {
self.log_scale.bucket_min_values[self.index + 1]
} else {
u64::MAX
}
}
#[inline]
pub fn width(&self) -> u64 {
let span = self.right() - self.left();
if self.is_last() { span + 1 } else { span }
}
#[inline]
pub fn midpoint(&self) -> u64 {
self.left() + (self.right() - self.left()) / 2
}
}
#[cfg(test)]
mod tests {
use crate::histogram::scale::LogScale;
#[test]
fn test_bucket_span() {
let scale = LogScale::get(3);
let b = scale.bucket_span(0);
assert_eq!(
(b.index(), b.left(), b.right(), b.width(), b.midpoint()),
(0, 0, 1, 1, 0)
);
let b = scale.bucket_span(5);
assert_eq!(
(b.index(), b.left(), b.right(), b.width(), b.midpoint()),
(5, 5, 6, 1, 5)
);
let b = scale.bucket_span(8);
assert_eq!(
(b.index(), b.left(), b.right(), b.width(), b.midpoint()),
(8, 8, 10, 2, 9)
);
let b = scale.bucket_span(12);
assert_eq!(
(b.index(), b.left(), b.right(), b.width(), b.midpoint()),
(12, 16, 20, 4, 18)
);
let b = scale.bucket_span(16);
assert_eq!(
(b.index(), b.left(), b.right(), b.width(), b.midpoint()),
(16, 32, 40, 8, 36)
);
let b = scale.bucket_span(251);
assert_eq!(b.index(), 251);
assert_eq!(b.left(), 0b111 << 61);
assert_eq!(b.right(), u64::MAX);
assert!(b.is_last());
assert_eq!(b.width(), u64::MAX - (0b111 << 61) + 1);
assert_eq!(b.midpoint(), (0b111 << 61) + (u64::MAX - (0b111 << 61)) / 2);
}
}