1use serde_derive::Serialize;
4
5#[derive(Debug, PartialEq, Clone, Serialize)]
8pub struct Config {
9 min: f64,
10 max: f64,
11 step: f64,
12 len: usize,
13}
14
15impl Config {
16 pub fn from_min_max_step(min: f64, max: f64, step: f64) -> Self {
17 assert!(min <= max, "min must be smaller than max");
18 let len = ((max - min) / step).ceil() as usize;
19 Config {
20 min,
21 max,
22 step,
23 len,
24 }
25 }
26 pub fn from_min_max_bins(min: f64, max: f64, len: usize) -> Self {
27 assert!(min <= max, "min must be smaller than max");
28 let step = (max - min) / len as f64;
29 Config {
30 min,
31 max,
32 step,
33 len,
34 }
35 }
36
37 #[inline]
38 pub fn len(&self) -> usize {
39 self.len
40 }
41
42 #[inline]
43 pub fn step(&self) -> f64 {
44 self.step
45 }
46
47 #[inline]
48 pub fn max(&self) -> f64 {
49 self.max
50 }
51
52 #[inline]
53 pub fn min(&self) -> f64 {
54 self.min
55 }
56
57 #[inline]
58 pub fn bin_for(&self, val: f64) -> HistBin {
59 use HistBin::*;
60 if val >= self.max {
61 Max
62 } else if val < self.min {
63 Min
64 } else {
65 let bin = ((val - self.min) / self.step).floor() as usize;
66 if bin >= self.len {
67 Max
68 } else {
69 Bin(bin)
70 }
71 }
72 }
73}
74
75#[derive(Debug)]
78pub enum HistBin {
79 Min,
80 Max,
81 Bin(usize),
82}
83
84#[derive(Debug, Clone, Serialize)]
87pub struct Histogram<'a> {
88 cfg: &'a Config,
89 hist: Vec<usize>,
90 min: usize,
91 max: usize,
92 count: usize,
93}
94impl<'a> Histogram<'a> {
95 pub fn new(cfg: &'a Config) -> Self {
96 Histogram {
97 cfg,
98 hist: vec![0; cfg.len()],
99 min: 0,
100 max: 0,
101 count: 0,
102 }
103 }
104}
105
106use std::ops::AddAssign;
107impl<'a, 'b> AddAssign<Histogram<'b>> for Histogram<'a> {
108 fn add_assign(&mut self, other: Histogram<'b>) {
109 assert!(
110 self.cfg == other.cfg,
111 "adding histogram with a different config"
112 );
113 for (a, b) in self.hist.iter_mut().zip(other.hist.iter()) {
114 *a += *b;
115 }
116 self.min += other.min;
117 self.max += other.max;
118 self.count += other.count;
119 }
120}
121impl<'a> AddAssign<f64> for Histogram<'a> {
122 fn add_assign(&mut self, other: f64) {
123 use HistBin::*;
124 match self.cfg.bin_for(other) {
125 Min => {
126 self.min += 1;
127 }
128 Max => {
129 self.max += 1;
130 }
131 Bin(bin) => {
132 self.hist[bin] += 1;
133 }
134 }
135 self.count += 1;
136 }
137}