add SummaryStats util type to tidepool

This commit is contained in:
tali 2023-04-14 15:28:20 -04:00
parent 517a64156a
commit 8b60c03232
1 changed files with 112 additions and 0 deletions

View File

@ -34,6 +34,95 @@ pub struct Profile {
// TODO: histograms about selected nodes // TODO: histograms about selected nodes
} }
#[derive(Copy, Clone, Debug)]
pub struct SummaryStats<T: Copy> {
count: usize,
min: Option<T>,
max: Option<T>,
sum: Option<T>,
}
impl<T: Copy> Default for SummaryStats<T> {
fn default() -> Self {
SummaryStats {
count: 0,
min: None,
max: None,
sum: None,
}
}
}
impl<T: Copy> SummaryStats<T> {
pub fn new() -> Self {
Self::default()
}
pub fn count(&self) -> usize {
self.count
}
pub fn min(&self) -> Option<T> {
self.min
}
pub fn max(&self) -> Option<T> {
self.max
}
}
impl<T> SummaryStats<T>
where
T: Ord + Copy + std::ops::Add<T, Output = T>,
{
pub fn insert(&mut self, x: T) {
self.count += 1;
self.min = Some(self.min.map_or(x, |y| x.min(y)));
self.max = Some(self.max.map_or(x, |y| x.max(y)));
self.sum = Some(self.sum.map_or(x, |y| x + y));
}
}
impl SummaryStats<f64> {
pub fn insert_f64(&mut self, x: f64) {
self.count += 1;
self.min = Some(self.min.map_or(x, |y| x.min(y)));
self.max = Some(self.max.map_or(x, |y| x.max(y)));
self.sum = Some(self.sum.map_or(x, |y| x + y));
}
}
impl<T> SummaryStats<T>
where
T: Copy + std::ops::Div<usize, Output = T>,
{
pub fn avg(&self) -> Option<T> {
self.sum.map(|x| x / self.count)
}
}
impl<T> SummaryStats<T>
where
T: Copy,
f64: From<T>,
{
pub fn avg_f64(&self) -> Option<f64> {
self.sum.map(|x| f64::from(x) / self.count as f64)
}
}
impl<T> Serialize for SummaryStats<T>
where
T: Serialize + Copy + std::ops::Div<usize, Output = T>,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
ser::summary_stats(self, serializer)
}
}
mod ser { mod ser {
use super::*; use super::*;
@ -78,4 +167,27 @@ mod ser {
{ {
dur.as_secs_f64().serialize(serializer) dur.as_secs_f64().serialize(serializer)
} }
pub fn summary_stats<S, T>(stats: &SummaryStats<T>, serializer: S) -> Result<S::Ok, S::Error>
where
T: Serialize + Copy + std::ops::Div<usize, Output = T>,
S: serde::Serializer,
{
#[derive(Serialize)]
struct Stats<T> {
#[serde(skip_serializing_if = "Option::is_none")]
min: Option<T>,
#[serde(skip_serializing_if = "Option::is_none")]
max: Option<T>,
#[serde(skip_serializing_if = "Option::is_none")]
avg: Option<T>,
}
Stats {
min: stats.min,
max: stats.max,
avg: stats.avg(),
}
.serialize(serializer)
}
} }