///|
/// Equal-width integer bucket specification.
pub(all) struct BucketSpec {
min : Int
max : Int
buckets : Int
} derive(Eq, Debug)
///|
pub fn BucketSpec::new(min : Int, max : Int, buckets : Int) -> BucketSpec {
guard max > min && buckets > 0 else { return { min: 0, max: 1, buckets: 1 } }
{ min, max, buckets }
}
///|
pub fn BucketSpec::bucket_count(self : BucketSpec) -> Int {
self.buckets
}
///|
pub fn BucketSpec::index_of(self : BucketSpec, value : Int) -> Int {
if value <= self.min {
0
} else if value >= self.max {
self.buckets - 1
} else {
let width = self.max - self.min
let shifted = value - self.min
let index = shifted * self.buckets / width
if index >= self.buckets {
self.buckets - 1
} else {
index
}
}
}
///|
pub fn BucketSpec::lower_bound(self : BucketSpec, index : Int) -> Int {
self.min + (self.max - self.min) * index / self.buckets
}
///|
pub fn BucketSpec::upper_bound(self : BucketSpec, index : Int) -> Int {
if index + 1 >= self.buckets {
self.max
} else {
self.min + (self.max - self.min) * (index + 1) / self.buckets
}
}