2009-09-11 Johannes Singler <singler@ira.uka.de>
[gcc.git] / libstdc++-v3 / include / parallel / multiway_merge.h
1 // -*- C++ -*-
2
3 // Copyright (C) 2007, 2008, 2009 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 /** @file parallel/multiway_merge.h
26 * @brief Implementation of sequential and parallel multiway merge.
27 *
28 * Explanations on the high-speed merging routines in the appendix of
29 *
30 * P. Sanders.
31 * Fast priority queues for cached memory.
32 * ACM Journal of Experimental Algorithmics, 5, 2000.
33 *
34 * This file is a GNU parallel extension to the Standard C++ Library.
35 */
36
37 // Written by Johannes Singler and Manuel Holtgrewe.
38
39 #ifndef _GLIBCXX_PARALLEL_MULTIWAY_MERGE_H
40 #define _GLIBCXX_PARALLEL_MULTIWAY_MERGE_H
41
42 #include <vector>
43
44 #include <bits/stl_algo.h>
45 #include <parallel/features.h>
46 #include <parallel/parallel.h>
47 #include <parallel/losertree.h>
48 #if _GLIBCXX_ASSERTIONS
49 #include <parallel/checkers.h>
50 #endif
51
52 /** @brief Length of a sequence described by a pair of iterators. */
53 #define _GLIBCXX_PARALLEL_LENGTH(s) ((s).second - (s).first)
54
55 namespace __gnu_parallel
56 {
57
58 // Announce guarded and unguarded iterator.
59
60 template<typename RandomAccessIterator, typename Comparator>
61 class guarded_iterator;
62
63 // Making the arguments const references seems to dangerous,
64 // the user-defined comparator might not be const.
65 template<typename RandomAccessIterator, typename Comparator>
66 inline bool
67 operator<(guarded_iterator<RandomAccessIterator, Comparator>& bi1,
68 guarded_iterator<RandomAccessIterator, Comparator>& bi2);
69
70 template<typename RandomAccessIterator, typename Comparator>
71 inline bool
72 operator<=(guarded_iterator<RandomAccessIterator, Comparator>& bi1,
73 guarded_iterator<RandomAccessIterator, Comparator>& bi2);
74
75 /** @brief Iterator wrapper supporting an implicit supremum at the end
76 * of the sequence, dominating all comparisons.
77 *
78 * The implicit supremum comes with a performance cost.
79 *
80 * Deriving from RandomAccessIterator is not possible since
81 * RandomAccessIterator need not be a class.
82 */
83 template<typename RandomAccessIterator, typename Comparator>
84 class guarded_iterator
85 {
86 private:
87 /** @brief Current iterator position. */
88 RandomAccessIterator current;
89
90 /** @brief End iterator of the sequence. */
91 RandomAccessIterator end;
92
93 /** @brief Comparator. */
94 Comparator& comp;
95
96 public:
97 /** @brief Constructor. Sets iterator to beginning of sequence.
98 * @param begin Begin iterator of sequence.
99 * @param end End iterator of sequence.
100 * @param comp Comparator provided for associated overloaded
101 * compare operators. */
102 guarded_iterator(RandomAccessIterator begin,
103 RandomAccessIterator end, Comparator& comp)
104 : current(begin), end(end), comp(comp)
105 { }
106
107 /** @brief Pre-increment operator.
108 * @return This. */
109 guarded_iterator<RandomAccessIterator, Comparator>&
110 operator++()
111 {
112 ++current;
113 return *this;
114 }
115
116 /** @brief Dereference operator.
117 * @return Referenced element. */
118 typename std::iterator_traits<RandomAccessIterator>::value_type&
119 operator*()
120 { return *current; }
121
122 /** @brief Convert to wrapped iterator.
123 * @return Wrapped iterator. */
124 operator RandomAccessIterator()
125 { return current; }
126
127 friend bool
128 operator< <RandomAccessIterator, Comparator>(
129 guarded_iterator<RandomAccessIterator, Comparator>& bi1,
130 guarded_iterator<RandomAccessIterator, Comparator>& bi2);
131
132 friend bool
133 operator<= <RandomAccessIterator, Comparator>(
134 guarded_iterator<RandomAccessIterator, Comparator>& bi1,
135 guarded_iterator<RandomAccessIterator, Comparator>& bi2);
136 };
137
138 /** @brief Compare two elements referenced by guarded iterators.
139 * @param bi1 First iterator.
140 * @param bi2 Second iterator.
141 * @return @c True if less. */
142 template<typename RandomAccessIterator, typename Comparator>
143 inline bool
144 operator<(guarded_iterator<RandomAccessIterator, Comparator>& bi1,
145 guarded_iterator<RandomAccessIterator, Comparator>& bi2)
146 {
147 if (bi1.current == bi1.end) //bi1 is sup
148 return bi2.current == bi2.end; //bi2 is not sup
149 if (bi2.current == bi2.end) //bi2 is sup
150 return true;
151 return (bi1.comp)(*bi1, *bi2); //normal compare
152 }
153
154 /** @brief Compare two elements referenced by guarded iterators.
155 * @param bi1 First iterator.
156 * @param bi2 Second iterator.
157 * @return @c True if less equal. */
158 template<typename RandomAccessIterator, typename Comparator>
159 inline bool
160 operator<=(guarded_iterator<RandomAccessIterator, Comparator>& bi1,
161 guarded_iterator<RandomAccessIterator, Comparator>& bi2)
162 {
163 if (bi2.current == bi2.end) //bi1 is sup
164 return bi1.current != bi1.end; //bi2 is not sup
165 if (bi1.current == bi1.end) //bi2 is sup
166 return false;
167 return !(bi1.comp)(*bi2, *bi1); //normal compare
168 }
169
170 template<typename RandomAccessIterator, typename Comparator>
171 class unguarded_iterator;
172
173 template<typename RandomAccessIterator, typename Comparator>
174 inline bool
175 operator<(unguarded_iterator<RandomAccessIterator, Comparator>& bi1,
176 unguarded_iterator<RandomAccessIterator, Comparator>& bi2);
177
178 template<typename RandomAccessIterator, typename Comparator>
179 inline bool
180 operator<=(unguarded_iterator<RandomAccessIterator, Comparator>& bi1,
181 unguarded_iterator<RandomAccessIterator, Comparator>& bi2);
182
183 template<typename RandomAccessIterator, typename Comparator>
184 class unguarded_iterator
185 {
186 private:
187 /** @brief Current iterator position. */
188 RandomAccessIterator current;
189 /** @brief Comparator. */
190 mutable Comparator& comp;
191
192 public:
193 /** @brief Constructor. Sets iterator to beginning of sequence.
194 * @param begin Begin iterator of sequence.
195 * @param end Unused, only for compatibility.
196 * @param comp Unused, only for compatibility. */
197 unguarded_iterator(RandomAccessIterator begin,
198 RandomAccessIterator end, Comparator& comp)
199 : current(begin), comp(comp)
200 { }
201
202 /** @brief Pre-increment operator.
203 * @return This. */
204 unguarded_iterator<RandomAccessIterator, Comparator>&
205 operator++()
206 {
207 ++current;
208 return *this;
209 }
210
211 /** @brief Dereference operator.
212 * @return Referenced element. */
213 typename std::iterator_traits<RandomAccessIterator>::value_type&
214 operator*()
215 { return *current; }
216
217 /** @brief Convert to wrapped iterator.
218 * @return Wrapped iterator. */
219 operator RandomAccessIterator()
220 { return current; }
221
222 friend bool
223 operator< <RandomAccessIterator, Comparator>(
224 unguarded_iterator<RandomAccessIterator, Comparator>& bi1,
225 unguarded_iterator<RandomAccessIterator, Comparator>& bi2);
226
227 friend bool
228 operator<= <RandomAccessIterator, Comparator>(
229 unguarded_iterator<RandomAccessIterator, Comparator>& bi1,
230 unguarded_iterator<RandomAccessIterator, Comparator>& bi2);
231 };
232
233 /** @brief Compare two elements referenced by unguarded iterators.
234 * @param bi1 First iterator.
235 * @param bi2 Second iterator.
236 * @return @c True if less. */
237 template<typename RandomAccessIterator, typename Comparator>
238 inline bool
239 operator<(unguarded_iterator<RandomAccessIterator, Comparator>& bi1,
240 unguarded_iterator<RandomAccessIterator, Comparator>& bi2)
241 {
242 // Normal compare.
243 return (bi1.comp)(*bi1, *bi2);
244 }
245
246 /** @brief Compare two elements referenced by unguarded iterators.
247 * @param bi1 First iterator.
248 * @param bi2 Second iterator.
249 * @return @c True if less equal. */
250 template<typename RandomAccessIterator, typename Comparator>
251 inline bool
252 operator<=(unguarded_iterator<RandomAccessIterator, Comparator>& bi1,
253 unguarded_iterator<RandomAccessIterator, Comparator>& bi2)
254 {
255 // Normal compare.
256 return !(bi1.comp)(*bi2, *bi1);
257 }
258
259 /** @brief Highly efficient 3-way merging procedure.
260 *
261 * Merging is done with the algorithm implementation described by Peter
262 * Sanders. Basically, the idea is to minimize the number of necessary
263 * comparison after merging out an element. The implementation trick
264 * that makes this fast is that the order of the sequences is stored
265 * in the instruction pointer (translated into labels in C++).
266 *
267 * This works well for merging up to 4 sequences.
268 *
269 * Note that making the merging stable does <em>not</em> come at a
270 * performance hit.
271 *
272 * Whether the merging is done guarded or unguarded is selected by the
273 * used iterator class.
274 *
275 * @param seqs_begin Begin iterator of iterator pair input sequence.
276 * @param seqs_end End iterator of iterator pair input sequence.
277 * @param target Begin iterator out output sequence.
278 * @param comp Comparator.
279 * @param length Maximum length to merge, less equal than the
280 * total number of elements available.
281 *
282 * @return End iterator of output sequence.
283 */
284 template<template<typename RAI, typename C> class iterator,
285 typename RandomAccessIteratorIterator,
286 typename RandomAccessIterator3,
287 typename _DifferenceTp,
288 typename Comparator>
289 RandomAccessIterator3
290 multiway_merge_3_variant(
291 RandomAccessIteratorIterator seqs_begin,
292 RandomAccessIteratorIterator seqs_end,
293 RandomAccessIterator3 target,
294 _DifferenceTp length, Comparator comp)
295 {
296 _GLIBCXX_CALL(length);
297
298 typedef _DifferenceTp difference_type;
299
300 typedef typename std::iterator_traits<RandomAccessIteratorIterator>
301 ::value_type::first_type
302 RandomAccessIterator1;
303 typedef typename std::iterator_traits<RandomAccessIterator1>::value_type
304 value_type;
305
306 if (length == 0)
307 return target;
308
309 #if _GLIBCXX_ASSERTIONS
310 _DifferenceTp orig_length = length;
311 #endif
312
313 iterator<RandomAccessIterator1, Comparator>
314 seq0(seqs_begin[0].first, seqs_begin[0].second, comp),
315 seq1(seqs_begin[1].first, seqs_begin[1].second, comp),
316 seq2(seqs_begin[2].first, seqs_begin[2].second, comp);
317
318 if (seq0 <= seq1)
319 {
320 if (seq1 <= seq2)
321 goto s012;
322 else
323 if (seq2 < seq0)
324 goto s201;
325 else
326 goto s021;
327 }
328 else
329 {
330 if (seq1 <= seq2)
331 {
332 if (seq0 <= seq2)
333 goto s102;
334 else
335 goto s120;
336 }
337 else
338 goto s210;
339 }
340 #define _GLIBCXX_PARALLEL_MERGE_3_CASE(a,b,c,c0,c1) \
341 s ## a ## b ## c : \
342 *target = *seq ## a; \
343 ++target; \
344 --length; \
345 ++seq ## a; \
346 if (length == 0) goto finish; \
347 if (seq ## a c0 seq ## b) goto s ## a ## b ## c; \
348 if (seq ## a c1 seq ## c) goto s ## b ## a ## c; \
349 goto s ## b ## c ## a;
350
351 _GLIBCXX_PARALLEL_MERGE_3_CASE(0, 1, 2, <=, <=);
352 _GLIBCXX_PARALLEL_MERGE_3_CASE(1, 2, 0, <=, < );
353 _GLIBCXX_PARALLEL_MERGE_3_CASE(2, 0, 1, < , < );
354 _GLIBCXX_PARALLEL_MERGE_3_CASE(1, 0, 2, < , <=);
355 _GLIBCXX_PARALLEL_MERGE_3_CASE(0, 2, 1, <=, <=);
356 _GLIBCXX_PARALLEL_MERGE_3_CASE(2, 1, 0, < , < );
357
358 #undef _GLIBCXX_PARALLEL_MERGE_3_CASE
359
360 finish:
361 ;
362
363 #if _GLIBCXX_ASSERTIONS
364 _GLIBCXX_PARALLEL_ASSERT(
365 ((RandomAccessIterator1)seq0 - seqs_begin[0].first) +
366 ((RandomAccessIterator1)seq1 - seqs_begin[1].first) +
367 ((RandomAccessIterator1)seq2 - seqs_begin[2].first)
368 == orig_length);
369 #endif
370
371 seqs_begin[0].first = seq0;
372 seqs_begin[1].first = seq1;
373 seqs_begin[2].first = seq2;
374
375 return target;
376 }
377
378 /**
379 * @brief Highly efficient 4-way merging procedure.
380 *
381 * Merging is done with the algorithm implementation described by Peter
382 * Sanders. Basically, the idea is to minimize the number of necessary
383 * comparison after merging out an element. The implementation trick
384 * that makes this fast is that the order of the sequences is stored
385 * in the instruction pointer (translated into goto labels in C++).
386 *
387 * This works well for merging up to 4 sequences.
388 *
389 * Note that making the merging stable does <em>not</em> come at a
390 * performance hit.
391 *
392 * Whether the merging is done guarded or unguarded is selected by the
393 * used iterator class.
394 *
395 * @param seqs_begin Begin iterator of iterator pair input sequence.
396 * @param seqs_end End iterator of iterator pair input sequence.
397 * @param target Begin iterator out output sequence.
398 * @param comp Comparator.
399 * @param length Maximum length to merge, less equal than the
400 * total number of elements available.
401 *
402 * @return End iterator of output sequence.
403 */
404 template<template<typename RAI, typename C> class iterator,
405 typename RandomAccessIteratorIterator,
406 typename RandomAccessIterator3,
407 typename _DifferenceTp,
408 typename Comparator>
409 RandomAccessIterator3
410 multiway_merge_4_variant(RandomAccessIteratorIterator seqs_begin,
411 RandomAccessIteratorIterator seqs_end,
412 RandomAccessIterator3 target,
413 _DifferenceTp length, Comparator comp)
414 {
415 _GLIBCXX_CALL(length);
416 typedef _DifferenceTp difference_type;
417
418 typedef typename std::iterator_traits<RandomAccessIteratorIterator>
419 ::value_type::first_type
420 RandomAccessIterator1;
421 typedef typename std::iterator_traits<RandomAccessIterator1>::value_type
422 value_type;
423
424 iterator<RandomAccessIterator1, Comparator>
425 seq0(seqs_begin[0].first, seqs_begin[0].second, comp),
426 seq1(seqs_begin[1].first, seqs_begin[1].second, comp),
427 seq2(seqs_begin[2].first, seqs_begin[2].second, comp),
428 seq3(seqs_begin[3].first, seqs_begin[3].second, comp);
429
430 #define _GLIBCXX_PARALLEL_DECISION(a,b,c,d) { \
431 if (seq ## d < seq ## a) goto s ## d ## a ## b ## c; \
432 if (seq ## d < seq ## b) goto s ## a ## d ## b ## c; \
433 if (seq ## d < seq ## c) goto s ## a ## b ## d ## c; \
434 goto s ## a ## b ## c ## d; }
435
436 if (seq0 <= seq1)
437 {
438 if (seq1 <= seq2)
439 _GLIBCXX_PARALLEL_DECISION(0,1,2,3)
440 else
441 if (seq2 < seq0)
442 _GLIBCXX_PARALLEL_DECISION(2,0,1,3)
443 else
444 _GLIBCXX_PARALLEL_DECISION(0,2,1,3)
445 }
446 else
447 {
448 if (seq1 <= seq2)
449 {
450 if (seq0 <= seq2)
451 _GLIBCXX_PARALLEL_DECISION(1,0,2,3)
452 else
453 _GLIBCXX_PARALLEL_DECISION(1,2,0,3)
454 }
455 else
456 _GLIBCXX_PARALLEL_DECISION(2,1,0,3)
457 }
458
459 #define _GLIBCXX_PARALLEL_MERGE_4_CASE(a,b,c,d,c0,c1,c2) \
460 s ## a ## b ## c ## d: \
461 if (length == 0) goto finish; \
462 *target = *seq ## a; \
463 ++target; \
464 --length; \
465 ++seq ## a; \
466 if (seq ## a c0 seq ## b) goto s ## a ## b ## c ## d; \
467 if (seq ## a c1 seq ## c) goto s ## b ## a ## c ## d; \
468 if (seq ## a c2 seq ## d) goto s ## b ## c ## a ## d; \
469 goto s ## b ## c ## d ## a;
470
471 _GLIBCXX_PARALLEL_MERGE_4_CASE(0, 1, 2, 3, <=, <=, <=);
472 _GLIBCXX_PARALLEL_MERGE_4_CASE(0, 1, 3, 2, <=, <=, <=);
473 _GLIBCXX_PARALLEL_MERGE_4_CASE(0, 2, 1, 3, <=, <=, <=);
474 _GLIBCXX_PARALLEL_MERGE_4_CASE(0, 2, 3, 1, <=, <=, <=);
475 _GLIBCXX_PARALLEL_MERGE_4_CASE(0, 3, 1, 2, <=, <=, <=);
476 _GLIBCXX_PARALLEL_MERGE_4_CASE(0, 3, 2, 1, <=, <=, <=);
477 _GLIBCXX_PARALLEL_MERGE_4_CASE(1, 0, 2, 3, < , <=, <=);
478 _GLIBCXX_PARALLEL_MERGE_4_CASE(1, 0, 3, 2, < , <=, <=);
479 _GLIBCXX_PARALLEL_MERGE_4_CASE(1, 2, 0, 3, <=, < , <=);
480 _GLIBCXX_PARALLEL_MERGE_4_CASE(1, 2, 3, 0, <=, <=, < );
481 _GLIBCXX_PARALLEL_MERGE_4_CASE(1, 3, 0, 2, <=, < , <=);
482 _GLIBCXX_PARALLEL_MERGE_4_CASE(1, 3, 2, 0, <=, <=, < );
483 _GLIBCXX_PARALLEL_MERGE_4_CASE(2, 0, 1, 3, < , < , <=);
484 _GLIBCXX_PARALLEL_MERGE_4_CASE(2, 0, 3, 1, < , <=, < );
485 _GLIBCXX_PARALLEL_MERGE_4_CASE(2, 1, 0, 3, < , < , <=);
486 _GLIBCXX_PARALLEL_MERGE_4_CASE(2, 1, 3, 0, < , <=, < );
487 _GLIBCXX_PARALLEL_MERGE_4_CASE(2, 3, 0, 1, <=, < , < );
488 _GLIBCXX_PARALLEL_MERGE_4_CASE(2, 3, 1, 0, <=, < , < );
489 _GLIBCXX_PARALLEL_MERGE_4_CASE(3, 0, 1, 2, < , < , < );
490 _GLIBCXX_PARALLEL_MERGE_4_CASE(3, 0, 2, 1, < , < , < );
491 _GLIBCXX_PARALLEL_MERGE_4_CASE(3, 1, 0, 2, < , < , < );
492 _GLIBCXX_PARALLEL_MERGE_4_CASE(3, 1, 2, 0, < , < , < );
493 _GLIBCXX_PARALLEL_MERGE_4_CASE(3, 2, 0, 1, < , < , < );
494 _GLIBCXX_PARALLEL_MERGE_4_CASE(3, 2, 1, 0, < , < , < );
495
496 #undef _GLIBCXX_PARALLEL_MERGE_4_CASE
497 #undef _GLIBCXX_PARALLEL_DECISION
498
499 finish:
500 ;
501
502 seqs_begin[0].first = seq0;
503 seqs_begin[1].first = seq1;
504 seqs_begin[2].first = seq2;
505 seqs_begin[3].first = seq3;
506
507 return target;
508 }
509
510 /** @brief Multi-way merging procedure for a high branching factor,
511 * guarded case.
512 *
513 * This merging variant uses a LoserTree class as selected by <tt>LT</tt>.
514 *
515 * Stability is selected through the used LoserTree class <tt>LT</tt>.
516 *
517 * At least one non-empty sequence is required.
518 *
519 * @param seqs_begin Begin iterator of iterator pair input sequence.
520 * @param seqs_end End iterator of iterator pair input sequence.
521 * @param target Begin iterator out output sequence.
522 * @param comp Comparator.
523 * @param length Maximum length to merge, less equal than the
524 * total number of elements available.
525 *
526 * @return End iterator of output sequence.
527 */
528 template<typename LT,
529 typename RandomAccessIteratorIterator,
530 typename RandomAccessIterator3,
531 typename _DifferenceTp,
532 typename Comparator>
533 RandomAccessIterator3
534 multiway_merge_loser_tree(RandomAccessIteratorIterator seqs_begin,
535 RandomAccessIteratorIterator seqs_end,
536 RandomAccessIterator3 target,
537 _DifferenceTp length, Comparator comp)
538 {
539 _GLIBCXX_CALL(length)
540
541 typedef _DifferenceTp difference_type;
542 typedef typename std::iterator_traits<RandomAccessIteratorIterator>
543 ::value_type::first_type
544 RandomAccessIterator1;
545 typedef typename std::iterator_traits<RandomAccessIterator1>::value_type
546 value_type;
547
548 int k = static_cast<int>(seqs_end - seqs_begin);
549
550 LT lt(k, comp);
551
552 // Default value for potentially non-default-constructible types.
553 value_type* arbitrary_element = NULL;
554
555 for (int t = 0; t < k; ++t)
556 {
557 if(arbitrary_element == NULL
558 && _GLIBCXX_PARALLEL_LENGTH(seqs_begin[t]) > 0)
559 arbitrary_element = &(*seqs_begin[t].first);
560 }
561
562 for (int t = 0; t < k; ++t)
563 {
564 if (seqs_begin[t].first == seqs_begin[t].second)
565 lt.insert_start(*arbitrary_element, t, true);
566 else
567 lt.insert_start(*seqs_begin[t].first, t, false);
568 }
569
570 lt.init();
571
572 int source;
573
574 for (difference_type i = 0; i < length; ++i)
575 {
576 //take out
577 source = lt.get_min_source();
578
579 *(target++) = *(seqs_begin[source].first++);
580
581 // Feed.
582 if (seqs_begin[source].first == seqs_begin[source].second)
583 lt.delete_min_insert(*arbitrary_element, true);
584 else
585 // Replace from same source.
586 lt.delete_min_insert(*seqs_begin[source].first, false);
587 }
588
589 return target;
590 }
591
592 /** @brief Multi-way merging procedure for a high branching factor,
593 * unguarded case.
594 *
595 * Merging is done using the LoserTree class <tt>LT</tt>.
596 *
597 * Stability is selected by the used LoserTrees.
598 *
599 * @pre No input will run out of elements during the merge.
600 *
601 * @param seqs_begin Begin iterator of iterator pair input sequence.
602 * @param seqs_end End iterator of iterator pair input sequence.
603 * @param target Begin iterator out output sequence.
604 * @param comp Comparator.
605 * @param length Maximum length to merge, less equal than the
606 * total number of elements available.
607 *
608 * @return End iterator of output sequence.
609 */
610 template<typename LT,
611 typename RandomAccessIteratorIterator,
612 typename RandomAccessIterator3,
613 typename _DifferenceTp, typename Comparator>
614 RandomAccessIterator3
615 multiway_merge_loser_tree_unguarded(
616 RandomAccessIteratorIterator seqs_begin,
617 RandomAccessIteratorIterator seqs_end,
618 RandomAccessIterator3 target,
619 const typename std::iterator_traits<typename std::iterator_traits<
620 RandomAccessIteratorIterator>::value_type::first_type>::value_type&
621 sentinel,
622 _DifferenceTp length,
623 Comparator comp)
624 {
625 _GLIBCXX_CALL(length)
626 typedef _DifferenceTp difference_type;
627
628 typedef typename std::iterator_traits<RandomAccessIteratorIterator>
629 ::value_type::first_type
630 RandomAccessIterator1;
631 typedef typename std::iterator_traits<RandomAccessIterator1>::value_type
632 value_type;
633
634 int k = seqs_end - seqs_begin;
635
636 LT lt(k, sentinel, comp);
637
638 for (int t = 0; t < k; ++t)
639 {
640 #if _GLIBCXX_ASSERTIONS
641 _GLIBCXX_PARALLEL_ASSERT(seqs_begin[t].first != seqs_begin[t].second);
642 #endif
643 lt.insert_start(*seqs_begin[t].first, t, false);
644 }
645
646 lt.init();
647
648 int source;
649
650 #if _GLIBCXX_ASSERTIONS
651 difference_type i = 0;
652 #endif
653
654 RandomAccessIterator3 target_end = target + length;
655 while (target < target_end)
656 {
657 // Take out.
658 source = lt.get_min_source();
659
660 #if _GLIBCXX_ASSERTIONS
661 _GLIBCXX_PARALLEL_ASSERT(0 <= source && source < k);
662 _GLIBCXX_PARALLEL_ASSERT(i == 0
663 || !comp(*(seqs_begin[source].first), *(target - 1)));
664 #endif
665
666 // Feed.
667 *(target++) = *(seqs_begin[source].first++);
668
669 #if _GLIBCXX_ASSERTIONS
670 ++i;
671 #endif
672 // Replace from same source.
673 lt.delete_min_insert(*seqs_begin[source].first, false);
674 }
675
676 return target;
677 }
678
679
680 /** @brief Multi-way merging procedure for a high branching factor,
681 * requiring sentinels to exist.
682 *
683 * @param stable The value must the same as for the used LoserTrees.
684 * @param UnguardedLoserTree Loser Tree variant to use for the unguarded
685 * merging.
686 * @param GuardedLoserTree Loser Tree variant to use for the guarded
687 * merging.
688 *
689 * @param seqs_begin Begin iterator of iterator pair input sequence.
690 * @param seqs_end End iterator of iterator pair input sequence.
691 * @param target Begin iterator out output sequence.
692 * @param comp Comparator.
693 * @param length Maximum length to merge, less equal than the
694 * total number of elements available.
695 *
696 * @return End iterator of output sequence.
697 */
698 template<
699 typename UnguardedLoserTree,
700 typename RandomAccessIteratorIterator,
701 typename RandomAccessIterator3,
702 typename _DifferenceTp,
703 typename Comparator>
704 RandomAccessIterator3
705 multiway_merge_loser_tree_sentinel(
706 RandomAccessIteratorIterator seqs_begin,
707 RandomAccessIteratorIterator seqs_end,
708 RandomAccessIterator3 target,
709 const typename std::iterator_traits<typename std::iterator_traits<
710 RandomAccessIteratorIterator>::value_type::first_type>::value_type&
711 sentinel,
712 _DifferenceTp length,
713 Comparator comp)
714 {
715 _GLIBCXX_CALL(length)
716
717 typedef _DifferenceTp difference_type;
718 typedef std::iterator_traits<RandomAccessIteratorIterator> traits_type;
719 typedef typename std::iterator_traits<RandomAccessIteratorIterator>
720 ::value_type::first_type
721 RandomAccessIterator1;
722 typedef typename std::iterator_traits<RandomAccessIterator1>::value_type
723 value_type;
724
725 RandomAccessIterator3 target_end;
726
727 for (RandomAccessIteratorIterator s = seqs_begin; s != seqs_end; ++s)
728 // Move the sequends end behind the sentinel spots. This has the
729 // effect that the sentinel appears to be within the sequence. Then,
730 // we can use the unguarded variant if we merge out as many
731 // non-sentinel elements as we have.
732 ++((*s).second);
733
734 target_end = multiway_merge_loser_tree_unguarded
735 <UnguardedLoserTree>
736 (seqs_begin, seqs_end, target, sentinel, length, comp);
737
738 #if _GLIBCXX_ASSERTIONS
739 _GLIBCXX_PARALLEL_ASSERT(target_end == target + length);
740 _GLIBCXX_PARALLEL_ASSERT(is_sorted(target, target_end, comp));
741 #endif
742
743 // Restore the sequence ends so the sentinels are not contained in the
744 // sequence any more (see comment in loop above).
745 for (RandomAccessIteratorIterator s = seqs_begin; s != seqs_end; ++s)
746 --((*s).second);
747
748 return target_end;
749 }
750
751 /**
752 * @brief Traits for determining whether the loser tree should
753 * use pointers or copies.
754 *
755 * The field "use_pointer" is used to determine whether to use pointers in
756 * the loser trees or whether to copy the values into the loser tree.
757 *
758 * The default behavior is to use pointers if the data type is 4 times as
759 * big as the pointer to it.
760 *
761 * Specialize for your data type to customize the behavior.
762 *
763 * Example:
764 *
765 * template<>
766 * struct loser_tree_traits<int>
767 * { static const bool use_pointer = false; };
768 *
769 * template<>
770 * struct loser_tree_traits<heavyweight_type>
771 * { static const bool use_pointer = true; };
772 *
773 * @param T type to give the loser tree traits for.
774 */
775 template <typename T>
776 struct loser_tree_traits
777 {
778 /**
779 * @brief True iff to use pointers instead of values in loser trees.
780 *
781 * The default behavior is to use pointers if the data type is four
782 * times as big as the pointer to it.
783 */
784 static const bool use_pointer = (sizeof(T) > 4 * sizeof(T*));
785 };
786
787 /**
788 * @brief Switch for 3-way merging with sentinels turned off.
789 *
790 * Note that 3-way merging is always stable!
791 */
792 template<
793 bool sentinels /*default == false*/,
794 typename RandomAccessIteratorIterator,
795 typename RandomAccessIterator3,
796 typename _DifferenceTp,
797 typename Comparator>
798 struct multiway_merge_3_variant_sentinel_switch
799 {
800 RandomAccessIterator3 operator()(
801 RandomAccessIteratorIterator seqs_begin,
802 RandomAccessIteratorIterator seqs_end,
803 RandomAccessIterator3 target,
804 _DifferenceTp length, Comparator comp)
805 {
806 return multiway_merge_3_variant<guarded_iterator>(
807 seqs_begin, seqs_end, target, length, comp);
808 }
809 };
810
811 /**
812 * @brief Switch for 3-way merging with sentinels turned on.
813 *
814 * Note that 3-way merging is always stable!
815 */
816 template<
817 typename RandomAccessIteratorIterator,
818 typename RandomAccessIterator3,
819 typename _DifferenceTp,
820 typename Comparator>
821 struct multiway_merge_3_variant_sentinel_switch
822 <true, RandomAccessIteratorIterator, RandomAccessIterator3,
823 _DifferenceTp, Comparator>
824 {
825 RandomAccessIterator3 operator()(
826 RandomAccessIteratorIterator seqs_begin,
827 RandomAccessIteratorIterator seqs_end,
828 RandomAccessIterator3 target,
829 _DifferenceTp length, Comparator comp)
830 {
831 return multiway_merge_3_variant<unguarded_iterator>(
832 seqs_begin, seqs_end, target, length, comp);
833 }
834 };
835
836 /**
837 * @brief Switch for 4-way merging with sentinels turned off.
838 *
839 * Note that 4-way merging is always stable!
840 */
841 template<
842 bool sentinels /*default == false*/,
843 typename RandomAccessIteratorIterator,
844 typename RandomAccessIterator3,
845 typename _DifferenceTp,
846 typename Comparator>
847 struct multiway_merge_4_variant_sentinel_switch
848 {
849 RandomAccessIterator3 operator()(
850 RandomAccessIteratorIterator seqs_begin,
851 RandomAccessIteratorIterator seqs_end,
852 RandomAccessIterator3 target,
853 _DifferenceTp length, Comparator comp)
854 {
855 return multiway_merge_4_variant<guarded_iterator>(
856 seqs_begin, seqs_end, target, length, comp);
857 }
858 };
859
860 /**
861 * @brief Switch for 4-way merging with sentinels turned on.
862 *
863 * Note that 4-way merging is always stable!
864 */
865 template<
866 typename RandomAccessIteratorIterator,
867 typename RandomAccessIterator3,
868 typename _DifferenceTp,
869 typename Comparator>
870 struct multiway_merge_4_variant_sentinel_switch
871 <true, RandomAccessIteratorIterator, RandomAccessIterator3,
872 _DifferenceTp, Comparator>
873 {
874 RandomAccessIterator3 operator()(
875 RandomAccessIteratorIterator seqs_begin,
876 RandomAccessIteratorIterator seqs_end,
877 RandomAccessIterator3 target,
878 _DifferenceTp length, Comparator comp)
879 {
880 return multiway_merge_4_variant<unguarded_iterator>(
881 seqs_begin, seqs_end, target, length, comp);
882 }
883 };
884
885 /**
886 * @brief Switch for k-way merging with sentinels turned on.
887 */
888 template<
889 bool sentinels,
890 bool stable,
891 typename RandomAccessIteratorIterator,
892 typename RandomAccessIterator3,
893 typename _DifferenceTp,
894 typename Comparator>
895 struct multiway_merge_k_variant_sentinel_switch
896 {
897 RandomAccessIterator3 operator()(
898 RandomAccessIteratorIterator seqs_begin,
899 RandomAccessIteratorIterator seqs_end,
900 RandomAccessIterator3 target,
901 const typename std::iterator_traits<typename std::iterator_traits<
902 RandomAccessIteratorIterator>::value_type::first_type>::value_type&
903 sentinel,
904 _DifferenceTp length, Comparator comp)
905 {
906 typedef typename std::iterator_traits<RandomAccessIteratorIterator>
907 ::value_type::first_type
908 RandomAccessIterator1;
909 typedef typename std::iterator_traits<RandomAccessIterator1>::value_type
910 value_type;
911
912 return multiway_merge_loser_tree_sentinel<
913 typename __gnu_cxx::__conditional_type<
914 loser_tree_traits<value_type>::use_pointer
915 , LoserTreePointerUnguarded<stable, value_type, Comparator>
916 , LoserTreeUnguarded<stable, value_type, Comparator>
917 >::__type>(seqs_begin, seqs_end, target, sentinel, length, comp);
918 }
919 };
920
921 /**
922 * @brief Switch for k-way merging with sentinels turned off.
923 */
924 template<
925 bool stable,
926 typename RandomAccessIteratorIterator,
927 typename RandomAccessIterator3,
928 typename _DifferenceTp,
929 typename Comparator>
930 struct multiway_merge_k_variant_sentinel_switch
931 <false, stable, RandomAccessIteratorIterator, RandomAccessIterator3,
932 _DifferenceTp, Comparator>
933 {
934 RandomAccessIterator3 operator()(
935 RandomAccessIteratorIterator seqs_begin,
936 RandomAccessIteratorIterator seqs_end,
937 RandomAccessIterator3 target,
938 const typename std::iterator_traits<typename std::iterator_traits<
939 RandomAccessIteratorIterator>::value_type::first_type>::value_type&
940 sentinel,
941 _DifferenceTp length, Comparator comp)
942 {
943 typedef typename std::iterator_traits<RandomAccessIteratorIterator>
944 ::value_type::first_type
945 RandomAccessIterator1;
946 typedef typename std::iterator_traits<RandomAccessIterator1>::value_type
947 value_type;
948
949 return multiway_merge_loser_tree<
950 typename __gnu_cxx::__conditional_type<
951 loser_tree_traits<value_type>::use_pointer
952 , LoserTreePointer<stable, value_type, Comparator>
953 , LoserTree<stable, value_type, Comparator>
954 >::__type >(seqs_begin, seqs_end, target, length, comp);
955 }
956 };
957
958 /** @brief Sequential multi-way merging switch.
959 *
960 * The _GLIBCXX_PARALLEL_DECISION is based on the branching factor and
961 * runtime settings.
962 * @param seqs_begin Begin iterator of iterator pair input sequence.
963 * @param seqs_end End iterator of iterator pair input sequence.
964 * @param target Begin iterator out output sequence.
965 * @param comp Comparator.
966 * @param length Maximum length to merge, possibly larger than the
967 * number of elements available.
968 * @param stable Stable merging incurs a performance penalty.
969 * @param sentinel The sequences have a sentinel element.
970 * @return End iterator of output sequence. */
971 template<
972 bool stable,
973 bool sentinels,
974 typename RandomAccessIteratorIterator,
975 typename RandomAccessIterator3,
976 typename _DifferenceTp,
977 typename Comparator>
978 RandomAccessIterator3
979 sequential_multiway_merge(
980 RandomAccessIteratorIterator seqs_begin,
981 RandomAccessIteratorIterator seqs_end,
982 RandomAccessIterator3 target,
983 const typename std::iterator_traits<typename std::iterator_traits<
984 RandomAccessIteratorIterator>::value_type::first_type>::value_type&
985 sentinel,
986 _DifferenceTp length, Comparator comp)
987 {
988 _GLIBCXX_CALL(length)
989
990 typedef _DifferenceTp difference_type;
991 typedef typename std::iterator_traits<RandomAccessIteratorIterator>
992 ::value_type::first_type
993 RandomAccessIterator1;
994 typedef typename std::iterator_traits<RandomAccessIterator1>::value_type
995 value_type;
996
997 #if _GLIBCXX_ASSERTIONS
998 for (RandomAccessIteratorIterator s = seqs_begin; s != seqs_end; ++s)
999 {
1000 _GLIBCXX_PARALLEL_ASSERT(is_sorted((*s).first, (*s).second, comp));
1001 }
1002 #endif
1003
1004 _DifferenceTp total_length = 0;
1005 for (RandomAccessIteratorIterator s = seqs_begin; s != seqs_end; ++s)
1006 total_length += _GLIBCXX_PARALLEL_LENGTH(*s);
1007
1008 length = std::min<_DifferenceTp>(length, total_length);
1009
1010 if(length == 0)
1011 return target;
1012
1013 RandomAccessIterator3 return_target = target;
1014 int k = static_cast<int>(seqs_end - seqs_begin);
1015
1016 switch (k)
1017 {
1018 case 0:
1019 break;
1020 case 1:
1021 return_target = std::copy(seqs_begin[0].first,
1022 seqs_begin[0].first + length,
1023 target);
1024 seqs_begin[0].first += length;
1025 break;
1026 case 2:
1027 return_target = merge_advance(seqs_begin[0].first,
1028 seqs_begin[0].second,
1029 seqs_begin[1].first,
1030 seqs_begin[1].second,
1031 target, length, comp);
1032 break;
1033 case 3:
1034 return_target = multiway_merge_3_variant_sentinel_switch<
1035 sentinels
1036 , RandomAccessIteratorIterator
1037 , RandomAccessIterator3
1038 , _DifferenceTp
1039 , Comparator>()(seqs_begin, seqs_end, target, length, comp);
1040 break;
1041 case 4:
1042 return_target = multiway_merge_4_variant_sentinel_switch<
1043 sentinels
1044 , RandomAccessIteratorIterator
1045 , RandomAccessIterator3
1046 , _DifferenceTp
1047 , Comparator>()(seqs_begin, seqs_end, target, length, comp);
1048 break;
1049 default:
1050 return_target = multiway_merge_k_variant_sentinel_switch<
1051 sentinels
1052 , stable
1053 , RandomAccessIteratorIterator
1054 , RandomAccessIterator3
1055 , _DifferenceTp
1056 , Comparator>()(seqs_begin, seqs_end, target, sentinel, length, comp);
1057 break;
1058 }
1059 #if _GLIBCXX_ASSERTIONS
1060 _GLIBCXX_PARALLEL_ASSERT(is_sorted(target, target + length, comp));
1061 #endif
1062
1063 return return_target;
1064 }
1065
1066 /**
1067 * @brief Stable sorting functor.
1068 *
1069 * Used to reduce code instanciation in multiway_merge_sampling_splitting.
1070 */
1071 template<bool stable, class RandomAccessIterator, class StrictWeakOrdering>
1072 struct sampling_sorter
1073 {
1074 void operator()(RandomAccessIterator first, RandomAccessIterator last,
1075 StrictWeakOrdering comp)
1076 { __gnu_sequential::stable_sort(first, last, comp); }
1077 };
1078
1079 /**
1080 * @brief Non-stable sorting functor.
1081 *
1082 * Used to reduce code instantiation in multiway_merge_sampling_splitting.
1083 */
1084 template<class RandomAccessIterator, class StrictWeakOrdering>
1085 struct sampling_sorter<false, RandomAccessIterator, StrictWeakOrdering>
1086 {
1087 void operator()(RandomAccessIterator first, RandomAccessIterator last,
1088 StrictWeakOrdering comp)
1089 { __gnu_sequential::sort(first, last, comp); }
1090 };
1091
1092 /**
1093 * @brief Sampling based splitting for parallel multiway-merge routine.
1094 */
1095 template<
1096 bool stable
1097 , typename RandomAccessIteratorIterator
1098 , typename Comparator
1099 , typename difference_type>
1100 void multiway_merge_sampling_splitting(
1101 RandomAccessIteratorIterator seqs_begin,
1102 RandomAccessIteratorIterator seqs_end,
1103 difference_type length, difference_type total_length, Comparator comp,
1104 std::vector<std::pair<difference_type, difference_type> > *pieces)
1105 {
1106 typedef typename std::iterator_traits<RandomAccessIteratorIterator>
1107 ::value_type::first_type
1108 RandomAccessIterator1;
1109 typedef typename std::iterator_traits<RandomAccessIterator1>::value_type
1110 value_type;
1111
1112 // k sequences.
1113 int k = static_cast<int>(seqs_end - seqs_begin);
1114
1115 int num_threads = omp_get_num_threads();
1116
1117 difference_type num_samples =
1118 __gnu_parallel::_Settings::get().merge_oversampling * num_threads;
1119
1120 value_type* samples = static_cast<value_type*>(
1121 ::operator new(sizeof(value_type) * k * num_samples));
1122 // Sample.
1123 for (int s = 0; s < k; ++s)
1124 for (difference_type i = 0; i < num_samples; ++i)
1125 {
1126 difference_type sample_index =
1127 static_cast<difference_type>(
1128 _GLIBCXX_PARALLEL_LENGTH(seqs_begin[s])
1129 * (double(i + 1) / (num_samples + 1))
1130 * (double(length) / total_length));
1131 new(&(samples[s * num_samples + i]))
1132 value_type(seqs_begin[s].first[sample_index]);
1133 }
1134
1135 // Sort stable or non-stable, depending on value of template parameter
1136 // "stable".
1137 sampling_sorter<stable, value_type*, Comparator>()(
1138 samples, samples + (num_samples * k), comp);
1139
1140 for (int slab = 0; slab < num_threads; ++slab)
1141 // For each slab / processor.
1142 for (int seq = 0; seq < k; ++seq)
1143 {
1144 // For each sequence.
1145 if (slab > 0)
1146 pieces[slab][seq].first =
1147 std::upper_bound(
1148 seqs_begin[seq].first,
1149 seqs_begin[seq].second,
1150 samples[num_samples * k * slab / num_threads],
1151 comp)
1152 - seqs_begin[seq].first;
1153 else
1154 // Absolute beginning.
1155 pieces[slab][seq].first = 0;
1156 if ((slab + 1) < num_threads)
1157 pieces[slab][seq].second =
1158 std::upper_bound(
1159 seqs_begin[seq].first,
1160 seqs_begin[seq].second,
1161 samples[num_samples * k * (slab + 1) /
1162 num_threads], comp)
1163 - seqs_begin[seq].first;
1164 else
1165 // Absolute end.
1166 pieces[slab][seq].second = _GLIBCXX_PARALLEL_LENGTH(seqs_begin[seq]);
1167 }
1168 ::operator delete(samples);
1169 }
1170
1171 /**
1172 * @brief Exact splitting for parallel multiway-merge routine.
1173 *
1174 * None of the passed sequences may be empty.
1175 */
1176 template<
1177 bool stable
1178 , typename RandomAccessIteratorIterator
1179 , typename Comparator
1180 , typename difference_type>
1181 void multiway_merge_exact_splitting(
1182 RandomAccessIteratorIterator seqs_begin,
1183 RandomAccessIteratorIterator seqs_end,
1184 difference_type length, difference_type total_length, Comparator comp,
1185 std::vector<std::pair<difference_type, difference_type> > *pieces)
1186 {
1187 typedef typename std::iterator_traits<RandomAccessIteratorIterator>
1188 ::value_type::first_type
1189 RandomAccessIterator1;
1190
1191 const bool tight = (total_length == length);
1192
1193 // k sequences.
1194 const int k = static_cast<int>(seqs_end - seqs_begin);
1195
1196 const int num_threads = omp_get_num_threads();
1197
1198 // (Settings::multiway_merge_splitting == __gnu_parallel::_Settings::EXACT).
1199 std::vector<RandomAccessIterator1>* offsets =
1200 new std::vector<RandomAccessIterator1>[num_threads];
1201 std::vector<
1202 std::pair<RandomAccessIterator1, RandomAccessIterator1>
1203 > se(k);
1204
1205 copy(seqs_begin, seqs_end, se.begin());
1206
1207 difference_type* borders =
1208 new difference_type[num_threads + 1];
1209 equally_split(length, num_threads, borders);
1210
1211 for (int s = 0; s < (num_threads - 1); ++s)
1212 {
1213 offsets[s].resize(k);
1214 multiseq_partition(
1215 se.begin(), se.end(), borders[s + 1],
1216 offsets[s].begin(), comp);
1217
1218 // Last one also needed and available.
1219 if (!tight)
1220 {
1221 offsets[num_threads - 1].resize(k);
1222 multiseq_partition(se.begin(), se.end(),
1223 difference_type(length),
1224 offsets[num_threads - 1].begin(), comp);
1225 }
1226 }
1227 delete[] borders;
1228
1229 for (int slab = 0; slab < num_threads; ++slab)
1230 {
1231 // For each slab / processor.
1232 for (int seq = 0; seq < k; ++seq)
1233 {
1234 // For each sequence.
1235 if (slab == 0)
1236 {
1237 // Absolute beginning.
1238 pieces[slab][seq].first = 0;
1239 }
1240 else
1241 pieces[slab][seq].first =
1242 pieces[slab - 1][seq].second;
1243 if (!tight || slab < (num_threads - 1))
1244 pieces[slab][seq].second =
1245 offsets[slab][seq] - seqs_begin[seq].first;
1246 else
1247 {
1248 // slab == num_threads - 1
1249 pieces[slab][seq].second =
1250 _GLIBCXX_PARALLEL_LENGTH(seqs_begin[seq]);
1251 }
1252 }
1253 }
1254 delete[] offsets;
1255 }
1256
1257 /** @brief Parallel multi-way merge routine.
1258 *
1259 * The _GLIBCXX_PARALLEL_DECISION is based on the branching factor
1260 * and runtime settings.
1261 *
1262 * Must not be called if the number of sequences is 1.
1263 *
1264 * @param Splitter functor to split input (either exact or sampling based)
1265 *
1266 * @param seqs_begin Begin iterator of iterator pair input sequence.
1267 * @param seqs_end End iterator of iterator pair input sequence.
1268 * @param target Begin iterator out output sequence.
1269 * @param comp Comparator.
1270 * @param length Maximum length to merge, possibly larger than the
1271 * number of elements available.
1272 * @param stable Stable merging incurs a performance penalty.
1273 * @param sentinel Ignored.
1274 * @return End iterator of output sequence.
1275 */
1276 template<
1277 bool stable,
1278 bool sentinels,
1279 typename RandomAccessIteratorIterator,
1280 typename RandomAccessIterator3,
1281 typename _DifferenceTp,
1282 typename Splitter,
1283 typename Comparator
1284 >
1285 RandomAccessIterator3
1286 parallel_multiway_merge(RandomAccessIteratorIterator seqs_begin,
1287 RandomAccessIteratorIterator seqs_end,
1288 RandomAccessIterator3 target,
1289 Splitter splitter,
1290 _DifferenceTp length,
1291 Comparator comp,
1292 thread_index_t num_threads)
1293 {
1294 #if _GLIBCXX_ASSERTIONS
1295 _GLIBCXX_PARALLEL_ASSERT(seqs_end - seqs_begin > 1);
1296 #endif
1297
1298 _GLIBCXX_CALL(length)
1299
1300 typedef _DifferenceTp difference_type;
1301 typedef typename std::iterator_traits<RandomAccessIteratorIterator>
1302 ::value_type::first_type
1303 RandomAccessIterator1;
1304 typedef typename
1305 std::iterator_traits<RandomAccessIterator1>::value_type value_type;
1306
1307 // Leave only non-empty sequences.
1308 typedef std::pair<RandomAccessIterator1, RandomAccessIterator1> seq_type;
1309 seq_type* ne_seqs = new seq_type[seqs_end - seqs_begin];
1310 int k = 0;
1311 difference_type total_length = 0;
1312 for (RandomAccessIteratorIterator raii = seqs_begin;
1313 raii != seqs_end; ++raii)
1314 {
1315 _DifferenceTp seq_length = _GLIBCXX_PARALLEL_LENGTH(*raii);
1316 if(seq_length > 0)
1317 {
1318 total_length += seq_length;
1319 ne_seqs[k++] = *raii;
1320 }
1321 }
1322
1323 _GLIBCXX_CALL(total_length)
1324
1325 length = std::min<_DifferenceTp>(length, total_length);
1326
1327 if (total_length == 0 || k == 0)
1328 {
1329 delete[] ne_seqs;
1330 return target;
1331 }
1332
1333 std::vector<std::pair<difference_type, difference_type> >* pieces;
1334
1335 num_threads = static_cast<thread_index_t>
1336 (std::min<difference_type>(num_threads, total_length));
1337
1338 # pragma omp parallel num_threads (num_threads)
1339 {
1340 # pragma omp single
1341 {
1342 num_threads = omp_get_num_threads();
1343 // Thread t will have to merge pieces[iam][0..k - 1]
1344 pieces = new std::vector<
1345 std::pair<difference_type, difference_type> >[num_threads];
1346 for (int s = 0; s < num_threads; ++s)
1347 pieces[s].resize(k);
1348
1349 difference_type num_samples =
1350 __gnu_parallel::_Settings::get().merge_oversampling *
1351 num_threads;
1352
1353 splitter(ne_seqs, ne_seqs + k, length, total_length,
1354 comp, pieces);
1355 } //single
1356
1357 thread_index_t iam = omp_get_thread_num();
1358
1359 difference_type target_position = 0;
1360
1361 for (int c = 0; c < k; ++c)
1362 target_position += pieces[iam][c].first;
1363
1364 seq_type* chunks = new seq_type[k];
1365
1366 for (int s = 0; s < k; ++s)
1367 {
1368 chunks[s] = std::make_pair(
1369 ne_seqs[s].first + pieces[iam][s].first,
1370 ne_seqs[s].first + pieces[iam][s].second);
1371 }
1372
1373 if(length > target_position)
1374 sequential_multiway_merge<stable, sentinels>(
1375 chunks, chunks + k, target + target_position,
1376 *(seqs_begin->second), length - target_position, comp);
1377
1378 delete[] chunks;
1379 } // parallel
1380
1381 #if _GLIBCXX_ASSERTIONS
1382 _GLIBCXX_PARALLEL_ASSERT(is_sorted(target, target + length, comp));
1383 #endif
1384
1385 k = 0;
1386 // Update ends of sequences.
1387 for (RandomAccessIteratorIterator raii = seqs_begin;
1388 raii != seqs_end; ++raii)
1389 {
1390 _DifferenceTp length = _GLIBCXX_PARALLEL_LENGTH(*raii);
1391 if(length > 0)
1392 (*raii).first += pieces[num_threads - 1][k++].second;
1393 }
1394
1395 delete[] pieces;
1396 delete[] ne_seqs;
1397
1398 return target + length;
1399 }
1400
1401 /**
1402 * @brief Multiway Merge Frontend.
1403 *
1404 * Merge the sequences specified by seqs_begin and seqs_end into
1405 * target. seqs_begin and seqs_end must point to a sequence of
1406 * pairs. These pairs must contain an iterator to the beginning
1407 * of a sequence in their first entry and an iterator the end of
1408 * the same sequence in their second entry.
1409 *
1410 * Ties are broken arbitrarily. See stable_multiway_merge for a variant
1411 * that breaks ties by sequence number but is slower.
1412 *
1413 * The first entries of the pairs (i.e. the begin iterators) will be moved
1414 * forward.
1415 *
1416 * The output sequence has to provide enough space for all elements
1417 * that are written to it.
1418 *
1419 * This function will merge the input sequences:
1420 *
1421 * - not stable
1422 * - parallel, depending on the input size and Settings
1423 * - using sampling for splitting
1424 * - not using sentinels
1425 *
1426 * Example:
1427 *
1428 * <pre>
1429 * int sequences[10][10];
1430 * for (int i = 0; i < 10; ++i)
1431 * for (int j = 0; i < 10; ++j)
1432 * sequences[i][j] = j;
1433 *
1434 * int out[33];
1435 * std::vector<std::pair<int*> > seqs;
1436 * for (int i = 0; i < 10; ++i)
1437 * { seqs.push(std::make_pair<int*>(sequences[i], sequences[i] + 10)) }
1438 *
1439 * multiway_merge(seqs.begin(), seqs.end(), target, std::less<int>(), 33);
1440 * </pre>
1441 *
1442 * @see stable_multiway_merge
1443 *
1444 * @pre All input sequences must be sorted.
1445 * @pre Target must provide enough space to merge out length elements or
1446 * the number of elements in all sequences, whichever is smaller.
1447 *
1448 * @post [target, return value) contains merged elements from the
1449 * input sequences.
1450 * @post return value - target = min(length, number of elements in all
1451 * sequences).
1452 *
1453 * @param RandomAccessIteratorPairIterator iterator over sequence
1454 * of pairs of iterators
1455 * @param RandomAccessIteratorOut iterator over target sequence
1456 * @param _DifferenceTp difference type for the sequence
1457 * @param Comparator strict weak ordering type to compare elements
1458 * in sequences
1459 *
1460 * @param seqs_begin begin of sequence sequence
1461 * @param seqs_end end of sequence sequence
1462 * @param target target sequence to merge to.
1463 * @param comp strict weak ordering to use for element comparison.
1464 * @param length Maximum length to merge, possibly larger than the
1465 * number of elements available.
1466 *
1467 * @return end iterator of output sequence
1468 */
1469 // multiway_merge
1470 // public interface
1471 template<
1472 typename RandomAccessIteratorPairIterator
1473 , typename RandomAccessIteratorOut
1474 , typename _DifferenceTp
1475 , typename Comparator>
1476 RandomAccessIteratorOut
1477 multiway_merge(RandomAccessIteratorPairIterator seqs_begin
1478 , RandomAccessIteratorPairIterator seqs_end
1479 , RandomAccessIteratorOut target
1480 , _DifferenceTp length, Comparator comp
1481 , __gnu_parallel::sequential_tag)
1482 {
1483 typedef _DifferenceTp difference_type;
1484 _GLIBCXX_CALL(seqs_end - seqs_begin)
1485
1486 // catch special case: no sequences
1487 if (seqs_begin == seqs_end)
1488 return target;
1489
1490 // Execute multiway merge *sequentially*.
1491 return sequential_multiway_merge
1492 </* stable = */ false, /* sentinels = */ false>
1493 (seqs_begin, seqs_end, target, *(seqs_begin->second), length, comp);
1494 }
1495
1496 // public interface
1497 template<
1498 typename RandomAccessIteratorPairIterator
1499 , typename RandomAccessIteratorOut
1500 , typename _DifferenceTp
1501 , typename Comparator>
1502 RandomAccessIteratorOut
1503 multiway_merge(RandomAccessIteratorPairIterator seqs_begin
1504 , RandomAccessIteratorPairIterator seqs_end
1505 , RandomAccessIteratorOut target
1506 , _DifferenceTp length, Comparator comp
1507 , __gnu_parallel::exact_tag tag)
1508 {
1509 typedef _DifferenceTp difference_type;
1510 _GLIBCXX_CALL(seqs_end - seqs_begin)
1511
1512 // catch special case: no sequences
1513 if (seqs_begin == seqs_end)
1514 return target;
1515
1516 // Execute merge; maybe parallel, depending on the number of merged
1517 // elements and the number of sequences and global thresholds in
1518 // Settings.
1519 if ((seqs_end - seqs_begin > 1) &&
1520 _GLIBCXX_PARALLEL_CONDITION(
1521 ((seqs_end - seqs_begin) >=
1522 __gnu_parallel::_Settings::get().multiway_merge_minimal_k)
1523 && ((sequence_index_t)length >=
1524 __gnu_parallel::_Settings::get().multiway_merge_minimal_n)))
1525 return parallel_multiway_merge
1526 </* stable = */ false, /* sentinels = */ false>(
1527 seqs_begin, seqs_end, target,
1528 multiway_merge_exact_splitting</* stable = */ false,
1529 typename std::iterator_traits<RandomAccessIteratorPairIterator>
1530 ::value_type*, Comparator, _DifferenceTp>,
1531 static_cast<difference_type>(length), comp, tag.get_num_threads());
1532 else
1533 return sequential_multiway_merge
1534 </* stable = */ false, /* sentinels = */ false>(
1535 seqs_begin, seqs_end, target, *(seqs_begin->second), length, comp);
1536 }
1537
1538 // public interface
1539 template<
1540 typename RandomAccessIteratorPairIterator
1541 , typename RandomAccessIteratorOut
1542 , typename _DifferenceTp
1543 , typename Comparator>
1544 RandomAccessIteratorOut
1545 multiway_merge(RandomAccessIteratorPairIterator seqs_begin
1546 , RandomAccessIteratorPairIterator seqs_end
1547 , RandomAccessIteratorOut target
1548 , _DifferenceTp length, Comparator comp
1549 , __gnu_parallel::sampling_tag tag)
1550 {
1551 typedef _DifferenceTp difference_type;
1552 _GLIBCXX_CALL(seqs_end - seqs_begin)
1553
1554 // catch special case: no sequences
1555 if (seqs_begin == seqs_end)
1556 return target;
1557
1558 // Execute merge; maybe parallel, depending on the number of merged
1559 // elements and the number of sequences and global thresholds in
1560 // Settings.
1561 if ((seqs_end - seqs_begin > 1) &&
1562 _GLIBCXX_PARALLEL_CONDITION(
1563 ((seqs_end - seqs_begin) >=
1564 __gnu_parallel::_Settings::get().multiway_merge_minimal_k)
1565 && ((sequence_index_t)length >=
1566 __gnu_parallel::_Settings::get().multiway_merge_minimal_n)))
1567 return parallel_multiway_merge
1568 </* stable = */ false, /* sentinels = */ false>(
1569 seqs_begin, seqs_end,
1570 target,
1571 multiway_merge_exact_splitting</* stable = */ false,
1572 typename std::iterator_traits<RandomAccessIteratorPairIterator>
1573 ::value_type*, Comparator, _DifferenceTp>,
1574 static_cast<difference_type>(length), comp, tag.get_num_threads());
1575 else
1576 return sequential_multiway_merge
1577 </* stable = */ false, /* sentinels = */ false>(
1578 seqs_begin, seqs_end,
1579 target, *(seqs_begin->second), length, comp);
1580 }
1581
1582 // public interface
1583 template<
1584 typename RandomAccessIteratorPairIterator
1585 , typename RandomAccessIteratorOut
1586 , typename _DifferenceTp
1587 , typename Comparator>
1588 RandomAccessIteratorOut
1589 multiway_merge(RandomAccessIteratorPairIterator seqs_begin
1590 , RandomAccessIteratorPairIterator seqs_end
1591 , RandomAccessIteratorOut target
1592 , _DifferenceTp length, Comparator comp
1593 , parallel_tag tag = parallel_tag(0))
1594 {
1595 return multiway_merge(seqs_begin, seqs_end, target, length, comp,
1596 exact_tag(tag.get_num_threads()));
1597 }
1598
1599 // public interface
1600 template<
1601 typename RandomAccessIteratorPairIterator
1602 , typename RandomAccessIteratorOut
1603 , typename _DifferenceTp
1604 , typename Comparator>
1605 RandomAccessIteratorOut
1606 multiway_merge(RandomAccessIteratorPairIterator seqs_begin
1607 , RandomAccessIteratorPairIterator seqs_end
1608 , RandomAccessIteratorOut target
1609 , _DifferenceTp length, Comparator comp
1610 , default_parallel_tag tag)
1611 {
1612 return multiway_merge(seqs_begin, seqs_end, target, length, comp,
1613 exact_tag(tag.get_num_threads()));
1614 }
1615
1616 // stable_multiway_merge
1617 // public interface
1618 template<
1619 typename RandomAccessIteratorPairIterator
1620 , typename RandomAccessIteratorOut
1621 , typename _DifferenceTp
1622 , typename Comparator>
1623 RandomAccessIteratorOut
1624 stable_multiway_merge(RandomAccessIteratorPairIterator seqs_begin
1625 , RandomAccessIteratorPairIterator seqs_end
1626 , RandomAccessIteratorOut target
1627 , _DifferenceTp length, Comparator comp
1628 , __gnu_parallel::sequential_tag)
1629 {
1630 typedef _DifferenceTp difference_type;
1631 _GLIBCXX_CALL(seqs_end - seqs_begin)
1632
1633 // catch special case: no sequences
1634 if (seqs_begin == seqs_end)
1635 return target;
1636
1637 // Execute multiway merge *sequentially*.
1638 return sequential_multiway_merge
1639 </* stable = */ true, /* sentinels = */ false>
1640 (seqs_begin, seqs_end, target, *(seqs_begin->second), length, comp);
1641 }
1642
1643 // public interface
1644 template<
1645 typename RandomAccessIteratorPairIterator
1646 , typename RandomAccessIteratorOut
1647 , typename _DifferenceTp
1648 , typename Comparator>
1649 RandomAccessIteratorOut
1650 stable_multiway_merge(RandomAccessIteratorPairIterator seqs_begin
1651 , RandomAccessIteratorPairIterator seqs_end
1652 , RandomAccessIteratorOut target
1653 , _DifferenceTp length, Comparator comp
1654 , __gnu_parallel::exact_tag tag)
1655 {
1656 typedef _DifferenceTp difference_type;
1657 _GLIBCXX_CALL(seqs_end - seqs_begin)
1658
1659 // catch special case: no sequences
1660 if (seqs_begin == seqs_end)
1661 return target;
1662
1663 // Execute merge; maybe parallel, depending on the number of merged
1664 // elements and the number of sequences and global thresholds in
1665 // Settings.
1666 if ((seqs_end - seqs_begin > 1) &&
1667 _GLIBCXX_PARALLEL_CONDITION(
1668 ((seqs_end - seqs_begin) >=
1669 __gnu_parallel::_Settings::get().multiway_merge_minimal_k)
1670 && ((sequence_index_t)length >=
1671 __gnu_parallel::_Settings::get().multiway_merge_minimal_n)))
1672 return parallel_multiway_merge
1673 </* stable = */ true, /* sentinels = */ false>(
1674 seqs_begin, seqs_end,
1675 target,
1676 multiway_merge_exact_splitting</* stable = */ true,
1677 typename std::iterator_traits<RandomAccessIteratorPairIterator>
1678 ::value_type*, Comparator, _DifferenceTp>,
1679 static_cast<difference_type>(length), comp, tag.get_num_threads());
1680 else
1681 return sequential_multiway_merge</* stable = */ true,
1682 /* sentinels = */ false>(
1683 seqs_begin, seqs_end,
1684 target, *(seqs_begin->second), length, comp);
1685 }
1686
1687 // public interface
1688 template<
1689 typename RandomAccessIteratorPairIterator
1690 , typename RandomAccessIteratorOut
1691 , typename _DifferenceTp
1692 , typename Comparator>
1693 RandomAccessIteratorOut
1694 stable_multiway_merge(RandomAccessIteratorPairIterator seqs_begin
1695 , RandomAccessIteratorPairIterator seqs_end
1696 , RandomAccessIteratorOut target
1697 , _DifferenceTp length, Comparator comp
1698 , sampling_tag tag)
1699 {
1700 typedef _DifferenceTp difference_type;
1701 _GLIBCXX_CALL(seqs_end - seqs_begin)
1702
1703 // catch special case: no sequences
1704 if (seqs_begin == seqs_end)
1705 return target;
1706
1707 // Execute merge; maybe parallel, depending on the number of merged
1708 // elements and the number of sequences and global thresholds in
1709 // Settings.
1710 if ((seqs_end - seqs_begin > 1) &&
1711 _GLIBCXX_PARALLEL_CONDITION(
1712 ((seqs_end - seqs_begin) >=
1713 __gnu_parallel::_Settings::get().multiway_merge_minimal_k)
1714 && ((sequence_index_t)length >=
1715 __gnu_parallel::_Settings::get().multiway_merge_minimal_n)))
1716 return parallel_multiway_merge
1717 </* stable = */ true, /* sentinels = */ false>(
1718 seqs_begin, seqs_end,
1719 target,
1720 multiway_merge_sampling_splitting</* stable = */ true,
1721 typename std::iterator_traits<RandomAccessIteratorPairIterator>
1722 ::value_type*, Comparator, _DifferenceTp>,
1723 static_cast<difference_type>(length), comp, tag.get_num_threads());
1724 else
1725 return sequential_multiway_merge
1726 </* stable = */ true, /* sentinels = */ false>(
1727 seqs_begin, seqs_end,
1728 target, *(seqs_begin->second), length, comp);
1729 }
1730
1731
1732 // public interface
1733 template<
1734 typename RandomAccessIteratorPairIterator
1735 , typename RandomAccessIteratorOut
1736 , typename _DifferenceTp
1737 , typename Comparator>
1738 RandomAccessIteratorOut
1739 stable_multiway_merge(RandomAccessIteratorPairIterator seqs_begin
1740 , RandomAccessIteratorPairIterator seqs_end
1741 , RandomAccessIteratorOut target
1742 , _DifferenceTp length, Comparator comp
1743 , parallel_tag tag = parallel_tag(0))
1744 {
1745 return stable_multiway_merge(seqs_begin, seqs_end, target, length, comp,
1746 exact_tag(tag.get_num_threads()));
1747 }
1748
1749 // public interface
1750 template<
1751 typename RandomAccessIteratorPairIterator
1752 , typename RandomAccessIteratorOut
1753 , typename _DifferenceTp
1754 , typename Comparator>
1755 RandomAccessIteratorOut
1756 stable_multiway_merge(RandomAccessIteratorPairIterator seqs_begin
1757 , RandomAccessIteratorPairIterator seqs_end
1758 , RandomAccessIteratorOut target
1759 , _DifferenceTp length, Comparator comp
1760 , default_parallel_tag tag)
1761 {
1762 return stable_multiway_merge(seqs_begin, seqs_end, target, length, comp,
1763 exact_tag(tag.get_num_threads()));
1764 }
1765
1766 /**
1767 * @brief Multiway Merge Frontend.
1768 *
1769 * Merge the sequences specified by seqs_begin and seqs_end into
1770 * target. seqs_begin and seqs_end must point to a sequence of
1771 * pairs. These pairs must contain an iterator to the beginning
1772 * of a sequence in their first entry and an iterator the end of
1773 * the same sequence in their second entry.
1774 *
1775 * Ties are broken arbitrarily. See stable_multiway_merge for a variant
1776 * that breaks ties by sequence number but is slower.
1777 *
1778 * The first entries of the pairs (i.e. the begin iterators) will be moved
1779 * forward accordingly.
1780 *
1781 * The output sequence has to provide enough space for all elements
1782 * that are written to it.
1783 *
1784 * This function will merge the input sequences:
1785 *
1786 * - not stable
1787 * - parallel, depending on the input size and Settings
1788 * - using sampling for splitting
1789 * - using sentinels
1790 *
1791 * You have to take care that the element the end iterator points to is
1792 * readable and contains a value that is greater than any other non-sentinel
1793 * value in all sequences.
1794 *
1795 * Example:
1796 *
1797 * <pre>
1798 * int sequences[10][11];
1799 * for (int i = 0; i < 10; ++i)
1800 * for (int j = 0; i < 11; ++j)
1801 * sequences[i][j] = j; // last one is sentinel!
1802 *
1803 * int out[33];
1804 * std::vector<std::pair<int*> > seqs;
1805 * for (int i = 0; i < 10; ++i)
1806 * { seqs.push(std::make_pair<int*>(sequences[i], sequences[i] + 10)) }
1807 *
1808 * multiway_merge(seqs.begin(), seqs.end(), target, std::less<int>(), 33);
1809 * </pre>
1810 *
1811 * @pre All input sequences must be sorted.
1812 * @pre Target must provide enough space to merge out length elements or
1813 * the number of elements in all sequences, whichever is smaller.
1814 * @pre For each @c i, @c seqs_begin[i].second must be the end
1815 * marker of the sequence, but also reference the one more sentinel
1816 * element.
1817 *
1818 * @post [target, return value) contains merged elements from the
1819 * input sequences.
1820 * @post return value - target = min(length, number of elements in all
1821 * sequences).
1822 *
1823 * @see stable_multiway_merge_sentinels
1824 *
1825 * @param RandomAccessIteratorPairIterator iterator over sequence
1826 * of pairs of iterators
1827 * @param RandomAccessIteratorOut iterator over target sequence
1828 * @param _DifferenceTp difference type for the sequence
1829 * @param Comparator strict weak ordering type to compare elements
1830 * in sequences
1831 *
1832 * @param seqs_begin begin of sequence sequence
1833 * @param seqs_end end of sequence sequence
1834 * @param target target sequence to merge to.
1835 * @param comp strict weak ordering to use for element comparison.
1836 * @param length Maximum length to merge, possibly larger than the
1837 * number of elements available.
1838 *
1839 * @return end iterator of output sequence
1840 */
1841 // multiway_merge_sentinels
1842 // public interface
1843 template<
1844 typename RandomAccessIteratorPairIterator
1845 , typename RandomAccessIteratorOut
1846 , typename _DifferenceTp
1847 , typename Comparator>
1848 RandomAccessIteratorOut
1849 multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin
1850 , RandomAccessIteratorPairIterator seqs_end
1851 , RandomAccessIteratorOut target
1852 , _DifferenceTp length, Comparator comp
1853 , __gnu_parallel::sequential_tag)
1854 {
1855 typedef _DifferenceTp difference_type;
1856 _GLIBCXX_CALL(seqs_end - seqs_begin)
1857
1858 // catch special case: no sequences
1859 if (seqs_begin == seqs_end)
1860 return target;
1861
1862 // Execute multiway merge *sequentially*.
1863 return sequential_multiway_merge
1864 </* stable = */ false, /* sentinels = */ true>
1865 (seqs_begin, seqs_end,
1866 target, *(seqs_begin->second), length, comp);
1867 }
1868
1869 // public interface
1870 template<
1871 typename RandomAccessIteratorPairIterator
1872 , typename RandomAccessIteratorOut
1873 , typename _DifferenceTp
1874 , typename Comparator>
1875 RandomAccessIteratorOut
1876 multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin
1877 , RandomAccessIteratorPairIterator seqs_end
1878 , RandomAccessIteratorOut target
1879 , _DifferenceTp length, Comparator comp
1880 , __gnu_parallel::exact_tag tag)
1881 {
1882 typedef _DifferenceTp difference_type;
1883 _GLIBCXX_CALL(seqs_end - seqs_begin)
1884
1885 // catch special case: no sequences
1886 if (seqs_begin == seqs_end)
1887 return target;
1888
1889 // Execute merge; maybe parallel, depending on the number of merged
1890 // elements and the number of sequences and global thresholds in
1891 // Settings.
1892 if ((seqs_end - seqs_begin > 1) &&
1893 _GLIBCXX_PARALLEL_CONDITION(
1894 ((seqs_end - seqs_begin) >=
1895 __gnu_parallel::_Settings::get().multiway_merge_minimal_k)
1896 && ((sequence_index_t)length >=
1897 __gnu_parallel::_Settings::get().multiway_merge_minimal_n)))
1898 return parallel_multiway_merge
1899 </* stable = */ false, /* sentinels = */ true>(
1900 seqs_begin, seqs_end,
1901 target,
1902 multiway_merge_exact_splitting</* stable = */ false,
1903 typename std::iterator_traits<RandomAccessIteratorPairIterator>
1904 ::value_type*, Comparator, _DifferenceTp>,
1905 static_cast<difference_type>(length), comp, tag.get_num_threads());
1906 else
1907 return sequential_multiway_merge
1908 </* stable = */ false, /* sentinels = */ true>(
1909 seqs_begin, seqs_end,
1910 target, *(seqs_begin->second), length, comp);
1911 }
1912
1913 // public interface
1914 template<
1915 typename RandomAccessIteratorPairIterator
1916 , typename RandomAccessIteratorOut
1917 , typename _DifferenceTp
1918 , typename Comparator>
1919 RandomAccessIteratorOut
1920 multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin
1921 , RandomAccessIteratorPairIterator seqs_end
1922 , RandomAccessIteratorOut target
1923 , _DifferenceTp length, Comparator comp
1924 , sampling_tag tag)
1925 {
1926 typedef _DifferenceTp difference_type;
1927 _GLIBCXX_CALL(seqs_end - seqs_begin)
1928
1929 // catch special case: no sequences
1930 if (seqs_begin == seqs_end)
1931 return target;
1932
1933 // Execute merge; maybe parallel, depending on the number of merged
1934 // elements and the number of sequences and global thresholds in
1935 // Settings.
1936 if ((seqs_end - seqs_begin > 1) &&
1937 _GLIBCXX_PARALLEL_CONDITION(
1938 ((seqs_end - seqs_begin) >=
1939 __gnu_parallel::_Settings::get().multiway_merge_minimal_k)
1940 && ((sequence_index_t)length >=
1941 __gnu_parallel::_Settings::get().multiway_merge_minimal_n)))
1942 return parallel_multiway_merge
1943 </* stable = */ false, /* sentinels = */ true>
1944 (seqs_begin, seqs_end, target,
1945 multiway_merge_sampling_splitting</* stable = */ false,
1946 typename std::iterator_traits<RandomAccessIteratorPairIterator>
1947 ::value_type*, Comparator, _DifferenceTp>,
1948 static_cast<difference_type>(length), comp, tag.get_num_threads());
1949 else
1950 return sequential_multiway_merge
1951 </* stable = */false, /* sentinels = */ true>(
1952 seqs_begin, seqs_end,
1953 target, *(seqs_begin->second), length, comp);
1954 }
1955
1956 // public interface
1957 template<
1958 typename RandomAccessIteratorPairIterator
1959 , typename RandomAccessIteratorOut
1960 , typename _DifferenceTp
1961 , typename Comparator>
1962 RandomAccessIteratorOut
1963 multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin
1964 , RandomAccessIteratorPairIterator seqs_end
1965 , RandomAccessIteratorOut target
1966 , _DifferenceTp length, Comparator comp
1967 , parallel_tag tag = parallel_tag(0))
1968 {
1969 return multiway_merge_sentinels(seqs_begin, seqs_end, target, length, comp,
1970 exact_tag(tag.get_num_threads()));
1971 }
1972
1973 // public interface
1974 template<
1975 typename RandomAccessIteratorPairIterator
1976 , typename RandomAccessIteratorOut
1977 , typename _DifferenceTp
1978 , typename Comparator>
1979 RandomAccessIteratorOut
1980 multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin
1981 , RandomAccessIteratorPairIterator seqs_end
1982 , RandomAccessIteratorOut target
1983 , _DifferenceTp length, Comparator comp
1984 , default_parallel_tag tag)
1985 {
1986 return multiway_merge_sentinels(seqs_begin, seqs_end, target, length, comp,
1987 exact_tag(tag.get_num_threads()));
1988 }
1989
1990 // stable_multiway_merge_sentinels
1991 // public interface
1992 template<
1993 typename RandomAccessIteratorPairIterator
1994 , typename RandomAccessIteratorOut
1995 , typename _DifferenceTp
1996 , typename Comparator>
1997 RandomAccessIteratorOut
1998 stable_multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin
1999 , RandomAccessIteratorPairIterator seqs_end
2000 , RandomAccessIteratorOut target
2001 , _DifferenceTp length, Comparator comp
2002 , __gnu_parallel::sequential_tag)
2003 {
2004 typedef _DifferenceTp difference_type;
2005 _GLIBCXX_CALL(seqs_end - seqs_begin)
2006
2007 // catch special case: no sequences
2008 if (seqs_begin == seqs_end)
2009 return target;
2010
2011 // Execute multiway merge *sequentially*.
2012 return sequential_multiway_merge
2013 </* stable = */ true, /* sentinels = */ true>
2014 (seqs_begin, seqs_end, target, *(seqs_begin->second), length, comp);
2015 }
2016
2017 // public interface
2018 template<
2019 typename RandomAccessIteratorPairIterator
2020 , typename RandomAccessIteratorOut
2021 , typename _DifferenceTp
2022 , typename Comparator>
2023 RandomAccessIteratorOut
2024 stable_multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin
2025 , RandomAccessIteratorPairIterator seqs_end
2026 , RandomAccessIteratorOut target
2027 , _DifferenceTp length, Comparator comp
2028 , __gnu_parallel::exact_tag tag)
2029 {
2030 typedef _DifferenceTp difference_type;
2031 _GLIBCXX_CALL(seqs_end - seqs_begin)
2032
2033 // catch special case: no sequences
2034 if (seqs_begin == seqs_end)
2035 return target;
2036
2037 // Execute merge; maybe parallel, depending on the number of merged
2038 // elements and the number of sequences and global thresholds in
2039 // Settings.
2040 if ((seqs_end - seqs_begin > 1) &&
2041 _GLIBCXX_PARALLEL_CONDITION(
2042 ((seqs_end - seqs_begin) >=
2043 __gnu_parallel::_Settings::get().multiway_merge_minimal_k)
2044 && ((sequence_index_t)length >=
2045 __gnu_parallel::_Settings::get().multiway_merge_minimal_n)))
2046 return parallel_multiway_merge
2047 </* stable = */ true, /* sentinels = */ true>(
2048 seqs_begin, seqs_end,
2049 target,
2050 multiway_merge_exact_splitting</* stable = */ true,
2051 typename std::iterator_traits<RandomAccessIteratorPairIterator>
2052 ::value_type*, Comparator, _DifferenceTp>,
2053 static_cast<difference_type>(length), comp, tag.get_num_threads());
2054 else
2055 return sequential_multiway_merge
2056 </* stable = */ true, /* sentinels = */ true>(
2057 seqs_begin, seqs_end, target, *(seqs_begin->second), length, comp);
2058 }
2059
2060 // public interface
2061 template<
2062 typename RandomAccessIteratorPairIterator
2063 , typename RandomAccessIteratorOut
2064 , typename _DifferenceTp
2065 , typename Comparator>
2066 RandomAccessIteratorOut
2067 stable_multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin
2068 , RandomAccessIteratorPairIterator seqs_end
2069 , RandomAccessIteratorOut target
2070 , _DifferenceTp length, Comparator comp
2071 , sampling_tag tag)
2072 {
2073 typedef _DifferenceTp difference_type;
2074 _GLIBCXX_CALL(seqs_end - seqs_begin)
2075
2076 // catch special case: no sequences
2077 if (seqs_begin == seqs_end)
2078 return target;
2079
2080 // Execute merge; maybe parallel, depending on the number of merged
2081 // elements and the number of sequences and global thresholds in
2082 // Settings.
2083 if ((seqs_end - seqs_begin > 1) &&
2084 _GLIBCXX_PARALLEL_CONDITION(
2085 ((seqs_end - seqs_begin) >=
2086 __gnu_parallel::_Settings::get().multiway_merge_minimal_k)
2087 && ((sequence_index_t)length >=
2088 __gnu_parallel::_Settings::get().multiway_merge_minimal_n)))
2089 return parallel_multiway_merge
2090 </* stable = */ true, /* sentinels = */ true>(
2091 seqs_begin, seqs_end,
2092 target,
2093 multiway_merge_sampling_splitting</* stable = */ true,
2094 typename std::iterator_traits<RandomAccessIteratorPairIterator>
2095 ::value_type*, Comparator, _DifferenceTp>,
2096 static_cast<difference_type>(length), comp, tag.get_num_threads());
2097 else
2098 return sequential_multiway_merge
2099 </* stable = */ true, /* sentinels = */ true>(
2100 seqs_begin, seqs_end,
2101 target, *(seqs_begin->second), length, comp);
2102 }
2103
2104 // public interface
2105 template<
2106 typename RandomAccessIteratorPairIterator
2107 , typename RandomAccessIteratorOut
2108 , typename _DifferenceTp
2109 , typename Comparator>
2110 RandomAccessIteratorOut
2111 stable_multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin
2112 , RandomAccessIteratorPairIterator seqs_end
2113 , RandomAccessIteratorOut target
2114 , _DifferenceTp length, Comparator comp
2115 , parallel_tag tag = parallel_tag(0))
2116 {
2117 return stable_multiway_merge_sentinels(seqs_begin, seqs_end, target, length, comp,
2118 exact_tag(tag.get_num_threads()));
2119 }
2120
2121 // public interface
2122 template<
2123 typename RandomAccessIteratorPairIterator
2124 , typename RandomAccessIteratorOut
2125 , typename _DifferenceTp
2126 , typename Comparator>
2127 RandomAccessIteratorOut
2128 stable_multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin
2129 , RandomAccessIteratorPairIterator seqs_end
2130 , RandomAccessIteratorOut target
2131 , _DifferenceTp length, Comparator comp
2132 , default_parallel_tag tag)
2133 {
2134 return stable_multiway_merge_sentinels(seqs_begin, seqs_end, target, length, comp,
2135 exact_tag(tag.get_num_threads()));
2136 }
2137
2138 }; // namespace __gnu_parallel
2139
2140 #endif /* _GLIBCXX_PARALLEL_MULTIWAY_MERGE_H */