00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 #ifndef _GLIBCXX_PARALLEL_MULTIWAY_MERGE_H
00046 #define _GLIBCXX_PARALLEL_MULTIWAY_MERGE_H
00047
00048 #include <vector>
00049
00050 #include <bits/stl_algo.h>
00051 #include <parallel/features.h>
00052 #include <parallel/parallel.h>
00053 #include <parallel/merge.h>
00054 #include <parallel/losertree.h>
00055 #if _GLIBCXX_ASSERTIONS
00056 #include <parallel/checkers.h>
00057 #endif
00058
00059
00060 #define _GLIBCXX_PARALLEL_LENGTH(s) ((s).second - (s).first)
00061
00062
00063 namespace __gnu_parallel
00064 {
00065 template<typename RandomAccessIterator, typename Comparator>
00066 class guarded_iterator;
00067
00068 template<typename RandomAccessIterator, typename Comparator>
00069 inline bool
00070 operator<(guarded_iterator<RandomAccessIterator, Comparator>& bi1,
00071 guarded_iterator<RandomAccessIterator, Comparator>& bi2);
00072
00073 template<typename RandomAccessIterator, typename Comparator>
00074 inline bool
00075 operator<=(guarded_iterator<RandomAccessIterator, Comparator>& bi1,
00076 guarded_iterator<RandomAccessIterator, Comparator>& bi2);
00077
00078
00079
00080
00081
00082
00083 template<typename RandomAccessIterator, typename Comparator>
00084 class guarded_iterator
00085 {
00086 private:
00087
00088 RandomAccessIterator current;
00089
00090
00091 RandomAccessIterator end;
00092
00093
00094 Comparator& comp;
00095
00096 public:
00097
00098
00099
00100
00101
00102 guarded_iterator(RandomAccessIterator begin,
00103 RandomAccessIterator end, Comparator& comp)
00104 : current(begin), end(end), comp(comp)
00105 { }
00106
00107
00108
00109 guarded_iterator<RandomAccessIterator, Comparator>&
00110 operator++()
00111 {
00112 ++current;
00113 return *this;
00114 }
00115
00116
00117
00118 typename std::iterator_traits<RandomAccessIterator>::value_type
00119 operator*()
00120 { return *current; }
00121
00122
00123
00124 operator RandomAccessIterator()
00125 { return current; }
00126
00127 friend bool
00128 operator< <RandomAccessIterator, Comparator>(
00129 guarded_iterator<RandomAccessIterator, Comparator>& bi1,
00130 guarded_iterator<RandomAccessIterator, Comparator>& bi2);
00131
00132 friend bool
00133 operator<= <RandomAccessIterator, Comparator>(
00134 guarded_iterator<RandomAccessIterator, Comparator>& bi1,
00135 guarded_iterator<RandomAccessIterator, Comparator>& bi2);
00136 };
00137
00138
00139
00140
00141
00142 template<typename RandomAccessIterator, typename Comparator>
00143 inline bool
00144 operator<(guarded_iterator<RandomAccessIterator, Comparator>& bi1,
00145 guarded_iterator<RandomAccessIterator, Comparator>& bi2)
00146 {
00147 if (bi1.current == bi1.end)
00148 return bi2.current == bi2.end;
00149 if (bi2.current == bi2.end)
00150 return true;
00151 return (bi1.comp)(*bi1, *bi2);
00152 }
00153
00154
00155
00156
00157
00158 template<typename RandomAccessIterator, typename Comparator>
00159 inline bool
00160 operator<=(guarded_iterator<RandomAccessIterator, Comparator>& bi1,
00161 guarded_iterator<RandomAccessIterator, Comparator>& bi2)
00162 {
00163 if (bi2.current == bi2.end)
00164 return bi1.current != bi1.end;
00165 if (bi1.current == bi1.end)
00166 return false;
00167 return !(bi1.comp)(*bi2, *bi1);
00168 }
00169
00170 template<typename RandomAccessIterator, typename Comparator>
00171 class unguarded_iterator;
00172
00173 template<typename RandomAccessIterator, typename Comparator>
00174 inline bool
00175 operator<(unguarded_iterator<RandomAccessIterator, Comparator>& bi1,
00176 unguarded_iterator<RandomAccessIterator, Comparator>& bi2);
00177
00178 template<typename RandomAccessIterator, typename Comparator>
00179 inline bool
00180 operator<=(unguarded_iterator<RandomAccessIterator, Comparator>& bi1,
00181 unguarded_iterator<RandomAccessIterator, Comparator>& bi2);
00182
00183 template<typename RandomAccessIterator, typename Comparator>
00184 class unguarded_iterator
00185 {
00186 private:
00187
00188 RandomAccessIterator& current;
00189
00190 mutable Comparator& comp;
00191
00192 public:
00193
00194
00195
00196
00197 unguarded_iterator(RandomAccessIterator begin,
00198 RandomAccessIterator end, Comparator& comp)
00199 : current(begin), comp(comp)
00200 { }
00201
00202
00203
00204 unguarded_iterator<RandomAccessIterator, Comparator>&
00205 operator++()
00206 {
00207 ++current;
00208 return *this;
00209 }
00210
00211
00212
00213 typename std::iterator_traits<RandomAccessIterator>::value_type
00214 operator*()
00215 { return *current; }
00216
00217
00218
00219 operator RandomAccessIterator()
00220 { return current; }
00221
00222 friend bool
00223 operator< <RandomAccessIterator, Comparator>(
00224 unguarded_iterator<RandomAccessIterator, Comparator>& bi1,
00225 unguarded_iterator<RandomAccessIterator, Comparator>& bi2);
00226
00227 friend bool
00228 operator<= <RandomAccessIterator, Comparator>(
00229 unguarded_iterator<RandomAccessIterator, Comparator>& bi1,
00230 unguarded_iterator<RandomAccessIterator, Comparator>& bi2);
00231 };
00232
00233
00234
00235
00236
00237 template<typename RandomAccessIterator, typename Comparator>
00238 inline bool
00239 operator<(unguarded_iterator<RandomAccessIterator, Comparator>& bi1,
00240 unguarded_iterator<RandomAccessIterator, Comparator>& bi2)
00241 {
00242
00243 return (bi1.comp)(*bi1, *bi2);
00244 }
00245
00246
00247
00248
00249
00250 template<typename RandomAccessIterator, typename Comparator>
00251 inline bool
00252 operator<=(unguarded_iterator<RandomAccessIterator, Comparator>& bi1,
00253 unguarded_iterator<RandomAccessIterator, Comparator>& bi2)
00254 {
00255
00256 return !(bi1.comp)(*bi2, *bi1);
00257 }
00258
00259
00260
00261
00262
00263
00264
00265
00266 template<typename RandomAccessIteratorIterator, typename Comparator>
00267 typename std::iterator_traits<
00268 typename std::iterator_traits<RandomAccessIteratorIterator>::value_type
00269 ::first_type>::difference_type
00270 prepare_unguarded(RandomAccessIteratorIterator seqs_begin,
00271 RandomAccessIteratorIterator seqs_end, Comparator comp,
00272 int& min_sequence, bool stable)
00273 {
00274 _GLIBCXX_CALL(seqs_end - seqs_begin)
00275
00276 typedef typename std::iterator_traits<RandomAccessIteratorIterator>
00277 ::value_type::first_type
00278 RandomAccessIterator1;
00279 typedef typename std::iterator_traits<RandomAccessIterator1>::value_type
00280 value_type;
00281 typedef typename std::iterator_traits<RandomAccessIterator1>
00282 ::difference_type
00283 difference_type;
00284
00285 if ((*seqs_begin).first == (*seqs_begin).second)
00286 {
00287
00288 min_sequence = 0;
00289 return -1;
00290 }
00291
00292
00293 value_type min = *((*seqs_begin).second - 1);
00294 min_sequence = 0;
00295 for (RandomAccessIteratorIterator s = seqs_begin + 1; s != seqs_end; ++s)
00296 {
00297 if ((*s).first == (*s).second)
00298 {
00299
00300 min_sequence = static_cast<int>(s - seqs_begin);
00301 return -1;
00302 }
00303
00304
00305 const value_type& v = *((*s).second - 1);
00306 if (comp(v, min))
00307 {
00308 min = v;
00309 min_sequence = static_cast<int>(s - seqs_begin);
00310 }
00311 }
00312
00313 difference_type overhang_size = 0;
00314
00315 int s = 0;
00316 for (s = 0; s <= min_sequence; ++s)
00317 {
00318 RandomAccessIterator1 split;
00319 if (stable)
00320 split = std::upper_bound(seqs_begin[s].first, seqs_begin[s].second,
00321 min, comp);
00322 else
00323 split = std::lower_bound(seqs_begin[s].first, seqs_begin[s].second,
00324 min, comp);
00325
00326 overhang_size += seqs_begin[s].second - split;
00327 }
00328
00329 for (; s < (seqs_end - seqs_begin); ++s)
00330 {
00331 RandomAccessIterator1 split = std::lower_bound(
00332 seqs_begin[s].first, seqs_begin[s].second, min, comp);
00333 overhang_size += seqs_begin[s].second - split;
00334 }
00335
00336
00337 return overhang_size;
00338 }
00339
00340
00341
00342
00343
00344 template<typename RandomAccessIteratorIterator, typename Comparator>
00345 typename std::iterator_traits<typename std::iterator_traits<
00346 RandomAccessIteratorIterator>::value_type::first_type>::difference_type
00347 prepare_unguarded_sentinel(RandomAccessIteratorIterator seqs_begin,
00348 RandomAccessIteratorIterator seqs_end,
00349 Comparator comp)
00350 {
00351 _GLIBCXX_CALL(seqs_end - seqs_begin)
00352
00353 typedef typename std::iterator_traits<RandomAccessIteratorIterator>
00354 ::value_type::first_type
00355 RandomAccessIterator1;
00356 typedef typename std::iterator_traits<RandomAccessIterator1>
00357 ::value_type
00358 value_type;
00359 typedef typename std::iterator_traits<RandomAccessIterator1>
00360 ::difference_type
00361 difference_type;
00362
00363
00364 value_type* max = NULL;
00365 for (RandomAccessIteratorIterator s = seqs_begin; s != seqs_end; ++s)
00366 {
00367 if ((*s).first == (*s).second)
00368 continue;
00369
00370
00371 value_type& v = *((*s).second - 1);
00372
00373
00374 if (!max || comp(*max, v))
00375 max = &v;
00376 }
00377
00378 difference_type overhang_size = 0;
00379 for (RandomAccessIteratorIterator s = seqs_begin; s != seqs_end; ++s)
00380 {
00381 RandomAccessIterator1 split =
00382 std::lower_bound((*s).first, (*s).second, *max, comp);
00383 overhang_size += (*s).second - split;
00384
00385
00386 *((*s).second) = *max;
00387 }
00388
00389
00390 return overhang_size;
00391 }
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401 template<template<typename RAI, typename C> class iterator,
00402 typename RandomAccessIteratorIterator,
00403 typename RandomAccessIterator3,
00404 typename _DifferenceTp,
00405 typename Comparator>
00406 RandomAccessIterator3
00407 multiway_merge_3_variant(RandomAccessIteratorIterator seqs_begin,
00408 RandomAccessIteratorIterator seqs_end,
00409 RandomAccessIterator3 target,
00410 Comparator comp, _DifferenceTp length,
00411 bool stable)
00412 {
00413 _GLIBCXX_CALL(length);
00414
00415 typedef _DifferenceTp difference_type;
00416
00417 typedef typename std::iterator_traits<RandomAccessIteratorIterator>
00418 ::value_type::first_type
00419 RandomAccessIterator1;
00420 typedef typename std::iterator_traits<RandomAccessIterator1>::value_type
00421 value_type;
00422
00423 if (length == 0)
00424 return target;
00425
00426 iterator<RandomAccessIterator1, Comparator>
00427 seq0(seqs_begin[0].first, seqs_begin[0].second, comp),
00428 seq1(seqs_begin[1].first, seqs_begin[1].second, comp),
00429 seq2(seqs_begin[2].first, seqs_begin[2].second, comp);
00430
00431 if (seq0 <= seq1)
00432 {
00433 if (seq1 <= seq2)
00434 goto s012;
00435 else
00436 if (seq2 < seq0)
00437 goto s201;
00438 else
00439 goto s021;
00440 }
00441 else
00442 {
00443 if (seq1 <= seq2)
00444 {
00445 if (seq0 <= seq2)
00446 goto s102;
00447 else
00448 goto s120;
00449 }
00450 else
00451 goto s210;
00452 }
00453
00454 #define _GLIBCXX_PARALLEL_MERGE_3_CASE(a,b,c,c0,c1)\
00455 s ## a ## b ## c : \
00456 *target = *seq ## a; \
00457 ++target; \
00458 --length; \
00459 ++seq ## a; \
00460 if (length == 0) goto finish; \
00461 if (seq ## a c0 seq ## b) goto s ## a ## b ## c; \
00462 if (seq ## a c1 seq ## c) goto s ## b ## a ## c; \
00463 goto s ## b ## c ## a;
00464
00465 _GLIBCXX_PARALLEL_MERGE_3_CASE(0, 1, 2, <=, <=);
00466 _GLIBCXX_PARALLEL_MERGE_3_CASE(1, 2, 0, <=, < );
00467 _GLIBCXX_PARALLEL_MERGE_3_CASE(2, 0, 1, < , < );
00468 _GLIBCXX_PARALLEL_MERGE_3_CASE(1, 0, 2, < , <=);
00469 _GLIBCXX_PARALLEL_MERGE_3_CASE(0, 2, 1, <=, <=);
00470 _GLIBCXX_PARALLEL_MERGE_3_CASE(2, 1, 0, < , < );
00471
00472 #undef _GLIBCXX_PARALLEL_MERGE_3_CASE
00473
00474 finish:
00475 ;
00476
00477 seqs_begin[0].first = seq0;
00478 seqs_begin[1].first = seq1;
00479 seqs_begin[2].first = seq2;
00480
00481 return target;
00482 }
00483
00484 template<typename RandomAccessIteratorIterator,
00485 typename RandomAccessIterator3,
00486 typename _DifferenceTp,
00487 typename Comparator>
00488 RandomAccessIterator3
00489 multiway_merge_3_combined(RandomAccessIteratorIterator seqs_begin,
00490 RandomAccessIteratorIterator seqs_end,
00491 RandomAccessIterator3 target,
00492 Comparator comp,
00493 _DifferenceTp length, bool stable)
00494 {
00495 _GLIBCXX_CALL(length);
00496
00497 typedef _DifferenceTp difference_type;
00498 typedef typename std::iterator_traits<RandomAccessIteratorIterator>
00499 ::value_type::first_type
00500 RandomAccessIterator1;
00501 typedef typename std::iterator_traits<RandomAccessIterator1>::value_type
00502 value_type;
00503
00504 int min_seq;
00505 RandomAccessIterator3 target_end;
00506
00507
00508 difference_type overhang =
00509 prepare_unguarded(seqs_begin, seqs_end, comp, min_seq, true);
00510
00511 difference_type total_length = 0;
00512 for (RandomAccessIteratorIterator s = seqs_begin; s != seqs_end; ++s)
00513 total_length += _GLIBCXX_PARALLEL_LENGTH(*s);
00514
00515 if (overhang != -1)
00516 {
00517 difference_type unguarded_length =
00518 std::min(length, total_length - overhang);
00519 target_end = multiway_merge_3_variant<unguarded_iterator>
00520 (seqs_begin, seqs_end, target, comp, unguarded_length, stable);
00521 overhang = length - unguarded_length;
00522 }
00523 else
00524 {
00525
00526 overhang = length;
00527 target_end = target;
00528 }
00529
00530 #if _GLIBCXX_ASSERTIONS
00531 _GLIBCXX_PARALLEL_ASSERT(target_end == target + length - overhang);
00532 _GLIBCXX_PARALLEL_ASSERT(is_sorted(target, target_end, comp));
00533 #endif
00534
00535 switch (min_seq)
00536 {
00537 case 0:
00538
00539 target_end = merge_advance(seqs_begin[1].first, seqs_begin[1].second,
00540 seqs_begin[2].first, seqs_begin[2].second,
00541 target_end, overhang, comp);
00542 break;
00543 case 1:
00544 target_end = merge_advance(seqs_begin[0].first, seqs_begin[0].second,
00545 seqs_begin[2].first, seqs_begin[2].second,
00546 target_end, overhang, comp);
00547 break;
00548 case 2:
00549 target_end = merge_advance(seqs_begin[0].first, seqs_begin[0].second,
00550 seqs_begin[1].first, seqs_begin[1].second,
00551 target_end, overhang, comp);
00552 break;
00553 default:
00554 _GLIBCXX_PARALLEL_ASSERT(false);
00555 }
00556
00557 #if _GLIBCXX_ASSERTIONS
00558 _GLIBCXX_PARALLEL_ASSERT(target_end == target + length);
00559 _GLIBCXX_PARALLEL_ASSERT(is_sorted(target, target_end, comp));
00560 #endif
00561
00562 return target_end;
00563 }
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573 template<template<typename RAI, typename C> class iterator,
00574 typename RandomAccessIteratorIterator,
00575 typename RandomAccessIterator3,
00576 typename _DifferenceTp,
00577 typename Comparator>
00578 RandomAccessIterator3
00579 multiway_merge_4_variant(RandomAccessIteratorIterator seqs_begin,
00580 RandomAccessIteratorIterator seqs_end,
00581 RandomAccessIterator3 target,
00582 Comparator comp, _DifferenceTp length, bool stable)
00583 {
00584 _GLIBCXX_CALL(length);
00585 typedef _DifferenceTp difference_type;
00586
00587 typedef typename std::iterator_traits<RandomAccessIteratorIterator>
00588 ::value_type::first_type
00589 RandomAccessIterator1;
00590 typedef typename std::iterator_traits<RandomAccessIterator1>::value_type
00591 value_type;
00592
00593 iterator<RandomAccessIterator1, Comparator>
00594 seq0(seqs_begin[0].first, seqs_begin[0].second, comp),
00595 seq1(seqs_begin[1].first, seqs_begin[1].second, comp),
00596 seq2(seqs_begin[2].first, seqs_begin[2].second, comp),
00597 seq3(seqs_begin[3].first, seqs_begin[3].second, comp);
00598
00599 #define _GLIBCXX_PARALLEL_DECISION(a,b,c,d) { \
00600 if (seq ## d < seq ## a) goto s ## d ## a ## b ## c; \
00601 if (seq ## d < seq ## b) goto s ## a ## d ## b ## c; \
00602 if (seq ## d < seq ## c) goto s ## a ## b ## d ## c; \
00603 goto s ## a ## b ## c ## d; }
00604
00605 if (seq0 <= seq1)
00606 {
00607 if (seq1 <= seq2)
00608 _GLIBCXX_PARALLEL_DECISION(0,1,2,3)
00609 else
00610 if (seq2 < seq0)
00611 _GLIBCXX_PARALLEL_DECISION(2,0,1,3)
00612 else
00613 _GLIBCXX_PARALLEL_DECISION(0,2,1,3)
00614 }
00615 else
00616 {
00617 if (seq1 <= seq2)
00618 {
00619 if (seq0 <= seq2)
00620 _GLIBCXX_PARALLEL_DECISION(1,0,2,3)
00621 else
00622 _GLIBCXX_PARALLEL_DECISION(1,2,0,3)
00623 }
00624 else
00625 _GLIBCXX_PARALLEL_DECISION(2,1,0,3)
00626 }
00627
00628 #define _GLIBCXX_PARALLEL_MERGE_4_CASE(a,b,c,d,c0,c1,c2) \
00629 s ## a ## b ## c ## d: \
00630 if (length == 0) goto finish; \
00631 *target = *seq ## a; \
00632 ++target; \
00633 --length; \
00634 ++seq ## a; \
00635 if (seq ## a c0 seq ## b) goto s ## a ## b ## c ## d; \
00636 if (seq ## a c1 seq ## c) goto s ## b ## a ## c ## d; \
00637 if (seq ## a c2 seq ## d) goto s ## b ## c ## a ## d; \
00638 goto s ## b ## c ## d ## a;
00639
00640 _GLIBCXX_PARALLEL_MERGE_4_CASE(0, 1, 2, 3, <=, <=, <=);
00641 _GLIBCXX_PARALLEL_MERGE_4_CASE(0, 1, 3, 2, <=, <=, <=);
00642 _GLIBCXX_PARALLEL_MERGE_4_CASE(0, 2, 1, 3, <=, <=, <=);
00643 _GLIBCXX_PARALLEL_MERGE_4_CASE(0, 2, 3, 1, <=, <=, <=);
00644 _GLIBCXX_PARALLEL_MERGE_4_CASE(0, 3, 1, 2, <=, <=, <=);
00645 _GLIBCXX_PARALLEL_MERGE_4_CASE(0, 3, 2, 1, <=, <=, <=);
00646 _GLIBCXX_PARALLEL_MERGE_4_CASE(1, 0, 2, 3, < , <=, <=);
00647 _GLIBCXX_PARALLEL_MERGE_4_CASE(1, 0, 3, 2, < , <=, <=);
00648 _GLIBCXX_PARALLEL_MERGE_4_CASE(1, 2, 0, 3, <=, < , <=);
00649 _GLIBCXX_PARALLEL_MERGE_4_CASE(1, 2, 3, 0, <=, <=, < );
00650 _GLIBCXX_PARALLEL_MERGE_4_CASE(1, 3, 0, 2, <=, < , <=);
00651 _GLIBCXX_PARALLEL_MERGE_4_CASE(1, 3, 2, 0, <=, <=, < );
00652 _GLIBCXX_PARALLEL_MERGE_4_CASE(2, 0, 1, 3, < , < , <=);
00653 _GLIBCXX_PARALLEL_MERGE_4_CASE(2, 0, 3, 1, < , <=, < );
00654 _GLIBCXX_PARALLEL_MERGE_4_CASE(2, 1, 0, 3, < , < , <=);
00655 _GLIBCXX_PARALLEL_MERGE_4_CASE(2, 1, 3, 0, < , <=, < );
00656 _GLIBCXX_PARALLEL_MERGE_4_CASE(2, 3, 0, 1, <=, < , < );
00657 _GLIBCXX_PARALLEL_MERGE_4_CASE(2, 3, 1, 0, <=, < , < );
00658 _GLIBCXX_PARALLEL_MERGE_4_CASE(3, 0, 1, 2, < , < , < );
00659 _GLIBCXX_PARALLEL_MERGE_4_CASE(3, 0, 2, 1, < , < , < );
00660 _GLIBCXX_PARALLEL_MERGE_4_CASE(3, 1, 0, 2, < , < , < );
00661 _GLIBCXX_PARALLEL_MERGE_4_CASE(3, 1, 2, 0, < , < , < );
00662 _GLIBCXX_PARALLEL_MERGE_4_CASE(3, 2, 0, 1, < , < , < );
00663 _GLIBCXX_PARALLEL_MERGE_4_CASE(3, 2, 1, 0, < , < , < );
00664
00665 #undef _GLIBCXX_PARALLEL_MERGE_4_CASE
00666 #undef _GLIBCXX_PARALLEL_DECISION
00667
00668 finish:
00669 ;
00670
00671 seqs_begin[0].first = seq0;
00672 seqs_begin[1].first = seq1;
00673 seqs_begin[2].first = seq2;
00674 seqs_begin[3].first = seq3;
00675
00676 return target;
00677 }
00678
00679 template<typename RandomAccessIteratorIterator,
00680 typename RandomAccessIterator3,
00681 typename _DifferenceTp,
00682 typename Comparator>
00683 RandomAccessIterator3
00684 multiway_merge_4_combined(RandomAccessIteratorIterator seqs_begin,
00685 RandomAccessIteratorIterator seqs_end,
00686 RandomAccessIterator3 target,
00687 Comparator comp,
00688 _DifferenceTp length, bool stable)
00689 {
00690 _GLIBCXX_CALL(length);
00691 typedef _DifferenceTp difference_type;
00692
00693 typedef typename std::iterator_traits<RandomAccessIteratorIterator>
00694 ::value_type::first_type
00695 RandomAccessIterator1;
00696 typedef typename std::iterator_traits<RandomAccessIterator1>::value_type
00697 value_type;
00698
00699 int min_seq;
00700 RandomAccessIterator3 target_end;
00701
00702
00703 difference_type overhang =
00704 prepare_unguarded(seqs_begin, seqs_end, comp, min_seq, true);
00705
00706 difference_type total_length = 0;
00707 for (RandomAccessIteratorIterator s = seqs_begin; s != seqs_end; ++s)
00708 total_length += _GLIBCXX_PARALLEL_LENGTH(*s);
00709
00710 if (overhang != -1)
00711 {
00712 difference_type unguarded_length =
00713 std::min(length, total_length - overhang);
00714 target_end = multiway_merge_4_variant<unguarded_iterator>
00715 (seqs_begin, seqs_end, target, comp, unguarded_length, stable);
00716 overhang = length - unguarded_length;
00717 }
00718 else
00719 {
00720
00721 overhang = length;
00722 target_end = target;
00723 }
00724
00725 #if _GLIBCXX_ASSERTIONS
00726 _GLIBCXX_PARALLEL_ASSERT(target_end == target + length - overhang);
00727 _GLIBCXX_PARALLEL_ASSERT(is_sorted(target, target_end, comp));
00728 #endif
00729
00730 std::vector<std::pair<RandomAccessIterator1, RandomAccessIterator1> >
00731 one_missing(seqs_begin, seqs_end);
00732 one_missing.erase(one_missing.begin() + min_seq);
00733
00734 target_end = multiway_merge_3_variant<guarded_iterator>(
00735 one_missing.begin(), one_missing.end(),
00736 target_end, comp, overhang, stable);
00737
00738
00739 one_missing.insert(one_missing.begin() + min_seq, seqs_begin[min_seq]);
00740
00741 copy(one_missing.begin(), one_missing.end(), seqs_begin);
00742
00743 #if _GLIBCXX_ASSERTIONS
00744 _GLIBCXX_PARALLEL_ASSERT(target_end == target + length);
00745 _GLIBCXX_PARALLEL_ASSERT(is_sorted(target, target_end, comp));
00746 #endif
00747
00748 return target_end;
00749 }
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763 template<typename RandomAccessIteratorIterator,
00764 typename RandomAccessIterator3,
00765 typename _DifferenceTp,
00766 typename Comparator>
00767 RandomAccessIterator3
00768 multiway_merge_bubble(RandomAccessIteratorIterator seqs_begin,
00769 RandomAccessIteratorIterator seqs_end,
00770 RandomAccessIterator3 target,
00771 Comparator comp, _DifferenceTp length, bool stable)
00772 {
00773 _GLIBCXX_CALL(length)
00774
00775 typedef _DifferenceTp difference_type;
00776 typedef typename std::iterator_traits<RandomAccessIteratorIterator>
00777 ::value_type::first_type
00778 RandomAccessIterator1;
00779 typedef typename std::iterator_traits<RandomAccessIterator1>::value_type
00780 value_type;
00781
00782 int k = static_cast<int>(seqs_end - seqs_begin);
00783 int nrs;
00784
00785
00786 value_type* fe = static_cast<value_type*>(
00787 ::operator new(sizeof(value_type) * k));
00788 int* source = new int[k];
00789 difference_type total_length = 0;
00790
00791
00792 nrs = 0;
00793 for (int pi = 0; pi < k; ++pi)
00794 {
00795 if (seqs_begin[pi].first != seqs_begin[pi].second)
00796 {
00797 ::new(&(fe[nrs])) value_type(*(seqs_begin[pi].first));
00798 source[nrs] = pi;
00799 ++nrs;
00800 total_length += _GLIBCXX_PARALLEL_LENGTH(seqs_begin[pi]);
00801 }
00802 }
00803
00804 if (stable)
00805 {
00806
00807 for (int k = 0; k < nrs - 1; ++k)
00808 for (int pi = nrs - 1; pi > k; --pi)
00809 if (comp(fe[pi], fe[pi - 1]) ||
00810 (!comp(fe[pi - 1], fe[pi]) && source[pi] < source[pi - 1]))
00811 {
00812 std::swap(fe[pi - 1], fe[pi]);
00813 std::swap(source[pi - 1], source[pi]);
00814 }
00815 }
00816 else
00817 {
00818 for (int k = 0; k < nrs - 1; ++k)
00819 for (int pi = nrs - 1; pi > k; --pi)
00820 if (comp(fe[pi], fe[pi-1]))
00821 {
00822 std::swap(fe[pi-1], fe[pi]);
00823 std::swap(source[pi-1], source[pi]);
00824 }
00825 }
00826
00827
00828 if (stable)
00829 {
00830 int j;
00831 while (nrs > 0 && length > 0)
00832 {
00833 if (source[0] < source[1])
00834 {
00835
00836 while ((nrs == 1 || !comp(fe[1], fe[0])) && length > 0)
00837 {
00838 *target = fe[0];
00839 ++target;
00840 ++(seqs_begin[source[0]].first);
00841 --length;
00842 if (seqs_begin[source[0]].first
00843 == seqs_begin[source[0]].second)
00844 {
00845
00846 for (int s = 0; s < nrs - 1; ++s)
00847 {
00848 fe[s] = fe[s + 1];
00849 source[s] = source[s + 1];
00850 }
00851 fe[nrs - 1].~value_type();
00852 --nrs;
00853 break;
00854 }
00855 else
00856 fe[0] = *(seqs_begin[source[0]].first);
00857 }
00858 }
00859 else
00860 {
00861
00862 while ((nrs == 1 || comp(fe[0], fe[1])) && length > 0)
00863 {
00864 *target = fe[0];
00865 ++target;
00866 ++(seqs_begin[source[0]].first);
00867 --length;
00868 if (seqs_begin[source[0]].first
00869 == seqs_begin[source[0]].second)
00870 {
00871 for (int s = 0; s < nrs - 1; ++s)
00872 {
00873 fe[s] = fe[s + 1];
00874 source[s] = source[s + 1];
00875 }
00876 fe[nrs - 1].~value_type();
00877 --nrs;
00878 break;
00879 }
00880 else
00881 fe[0] = *(seqs_begin[source[0]].first);
00882 }
00883 }
00884
00885
00886 j = 1;
00887 while ((j < nrs) && (comp(fe[j], fe[j - 1])
00888 || (!comp(fe[j - 1], fe[j])
00889 && (source[j] < source[j - 1]))))
00890 {
00891 std::swap(fe[j - 1], fe[j]);
00892 std::swap(source[j - 1], source[j]);
00893 ++j;
00894 }
00895 }
00896 }
00897 else
00898 {
00899 int j;
00900 while (nrs > 0 && length > 0)
00901 {
00902
00903 while (nrs == 1 || (!comp(fe[1], fe[0])) && length > 0)
00904 {
00905 *target = fe[0];
00906 ++target;
00907 ++seqs_begin[source[0]].first;
00908 --length;
00909 if (seqs_begin[source[0]].first
00910 == seqs_begin[source[0]].second)
00911 {
00912 for (int s = 0; s < (nrs - 1); ++s)
00913 {
00914 fe[s] = fe[s + 1];
00915 source[s] = source[s + 1];
00916 }
00917 fe[nrs - 1].~value_type();
00918 --nrs;
00919 break;
00920 }
00921 else
00922 fe[0] = *(seqs_begin[source[0]].first);
00923 }
00924
00925
00926 j = 1;
00927 while ((j < nrs) && comp(fe[j], fe[j - 1]))
00928 {
00929 std::swap(fe[j - 1], fe[j]);
00930 std::swap(source[j - 1], source[j]);
00931 ++j;
00932 }
00933 }
00934 }
00935
00936 ::operator delete(fe);
00937 delete[] source;
00938
00939 return target;
00940 }
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954 template<typename LT,
00955 typename RandomAccessIteratorIterator,
00956 typename RandomAccessIterator3,
00957 typename _DifferenceTp,
00958 typename Comparator>
00959 RandomAccessIterator3
00960 multiway_merge_loser_tree(RandomAccessIteratorIterator seqs_begin,
00961 RandomAccessIteratorIterator seqs_end,
00962 RandomAccessIterator3 target,
00963 Comparator comp,
00964 _DifferenceTp length, bool stable)
00965 {
00966 _GLIBCXX_CALL(length)
00967
00968 typedef _DifferenceTp difference_type;
00969 typedef typename std::iterator_traits<RandomAccessIteratorIterator>
00970 ::value_type::first_type
00971 RandomAccessIterator1;
00972 typedef typename std::iterator_traits<RandomAccessIterator1>::value_type
00973 value_type;
00974
00975 int k = static_cast<int>(seqs_end - seqs_begin);
00976
00977 LT lt(k, comp);
00978
00979 difference_type total_length = 0;
00980
00981
00982 value_type* arbitrary_element = NULL;
00983
00984 for (int t = 0; t < k; ++t)
00985 {
00986 if(arbitrary_element == NULL
00987 && _GLIBCXX_PARALLEL_LENGTH(seqs_begin[t]) > 0)
00988 arbitrary_element = &(*seqs_begin[t].first);
00989 total_length += _GLIBCXX_PARALLEL_LENGTH(seqs_begin[t]);
00990 }
00991
00992 if(total_length == 0)
00993 return target;
00994
00995 for (int t = 0; t < k; ++t)
00996 {
00997 if (stable)
00998 {
00999 if (seqs_begin[t].first == seqs_begin[t].second)
01000 lt.insert_start_stable(*arbitrary_element, t, true);
01001 else
01002 lt.insert_start_stable(*seqs_begin[t].first, t, false);
01003 }
01004 else
01005 {
01006 if (seqs_begin[t].first == seqs_begin[t].second)
01007 lt.insert_start(*arbitrary_element, t, true);
01008 else
01009 lt.insert_start(*seqs_begin[t].first, t, false);
01010 }
01011 }
01012
01013 if (stable)
01014 lt.init_stable();
01015 else
01016 lt.init();
01017
01018 total_length = std::min(total_length, length);
01019
01020 int source;
01021
01022 if (stable)
01023 {
01024 for (difference_type i = 0; i < total_length; ++i)
01025 {
01026
01027 source = lt.get_min_source();
01028
01029 *(target++) = *(seqs_begin[source].first++);
01030
01031
01032 if (seqs_begin[source].first == seqs_begin[source].second)
01033 lt.delete_min_insert_stable(*arbitrary_element, true);
01034 else
01035
01036 lt.delete_min_insert_stable(*seqs_begin[source].first, false);
01037
01038 }
01039 }
01040 else
01041 {
01042 for (difference_type i = 0; i < total_length; ++i)
01043 {
01044
01045 source = lt.get_min_source();
01046
01047 *(target++) = *(seqs_begin[source].first++);
01048
01049
01050 if (seqs_begin[source].first == seqs_begin[source].second)
01051 lt.delete_min_insert(*arbitrary_element, true);
01052 else
01053
01054 lt.delete_min_insert(*seqs_begin[source].first, false);
01055 }
01056 }
01057
01058 return target;
01059 }
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074 template<typename LT,
01075 typename RandomAccessIteratorIterator,
01076 typename RandomAccessIterator3,
01077 typename _DifferenceTp, typename Comparator>
01078 RandomAccessIterator3
01079 multiway_merge_loser_tree_unguarded(RandomAccessIteratorIterator seqs_begin,
01080 RandomAccessIteratorIterator seqs_end,
01081 RandomAccessIterator3 target,
01082 Comparator comp,
01083 _DifferenceTp length, bool stable)
01084 {
01085 _GLIBCXX_CALL(length)
01086 typedef _DifferenceTp difference_type;
01087
01088 typedef typename std::iterator_traits<RandomAccessIteratorIterator>
01089 ::value_type::first_type
01090 RandomAccessIterator1;
01091 typedef typename std::iterator_traits<RandomAccessIterator1>::value_type
01092 value_type;
01093
01094 int k = seqs_end - seqs_begin;
01095
01096 LT lt(k, comp);
01097
01098 difference_type total_length = 0;
01099
01100 for (int t = 0; t < k; ++t)
01101 {
01102 #if _GLIBCXX_ASSERTIONS
01103 _GLIBCXX_PARALLEL_ASSERT(seqs_begin[t].first != seqs_begin[t].second);
01104 #endif
01105 if (stable)
01106 lt.insert_start_stable(*seqs_begin[t].first, t, false);
01107 else
01108 lt.insert_start(*seqs_begin[t].first, t, false);
01109
01110 total_length += _GLIBCXX_PARALLEL_LENGTH(seqs_begin[t]);
01111 }
01112
01113 if (stable)
01114 lt.init_stable();
01115 else
01116 lt.init();
01117
01118
01119 length = std::min(total_length, length);
01120
01121 int source;
01122
01123 #if _GLIBCXX_ASSERTIONS
01124 difference_type i = 0;
01125 #endif
01126
01127 if (stable)
01128 {
01129 RandomAccessIterator3 target_end = target + length;
01130 while (target < target_end)
01131 {
01132
01133 source = lt.get_min_source();
01134
01135 #if _GLIBCXX_ASSERTIONS
01136 _GLIBCXX_PARALLEL_ASSERT(i == 0
01137 || !comp(*(seqs_begin[source].first), *(target - 1)));
01138 #endif
01139
01140 *(target++) = *(seqs_begin[source].first++);
01141
01142 #if _GLIBCXX_ASSERTIONS
01143 _GLIBCXX_PARALLEL_ASSERT(
01144 (seqs_begin[source].first != seqs_begin[source].second)
01145 || (i == length - 1));
01146 ++i;
01147 #endif
01148
01149
01150 lt.delete_min_insert_stable(*seqs_begin[source].first, false);
01151
01152 }
01153 }
01154 else
01155 {
01156 RandomAccessIterator3 target_end = target + length;
01157 while (target < target_end)
01158 {
01159
01160 source = lt.get_min_source();
01161
01162 #if _GLIBCXX_ASSERTIONS
01163 if (i > 0 && comp(*(seqs_begin[source].first), *(target - 1)))
01164 printf(" %i %i %i\n", length, i, source);
01165 _GLIBCXX_PARALLEL_ASSERT(i == 0
01166 || !comp(*(seqs_begin[source].first), *(target - 1)));
01167 #endif
01168
01169 *(target++) = *(seqs_begin[source].first++);
01170
01171 #if _GLIBCXX_ASSERTIONS
01172 if (!((seqs_begin[source].first != seqs_begin[source].second)
01173 || (i >= length - 1)))
01174 printf(" %i %i %i\n", length, i, source);
01175 _GLIBCXX_PARALLEL_ASSERT(
01176 (seqs_begin[source].first != seqs_begin[source].second)
01177 || (i >= length - 1));
01178 ++i;
01179 #endif
01180
01181
01182 lt.delete_min_insert(*seqs_begin[source].first, false);
01183 }
01184 }
01185
01186 return target;
01187 }
01188
01189 template<typename RandomAccessIteratorIterator,
01190 typename RandomAccessIterator3,
01191 typename _DifferenceTp,
01192 typename Comparator>
01193 RandomAccessIterator3
01194 multiway_merge_loser_tree_combined(RandomAccessIteratorIterator seqs_begin,
01195 RandomAccessIteratorIterator seqs_end,
01196 RandomAccessIterator3 target,
01197 Comparator comp,
01198 _DifferenceTp length, bool stable)
01199 {
01200 _GLIBCXX_CALL(length)
01201
01202 typedef _DifferenceTp difference_type;
01203
01204 typedef typename std::iterator_traits<RandomAccessIteratorIterator>
01205 ::value_type::first_type
01206 RandomAccessIterator1;
01207 typedef typename std::iterator_traits<RandomAccessIterator1>::value_type
01208 value_type;
01209
01210 int min_seq;
01211 RandomAccessIterator3 target_end;
01212 difference_type overhang = prepare_unguarded(seqs_begin, seqs_end,
01213 comp, min_seq, stable);
01214
01215 difference_type total_length = 0;
01216 for (RandomAccessIteratorIterator s = seqs_begin; s != seqs_end; ++s)
01217 total_length += _GLIBCXX_PARALLEL_LENGTH(*s);
01218
01219 if (overhang != -1)
01220 {
01221 difference_type unguarded_length =
01222 std::min(length, total_length - overhang);
01223 target_end = multiway_merge_loser_tree_unguarded
01224 <typename loser_tree_unguarded_traits<value_type, Comparator>::LT>
01225 (seqs_begin, seqs_end, target, comp, unguarded_length, stable);
01226 overhang = length - unguarded_length;
01227 }
01228 else
01229 {
01230
01231 overhang = length;
01232 target_end = target;
01233 }
01234
01235 #if _GLIBCXX_ASSERTIONS
01236 _GLIBCXX_PARALLEL_ASSERT(target_end == target + length - overhang);
01237 _GLIBCXX_PARALLEL_ASSERT(is_sorted(target, target_end, comp));
01238 #endif
01239
01240 target_end = multiway_merge_loser_tree
01241 <typename loser_tree_traits<value_type, Comparator>::LT>
01242 (seqs_begin, seqs_end, target_end, comp, overhang, stable);
01243
01244 #if _GLIBCXX_ASSERTIONS
01245 _GLIBCXX_PARALLEL_ASSERT(target_end == target + length);
01246 _GLIBCXX_PARALLEL_ASSERT(is_sorted(target, target_end, comp));
01247 #endif
01248
01249 return target_end;
01250 }
01251
01252 template<typename RandomAccessIteratorIterator,
01253 typename RandomAccessIterator3,
01254 typename _DifferenceTp,
01255 typename Comparator>
01256 RandomAccessIterator3
01257 multiway_merge_loser_tree_sentinel(RandomAccessIteratorIterator seqs_begin,
01258 RandomAccessIteratorIterator seqs_end,
01259 RandomAccessIterator3 target,
01260 Comparator comp,
01261 _DifferenceTp length, bool stable)
01262 {
01263 _GLIBCXX_CALL(length)
01264
01265 typedef _DifferenceTp difference_type;
01266 typedef std::iterator_traits<RandomAccessIteratorIterator> traits_type;
01267 typedef typename std::iterator_traits<RandomAccessIteratorIterator>
01268 ::value_type::first_type
01269 RandomAccessIterator1;
01270 typedef typename std::iterator_traits<RandomAccessIterator1>::value_type
01271 value_type;
01272
01273 RandomAccessIterator3 target_end;
01274 difference_type overhang =
01275 prepare_unguarded_sentinel(seqs_begin, seqs_end, comp);
01276
01277 difference_type total_length = 0;
01278 for (RandomAccessIteratorIterator s = seqs_begin; s != seqs_end; ++s)
01279 {
01280 total_length += _GLIBCXX_PARALLEL_LENGTH(*s);
01281
01282
01283 ++((*s).second);
01284 }
01285
01286 difference_type unguarded_length =
01287 std::min(length, total_length - overhang);
01288 target_end = multiway_merge_loser_tree_unguarded
01289 <typename loser_tree_unguarded_traits<value_type, Comparator>::LT>
01290 (seqs_begin, seqs_end, target, comp, unguarded_length, stable);
01291 overhang = length - unguarded_length;
01292
01293 #if _GLIBCXX_ASSERTIONS
01294 _GLIBCXX_PARALLEL_ASSERT(target_end == target + length - overhang);
01295 _GLIBCXX_PARALLEL_ASSERT(is_sorted(target, target_end, comp));
01296 #endif
01297
01298
01299 for (RandomAccessIteratorIterator s = seqs_begin;
01300 s != seqs_end && overhang > 0; ++s)
01301 {
01302
01303 --((*s).second);
01304 difference_type local_length =
01305 std::min<difference_type>(overhang, _GLIBCXX_PARALLEL_LENGTH(*s));
01306 target_end = std::copy((*s).first, (*s).first + local_length,
01307 target_end);
01308 (*s).first += local_length;
01309 overhang -= local_length;
01310 }
01311
01312 #if _GLIBCXX_ASSERTIONS
01313 _GLIBCXX_PARALLEL_ASSERT(overhang == 0);
01314 _GLIBCXX_PARALLEL_ASSERT(target_end == target + length);
01315 _GLIBCXX_PARALLEL_ASSERT(is_sorted(target, target_end, comp));
01316 #endif
01317
01318 return target_end;
01319 }
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333 template<typename RandomAccessIteratorIterator,
01334 typename RandomAccessIterator3,
01335 typename _DifferenceTp,
01336 typename Comparator>
01337 RandomAccessIterator3
01338 multiway_merge(RandomAccessIteratorIterator seqs_begin,
01339 RandomAccessIteratorIterator seqs_end,
01340 RandomAccessIterator3 target,
01341 Comparator comp, _DifferenceTp length,
01342 bool stable, bool sentinel,
01343 sequential_tag)
01344 {
01345 _GLIBCXX_CALL(length)
01346
01347 typedef _DifferenceTp difference_type;
01348 typedef typename std::iterator_traits<RandomAccessIteratorIterator>
01349 ::value_type::first_type
01350 RandomAccessIterator1;
01351 typedef typename std::iterator_traits<RandomAccessIterator1>::value_type
01352 value_type;
01353
01354 #if _GLIBCXX_ASSERTIONS
01355 for (RandomAccessIteratorIterator s = seqs_begin; s != seqs_end; ++s)
01356 _GLIBCXX_PARALLEL_ASSERT(is_sorted((*s).first, (*s).second, comp));
01357 #endif
01358
01359 RandomAccessIterator3 return_target = target;
01360 int k = static_cast<int>(seqs_end - seqs_begin);
01361
01362 _MultiwayMergeAlgorithm mwma = _Settings::get().multiway_merge_algorithm;
01363
01364 if (!sentinel && mwma == LOSER_TREE_SENTINEL)
01365 mwma = LOSER_TREE_COMBINED;
01366
01367 switch (k)
01368 {
01369 case 0:
01370 break;
01371 case 1:
01372 return_target = std::copy(seqs_begin[0].first,
01373 seqs_begin[0].first + length,
01374 target);
01375 seqs_begin[0].first += length;
01376 break;
01377 case 2:
01378 return_target = merge_advance(seqs_begin[0].first,
01379 seqs_begin[0].second,
01380 seqs_begin[1].first,
01381 seqs_begin[1].second,
01382 target, length, comp);
01383 break;
01384 case 3:
01385 switch (mwma)
01386 {
01387 case LOSER_TREE_COMBINED:
01388 return_target = multiway_merge_3_combined(seqs_begin,
01389 seqs_end,
01390 target,
01391 comp, length,
01392 stable);
01393 break;
01394 case LOSER_TREE_SENTINEL:
01395 return_target =
01396 multiway_merge_3_variant<unguarded_iterator>(seqs_begin,
01397 seqs_end,
01398 target,
01399 comp, length,
01400 stable);
01401 break;
01402 default:
01403 return_target =
01404 multiway_merge_3_variant<guarded_iterator>(seqs_begin,
01405 seqs_end,
01406 target,
01407 comp, length,
01408 stable);
01409 break;
01410 }
01411 break;
01412 case 4:
01413 switch (mwma)
01414 {
01415 case LOSER_TREE_COMBINED:
01416 return_target = multiway_merge_4_combined(seqs_begin,
01417 seqs_end,
01418 target,
01419 comp, length, stable);
01420 break;
01421 case LOSER_TREE_SENTINEL:
01422 return_target =
01423 multiway_merge_4_variant<unguarded_iterator>(seqs_begin,
01424 seqs_end,
01425 target,
01426 comp, length,
01427 stable);
01428 break;
01429 default:
01430 return_target = multiway_merge_4_variant<guarded_iterator>(
01431 seqs_begin,
01432 seqs_end,
01433 target,
01434 comp, length, stable);
01435 break;
01436 }
01437 break;
01438 default:
01439 {
01440 switch (mwma)
01441 {
01442 case BUBBLE:
01443 return_target = multiway_merge_bubble(seqs_begin,
01444 seqs_end,
01445 target,
01446 comp, length, stable);
01447 break;
01448 #if _GLIBCXX_LOSER_TREE_EXPLICIT
01449 case LOSER_TREE_EXPLICIT:
01450 return_target = multiway_merge_loser_tree<
01451 LoserTreeExplicit<value_type, Comparator> >(seqs_begin,
01452 seqs_end,
01453 target,
01454 comp, length,
01455 stable);
01456 break;
01457 #endif
01458 #if _GLIBCXX_LOSER_TREE
01459 case LOSER_TREE:
01460 return_target = multiway_merge_loser_tree<
01461 LoserTree<value_type, Comparator> >(seqs_begin,
01462 seqs_end,
01463 target,
01464 comp, length,
01465 stable);
01466 break;
01467 #endif
01468 #if _GLIBCXX_LOSER_TREE_COMBINED
01469 case LOSER_TREE_COMBINED:
01470 return_target = multiway_merge_loser_tree_combined(seqs_begin,
01471 seqs_end,
01472 target,
01473 comp, length,
01474 stable);
01475 break;
01476 #endif
01477 #if _GLIBCXX_LOSER_TREE_SENTINEL
01478 case LOSER_TREE_SENTINEL:
01479 return_target = multiway_merge_loser_tree_sentinel(seqs_begin,
01480 seqs_end,
01481 target,
01482 comp, length,
01483 stable);
01484 break;
01485 #endif
01486 default:
01487
01488 _GLIBCXX_PARALLEL_ASSERT(0);
01489 break;
01490 }
01491 }
01492 }
01493 #if _GLIBCXX_ASSERTIONS
01494 _GLIBCXX_PARALLEL_ASSERT(is_sorted(target, target + length, comp));
01495 #endif
01496
01497 return return_target;
01498 }
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513 template<typename RandomAccessIteratorIterator,
01514 typename RandomAccessIterator3,
01515 typename _DifferenceTp,
01516 typename Comparator>
01517 RandomAccessIterator3
01518 parallel_multiway_merge(RandomAccessIteratorIterator seqs_begin,
01519 RandomAccessIteratorIterator seqs_end,
01520 RandomAccessIterator3 target,
01521 Comparator comp,
01522 _DifferenceTp length, bool stable, bool sentinel)
01523 {
01524 _GLIBCXX_CALL(length)
01525
01526 typedef _DifferenceTp difference_type;
01527 typedef typename std::iterator_traits<RandomAccessIteratorIterator>
01528 ::value_type::first_type
01529 RandomAccessIterator1;
01530 typedef typename std::iterator_traits<RandomAccessIterator1>::value_type
01531 value_type;
01532
01533
01534 int k = static_cast<int>(seqs_end - seqs_begin);
01535
01536 difference_type total_length = 0;
01537 for (RandomAccessIteratorIterator raii = seqs_begin;
01538 raii != seqs_end; ++raii)
01539 total_length += _GLIBCXX_PARALLEL_LENGTH(*raii);
01540
01541 _GLIBCXX_CALL(total_length)
01542
01543 if (total_length == 0 || k == 0)
01544 return target;
01545
01546 bool tight = (total_length == length);
01547
01548 std::vector<std::pair<difference_type, difference_type> >* pieces;
01549
01550 thread_index_t num_threads = static_cast<thread_index_t>(
01551 std::min<difference_type>(get_max_threads(), total_length));
01552 const _Settings& __s = _Settings::get();
01553
01554 # pragma omp parallel num_threads (num_threads)
01555 {
01556 # pragma omp single
01557 {
01558 num_threads = omp_get_num_threads();
01559
01560 pieces = new std::vector<
01561 std::pair<difference_type, difference_type> >[num_threads];
01562 for (int s = 0; s < num_threads; ++s)
01563 pieces[s].resize(k);
01564
01565 difference_type num_samples = __s.merge_oversampling
01566 * num_threads;
01567
01568 if (__s.multiway_merge_splitting == SAMPLING)
01569 {
01570 value_type* samples = static_cast<value_type*>(
01571 ::operator new(sizeof(value_type) * k * num_samples));
01572
01573 for (int s = 0; s < k; ++s)
01574 for (difference_type i = 0; i < num_samples; ++i)
01575 {
01576 difference_type sample_index =
01577 static_cast<difference_type>(
01578 _GLIBCXX_PARALLEL_LENGTH(seqs_begin[s])
01579 * (double(i + 1) / (num_samples + 1))
01580 * (double(length) / total_length));
01581 ::new(&(samples[s * num_samples + i]))
01582 value_type(seqs_begin[s].first[sample_index]);
01583 }
01584
01585 if (stable)
01586 __gnu_sequential::stable_sort(samples, samples
01587 + (num_samples * k), comp);
01588 else
01589 __gnu_sequential::sort(samples, samples
01590 + (num_samples * k), comp);
01591
01592 for (int slab = 0; slab < num_threads; ++slab)
01593
01594 for (int seq = 0; seq < k; ++seq)
01595 {
01596
01597 if (slab > 0)
01598 pieces[slab][seq].first =
01599 std::upper_bound(seqs_begin[seq].first,
01600 seqs_begin[seq].second,
01601 samples[num_samples * k
01602 * slab / num_threads],
01603 comp)
01604 - seqs_begin[seq].first;
01605 else
01606 {
01607
01608 pieces[slab][seq].first = 0;
01609 }
01610 if ((slab + 1) < num_threads)
01611 pieces[slab][seq].second =
01612 std::upper_bound(seqs_begin[seq].first,
01613 seqs_begin[seq].second,
01614 samples[num_samples * k
01615 * (slab + 1)
01616 / num_threads], comp)
01617 - seqs_begin[seq].first;
01618 else
01619 pieces[slab][seq].second
01620 = _GLIBCXX_PARALLEL_LENGTH(seqs_begin[seq]);
01621 }
01622 ::operator delete(samples);
01623 }
01624 else
01625 {
01626
01627 std::vector<RandomAccessIterator1>* offsets =
01628 new std::vector<RandomAccessIterator1>[num_threads];
01629 std::vector<
01630 std::pair<RandomAccessIterator1, RandomAccessIterator1>
01631 > se(k);
01632
01633 copy(seqs_begin, seqs_end, se.begin());
01634
01635 difference_type* borders =
01636 new difference_type[num_threads + 1];
01637 equally_split(length, num_threads, borders);
01638
01639 for (int s = 0; s < (num_threads - 1); ++s)
01640 {
01641 offsets[s].resize(k);
01642 multiseq_partition(
01643 se.begin(), se.end(), borders[s + 1],
01644 offsets[s].begin(), comp);
01645
01646
01647 if (!tight)
01648 {
01649 offsets[num_threads - 1].resize(k);
01650 multiseq_partition(se.begin(), se.end(),
01651 difference_type(length),
01652 offsets[num_threads - 1].begin(),
01653 comp);
01654 }
01655 }
01656
01657
01658 for (int slab = 0; slab < num_threads; ++slab)
01659 {
01660
01661 for (int seq = 0; seq < k; ++seq)
01662 {
01663
01664 if (slab == 0)
01665 {
01666
01667 pieces[slab][seq].first = 0;
01668 }
01669 else
01670 pieces[slab][seq].first =
01671 pieces[slab - 1][seq].second;
01672 if (!tight || slab < (num_threads - 1))
01673 pieces[slab][seq].second =
01674 offsets[slab][seq] - seqs_begin[seq].first;
01675 else
01676 {
01677
01678 pieces[slab][seq].second =
01679 _GLIBCXX_PARALLEL_LENGTH(seqs_begin[seq]);
01680 }
01681 }
01682 }
01683 delete[] offsets;
01684 }
01685 }
01686
01687 thread_index_t iam = omp_get_thread_num();
01688
01689 difference_type target_position = 0;
01690
01691 for (int c = 0; c < k; ++c)
01692 target_position += pieces[iam][c].first;
01693
01694 if (k > 2)
01695 {
01696 std::pair<RandomAccessIterator1, RandomAccessIterator1>* chunks
01697 = new
01698 std::pair<RandomAccessIterator1, RandomAccessIterator1>[k];
01699
01700 difference_type local_length = 0;
01701 for (int s = 0; s < k; ++s)
01702 {
01703 chunks[s] = std::make_pair(
01704 seqs_begin[s].first + pieces[iam][s].first,
01705 seqs_begin[s].first + pieces[iam][s].second);
01706 local_length += _GLIBCXX_PARALLEL_LENGTH(chunks[s]);
01707 }
01708
01709 multiway_merge(
01710 chunks, chunks + k, target + target_position, comp,
01711 std::min(local_length, length - target_position),
01712 stable, false, sequential_tag());
01713
01714 delete[] chunks;
01715 }
01716 else if (k == 2)
01717 {
01718 RandomAccessIterator1
01719 begin0 = seqs_begin[0].first + pieces[iam][0].first,
01720 begin1 = seqs_begin[1].first + pieces[iam][1].first;
01721 merge_advance(begin0,
01722 seqs_begin[0].first + pieces[iam][0].second,
01723 begin1,
01724 seqs_begin[1].first + pieces[iam][1].second,
01725 target + target_position,
01726 (pieces[iam][0].second - pieces[iam][0].first) +
01727 (pieces[iam][1].second - pieces[iam][1].first),
01728 comp);
01729 }
01730 }
01731
01732 #if _GLIBCXX_ASSERTIONS
01733 _GLIBCXX_PARALLEL_ASSERT(is_sorted(target, target + length, comp));
01734 #endif
01735
01736
01737 for (int s = 0; s < k; ++s)
01738 seqs_begin[s].first += pieces[num_threads - 1][s].second;
01739
01740 delete[] pieces;
01741
01742 return target + length;
01743 }
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755 template<typename RandomAccessIteratorPairIterator,
01756 typename RandomAccessIterator3,
01757 typename _DifferenceTp,
01758 typename Comparator>
01759 RandomAccessIterator3
01760 multiway_merge(RandomAccessIteratorPairIterator seqs_begin,
01761 RandomAccessIteratorPairIterator seqs_end,
01762 RandomAccessIterator3 target, Comparator comp,
01763 _DifferenceTp length, bool stable)
01764 {
01765 typedef _DifferenceTp difference_type;
01766 _GLIBCXX_CALL(seqs_end - seqs_begin)
01767
01768 if (seqs_begin == seqs_end)
01769 return target;
01770
01771 const _Settings& __s = _Settings::get();
01772
01773 RandomAccessIterator3 target_end;
01774 if (_GLIBCXX_PARALLEL_CONDITION(
01775 ((seqs_end - seqs_begin) >= __s.multiway_merge_minimal_k)
01776 && ((sequence_index_t)length >= __s.multiway_merge_minimal_n)))
01777 target_end = parallel_multiway_merge(seqs_begin, seqs_end,
01778 target, comp,
01779 static_cast<difference_type>(length),
01780 stable, false);
01781 else
01782 target_end = multiway_merge(seqs_begin, seqs_end, target, comp, length,
01783 stable, false, sequential_tag());
01784
01785 return target_end;
01786 }
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798
01799 template<typename RandomAccessIteratorPairIterator,
01800 typename RandomAccessIterator3,
01801 typename _DifferenceTp,
01802 typename Comparator>
01803 RandomAccessIterator3
01804 multiway_merge_sentinel(RandomAccessIteratorPairIterator seqs_begin,
01805 RandomAccessIteratorPairIterator seqs_end,
01806 RandomAccessIterator3 target,
01807 Comparator comp,
01808 _DifferenceTp length,
01809 bool stable)
01810 {
01811 typedef _DifferenceTp difference_type;
01812
01813 if (seqs_begin == seqs_end)
01814 return target;
01815
01816 _GLIBCXX_CALL(seqs_end - seqs_begin)
01817
01818 const _Settings& __s = _Settings::get();
01819 const bool cond1 = seqs_end - seqs_begin >= __s.multiway_merge_minimal_k;
01820 const bool cond2 = sequence_index_t(length) >= __s.multiway_merge_minimal_n;
01821 if (_GLIBCXX_PARALLEL_CONDITION(cond1 && cond2))
01822 return parallel_multiway_merge(seqs_begin, seqs_end, target, comp,
01823 length, stable, true);
01824 else
01825 return multiway_merge(seqs_begin, seqs_end, target, comp, length, stable,
01826 true, sequential_tag());
01827 }
01828 }
01829
01830 #endif