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