hyperloglog_rs/
array_default.rs

1//! This module contains the `ArrayDefault` trait, which is used to set the default value of an array.
2//! This trait is necessary as the standard library only provides a `Default` implementation for arrays
3//! of limited length, while we need this for objects of several differenty lengths.
4use crate::prelude::Primitive;
5
6pub trait ArrayDefault<T> {
7    fn default_array() -> Self;
8}
9
10pub trait ArrayIter<T: Default + PartialEq> {
11    type Iter<'a>: Iterator<Item = &'a T> + DoubleEndedIterator + ExactSizeIterator
12    where
13        Self: 'a,
14        T: 'a;
15    type IterMut<'a>: Iterator<Item = &'a mut T> + DoubleEndedIterator + ExactSizeIterator
16    where
17        Self: 'a,
18        T: 'a;
19    type IntoIter: Iterator<Item = T> + DoubleEndedIterator + ExactSizeIterator;
20
21    fn into_iter_elements(self) -> Self::IntoIter;
22    fn iter_elements(&self) -> Self::Iter<'_>;
23    fn iter_elements_mut(&mut self) -> Self::IterMut<'_>;
24    fn len(&self) -> usize;
25    fn last(&self) -> Option<&T>;
26    fn reset(&mut self) {
27        for element in self.iter_elements_mut() {
28            *element = T::default();
29        }
30    }
31    fn is_empty(&self) -> bool {
32        self.len() == 0
33    }
34    /// Returns the first element that is not equal to the default value.
35    fn first_non_zero_index(&self) -> Option<usize> {
36        self.iter_elements().position(|a| *a != T::default())
37    }
38    /// Returns the last element that is not equal to the default value.
39    fn last_non_zero_index(&self) -> Option<usize> {
40        self.iter_elements().rposition(|a| *a != T::default())
41    }
42}
43
44pub trait ArrayIterArgmin<T>: ArrayIter<T>
45where
46    T: PartialOrd + PartialEq + Default,
47{
48    /// Returns the index of the element with the smallest value.
49    fn argmin(&self) -> Option<usize> {
50        self.iter_elements()
51            .enumerate()
52            .min_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap())
53            .map(|(i, _)| i)
54    }
55
56    /// Returns the index of the element with the smallest value that is not equal to the default value.
57    fn non_zero_argmin(&self) -> Option<usize> {
58        self.iter_elements()
59            .enumerate()
60            .filter(|(_, a)| **a != T::default())
61            .min_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap())
62            .map(|(i, _)| i)
63    }
64}
65
66pub trait ArrayIterArgmax<T>: ArrayIter<T>
67where
68    T: PartialOrd + PartialEq + Default,
69{
70    /// Returns the index of the element with the largest value.
71    fn argmax(&self) -> Option<usize> {
72        self.iter_elements()
73            .enumerate()
74            .max_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap())
75            .map(|(i, _)| i)
76    }
77
78    /// Returns the index of the element with the largest value that is not equal to the default value.
79    fn non_zero_argmax(&self) -> Option<usize> {
80        self.iter_elements()
81            .enumerate()
82            .filter(|(_, a)| **a != T::default())
83            .max_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap())
84            .map(|(i, _)| i)
85    }
86}
87
88impl<T: Default + Copy, const N: usize> ArrayDefault<T> for [T; N] {
89    #[inline(always)]
90    fn default_array() -> Self {
91        [T::default(); N]
92    }
93}
94
95pub trait PrimitiveArray<T> {
96    type Array;
97
98    fn convert_array(&self) -> Self::Array;
99}
100
101impl<F: Copy + Primitive<T>, T: Default + Copy, const N: usize> PrimitiveArray<T> for [F; N] {
102    type Array = [T; N];
103
104    #[inline(always)]
105    fn convert_array(&self) -> Self::Array {
106        let mut array = [T::default(); N];
107        for (src, dst) in self.iter().zip(array.iter_mut()) {
108            *dst = src.convert();
109        }
110        array
111    }
112}
113
114impl<T: PartialOrd + Default, const N: usize> ArrayIterArgmin<T> for [T; N] {}
115impl<T: PartialOrd + Default, const N: usize> ArrayIterArgmax<T> for [T; N] {}
116
117impl<T: Default + PartialEq, const N: usize> ArrayIter<T> for [T; N] {
118    type Iter<'a> = core::slice::Iter<'a, T> where Self: 'a;
119    type IterMut<'a> = core::slice::IterMut<'a, T> where Self: 'a;
120    type IntoIter = core::array::IntoIter<T, N>;
121
122    #[inline(always)]
123    fn into_iter_elements(self) -> Self::IntoIter {
124        self.into_iter()
125    }
126
127    #[inline(always)]
128    fn iter_elements(&self) -> Self::Iter<'_> {
129        self.iter()
130    }
131
132    #[inline(always)]
133    fn iter_elements_mut(&mut self) -> Self::IterMut<'_> {
134        self.iter_mut()
135    }
136
137    #[inline(always)]
138    fn len(&self) -> usize {
139        N
140    }
141
142    #[inline(always)]
143    fn last(&self) -> Option<&T> {
144        <[T]>::last(self)
145    }
146}