Import gcc-4.7.2 to new vendor branch
[dragonfly.git] / contrib / gcc-4.7 / libstdc++-v3 / include / parallel / set_operations.h
1 // -*- C++ -*-
2
3 // Copyright (C) 2007, 2008, 2009, 2010, 2011 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 3, or (at your option) any later
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
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.
19
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/>.
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
42 namespace __gnu_parallel
43 {
44   template<typename _IIter, typename _OutputIterator>
45     _OutputIterator
46     __copy_tail(std::pair<_IIter, _IIter> __b,
47                 std::pair<_IIter, _IIter> __e, _OutputIterator __r)
48     {
49       if (__b.first != __e.first)
50         {
51           do
52             {
53               *__r++ = *__b.first++;
54             }
55           while (__b.first != __e.first);
56         }
57       else
58         {
59           while (__b.second != __e.second)
60             *__r++ = *__b.second++;
61         }
62       return __r;
63     }
64
65   template<typename _IIter,
66            typename _OutputIterator,
67            typename _Compare>
68     struct __symmetric_difference_func
69     {
70       typedef std::iterator_traits<_IIter> _TraitsType;
71       typedef typename _TraitsType::difference_type _DifferenceType;
72       typedef typename std::pair<_IIter, _IIter> _IteratorPair;
73
74       __symmetric_difference_func(_Compare __comp) : _M_comp(__comp) {}
75
76       _Compare _M_comp;
77
78       _OutputIterator
79       _M_invoke(_IIter __a, _IIter __b, _IIter __c, _IIter __d,
80                 _OutputIterator __r) const
81       {
82         while (__a != __b && __c != __d)
83           {
84             if (_M_comp(*__a, *__c))
85               {
86                 *__r = *__a;
87                 ++__a;
88                 ++__r;
89               }
90             else if (_M_comp(*__c, *__a))
91               {
92                 *__r = *__c;
93                 ++__c;
94                 ++__r;
95               }
96             else
97               {
98                 ++__a;
99                 ++__c;
100               }
101           }
102         return std::copy(__c, __d, std::copy(__a, __b, __r));
103       }
104
105       _DifferenceType
106       __count(_IIter __a, _IIter __b, _IIter __c, _IIter __d) const
107       {
108         _DifferenceType __counter = 0;
109
110         while (__a != __b && __c != __d)
111           {
112             if (_M_comp(*__a, *__c))
113               {
114                 ++__a;
115                 ++__counter;
116               }
117             else if (_M_comp(*__c, *__a))
118               {
119                 ++__c;
120                 ++__counter;
121               }
122             else
123               {
124                 ++__a;
125                 ++__c;
126               }
127           }
128
129         return __counter + (__b - __a) + (__d - __c);
130       }
131
132       _OutputIterator
133       __first_empty(_IIter __c, _IIter __d, _OutputIterator __out) const
134       { return std::copy(__c, __d, __out); }
135
136       _OutputIterator
137       __second_empty(_IIter __a, _IIter __b, _OutputIterator __out) const
138       { return std::copy(__a, __b, __out); }
139     };
140
141
142   template<typename _IIter,
143            typename _OutputIterator,
144            typename _Compare>
145     struct __difference_func
146     {
147       typedef std::iterator_traits<_IIter> _TraitsType;
148       typedef typename _TraitsType::difference_type _DifferenceType;
149       typedef typename std::pair<_IIter, _IIter> _IteratorPair;
150
151       __difference_func(_Compare __comp) : _M_comp(__comp) {}
152
153       _Compare _M_comp;
154
155       _OutputIterator
156       _M_invoke(_IIter __a, _IIter __b, _IIter __c, _IIter __d,
157                 _OutputIterator __r) const
158       {
159         while (__a != __b && __c != __d)
160           {
161             if (_M_comp(*__a, *__c))
162               {
163                 *__r = *__a;
164                 ++__a;
165                 ++__r;
166               }
167             else if (_M_comp(*__c, *__a))
168               { ++__c; }
169             else
170               {
171                 ++__a;
172                 ++__c;
173               }
174           }
175         return std::copy(__a, __b, __r);
176       }
177
178       _DifferenceType
179       __count(_IIter __a, _IIter __b,
180               _IIter __c, _IIter __d) const
181       {
182         _DifferenceType __counter = 0;
183
184         while (__a != __b && __c != __d)
185           {
186             if (_M_comp(*__a, *__c))
187               {
188                 ++__a;
189                 ++__counter;
190               }
191             else if (_M_comp(*__c, *__a))
192               { ++__c; }
193             else
194               { ++__a; ++__c; }
195           }
196
197         return __counter + (__b - __a);
198       }
199
200       _OutputIterator
201       __first_empty(_IIter, _IIter, _OutputIterator __out) const
202       { return __out; }
203
204       _OutputIterator
205       __second_empty(_IIter __a, _IIter __b, _OutputIterator __out) const
206       { return std::copy(__a, __b, __out); }
207     };
208
209
210   template<typename _IIter,
211            typename _OutputIterator,
212            typename _Compare>
213     struct __intersection_func
214     {
215       typedef std::iterator_traits<_IIter> _TraitsType;
216       typedef typename _TraitsType::difference_type _DifferenceType;
217       typedef typename std::pair<_IIter, _IIter> _IteratorPair;
218
219       __intersection_func(_Compare __comp) : _M_comp(__comp) {}
220
221       _Compare _M_comp;
222
223       _OutputIterator
224       _M_invoke(_IIter __a, _IIter __b, _IIter __c, _IIter __d,
225                 _OutputIterator __r) const
226       {
227         while (__a != __b && __c != __d)
228           {
229             if (_M_comp(*__a, *__c))
230               { ++__a; }
231             else if (_M_comp(*__c, *__a))
232               { ++__c; }
233             else
234               {
235                 *__r = *__a;
236                 ++__a;
237                 ++__c;
238                 ++__r;
239               }
240           }
241
242         return __r;
243       }
244
245       _DifferenceType
246       __count(_IIter __a, _IIter __b, _IIter __c, _IIter __d) const
247       {
248         _DifferenceType __counter = 0;
249
250         while (__a != __b && __c != __d)
251           {
252             if (_M_comp(*__a, *__c))
253               { ++__a; }
254             else if (_M_comp(*__c, *__a))
255               { ++__c; }
256             else
257               {
258                 ++__a;
259                 ++__c;
260                 ++__counter;
261               }
262           }
263
264         return __counter;
265       }
266
267       _OutputIterator
268       __first_empty(_IIter, _IIter, _OutputIterator __out) const
269       { return __out; }
270
271       _OutputIterator
272       __second_empty(_IIter, _IIter, _OutputIterator __out) const
273       { return __out; }
274     };
275
276   template<class _IIter, class _OutputIterator, class _Compare>
277     struct __union_func
278     {
279       typedef typename std::iterator_traits<_IIter>::difference_type
280       _DifferenceType;
281
282       __union_func(_Compare __comp) : _M_comp(__comp) {}
283
284       _Compare _M_comp;
285
286       _OutputIterator
287       _M_invoke(_IIter __a, const _IIter __b, _IIter __c,
288                 const _IIter __d, _OutputIterator __r) const
289       {
290         while (__a != __b && __c != __d)
291           {
292             if (_M_comp(*__a, *__c))
293               {
294                 *__r = *__a;
295                 ++__a;
296               }
297             else if (_M_comp(*__c, *__a))
298               {
299                 *__r = *__c;
300                 ++__c;
301               }
302             else
303               {
304                 *__r = *__a;
305                 ++__a;
306                 ++__c;
307               }
308             ++__r;
309           }
310         return std::copy(__c, __d, std::copy(__a, __b, __r));
311       }
312
313       _DifferenceType
314       __count(_IIter __a, _IIter __b, _IIter __c, _IIter __d) const
315       {
316         _DifferenceType __counter = 0;
317
318         while (__a != __b && __c != __d)
319           {
320             if (_M_comp(*__a, *__c))
321               { ++__a; }
322             else if (_M_comp(*__c, *__a))
323               { ++__c; }
324             else
325               {
326                 ++__a;
327                 ++__c;
328               }
329             ++__counter;
330           }
331
332         __counter += (__b - __a);
333         __counter += (__d - __c);
334         return __counter;
335       }
336
337       _OutputIterator
338       __first_empty(_IIter __c, _IIter __d, _OutputIterator __out) const
339       { return std::copy(__c, __d, __out); }
340
341       _OutputIterator
342       __second_empty(_IIter __a, _IIter __b, _OutputIterator __out) const
343       { return std::copy(__a, __b, __out); }
344     };
345
346   template<typename _IIter,
347            typename _OutputIterator,
348            typename _Operation>
349     _OutputIterator
350     __parallel_set_operation(_IIter __begin1, _IIter __end1,
351                              _IIter __begin2, _IIter __end2,
352                              _OutputIterator __result, _Operation __op)
353     {
354       _GLIBCXX_CALL((__end1 - __begin1) + (__end2 - __begin2))
355
356       typedef std::iterator_traits<_IIter> _TraitsType;
357       typedef typename _TraitsType::difference_type _DifferenceType;
358       typedef typename std::pair<_IIter, _IIter> _IteratorPair;
359
360       if (__begin1 == __end1)
361         return __op.__first_empty(__begin2, __end2, __result);
362
363       if (__begin2 == __end2)
364         return __op.__second_empty(__begin1, __end1, __result);
365
366       const _DifferenceType __size = (__end1 - __begin1) + (__end2 - __begin2);
367
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;
374
375       _ThreadIndex __num_threads =
376           std::min<_DifferenceType>(__get_max_threads(),
377               std::min(__end1 - __begin1, __end2 - __begin2));
378
379 #     pragma omp parallel num_threads(__num_threads)
380       {
381 #       pragma omp single
382         {
383           __num_threads = omp_get_num_threads();
384
385           __borders = new _DifferenceType[__num_threads + 2];
386           __equally_split(__size, __num_threads + 1, __borders);
387           __block_begins = new _IteratorPair[__num_threads + 1];
388           // Very __start.
389           __block_begins[0] = std::make_pair(__begin1, __begin2);
390           __lengths = new _DifferenceType[__num_threads];
391         } //single
392
393         _ThreadIndex __iam = omp_get_thread_num();
394
395         // _Result from multiseq_partition.
396         _IIter __offset[2];
397         const _DifferenceType __rank = __borders[__iam + 1];
398
399         multiseq_partition(__sequence, __sequence + 2,
400                            __rank, __offset, __op._M_comp);
401
402         // allowed to read?
403         // together
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)))
408           {
409             // Avoid split between globally equal elements: move one to
410             // front in first sequence.
411               --__offset[0];
412           }
413
414         _IteratorPair __block_end = __block_begins[__iam + 1] =
415           _IteratorPair(__offset[0], __offset[1]);
416
417         // Make sure all threads have their block_begin result written out.
418 #       pragma omp barrier
419
420         _IteratorPair __block_begin = __block_begins[__iam];
421
422         // Begin working for the first block, while the others except
423         // the last start to count.
424         if (__iam == 0)
425           {
426             // The first thread can copy already.
427             __lengths[ __iam ] =
428               __op._M_invoke(__block_begin.first, __block_end.first,
429                              __block_begin.second, __block_end.second,
430                              __result) - __result;
431           }
432         else
433           {
434             __lengths[ __iam ] =
435               __op.__count(__block_begin.first, __block_end.first,
436                            __block_begin.second, __block_end.second);
437           }
438
439         // Make sure everyone wrote their lengths.
440 #       pragma omp barrier
441
442         _OutputIterator __r = __result;
443
444         if (__iam == 0)
445           {
446             // Do the last block.
447             for (_ThreadIndex __i = 0; __i < __num_threads; ++__i)
448               __r += __lengths[__i];
449
450             __block_begin = __block_begins[__num_threads];
451
452             // Return the result iterator of the last block.
453             __return_value =
454               __op._M_invoke(__block_begin.first, __end1,
455                              __block_begin.second, __end2, __r);
456
457           }
458           else
459             {
460               for (_ThreadIndex __i = 0; __i < __iam; ++__i)
461                 __r += __lengths[ __i ];
462
463               // Reset begins for copy pass.
464               __op._M_invoke(__block_begin.first, __block_end.first,
465                              __block_begin.second, __block_end.second, __r);
466             }
467         }
468       return __return_value;
469     }
470
471   template<typename _IIter,
472            typename _OutputIterator,
473            typename _Compare>
474     inline _OutputIterator
475     __parallel_set_union(_IIter __begin1, _IIter __end1,
476                          _IIter __begin2, _IIter __end2,
477                          _OutputIterator __result, _Compare __comp)
478     {
479       return __parallel_set_operation(__begin1, __end1, __begin2, __end2,
480                                       __result,
481                                       __union_func< _IIter, _OutputIterator,
482                                       _Compare>(__comp));
483     }
484
485   template<typename _IIter,
486            typename _OutputIterator,
487            typename _Compare>
488     inline _OutputIterator
489     __parallel_set_intersection(_IIter __begin1, _IIter __end1,
490                                 _IIter __begin2, _IIter __end2,
491                                 _OutputIterator __result, _Compare __comp)
492     {
493       return __parallel_set_operation(__begin1, __end1, __begin2, __end2,
494                                       __result,
495                                       __intersection_func<_IIter,
496                                       _OutputIterator, _Compare>(__comp));
497     }
498
499   template<typename _IIter,
500            typename _OutputIterator,
501            typename _Compare>
502     inline _OutputIterator
503     __parallel_set_difference(_IIter __begin1, _IIter __end1,
504                               _IIter __begin2, _IIter __end2,
505                               _OutputIterator __result, _Compare __comp)
506     {
507       return __parallel_set_operation(__begin1, __end1, __begin2, __end2,
508                                       __result,
509                                       __difference_func<_IIter,
510                                       _OutputIterator, _Compare>(__comp));
511     }
512
513   template<typename _IIter,
514            typename _OutputIterator,
515            typename _Compare>
516     inline _OutputIterator
517     __parallel_set_symmetric_difference(_IIter __begin1, _IIter __end1,
518                                         _IIter __begin2, _IIter __end2,
519                                         _OutputIterator __result,
520                                         _Compare __comp)
521     {
522       return __parallel_set_operation(__begin1, __end1, __begin2, __end2,
523                                       __result,
524                                       __symmetric_difference_func<_IIter,
525                                       _OutputIterator, _Compare>(__comp));
526     }
527 }
528
529 #endif /* _GLIBCXX_PARALLEL_SET_OPERATIONS_H */