3 // Copyright (C) 2007-2018 Free Software Foundation, Inc.
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 3, or (at your option) any later
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 // 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.
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/>.
26 * @file parallel/set_operations.h
27 * @brief Parallel implementations of set operations for random-access
29 * This file is a GNU parallel extension to the Standard C++ Library.
32 // Written by Marius Elvert and Felix Bondarenko.
34 #ifndef _GLIBCXX_PARALLEL_SET_OPERATIONS_H
35 #define _GLIBCXX_PARALLEL_SET_OPERATIONS_H 1
39 #include <parallel/settings.h>
40 #include <parallel/multiseq_selection.h>
42 namespace __gnu_parallel
44 template<typename _IIter
, typename _OutputIterator
>
46 __copy_tail(std::pair
<_IIter
, _IIter
> __b
,
47 std::pair
<_IIter
, _IIter
> __e
, _OutputIterator __r
)
49 if (__b
.first
!= __e
.first
)
53 *__r
++ = *__b
.first
++;
55 while (__b
.first
!= __e
.first
);
59 while (__b
.second
!= __e
.second
)
60 *__r
++ = *__b
.second
++;
65 template<typename _IIter
,
66 typename _OutputIterator
,
68 struct __symmetric_difference_func
70 typedef std::iterator_traits
<_IIter
> _TraitsType
;
71 typedef typename
_TraitsType::difference_type _DifferenceType
;
72 typedef typename
std::pair
<_IIter
, _IIter
> _IteratorPair
;
74 __symmetric_difference_func(_Compare __comp
) : _M_comp(__comp
) {}
79 _M_invoke(_IIter __a
, _IIter __b
, _IIter __c
, _IIter __d
,
80 _OutputIterator __r
) const
82 while (__a
!= __b
&& __c
!= __d
)
84 if (_M_comp(*__a
, *__c
))
90 else if (_M_comp(*__c
, *__a
))
102 return std::copy(__c
, __d
, std::copy(__a
, __b
, __r
));
106 __count(_IIter __a
, _IIter __b
, _IIter __c
, _IIter __d
) const
108 _DifferenceType __counter
= 0;
110 while (__a
!= __b
&& __c
!= __d
)
112 if (_M_comp(*__a
, *__c
))
117 else if (_M_comp(*__c
, *__a
))
129 return __counter
+ (__b
- __a
) + (__d
- __c
);
133 __first_empty(_IIter __c
, _IIter __d
, _OutputIterator __out
) const
134 { return std::copy(__c
, __d
, __out
); }
137 __second_empty(_IIter __a
, _IIter __b
, _OutputIterator __out
) const
138 { return std::copy(__a
, __b
, __out
); }
142 template<typename _IIter
,
143 typename _OutputIterator
,
145 struct __difference_func
147 typedef std::iterator_traits
<_IIter
> _TraitsType
;
148 typedef typename
_TraitsType::difference_type _DifferenceType
;
149 typedef typename
std::pair
<_IIter
, _IIter
> _IteratorPair
;
151 __difference_func(_Compare __comp
) : _M_comp(__comp
) {}
156 _M_invoke(_IIter __a
, _IIter __b
, _IIter __c
, _IIter __d
,
157 _OutputIterator __r
) const
159 while (__a
!= __b
&& __c
!= __d
)
161 if (_M_comp(*__a
, *__c
))
167 else if (_M_comp(*__c
, *__a
))
175 return std::copy(__a
, __b
, __r
);
179 __count(_IIter __a
, _IIter __b
,
180 _IIter __c
, _IIter __d
) const
182 _DifferenceType __counter
= 0;
184 while (__a
!= __b
&& __c
!= __d
)
186 if (_M_comp(*__a
, *__c
))
191 else if (_M_comp(*__c
, *__a
))
197 return __counter
+ (__b
- __a
);
201 __first_empty(_IIter
, _IIter
, _OutputIterator __out
) const
205 __second_empty(_IIter __a
, _IIter __b
, _OutputIterator __out
) const
206 { return std::copy(__a
, __b
, __out
); }
210 template<typename _IIter
,
211 typename _OutputIterator
,
213 struct __intersection_func
215 typedef std::iterator_traits
<_IIter
> _TraitsType
;
216 typedef typename
_TraitsType::difference_type _DifferenceType
;
217 typedef typename
std::pair
<_IIter
, _IIter
> _IteratorPair
;
219 __intersection_func(_Compare __comp
) : _M_comp(__comp
) {}
224 _M_invoke(_IIter __a
, _IIter __b
, _IIter __c
, _IIter __d
,
225 _OutputIterator __r
) const
227 while (__a
!= __b
&& __c
!= __d
)
229 if (_M_comp(*__a
, *__c
))
231 else if (_M_comp(*__c
, *__a
))
246 __count(_IIter __a
, _IIter __b
, _IIter __c
, _IIter __d
) const
248 _DifferenceType __counter
= 0;
250 while (__a
!= __b
&& __c
!= __d
)
252 if (_M_comp(*__a
, *__c
))
254 else if (_M_comp(*__c
, *__a
))
268 __first_empty(_IIter
, _IIter
, _OutputIterator __out
) const
272 __second_empty(_IIter
, _IIter
, _OutputIterator __out
) const
276 template<class _IIter
, class _OutputIterator
, class _Compare
>
279 typedef typename
std::iterator_traits
<_IIter
>::difference_type
282 __union_func(_Compare __comp
) : _M_comp(__comp
) {}
287 _M_invoke(_IIter __a
, const _IIter __b
, _IIter __c
,
288 const _IIter __d
, _OutputIterator __r
) const
290 while (__a
!= __b
&& __c
!= __d
)
292 if (_M_comp(*__a
, *__c
))
297 else if (_M_comp(*__c
, *__a
))
310 return std::copy(__c
, __d
, std::copy(__a
, __b
, __r
));
314 __count(_IIter __a
, _IIter __b
, _IIter __c
, _IIter __d
) const
316 _DifferenceType __counter
= 0;
318 while (__a
!= __b
&& __c
!= __d
)
320 if (_M_comp(*__a
, *__c
))
322 else if (_M_comp(*__c
, *__a
))
332 __counter
+= (__b
- __a
);
333 __counter
+= (__d
- __c
);
338 __first_empty(_IIter __c
, _IIter __d
, _OutputIterator __out
) const
339 { return std::copy(__c
, __d
, __out
); }
342 __second_empty(_IIter __a
, _IIter __b
, _OutputIterator __out
) const
343 { return std::copy(__a
, __b
, __out
); }
346 template<typename _IIter
,
347 typename _OutputIterator
,
350 __parallel_set_operation(_IIter __begin1
, _IIter __end1
,
351 _IIter __begin2
, _IIter __end2
,
352 _OutputIterator __result
, _Operation __op
)
354 _GLIBCXX_CALL((__end1
- __begin1
) + (__end2
- __begin2
))
356 typedef std::iterator_traits
<_IIter
> _TraitsType
;
357 typedef typename
_TraitsType::difference_type _DifferenceType
;
358 typedef typename
std::pair
<_IIter
, _IIter
> _IteratorPair
;
360 if (__begin1
== __end1
)
361 return __op
.__first_empty(__begin2
, __end2
, __result
);
363 if (__begin2
== __end2
)
364 return __op
.__second_empty(__begin1
, __end1
, __result
);
366 const _DifferenceType __size
= (__end1
- __begin1
) + (__end2
- __begin2
);
368 const _IteratorPair __sequence
[2] = { std::make_pair(__begin1
, __end1
),
369 std::make_pair(__begin2
, __end2
) };
370 _OutputIterator __return_value
= __result
;
371 _DifferenceType
*__borders
;
372 _IteratorPair
*__block_begins
;
373 _DifferenceType
* __lengths
;
375 _ThreadIndex __num_threads
=
376 std::min
<_DifferenceType
>(__get_max_threads(),
377 std::min(__end1
- __begin1
, __end2
- __begin2
));
379 # pragma omp parallel num_threads(__num_threads)
383 __num_threads
= omp_get_num_threads();
385 __borders
= new _DifferenceType
[__num_threads
+ 2];
386 __equally_split(__size
, __num_threads
+ 1, __borders
);
387 __block_begins
= new _IteratorPair
[__num_threads
+ 1];
389 __block_begins
[0] = std::make_pair(__begin1
, __begin2
);
390 __lengths
= new _DifferenceType
[__num_threads
];
393 _ThreadIndex __iam
= omp_get_thread_num();
395 // _Result from multiseq_partition.
397 const _DifferenceType __rank
= __borders
[__iam
+ 1];
399 multiseq_partition(__sequence
, __sequence
+ 2,
400 __rank
, __offset
, __op
._M_comp
);
404 // *(__offset[ 0 ] - 1) == *__offset[ 1 ]
405 if (__offset
[ 0 ] != __begin1
&& __offset
[1] != __end2
406 && !__op
._M_comp(*(__offset
[0] - 1), *__offset
[1])
407 && !__op
._M_comp(*__offset
[1], *(__offset
[0] - 1)))
409 // Avoid split between globally equal elements: move one to
410 // front in first sequence.
414 _IteratorPair __block_end
= __block_begins
[__iam
+ 1] =
415 _IteratorPair(__offset
[0], __offset
[1]);
417 // Make sure all threads have their block_begin result written out.
420 _IteratorPair __block_begin
= __block_begins
[__iam
];
422 // Begin working for the first block, while the others except
423 // the last start to count.
426 // The first thread can copy already.
428 __op
._M_invoke(__block_begin
.first
, __block_end
.first
,
429 __block_begin
.second
, __block_end
.second
,
430 __result
) - __result
;
435 __op
.__count(__block_begin
.first
, __block_end
.first
,
436 __block_begin
.second
, __block_end
.second
);
439 // Make sure everyone wrote their lengths.
442 _OutputIterator __r
= __result
;
446 // Do the last block.
447 for (_ThreadIndex __i
= 0; __i
< __num_threads
; ++__i
)
448 __r
+= __lengths
[__i
];
450 __block_begin
= __block_begins
[__num_threads
];
452 // Return the result iterator of the last block.
454 __op
._M_invoke(__block_begin
.first
, __end1
,
455 __block_begin
.second
, __end2
, __r
);
460 for (_ThreadIndex __i
= 0; __i
< __iam
; ++__i
)
461 __r
+= __lengths
[ __i
];
463 // Reset begins for copy pass.
464 __op
._M_invoke(__block_begin
.first
, __block_end
.first
,
465 __block_begin
.second
, __block_end
.second
, __r
);
468 return __return_value
;
471 template<typename _IIter
,
472 typename _OutputIterator
,
474 inline _OutputIterator
475 __parallel_set_union(_IIter __begin1
, _IIter __end1
,
476 _IIter __begin2
, _IIter __end2
,
477 _OutputIterator __result
, _Compare __comp
)
479 return __parallel_set_operation(__begin1
, __end1
, __begin2
, __end2
,
481 __union_func
< _IIter
, _OutputIterator
,
485 template<typename _IIter
,
486 typename _OutputIterator
,
488 inline _OutputIterator
489 __parallel_set_intersection(_IIter __begin1
, _IIter __end1
,
490 _IIter __begin2
, _IIter __end2
,
491 _OutputIterator __result
, _Compare __comp
)
493 return __parallel_set_operation(__begin1
, __end1
, __begin2
, __end2
,
495 __intersection_func
<_IIter
,
496 _OutputIterator
, _Compare
>(__comp
));
499 template<typename _IIter
,
500 typename _OutputIterator
,
502 inline _OutputIterator
503 __parallel_set_difference(_IIter __begin1
, _IIter __end1
,
504 _IIter __begin2
, _IIter __end2
,
505 _OutputIterator __result
, _Compare __comp
)
507 return __parallel_set_operation(__begin1
, __end1
, __begin2
, __end2
,
509 __difference_func
<_IIter
,
510 _OutputIterator
, _Compare
>(__comp
));
513 template<typename _IIter
,
514 typename _OutputIterator
,
516 inline _OutputIterator
517 __parallel_set_symmetric_difference(_IIter __begin1
, _IIter __end1
,
518 _IIter __begin2
, _IIter __end2
,
519 _OutputIterator __result
,
522 return __parallel_set_operation(__begin1
, __end1
, __begin2
, __end2
,
524 __symmetric_difference_func
<_IIter
,
525 _OutputIterator
, _Compare
>(__comp
));
529 #endif /* _GLIBCXX_PARALLEL_SET_OPERATIONS_H */