]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/include/parallel/set_operations.h
cfglayout.c (fixup_reorder_chain): Accept conditional jumps without a fallthrough...
[thirdparty/gcc.git] / libstdc++-v3 / include / parallel / set_operations.h
CommitLineData
c2ba9709
JS
1// -*- C++ -*-
2
748086b7 3// Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
c2ba9709
JS
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
748086b7 8// Foundation; either version 3, or (at your option) any later
c2ba9709
JS
9// version.
10
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.
15
748086b7
JJ
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
c2ba9709 19
748086b7
JJ
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
c2ba9709
JS
24
25/**
26 * @file parallel/set_operations.h
27 * @brief Parallel implementations of set operations for random-access
28 * iterators.
29 * This file is a GNU parallel extension to the Standard C++ Library.
30 */
31
32// Written by Marius Elvert and Felix Bondarenko.
33
34#ifndef _GLIBCXX_PARALLEL_SET_OPERATIONS_H
35#define _GLIBCXX_PARALLEL_SET_OPERATIONS_H 1
36
37#include <omp.h>
38
39#include <parallel/settings.h>
40#include <parallel/multiseq_selection.h>
41
42namespace __gnu_parallel
43{
1acba85b
JS
44template<typename _IIter, typename _OutputIterator>
45 _OutputIterator
46 copy_tail(std::pair<_IIter, _IIter> __b,
47 std::pair<_IIter, _IIter> __e, _OutputIterator __r)
c2ba9709 48 {
1acba85b 49 if (__b.first != __e.first)
c2ba9709 50 {
e683ee2a
JS
51 do
52 {
1acba85b 53 *__r++ = *__b.first++;
e683ee2a 54 }
1acba85b 55 while (__b.first != __e.first);
c2ba9709
JS
56 }
57 else
58 {
1acba85b
JS
59 while (__b.second != __e.second)
60 *__r++ = *__b.second++;
c2ba9709 61 }
1acba85b 62 return __r;
c2ba9709
JS
63 }
64
1acba85b
JS
65template<typename _IIter,
66 typename _OutputIterator,
67 typename _Compare>
c2ba9709
JS
68 struct symmetric_difference_func
69 {
1acba85b
JS
70 typedef std::iterator_traits<_IIter> _TraitsType;
71 typedef typename _TraitsType::difference_type _DifferenceType;
72 typedef typename std::pair<_IIter, _IIter> _IteratorPair;
c2ba9709 73
54384f7f 74 symmetric_difference_func(_Compare __comp) : _M_comp(__comp) {}
c2ba9709 75
54384f7f 76 _Compare _M_comp;
c2ba9709 77
1acba85b
JS
78 _OutputIterator
79 _M_invoke(_IIter __a, _IIter __b,
80 _IIter __c, _IIter d,
81 _OutputIterator __r) const
c2ba9709 82 {
1acba85b 83 while (__a != __b && __c != d)
e683ee2a 84 {
54384f7f 85 if (_M_comp(*__a, *__c))
e683ee2a 86 {
1acba85b
JS
87 *__r = *__a;
88 ++__a;
89 ++__r;
e683ee2a 90 }
54384f7f 91 else if (_M_comp(*__c, *__a))
e683ee2a 92 {
1acba85b
JS
93 *__r = *__c;
94 ++__c;
95 ++__r;
e683ee2a
JS
96 }
97 else
98 {
1acba85b
JS
99 ++__a;
100 ++__c;
e683ee2a
JS
101 }
102 }
1acba85b 103 return std::copy(__c, d, std::copy(__a, __b, __r));
c2ba9709
JS
104 }
105
1acba85b
JS
106 _DifferenceType
107 __count(_IIter __a, _IIter __b,
108 _IIter __c, _IIter d) const
c2ba9709 109 {
1acba85b 110 _DifferenceType __counter = 0;
c2ba9709 111
1acba85b 112 while (__a != __b && __c != d)
e683ee2a 113 {
54384f7f 114 if (_M_comp(*__a, *__c))
e683ee2a 115 {
1acba85b
JS
116 ++__a;
117 ++__counter;
e683ee2a 118 }
54384f7f 119 else if (_M_comp(*__c, *__a))
e683ee2a 120 {
1acba85b
JS
121 ++__c;
122 ++__counter;
e683ee2a
JS
123 }
124 else
125 {
1acba85b
JS
126 ++__a;
127 ++__c;
e683ee2a
JS
128 }
129 }
c2ba9709 130
1acba85b 131 return __counter + (__b - __a) + (d - __c);
c2ba9709
JS
132 }
133
1acba85b
JS
134 _OutputIterator
135 __first_empty(_IIter __c, _IIter d, _OutputIterator __out) const
136 { return std::copy(__c, d, __out); }
c2ba9709 137
1acba85b
JS
138 _OutputIterator
139 __second_empty(_IIter __a, _IIter __b, _OutputIterator __out) const
140 { return std::copy(__a, __b, __out); }
c2ba9709
JS
141 };
142
143
1acba85b
JS
144template<typename _IIter,
145 typename _OutputIterator,
146 typename _Compare>
147 struct __difference_func
c2ba9709 148 {
1acba85b
JS
149 typedef std::iterator_traits<_IIter> _TraitsType;
150 typedef typename _TraitsType::difference_type _DifferenceType;
151 typedef typename std::pair<_IIter, _IIter> _IteratorPair;
c2ba9709 152
54384f7f 153 __difference_func(_Compare __comp) : _M_comp(__comp) {}
c2ba9709 154
54384f7f 155 _Compare _M_comp;
c2ba9709 156
1acba85b
JS
157 _OutputIterator
158 _M_invoke(_IIter __a, _IIter __b, _IIter __c, _IIter d,
159 _OutputIterator __r) const
c2ba9709 160 {
1acba85b 161 while (__a != __b && __c != d)
e683ee2a 162 {
54384f7f 163 if (_M_comp(*__a, *__c))
e683ee2a 164 {
1acba85b
JS
165 *__r = *__a;
166 ++__a;
167 ++__r;
e683ee2a 168 }
54384f7f 169 else if (_M_comp(*__c, *__a))
1acba85b 170 { ++__c; }
e683ee2a
JS
171 else
172 {
1acba85b
JS
173 ++__a;
174 ++__c;
e683ee2a
JS
175 }
176 }
1acba85b 177 return std::copy(__a, __b, __r);
c2ba9709
JS
178 }
179
1acba85b
JS
180 _DifferenceType
181 __count(_IIter __a, _IIter __b,
182 _IIter __c, _IIter d) const
c2ba9709 183 {
1acba85b 184 _DifferenceType __counter = 0;
c2ba9709 185
1acba85b 186 while (__a != __b && __c != d)
e683ee2a 187 {
54384f7f 188 if (_M_comp(*__a, *__c))
e683ee2a 189 {
1acba85b
JS
190 ++__a;
191 ++__counter;
e683ee2a 192 }
54384f7f 193 else if (_M_comp(*__c, *__a))
1acba85b 194 { ++__c; }
e683ee2a 195 else
1acba85b 196 { ++__a; ++__c; }
e683ee2a 197 }
c2ba9709 198
1acba85b 199 return __counter + (__b - __a);
c2ba9709
JS
200 }
201
1acba85b
JS
202 inline _OutputIterator
203 __first_empty(_IIter __c, _IIter d, _OutputIterator __out) const
204 { return __out; }
c2ba9709 205
1acba85b
JS
206 inline _OutputIterator
207 __second_empty(_IIter __a, _IIter __b, _OutputIterator __out) const
208 { return std::copy(__a, __b, __out); }
c2ba9709
JS
209 };
210
211
1acba85b
JS
212template<typename _IIter,
213 typename _OutputIterator,
214 typename _Compare>
215 struct __intersection_func
c2ba9709 216 {
1acba85b
JS
217 typedef std::iterator_traits<_IIter> _TraitsType;
218 typedef typename _TraitsType::difference_type _DifferenceType;
219 typedef typename std::pair<_IIter, _IIter> _IteratorPair;
c2ba9709 220
54384f7f 221 __intersection_func(_Compare __comp) : _M_comp(__comp) {}
c2ba9709 222
54384f7f 223 _Compare _M_comp;
c2ba9709 224
1acba85b
JS
225 _OutputIterator
226 _M_invoke(_IIter __a, _IIter __b, _IIter __c, _IIter d,
227 _OutputIterator __r) const
c2ba9709 228 {
1acba85b 229 while (__a != __b && __c != d)
e683ee2a 230 {
54384f7f 231 if (_M_comp(*__a, *__c))
1acba85b 232 { ++__a; }
54384f7f 233 else if (_M_comp(*__c, *__a))
1acba85b 234 { ++__c; }
e683ee2a
JS
235 else
236 {
1acba85b
JS
237 *__r = *__a;
238 ++__a;
239 ++__c;
240 ++__r;
e683ee2a
JS
241 }
242 }
c2ba9709 243
1acba85b 244 return __r;
c2ba9709
JS
245 }
246
1acba85b
JS
247 _DifferenceType
248 __count(_IIter __a, _IIter __b,
249 _IIter __c, _IIter d) const
c2ba9709 250 {
1acba85b 251 _DifferenceType __counter = 0;
c2ba9709 252
1acba85b 253 while (__a != __b && __c != d)
e683ee2a 254 {
54384f7f 255 if (_M_comp(*__a, *__c))
1acba85b 256 { ++__a; }
54384f7f 257 else if (_M_comp(*__c, *__a))
1acba85b 258 { ++__c; }
e683ee2a
JS
259 else
260 {
1acba85b
JS
261 ++__a;
262 ++__c;
263 ++__counter;
e683ee2a
JS
264 }
265 }
c2ba9709 266
1acba85b 267 return __counter;
c2ba9709
JS
268 }
269
1acba85b
JS
270 inline _OutputIterator
271 __first_empty(_IIter __c, _IIter d, _OutputIterator __out) const
272 { return __out; }
c2ba9709 273
1acba85b
JS
274 inline _OutputIterator
275 __second_empty(_IIter __a, _IIter __b, _OutputIterator __out) const
276 { return __out; }
c2ba9709
JS
277 };
278
1acba85b
JS
279template<class _IIter, class _OutputIterator, class _Compare>
280 struct __union_func
c2ba9709 281 {
1acba85b
JS
282 typedef typename std::iterator_traits<_IIter>::difference_type
283 _DifferenceType;
c2ba9709 284
54384f7f 285 __union_func(_Compare __comp) : _M_comp(__comp) {}
c2ba9709 286
54384f7f 287 _Compare _M_comp;
c2ba9709 288
1acba85b
JS
289 _OutputIterator
290 _M_invoke(_IIter __a, const _IIter __b, _IIter __c,
291 const _IIter d, _OutputIterator __r) const
c2ba9709 292 {
1acba85b 293 while (__a != __b && __c != d)
e683ee2a 294 {
54384f7f 295 if (_M_comp(*__a, *__c))
e683ee2a 296 {
1acba85b
JS
297 *__r = *__a;
298 ++__a;
e683ee2a 299 }
54384f7f 300 else if (_M_comp(*__c, *__a))
e683ee2a 301 {
1acba85b
JS
302 *__r = *__c;
303 ++__c;
e683ee2a
JS
304 }
305 else
306 {
1acba85b
JS
307 *__r = *__a;
308 ++__a;
309 ++__c;
e683ee2a 310 }
1acba85b 311 ++__r;
e683ee2a 312 }
1acba85b 313 return std::copy(__c, d, std::copy(__a, __b, __r));
c2ba9709
JS
314 }
315
1acba85b
JS
316 _DifferenceType
317 __count(_IIter __a, _IIter __b,
318 _IIter __c, _IIter d) const
c2ba9709 319 {
1acba85b 320 _DifferenceType __counter = 0;
c2ba9709 321
1acba85b 322 while (__a != __b && __c != d)
e683ee2a 323 {
54384f7f 324 if (_M_comp(*__a, *__c))
1acba85b 325 { ++__a; }
54384f7f 326 else if (_M_comp(*__c, *__a))
1acba85b 327 { ++__c; }
e683ee2a
JS
328 else
329 {
1acba85b
JS
330 ++__a;
331 ++__c;
e683ee2a 332 }
1acba85b 333 ++__counter;
e683ee2a 334 }
c2ba9709 335
1acba85b
JS
336 __counter += (__b - __a);
337 __counter += (d - __c);
338 return __counter;
c2ba9709
JS
339 }
340
1acba85b
JS
341 inline _OutputIterator
342 __first_empty(_IIter __c, _IIter d, _OutputIterator __out) const
343 { return std::copy(__c, d, __out); }
c2ba9709 344
1acba85b
JS
345 inline _OutputIterator
346 __second_empty(_IIter __a, _IIter __b, _OutputIterator __out) const
347 { return std::copy(__a, __b, __out); }
c2ba9709
JS
348 };
349
1acba85b
JS
350template<typename _IIter,
351 typename _OutputIterator,
5817ff8e 352 typename Operation>
1acba85b
JS
353 _OutputIterator
354 __parallel_set_operation(_IIter __begin1, _IIter __end1,
355 _IIter __begin2, _IIter __end2,
356 _OutputIterator __result, Operation __op)
c2ba9709 357 {
1acba85b 358 _GLIBCXX_CALL((__end1 - __begin1) + (__end2 - __begin2))
c2ba9709 359
1acba85b
JS
360 typedef std::iterator_traits<_IIter> _TraitsType;
361 typedef typename _TraitsType::difference_type _DifferenceType;
362 typedef typename std::pair<_IIter, _IIter> _IteratorPair;
c2ba9709 363
1acba85b
JS
364 if (__begin1 == __end1)
365 return __op.__first_empty(__begin2, __end2, __result);
c2ba9709 366
1acba85b
JS
367 if (__begin2 == __end2)
368 return __op.__second_empty(__begin1, __end1, __result);
c2ba9709 369
1acba85b 370 const _DifferenceType size = (__end1 - __begin1) + (__end2 - __begin2);
c2ba9709 371
1acba85b
JS
372 const _IteratorPair __sequence[ 2 ] =
373 { std::make_pair(__begin1, __end1), std::make_pair(__begin2, __end2) } ;
374 _OutputIterator return_value = __result;
375 _DifferenceType *__borders;
376 _IteratorPair *__block_begins;
377 _DifferenceType* __lengths;
c2ba9709 378
1acba85b
JS
379 _ThreadIndex __num_threads =
380 std::min<_DifferenceType>(__get_max_threads(),
381 std::min(__end1 - __begin1, __end2 - __begin2));
e683ee2a 382
1acba85b 383# pragma omp parallel num_threads(__num_threads)
e683ee2a
JS
384 {
385# pragma omp single
386 {
1acba85b
JS
387 __num_threads = omp_get_num_threads();
388
389 __borders = new _DifferenceType[__num_threads + 2];
390 equally_split(size, __num_threads + 1, __borders);
391 __block_begins = new _IteratorPair[__num_threads + 1];
392 // Very __start.
393 __block_begins[0] = std::make_pair(__begin1, __begin2);
394 __lengths = new _DifferenceType[__num_threads];
e683ee2a
JS
395 } //single
396
1acba85b 397 _ThreadIndex __iam = omp_get_thread_num();
e683ee2a 398
1acba85b
JS
399 // _Result from multiseq_partition.
400 _IIter __offset[2];
401 const _DifferenceType __rank = __borders[__iam + 1];
e683ee2a 402
54384f7f 403 multiseq_partition(__sequence, __sequence + 2, __rank, __offset, __op._M_comp);
e683ee2a
JS
404
405 // allowed to read?
406 // together
1acba85b
JS
407 // *(__offset[ 0 ] - 1) == *__offset[ 1 ]
408 if (__offset[ 0 ] != __begin1 && __offset[ 1 ] != __end2
54384f7f
JS
409 && !__op._M_comp(*(__offset[ 0 ] - 1), *__offset[ 1 ])
410 && !__op._M_comp(*__offset[ 1 ], *(__offset[ 0 ] - 1)))
e683ee2a
JS
411 {
412 // Avoid split between globally equal elements: move one to
413 // front in first sequence.
1acba85b 414 --__offset[ 0 ];
e683ee2a
JS
415 }
416
1acba85b
JS
417 _IteratorPair block_end = __block_begins[ __iam + 1 ] =
418 _IteratorPair(__offset[ 0 ], __offset[ 1 ]);
e683ee2a
JS
419
420 // Make sure all threads have their block_begin result written out.
421# pragma omp barrier
422
1acba85b 423 _IteratorPair __block_begin = __block_begins[ __iam ];
e683ee2a
JS
424
425 // Begin working for the first block, while the others except
426 // the last start to count.
1acba85b 427 if (__iam == 0)
e683ee2a
JS
428 {
429 // The first thread can copy already.
1acba85b
JS
430 __lengths[ __iam ] = __op._M_invoke(__block_begin.first, block_end.first,
431 __block_begin.second, block_end.second,
432 __result)
433 - __result;
e683ee2a
JS
434 }
435 else
436 {
1acba85b
JS
437 __lengths[ __iam ] = __op.__count(__block_begin.first, block_end.first,
438 __block_begin.second, block_end.second);
e683ee2a
JS
439 }
440
441 // Make sure everyone wrote their lengths.
442# pragma omp barrier
443
1acba85b 444 _OutputIterator __r = __result;
e683ee2a 445
1acba85b 446 if (__iam == 0)
e683ee2a
JS
447 {
448 // Do the last block.
1acba85b
JS
449 for (int __i = 0; __i < __num_threads; ++__i)
450 __r += __lengths[__i];
e683ee2a 451
1acba85b 452 __block_begin = __block_begins[__num_threads];
e683ee2a
JS
453
454 // Return the result iterator of the last block.
1acba85b
JS
455 return_value = __op._M_invoke(
456 __block_begin.first, __end1, __block_begin.second, __end2, __r);
e683ee2a
JS
457
458 }
459 else
460 {
1acba85b
JS
461 for (int __i = 0; __i < __iam; ++__i)
462 __r += __lengths[ __i ];
e683ee2a
JS
463
464 // Reset begins for copy pass.
1acba85b
JS
465 __op._M_invoke(__block_begin.first, block_end.first,
466 __block_begin.second, block_end.second, __r);
e683ee2a
JS
467 }
468 }
c2ba9709
JS
469 return return_value;
470 }
471
472
1acba85b
JS
473template<typename _IIter,
474 typename _OutputIterator,
475 typename _Compare>
476 inline _OutputIterator
477 __parallel_set_union(_IIter __begin1, _IIter __end1,
478 _IIter __begin2, _IIter __end2,
54384f7f 479 _OutputIterator __result, _Compare _M_comp)
c2ba9709 480 {
1acba85b 481 return __parallel_set_operation(__begin1, __end1, __begin2, __end2, __result,
54384f7f 482 __union_func< _IIter, _OutputIterator, _Compare>(_M_comp));
c2ba9709
JS
483 }
484
1acba85b
JS
485template<typename _IIter,
486 typename _OutputIterator,
487 typename _Compare>
488 inline _OutputIterator
489 __parallel_set_intersection(_IIter __begin1, _IIter __end1,
490 _IIter __begin2, _IIter __end2,
54384f7f 491 _OutputIterator __result, _Compare _M_comp)
c2ba9709 492 {
1acba85b 493 return __parallel_set_operation(__begin1, __end1, __begin2, __end2, __result,
54384f7f 494 __intersection_func<_IIter, _OutputIterator, _Compare>(_M_comp));
c2ba9709
JS
495 }
496
1acba85b
JS
497template<typename _IIter,
498 typename _OutputIterator,
499 typename _Compare>
500 inline _OutputIterator
501 __parallel_set_difference(_IIter __begin1, _IIter __end1,
502 _IIter __begin2, _IIter __end2,
54384f7f 503 _OutputIterator __result, _Compare _M_comp)
c2ba9709 504 {
1acba85b 505 return __parallel_set_operation(__begin1, __end1, __begin2, __end2, __result,
54384f7f 506 __difference_func<_IIter, _OutputIterator, _Compare>(_M_comp));
c2ba9709
JS
507 }
508
1acba85b
JS
509template<typename _IIter,
510 typename _OutputIterator,
511 typename _Compare>
512 inline _OutputIterator
513 __parallel_set_symmetric_difference(_IIter __begin1, _IIter __end1,
514 _IIter __begin2, _IIter __end2,
54384f7f 515 _OutputIterator __result, _Compare _M_comp)
c2ba9709 516 {
1acba85b
JS
517 return __parallel_set_operation(__begin1, __end1, __begin2, __end2, __result,
518 symmetric_difference_func<_IIter, _OutputIterator, _Compare>
54384f7f 519 (_M_comp));
c2ba9709
JS
520 }
521
522}
523
cbcd1e45 524#endif /* _GLIBCXX_PARALLEL_SET_OPERATIONS_H */