Imported Upstream version 1.57.0
[platform/upstream/boost.git] / libs / geometry / test / iterators / flatten_iterator.cpp
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 // Unit Test
3
4 // Copyright (c) 2014, Oracle and/or its affiliates.
5
6 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
7
8 // Licensed under the Boost Software License version 1.0.
9 // http://www.boost.org/users/license.html
10
11 #ifndef BOOST_TEST_MODULE
12 #define BOOST_TEST_MODULE test_flatten_iterator
13 #endif
14
15 #include <boost/test/included/unit_test.hpp>
16
17 #include <cstddef>
18 #include <iostream>
19 #include <string>
20 #include <sstream>
21 #include <algorithm>
22 #include <iterator>
23
24 #include <vector>
25 #include <list>
26
27 #include <boost/core/ignore_unused.hpp>
28 #include <boost/mpl/if.hpp>
29 #include <boost/type_traits/is_const.hpp>
30 #include <boost/assign/std/vector.hpp>
31 #include <boost/assign/std/list.hpp>
32 #include <boost/assign/std/set.hpp>
33
34 #include "test_iterator_common.hpp"
35
36 #include <boost/geometry/iterators/flatten_iterator.hpp>
37
38 using namespace boost::assign;
39
40
41 template <typename InnerContainer>
42 struct access_begin
43 {
44     typedef typename boost::mpl::if_
45     <
46         typename boost::is_const<InnerContainer>::type,
47         typename InnerContainer::const_iterator,
48         typename InnerContainer::iterator
49     >::type return_type;
50
51     static inline return_type apply(InnerContainer& inner)
52     {
53         return inner.begin();
54     }
55 };
56
57
58 template <typename InnerContainer>
59 struct access_end
60 {
61     typedef typename boost::mpl::if_
62     <
63         typename boost::is_const<InnerContainer>::type,
64         typename InnerContainer::const_iterator,
65         typename InnerContainer::iterator
66     >::type return_type;
67
68     static inline return_type apply(InnerContainer& inner)
69     {
70         return inner.end();
71     }
72 };
73
74
75 template <typename NestedContainer>
76 inline std::size_t number_of_elements(NestedContainer const& c)
77 {
78     std::size_t num_elements(0);
79     for (typename NestedContainer::const_iterator outer = c.begin();
80          outer != c.end(); ++outer)
81     {
82         num_elements += outer->size();
83     }
84     return num_elements;
85 }
86
87
88 struct test_flatten_iterator
89 {
90     template
91     <
92         typename FlattenIterator,
93         typename ConstFlattenIterator,
94         typename NestedContainer
95     >
96     static inline
97     void test_using_max_element(FlattenIterator first,
98                                 FlattenIterator beyond,
99                                 ConstFlattenIterator const_first,
100                                 ConstFlattenIterator const_beyond,
101                                 NestedContainer const& c)
102     {
103         typedef typename std::iterator_traits
104             <
105                 FlattenIterator
106             >::value_type value_type;
107
108         typedef typename NestedContainer::const_iterator const_outer_iterator;
109         typedef typename NestedContainer::value_type inner_container;
110         typedef typename inner_container::const_iterator const_inner_iterator;
111
112         if ( first == beyond )
113         {
114             return;
115         }
116
117         FlattenIterator it_max = std::max_element(first, beyond);
118         ConstFlattenIterator const_it_max =
119             std::max_element(const_first, const_beyond);
120
121         BOOST_CHECK( it_max == const_it_max );
122         BOOST_CHECK( *it_max == *const_it_max );
123
124         value_type old_value = *const_first;
125         value_type new_value = *it_max + 1;
126
127         *first = *it_max + 1;
128         const_outer_iterator outer = c.begin();
129         while ( outer->begin() == outer->end() )
130         {
131             ++outer;
132         }
133         const_inner_iterator inner = outer->begin();
134             
135         BOOST_CHECK( *inner == new_value );
136
137 #ifdef BOOST_GEOMETRY_TEST_DEBUG
138         std::cout << std::endl;
139         std::cout << "modified 1st element of 1st non-empty "
140                   << "inner container:" << std::endl;
141         print_nested_container(std::cout, c.begin(), c.end(), "nested   :")
142             << std::endl;
143         print_container(std::cout, first, beyond, "flattened:") << std::endl;
144 #endif
145
146         *first = old_value;
147         BOOST_CHECK( *inner == old_value );
148     }
149
150     template <typename NestedContainer>
151     static inline void apply(NestedContainer& c,
152                              std::string const& case_id,
153                              std::string const& container_id)
154     {
155         boost::ignore_unused(case_id, container_id);
156
157 #ifdef BOOST_GEOMETRY_TEST_DEBUG
158         std::stringstream sstream;
159         sstream << case_id << " [" << container_id << "]";
160
161         std::cout << "case id: " << sstream.str() << std::endl;
162 #endif
163         typedef typename NestedContainer::const_iterator const_outer_iterator;
164         typedef typename NestedContainer::iterator outer_iterator;
165         typedef typename NestedContainer::value_type inner_container;
166
167         typedef typename inner_container::const_iterator const_inner_iterator;
168         typedef typename inner_container::iterator inner_iterator;
169
170         typedef boost::geometry::flatten_iterator
171             <
172                 const_outer_iterator,
173                 const_inner_iterator,
174                 typename inner_container::value_type const,
175                 access_begin<inner_container const>,
176                 access_end<inner_container const>
177             > const_flatten_iterator;
178
179         typedef boost::geometry::flatten_iterator
180             <
181                 outer_iterator,
182                 inner_iterator,
183                 typename inner_container::value_type,
184                 access_begin<inner_container>,
185                 access_end<inner_container>
186             > flatten_iterator;
187
188         typedef typename std::iterator_traits
189             <
190                 flatten_iterator
191             >::value_type value_type;
192
193         flatten_iterator begin(c.begin(), c.end());
194         flatten_iterator end(c.end());
195         const_flatten_iterator const_begin(begin);
196         const_flatten_iterator const_end(end);
197         const_begin = begin;
198         const_end = end;
199
200         // test copying, dereferencing and element equality
201         std::vector<value_type> combined;
202         for (const_outer_iterator outer = c.begin();
203              outer != c.end(); ++outer)
204         {
205             std::copy(outer->begin(), outer->end(),
206                       std::back_inserter(combined));
207         }
208         test_equality(begin, end, combined);
209         test_equality(const_begin, const_end, combined);        
210
211         combined.clear();
212         std::copy(begin, end, std::back_inserter(combined));
213         test_equality(begin, end, combined);
214         test_equality(const_begin, const_end, combined);
215
216         combined.clear();
217         std::copy(const_begin, const_end, std::back_inserter(combined));
218         test_equality(begin, end, combined);
219         test_equality(const_begin, const_end, combined);
220
221         // test sizes (and std::distance)
222         test_size(begin, end, combined);
223         test_size(const_begin, const_end, combined);
224
225 #ifdef BOOST_GEOMETRY_TEST_DEBUG
226         print_nested_container(std::cout, c.begin(), c.end(), "nested    :")
227             << std::endl;
228         print_container(std::cout, begin, end, "flattened :")
229             << std::endl;
230
231         if ( begin != end )
232         {
233             std::cout << "min element: "
234                       << *std::min_element(begin, end)
235                       << std::endl;
236             std::cout << "max element: "
237                       << *std::max_element(const_begin, const_end)
238                       << std::endl;
239         }
240 #endif
241
242         // perform reversals (std::reverse)
243         test_using_reverse(begin, end, combined);
244
245         // test std::max_element, dereferencing and value assigment
246         test_using_max_element(begin, end, const_begin, const_end, c);
247
248         // test std::count_if / std::remove_if
249         test_using_remove_if(begin, end, combined);
250 #ifdef BOOST_GEOMETRY_TEST_DEBUG
251             std::cout << "====================" << std::endl << std::endl;
252 #endif
253     }
254 };
255
256
257
258 // the actual test cases -- START
259 template <int CaseNumber>
260 struct test_case_per_container;
261
262 template<>
263 struct test_case_per_container<0>
264 {
265     template <typename NestedContainer>
266     static inline void apply(std::string const& case_id,
267                              std::string const& container_id)
268     {
269         NestedContainer c;
270         test_flatten_iterator::apply(c, case_id, container_id);
271     }
272 };
273
274 template<>
275 struct test_case_per_container<1>
276 {
277     template <typename NestedContainer>
278     static inline void apply(std::string const& case_id,
279                              std::string const& container_id)
280     {
281         NestedContainer c;
282         for (int i = 0; i < 5; ++i)
283         {
284             c += typename NestedContainer::value_type();
285         }
286         test_flatten_iterator::apply(c, case_id, container_id);
287     }
288 };
289
290 template<>
291 struct test_case_per_container<2>
292 {
293     template <typename NestedContainer>
294     static inline void apply(std::string const& case_id,
295                              std::string const& container_id)
296     {
297         NestedContainer c;
298         typename NestedContainer::value_type ic[4];
299
300         ic[0] += 5,4,3,2,1;
301         ic[1] += 6,7,8;
302         ic[2] += 9;
303         ic[3] += 9,8,7,6,5;
304         c += ic[0],ic[1],ic[2],ic[3];
305
306         test_flatten_iterator::apply(c, case_id, container_id);
307     }
308 };
309
310 template<>
311 struct test_case_per_container<3>
312 {
313     template <typename NestedContainer>
314     static inline void apply(std::string const& case_id,
315                              std::string const& container_id)
316     {
317         NestedContainer c;
318         typename NestedContainer::value_type ic[20];
319
320         ic[2] += 5,4,3,2,1;
321         ic[3] += 6,7,8;
322         ic[8] += 9;
323         ic[9] += 9,8,7,6,5;
324         ic[14] += 4,3,2,1;
325         for (std::size_t i = 0; i < 20; ++i)
326         {
327             c += ic[i];
328         }
329
330         test_flatten_iterator::apply(c, case_id, container_id);
331     }
332 };
333 // the actual test cases -- END
334
335
336
337 template <int CaseNumber>
338 inline void test_case_all_containers(std::string const& case_id)
339 {
340     typedef typename std::vector<std::vector<int> > VV;
341     typedef typename std::vector<std::list<int> > VL;
342     typedef typename std::list<std::vector<int> > LV;
343     typedef typename std::list<std::list<int> > LL;
344
345 #ifdef BOOST_GEOMETRY_TEST_DEBUG
346     std::cout << std::endl << std::endl;
347 #endif
348     test_case_per_container<CaseNumber>::template apply<VV>(case_id, "VV");
349     test_case_per_container<CaseNumber>::template apply<VL>(case_id, "VL");
350     test_case_per_container<CaseNumber>::template apply<LV>(case_id, "LV");
351     test_case_per_container<CaseNumber>::template apply<LL>(case_id, "LL");
352
353 #ifdef BOOST_GEOMETRY_TEST_DEBUG
354     std::cout << std::endl;
355     std::cout << "********************************************************"
356               << std::endl << std::endl;
357 #endif
358 }
359
360
361
362 BOOST_AUTO_TEST_CASE( test_flatten_iterator_all )
363 {
364     test_case_all_containers<0>("empty");
365     test_case_all_containers<1>("case1");
366     test_case_all_containers<2>("case2");
367     test_case_all_containers<3>("case3");
368 }