pub trait Estimate {
fn add(&mut self, x: f64);
fn estimate(&self) -> f64;
}
pub trait Merge {
fn merge(&mut self, other: &Self);
}
#[inline(always)]
fn multinomial_variance(n: f64, n_tot_inv: f64) -> f64 {
n * (1. - n * n_tot_inv)
}
pub trait Histogram
where
for<'a> &'a Self: IntoIterator<Item = ((f64, f64), u64)>,
{
fn bins(&self) -> &[u64];
#[inline]
fn variance(&self, bin: usize) -> f64 {
let count = self.bins()[bin];
let sum: u64 = self.bins().iter().sum();
multinomial_variance(count as f64, 1. / (sum as f64))
}
#[inline]
fn normalized_bins(&self) -> IterNormalized<<&Self as IntoIterator>::IntoIter> {
IterNormalized {
histogram_iter: self.into_iter(),
}
}
#[inline]
fn widths(&self) -> IterWidths<<&Self as IntoIterator>::IntoIter> {
IterWidths {
histogram_iter: self.into_iter(),
}
}
#[inline]
fn centers(&self) -> IterBinCenters<<&Self as IntoIterator>::IntoIter> {
IterBinCenters {
histogram_iter: self.into_iter(),
}
}
#[inline]
fn variances(&self) -> IterVariances<<&Self as IntoIterator>::IntoIter> {
let sum: u64 = self.bins().iter().sum();
IterVariances {
histogram_iter: self.into_iter(),
sum_inv: 1. / (sum as f64),
}
}
}
#[derive(Debug, Clone)]
pub struct IterNormalized<T>
where
T: Iterator<Item = ((f64, f64), u64)>,
{
histogram_iter: T,
}
impl<T> Iterator for IterNormalized<T>
where
T: Iterator<Item = ((f64, f64), u64)>,
{
type Item = f64;
#[inline]
fn next(&mut self) -> Option<f64> {
self.histogram_iter
.next()
.map(|((a, b), count)| (count as f64) / (b - a))
}
}
#[derive(Debug, Clone)]
pub struct IterWidths<T>
where
T: Iterator<Item = ((f64, f64), u64)>,
{
histogram_iter: T,
}
impl<T> Iterator for IterWidths<T>
where
T: Iterator<Item = ((f64, f64), u64)>,
{
type Item = f64;
#[inline]
fn next(&mut self) -> Option<f64> {
self.histogram_iter.next().map(|((a, b), _)| b - a)
}
}
#[derive(Debug, Clone)]
pub struct IterBinCenters<T>
where
T: Iterator<Item = ((f64, f64), u64)>,
{
histogram_iter: T,
}
impl<T> Iterator for IterBinCenters<T>
where
T: Iterator<Item = ((f64, f64), u64)>,
{
type Item = f64;
#[inline]
fn next(&mut self) -> Option<f64> {
self.histogram_iter.next().map(|((a, b), _)| 0.5 * (a + b))
}
}
#[derive(Debug, Clone)]
pub struct IterVariances<T>
where
T: Iterator<Item = ((f64, f64), u64)>,
{
histogram_iter: T,
sum_inv: f64,
}
impl<T> Iterator for IterVariances<T>
where
T: Iterator<Item = ((f64, f64), u64)>,
{
type Item = f64;
#[inline]
fn next(&mut self) -> Option<f64> {
self.histogram_iter
.next()
.map(|(_, n)| multinomial_variance(n as f64, self.sum_inv))
}
}