Skip to main content

int_interval_set/batch/
usize.rs

1// -----------------------------------------------------------------------------
2// @generated by xtask/codegen (--batch --unsigned)
3// DO NOT EDIT MANUALLY.
4// Changes will be overwritten.
5// -----------------------------------------------------------------------------
6
7#[cfg(test)]
8mod membership_queries_tests;
9#[cfg(test)]
10mod statistics_tests;
11
12use int_interval::UsizeCO;
13
14#[derive(Clone, Debug, Default, PartialEq, Eq)]
15#[repr(transparent)]
16pub struct UsizeCOBatchSet(Vec<UsizeCO>);
17
18// ============================================================
19// conversions / views
20// ============================================================
21
22impl UsizeCOBatchSet {
23    #[inline]
24    pub fn into_inner(self) -> Vec<UsizeCO> {
25        self.0
26    }
27
28    #[inline]
29    pub fn as_slice(&self) -> &[UsizeCO] {
30        &self.0
31    }
32}
33
34// ============================================================
35// membership queries
36// ============================================================
37
38impl UsizeCOBatchSet {
39    #[inline]
40    pub fn contains_interval(&self, iv: UsizeCO) -> bool {
41        let slice = self.as_slice();
42        let i = slice.partition_point(|seg| seg.start() <= iv.start());
43        i > 0 && slice[i - 1].contains_interval(iv)
44    }
45
46    #[inline]
47    pub fn contains_point(&self, x: usize) -> bool {
48        let slice = self.as_slice();
49        let i = slice.partition_point(|seg| seg.start() <= x);
50        i > 0 && slice[i - 1].contains(x)
51    }
52
53    #[inline]
54    pub fn interval_containing_point(&self, x: usize) -> Option<UsizeCO> {
55        let slice = self.as_slice();
56        let i = slice.partition_point(|seg| seg.start() <= x);
57
58        if i == 0 {
59            return None;
60        }
61
62        let iv = slice[i - 1];
63        iv.contains(x).then_some(iv)
64    }
65
66    #[inline]
67    pub fn intersects(&self, q: UsizeCO) -> bool {
68        let slice = self.as_slice();
69        let i = slice.partition_point(|seg| seg.start() < q.end_excl());
70
71        if i == 0 {
72            return false;
73        }
74
75        let mut j = i - 1;
76        while j < slice.len() {
77            let iv = slice[j];
78            if iv.start() >= q.end_excl() {
79                break;
80            }
81            if iv.intersects(q) {
82                return true;
83            }
84            j += 1;
85        }
86
87        false
88    }
89}
90
91// ============================================================
92// iteration
93// ============================================================
94
95impl UsizeCOBatchSet {
96    #[inline]
97    pub fn iter_intervals(&self) -> impl Iterator<Item = UsizeCO> {
98        self.as_slice().iter().copied()
99    }
100
101    #[inline]
102    pub fn iter_points(&self) -> impl Iterator<Item = usize> {
103        self.iter_intervals().flat_map(UsizeCO::iter)
104    }
105}
106
107// ============================================================
108// statistics / coverage
109// ============================================================
110
111impl UsizeCOBatchSet {
112    #[inline]
113    pub fn interval_count(&self) -> usize {
114        self.0.len() as usize
115    }
116
117    #[inline]
118    pub fn point_count(&self) -> usize {
119        self.0.iter().map(|iv| iv.len()).sum()
120    }
121
122    #[inline]
123    pub fn coverage_len_of(&self, q: UsizeCO) -> usize {
124        let slice = self.as_slice();
125        let mut i = slice.partition_point(|seg| seg.start() < q.start());
126        i = i.saturating_sub(1);
127
128        let mut acc = 0usize;
129        while i < slice.len() {
130            let iv = slice[i];
131            if iv.start() >= q.end_excl() {
132                break;
133            }
134
135            if let Some(overlap) = iv.intersection(q) {
136                acc += overlap.len();
137            }
138
139            i += 1;
140        }
141
142        acc
143    }
144
145    #[inline]
146    pub fn coverage_ratio_of(&self, q: UsizeCO) -> f32 {
147        self.coverage_len_of(q) as f32 / q.len() as f32
148    }
149}
150
151// ============================================================
152// normalization / construction
153// ============================================================
154
155mod construction {
156    use super::*;
157
158    #[inline]
159    fn normalize(mut xs: Vec<UsizeCO>) -> Vec<UsizeCO> {
160        if xs.len() <= 1 {
161            return xs;
162        }
163
164        xs.sort_unstable_by(|a, b| {
165            a.start()
166                .cmp(&b.start())
167                .then(a.end_excl().cmp(&b.end_excl()))
168        });
169
170        let mut out = Vec::with_capacity(xs.len());
171
172        for iv in xs {
173            match out.last_mut() {
174                None => out.push(iv),
175                Some(last) => {
176                    if last.is_contiguous_with(iv) {
177                        *last = last.convex_hull(iv);
178                    } else {
179                        out.push(iv);
180                    }
181                }
182            }
183        }
184
185        out
186    }
187
188    impl From<Vec<UsizeCO>> for UsizeCOBatchSet {
189        #[inline]
190        fn from(value: Vec<UsizeCO>) -> Self {
191            Self(normalize(value))
192        }
193    }
194
195    impl<const N: usize> From<[UsizeCO; N]> for UsizeCOBatchSet {
196        #[inline]
197        fn from(value: [UsizeCO; N]) -> Self {
198            Self::from(Vec::from(value))
199        }
200    }
201
202    impl FromIterator<UsizeCO> for UsizeCOBatchSet {
203        #[inline]
204        fn from_iter<T: IntoIterator<Item = UsizeCO>>(iter: T) -> Self {
205            Self::from(iter.into_iter().collect::<Vec<_>>())
206        }
207    }
208}