pipecircuit 0.0.23

Correct. Robust. Fast. Portable. Pick four.
Documentation
use super::EvidenceCounter;

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct EvidencePowerOfTwoHistogram<const BUCKET_COUNT: usize> {
    buckets: [EvidenceCounter; BUCKET_COUNT],
    out_of_range: bool,
}

impl<const BUCKET_COUNT: usize> EvidencePowerOfTwoHistogram<BUCKET_COUNT> {
    pub const fn new() -> Self {
        Self {
            buckets: [EvidenceCounter::new(); BUCKET_COUNT],
            out_of_range: false,
        }
    }

    pub const fn buckets(&self) -> &[EvidenceCounter; BUCKET_COUNT] {
        &self.buckets
    }

    pub const fn out_of_range(&self) -> bool {
        self.out_of_range
    }

    pub fn valid(&self) -> bool {
        !self.out_of_range && self.buckets.iter().all(|bucket| bucket.valid())
    }

    pub fn record(&mut self, value: usize) {
        let bucket = usize::BITS.saturating_sub(value.leading_zeros()) as usize;
        let Some(counter) = self.buckets.get_mut(bucket) else {
            self.out_of_range = true;
            return;
        };
        counter.record(1);
    }

    pub fn reset(&mut self) {
        *self = Self::new();
    }
}

impl<const BUCKET_COUNT: usize> Default for EvidencePowerOfTwoHistogram<BUCKET_COUNT> {
    fn default() -> Self {
        Self::new()
    }
}