1*38fd1498Szrj // -*- C++ -*- 2*38fd1498Szrj 3*38fd1498Szrj // Copyright (C) 2007-2018 Free Software Foundation, Inc. 4*38fd1498Szrj // 5*38fd1498Szrj // This file is part of the GNU ISO C++ Library. This library is free 6*38fd1498Szrj // software; you can redistribute it and/or modify it under the terms 7*38fd1498Szrj // of the GNU General Public License as published by the Free Software 8*38fd1498Szrj // Foundation; either version 3, or (at your option) any later 9*38fd1498Szrj // version. 10*38fd1498Szrj 11*38fd1498Szrj // This library is distributed in the hope that it will be useful, but 12*38fd1498Szrj // WITHOUT ANY WARRANTY; without even the implied warranty of 13*38fd1498Szrj // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14*38fd1498Szrj // General Public License for more details. 15*38fd1498Szrj 16*38fd1498Szrj // Under Section 7 of GPL version 3, you are granted additional 17*38fd1498Szrj // permissions described in the GCC Runtime Library Exception, version 18*38fd1498Szrj // 3.1, as published by the Free Software Foundation. 19*38fd1498Szrj 20*38fd1498Szrj // You should have received a copy of the GNU General Public License and 21*38fd1498Szrj // a copy of the GCC Runtime Library Exception along with this program; 22*38fd1498Szrj // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23*38fd1498Szrj // <http://www.gnu.org/licenses/>. 24*38fd1498Szrj 25*38fd1498Szrj /** @file parallel/multiseq_selection.h 26*38fd1498Szrj * @brief Functions to find elements of a certain global __rank in 27*38fd1498Szrj * multiple sorted sequences. Also serves for splitting such 28*38fd1498Szrj * sequence sets. 29*38fd1498Szrj * 30*38fd1498Szrj * The algorithm description can be found in 31*38fd1498Szrj * 32*38fd1498Szrj * P. J. Varman, S. D. Scheufler, B. R. Iyer, and G. R. Ricard. 33*38fd1498Szrj * Merging Multiple Lists on Hierarchical-Memory Multiprocessors. 34*38fd1498Szrj * Journal of Parallel and Distributed Computing, 12(2):171–177, 1991. 35*38fd1498Szrj * 36*38fd1498Szrj * This file is a GNU parallel extension to the Standard C++ Library. 37*38fd1498Szrj */ 38*38fd1498Szrj 39*38fd1498Szrj // Written by Johannes Singler. 40*38fd1498Szrj 41*38fd1498Szrj #ifndef _GLIBCXX_PARALLEL_MULTISEQ_SELECTION_H 42*38fd1498Szrj #define _GLIBCXX_PARALLEL_MULTISEQ_SELECTION_H 1 43*38fd1498Szrj 44*38fd1498Szrj #include <vector> 45*38fd1498Szrj #include <queue> 46*38fd1498Szrj 47*38fd1498Szrj #include <bits/stl_algo.h> 48*38fd1498Szrj 49*38fd1498Szrj namespace __gnu_parallel 50*38fd1498Szrj { 51*38fd1498Szrj /** @brief Compare __a pair of types lexicographically, ascending. */ 52*38fd1498Szrj template<typename _T1, typename _T2, typename _Compare> 53*38fd1498Szrj class _Lexicographic 54*38fd1498Szrj : public std::binary_function<std::pair<_T1, _T2>, 55*38fd1498Szrj std::pair<_T1, _T2>, bool> 56*38fd1498Szrj { 57*38fd1498Szrj private: 58*38fd1498Szrj _Compare& _M_comp; 59*38fd1498Szrj 60*38fd1498Szrj public: _Lexicographic(_Compare & __comp)61*38fd1498Szrj _Lexicographic(_Compare& __comp) : _M_comp(__comp) { } 62*38fd1498Szrj 63*38fd1498Szrj bool operator()64*38fd1498Szrj operator()(const std::pair<_T1, _T2>& __p1, 65*38fd1498Szrj const std::pair<_T1, _T2>& __p2) const 66*38fd1498Szrj { 67*38fd1498Szrj if (_M_comp(__p1.first, __p2.first)) 68*38fd1498Szrj return true; 69*38fd1498Szrj 70*38fd1498Szrj if (_M_comp(__p2.first, __p1.first)) 71*38fd1498Szrj return false; 72*38fd1498Szrj 73*38fd1498Szrj // Firsts are equal. 74*38fd1498Szrj return __p1.second < __p2.second; 75*38fd1498Szrj } 76*38fd1498Szrj }; 77*38fd1498Szrj 78*38fd1498Szrj /** @brief Compare __a pair of types lexicographically, descending. */ 79*38fd1498Szrj template<typename _T1, typename _T2, typename _Compare> 80*38fd1498Szrj class _LexicographicReverse : public std::binary_function<_T1, _T2, bool> 81*38fd1498Szrj { 82*38fd1498Szrj private: 83*38fd1498Szrj _Compare& _M_comp; 84*38fd1498Szrj 85*38fd1498Szrj public: _LexicographicReverse(_Compare & __comp)86*38fd1498Szrj _LexicographicReverse(_Compare& __comp) : _M_comp(__comp) { } 87*38fd1498Szrj 88*38fd1498Szrj bool operator()89*38fd1498Szrj operator()(const std::pair<_T1, _T2>& __p1, 90*38fd1498Szrj const std::pair<_T1, _T2>& __p2) const 91*38fd1498Szrj { 92*38fd1498Szrj if (_M_comp(__p2.first, __p1.first)) 93*38fd1498Szrj return true; 94*38fd1498Szrj 95*38fd1498Szrj if (_M_comp(__p1.first, __p2.first)) 96*38fd1498Szrj return false; 97*38fd1498Szrj 98*38fd1498Szrj // Firsts are equal. 99*38fd1498Szrj return __p2.second < __p1.second; 100*38fd1498Szrj } 101*38fd1498Szrj }; 102*38fd1498Szrj 103*38fd1498Szrj /** 104*38fd1498Szrj * @brief Splits several sorted sequences at a certain global __rank, 105*38fd1498Szrj * resulting in a splitting point for each sequence. 106*38fd1498Szrj * The sequences are passed via a sequence of random-access 107*38fd1498Szrj * iterator pairs, none of the sequences may be empty. If there 108*38fd1498Szrj * are several equal elements across the split, the ones on the 109*38fd1498Szrj * __left side will be chosen from sequences with smaller number. 110*38fd1498Szrj * @param __begin_seqs Begin of the sequence of iterator pairs. 111*38fd1498Szrj * @param __end_seqs End of the sequence of iterator pairs. 112*38fd1498Szrj * @param __rank The global rank to partition at. 113*38fd1498Szrj * @param __begin_offsets A random-access __sequence __begin where the 114*38fd1498Szrj * __result will be stored in. Each element of the sequence is an 115*38fd1498Szrj * iterator that points to the first element on the greater part of 116*38fd1498Szrj * the respective __sequence. 117*38fd1498Szrj * @param __comp The ordering functor, defaults to std::less<_Tp>. 118*38fd1498Szrj */ 119*38fd1498Szrj template<typename _RanSeqs, typename _RankType, typename _RankIterator, 120*38fd1498Szrj typename _Compare> 121*38fd1498Szrj void 122*38fd1498Szrj multiseq_partition(_RanSeqs __begin_seqs, _RanSeqs __end_seqs, 123*38fd1498Szrj _RankType __rank, 124*38fd1498Szrj _RankIterator __begin_offsets, 125*38fd1498Szrj _Compare __comp = std::less< 126*38fd1498Szrj typename std::iterator_traits<typename 127*38fd1498Szrj std::iterator_traits<_RanSeqs>::value_type:: 128*38fd1498Szrj first_type>::value_type>()) // std::less<_Tp> 129*38fd1498Szrj { 130*38fd1498Szrj _GLIBCXX_CALL(__end_seqs - __begin_seqs) 131*38fd1498Szrj 132*38fd1498Szrj typedef typename std::iterator_traits<_RanSeqs>::value_type::first_type 133*38fd1498Szrj _It; 134*38fd1498Szrj typedef typename std::iterator_traits<_RanSeqs>::difference_type 135*38fd1498Szrj _SeqNumber; 136*38fd1498Szrj typedef typename std::iterator_traits<_It>::difference_type 137*38fd1498Szrj _DifferenceType; 138*38fd1498Szrj typedef typename std::iterator_traits<_It>::value_type _ValueType; 139*38fd1498Szrj 140*38fd1498Szrj _Lexicographic<_ValueType, _SeqNumber, _Compare> __lcomp(__comp); 141*38fd1498Szrj _LexicographicReverse<_ValueType, _SeqNumber, _Compare> __lrcomp(__comp); 142*38fd1498Szrj 143*38fd1498Szrj // Number of sequences, number of elements in total (possibly 144*38fd1498Szrj // including padding). 145*38fd1498Szrj _DifferenceType __m = std::distance(__begin_seqs, __end_seqs), __nn = 0, 146*38fd1498Szrj __nmax, __n, __r; 147*38fd1498Szrj 148*38fd1498Szrj for (_SeqNumber __i = 0; __i < __m; __i++) 149*38fd1498Szrj { 150*38fd1498Szrj __nn += std::distance(__begin_seqs[__i].first, 151*38fd1498Szrj __begin_seqs[__i].second); 152*38fd1498Szrj _GLIBCXX_PARALLEL_ASSERT( 153*38fd1498Szrj std::distance(__begin_seqs[__i].first, 154*38fd1498Szrj __begin_seqs[__i].second) > 0); 155*38fd1498Szrj } 156*38fd1498Szrj 157*38fd1498Szrj if (__rank == __nn) 158*38fd1498Szrj { 159*38fd1498Szrj for (_SeqNumber __i = 0; __i < __m; __i++) 160*38fd1498Szrj __begin_offsets[__i] = __begin_seqs[__i].second; // Very end. 161*38fd1498Szrj // Return __m - 1; 162*38fd1498Szrj return; 163*38fd1498Szrj } 164*38fd1498Szrj 165*38fd1498Szrj _GLIBCXX_PARALLEL_ASSERT(__m != 0); 166*38fd1498Szrj _GLIBCXX_PARALLEL_ASSERT(__nn != 0); 167*38fd1498Szrj _GLIBCXX_PARALLEL_ASSERT(__rank >= 0); 168*38fd1498Szrj _GLIBCXX_PARALLEL_ASSERT(__rank < __nn); 169*38fd1498Szrj 170*38fd1498Szrj _DifferenceType* __ns = new _DifferenceType[__m]; 171*38fd1498Szrj _DifferenceType* __a = new _DifferenceType[__m]; 172*38fd1498Szrj _DifferenceType* __b = new _DifferenceType[__m]; 173*38fd1498Szrj _DifferenceType __l; 174*38fd1498Szrj 175*38fd1498Szrj __ns[0] = std::distance(__begin_seqs[0].first, __begin_seqs[0].second); 176*38fd1498Szrj __nmax = __ns[0]; 177*38fd1498Szrj for (_SeqNumber __i = 0; __i < __m; __i++) 178*38fd1498Szrj { 179*38fd1498Szrj __ns[__i] = std::distance(__begin_seqs[__i].first, 180*38fd1498Szrj __begin_seqs[__i].second); 181*38fd1498Szrj __nmax = std::max(__nmax, __ns[__i]); 182*38fd1498Szrj } 183*38fd1498Szrj 184*38fd1498Szrj __r = __rd_log2(__nmax) + 1; 185*38fd1498Szrj 186*38fd1498Szrj // Pad all lists to this length, at least as long as any ns[__i], 187*38fd1498Szrj // equality iff __nmax = 2^__k - 1. 188*38fd1498Szrj __l = (1ULL << __r) - 1; 189*38fd1498Szrj 190*38fd1498Szrj for (_SeqNumber __i = 0; __i < __m; __i++) 191*38fd1498Szrj { 192*38fd1498Szrj __a[__i] = 0; 193*38fd1498Szrj __b[__i] = __l; 194*38fd1498Szrj } 195*38fd1498Szrj __n = __l / 2; 196*38fd1498Szrj 197*38fd1498Szrj // Invariants: 198*38fd1498Szrj // 0 <= __a[__i] <= __ns[__i], 0 <= __b[__i] <= __l 199*38fd1498Szrj 200*38fd1498Szrj #define __S(__i) (__begin_seqs[__i].first) 201*38fd1498Szrj 202*38fd1498Szrj // Initial partition. 203*38fd1498Szrj std::vector<std::pair<_ValueType, _SeqNumber> > __sample; 204*38fd1498Szrj 205*38fd1498Szrj for (_SeqNumber __i = 0; __i < __m; __i++) 206*38fd1498Szrj if (__n < __ns[__i]) //__sequence long enough 207*38fd1498Szrj __sample.push_back(std::make_pair(__S(__i)[__n], __i)); 208*38fd1498Szrj __gnu_sequential::sort(__sample.begin(), __sample.end(), __lcomp); 209*38fd1498Szrj 210*38fd1498Szrj for (_SeqNumber __i = 0; __i < __m; __i++) //conceptual infinity 211*38fd1498Szrj if (__n >= __ns[__i]) //__sequence too short, conceptual infinity 212*38fd1498Szrj __sample.push_back( 213*38fd1498Szrj std::make_pair(__S(__i)[0] /*__dummy element*/, __i)); 214*38fd1498Szrj 215*38fd1498Szrj _DifferenceType __localrank = __rank / __l; 216*38fd1498Szrj 217*38fd1498Szrj _SeqNumber __j; 218*38fd1498Szrj for (__j = 0; 219*38fd1498Szrj __j < __localrank && ((__n + 1) <= __ns[__sample[__j].second]); 220*38fd1498Szrj ++__j) 221*38fd1498Szrj __a[__sample[__j].second] += __n + 1; 222*38fd1498Szrj for (; __j < __m; __j++) 223*38fd1498Szrj __b[__sample[__j].second] -= __n + 1; 224*38fd1498Szrj 225*38fd1498Szrj // Further refinement. 226*38fd1498Szrj while (__n > 0) 227*38fd1498Szrj { 228*38fd1498Szrj __n /= 2; 229*38fd1498Szrj 230*38fd1498Szrj _SeqNumber __lmax_seq = -1; // to avoid warning 231*38fd1498Szrj const _ValueType* __lmax = 0; // impossible to avoid the warning? 232*38fd1498Szrj for (_SeqNumber __i = 0; __i < __m; __i++) 233*38fd1498Szrj { 234*38fd1498Szrj if (__a[__i] > 0) 235*38fd1498Szrj { 236*38fd1498Szrj if (!__lmax) 237*38fd1498Szrj { 238*38fd1498Szrj __lmax = &(__S(__i)[__a[__i] - 1]); 239*38fd1498Szrj __lmax_seq = __i; 240*38fd1498Szrj } 241*38fd1498Szrj else 242*38fd1498Szrj { 243*38fd1498Szrj // Max, favor rear sequences. 244*38fd1498Szrj if (!__comp(__S(__i)[__a[__i] - 1], *__lmax)) 245*38fd1498Szrj { 246*38fd1498Szrj __lmax = &(__S(__i)[__a[__i] - 1]); 247*38fd1498Szrj __lmax_seq = __i; 248*38fd1498Szrj } 249*38fd1498Szrj } 250*38fd1498Szrj } 251*38fd1498Szrj } 252*38fd1498Szrj 253*38fd1498Szrj _SeqNumber __i; 254*38fd1498Szrj for (__i = 0; __i < __m; __i++) 255*38fd1498Szrj { 256*38fd1498Szrj _DifferenceType __middle = (__b[__i] + __a[__i]) / 2; 257*38fd1498Szrj if (__lmax && __middle < __ns[__i] && 258*38fd1498Szrj __lcomp(std::make_pair(__S(__i)[__middle], __i), 259*38fd1498Szrj std::make_pair(*__lmax, __lmax_seq))) 260*38fd1498Szrj __a[__i] = std::min(__a[__i] + __n + 1, __ns[__i]); 261*38fd1498Szrj else 262*38fd1498Szrj __b[__i] -= __n + 1; 263*38fd1498Szrj } 264*38fd1498Szrj 265*38fd1498Szrj _DifferenceType __leftsize = 0; 266*38fd1498Szrj for (_SeqNumber __i = 0; __i < __m; __i++) 267*38fd1498Szrj __leftsize += __a[__i] / (__n + 1); 268*38fd1498Szrj 269*38fd1498Szrj _DifferenceType __skew = __rank / (__n + 1) - __leftsize; 270*38fd1498Szrj 271*38fd1498Szrj if (__skew > 0) 272*38fd1498Szrj { 273*38fd1498Szrj // Move to the left, find smallest. 274*38fd1498Szrj std::priority_queue<std::pair<_ValueType, _SeqNumber>, 275*38fd1498Szrj std::vector<std::pair<_ValueType, _SeqNumber> >, 276*38fd1498Szrj _LexicographicReverse<_ValueType, _SeqNumber, _Compare> > 277*38fd1498Szrj __pq(__lrcomp); 278*38fd1498Szrj 279*38fd1498Szrj for (_SeqNumber __i = 0; __i < __m; __i++) 280*38fd1498Szrj if (__b[__i] < __ns[__i]) 281*38fd1498Szrj __pq.push(std::make_pair(__S(__i)[__b[__i]], __i)); 282*38fd1498Szrj 283*38fd1498Szrj for (; __skew != 0 && !__pq.empty(); --__skew) 284*38fd1498Szrj { 285*38fd1498Szrj _SeqNumber __source = __pq.top().second; 286*38fd1498Szrj __pq.pop(); 287*38fd1498Szrj 288*38fd1498Szrj __a[__source] 289*38fd1498Szrj = std::min(__a[__source] + __n + 1, __ns[__source]); 290*38fd1498Szrj __b[__source] += __n + 1; 291*38fd1498Szrj 292*38fd1498Szrj if (__b[__source] < __ns[__source]) 293*38fd1498Szrj __pq.push( 294*38fd1498Szrj std::make_pair(__S(__source)[__b[__source]], __source)); 295*38fd1498Szrj } 296*38fd1498Szrj } 297*38fd1498Szrj else if (__skew < 0) 298*38fd1498Szrj { 299*38fd1498Szrj // Move to the right, find greatest. 300*38fd1498Szrj std::priority_queue<std::pair<_ValueType, _SeqNumber>, 301*38fd1498Szrj std::vector<std::pair<_ValueType, _SeqNumber> >, 302*38fd1498Szrj _Lexicographic<_ValueType, _SeqNumber, _Compare> > 303*38fd1498Szrj __pq(__lcomp); 304*38fd1498Szrj 305*38fd1498Szrj for (_SeqNumber __i = 0; __i < __m; __i++) 306*38fd1498Szrj if (__a[__i] > 0) 307*38fd1498Szrj __pq.push(std::make_pair(__S(__i)[__a[__i] - 1], __i)); 308*38fd1498Szrj 309*38fd1498Szrj for (; __skew != 0; ++__skew) 310*38fd1498Szrj { 311*38fd1498Szrj _SeqNumber __source = __pq.top().second; 312*38fd1498Szrj __pq.pop(); 313*38fd1498Szrj 314*38fd1498Szrj __a[__source] -= __n + 1; 315*38fd1498Szrj __b[__source] -= __n + 1; 316*38fd1498Szrj 317*38fd1498Szrj if (__a[__source] > 0) 318*38fd1498Szrj __pq.push(std::make_pair( 319*38fd1498Szrj __S(__source)[__a[__source] - 1], __source)); 320*38fd1498Szrj } 321*38fd1498Szrj } 322*38fd1498Szrj } 323*38fd1498Szrj 324*38fd1498Szrj // Postconditions: 325*38fd1498Szrj // __a[__i] == __b[__i] in most cases, except when __a[__i] has been 326*38fd1498Szrj // clamped because of having reached the boundary 327*38fd1498Szrj 328*38fd1498Szrj // Now return the result, calculate the offset. 329*38fd1498Szrj 330*38fd1498Szrj // Compare the keys on both edges of the border. 331*38fd1498Szrj 332*38fd1498Szrj // Maximum of left edge, minimum of right edge. 333*38fd1498Szrj _ValueType* __maxleft = 0; 334*38fd1498Szrj _ValueType* __minright = 0; 335*38fd1498Szrj for (_SeqNumber __i = 0; __i < __m; __i++) 336*38fd1498Szrj { 337*38fd1498Szrj if (__a[__i] > 0) 338*38fd1498Szrj { 339*38fd1498Szrj if (!__maxleft) 340*38fd1498Szrj __maxleft = &(__S(__i)[__a[__i] - 1]); 341*38fd1498Szrj else 342*38fd1498Szrj { 343*38fd1498Szrj // Max, favor rear sequences. 344*38fd1498Szrj if (!__comp(__S(__i)[__a[__i] - 1], *__maxleft)) 345*38fd1498Szrj __maxleft = &(__S(__i)[__a[__i] - 1]); 346*38fd1498Szrj } 347*38fd1498Szrj } 348*38fd1498Szrj if (__b[__i] < __ns[__i]) 349*38fd1498Szrj { 350*38fd1498Szrj if (!__minright) 351*38fd1498Szrj __minright = &(__S(__i)[__b[__i]]); 352*38fd1498Szrj else 353*38fd1498Szrj { 354*38fd1498Szrj // Min, favor fore sequences. 355*38fd1498Szrj if (__comp(__S(__i)[__b[__i]], *__minright)) 356*38fd1498Szrj __minright = &(__S(__i)[__b[__i]]); 357*38fd1498Szrj } 358*38fd1498Szrj } 359*38fd1498Szrj } 360*38fd1498Szrj 361*38fd1498Szrj _SeqNumber __seq = 0; 362*38fd1498Szrj for (_SeqNumber __i = 0; __i < __m; __i++) 363*38fd1498Szrj __begin_offsets[__i] = __S(__i) + __a[__i]; 364*38fd1498Szrj 365*38fd1498Szrj delete[] __ns; 366*38fd1498Szrj delete[] __a; 367*38fd1498Szrj delete[] __b; 368*38fd1498Szrj } 369*38fd1498Szrj 370*38fd1498Szrj 371*38fd1498Szrj /** 372*38fd1498Szrj * @brief Selects the element at a certain global __rank from several 373*38fd1498Szrj * sorted sequences. 374*38fd1498Szrj * 375*38fd1498Szrj * The sequences are passed via a sequence of random-access 376*38fd1498Szrj * iterator pairs, none of the sequences may be empty. 377*38fd1498Szrj * @param __begin_seqs Begin of the sequence of iterator pairs. 378*38fd1498Szrj * @param __end_seqs End of the sequence of iterator pairs. 379*38fd1498Szrj * @param __rank The global rank to partition at. 380*38fd1498Szrj * @param __offset The rank of the selected element in the global 381*38fd1498Szrj * subsequence of elements equal to the selected element. If the 382*38fd1498Szrj * selected element is unique, this number is 0. 383*38fd1498Szrj * @param __comp The ordering functor, defaults to std::less. 384*38fd1498Szrj */ 385*38fd1498Szrj template<typename _Tp, typename _RanSeqs, typename _RankType, 386*38fd1498Szrj typename _Compare> 387*38fd1498Szrj _Tp 388*38fd1498Szrj multiseq_selection(_RanSeqs __begin_seqs, _RanSeqs __end_seqs, 389*38fd1498Szrj _RankType __rank, 390*38fd1498Szrj _RankType& __offset, _Compare __comp = std::less<_Tp>()) 391*38fd1498Szrj { 392*38fd1498Szrj _GLIBCXX_CALL(__end_seqs - __begin_seqs) 393*38fd1498Szrj 394*38fd1498Szrj typedef typename std::iterator_traits<_RanSeqs>::value_type::first_type 395*38fd1498Szrj _It; 396*38fd1498Szrj typedef typename std::iterator_traits<_RanSeqs>::difference_type 397*38fd1498Szrj _SeqNumber; 398*38fd1498Szrj typedef typename std::iterator_traits<_It>::difference_type 399*38fd1498Szrj _DifferenceType; 400*38fd1498Szrj 401*38fd1498Szrj _Lexicographic<_Tp, _SeqNumber, _Compare> __lcomp(__comp); 402*38fd1498Szrj _LexicographicReverse<_Tp, _SeqNumber, _Compare> __lrcomp(__comp); 403*38fd1498Szrj 404*38fd1498Szrj // Number of sequences, number of elements in total (possibly 405*38fd1498Szrj // including padding). 406*38fd1498Szrj _DifferenceType __m = std::distance(__begin_seqs, __end_seqs); 407*38fd1498Szrj _DifferenceType __nn = 0; 408*38fd1498Szrj _DifferenceType __nmax, __n, __r; 409*38fd1498Szrj 410*38fd1498Szrj for (_SeqNumber __i = 0; __i < __m; __i++) 411*38fd1498Szrj __nn += std::distance(__begin_seqs[__i].first, 412*38fd1498Szrj __begin_seqs[__i].second); 413*38fd1498Szrj 414*38fd1498Szrj if (__m == 0 || __nn == 0 || __rank < 0 || __rank >= __nn) 415*38fd1498Szrj { 416*38fd1498Szrj // result undefined if there is no data or __rank is outside bounds 417*38fd1498Szrj throw std::exception(); 418*38fd1498Szrj } 419*38fd1498Szrj 420*38fd1498Szrj 421*38fd1498Szrj _DifferenceType* __ns = new _DifferenceType[__m]; 422*38fd1498Szrj _DifferenceType* __a = new _DifferenceType[__m]; 423*38fd1498Szrj _DifferenceType* __b = new _DifferenceType[__m]; 424*38fd1498Szrj _DifferenceType __l; 425*38fd1498Szrj 426*38fd1498Szrj __ns[0] = std::distance(__begin_seqs[0].first, __begin_seqs[0].second); 427*38fd1498Szrj __nmax = __ns[0]; 428*38fd1498Szrj for (_SeqNumber __i = 0; __i < __m; ++__i) 429*38fd1498Szrj { 430*38fd1498Szrj __ns[__i] = std::distance(__begin_seqs[__i].first, 431*38fd1498Szrj __begin_seqs[__i].second); 432*38fd1498Szrj __nmax = std::max(__nmax, __ns[__i]); 433*38fd1498Szrj } 434*38fd1498Szrj 435*38fd1498Szrj __r = __rd_log2(__nmax) + 1; 436*38fd1498Szrj 437*38fd1498Szrj // Pad all lists to this length, at least as long as any ns[__i], 438*38fd1498Szrj // equality iff __nmax = 2^__k - 1 439*38fd1498Szrj __l = __round_up_to_pow2(__r) - 1; 440*38fd1498Szrj 441*38fd1498Szrj for (_SeqNumber __i = 0; __i < __m; ++__i) 442*38fd1498Szrj { 443*38fd1498Szrj __a[__i] = 0; 444*38fd1498Szrj __b[__i] = __l; 445*38fd1498Szrj } 446*38fd1498Szrj __n = __l / 2; 447*38fd1498Szrj 448*38fd1498Szrj // Invariants: 449*38fd1498Szrj // 0 <= __a[__i] <= __ns[__i], 0 <= __b[__i] <= __l 450*38fd1498Szrj 451*38fd1498Szrj #define __S(__i) (__begin_seqs[__i].first) 452*38fd1498Szrj 453*38fd1498Szrj // Initial partition. 454*38fd1498Szrj std::vector<std::pair<_Tp, _SeqNumber> > __sample; 455*38fd1498Szrj 456*38fd1498Szrj for (_SeqNumber __i = 0; __i < __m; __i++) 457*38fd1498Szrj if (__n < __ns[__i]) 458*38fd1498Szrj __sample.push_back(std::make_pair(__S(__i)[__n], __i)); 459*38fd1498Szrj __gnu_sequential::sort(__sample.begin(), __sample.end(), 460*38fd1498Szrj __lcomp, sequential_tag()); 461*38fd1498Szrj 462*38fd1498Szrj // Conceptual infinity. 463*38fd1498Szrj for (_SeqNumber __i = 0; __i < __m; __i++) 464*38fd1498Szrj if (__n >= __ns[__i]) 465*38fd1498Szrj __sample.push_back( 466*38fd1498Szrj std::make_pair(__S(__i)[0] /*__dummy element*/, __i)); 467*38fd1498Szrj 468*38fd1498Szrj _DifferenceType __localrank = __rank / __l; 469*38fd1498Szrj 470*38fd1498Szrj _SeqNumber __j; 471*38fd1498Szrj for (__j = 0; 472*38fd1498Szrj __j < __localrank && ((__n + 1) <= __ns[__sample[__j].second]); 473*38fd1498Szrj ++__j) 474*38fd1498Szrj __a[__sample[__j].second] += __n + 1; 475*38fd1498Szrj for (; __j < __m; ++__j) 476*38fd1498Szrj __b[__sample[__j].second] -= __n + 1; 477*38fd1498Szrj 478*38fd1498Szrj // Further refinement. 479*38fd1498Szrj while (__n > 0) 480*38fd1498Szrj { 481*38fd1498Szrj __n /= 2; 482*38fd1498Szrj 483*38fd1498Szrj const _Tp* __lmax = 0; 484*38fd1498Szrj for (_SeqNumber __i = 0; __i < __m; ++__i) 485*38fd1498Szrj { 486*38fd1498Szrj if (__a[__i] > 0) 487*38fd1498Szrj { 488*38fd1498Szrj if (!__lmax) 489*38fd1498Szrj __lmax = &(__S(__i)[__a[__i] - 1]); 490*38fd1498Szrj else 491*38fd1498Szrj { 492*38fd1498Szrj if (__comp(*__lmax, __S(__i)[__a[__i] - 1])) //max 493*38fd1498Szrj __lmax = &(__S(__i)[__a[__i] - 1]); 494*38fd1498Szrj } 495*38fd1498Szrj } 496*38fd1498Szrj } 497*38fd1498Szrj 498*38fd1498Szrj _SeqNumber __i; 499*38fd1498Szrj for (__i = 0; __i < __m; __i++) 500*38fd1498Szrj { 501*38fd1498Szrj _DifferenceType __middle = (__b[__i] + __a[__i]) / 2; 502*38fd1498Szrj if (__lmax && __middle < __ns[__i] 503*38fd1498Szrj && __comp(__S(__i)[__middle], *__lmax)) 504*38fd1498Szrj __a[__i] = std::min(__a[__i] + __n + 1, __ns[__i]); 505*38fd1498Szrj else 506*38fd1498Szrj __b[__i] -= __n + 1; 507*38fd1498Szrj } 508*38fd1498Szrj 509*38fd1498Szrj _DifferenceType __leftsize = 0; 510*38fd1498Szrj for (_SeqNumber __i = 0; __i < __m; ++__i) 511*38fd1498Szrj __leftsize += __a[__i] / (__n + 1); 512*38fd1498Szrj 513*38fd1498Szrj _DifferenceType __skew = __rank / (__n + 1) - __leftsize; 514*38fd1498Szrj 515*38fd1498Szrj if (__skew > 0) 516*38fd1498Szrj { 517*38fd1498Szrj // Move to the left, find smallest. 518*38fd1498Szrj std::priority_queue<std::pair<_Tp, _SeqNumber>, 519*38fd1498Szrj std::vector<std::pair<_Tp, _SeqNumber> >, 520*38fd1498Szrj _LexicographicReverse<_Tp, _SeqNumber, _Compare> > 521*38fd1498Szrj __pq(__lrcomp); 522*38fd1498Szrj 523*38fd1498Szrj for (_SeqNumber __i = 0; __i < __m; ++__i) 524*38fd1498Szrj if (__b[__i] < __ns[__i]) 525*38fd1498Szrj __pq.push(std::make_pair(__S(__i)[__b[__i]], __i)); 526*38fd1498Szrj 527*38fd1498Szrj for (; __skew != 0 && !__pq.empty(); --__skew) 528*38fd1498Szrj { 529*38fd1498Szrj _SeqNumber __source = __pq.top().second; 530*38fd1498Szrj __pq.pop(); 531*38fd1498Szrj 532*38fd1498Szrj __a[__source] 533*38fd1498Szrj = std::min(__a[__source] + __n + 1, __ns[__source]); 534*38fd1498Szrj __b[__source] += __n + 1; 535*38fd1498Szrj 536*38fd1498Szrj if (__b[__source] < __ns[__source]) 537*38fd1498Szrj __pq.push( 538*38fd1498Szrj std::make_pair(__S(__source)[__b[__source]], __source)); 539*38fd1498Szrj } 540*38fd1498Szrj } 541*38fd1498Szrj else if (__skew < 0) 542*38fd1498Szrj { 543*38fd1498Szrj // Move to the right, find greatest. 544*38fd1498Szrj std::priority_queue<std::pair<_Tp, _SeqNumber>, 545*38fd1498Szrj std::vector<std::pair<_Tp, _SeqNumber> >, 546*38fd1498Szrj _Lexicographic<_Tp, _SeqNumber, _Compare> > __pq(__lcomp); 547*38fd1498Szrj 548*38fd1498Szrj for (_SeqNumber __i = 0; __i < __m; ++__i) 549*38fd1498Szrj if (__a[__i] > 0) 550*38fd1498Szrj __pq.push(std::make_pair(__S(__i)[__a[__i] - 1], __i)); 551*38fd1498Szrj 552*38fd1498Szrj for (; __skew != 0; ++__skew) 553*38fd1498Szrj { 554*38fd1498Szrj _SeqNumber __source = __pq.top().second; 555*38fd1498Szrj __pq.pop(); 556*38fd1498Szrj 557*38fd1498Szrj __a[__source] -= __n + 1; 558*38fd1498Szrj __b[__source] -= __n + 1; 559*38fd1498Szrj 560*38fd1498Szrj if (__a[__source] > 0) 561*38fd1498Szrj __pq.push(std::make_pair( 562*38fd1498Szrj __S(__source)[__a[__source] - 1], __source)); 563*38fd1498Szrj } 564*38fd1498Szrj } 565*38fd1498Szrj } 566*38fd1498Szrj 567*38fd1498Szrj // Postconditions: 568*38fd1498Szrj // __a[__i] == __b[__i] in most cases, except when __a[__i] has been 569*38fd1498Szrj // clamped because of having reached the boundary 570*38fd1498Szrj 571*38fd1498Szrj // Now return the result, calculate the offset. 572*38fd1498Szrj 573*38fd1498Szrj // Compare the keys on both edges of the border. 574*38fd1498Szrj 575*38fd1498Szrj // Maximum of left edge, minimum of right edge. 576*38fd1498Szrj bool __maxleftset = false, __minrightset = false; 577*38fd1498Szrj 578*38fd1498Szrj // Impossible to avoid the warning? 579*38fd1498Szrj _Tp __maxleft, __minright; 580*38fd1498Szrj for (_SeqNumber __i = 0; __i < __m; ++__i) 581*38fd1498Szrj { 582*38fd1498Szrj if (__a[__i] > 0) 583*38fd1498Szrj { 584*38fd1498Szrj if (!__maxleftset) 585*38fd1498Szrj { 586*38fd1498Szrj __maxleft = __S(__i)[__a[__i] - 1]; 587*38fd1498Szrj __maxleftset = true; 588*38fd1498Szrj } 589*38fd1498Szrj else 590*38fd1498Szrj { 591*38fd1498Szrj // Max. 592*38fd1498Szrj if (__comp(__maxleft, __S(__i)[__a[__i] - 1])) 593*38fd1498Szrj __maxleft = __S(__i)[__a[__i] - 1]; 594*38fd1498Szrj } 595*38fd1498Szrj } 596*38fd1498Szrj if (__b[__i] < __ns[__i]) 597*38fd1498Szrj { 598*38fd1498Szrj if (!__minrightset) 599*38fd1498Szrj { 600*38fd1498Szrj __minright = __S(__i)[__b[__i]]; 601*38fd1498Szrj __minrightset = true; 602*38fd1498Szrj } 603*38fd1498Szrj else 604*38fd1498Szrj { 605*38fd1498Szrj // Min. 606*38fd1498Szrj if (__comp(__S(__i)[__b[__i]], __minright)) 607*38fd1498Szrj __minright = __S(__i)[__b[__i]]; 608*38fd1498Szrj } 609*38fd1498Szrj } 610*38fd1498Szrj } 611*38fd1498Szrj 612*38fd1498Szrj // Minright is the __splitter, in any case. 613*38fd1498Szrj 614*38fd1498Szrj if (!__maxleftset || __comp(__minright, __maxleft)) 615*38fd1498Szrj { 616*38fd1498Szrj // Good luck, everything is split unambiguously. 617*38fd1498Szrj __offset = 0; 618*38fd1498Szrj } 619*38fd1498Szrj else 620*38fd1498Szrj { 621*38fd1498Szrj // We have to calculate an offset. 622*38fd1498Szrj __offset = 0; 623*38fd1498Szrj 624*38fd1498Szrj for (_SeqNumber __i = 0; __i < __m; ++__i) 625*38fd1498Szrj { 626*38fd1498Szrj _DifferenceType lb 627*38fd1498Szrj = std::lower_bound(__S(__i), __S(__i) + __ns[__i], 628*38fd1498Szrj __minright, 629*38fd1498Szrj __comp) - __S(__i); 630*38fd1498Szrj __offset += __a[__i] - lb; 631*38fd1498Szrj } 632*38fd1498Szrj } 633*38fd1498Szrj 634*38fd1498Szrj delete[] __ns; 635*38fd1498Szrj delete[] __a; 636*38fd1498Szrj delete[] __b; 637*38fd1498Szrj 638*38fd1498Szrj return __minright; 639*38fd1498Szrj } 640*38fd1498Szrj } 641*38fd1498Szrj 642*38fd1498Szrj #undef __S 643*38fd1498Szrj 644*38fd1498Szrj #endif /* _GLIBCXX_PARALLEL_MULTISEQ_SELECTION_H */ 645