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