3 // Copyright (C) 2007, 2008 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 2, 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 // 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
32 * @file parallel/set_operations.h
33 * @brief Parallel implementations of set operations for random-access
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
45 #include <parallel/settings.h>
46 #include <parallel/multiseq_selection.h>
48 namespace __gnu_parallel
50 template<typename InputIterator
, typename OutputIterator
>
52 copy_tail(std::pair
<InputIterator
, InputIterator
> b
,
53 std::pair
<InputIterator
, InputIterator
> e
, OutputIterator r
)
55 if (b
.first
!= e
.first
)
61 while (b
.first
!= e
.first
);
65 while (b
.second
!= e
.second
)
71 template<typename InputIterator
,
72 typename OutputIterator
,
74 struct symmetric_difference_func
76 typedef std::iterator_traits
<InputIterator
> traits_type
;
77 typedef typename
traits_type::difference_type difference_type
;
78 typedef typename
std::pair
<InputIterator
, InputIterator
> iterator_pair
;
80 symmetric_difference_func(Comparator c
) : comp(c
) {}
85 invoke(InputIterator a
, InputIterator b
,
86 InputIterator c
, InputIterator d
,
87 OutputIterator r
) const
89 while (a
!= b
&& c
!= d
)
97 else if (comp(*c
, *a
))
109 return std::copy(c
, d
, std::copy(a
, b
, r
));
113 count(InputIterator a
, InputIterator b
,
114 InputIterator c
, InputIterator d
) const
116 difference_type counter
= 0;
118 while (a
!= b
&& c
!= d
)
125 else if (comp(*c
, *a
))
137 return counter
+ (b
- a
) + (d
- c
);
141 first_empty(InputIterator c
, InputIterator d
, OutputIterator out
) const
142 { return std::copy(c
, d
, out
); }
145 second_empty(InputIterator a
, InputIterator b
, OutputIterator out
) const
146 { return std::copy(a
, b
, out
); }
150 template<typename InputIterator
,
151 typename OutputIterator
,
153 struct difference_func
155 typedef std::iterator_traits
<InputIterator
> traits_type
;
156 typedef typename
traits_type::difference_type difference_type
;
157 typedef typename
std::pair
<InputIterator
, InputIterator
> iterator_pair
;
159 difference_func(Comparator c
) : comp(c
) {}
164 invoke(InputIterator a
, InputIterator b
, InputIterator c
, InputIterator d
,
165 OutputIterator r
) const
167 while (a
!= b
&& c
!= d
)
175 else if (comp(*c
, *a
))
183 return std::copy(a
, b
, r
);
187 count(InputIterator a
, InputIterator b
,
188 InputIterator c
, InputIterator d
) const
190 difference_type counter
= 0;
192 while (a
!= b
&& c
!= d
)
199 else if (comp(*c
, *a
))
205 return counter
+ (b
- a
);
208 inline OutputIterator
209 first_empty(InputIterator c
, InputIterator d
, OutputIterator out
) const
212 inline OutputIterator
213 second_empty(InputIterator a
, InputIterator b
, OutputIterator out
) const
214 { return std::copy(a
, b
, out
); }
218 template<typename InputIterator
,
219 typename OutputIterator
,
221 struct intersection_func
223 typedef std::iterator_traits
<InputIterator
> traits_type
;
224 typedef typename
traits_type::difference_type difference_type
;
225 typedef typename
std::pair
<InputIterator
, InputIterator
> iterator_pair
;
227 intersection_func(Comparator c
) : comp(c
) {}
232 invoke(InputIterator a
, InputIterator b
, InputIterator c
, InputIterator d
,
233 OutputIterator r
) const
235 while (a
!= b
&& c
!= d
)
239 else if (comp(*c
, *a
))
254 count(InputIterator a
, InputIterator b
,
255 InputIterator c
, InputIterator d
) const
257 difference_type counter
= 0;
259 while (a
!= b
&& c
!= d
)
263 else if (comp(*c
, *a
))
276 inline OutputIterator
277 first_empty(InputIterator c
, InputIterator d
, OutputIterator out
) const
280 inline OutputIterator
281 second_empty(InputIterator a
, InputIterator b
, OutputIterator out
) const
285 template<class InputIterator
, class OutputIterator
, class Comparator
>
288 typedef typename
std::iterator_traits
<InputIterator
>::difference_type
291 union_func(Comparator c
) : comp(c
) {}
296 invoke(InputIterator a
, const InputIterator b
, InputIterator c
,
297 const InputIterator d
, OutputIterator r
) const
299 while (a
!= b
&& c
!= d
)
306 else if (comp(*c
, *a
))
319 return std::copy(c
, d
, std::copy(a
, b
, r
));
323 count(InputIterator a
, InputIterator b
,
324 InputIterator c
, InputIterator d
) const
326 difference_type counter
= 0;
328 while (a
!= b
&& c
!= d
)
332 else if (comp(*c
, *a
))
347 inline OutputIterator
348 first_empty(InputIterator c
, InputIterator d
, OutputIterator out
) const
349 { return std::copy(c
, d
, out
); }
351 inline OutputIterator
352 second_empty(InputIterator a
, InputIterator b
, OutputIterator out
) const
353 { return std::copy(a
, b
, out
); }
356 template<typename InputIterator
,
357 typename OutputIterator
,
360 parallel_set_operation(InputIterator begin1
, InputIterator end1
,
361 InputIterator begin2
, InputIterator end2
,
362 OutputIterator result
, Operation op
)
364 _GLIBCXX_CALL((end1
- begin1
) + (end2
- begin2
))
366 typedef std::iterator_traits
<InputIterator
> traits_type
;
367 typedef typename
traits_type::difference_type difference_type
;
368 typedef typename
std::pair
<InputIterator
, InputIterator
> iterator_pair
;
371 return op
.first_empty(begin2
, end2
, result
);
374 return op
.second_empty(begin1
, end1
, result
);
376 const difference_type size
= (end1
- begin1
) + (end2
- begin2
);
378 const iterator_pair sequence
[ 2 ] =
379 { std::make_pair(begin1
, end1
), std::make_pair(begin2
, end2
) } ;
380 OutputIterator return_value
= result
;
381 difference_type
*borders
;
382 iterator_pair
*block_begins
;
383 difference_type
* lengths
;
385 thread_index_t num_threads
=
386 std::min
<difference_type
>(get_max_threads(),
387 std::min(end1
- begin1
, end2
- begin2
));
389 # pragma omp parallel num_threads(num_threads)
393 num_threads
= omp_get_num_threads();
395 borders
= new difference_type
[num_threads
+ 2];
396 equally_split(size
, num_threads
+ 1, borders
);
397 block_begins
= new iterator_pair
[num_threads
+ 1];
399 block_begins
[0] = std::make_pair(begin1
, begin2
);
400 lengths
= new difference_type
[num_threads
];
403 thread_index_t iam
= omp_get_thread_num();
405 // Result from multiseq_partition.
406 InputIterator offset
[2];
407 const difference_type rank
= borders
[iam
+ 1];
409 multiseq_partition(sequence
, sequence
+ 2, rank
, offset
, op
.comp
);
413 // *(offset[ 0 ] - 1) == *offset[ 1 ]
414 if (offset
[ 0 ] != begin1
&& offset
[ 1 ] != end2
415 && !op
.comp(*(offset
[ 0 ] - 1), *offset
[ 1 ])
416 && !op
.comp(*offset
[ 1 ], *(offset
[ 0 ] - 1)))
418 // Avoid split between globally equal elements: move one to
419 // front in first sequence.
423 iterator_pair block_end
= block_begins
[ iam
+ 1 ] =
424 iterator_pair(offset
[ 0 ], offset
[ 1 ]);
426 // Make sure all threads have their block_begin result written out.
429 iterator_pair block_begin
= block_begins
[ iam
];
431 // Begin working for the first block, while the others except
432 // the last start to count.
435 // The first thread can copy already.
436 lengths
[ iam
] = op
.invoke(block_begin
.first
, block_end
.first
,
437 block_begin
.second
, block_end
.second
,
443 lengths
[ iam
] = op
.count(block_begin
.first
, block_end
.first
,
444 block_begin
.second
, block_end
.second
);
447 // Make sure everyone wrote their lengths.
450 OutputIterator r
= result
;
454 // Do the last block.
455 for (int i
= 0; i
< num_threads
; ++i
)
458 block_begin
= block_begins
[num_threads
];
460 // Return the result iterator of the last block.
461 return_value
= op
.invoke(
462 block_begin
.first
, end1
, block_begin
.second
, end2
, r
);
467 for (int i
= 0; i
< iam
; ++i
)
470 // Reset begins for copy pass.
471 op
.invoke(block_begin
.first
, block_end
.first
,
472 block_begin
.second
, block_end
.second
, r
);
479 template<typename InputIterator
,
480 typename OutputIterator
,
482 inline OutputIterator
483 parallel_set_union(InputIterator begin1
, InputIterator end1
,
484 InputIterator begin2
, InputIterator end2
,
485 OutputIterator result
, Comparator comp
)
487 return parallel_set_operation(begin1
, end1
, begin2
, end2
, result
,
488 union_func
< InputIterator
, OutputIterator
, Comparator
>(comp
));
491 template<typename InputIterator
,
492 typename OutputIterator
,
494 inline OutputIterator
495 parallel_set_intersection(InputIterator begin1
, InputIterator end1
,
496 InputIterator begin2
, InputIterator end2
,
497 OutputIterator result
, Comparator comp
)
499 return parallel_set_operation(begin1
, end1
, begin2
, end2
, result
,
500 intersection_func
<InputIterator
, OutputIterator
, Comparator
>(comp
));
504 template<typename InputIterator
, typename OutputIterator
>
505 inline OutputIterator
506 set_intersection(InputIterator begin1
, InputIterator end1
,
507 InputIterator begin2
, InputIterator end2
,
508 OutputIterator result
)
510 typedef std::iterator_traits
<InputIterator
> traits_type
;
511 typedef typename
traits_type::value_type value_type
;
513 return set_intersection(begin1
, end1
, begin2
, end2
, result
,
514 std::less
<value_type
>());
517 template<typename InputIterator
,
518 typename OutputIterator
,
520 inline OutputIterator
521 parallel_set_difference(InputIterator begin1
, InputIterator end1
,
522 InputIterator begin2
, InputIterator end2
,
523 OutputIterator result
, Comparator comp
)
525 return parallel_set_operation(begin1
, end1
, begin2
, end2
, result
,
526 difference_func
<InputIterator
, OutputIterator
, Comparator
>(comp
));
529 template<typename InputIterator
,
530 typename OutputIterator
,
532 inline OutputIterator
533 parallel_set_symmetric_difference(InputIterator begin1
, InputIterator end1
,
534 InputIterator begin2
, InputIterator end2
,
535 OutputIterator result
, Comparator comp
)
537 return parallel_set_operation(begin1
, end1
, begin2
, end2
, result
,
538 symmetric_difference_func
<InputIterator
, OutputIterator
, Comparator
>
544 #endif // _GLIBCXX_SET_ALGORITHM_