1 // Copyright Neil Groves 2009. Use, modification and
2 // distribution is subject to the Boost Software License, Version
3 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
5 //
6 //
7 // For more information, see http://www.boost.org/libs/range/
8 //
9 #include <boost/range/algorithm/set_algorithm.hpp>
10
11 #include <boost/test/test_tools.hpp>
12 #include <boost/test/unit_test.hpp>
13
14 #include <boost/assign.hpp>
15 #include <algorithm>
16 #include <functional>
17 #include <list>
18 #include <numeric>
19 #include <deque>
20 #include <vector>
21
22 namespace boost
23 {
24 namespace
25 {
26 template<class Container1, class Iterator, class Container2>
check_result(Container1 & reference,Iterator reference_result,Container2 & test_cont,Iterator test_result)27 void check_result(
28 Container1& reference,
29 Iterator reference_result,
30 Container2& test_cont,
31 Iterator test_result
32 )
33 {
34 BOOST_CHECK_EQUAL(
35 std::distance<Iterator>(reference.begin(), reference_result),
36 std::distance<Iterator>(test_cont.begin(), test_result)
37 );
38
39 BOOST_CHECK_EQUAL_COLLECTIONS(
40 reference.begin(), reference.end(),
41 test_cont.begin(), test_cont.end()
42 );
43 }
44
45 template<class Container1, class Container2>
test(Container1 & cont1,Container2 & cont2)46 void test(Container1& cont1, Container2& cont2)
47 {
48 typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_t;
49 typedef BOOST_DEDUCED_TYPENAME std::vector<value_t>::iterator iterator_t;
50
51 std::vector<value_t> reference(cont1.size() + cont2.size());
52 std::vector<value_t> test_cont(reference);
53
54 iterator_t reference_result
55 = std::set_intersection(cont1.begin(), cont1.end(),
56 cont2.begin(), cont2.end(),
57 reference.begin());
58
59 iterator_t test_result
60 = boost::set_intersection(cont1, cont2, test_cont.begin());
61
62 check_result(reference, reference_result,
63 test_cont, test_result);
64
65 test_result = boost::set_intersection(
66 boost::make_iterator_range(cont1), cont2,
67 test_cont.begin());
68
69 check_result(reference, reference_result,
70 test_cont, test_result);
71
72 test_result = boost::set_intersection(
73 cont1, boost::make_iterator_range(cont2),
74 test_cont.begin());
75
76 check_result(reference, reference_result,
77 test_cont, test_result);
78
79 test_result = boost::set_intersection(
80 boost::make_iterator_range(cont1),
81 boost::make_iterator_range(cont2),
82 test_cont.begin());
83
84 check_result(reference, reference_result,
85 test_cont, test_result);
86 }
87
88 template<class Container, class BinaryPredicate>
sort_container(Container & cont,BinaryPredicate pred)89 void sort_container(Container& cont, BinaryPredicate pred)
90 {
91 typedef BOOST_DEDUCED_TYPENAME Container::value_type value_t;
92
93 std::vector<value_t> temp(cont.begin(), cont.end());
94 std::sort(temp.begin(), temp.end(), pred);
95 cont.assign(temp.begin(), temp.end());
96 }
97
98 template<class Container1,
99 class Container2,
100 class BinaryPredicate>
test_pred(Container1 cont1,Container2 cont2,BinaryPredicate pred)101 void test_pred(Container1 cont1, Container2 cont2,
102 BinaryPredicate pred)
103 {
104 typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_t;
105 typedef BOOST_DEDUCED_TYPENAME std::vector<value_t>::iterator iterator_t;
106
107 sort_container(cont1, pred);
108 sort_container(cont2, pred);
109
110 std::vector<value_t> reference(cont1.size() + cont2.size());
111 std::vector<value_t> test_cont(reference);
112
113 iterator_t reference_result
114 = std::set_intersection(cont1.begin(), cont1.end(),
115 cont2.begin(), cont2.end(),
116 reference.begin(),
117 pred);
118
119 iterator_t test_result
120 = boost::set_intersection(cont1, cont2, test_cont.begin(), pred);
121
122 check_result(reference, reference_result,
123 test_cont, test_result);
124
125 test_result = boost::set_intersection(
126 boost::make_iterator_range(cont1), cont2,
127 test_cont.begin(), pred);
128
129 check_result(reference, reference_result,
130 test_cont, test_result);
131
132 test_result = boost::set_intersection(
133 cont1, boost::make_iterator_range(cont2),
134 test_cont.begin(), pred);
135
136 check_result(reference, reference_result,
137 test_cont, test_result);
138
139 test_result = boost::set_intersection(
140 boost::make_iterator_range(cont1),
141 boost::make_iterator_range(cont2),
142 test_cont.begin(), pred);
143
144 check_result(reference, reference_result,
145 test_cont, test_result);
146 }
147
148 template<class Container1, class Container2>
test_set_intersection_impl(Container1 & cont1,Container2 & cont2)149 void test_set_intersection_impl(
150 Container1& cont1,
151 Container2& cont2
152 )
153 {
154 test(cont1, cont2);
155 test_pred(cont1, cont2, std::less<int>());
156 test_pred(cont1, cont2, std::greater<int>());
157 }
158
159 template<class Container1, class Container2>
test_set_intersection_impl()160 void test_set_intersection_impl()
161 {
162 using namespace boost::assign;
163
164 Container1 cont1;
165 Container2 cont2;
166
167 test_set_intersection_impl(cont1, cont2);
168
169 cont1.clear();
170 cont2.clear();
171 cont1 += 1;
172 test_set_intersection_impl(cont1, cont2);
173
174 cont1.clear();
175 cont2.clear();
176 cont2 += 1;
177 test_set_intersection_impl(cont1, cont2);
178
179 cont1.clear();
180 cont2.clear();
181 cont1 += 1,2,3,4,5,6,7,8,9;
182 cont2 += 2,3,4;
183 test_set_intersection_impl(cont1, cont2);
184
185 cont1.clear();
186 cont2.clear();
187 cont1 += 2,3,4;
188 cont2 += 1,2,3,4,5,6,7,8,9;
189 test_set_intersection_impl(cont1, cont2);
190 }
191
test_set_intersection()192 void test_set_intersection()
193 {
194 test_set_intersection_impl< std::vector<int>, std::vector<int> >();
195 test_set_intersection_impl< std::list<int>, std::list<int> >();
196 test_set_intersection_impl< std::deque<int>, std::deque<int> >();
197 test_set_intersection_impl< std::vector<int>, std::list<int> >();
198 test_set_intersection_impl< std::list<int>, std::vector<int> >();
199 }
200 }
201 }
202
203
204 boost::unit_test::test_suite*
init_unit_test_suite(int argc,char * argv[])205 init_unit_test_suite(int argc, char* argv[])
206 {
207 boost::unit_test::test_suite* test
208 = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.set_intersection" );
209
210 test->add( BOOST_TEST_CASE( &boost::test_set_intersection ) );
211
212 return test;
213 }
214