1*e4b17023SJohn Marino // -*- C++ -*- 2*e4b17023SJohn Marino 3*e4b17023SJohn Marino // Copyright (C) 2007, 2008, 2009, 2010 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/partition.h 26*e4b17023SJohn Marino * @brief Parallel implementation of std::partition(), 27*e4b17023SJohn Marino * std::nth_element(), and std::partial_sort(). 28*e4b17023SJohn Marino * This file is a GNU parallel extension to the Standard C++ Library. 29*e4b17023SJohn Marino */ 30*e4b17023SJohn Marino 31*e4b17023SJohn Marino // Written by Johannes Singler and Felix Putze. 32*e4b17023SJohn Marino 33*e4b17023SJohn Marino #ifndef _GLIBCXX_PARALLEL_PARTITION_H 34*e4b17023SJohn Marino #define _GLIBCXX_PARALLEL_PARTITION_H 1 35*e4b17023SJohn Marino 36*e4b17023SJohn Marino #include <parallel/basic_iterator.h> 37*e4b17023SJohn Marino #include <parallel/sort.h> 38*e4b17023SJohn Marino #include <parallel/random_number.h> 39*e4b17023SJohn Marino #include <bits/stl_algo.h> 40*e4b17023SJohn Marino #include <parallel/parallel.h> 41*e4b17023SJohn Marino 42*e4b17023SJohn Marino /** @brief Decide whether to declare certain variables volatile. */ 43*e4b17023SJohn Marino #define _GLIBCXX_VOLATILE volatile 44*e4b17023SJohn Marino 45*e4b17023SJohn Marino namespace __gnu_parallel 46*e4b17023SJohn Marino { 47*e4b17023SJohn Marino /** @brief Parallel implementation of std::partition. 48*e4b17023SJohn Marino * @param __begin Begin iterator of input sequence to split. 49*e4b17023SJohn Marino * @param __end End iterator of input sequence to split. 50*e4b17023SJohn Marino * @param __pred Partition predicate, possibly including some kind 51*e4b17023SJohn Marino * of pivot. 52*e4b17023SJohn Marino * @param __num_threads Maximum number of threads to use for this task. 53*e4b17023SJohn Marino * @return Number of elements not fulfilling the predicate. */ 54*e4b17023SJohn Marino template<typename _RAIter, typename _Predicate> 55*e4b17023SJohn Marino typename std::iterator_traits<_RAIter>::difference_type __parallel_partition(_RAIter __begin,_RAIter __end,_Predicate __pred,_ThreadIndex __num_threads)56*e4b17023SJohn Marino __parallel_partition(_RAIter __begin, _RAIter __end, 57*e4b17023SJohn Marino _Predicate __pred, _ThreadIndex __num_threads) 58*e4b17023SJohn Marino { 59*e4b17023SJohn Marino typedef std::iterator_traits<_RAIter> _TraitsType; 60*e4b17023SJohn Marino typedef typename _TraitsType::value_type _ValueType; 61*e4b17023SJohn Marino typedef typename _TraitsType::difference_type _DifferenceType; 62*e4b17023SJohn Marino 63*e4b17023SJohn Marino _DifferenceType __n = __end - __begin; 64*e4b17023SJohn Marino 65*e4b17023SJohn Marino _GLIBCXX_CALL(__n) 66*e4b17023SJohn Marino 67*e4b17023SJohn Marino const _Settings& __s = _Settings::get(); 68*e4b17023SJohn Marino 69*e4b17023SJohn Marino // shared 70*e4b17023SJohn Marino _GLIBCXX_VOLATILE _DifferenceType __left = 0, __right = __n - 1, 71*e4b17023SJohn Marino __dist = __n, 72*e4b17023SJohn Marino __leftover_left, __leftover_right, 73*e4b17023SJohn Marino __leftnew, __rightnew; 74*e4b17023SJohn Marino 75*e4b17023SJohn Marino // just 0 or 1, but int to allow atomic operations 76*e4b17023SJohn Marino int* __reserved_left = 0, * __reserved_right = 0; 77*e4b17023SJohn Marino 78*e4b17023SJohn Marino _DifferenceType __chunk_size = __s.partition_chunk_size; 79*e4b17023SJohn Marino 80*e4b17023SJohn Marino //at least two chunks per thread 81*e4b17023SJohn Marino if (__dist >= 2 * __num_threads * __chunk_size) 82*e4b17023SJohn Marino # pragma omp parallel num_threads(__num_threads) 83*e4b17023SJohn Marino { 84*e4b17023SJohn Marino # pragma omp single 85*e4b17023SJohn Marino { 86*e4b17023SJohn Marino __num_threads = omp_get_num_threads(); 87*e4b17023SJohn Marino __reserved_left = new int[__num_threads]; 88*e4b17023SJohn Marino __reserved_right = new int[__num_threads]; 89*e4b17023SJohn Marino 90*e4b17023SJohn Marino if (__s.partition_chunk_share > 0.0) 91*e4b17023SJohn Marino __chunk_size = std::max<_DifferenceType> 92*e4b17023SJohn Marino (__s.partition_chunk_size, (double)__n 93*e4b17023SJohn Marino * __s.partition_chunk_share / (double)__num_threads); 94*e4b17023SJohn Marino else 95*e4b17023SJohn Marino __chunk_size = __s.partition_chunk_size; 96*e4b17023SJohn Marino } 97*e4b17023SJohn Marino 98*e4b17023SJohn Marino while (__dist >= 2 * __num_threads * __chunk_size) 99*e4b17023SJohn Marino { 100*e4b17023SJohn Marino # pragma omp single 101*e4b17023SJohn Marino { 102*e4b17023SJohn Marino _DifferenceType __num_chunks = __dist / __chunk_size; 103*e4b17023SJohn Marino 104*e4b17023SJohn Marino for (_ThreadIndex __r = 0; __r < __num_threads; ++__r) 105*e4b17023SJohn Marino { 106*e4b17023SJohn Marino __reserved_left [__r] = 0; // false 107*e4b17023SJohn Marino __reserved_right[__r] = 0; // false 108*e4b17023SJohn Marino } 109*e4b17023SJohn Marino __leftover_left = 0; 110*e4b17023SJohn Marino __leftover_right = 0; 111*e4b17023SJohn Marino } //implicit barrier 112*e4b17023SJohn Marino 113*e4b17023SJohn Marino // Private. 114*e4b17023SJohn Marino _DifferenceType __thread_left, __thread_left_border, 115*e4b17023SJohn Marino __thread_right, __thread_right_border; 116*e4b17023SJohn Marino 117*e4b17023SJohn Marino __thread_left = __left + 1; 118*e4b17023SJohn Marino // Just to satisfy the condition below. 119*e4b17023SJohn Marino __thread_left_border = __thread_left - 1; 120*e4b17023SJohn Marino 121*e4b17023SJohn Marino __thread_right = __n - 1; 122*e4b17023SJohn Marino // Just to satisfy the condition below. 123*e4b17023SJohn Marino __thread_right_border = __thread_right + 1; 124*e4b17023SJohn Marino 125*e4b17023SJohn Marino bool __iam_finished = false; 126*e4b17023SJohn Marino while (!__iam_finished) 127*e4b17023SJohn Marino { 128*e4b17023SJohn Marino if (__thread_left > __thread_left_border) 129*e4b17023SJohn Marino { 130*e4b17023SJohn Marino _DifferenceType __former_dist = 131*e4b17023SJohn Marino __fetch_and_add(&__dist, -__chunk_size); 132*e4b17023SJohn Marino if (__former_dist < __chunk_size) 133*e4b17023SJohn Marino { 134*e4b17023SJohn Marino __fetch_and_add(&__dist, __chunk_size); 135*e4b17023SJohn Marino __iam_finished = true; 136*e4b17023SJohn Marino break; 137*e4b17023SJohn Marino } 138*e4b17023SJohn Marino else 139*e4b17023SJohn Marino { 140*e4b17023SJohn Marino __thread_left = 141*e4b17023SJohn Marino __fetch_and_add(&__left, __chunk_size); 142*e4b17023SJohn Marino __thread_left_border = 143*e4b17023SJohn Marino __thread_left + (__chunk_size - 1); 144*e4b17023SJohn Marino } 145*e4b17023SJohn Marino } 146*e4b17023SJohn Marino 147*e4b17023SJohn Marino if (__thread_right < __thread_right_border) 148*e4b17023SJohn Marino { 149*e4b17023SJohn Marino _DifferenceType __former_dist = 150*e4b17023SJohn Marino __fetch_and_add(&__dist, -__chunk_size); 151*e4b17023SJohn Marino if (__former_dist < __chunk_size) 152*e4b17023SJohn Marino { 153*e4b17023SJohn Marino __fetch_and_add(&__dist, __chunk_size); 154*e4b17023SJohn Marino __iam_finished = true; 155*e4b17023SJohn Marino break; 156*e4b17023SJohn Marino } 157*e4b17023SJohn Marino else 158*e4b17023SJohn Marino { 159*e4b17023SJohn Marino __thread_right = 160*e4b17023SJohn Marino __fetch_and_add(&__right, -__chunk_size); 161*e4b17023SJohn Marino __thread_right_border = 162*e4b17023SJohn Marino __thread_right - (__chunk_size - 1); 163*e4b17023SJohn Marino } 164*e4b17023SJohn Marino } 165*e4b17023SJohn Marino 166*e4b17023SJohn Marino // Swap as usual. 167*e4b17023SJohn Marino while (__thread_left < __thread_right) 168*e4b17023SJohn Marino { 169*e4b17023SJohn Marino while (__pred(__begin[__thread_left]) 170*e4b17023SJohn Marino && __thread_left <= __thread_left_border) 171*e4b17023SJohn Marino ++__thread_left; 172*e4b17023SJohn Marino while (!__pred(__begin[__thread_right]) 173*e4b17023SJohn Marino && __thread_right >= __thread_right_border) 174*e4b17023SJohn Marino --__thread_right; 175*e4b17023SJohn Marino 176*e4b17023SJohn Marino if (__thread_left > __thread_left_border 177*e4b17023SJohn Marino || __thread_right < __thread_right_border) 178*e4b17023SJohn Marino // Fetch new chunk(__s). 179*e4b17023SJohn Marino break; 180*e4b17023SJohn Marino 181*e4b17023SJohn Marino std::iter_swap(__begin + __thread_left, 182*e4b17023SJohn Marino __begin + __thread_right); 183*e4b17023SJohn Marino ++__thread_left; 184*e4b17023SJohn Marino --__thread_right; 185*e4b17023SJohn Marino } 186*e4b17023SJohn Marino } 187*e4b17023SJohn Marino 188*e4b17023SJohn Marino // Now swap the leftover chunks to the right places. 189*e4b17023SJohn Marino if (__thread_left <= __thread_left_border) 190*e4b17023SJohn Marino # pragma omp atomic 191*e4b17023SJohn Marino ++__leftover_left; 192*e4b17023SJohn Marino if (__thread_right >= __thread_right_border) 193*e4b17023SJohn Marino # pragma omp atomic 194*e4b17023SJohn Marino ++__leftover_right; 195*e4b17023SJohn Marino 196*e4b17023SJohn Marino # pragma omp barrier 197*e4b17023SJohn Marino 198*e4b17023SJohn Marino _DifferenceType 199*e4b17023SJohn Marino __leftold = __left, 200*e4b17023SJohn Marino __leftnew = __left - __leftover_left * __chunk_size, 201*e4b17023SJohn Marino __rightold = __right, 202*e4b17023SJohn Marino __rightnew = __right + __leftover_right * __chunk_size; 203*e4b17023SJohn Marino 204*e4b17023SJohn Marino // <=> __thread_left_border + (__chunk_size - 1) >= __leftnew 205*e4b17023SJohn Marino if (__thread_left <= __thread_left_border 206*e4b17023SJohn Marino && __thread_left_border >= __leftnew) 207*e4b17023SJohn Marino { 208*e4b17023SJohn Marino // Chunk already in place, reserve spot. 209*e4b17023SJohn Marino __reserved_left[(__left - (__thread_left_border + 1)) 210*e4b17023SJohn Marino / __chunk_size] = 1; 211*e4b17023SJohn Marino } 212*e4b17023SJohn Marino 213*e4b17023SJohn Marino // <=> __thread_right_border - (__chunk_size - 1) <= __rightnew 214*e4b17023SJohn Marino if (__thread_right >= __thread_right_border 215*e4b17023SJohn Marino && __thread_right_border <= __rightnew) 216*e4b17023SJohn Marino { 217*e4b17023SJohn Marino // Chunk already in place, reserve spot. 218*e4b17023SJohn Marino __reserved_right[((__thread_right_border - 1) - __right) 219*e4b17023SJohn Marino / __chunk_size] = 1; 220*e4b17023SJohn Marino } 221*e4b17023SJohn Marino 222*e4b17023SJohn Marino # pragma omp barrier 223*e4b17023SJohn Marino 224*e4b17023SJohn Marino if (__thread_left <= __thread_left_border 225*e4b17023SJohn Marino && __thread_left_border < __leftnew) 226*e4b17023SJohn Marino { 227*e4b17023SJohn Marino // Find spot and swap. 228*e4b17023SJohn Marino _DifferenceType __swapstart = -1; 229*e4b17023SJohn Marino for (int __r = 0; __r < __leftover_left; ++__r) 230*e4b17023SJohn Marino if (__reserved_left[__r] == 0 231*e4b17023SJohn Marino && __compare_and_swap(&(__reserved_left[__r]), 0, 1)) 232*e4b17023SJohn Marino { 233*e4b17023SJohn Marino __swapstart = __leftold - (__r + 1) * __chunk_size; 234*e4b17023SJohn Marino break; 235*e4b17023SJohn Marino } 236*e4b17023SJohn Marino 237*e4b17023SJohn Marino #if _GLIBCXX_ASSERTIONS 238*e4b17023SJohn Marino _GLIBCXX_PARALLEL_ASSERT(__swapstart != -1); 239*e4b17023SJohn Marino #endif 240*e4b17023SJohn Marino 241*e4b17023SJohn Marino std::swap_ranges(__begin + __thread_left_border 242*e4b17023SJohn Marino - (__chunk_size - 1), 243*e4b17023SJohn Marino __begin + __thread_left_border + 1, 244*e4b17023SJohn Marino __begin + __swapstart); 245*e4b17023SJohn Marino } 246*e4b17023SJohn Marino 247*e4b17023SJohn Marino if (__thread_right >= __thread_right_border 248*e4b17023SJohn Marino && __thread_right_border > __rightnew) 249*e4b17023SJohn Marino { 250*e4b17023SJohn Marino // Find spot and swap 251*e4b17023SJohn Marino _DifferenceType __swapstart = -1; 252*e4b17023SJohn Marino for (int __r = 0; __r < __leftover_right; ++__r) 253*e4b17023SJohn Marino if (__reserved_right[__r] == 0 254*e4b17023SJohn Marino && __compare_and_swap(&(__reserved_right[__r]), 0, 1)) 255*e4b17023SJohn Marino { 256*e4b17023SJohn Marino __swapstart = __rightold + __r * __chunk_size + 1; 257*e4b17023SJohn Marino break; 258*e4b17023SJohn Marino } 259*e4b17023SJohn Marino 260*e4b17023SJohn Marino #if _GLIBCXX_ASSERTIONS 261*e4b17023SJohn Marino _GLIBCXX_PARALLEL_ASSERT(__swapstart != -1); 262*e4b17023SJohn Marino #endif 263*e4b17023SJohn Marino 264*e4b17023SJohn Marino std::swap_ranges(__begin + __thread_right_border, 265*e4b17023SJohn Marino __begin + __thread_right_border 266*e4b17023SJohn Marino + __chunk_size, __begin + __swapstart); 267*e4b17023SJohn Marino } 268*e4b17023SJohn Marino #if _GLIBCXX_ASSERTIONS 269*e4b17023SJohn Marino # pragma omp barrier 270*e4b17023SJohn Marino 271*e4b17023SJohn Marino # pragma omp single 272*e4b17023SJohn Marino { 273*e4b17023SJohn Marino for (_DifferenceType __r = 0; __r < __leftover_left; ++__r) 274*e4b17023SJohn Marino _GLIBCXX_PARALLEL_ASSERT(__reserved_left[__r] == 1); 275*e4b17023SJohn Marino for (_DifferenceType __r = 0; __r < __leftover_right; ++__r) 276*e4b17023SJohn Marino _GLIBCXX_PARALLEL_ASSERT(__reserved_right[__r] == 1); 277*e4b17023SJohn Marino } 278*e4b17023SJohn Marino #endif 279*e4b17023SJohn Marino 280*e4b17023SJohn Marino __left = __leftnew; 281*e4b17023SJohn Marino __right = __rightnew; 282*e4b17023SJohn Marino __dist = __right - __left + 1; 283*e4b17023SJohn Marino } 284*e4b17023SJohn Marino 285*e4b17023SJohn Marino # pragma omp flush(__left, __right) 286*e4b17023SJohn Marino } // end "recursion" //parallel 287*e4b17023SJohn Marino 288*e4b17023SJohn Marino _DifferenceType __final_left = __left, __final_right = __right; 289*e4b17023SJohn Marino 290*e4b17023SJohn Marino while (__final_left < __final_right) 291*e4b17023SJohn Marino { 292*e4b17023SJohn Marino // Go right until key is geq than pivot. 293*e4b17023SJohn Marino while (__pred(__begin[__final_left]) 294*e4b17023SJohn Marino && __final_left < __final_right) 295*e4b17023SJohn Marino ++__final_left; 296*e4b17023SJohn Marino 297*e4b17023SJohn Marino // Go left until key is less than pivot. 298*e4b17023SJohn Marino while (!__pred(__begin[__final_right]) 299*e4b17023SJohn Marino && __final_left < __final_right) 300*e4b17023SJohn Marino --__final_right; 301*e4b17023SJohn Marino 302*e4b17023SJohn Marino if (__final_left == __final_right) 303*e4b17023SJohn Marino break; 304*e4b17023SJohn Marino std::iter_swap(__begin + __final_left, __begin + __final_right); 305*e4b17023SJohn Marino ++__final_left; 306*e4b17023SJohn Marino --__final_right; 307*e4b17023SJohn Marino } 308*e4b17023SJohn Marino 309*e4b17023SJohn Marino // All elements on the left side are < piv, all elements on the 310*e4b17023SJohn Marino // right are >= piv 311*e4b17023SJohn Marino delete[] __reserved_left; 312*e4b17023SJohn Marino delete[] __reserved_right; 313*e4b17023SJohn Marino 314*e4b17023SJohn Marino // Element "between" __final_left and __final_right might not have 315*e4b17023SJohn Marino // been regarded yet 316*e4b17023SJohn Marino if (__final_left < __n && !__pred(__begin[__final_left])) 317*e4b17023SJohn Marino // Really swapped. 318*e4b17023SJohn Marino return __final_left; 319*e4b17023SJohn Marino else 320*e4b17023SJohn Marino return __final_left + 1; 321*e4b17023SJohn Marino } 322*e4b17023SJohn Marino 323*e4b17023SJohn Marino /** 324*e4b17023SJohn Marino * @brief Parallel implementation of std::nth_element(). 325*e4b17023SJohn Marino * @param __begin Begin iterator of input sequence. 326*e4b17023SJohn Marino * @param __nth _Iterator of element that must be in position afterwards. 327*e4b17023SJohn Marino * @param __end End iterator of input sequence. 328*e4b17023SJohn Marino * @param __comp Comparator. 329*e4b17023SJohn Marino */ 330*e4b17023SJohn Marino template<typename _RAIter, typename _Compare> 331*e4b17023SJohn Marino void __parallel_nth_element(_RAIter __begin,_RAIter __nth,_RAIter __end,_Compare __comp)332*e4b17023SJohn Marino __parallel_nth_element(_RAIter __begin, _RAIter __nth, 333*e4b17023SJohn Marino _RAIter __end, _Compare __comp) 334*e4b17023SJohn Marino { 335*e4b17023SJohn Marino typedef std::iterator_traits<_RAIter> _TraitsType; 336*e4b17023SJohn Marino typedef typename _TraitsType::value_type _ValueType; 337*e4b17023SJohn Marino typedef typename _TraitsType::difference_type _DifferenceType; 338*e4b17023SJohn Marino 339*e4b17023SJohn Marino _GLIBCXX_CALL(__end - __begin) 340*e4b17023SJohn Marino 341*e4b17023SJohn Marino _RAIter __split; 342*e4b17023SJohn Marino _RandomNumber __rng; 343*e4b17023SJohn Marino 344*e4b17023SJohn Marino const _Settings& __s = _Settings::get(); 345*e4b17023SJohn Marino _DifferenceType __minimum_length = std::max<_DifferenceType>(2, 346*e4b17023SJohn Marino std::max(__s.nth_element_minimal_n, __s.partition_minimal_n)); 347*e4b17023SJohn Marino 348*e4b17023SJohn Marino // Break if input range to small. 349*e4b17023SJohn Marino while (static_cast<_SequenceIndex>(__end - __begin) >= __minimum_length) 350*e4b17023SJohn Marino { 351*e4b17023SJohn Marino _DifferenceType __n = __end - __begin; 352*e4b17023SJohn Marino 353*e4b17023SJohn Marino _RAIter __pivot_pos = __begin + __rng(__n); 354*e4b17023SJohn Marino 355*e4b17023SJohn Marino // Swap __pivot_pos value to end. 356*e4b17023SJohn Marino if (__pivot_pos != (__end - 1)) 357*e4b17023SJohn Marino std::iter_swap(__pivot_pos, __end - 1); 358*e4b17023SJohn Marino __pivot_pos = __end - 1; 359*e4b17023SJohn Marino 360*e4b17023SJohn Marino // _Compare must have first_value_type, second_value_type, 361*e4b17023SJohn Marino // result_type 362*e4b17023SJohn Marino // _Compare == 363*e4b17023SJohn Marino // __gnu_parallel::_Lexicographic<S, int, 364*e4b17023SJohn Marino // __gnu_parallel::_Less<S, S> > 365*e4b17023SJohn Marino // __pivot_pos == std::pair<S, int>* 366*e4b17023SJohn Marino __gnu_parallel::__binder2nd<_Compare, _ValueType, _ValueType, bool> 367*e4b17023SJohn Marino __pred(__comp, *__pivot_pos); 368*e4b17023SJohn Marino 369*e4b17023SJohn Marino // Divide, leave pivot unchanged in last place. 370*e4b17023SJohn Marino _RAIter __split_pos1, __split_pos2; 371*e4b17023SJohn Marino __split_pos1 = __begin + __parallel_partition(__begin, __end - 1, 372*e4b17023SJohn Marino __pred, 373*e4b17023SJohn Marino __get_max_threads()); 374*e4b17023SJohn Marino 375*e4b17023SJohn Marino // Left side: < __pivot_pos; __right side: >= __pivot_pos 376*e4b17023SJohn Marino 377*e4b17023SJohn Marino // Swap pivot back to middle. 378*e4b17023SJohn Marino if (__split_pos1 != __pivot_pos) 379*e4b17023SJohn Marino std::iter_swap(__split_pos1, __pivot_pos); 380*e4b17023SJohn Marino __pivot_pos = __split_pos1; 381*e4b17023SJohn Marino 382*e4b17023SJohn Marino // In case all elements are equal, __split_pos1 == 0 383*e4b17023SJohn Marino if ((__split_pos1 + 1 - __begin) < (__n >> 7) 384*e4b17023SJohn Marino || (__end - __split_pos1) < (__n >> 7)) 385*e4b17023SJohn Marino { 386*e4b17023SJohn Marino // Very unequal split, one part smaller than one 128th 387*e4b17023SJohn Marino // elements not strictly larger than the pivot. 388*e4b17023SJohn Marino __gnu_parallel::__unary_negate<__gnu_parallel:: 389*e4b17023SJohn Marino __binder1st<_Compare, _ValueType, 390*e4b17023SJohn Marino _ValueType, bool>, _ValueType> 391*e4b17023SJohn Marino __pred(__gnu_parallel::__binder1st<_Compare, _ValueType, 392*e4b17023SJohn Marino _ValueType, bool>(__comp, *__pivot_pos)); 393*e4b17023SJohn Marino 394*e4b17023SJohn Marino // Find other end of pivot-equal range. 395*e4b17023SJohn Marino __split_pos2 = __gnu_sequential::partition(__split_pos1 + 1, 396*e4b17023SJohn Marino __end, __pred); 397*e4b17023SJohn Marino } 398*e4b17023SJohn Marino else 399*e4b17023SJohn Marino // Only skip the pivot. 400*e4b17023SJohn Marino __split_pos2 = __split_pos1 + 1; 401*e4b17023SJohn Marino 402*e4b17023SJohn Marino // Compare iterators. 403*e4b17023SJohn Marino if (__split_pos2 <= __nth) 404*e4b17023SJohn Marino __begin = __split_pos2; 405*e4b17023SJohn Marino else if (__nth < __split_pos1) 406*e4b17023SJohn Marino __end = __split_pos1; 407*e4b17023SJohn Marino else 408*e4b17023SJohn Marino break; 409*e4b17023SJohn Marino } 410*e4b17023SJohn Marino 411*e4b17023SJohn Marino // Only at most _Settings::partition_minimal_n __elements __left. 412*e4b17023SJohn Marino __gnu_sequential::nth_element(__begin, __nth, __end, __comp); 413*e4b17023SJohn Marino } 414*e4b17023SJohn Marino 415*e4b17023SJohn Marino /** @brief Parallel implementation of std::partial_sort(). 416*e4b17023SJohn Marino * @param __begin Begin iterator of input sequence. 417*e4b17023SJohn Marino * @param __middle Sort until this position. 418*e4b17023SJohn Marino * @param __end End iterator of input sequence. 419*e4b17023SJohn Marino * @param __comp Comparator. */ 420*e4b17023SJohn Marino template<typename _RAIter, typename _Compare> 421*e4b17023SJohn Marino void __parallel_partial_sort(_RAIter __begin,_RAIter __middle,_RAIter __end,_Compare __comp)422*e4b17023SJohn Marino __parallel_partial_sort(_RAIter __begin, 423*e4b17023SJohn Marino _RAIter __middle, 424*e4b17023SJohn Marino _RAIter __end, _Compare __comp) 425*e4b17023SJohn Marino { 426*e4b17023SJohn Marino __parallel_nth_element(__begin, __middle, __end, __comp); 427*e4b17023SJohn Marino std::sort(__begin, __middle, __comp); 428*e4b17023SJohn Marino } 429*e4b17023SJohn Marino 430*e4b17023SJohn Marino } //namespace __gnu_parallel 431*e4b17023SJohn Marino 432*e4b17023SJohn Marino #undef _GLIBCXX_VOLATILE 433*e4b17023SJohn Marino 434*e4b17023SJohn Marino #endif /* _GLIBCXX_PARALLEL_PARTITION_H */ 435