3 // Copyright (C) 2007 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
, 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
) {}
82 inline OutputIterator
invoke(InputIterator a
, InputIterator b
,
83 InputIterator c
, InputIterator d
,
84 OutputIterator r
) const
86 while (a
!= b
&& c
!= d
)
94 else if (comp(*c
, *a
))
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
)
121 else if (comp(*c
, *a
))
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
) {}
158 inline OutputIterator
159 invoke(InputIterator a
, InputIterator b
, InputIterator c
, InputIterator d
,
160 OutputIterator r
) const
162 while (a
!= b
&& c
!= d
)
170 else if (comp(*c
, *a
))
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
)
193 else if (comp(*c
, *a
))
199 return counter
+ (b
- a
);
202 inline OutputIterator
203 first_empty(InputIterator c
, InputIterator d
, OutputIterator out
) const
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
) {}
223 inline OutputIterator
224 invoke(InputIterator a
, InputIterator b
, InputIterator c
, InputIterator d
,
225 OutputIterator r
) const
227 while (a
!= b
&& c
!= d
)
231 else if (comp(*c
, *a
))
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
)
254 else if (comp(*c
, *a
))
267 inline OutputIterator
268 first_empty(InputIterator c
, InputIterator d
, OutputIterator out
) const
271 inline OutputIterator
272 second_empty(InputIterator a
, InputIterator b
, OutputIterator out
) const
276 template<class InputIterator
, class OutputIterator
, class Comparator
>
279 typedef typename
std::iterator_traits
<InputIterator
>::difference_type difference_type
;
281 union_func(Comparator c
) : comp(c
) {}
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
)
296 else if (comp(*c
, *a
))
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
)
322 else if (comp(*c
, *a
))
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
>
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
;
360 return op
.first_empty(begin2
, end2
, result
);
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];
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
;
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
);
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.
408 iterator_pair block_end
= block_begins
[ iam
+ 1 ] = iterator_pair(offset
[ 0 ], offset
[ 1 ]);
412 // Make sure all threads have their block_begin result written out.
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.
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
;
428 length
[ iam
] = op
.count(block_begin
.first
, block_end
.first
,
429 block_begin
.second
, block_end
.second
);
434 // Make sure everyone wrote their lengths.
438 OutputIterator r
= result
;
442 // Do the last block.
443 for (int i
= 0; i
< num_threads
; ++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
);
454 for (int i
= 0; i
< iam
; ++i
)
457 // Reset begins for copy pass.
458 op
.invoke(block_begin
.first
, block_end
.first
,
459 block_begin
.second
, block_end
.second
, r
);
469 template<typename InputIterator
, typename OutputIterator
, typename Comparator
>
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
>
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
>
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
>
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
>
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_