1use alloc::vec::Vec;
4
5use libm::log2;
6use serde::Serialize;
7
8#[derive(Copy, Clone, Debug, PartialEq, Serialize)]
10pub struct ErrorBits(pub f64);
11
12impl ErrorBits {
13 pub const fn from_log2(bits: f64) -> Self {
14 Self(bits)
15 }
16
17 pub fn from_prob(p: f64) -> Self {
18 Self(-log2(p))
19 }
20
21 pub fn sum(errors: &[Self]) -> Self {
25 let total: f64 = errors.iter().map(|e| pow2_neg(e.0)).sum();
26 Self::from_prob(total)
27 }
28
29 #[allow(clippy::missing_const_for_fn)] pub fn min(errors: &[Self]) -> Self {
33 let m = errors.iter().map(|e| e.0).fold(f64::INFINITY, f64::min);
34 Self(m)
35 }
36
37 pub const fn bits(self) -> f64 {
38 self.0
39 }
40
41 pub fn floor(self) -> usize {
42 libm::floor(self.0) as usize
43 }
44}
45
46fn pow2_neg(bits: f64) -> f64 {
47 libm::pow(2.0, -bits)
48}
49
50pub fn sum_errors<I: IntoIterator<Item = ErrorBits>>(iter: I) -> ErrorBits {
52 let v: Vec<_> = iter.into_iter().collect();
53 ErrorBits::sum(&v)
54}