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