sdset/multi/
symmetric_difference.rs1use crate::set::{Set, vec_sets_into_slices};
2use crate::two_minimums::{two_minimums, Minimums::*};
3use crate::{SetOperation, Collection};
4
5#[derive(Clone)]
26pub struct SymmetricDifference<'a, T: 'a> {
27 slices: Vec<&'a [T]>,
28}
29
30impl<'a, T> SymmetricDifference<'a, T> {
31 pub fn new(slices: Vec<&'a Set<T>>) -> Self {
33 Self {
34 slices: vec_sets_into_slices(slices),
35 }
36 }
37}
38
39impl<'a, T: Ord> SymmetricDifference<'a, T> {
40 #[inline]
41 fn extend_collection<C, U, F, G>(mut self, output: &mut C, extend: F, push: G)
42 where C: Collection<U>,
43 F: Fn(&mut C, &'a [T]),
44 G: Fn(&mut C, &'a T),
45 {
46 loop {
47 match two_minimums(&self.slices) {
48 Two((i, f), (_, s)) => {
49 if f != s {
50 let off = self.slices[i].iter().take_while(|&e| e < s).count();
51 extend(output, &self.slices[i][..off]);
52 self.slices[i] = &self.slices[i][off..];
53 }
54 else {
55 let mut count = 0;
56 for slice in self.slices.iter_mut() {
57 if slice.first() == Some(f) {
58 count += 1;
59 *slice = &slice[1..];
60 }
61 }
62 if count % 2 != 0 {
64 push(output, f);
65 }
66 }
67 },
68 One((i, _)) => {
69 extend(output, self.slices[i]);
70 break;
71 },
72 Nothing => break,
73 }
74 }
75 }
76}
77
78impl<'a, T: Ord + Clone> SetOperation<T> for SymmetricDifference<'a, T> {
79 fn extend_collection<C>(self, output: &mut C) where C: Collection<T> {
80 self.extend_collection(output, Collection::extend_from_slice, |v, x| v.push(x.clone()));
81 }
82}
83
84impl<'a, T: Ord> SetOperation<&'a T> for SymmetricDifference<'a, T> {
85 fn extend_collection<C>(self, output: &mut C) where C: Collection<&'a T> {
86 self.extend_collection(output, Collection::extend, Collection::push);
87 }
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93 use crate::set::{sort_dedup_vec, SetBuf};
94
95 quickcheck! {
96 fn qc_symmetric_difference(xss: Vec<Vec<i32>>) -> bool {
97 use std::collections::BTreeSet;
98 use std::iter::FromIterator;
99
100 let mut xss = xss;
102
103 for xs in &mut xss {
104 sort_dedup_vec(xs);
105 }
106
107 let x: SetBuf<i32> = {
108 let xss = xss.iter().map(|xs| xs.as_slice()).collect();
109 SymmetricDifference { slices: xss }.into_set_buf()
110 };
111
112 let mut y = BTreeSet::new();
113 for v in xss {
114 let x = BTreeSet::from_iter(v.iter().cloned());
115 y = y.symmetric_difference(&x).cloned().collect();
116 }
117 let y: Vec<_> = y.into_iter().collect();
118
119 x.as_slice() == y.as_slice()
120 }
121 }
122}
123
124#[cfg(all(feature = "unstable", test))]
125mod bench {
126 extern crate test;
127 use super::*;
128 use self::test::Bencher;
129 use crate::set::SetBuf;
130
131 #[bench]
132 fn two_slices_big(bench: &mut Bencher) {
133 let a: Vec<_> = (0..100).collect();
134 let b: Vec<_> = (1..101).collect();
135
136 bench.iter(|| {
137 let symdiff_: SetBuf<i32> = SymmetricDifference { slices: vec![&a, &b] }.into_set_buf();
138 test::black_box(|| symdiff_);
139 });
140 }
141
142 #[bench]
143 fn two_slices_big2(bench: &mut Bencher) {
144 let a: Vec<_> = (0..100).collect();
145 let b: Vec<_> = (51..151).collect();
146
147 bench.iter(|| {
148 let symdiff_: SetBuf<i32> = SymmetricDifference { slices: vec![&a, &b] }.into_set_buf();
149 test::black_box(|| symdiff_);
150 });
151 }
152
153 #[bench]
154 fn two_slices_big3(bench: &mut Bencher) {
155 let a: Vec<_> = (0..100).collect();
156 let b: Vec<_> = (100..200).collect();
157
158 bench.iter(|| {
159 let symdiff_: SetBuf<i32> = SymmetricDifference { slices: vec![&a, &b] }.into_set_buf();
160 test::black_box(|| symdiff_);
161 });
162 }
163
164 #[bench]
165 fn three_slices_big(bench: &mut Bencher) {
166 let a: Vec<_> = (0..100).collect();
167 let b: Vec<_> = (1..101).collect();
168 let c: Vec<_> = (2..102).collect();
169
170 bench.iter(|| {
171 let symdiff_: SetBuf<i32> = SymmetricDifference { slices: vec![&a, &b, &c] }.into_set_buf();
172 test::black_box(|| symdiff_);
173 });
174 }
175
176 #[bench]
177 fn three_slices_big2(bench: &mut Bencher) {
178 let a: Vec<_> = (0..100).collect();
179 let b: Vec<_> = (34..134).collect();
180 let c: Vec<_> = (66..167).collect();
181
182 bench.iter(|| {
183 let symdiff_: SetBuf<i32> = SymmetricDifference { slices: vec![&a, &b, &c] }.into_set_buf();
184 test::black_box(|| symdiff_);
185 });
186 }
187
188 #[bench]
189 fn three_slices_big3(bench: &mut Bencher) {
190 let a: Vec<_> = (0..100).collect();
191 let b: Vec<_> = (100..200).collect();
192 let c: Vec<_> = (200..300).collect();
193
194 bench.iter(|| {
195 let symdiff_: SetBuf<i32> = SymmetricDifference { slices: vec![&a, &b, &c] }.into_set_buf();
196 test::black_box(|| symdiff_);
197 });
198 }
199}