sdset/multi/
intersection.rs

1use std::cmp;
2use crate::set::{Set, vec_sets_into_slices};
3use crate::{SetOperation, Collection, exponential_offset_ge};
4
5use self::Equality::*;
6
7/// Represent the _intersection_ set operation that will be applied to the slices.
8///
9/// Note that the intersection is all the elements that are in all the slices at the same time.
10///
11/// # Examples
12/// ```
13/// # use sdset::Error;
14/// # fn try_main() -> Result<(), Error> {
15/// use sdset::multi::OpBuilder;
16/// use sdset::{SetOperation, Set, SetBuf};
17///
18/// let a = Set::new(&[1, 2, 4])?;
19/// let b = Set::new(&[2, 3, 4, 5, 7])?;
20/// let c = Set::new(&[2, 4, 6, 7])?;
21///
22/// let op = OpBuilder::from_vec(vec![a, b, c]).intersection();
23///
24/// let res: SetBuf<i32> = op.into_set_buf();
25/// assert_eq!(&res[..], &[2, 4]);
26/// # Ok(()) }
27/// # try_main().unwrap();
28/// ```
29#[derive(Clone)]
30pub struct Intersection<'a, T: 'a> {
31    slices: Vec<&'a [T]>,
32}
33
34impl<'a, T> Intersection<'a, T> {
35    /// Construct one with slices checked to be sorted and deduplicated.
36    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            // FIXME temporary hack (can have mutable parameters!)
153            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}