sampling/histogram/
histogram_int.rs

1#![allow(deprecated)]
2use{
3    crate::histogram::*,
4    num_traits::{
5        ops::{
6            checked::*, 
7            wrapping::*
8        },
9        cast::*,
10        identities::*,
11        Bounded
12    },
13    std::{
14        borrow::*,
15        ops::*,
16        num::*
17    }
18};
19
20#[cfg(feature = "serde_support")]
21use serde::{Serialize, Deserialize};
22
23
24/// # Generic Histogram for integer types
25/// 
26/// If possible, consider using [GenericHist] with [FastSingleIntBinning] or, 
27/// if your bin width is not 1, with [BinningWithWidth] instead (see [Binning::to_generic_hist]).
28/// This will likely be faster than using `HistogramInt<T>` 
29#[derive(Debug, Clone)]
30#[deprecated(since="0.2.0", note="Use GenericHist of BinningWithWidth instead")]
31#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
32pub struct HistogramInt<T>
33{
34    pub(crate) bin_borders: Vec<T>,
35    pub(crate) hist: Vec<usize>,
36}
37
38impl<T> HistogramInt<T>{
39    /// similar to `self.borders_clone` but does not allocate memory
40    pub fn borders(&self) -> &Vec<T>
41    {
42        &self.bin_borders
43    }
44
45    /// # Iterator over all the bins
46    /// In HistogramInt a bin is defined by two values: The left border (inclusive)
47    /// and the right border (exclusive)
48    /// 
49    /// Here you get an iterator which iterates over said borders.
50    /// The Iterator returns a borrowed Array of length two, where the first value is 
51    /// the left (inclusive) border and the second value is the right (exclusive) border
52    /// 
53    /// ## Example
54    /// ```
55    /// use sampling::histogram::*;
56    /// 
57    /// let hist = HistI8::new(0, 8, 4).unwrap();
58    /// let mut bin_iter = hist.bin_iter();
59    ///
60    /// assert_eq!(bin_iter.next(), Some(&[0_i8, 2]));
61    /// assert_eq!(bin_iter.next(), Some(&[2, 4]));
62    /// assert_eq!(bin_iter.next(), Some(&[4, 6]));
63    /// assert_eq!(bin_iter.next(), Some(&[6, 8]));
64    /// assert_eq!(bin_iter.next(), None);
65    /// ```
66    pub fn bin_iter(& self) -> impl Iterator<Item = &[T;2]>
67    {
68        BorderWindow::new(self.bin_borders.as_slice())
69    }
70
71    /// # Iterate over all bins
72    /// In HistogramInt a bin is defined by two values: The left border (inclusive)
73    /// and the right border (exclusive)
74    /// 
75    /// This iterates over these values as well as the corresponding hit count (i.e. how often 
76    /// the corresponding bin was hit)
77    /// ## Item of Iterator
78    /// `(&[left_border, right_border], number_of_hits)`
79    /// ## Example
80    /// ``` 
81    /// use sampling::histogram::*;
82    /// 
83    /// let mut hist = HistUsize::new(0, 6, 3).unwrap();
84    /// 
85    /// hist.increment(0).unwrap();
86    /// hist.increment(5).unwrap();
87    /// hist.increment(4).unwrap();
88    /// 
89    /// let mut iter = hist.bin_hits_iter();
90    /// assert_eq!(
91    ///     iter.next(),
92    ///     Some(
93    ///         (&[0, 2], 1)
94    ///     )
95    /// );
96    /// assert_eq!(
97    ///     iter.next(),
98    ///     Some(
99    ///         (&[2, 4], 0)
100    ///     )
101    /// );
102    /// assert_eq!(
103    ///     iter.next(),
104    ///     Some(
105    ///         (&[4, 6], 2)
106    ///     )
107    /// );
108    /// assert_eq!(iter.next(), None);
109    /// ```
110    pub fn bin_hits_iter(&self) -> impl Iterator<Item = (&[T;2], usize)>
111    {
112        self.bin_iter()
113            .zip(
114                self.hist
115                    .iter()
116                    .copied()
117            )
118    }
119
120}
121
122
123impl<T> HistogramInt<T>
124where T: Sub<T, Output=T> + Add<T, Output=T> + Ord + One + Copy + NumCast
125{
126    #[inline]
127    /// # Increment hit count 
128    /// If `val` is inside the histogram, the corresponding bin count will be increased
129    /// by 1 and the index corresponding to the bin in returned: `Ok(index)`.
130    /// Otherwise an Error is returned
131    /// ## Note
132    /// This is the same as [HistogramVal::count_val]
133    pub fn increment<V: Borrow<T>>(&mut self, val: V) -> Result<usize, HistErrors> {
134        self.count_val(val)
135    }
136
137    #[inline]
138    /// # Increment hit count
139    /// Increments the hit count of the bin corresponding to `val`.
140    /// If no bin corresponding to `val` exists, nothing happens
141    pub fn increment_quiet<V: Borrow<T>>(&mut self, val: V)
142    {
143        let _ = self.increment(val);
144    }
145}
146
147
148impl<T> HistogramInt<T>
149where T: Copy{
150    fn get_right(&self) -> T
151    {
152        self.bin_borders[self.bin_borders.len() - 1]
153    }
154}
155
156
157impl<T> HistogramInt<T> 
158where T: PartialOrd + ToPrimitive + FromPrimitive + CheckedAdd + One + HasUnsignedVersion + Bounded
159        + Sub<T, Output=T> + Mul<T, Output=T> + Zero + Copy,
160    std::ops::RangeInclusive<T>: Iterator<Item=T>,
161    T::Unsigned: Bounded + HasUnsignedVersion<LeBytes=T::LeBytes, Unsigned=T::Unsigned> 
162        + WrappingAdd + ToPrimitive + Sub<Output=T::Unsigned>
163        + std::ops::Rem<Output=T::Unsigned> + FromPrimitive + Zero
164        + std::cmp::Eq + std::ops::Div<Output=T::Unsigned>
165        + Ord + std::ops::Mul<Output=T::Unsigned> + WrappingSub + Copy,
166    std::ops::RangeInclusive<T::Unsigned>: Iterator<Item=T::Unsigned>
167{
168    /// # Create a new histogram
169    /// * `right`: exclusive border
170    /// * `left`: inclusive border
171    /// * `bins`: how many bins do you need?
172    /// # Note
173    /// * `(right - left) % bins == 0` has to be true, otherwise
174    ///     the bins cannot all have the same length!
175    pub fn new(left: T, right: T, bins: usize) -> Result<Self, HistErrors> {
176        if left >= right {
177            return Err(HistErrors::IntervalWidthZero);
178        } else if bins == 0 {
179            return Err(HistErrors::NoBins);
180        }
181        let left_u = to_u(left);
182        let right_u = to_u(right);
183        let border_difference = right_u - left_u;
184        let b = match T::Unsigned::from_usize(bins)
185        {
186            Some(val) => val,
187            None => return Err(HistErrors::IntervalWidthZero),
188        };
189        if border_difference % b != T::Unsigned::zero() {
190            return Err(HistErrors::ModuloError);
191        }
192
193        let bin_size = border_difference / b;
194
195        if bin_size <= T::Unsigned::zero() {
196            return Err(HistErrors::IntervalWidthZero);
197        }
198        
199        let hist = vec![0; bins];
200        let bin_borders: Vec<_> = (T::Unsigned::zero()..=b)
201            .map(|val| {
202                from_u(
203                    left_u + to_u(val) * bin_size
204                )
205            })
206            .collect();
207        Ok(
208            Self{
209                bin_borders,
210                hist
211            }
212        )
213    }
214    /// # Create a new histogram
215    /// * equivalent to [`Self::new(left, right + 1, bins)`](#method.new)
216    ///     (except that this method checks for possible overflow)
217    /// # Note:
218    /// * Due to implementation details, `right` cannot be `T::MAX` - 
219    ///     if you try, you will get `Err(HistErrors::Overflow)`
220    pub fn new_inclusive(left: T, right: T, bins: usize) -> Result<Self, HistErrors>
221    {
222        let right = match right.checked_add(&T::one()){
223            None => return Err(HistErrors::Overflow),
224            Some(val) => val,
225        };
226        Self::new(left, right, bins)
227    }
228}
229
230impl<T> Histogram for HistogramInt<T>
231{
232    #[inline]
233    fn bin_count(&self) -> usize {
234        self.hist.len()
235    }
236
237    #[inline]
238    fn hist(&self) -> &Vec<usize> {
239        &self.hist
240    }
241
242    #[inline]
243    fn increment_index_by(&mut self, index: usize, count: usize) -> Result<(), HistErrors> {
244        match self.hist.get_mut(index) {
245            None => Err(HistErrors::OutsideHist),
246            Some(val) => {
247                *val += count;
248                Ok(())
249            },
250        }
251    }
252
253    #[inline]
254    fn reset(&mut self) {
255        // compiles down to memset :)
256        self.hist
257            .iter_mut()
258            .for_each(|h| *h = 0);
259    }
260}
261
262impl<T> HistogramVal<T> for HistogramInt<T>
263where T: Ord + Sub<T, Output=T> + Add<T, Output=T> + One + NumCast + Copy
264{
265    fn count_val<V: Borrow<T>>(&mut self, val: V) -> Result<usize, HistErrors>
266    {
267        let id = self.get_bin_index(val)?;
268        self.increment_index(id)
269            .map(|_| id)
270    }
271
272    fn distance<V: Borrow<T>>(&self, val: V) -> f64 {
273        let val = val.borrow();
274        if self.not_inside(val) {
275            let dist = if *val < self.first_border() {
276                self.first_border() - *val
277            } else {
278                *val - self.get_right() + T::one()
279            };
280            dist.to_f64().unwrap()
281        } else {
282            0.0
283        }
284    }
285
286    #[inline]
287    fn first_border(&self) -> T {
288        self.bin_borders[0]
289    }
290
291    fn last_border(&self) -> T {
292        self.bin_borders[self.bin_borders.len() - 1]
293    }
294
295    #[inline(always)]
296    fn last_border_is_inclusive(&self) -> bool {
297        false
298    }
299
300    #[inline]
301    fn is_inside<V: Borrow<T>>(&self, val: V) -> bool {
302        let val = *val.borrow();
303        val >= self.first_border()
304            && val < self.get_right()
305    }
306
307    #[inline]
308    fn not_inside<V: Borrow<T>>(&self, val: V) -> bool {
309        let val = *val.borrow();
310        val < self.first_border()
311            || val >= self.get_right()
312    }
313
314    /// None if not inside Hist covered zone
315    fn get_bin_index<V: Borrow<T>>(&self, val: V) -> Result<usize, HistErrors>
316    {
317        let val = val.borrow();
318        if self.not_inside(val)
319        {
320            return Err(HistErrors::OutsideHist);
321        }
322
323        self.bin_borders
324            .binary_search(val.borrow())
325            .or_else(|index_m1| Ok(index_m1 - 1))
326    }
327
328    /// # consider using `self.bin_iter()` instead
329    /// * this will return an iterator over the bins for displaying purposes
330    /// * all bins are defined via an inclusive and an exclusive border
331    /// * It is more efficient to use `self.bin_iter()`instead
332    fn bin_enum_iter(&'_ self) -> Box<dyn Iterator<Item=Bin<T>> + '_> {
333        let iter = self.bin_iter()
334            .map(|[left, right]| Bin::InclusiveExclusive(*left, *right));
335        Box::new(iter)
336    }
337}
338
339impl<T> HistogramIntervalDistance<T> for HistogramInt<T> 
340where T: Ord + Sub<T, Output=T> + Add<T, Output=T> + One + NumCast + Copy
341{
342    fn interval_distance_overlap<V: Borrow<T>>(&self, val: V, overlap: NonZeroUsize) -> usize {
343        let val = val.borrow();
344        if self.not_inside(val) {
345            let num_bins_overlap = 1usize.max(self.bin_count() / overlap.get());
346            let dist = 
347            if *val < self.first_border() { 
348                self.first_border() - *val
349            } else {
350                *val - self.get_right()
351            };
352            1 + dist.to_usize().unwrap() / num_bins_overlap
353        } else {
354            0
355        }
356    }
357}
358
359impl<T> HistogramPartition for HistogramInt<T> 
360where T: Clone + std::fmt::Debug
361{
362    fn overlapping_partition(&self, n: NonZeroUsize, overlap: usize) -> Result<Vec<Self>, HistErrors>
363    {
364        let mut result = Vec::with_capacity(n.get());
365        let size = self.bin_count() - 1;
366        let denominator = n.get() + overlap;
367
368        for c in 0..n.get() {
369            let left_index = c.checked_mul(size)
370                .ok_or(HistErrors::Overflow)?
371                / denominator;
372            
373            let zaehler = c + overlap + 1;
374            let right_index = 1 + zaehler.checked_mul(size)
375                .ok_or(HistErrors::Overflow)?
376                / denominator;
377
378            if left_index >= right_index {
379                return Err(HistErrors::IntervalWidthZero);
380            }
381            
382            let borders = self
383                .borders()[left_index..=right_index]
384                .to_vec();
385            let hist = vec![0; borders.len() - 1];
386
387            let res = Self{
388                bin_borders: borders,
389                hist
390            };
391            
392            result.push(res);
393        }
394        Ok(result)
395    }
396}
397
398impl<T> IntervalOrder for HistogramInt<T>
399where T: Ord
400{
401    fn left_compare(&self, other: &Self) -> std::cmp::Ordering {
402        let self_left = &self.bin_borders[0];
403        let other_left = &other.bin_borders[0];
404        let order = self_left.cmp(other_left);
405        if order.is_eq() {
406            let self_right = self.bin_borders.last().unwrap();
407            let other_right = other.bin_borders.last().unwrap();
408            return self_right.cmp(other_right);
409        }
410        order
411    }
412}
413
414
415/// # Histogram for binning `usize` - alias for `HistogramInt<usize>`
416/// * you should use [HistUsizeFast] or [GenericHist] of [FastBinningUSIZE] instead, if your bin width is 1
417/// * Otherwise use [GenericHist] of [BinningUSIZE] instead (see [Binning::to_generic_hist])
418/// * This type still works fine, but is slower than the alternative. 
419/// * This type alias might be removed in future releases 
420#[deprecated(since="0.2.0", note="Use GenericHist of BinningUSIZE instead")]
421pub type HistUsize = HistogramInt<usize>;
422/// # Histogram for binning `u128` - alias for `HistogramInt<u128>`
423/// * you should use [HistU128Fast] or [GenericHist] of [FastBinningU128] instead, if your bin width is 1
424/// * Otherwise use [GenericHist] of [BinningU128] instead (see [Binning::to_generic_hist])
425/// * This type still works fine, but is slower than the alternative. 
426/// * This type alias might be removed in future releases 
427#[deprecated(since="0.2.0", note="Use GenericHist of BinningU128 instead")]
428pub type HistU128 = HistogramInt<u128>;
429/// # Histogram for binning `u64` - alias for `HistogramInt<u64>`
430/// * you should use [HistU64Fast] or [GenericHist] of [FastBinningU64] instead, if your bin width is 1
431/// * Otherwise use [GenericHist] of [BinningU64] instead (see [Binning::to_generic_hist])
432/// * This type still works fine, but is slower than the alternative. 
433/// * This type alias might be removed in future releases 
434#[deprecated(since="0.2.0", note="Use GenericHist of BinningU64 instead")]
435pub type HistU64 = HistogramInt<u64>;
436/// # Histogram for binning `u32` - alias for `HistogramInt<u32>`
437/// * you should use [HistU32Fast] or [GenericHist] of [FastBinningU32] instead, if your bin width is 1
438/// * Otherwise use [GenericHist] of [BinningU32] instead (see [Binning::to_generic_hist])
439/// * This type still works fine, but is slower than the alternative. 
440/// * This type alias might be removed in future releases 
441#[deprecated(since="0.2.0", note="Use GenericHist of BinningU32 instead")]
442pub type HistU32 = HistogramInt<u32>;
443/// # Histogram for binning `u16` - alias for `HistogramInt<u16>`
444/// * you should use [HistU16Fast] or [GenericHist] of [FastBinningU16] instead, if your bin width is 1
445/// * Otherwise use [GenericHist] of [BinningU16] instead (see [Binning::to_generic_hist])
446/// * This type still works fine, but is slower than the alternative. 
447/// * This type alias might be removed in future releases 
448#[deprecated(since="0.2.0", note="Use GenericHist of BinningU16 instead")]
449pub type HistU16 = HistogramInt<u16>;
450/// # Histogram for binning `u8` - alias for `HistogramInt<u8>`
451/// * you should use [HistU8Fast] or [GenericHist] of [FastBinningU8] instead, if your bin width is 1
452/// * Otherwise use [GenericHist] of [BinningU8] instead (see [Binning::to_generic_hist])
453/// * This type still works fine, but is slower than the alternative. 
454/// * This type alias might be removed in future releases 
455#[deprecated(since="0.2.0", note="Use GenericHist of BinningU8 instead")]
456pub type HistU8 = HistogramInt<u8>;
457
458/// # Histogram for binning `isize` - alias for `HistogramInt<isize>`
459/// * you should use [HistIsizeFast] or [GenericHist] of [FastBinningISIZE] instead, if your bin width is 1
460/// * Otherwise use [GenericHist] of [BinningISIZE] instead (see [Binning::to_generic_hist])
461/// * This type still works fine, but is slower than the alternative. 
462/// * This type alias might be removed in future releases 
463#[deprecated(since="0.2.0", note="Use GenericHist of BinningISIZE instead")]
464pub type HistIsize = HistogramInt<isize>;
465/// # Histogram for binning `i128` - alias for `HistogramInt<i128>`
466/// * you should use [HistI128Fast] or [GenericHist] of [FastBinningI128] instead, if your bin width is 1
467/// * Otherwise use [GenericHist] of [BinningI128] instead (see [Binning::to_generic_hist])
468/// * This type still works fine, but is slower than the alternative. 
469/// * This type alias might be removed in future releases 
470#[deprecated(since="0.2.0", note="Use GenericHist of BinningI128 instead")]
471pub type HistI128 = HistogramInt<i128>;
472/// # Histogram for binning `i64` - alias for `HistogramInt<i64>`
473/// * you should use [HistI64Fast] or [GenericHist] of [FastBinningI64] instead, if your bin width is 1
474/// * Otherwise use [GenericHist] of [BinningI64] instead (see [Binning::to_generic_hist])
475/// * This type still works fine, but is slower than the alternative. 
476/// * This type alias might be removed in future releases 
477#[deprecated(since="0.2.0", note="Use GenericHist of BinningI64 instead")]
478pub type HistI64 = HistogramInt<i64>;
479/// # Histogram for binning `i32` - alias for `HistogramInt<i32>`
480/// * you should use [HistI32Fast] or [GenericHist] of [FastBinningI32] instead, if your bin width is 1
481/// * Otherwise use [GenericHist] of [BinningI32] instead (see [Binning::to_generic_hist])
482/// * This type still works fine, but is slower than the alternative. 
483/// * This type alias might be removed in future releases 
484#[deprecated(since="0.2.0", note="Use GenericHist of BinningI32 instead")]
485pub type HistI32 = HistogramInt<i32>;
486/// # Histogram for binning `i16` - alias for `HistogramInt<i16>`
487/// * you should use [HistI16Fast] or [GenericHist] of [FastBinningI16] instead, if your bin width is 1
488/// * Otherwise use [GenericHist] of [BinningI16] instead (see [Binning::to_generic_hist])
489/// * This type still works fine, but is slower than the alternative. 
490/// * This type alias might be removed in future releases 
491#[deprecated(since="0.2.0", note="Use GenericHist of BinningI16 instead")]
492pub type HistI16 = HistogramInt<i16>;
493/// # Histogram for binning `i8` - alias for `HistogramInt<i8>`
494/// * you should use [HistI8Fast] or [GenericHist] of [FastBinningI8] instead, if your bin width is 1
495/// * Otherwise use [GenericHist] of [BinningI8] instead (see [Binning::to_generic_hist])
496/// * This type still works fine, but is slower than the alternative. 
497/// * This type alias might be removed in future releases 
498#[deprecated(since="0.2.0", note="Use GenericHist of BinningI8 instead")]
499pub type HistI8 = HistogramInt<i8>;
500
501#[cfg(test)]
502mod tests{
503    use super::*;
504    use rand::{SeedableRng, distributions::*};
505    use rand_pcg::Pcg64Mcg;
506    use num_traits::Bounded;
507    fn hist_test_normal<T>(left: T, right: T)
508    where T: num_traits::Bounded + PartialOrd + CheckedSub 
509        + CheckedAdd + Zero + Ord + HasUnsignedVersion
510        + One + NumCast + Copy + FromPrimitive + Bounded,
511    std::ops::RangeInclusive<T>: Iterator<Item=T>,
512    T::Unsigned: Bounded + HasUnsignedVersion<LeBytes=T::LeBytes, Unsigned=T::Unsigned> 
513        + WrappingAdd + ToPrimitive + Sub<Output=T::Unsigned>
514        + std::ops::Rem<Output=T::Unsigned> + FromPrimitive + Zero
515        + std::cmp::Eq + std::ops::Div<Output=T::Unsigned>
516        + Ord + std::ops::Mul<Output=T::Unsigned> + WrappingSub + Copy,
517    std::ops::RangeInclusive<T::Unsigned>: Iterator<Item=T::Unsigned>,
518    HistogramInt::<T>: std::fmt::Debug,
519    {
520        let bin_count = (to_u(right) - to_u(left)).to_usize().unwrap() + 1;
521        let hist_wrapped =  HistogramInt::<T>::new_inclusive(left, right, bin_count);
522       
523        let mut hist = hist_wrapped.unwrap();
524        assert!(hist.not_inside(T::max_value()));
525        assert!(hist.not_inside(T::min_value()));
526        for (id, i) in (left..=right).enumerate() {
527            assert!(hist.is_inside(i));
528            assert_eq!(hist.is_inside(i), !hist.not_inside(i));
529            assert!(hist.get_bin_index(i).unwrap() == id);
530            assert_eq!(hist.distance(i), 0.0);
531            assert_eq!(hist.interval_distance_overlap(i, unsafe{NonZeroUsize::new_unchecked(2)}), 0);
532            hist.count_val(i).unwrap();
533        }
534        let lm1 = left - T::one();
535        let rp1 = right + T::one();
536        assert!(hist.not_inside(lm1));
537        assert!(hist.not_inside(rp1));
538        assert_eq!(hist.is_inside(lm1), !hist.not_inside(lm1));
539        assert_eq!(hist.is_inside(rp1), !hist.not_inside(rp1));
540        assert_eq!(hist.distance(lm1), 1.0);
541        assert_eq!(hist.distance(rp1), 1.0);
542        let one = unsafe{NonZeroUsize::new_unchecked(1)};
543        assert_eq!(hist.interval_distance_overlap(rp1, one), 1);
544        assert_eq!(hist.interval_distance_overlap(lm1, one), 1);
545        let borders: Vec<_> = hist.bin_enum_iter()
546            .map(
547                |bin|
548                {
549                    match bin {
550                        Bin::InclusiveExclusive(left, right) => (left, right),
551                        _ => unreachable!()
552                    }
553                }
554            ).collect();
555        assert_eq!(borders.len(), hist.bin_count());
556        assert_eq!(
557            HistogramInt::<T>::new_inclusive(left, T::max_value(), bin_count).expect_err("err"),
558            HistErrors::Overflow
559        );
560    }
561
562
563    #[test]
564    fn hist_normal()
565    {
566        hist_test_normal(20usize, 31usize);
567        hist_test_normal(-23isize, 31isize);
568        hist_test_normal(-23i16, 31);
569        hist_test_normal(1u8, 3u8);
570        hist_test_normal(123u128, 300u128);
571        hist_test_normal(-123i128, 300i128);
572
573        hist_test_normal(i8::MIN + 1, i8::MAX - 1);
574    }
575
576    #[test]
577    fn hist_index(){
578        let hist = HistogramInt::<isize>::new(0, 20, 2).unwrap();
579        assert_eq!(hist.borders(), &[0_isize, 10, 20]);
580        for i in 0..=9
581        {
582            assert_eq!(hist.get_bin_index(i).unwrap(), 0);
583        }
584        for i in 10..20 {
585            assert_eq!(hist.get_bin_index(i).unwrap(), 1);
586        }
587        assert!(hist.get_bin_index(20).is_err());
588    }
589
590    /// This test makes sure, that HistogramInt and HistogramFast return the same partitions,
591    /// when the histograms are equivalent
592    #[allow(deprecated)]
593    #[test]
594    fn overlapping_partition_test()
595    {
596
597        let mut rng = Pcg64Mcg::seed_from_u64(2314668);
598        let uni = Uniform::new_inclusive(-100, 100);
599        let uni_n = Uniform::new_inclusive(1, 16);
600
601        for overlap in 0..=5 {
602            for _ in 0..100 {
603                let n: usize = uni_n.sample(&mut rng);
604                let (left, right) = loop {
605                    let mut num_1 = uni.sample(&mut rng);
606                    let mut num_2 = uni.sample(&mut rng);
607    
608                    if num_1 != num_2 {
609                        if num_2 < num_1 {
610                            std::mem::swap(&mut num_1, &mut num_2);
611                        }
612                        if (num_2 as isize - num_1 as isize) < (overlap as isize + 1) {
613                            continue;
614                        }
615                        break (num_1, num_2)
616                    }
617                };
618    
619                let hist_fast = HistI8Fast::new_inclusive(left, right).unwrap();
620                let hist_i = HistI8::new_inclusive(left, right, hist_fast.bin_count()).unwrap();
621                let n_non_zero = NonZeroUsize::new(n).unwrap();
622        
623                let overlapping_f = hist_fast.overlapping_partition(n_non_zero, overlap);
624                let overlapping_i = hist_i.overlapping_partition(n_non_zero, overlap);
625
626                if overlapping_i.is_err() {
627                    assert_eq!(overlapping_f.unwrap_err(), overlapping_i.unwrap_err());
628                    continue;
629                }
630
631                let overlapping_i = overlapping_i.unwrap();
632                let overlapping_f = overlapping_f.unwrap();
633
634                let len = overlapping_i.len();
635
636                for (index,(a, b)) in overlapping_f
637                    .into_iter()
638                    .zip(overlapping_i)
639                    .enumerate()
640                {
641                    let bins_a: Vec<_> = a
642                        .bin_enum_iter()
643                        .map(
644                            |bin|
645                            {
646                                match bin{
647                                    Bin::SingleValued(val) => val,
648                                    _ => unreachable!()
649                                }
650                            }
651                        ).collect();
652
653                    assert_eq!(bins_a.len(), a.hist().len());
654                    
655                    let bins_b: Vec<_> = b
656                        .bin_enum_iter()
657                        .map(
658                            |bin|
659                            {
660                                match bin{
661                                    Bin::InclusiveExclusive(left, right) => (left, right),
662                                    _ => unreachable!()
663                                }
664                            }
665                        ).collect();
666
667                    assert_eq!(bins_b.len(), b.hist().len());
668
669                    if bins_a.len() != bins_b.len()
670                    {
671                        println!("Fast: {} SLOW {}", a.bin_count(), b.bin_count());
672                        dbg!(left, right, overlap);
673                        dbg!(hist_i.bin_count(), hist_fast.bin_count());
674                        dbg!(&bins_b, &bins_a);
675                        eprintln!("index: {} of {}", index, len);
676                    }
677
678                    assert_eq!(bins_a.len(), bins_b.len());
679                    assert_eq!(a.bin_count(), b.bin_count());
680        
681                    for (b_a, b_b) in bins_a.into_iter().zip(bins_b)
682                    {
683                        assert_eq!((b_a, b_a + 1), b_b);
684                    }
685                }
686            }
687        }
688        
689    }
690
691    /// Check, that the range of the overlapping intervals contain the whole original interval
692    #[allow(deprecated)]
693    #[test]
694    fn overlapping_partition_test2()
695    {
696        let mut rng = Pcg64Mcg::seed_from_u64(231468);
697        let uni = Uniform::new_inclusive(-100, 100);
698        let uni_n = Uniform::new_inclusive(2, 6);
699        for overlap in 0..=5 {
700            for _ in 0..100 {
701                let n: usize = uni_n.sample(&mut rng);
702                let (left, right) = loop {
703                    let mut num_1 = uni.sample(&mut rng);
704                    let mut num_2 = uni.sample(&mut rng);
705
706                    if num_1 != num_2 {
707                        if num_2 < num_1 {
708                            std::mem::swap(&mut num_1, &mut num_2);
709                        }
710                        if (num_2 as isize - num_1 as isize) < (overlap as isize + 1) {
711                            continue;
712                        }
713                        break (num_1, num_2)
714                    }
715                };
716                let hist_fast = HistI8Fast::new_inclusive(left, right).unwrap();
717                let hist_i = HistI8::new_inclusive(left, right, hist_fast.bin_count()).unwrap();
718                let overlapping_i = hist_i.overlapping_partition(NonZeroUsize::new(n).unwrap(), overlap)
719                    .unwrap();
720
721                assert_eq!(
722                    overlapping_i.last().unwrap().borders().last(),
723                    hist_i.borders().last()
724                );
725
726                assert_eq!(
727                    overlapping_i.first().unwrap().borders().first(),
728                    hist_i.borders().first()
729                );
730            }
731        }
732    }
733
734    /// Check, that the range of the overlapping intervals contain the whole original interval
735    /// Different binsize than the other test
736    #[allow(deprecated)]
737    #[test]
738    fn overlapping_partition_test3()
739    {
740        let mut rng = Pcg64Mcg::seed_from_u64(23148);
741        let uni = Uniform::new_inclusive(-300, 300);
742        let uni_n = Uniform::new_inclusive(2, 4);
743        for binsize in 2..=7 {
744            for overlap in 0..=5 {
745                for _ in 0..100 {
746                    let n: usize = uni_n.sample(&mut rng);
747                    let (left, right) = loop {
748                        let mut num_1 = uni.sample(&mut rng);
749                        let mut num_2 = uni.sample(&mut rng);
750    
751                        if num_1 != num_2 {
752                            if num_2 < num_1 {
753                                std::mem::swap(&mut num_1, &mut num_2);
754                            }
755                            if (num_2 as isize - num_1 as isize) < (overlap as isize + 1) {
756                                continue;
757                            }
758                            let hist_fast = HistI16Fast::new_inclusive(num_1, num_2).unwrap();
759                            if hist_fast.bin_count() % binsize != 0 {
760                                continue;
761                            }
762                            break (num_1, num_2)
763                        }
764                    };
765                    let hist_fast = HistI16Fast::new_inclusive(left, right).unwrap();
766                    let hist_i = HistI16::new_inclusive(left, right, hist_fast.bin_count() / binsize).unwrap();
767                    let overlapping_i = hist_i.overlapping_partition(NonZeroUsize::new(n).unwrap(), overlap)
768                        .unwrap();
769                    
770                    assert_eq!(
771                        overlapping_i.last().unwrap().borders().last(),
772                        hist_i.borders().last()
773                    );
774    
775                    assert_eq!(
776                        overlapping_i.first().unwrap().borders().first(),
777                        hist_i.borders().first()
778                    );
779                }
780            }
781        }
782        
783    }
784
785    #[allow(deprecated)]
786    #[test]
787    fn bin_iter_test()
788    {
789        let hist = HistI16::new(0, 4, 4).unwrap();
790
791        let mut bin_iter = hist.bin_iter();
792
793        assert_eq!(bin_iter.next(), Some(&[0_i16, 1_i16]));
794        assert_eq!(bin_iter.next(), Some(&[1_i16, 2_i16]));
795        assert_eq!(bin_iter.next(), Some(&[2_i16, 3_i16]));
796        assert_eq!(bin_iter.next(), Some(&[3_i16, 4_i16]));
797        assert_eq!(bin_iter.next(), None);
798
799        let hist = HistU8::new(0,8, 4).unwrap();
800
801        let mut bin_iter = hist.bin_iter();
802
803        assert_eq!(bin_iter.next(), Some(&[0_u8, 2_u8]));
804        assert_eq!(bin_iter.next(), Some(&[2_u8, 4_u8]));
805        assert_eq!(bin_iter.next(), Some(&[4_u8, 6_u8]));
806        assert_eq!(bin_iter.next(), Some(&[6_u8, 8_u8]));
807        assert_eq!(bin_iter.next(), None);
808    }
809}