1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
use super::*;
use std::{
    marker::PhantomData,
    borrow::Borrow
};


/// # Provides Histogram functionallity
/// * Is automatically implemented for any type that implements Binning
pub struct GenericHist<B, T>{
    /// The binning
    binning: B,
    /// Here we count the hits of the histogram
    hits: Vec<usize>,
    /// type that is counted
    phantom: PhantomData<T>
}

impl<B, T> GenericHist<B, T> 
where B: Binning<T>{
    /// Create a new histogram from an arbitrary binning
    pub fn new(binning: B) -> Self{
        Self{
            hits: vec![0; binning.get_bin_len()],
            binning ,
            phantom: PhantomData
        }
    }

    /// Get reference to underlying binning
    pub fn binning(&self) -> &B
    {
        &self.binning
    }
}

impl<B, T> Histogram for GenericHist<B, T>
where B: Binning<T> {
    fn hist(&self) -> &Vec<usize> {
        &self.hits
    }

    #[inline]
    fn any_bin_zero(&self) -> bool {
        self.hits.iter().any(|h| *h == 0)
    }

    fn bin_count(&self) -> usize {
        debug_assert_eq!(self.binning.get_bin_len(), self.hits.len());
        self.hits.len()
    }

    #[inline]
    fn count_index(&mut self, index: usize) -> Result<(), HistErrors> {
        let entry = self.hits
            .get_mut(index)
            .ok_or(HistErrors::OutsideHist)?;
        *entry += 1;
        Ok(())
    }

    #[inline]
    fn count_multiple_index(&mut self, index: usize, count: usize) -> Result<(), HistErrors> {
        let entry = self.hits
            .get_mut(index)
            .ok_or(HistErrors::OutsideHist)?;
        *entry += count;
        Ok(())
    }

    fn reset(&mut self) {
        self.hits.iter_mut().for_each(|val| *val = 0);
    }
}

impl<T,B> HistogramVal<T> for GenericHist<B, T>
where B: Binning<T>
{
    #[inline(always)]
    fn get_bin_index<V: Borrow<T>>(&self, val: V) -> Result<usize, HistErrors> {
        self.binning.get_bin_index(val)
            .ok_or(HistErrors::OutsideHist)
    }

    fn first_border(&self) -> T {
        self.binning.first_border()
    }

    fn is_inside<V: Borrow<T>>(&self, val: V) -> bool {
        self.binning.is_inside(val)
    }

    #[inline(always)]
    fn count_val<V: Borrow<T>>(&mut self, val: V) -> Result<usize, HistErrors> {
        let index = self.get_bin_index(val)?;
        self.count_index(index)
            .map(|_| index)
    }

    fn not_inside<V: Borrow<T>>(&self, val: V) -> bool {
        self.binning.not_inside(val)
    }

    fn last_border(&self) -> T {
        self.binning.last_border()
    }

    #[inline]
    fn last_border_is_inclusive(&self) -> bool {
        self.binning.last_border_is_inclusive()
    }

    fn distance<V: Borrow<T>>(&self, val: V) -> f64 {
        self.binning.distance(val)
    }

    fn bin_enum_iter(&self) -> Box<dyn Iterator<Item=Bin<T>>> {
        self.binning().bin_iter()
    }
}