1*e4b17023SJohn Marino // -*- C++ -*- 2*e4b17023SJohn Marino 3*e4b17023SJohn Marino // Copyright (C) 2007, 2008, 2009 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/list_partition.h 26*e4b17023SJohn Marino * @brief _Functionality to split __sequence referenced by only input 27*e4b17023SJohn Marino * iterators. 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 Leonor Frias Moya and Johannes Singler. 32*e4b17023SJohn Marino 33*e4b17023SJohn Marino #ifndef _GLIBCXX_PARALLEL_LIST_PARTITION_H 34*e4b17023SJohn Marino #define _GLIBCXX_PARALLEL_LIST_PARTITION_H 1 35*e4b17023SJohn Marino 36*e4b17023SJohn Marino #include <parallel/parallel.h> 37*e4b17023SJohn Marino #include <vector> 38*e4b17023SJohn Marino 39*e4b17023SJohn Marino namespace __gnu_parallel 40*e4b17023SJohn Marino { 41*e4b17023SJohn Marino /** @brief Shrinks and doubles the ranges. 42*e4b17023SJohn Marino * @param __os_starts Start positions worked on (oversampled). 43*e4b17023SJohn Marino * @param __count_to_two Counts up to 2. 44*e4b17023SJohn Marino * @param __range_length Current length of a chunk. 45*e4b17023SJohn Marino * @param __make_twice Whether the @c __os_starts is allowed to be 46*e4b17023SJohn Marino * grown or not 47*e4b17023SJohn Marino */ 48*e4b17023SJohn Marino template<typename _IIter> 49*e4b17023SJohn Marino void __shrink_and_double(std::vector<_IIter> & __os_starts,size_t & __count_to_two,size_t & __range_length,const bool __make_twice)50*e4b17023SJohn Marino __shrink_and_double(std::vector<_IIter>& __os_starts, 51*e4b17023SJohn Marino size_t& __count_to_two, size_t& __range_length, 52*e4b17023SJohn Marino const bool __make_twice) 53*e4b17023SJohn Marino { 54*e4b17023SJohn Marino ++__count_to_two; 55*e4b17023SJohn Marino if (!__make_twice || __count_to_two < 2) 56*e4b17023SJohn Marino __shrink(__os_starts, __count_to_two, __range_length); 57*e4b17023SJohn Marino else 58*e4b17023SJohn Marino { 59*e4b17023SJohn Marino __os_starts.resize((__os_starts.size() - 1) * 2 + 1); 60*e4b17023SJohn Marino __count_to_two = 0; 61*e4b17023SJohn Marino } 62*e4b17023SJohn Marino } 63*e4b17023SJohn Marino 64*e4b17023SJohn Marino /** @brief Combines two ranges into one and thus halves the number of ranges. 65*e4b17023SJohn Marino * @param __os_starts Start positions worked on (oversampled). 66*e4b17023SJohn Marino * @param __count_to_two Counts up to 2. 67*e4b17023SJohn Marino * @param __range_length Current length of a chunk. */ 68*e4b17023SJohn Marino template<typename _IIter> 69*e4b17023SJohn Marino void __shrink(std::vector<_IIter> & __os_starts,size_t & __count_to_two,size_t & __range_length)70*e4b17023SJohn Marino __shrink(std::vector<_IIter>& __os_starts, size_t& __count_to_two, 71*e4b17023SJohn Marino size_t& __range_length) 72*e4b17023SJohn Marino { 73*e4b17023SJohn Marino for (typename std::vector<_IIter>::size_type __i = 0; 74*e4b17023SJohn Marino __i <= (__os_starts.size() / 2); ++__i) 75*e4b17023SJohn Marino __os_starts[__i] = __os_starts[__i * 2]; 76*e4b17023SJohn Marino __range_length *= 2; 77*e4b17023SJohn Marino } 78*e4b17023SJohn Marino 79*e4b17023SJohn Marino /** @brief Splits a sequence given by input iterators into parts of 80*e4b17023SJohn Marino * almost equal size 81*e4b17023SJohn Marino * 82*e4b17023SJohn Marino * The function needs only one pass over the sequence. 83*e4b17023SJohn Marino * @param __begin Begin iterator of input sequence. 84*e4b17023SJohn Marino * @param __end End iterator of input sequence. 85*e4b17023SJohn Marino * @param __starts Start iterators for the resulting parts, dimension 86*e4b17023SJohn Marino * @c __num_parts+1. For convenience, @c __starts @c [__num_parts] 87*e4b17023SJohn Marino * contains the end iterator of the sequence. 88*e4b17023SJohn Marino * @param __lengths Length of the resulting parts. 89*e4b17023SJohn Marino * @param __num_parts Number of parts to split the sequence into. 90*e4b17023SJohn Marino * @param __f Functor to be applied to each element by traversing __it 91*e4b17023SJohn Marino * @param __oversampling Oversampling factor. If 0, then the 92*e4b17023SJohn Marino * partitions will differ in at most 93*e4b17023SJohn Marino * \sqrt{\mathrm{__end} - \mathrm{__begin}} 94*e4b17023SJohn Marino * __elements. Otherwise, the ratio between the 95*e4b17023SJohn Marino * longest and the shortest part is bounded by 96*e4b17023SJohn Marino * 1/(\mathrm{__oversampling} \cdot \mathrm{num\_parts}) 97*e4b17023SJohn Marino * @return Length of the whole sequence. 98*e4b17023SJohn Marino */ 99*e4b17023SJohn Marino template<typename _IIter, typename _FunctorType> 100*e4b17023SJohn Marino size_t 101*e4b17023SJohn Marino list_partition(const _IIter __begin, const _IIter __end, 102*e4b17023SJohn Marino _IIter* __starts, size_t* __lengths, const int __num_parts, 103*e4b17023SJohn Marino _FunctorType& __f, int __oversampling = 0) 104*e4b17023SJohn Marino { 105*e4b17023SJohn Marino bool __make_twice = false; 106*e4b17023SJohn Marino 107*e4b17023SJohn Marino // The resizing algorithm is chosen according to the oversampling factor. 108*e4b17023SJohn Marino if (__oversampling == 0) 109*e4b17023SJohn Marino { 110*e4b17023SJohn Marino __make_twice = true; 111*e4b17023SJohn Marino __oversampling = 1; 112*e4b17023SJohn Marino } 113*e4b17023SJohn Marino 114*e4b17023SJohn Marino std::vector<_IIter> __os_starts(2 * __oversampling * __num_parts + 1); 115*e4b17023SJohn Marino 116*e4b17023SJohn Marino __os_starts[0] = __begin; 117*e4b17023SJohn Marino _IIter __prev = __begin, __it = __begin; 118*e4b17023SJohn Marino size_t __dist_limit = 0, __dist = 0; 119*e4b17023SJohn Marino size_t __cur = 1, __next = 1; 120*e4b17023SJohn Marino size_t __range_length = 1; 121*e4b17023SJohn Marino size_t __count_to_two = 0; 122*e4b17023SJohn Marino while (__it != __end) 123*e4b17023SJohn Marino { 124*e4b17023SJohn Marino __cur = __next; 125*e4b17023SJohn Marino for (; __cur < __os_starts.size() and __it != __end; ++__cur) 126*e4b17023SJohn Marino { 127*e4b17023SJohn Marino for (__dist_limit += __range_length; 128*e4b17023SJohn Marino __dist < __dist_limit and __it != __end; ++__dist) 129*e4b17023SJohn Marino { 130*e4b17023SJohn Marino __f(__it); 131*e4b17023SJohn Marino ++__it; 132*e4b17023SJohn Marino } 133*e4b17023SJohn Marino __os_starts[__cur] = __it; 134*e4b17023SJohn Marino } 135*e4b17023SJohn Marino 136*e4b17023SJohn Marino // Must compare for end and not __cur < __os_starts.size() , because 137*e4b17023SJohn Marino // __cur could be == __os_starts.size() as well 138*e4b17023SJohn Marino if (__it == __end) 139*e4b17023SJohn Marino break; 140*e4b17023SJohn Marino 141*e4b17023SJohn Marino __shrink_and_double(__os_starts, __count_to_two, __range_length, 142*e4b17023SJohn Marino __make_twice); 143*e4b17023SJohn Marino __next = __os_starts.size() / 2 + 1; 144*e4b17023SJohn Marino } 145*e4b17023SJohn Marino 146*e4b17023SJohn Marino // Calculation of the parts (one must be extracted from __current 147*e4b17023SJohn Marino // because the partition beginning at end, consists only of 148*e4b17023SJohn Marino // itself). 149*e4b17023SJohn Marino size_t __size_part = (__cur - 1) / __num_parts; 150*e4b17023SJohn Marino int __size_greater = static_cast<int>((__cur - 1) % __num_parts); 151*e4b17023SJohn Marino __starts[0] = __os_starts[0]; 152*e4b17023SJohn Marino 153*e4b17023SJohn Marino size_t __index = 0; 154*e4b17023SJohn Marino 155*e4b17023SJohn Marino // Smallest partitions. 156*e4b17023SJohn Marino for (int __i = 1; __i < (__num_parts + 1 - __size_greater); ++__i) 157*e4b17023SJohn Marino { 158*e4b17023SJohn Marino __lengths[__i - 1] = __size_part * __range_length; 159*e4b17023SJohn Marino __index += __size_part; 160*e4b17023SJohn Marino __starts[__i] = __os_starts[__index]; 161*e4b17023SJohn Marino } 162*e4b17023SJohn Marino 163*e4b17023SJohn Marino // Biggest partitions. 164*e4b17023SJohn Marino for (int __i = __num_parts + 1 - __size_greater; __i <= __num_parts; 165*e4b17023SJohn Marino ++__i) 166*e4b17023SJohn Marino { 167*e4b17023SJohn Marino __lengths[__i - 1] = (__size_part+1) * __range_length; 168*e4b17023SJohn Marino __index += (__size_part+1); 169*e4b17023SJohn Marino __starts[__i] = __os_starts[__index]; 170*e4b17023SJohn Marino } 171*e4b17023SJohn Marino 172*e4b17023SJohn Marino // Correction of the end size (the end iteration has not finished). 173*e4b17023SJohn Marino __lengths[__num_parts - 1] -= (__dist_limit - __dist); 174*e4b17023SJohn Marino 175*e4b17023SJohn Marino return __dist; 176*e4b17023SJohn Marino } 177*e4b17023SJohn Marino } 178*e4b17023SJohn Marino 179*e4b17023SJohn Marino #endif /* _GLIBCXX_PARALLEL_LIST_PARTITION_H */ 180