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/unique_copy.h 26*e4b17023SJohn Marino * @brief Parallel implementations of std::unique_copy(). 27*e4b17023SJohn Marino * This file is a GNU parallel extension to the Standard C++ Library. 28*e4b17023SJohn Marino */ 29*e4b17023SJohn Marino 30*e4b17023SJohn Marino // Written by Robert Geisberger and Robin Dapp. 31*e4b17023SJohn Marino 32*e4b17023SJohn Marino #ifndef _GLIBCXX_PARALLEL_UNIQUE_COPY_H 33*e4b17023SJohn Marino #define _GLIBCXX_PARALLEL_UNIQUE_COPY_H 1 34*e4b17023SJohn Marino 35*e4b17023SJohn Marino #include <parallel/parallel.h> 36*e4b17023SJohn Marino #include <parallel/multiseq_selection.h> 37*e4b17023SJohn Marino 38*e4b17023SJohn Marino namespace __gnu_parallel 39*e4b17023SJohn Marino { 40*e4b17023SJohn Marino /** @brief Parallel std::unique_copy(), w/__o explicit equality predicate. 41*e4b17023SJohn Marino * @param __first Begin iterator of input sequence. 42*e4b17023SJohn Marino * @param __last End iterator of input sequence. 43*e4b17023SJohn Marino * @param __result Begin iterator of result __sequence. 44*e4b17023SJohn Marino * @param __binary_pred Equality predicate. 45*e4b17023SJohn Marino * @return End iterator of result __sequence. */ 46*e4b17023SJohn Marino template<typename _IIter, 47*e4b17023SJohn Marino class _OutputIterator, 48*e4b17023SJohn Marino class _BinaryPredicate> 49*e4b17023SJohn Marino _OutputIterator __parallel_unique_copy(_IIter __first,_IIter __last,_OutputIterator __result,_BinaryPredicate __binary_pred)50*e4b17023SJohn Marino __parallel_unique_copy(_IIter __first, _IIter __last, 51*e4b17023SJohn Marino _OutputIterator __result, 52*e4b17023SJohn Marino _BinaryPredicate __binary_pred) 53*e4b17023SJohn Marino { 54*e4b17023SJohn Marino _GLIBCXX_CALL(__last - __first) 55*e4b17023SJohn Marino 56*e4b17023SJohn Marino typedef std::iterator_traits<_IIter> _TraitsType; 57*e4b17023SJohn Marino typedef typename _TraitsType::value_type _ValueType; 58*e4b17023SJohn Marino typedef typename _TraitsType::difference_type _DifferenceType; 59*e4b17023SJohn Marino 60*e4b17023SJohn Marino _DifferenceType __size = __last - __first; 61*e4b17023SJohn Marino 62*e4b17023SJohn Marino if (__size == 0) 63*e4b17023SJohn Marino return __result; 64*e4b17023SJohn Marino 65*e4b17023SJohn Marino // Let the first thread process two parts. 66*e4b17023SJohn Marino _DifferenceType *__counter; 67*e4b17023SJohn Marino _DifferenceType *__borders; 68*e4b17023SJohn Marino 69*e4b17023SJohn Marino _ThreadIndex __num_threads = __get_max_threads(); 70*e4b17023SJohn Marino // First part contains at least one element. 71*e4b17023SJohn Marino # pragma omp parallel num_threads(__num_threads) 72*e4b17023SJohn Marino { 73*e4b17023SJohn Marino # pragma omp single 74*e4b17023SJohn Marino { 75*e4b17023SJohn Marino __num_threads = omp_get_num_threads(); 76*e4b17023SJohn Marino __borders = new _DifferenceType[__num_threads + 2]; 77*e4b17023SJohn Marino __equally_split(__size, __num_threads + 1, __borders); 78*e4b17023SJohn Marino __counter = new _DifferenceType[__num_threads + 1]; 79*e4b17023SJohn Marino } 80*e4b17023SJohn Marino 81*e4b17023SJohn Marino _ThreadIndex __iam = omp_get_thread_num(); 82*e4b17023SJohn Marino 83*e4b17023SJohn Marino _DifferenceType __begin, __end; 84*e4b17023SJohn Marino 85*e4b17023SJohn Marino // Check for length without duplicates 86*e4b17023SJohn Marino // Needed for position in output 87*e4b17023SJohn Marino _DifferenceType __i = 0; 88*e4b17023SJohn Marino _OutputIterator __out = __result; 89*e4b17023SJohn Marino 90*e4b17023SJohn Marino if (__iam == 0) 91*e4b17023SJohn Marino { 92*e4b17023SJohn Marino __begin = __borders[0] + 1; // == 1 93*e4b17023SJohn Marino __end = __borders[__iam + 1]; 94*e4b17023SJohn Marino 95*e4b17023SJohn Marino ++__i; 96*e4b17023SJohn Marino *__out++ = *__first; 97*e4b17023SJohn Marino 98*e4b17023SJohn Marino for (_IIter __iter = __first + __begin; __iter < __first + __end; 99*e4b17023SJohn Marino ++__iter) 100*e4b17023SJohn Marino { 101*e4b17023SJohn Marino if (!__binary_pred(*__iter, *(__iter - 1))) 102*e4b17023SJohn Marino { 103*e4b17023SJohn Marino ++__i; 104*e4b17023SJohn Marino *__out++ = *__iter; 105*e4b17023SJohn Marino } 106*e4b17023SJohn Marino } 107*e4b17023SJohn Marino } 108*e4b17023SJohn Marino else 109*e4b17023SJohn Marino { 110*e4b17023SJohn Marino __begin = __borders[__iam]; //one part 111*e4b17023SJohn Marino __end = __borders[__iam + 1]; 112*e4b17023SJohn Marino 113*e4b17023SJohn Marino for (_IIter __iter = __first + __begin; __iter < __first + __end; 114*e4b17023SJohn Marino ++__iter) 115*e4b17023SJohn Marino { 116*e4b17023SJohn Marino if (!__binary_pred(*__iter, *(__iter - 1))) 117*e4b17023SJohn Marino ++__i; 118*e4b17023SJohn Marino } 119*e4b17023SJohn Marino } 120*e4b17023SJohn Marino __counter[__iam] = __i; 121*e4b17023SJohn Marino 122*e4b17023SJohn Marino // Last part still untouched. 123*e4b17023SJohn Marino _DifferenceType __begin_output; 124*e4b17023SJohn Marino 125*e4b17023SJohn Marino # pragma omp barrier 126*e4b17023SJohn Marino 127*e4b17023SJohn Marino // Store result in output on calculated positions. 128*e4b17023SJohn Marino __begin_output = 0; 129*e4b17023SJohn Marino 130*e4b17023SJohn Marino if (__iam == 0) 131*e4b17023SJohn Marino { 132*e4b17023SJohn Marino for (_ThreadIndex __t = 0; __t < __num_threads; ++__t) 133*e4b17023SJohn Marino __begin_output += __counter[__t]; 134*e4b17023SJohn Marino 135*e4b17023SJohn Marino __i = 0; 136*e4b17023SJohn Marino 137*e4b17023SJohn Marino _OutputIterator __iter_out = __result + __begin_output; 138*e4b17023SJohn Marino 139*e4b17023SJohn Marino __begin = __borders[__num_threads]; 140*e4b17023SJohn Marino __end = __size; 141*e4b17023SJohn Marino 142*e4b17023SJohn Marino for (_IIter __iter = __first + __begin; __iter < __first + __end; 143*e4b17023SJohn Marino ++__iter) 144*e4b17023SJohn Marino { 145*e4b17023SJohn Marino if (__iter == __first 146*e4b17023SJohn Marino || !__binary_pred(*__iter, *(__iter - 1))) 147*e4b17023SJohn Marino { 148*e4b17023SJohn Marino ++__i; 149*e4b17023SJohn Marino *__iter_out++ = *__iter; 150*e4b17023SJohn Marino } 151*e4b17023SJohn Marino } 152*e4b17023SJohn Marino 153*e4b17023SJohn Marino __counter[__num_threads] = __i; 154*e4b17023SJohn Marino } 155*e4b17023SJohn Marino else 156*e4b17023SJohn Marino { 157*e4b17023SJohn Marino for (_ThreadIndex __t = 0; __t < __iam; __t++) 158*e4b17023SJohn Marino __begin_output += __counter[__t]; 159*e4b17023SJohn Marino 160*e4b17023SJohn Marino _OutputIterator __iter_out = __result + __begin_output; 161*e4b17023SJohn Marino for (_IIter __iter = __first + __begin; __iter < __first + __end; 162*e4b17023SJohn Marino ++__iter) 163*e4b17023SJohn Marino { 164*e4b17023SJohn Marino if (!__binary_pred(*__iter, *(__iter - 1))) 165*e4b17023SJohn Marino *__iter_out++ = *__iter; 166*e4b17023SJohn Marino } 167*e4b17023SJohn Marino } 168*e4b17023SJohn Marino } 169*e4b17023SJohn Marino 170*e4b17023SJohn Marino _DifferenceType __end_output = 0; 171*e4b17023SJohn Marino for (_ThreadIndex __t = 0; __t < __num_threads + 1; __t++) 172*e4b17023SJohn Marino __end_output += __counter[__t]; 173*e4b17023SJohn Marino 174*e4b17023SJohn Marino delete[] __borders; 175*e4b17023SJohn Marino 176*e4b17023SJohn Marino return __result + __end_output; 177*e4b17023SJohn Marino } 178*e4b17023SJohn Marino 179*e4b17023SJohn Marino /** @brief Parallel std::unique_copy(), without explicit equality predicate 180*e4b17023SJohn Marino * @param __first Begin iterator of input sequence. 181*e4b17023SJohn Marino * @param __last End iterator of input sequence. 182*e4b17023SJohn Marino * @param __result Begin iterator of result __sequence. 183*e4b17023SJohn Marino * @return End iterator of result __sequence. */ 184*e4b17023SJohn Marino template<typename _IIter, class _OutputIterator> 185*e4b17023SJohn Marino inline _OutputIterator __parallel_unique_copy(_IIter __first,_IIter __last,_OutputIterator __result)186*e4b17023SJohn Marino __parallel_unique_copy(_IIter __first, _IIter __last, 187*e4b17023SJohn Marino _OutputIterator __result) 188*e4b17023SJohn Marino { 189*e4b17023SJohn Marino typedef typename std::iterator_traits<_IIter>::value_type 190*e4b17023SJohn Marino _ValueType; 191*e4b17023SJohn Marino return __parallel_unique_copy(__first, __last, __result, 192*e4b17023SJohn Marino std::equal_to<_ValueType>()); 193*e4b17023SJohn Marino } 194*e4b17023SJohn Marino 195*e4b17023SJohn Marino }//namespace __gnu_parallel 196*e4b17023SJohn Marino 197*e4b17023SJohn Marino #endif /* _GLIBCXX_PARALLEL_UNIQUE_COPY_H */ 198