use tdigest::TDigest;
const DIGEST_SIZE: usize = 100;
const BUFFER_SIZE: usize = 512;
#[derive(Debug, Clone)]
pub struct ApproxQuantiles {
digest: Option<TDigest>,
buffer: Vec<f64>,
}
impl ApproxQuantiles {
pub fn new() -> Self {
Self {
digest: Some(TDigest::new_with_size(DIGEST_SIZE)),
buffer: Vec::with_capacity(BUFFER_SIZE),
}
}
pub fn clear(&mut self) {
self.digest = Some(TDigest::new_with_size(DIGEST_SIZE));
self.buffer.clear();
}
pub fn flush(&mut self) {
if self.buffer.is_empty() {
return;
}
self.digest = Some(
self.digest
.as_mut()
.unwrap()
.merge_unsorted(self.buffer.clone()),
);
self.buffer.clear();
}
pub fn add(&mut self, value: f64) {
self.buffer.push(value);
if self.buffer.len() == BUFFER_SIZE {
self.flush();
}
}
pub fn finalize(&mut self) {
self.flush();
}
pub fn get(&self, q: f64) -> f64 {
self.digest.as_ref().unwrap().estimate_quantile(q)
}
pub fn merge(&mut self, other: Self) {
self.flush();
self.buffer = other.buffer;
self.digest = Some(TDigest::merge_digests(vec![
self.digest.take().unwrap(),
other.digest.unwrap(),
]));
}
}