irithyll_core/histogram/
mod.rs1use alloc::boxed::Box;
8use alloc::vec::Vec;
9
10pub mod bins;
11pub mod categorical;
12#[cfg(feature = "kmeans-binning")]
13pub mod kmeans;
14pub mod quantile;
15#[cfg(feature = "simd")]
16pub mod simd;
17pub mod uniform;
18
19#[derive(Debug, Clone)]
21pub struct BinEdges {
22 pub edges: Vec<f64>,
24}
25
26impl BinEdges {
27 #[inline]
29 pub fn find_bin(&self, value: f64) -> usize {
30 match self
31 .edges
32 .binary_search_by(|e| e.partial_cmp(&value).unwrap())
33 {
34 Ok(i) => i + 1,
35 Err(i) => i,
36 }
37 }
38
39 #[inline]
41 pub fn n_bins(&self) -> usize {
42 self.edges.len() + 1
43 }
44}
45
46pub trait BinningStrategy: Send + Sync + 'static {
48 fn observe(&mut self, value: f64);
50
51 fn compute_edges(&self, n_bins: usize) -> BinEdges;
53
54 fn reset(&mut self);
56
57 fn clone_fresh(&self) -> Box<dyn BinningStrategy>;
59}
60
61#[derive(Debug, Clone)]
71pub enum BinnerKind {
72 Uniform(uniform::UniformBinning),
74
75 Categorical(categorical::CategoricalBinning),
77
78 #[cfg(feature = "kmeans-binning")]
80 KMeans(kmeans::KMeansBinning),
81}
82
83impl BinnerKind {
84 #[inline]
86 pub fn uniform() -> Self {
87 BinnerKind::Uniform(uniform::UniformBinning::new())
88 }
89
90 #[inline]
92 pub fn categorical() -> Self {
93 BinnerKind::Categorical(categorical::CategoricalBinning::new())
94 }
95
96 #[cfg(feature = "kmeans-binning")]
98 #[inline]
99 pub fn kmeans() -> Self {
100 BinnerKind::KMeans(kmeans::KMeansBinning::new())
101 }
102
103 #[inline]
105 pub fn observe(&mut self, value: f64) {
106 match self {
107 BinnerKind::Uniform(b) => b.observe(value),
108 BinnerKind::Categorical(b) => b.observe(value),
109 #[cfg(feature = "kmeans-binning")]
110 BinnerKind::KMeans(b) => b.observe(value),
111 }
112 }
113
114 #[inline]
116 pub fn compute_edges(&self, n_bins: usize) -> BinEdges {
117 match self {
118 BinnerKind::Uniform(b) => b.compute_edges(n_bins),
119 BinnerKind::Categorical(b) => b.compute_edges(n_bins),
120 #[cfg(feature = "kmeans-binning")]
121 BinnerKind::KMeans(b) => b.compute_edges(n_bins),
122 }
123 }
124
125 #[inline]
127 pub fn reset(&mut self) {
128 match self {
129 BinnerKind::Uniform(b) => b.reset(),
130 BinnerKind::Categorical(b) => b.reset(),
131 #[cfg(feature = "kmeans-binning")]
132 BinnerKind::KMeans(b) => b.reset(),
133 }
134 }
135
136 #[inline]
138 pub fn is_categorical(&self) -> bool {
139 matches!(self, BinnerKind::Categorical(_))
140 }
141
142 pub fn clone_fresh(&self) -> Self {
144 match self {
145 BinnerKind::Uniform(_) => BinnerKind::Uniform(uniform::UniformBinning::new()),
146 BinnerKind::Categorical(_) => {
147 BinnerKind::Categorical(categorical::CategoricalBinning::new())
148 }
149 #[cfg(feature = "kmeans-binning")]
150 BinnerKind::KMeans(_) => BinnerKind::KMeans(kmeans::KMeansBinning::new()),
151 }
152 }
153}