Merged with mainline at revision 128810.
[official-gcc.git] / libstdc++-v3 / include / parallel / set_operations.h
blob006176de46f8ca2ffbf01bcedc9d8b1f02fcaea6
1 // -*- C++ -*-
3 // Copyright (C) 2007 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the terms
7 // of the GNU General Public License as published by the Free Software
8 // Foundation; either version 2, or (at your option) any later
9 // version.
11 // This library is distributed in the hope that it will be useful, but
12 // WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this library; see the file COPYING. If not, write to
18 // the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
19 // MA 02111-1307, USA.
21 // As a special exception, you may use this file as part of a free
22 // software library without restriction. Specifically, if other files
23 // instantiate templates or use macros or inline functions from this
24 // file, or you compile this file and link it with other files to
25 // produce an executable, this file does not by itself cause the
26 // resulting executable to be covered by the GNU General Public
27 // License. This exception does not however invalidate any other
28 // reasons why the executable file might be covered by the GNU General
29 // Public License.
31 /**
32 * @file parallel/set_operations.h
33 * @brief Parallel implementations of set operations for random-access
34 * iterators.
35 * This file is a GNU parallel extension to the Standard C++ Library.
38 // Written by Marius Elvert and Felix Bondarenko.
40 #ifndef _GLIBCXX_PARALLEL_SET_OPERATIONS_H
41 #define _GLIBCXX_PARALLEL_SET_OPERATIONS_H 1
43 #include <omp.h>
45 #include <parallel/settings.h>
46 #include <parallel/multiseq_selection.h>
48 namespace __gnu_parallel
50 template<typename InputIterator, typename OutputIterator>
51 inline OutputIterator
52 copy_tail(std::pair<InputIterator, InputIterator> b,
53 std::pair<InputIterator, InputIterator> e, OutputIterator r)
55 if (b.first != e.first)
59 *r++ = *b.first++;
61 while (b.first != e.first);
63 else
65 while (b.second != e.second)
66 *r++ = *b.second++;
68 return r;
71 template<typename InputIterator, typename OutputIterator, typename Comparator>
72 struct symmetric_difference_func
74 typedef std::iterator_traits<InputIterator> traits_type;
75 typedef typename traits_type::difference_type difference_type;
76 typedef typename std::pair<InputIterator, InputIterator> iterator_pair;
78 symmetric_difference_func(Comparator c) : comp(c) {}
80 Comparator comp;
82 inline OutputIterator invoke(InputIterator a, InputIterator b,
83 InputIterator c, InputIterator d,
84 OutputIterator r) const
86 while (a != b && c != d)
88 if (comp(*a, *c))
90 *r = *a;
91 ++a;
92 ++r;
94 else if (comp(*c, *a))
96 *r = *c;
97 ++c;
98 ++r;
100 else
102 ++a;
103 ++c;
106 return std::copy(c, d, std::copy(a, b, r));
109 inline difference_type
110 count(InputIterator a, InputIterator b, InputIterator c, InputIterator d) const
112 difference_type counter = 0;
114 while (a != b && c != d)
116 if (comp(*a, *c))
118 ++a;
119 ++counter;
121 else if (comp(*c, *a))
123 ++c;
124 ++counter;
126 else
128 ++a;
129 ++c;
133 return counter + (b - a) + (d - c);
136 inline OutputIterator
137 first_empty(InputIterator c, InputIterator d, OutputIterator out) const
138 { return std::copy(c, d, out); }
140 inline OutputIterator
141 second_empty(InputIterator a, InputIterator b, OutputIterator out) const
142 { return std::copy(a, b, out); }
147 template<typename InputIterator, typename OutputIterator, typename Comparator>
148 struct difference_func
150 typedef std::iterator_traits<InputIterator> traits_type;
151 typedef typename traits_type::difference_type difference_type;
152 typedef typename std::pair<InputIterator, InputIterator> iterator_pair;
154 difference_func(Comparator c) : comp(c) {}
156 Comparator comp;
158 inline OutputIterator
159 invoke(InputIterator a, InputIterator b, InputIterator c, InputIterator d,
160 OutputIterator r) const
162 while (a != b && c != d)
164 if (comp(*a, *c))
166 *r = *a;
167 ++a;
168 ++r;
170 else if (comp(*c, *a))
171 { ++c; }
172 else
174 ++a;
175 ++c;
178 return std::copy(a, b, r);
181 inline difference_type
182 count(InputIterator a, InputIterator b, InputIterator c, InputIterator d) const
184 difference_type counter = 0;
186 while (a != b && c != d)
188 if (comp(*a, *c))
190 ++a;
191 ++counter;
193 else if (comp(*c, *a))
194 { ++c; }
195 else
196 { ++a; ++c; }
199 return counter + (b - a);
202 inline OutputIterator
203 first_empty(InputIterator c, InputIterator d, OutputIterator out) const
204 { return out; }
206 inline OutputIterator
207 second_empty(InputIterator a, InputIterator b, OutputIterator out) const
208 { return std::copy(a, b, out); }
212 template<typename InputIterator, typename OutputIterator, typename Comparator>
213 struct intersection_func
215 typedef std::iterator_traits<InputIterator> traits_type;
216 typedef typename traits_type::difference_type difference_type;
217 typedef typename std::pair<InputIterator, InputIterator> iterator_pair;
219 intersection_func(Comparator c) : comp(c) {}
221 Comparator comp;
223 inline OutputIterator
224 invoke(InputIterator a, InputIterator b, InputIterator c, InputIterator d,
225 OutputIterator r) const
227 while (a != b && c != d)
229 if (comp(*a, *c))
230 { ++a; }
231 else if (comp(*c, *a))
232 { ++c; }
233 else
235 *r = *a;
236 ++a;
237 ++c;
238 ++r;
242 return r;
245 inline difference_type
246 count(InputIterator a, InputIterator b, InputIterator c, InputIterator d) const
248 difference_type counter = 0;
250 while (a != b && c != d)
252 if (comp(*a, *c))
253 { ++a; }
254 else if (comp(*c, *a))
255 { ++c; }
256 else
258 ++a;
259 ++c;
260 ++counter;
264 return counter;
267 inline OutputIterator
268 first_empty(InputIterator c, InputIterator d, OutputIterator out) const
269 { return out; }
271 inline OutputIterator
272 second_empty(InputIterator a, InputIterator b, OutputIterator out) const
273 { return out; }
276 template<class InputIterator, class OutputIterator, class Comparator>
277 struct union_func
279 typedef typename std::iterator_traits<InputIterator>::difference_type difference_type;
281 union_func(Comparator c) : comp(c) {}
283 Comparator comp;
285 inline OutputIterator
286 invoke(InputIterator a, const InputIterator b, InputIterator c,
287 const InputIterator d, OutputIterator r) const
289 while (a != b && c != d)
291 if (comp(*a, *c))
293 *r = *a;
294 ++a;
296 else if (comp(*c, *a))
298 *r = *c;
299 ++c;
301 else
303 *r = *a;
304 ++a;
305 ++c;
307 ++r;
309 return std::copy(c, d, std::copy(a, b, r));
312 inline difference_type
313 count(InputIterator a, const InputIterator b, InputIterator c,
314 const InputIterator d) const
316 difference_type counter = 0;
318 while (a != b && c != d)
320 if (comp(*a, *c))
321 { ++a; }
322 else if (comp(*c, *a))
323 { ++c; }
324 else
326 ++a;
327 ++c;
329 ++counter;
332 counter += (b - a);
333 counter += (d - c);
334 return counter;
337 inline OutputIterator
338 first_empty(InputIterator c, InputIterator d, OutputIterator out) const
339 { return std::copy(c, d, out); }
341 inline OutputIterator
342 second_empty(InputIterator a, InputIterator b, OutputIterator out) const
343 { return std::copy(a, b, out); }
346 template<typename InputIterator, typename OutputIterator, typename Operation>
347 OutputIterator
348 parallel_set_operation(InputIterator begin1, InputIterator end1,
349 InputIterator begin2, InputIterator end2,
350 OutputIterator result, Operation op)
352 _GLIBCXX_CALL((end1 - begin1) + (end2 - begin2))
354 typedef std::iterator_traits<InputIterator> traits_type;
355 typedef typename traits_type::difference_type difference_type;
356 typedef typename std::pair<InputIterator, InputIterator> iterator_pair;
359 if (begin1 == end1)
360 return op.first_empty(begin2, end2, result);
362 if (begin2 == end2)
363 return op.second_empty(begin1, end1, result);
365 const difference_type size = (end1 - begin1) + (end2 - begin2);
367 thread_index_t num_threads = std::min<difference_type>(std::min(end1 - begin1, end2 - begin2), get_max_threads());
369 difference_type borders[num_threads + 2];
370 equally_split(size, num_threads + 1, borders);
372 const iterator_pair sequence[ 2 ] = { std::make_pair(begin1, end1), std::make_pair(begin2, end2) } ;
374 iterator_pair block_begins[num_threads + 1];
376 // Very start.
377 block_begins[0] = std::make_pair(begin1, begin2);
378 difference_type length[num_threads];
380 OutputIterator return_value = result;
382 #pragma omp parallel num_threads(num_threads)
384 Timing<sequential_tag> t;
386 t.tic();
388 // Result from multiseq_partition.
389 InputIterator offset[2];
390 const int iam = omp_get_thread_num();
392 const difference_type rank = borders[iam + 1];
394 multiseq_partition(sequence, sequence + 2, rank, offset, op.comp);
396 // allowed to read?
397 // together
398 // *(offset[ 0 ] - 1) == *offset[ 1 ]
399 if (offset[ 0 ] != begin1 && offset[ 1 ] != end2
400 && !op.comp(*(offset[ 0 ] - 1), *offset[ 1 ])
401 && !op.comp(*offset[ 1 ], *(offset[ 0 ] - 1)))
403 // Avoid split between globally equal elements: move one to
404 // front in first sequence.
405 --offset[ 0 ];
408 iterator_pair block_end = block_begins[ iam + 1 ] = iterator_pair(offset[ 0 ], offset[ 1 ]);
410 t.tic();
412 // Make sure all threads have their block_begin result written out.
413 #pragma omp barrier
415 t.tic();
417 iterator_pair block_begin = block_begins[ iam ];
419 // Begin working for the first block, while the others except
420 // the last start to count.
421 if (iam == 0)
423 // The first thread can copy already.
424 length[ iam ] = op.invoke(block_begin.first, block_end.first, block_begin.second, block_end.second, result) - result;
426 else
428 length[ iam ] = op.count(block_begin.first, block_end.first,
429 block_begin.second, block_end.second);
432 t.tic();
434 // Make sure everyone wrote their lengths.
435 #pragma omp barrier
437 t.tic();
438 OutputIterator r = result;
440 if (iam == 0)
442 // Do the last block.
443 for (int i = 0; i < num_threads; ++i)
444 r += length[i];
446 block_begin = block_begins[num_threads];
448 // Return the result iterator of the last block.
449 return_value = op.invoke(block_begin.first, end1, block_begin.second, end2, r);
452 else
454 for (int i = 0; i < iam; ++i)
455 r += length[ i ];
457 // Reset begins for copy pass.
458 op.invoke(block_begin.first, block_end.first,
459 block_begin.second, block_end.second, r);
462 t.tic();
463 t.print();
465 return return_value;
469 template<typename InputIterator, typename OutputIterator, typename Comparator>
470 OutputIterator
471 parallel_set_union(InputIterator begin1, InputIterator end1,
472 InputIterator begin2, InputIterator end2,
473 OutputIterator result, Comparator comp)
475 return parallel_set_operation(begin1, end1, begin2, end2, result,
476 union_func< InputIterator, OutputIterator, Comparator>(comp));
479 template<typename InputIterator, typename OutputIterator, typename Comparator>
480 OutputIterator
481 parallel_set_intersection(InputIterator begin1, InputIterator end1,
482 InputIterator begin2, InputIterator end2,
483 OutputIterator result, Comparator comp)
485 return parallel_set_operation(begin1, end1, begin2, end2, result,
486 intersection_func<InputIterator, OutputIterator, Comparator>(comp));
490 template<typename InputIterator, typename OutputIterator>
491 OutputIterator
492 set_intersection(InputIterator begin1, InputIterator end1, InputIterator begin2, InputIterator end2, OutputIterator result)
494 typedef std::iterator_traits<InputIterator> traits_type;
495 typedef typename traits_type::value_type value_type;
497 return set_intersection(begin1, end1, begin2, end2, result,
498 std::less<value_type>());
501 template<typename InputIterator, typename OutputIterator, typename Comparator>
502 OutputIterator
503 parallel_set_difference(InputIterator begin1, InputIterator end1,
504 InputIterator begin2, InputIterator end2,
505 OutputIterator result, Comparator comp)
507 return parallel_set_operation(begin1, end1, begin2, end2, result,
508 difference_func<InputIterator, OutputIterator, Comparator>(comp));
511 template<typename InputIterator, typename OutputIterator, typename Comparator>
512 OutputIterator
513 parallel_set_symmetric_difference(InputIterator begin1, InputIterator end1, InputIterator begin2, InputIterator end2, OutputIterator result, Comparator comp)
515 return parallel_set_operation(begin1, end1, begin2, end2, result,
516 symmetric_difference_func<InputIterator, OutputIterator, Comparator>(comp));
521 #endif // _GLIBCXX_SET_ALGORITHM_