use crate::{Float, Statistic};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[derive(Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Distribution<F: Float> {
statistic: Statistic<F>,
values: Vec<F>,
}
impl<F: Float> Distribution<F> {
pub fn with_capacity(capacity: usize) -> Self {
Distribution {
statistic: Statistic::default(),
values: Vec::with_capacity(capacity),
}
}
#[inline(always)]
pub fn add(&mut self, value: F) {
if self.values.capacity() == self.values.len() {
panic!(
"Distribution capacity exceeded: {}. Consider increasing the capacity or using a different data structure.",
self.values.capacity()
);
}
self.statistic.add(value);
self.values.push(value);
}
pub fn count(&self) -> usize {
self.values.len()
}
pub fn min(&self) -> F {
self.statistic.min()
}
pub fn max(&self) -> F {
self.statistic.max()
}
pub fn mean(&self) -> F {
self.statistic.mean()
}
pub fn sum(&self) -> F {
self.statistic.sum()
}
pub fn variance(&self) -> Option<F> {
self.statistic.variance()
}
pub fn std_dev(&self) -> Option<F> {
self.statistic.std_dev()
}
pub fn skewness(&self) -> Option<F> {
self.statistic.skewness()
}
pub fn kurtosis(&self) -> Option<F> {
self.statistic.kurtosis()
}
pub fn clear(&mut self) {
self.statistic.clear();
self.values.clear();
}
}
impl<F> Extend<F> for Distribution<F>
where
F: Float,
{
fn extend<T: IntoIterator<Item = F>>(&mut self, iter: T) {
self.clear();
self.values.extend(iter);
for &value in &self.values {
self.statistic.add(value);
}
}
}
impl From<&[f32]> for Distribution<f32> {
fn from(value: &[f32]) -> Self {
let mut result = Distribution::with_capacity(value.len());
for &v in value {
result.add(v);
}
result
}
}
impl From<Vec<f32>> for Distribution<f32> {
fn from(value: Vec<f32>) -> Self {
let mut result = Distribution::with_capacity(value.len());
for v in value {
result.add(v);
}
result
}
}
impl From<&Vec<usize>> for Distribution<f32> {
fn from(value: &Vec<usize>) -> Self {
let mut dist = Distribution::with_capacity(value.len());
for v in value.iter().map(|&v| v as f32) {
dist.add(v);
}
dist
}
}