sdset/multi/
intersection.rs1use std::cmp;
2use crate::set::{Set, vec_sets_into_slices};
3use crate::{SetOperation, Collection, exponential_offset_ge};
4
5use self::Equality::*;
6
7#[derive(Clone)]
30pub struct Intersection<'a, T: 'a> {
31 slices: Vec<&'a [T]>,
32}
33
34impl<'a, T> Intersection<'a, T> {
35 pub fn new(slices: Vec<&'a Set<T>>) -> Self {
37 Self {
38 slices: vec_sets_into_slices(slices),
39 }
40 }
41}
42
43enum Equality<'a, T: 'a> {
44 NotEqual(&'a T),
45 Equal(&'a T),
46}
47
48#[inline]
49fn test_equality<'a, T: Ord>(slices: &[&'a [T]]) -> Equality<'a, T> {
50 let mut is_equal = true;
51 let mut max = &slices[0][0];
52 for x in slices {
53 let x = &x[0];
54 if is_equal { is_equal = max == x }
55 max = cmp::max(max, x);
56 }
57 if is_equal { Equal(max) } else { NotEqual(max) }
58}
59
60impl<'a, T: Ord> Intersection<'a, T> {
61 #[inline]
62 fn extend_collection<C, U, F>(mut self, output: &mut C, push: F)
63 where C: Collection<U>,
64 F: Fn(&mut C, &'a T)
65 {
66 if self.slices.is_empty() { return }
67 if self.slices.iter().any(|s| s.is_empty()) { return }
68
69 loop {
70 match test_equality(&self.slices) {
71 Equal(x) => {
72 push(output, x);
73 for slice in &mut self.slices {
74 *slice = &slice[1..];
75 if slice.is_empty() { return }
76 }
77 },
78 NotEqual(x) => {
79 for slice in &mut self.slices {
80 *slice = exponential_offset_ge(slice, x);
81 if slice.is_empty() { return }
82 }
83 }
84 }
85 }
86 }
87}
88
89impl<'a, T: Ord + Clone> SetOperation<T> for Intersection<'a, T> {
90 fn extend_collection<C>(self, output: &mut C) where C: Collection<T> {
91 self.extend_collection(output, |v, x| v.push(x.clone()))
92 }
93}
94
95impl<'a, T: Ord> SetOperation<&'a T> for Intersection<'a, T> {
96 fn extend_collection<C>(self, output: &mut C) where C: Collection<&'a T> {
97 self.extend_collection(output, Collection::push)
98 }
99}
100
101#[cfg(test)]
102mod tests {
103 use super::*;
104 use crate::set::{sort_dedup_vec, SetBuf};
105
106 #[test]
107 fn no_slice() {
108 let intersection_: SetBuf<i32> = Intersection { slices: vec![] }.into_set_buf();
109 assert_eq!(&intersection_[..], &[]);
110 }
111
112 #[test]
113 fn one_empty_slice() {
114 let a: &[i32] = &[];
115
116 let intersection_: SetBuf<i32> = Intersection { slices: vec![a] }.into_set_buf();
117 assert_eq!(&intersection_[..], &[]);
118 }
119
120 #[test]
121 fn one_slice() {
122 let a = &[1, 2, 3];
123
124 let intersection_: SetBuf<i32> = Intersection { slices: vec![a] }.into_set_buf();
125 assert_eq!(&intersection_[..], &[1, 2, 3]);
126 }
127
128 #[test]
129 fn two_slices() {
130 let a = &[1, 2, 3];
131 let b = &[2, 3, 4];
132
133 let intersection_: SetBuf<i32> = Intersection { slices: vec![a, b] }.into_set_buf();
134 assert_eq!(&intersection_[..], &[2, 3]);
135 }
136
137 #[test]
138 fn three_slices() {
139 let a = &[1, 2, 3];
140 let b = &[2, 3, 4];
141 let c = &[3, 4, 5];
142
143 let intersection_: SetBuf<i32> = Intersection { slices: vec![a, b, c] }.into_set_buf();
144 assert_eq!(&intersection_[..], &[3]);
145 }
146
147 quickcheck! {
148 fn qc_intersection(xss: Vec<Vec<i32>>) -> bool {
149 use std::collections::BTreeSet;
150 use std::iter::FromIterator;
151
152 let mut xss = xss;
154
155 for xs in &mut xss {
156 sort_dedup_vec(xs);
157 }
158
159 let x: SetBuf<i32> = {
160 let xss = xss.iter().map(|xs| xs.as_slice()).collect();
161 Intersection { slices: xss }.into_set_buf()
162 };
163
164 let mut xss = xss.into_iter();
165 let mut y = match xss.next() {
166 Some(xs) => BTreeSet::from_iter(xs),
167 None => BTreeSet::new(),
168 };
169
170 for v in xss {
171 let x = BTreeSet::from_iter(v.iter().cloned());
172 y = y.intersection(&x).cloned().collect();
173 }
174 let y: Vec<_> = y.into_iter().collect();
175
176 x.as_slice() == y.as_slice()
177 }
178 }
179}
180
181#[cfg(all(feature = "unstable", test))]
182mod bench {
183 extern crate test;
184 use super::*;
185 use self::test::Bencher;
186 use crate::set::SetBuf;
187
188 #[bench]
189 fn two_slices_big(bench: &mut Bencher) {
190 let a: Vec<_> = (0..100).collect();
191 let b: Vec<_> = (1..101).collect();
192
193 bench.iter(|| {
194 let intersection_: SetBuf<i32> = Intersection { slices: vec![&a, &b] }.into_set_buf();
195 test::black_box(|| intersection_);
196 });
197 }
198
199 #[bench]
200 fn two_slices_big2(bench: &mut Bencher) {
201 let a: Vec<_> = (0..100).collect();
202 let b: Vec<_> = (51..151).collect();
203
204 bench.iter(|| {
205 let intersection_: SetBuf<i32> = Intersection { slices: vec![&a, &b] }.into_set_buf();
206 test::black_box(|| intersection_);
207 });
208 }
209
210 #[bench]
211 fn two_slices_big3(bench: &mut Bencher) {
212 let a: Vec<_> = (0..100).collect();
213 let b: Vec<_> = (100..200).collect();
214
215 bench.iter(|| {
216 let intersection_: SetBuf<i32> = Intersection { slices: vec![&a, &b] }.into_set_buf();
217 test::black_box(|| intersection_);
218 });
219 }
220
221 #[bench]
222 fn three_slices_big(bench: &mut Bencher) {
223 let a: Vec<_> = (0..100).collect();
224 let b: Vec<_> = (1..101).collect();
225 let c: Vec<_> = (2..102).collect();
226
227 bench.iter(|| {
228 let intersection_: SetBuf<i32> = Intersection { slices: vec![&a, &b, &c] }.into_set_buf();
229 test::black_box(|| intersection_);
230 });
231 }
232
233 #[bench]
234 fn three_slices_big2(bench: &mut Bencher) {
235 let a: Vec<_> = (0..100).collect();
236 let b: Vec<_> = (34..134).collect();
237 let c: Vec<_> = (66..167).collect();
238
239 bench.iter(|| {
240 let intersection_: SetBuf<i32> = Intersection { slices: vec![&a, &b, &c] }.into_set_buf();
241 test::black_box(|| intersection_);
242 });
243 }
244
245 #[bench]
246 fn three_slices_big3(bench: &mut Bencher) {
247 let a: Vec<_> = (0..100).collect();
248 let b: Vec<_> = (100..200).collect();
249 let c: Vec<_> = (200..300).collect();
250
251 bench.iter(|| {
252 let intersection_: SetBuf<i32> = Intersection { slices: vec![&a, &b, &c] }.into_set_buf();
253 test::black_box(|| intersection_);
254 });
255 }
256}