Skip to main content

int_interval_set/batch/
isize.rs

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