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