xref: /dflybsd-src/contrib/gcc-4.7/libstdc++-v3/include/parallel/unique_copy.h (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
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