xref: /dflybsd-src/contrib/gcc-8.0/libstdc++-v3/include/parallel/merge.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/merge.h
26*38fd1498Szrj  *  @brief Parallel implementation of std::merge().
27*38fd1498Szrj  *  This file is a GNU parallel extension to the Standard C++ Library.
28*38fd1498Szrj  */
29*38fd1498Szrj 
30*38fd1498Szrj // Written by Johannes Singler.
31*38fd1498Szrj 
32*38fd1498Szrj #ifndef _GLIBCXX_PARALLEL_MERGE_H
33*38fd1498Szrj #define _GLIBCXX_PARALLEL_MERGE_H 1
34*38fd1498Szrj 
35*38fd1498Szrj #include <parallel/basic_iterator.h>
36*38fd1498Szrj #include <bits/stl_algo.h>
37*38fd1498Szrj 
38*38fd1498Szrj namespace __gnu_parallel
39*38fd1498Szrj {
40*38fd1498Szrj   /** @brief Merge routine being able to merge only the @c __max_length
41*38fd1498Szrj    * smallest elements.
42*38fd1498Szrj    *
43*38fd1498Szrj    * The @c __begin iterators are advanced accordingly, they might not
44*38fd1498Szrj    * reach @c __end, in contrast to the usual variant.
45*38fd1498Szrj    * @param __begin1 Begin iterator of first sequence.
46*38fd1498Szrj    * @param __end1 End iterator of first sequence.
47*38fd1498Szrj    * @param __begin2 Begin iterator of second sequence.
48*38fd1498Szrj    * @param __end2 End iterator of second sequence.
49*38fd1498Szrj    * @param __target Target begin iterator.
50*38fd1498Szrj    * @param __max_length Maximum number of elements to merge.
51*38fd1498Szrj    * @param __comp Comparator.
52*38fd1498Szrj    * @return Output end iterator. */
53*38fd1498Szrj   template<typename _RAIter1, typename _RAIter2,
54*38fd1498Szrj            typename _OutputIterator, typename _DifferenceTp,
55*38fd1498Szrj            typename _Compare>
56*38fd1498Szrj     _OutputIterator
__merge_advance_usual(_RAIter1 & __begin1,_RAIter1 __end1,_RAIter2 & __begin2,_RAIter2 __end2,_OutputIterator __target,_DifferenceTp __max_length,_Compare __comp)57*38fd1498Szrj     __merge_advance_usual(_RAIter1& __begin1, _RAIter1 __end1,
58*38fd1498Szrj 			  _RAIter2& __begin2, _RAIter2 __end2,
59*38fd1498Szrj 			  _OutputIterator __target,
60*38fd1498Szrj 			  _DifferenceTp __max_length, _Compare __comp)
61*38fd1498Szrj     {
62*38fd1498Szrj       typedef _DifferenceTp _DifferenceType;
63*38fd1498Szrj       while (__begin1 != __end1 && __begin2 != __end2 && __max_length > 0)
64*38fd1498Szrj         {
65*38fd1498Szrj           // array1[__i1] < array0[i0]
66*38fd1498Szrj           if (__comp(*__begin2, *__begin1))
67*38fd1498Szrj             *__target++ = *__begin2++;
68*38fd1498Szrj           else
69*38fd1498Szrj             *__target++ = *__begin1++;
70*38fd1498Szrj           --__max_length;
71*38fd1498Szrj         }
72*38fd1498Szrj 
73*38fd1498Szrj       if (__begin1 != __end1)
74*38fd1498Szrj         {
75*38fd1498Szrj           __target = std::copy(__begin1, __begin1 + __max_length, __target);
76*38fd1498Szrj           __begin1 += __max_length;
77*38fd1498Szrj         }
78*38fd1498Szrj       else
79*38fd1498Szrj         {
80*38fd1498Szrj           __target = std::copy(__begin2, __begin2 + __max_length, __target);
81*38fd1498Szrj           __begin2 += __max_length;
82*38fd1498Szrj         }
83*38fd1498Szrj       return __target;
84*38fd1498Szrj     }
85*38fd1498Szrj 
86*38fd1498Szrj   /** @brief Merge routine being able to merge only the @c __max_length
87*38fd1498Szrj    * smallest elements.
88*38fd1498Szrj    *
89*38fd1498Szrj    * The @c __begin iterators are advanced accordingly, they might not
90*38fd1498Szrj    * reach @c __end, in contrast to the usual variant.
91*38fd1498Szrj    * Specially designed code should allow the compiler to generate
92*38fd1498Szrj    * conditional moves instead of branches.
93*38fd1498Szrj    * @param __begin1 Begin iterator of first sequence.
94*38fd1498Szrj    * @param __end1 End iterator of first sequence.
95*38fd1498Szrj    * @param __begin2 Begin iterator of second sequence.
96*38fd1498Szrj    * @param __end2 End iterator of second sequence.
97*38fd1498Szrj    * @param __target Target begin iterator.
98*38fd1498Szrj    * @param __max_length Maximum number of elements to merge.
99*38fd1498Szrj    * @param __comp Comparator.
100*38fd1498Szrj    * @return Output end iterator. */
101*38fd1498Szrj   template<typename _RAIter1, typename _RAIter2,
102*38fd1498Szrj            typename _OutputIterator, typename _DifferenceTp,
103*38fd1498Szrj            typename _Compare>
104*38fd1498Szrj     _OutputIterator
__merge_advance_movc(_RAIter1 & __begin1,_RAIter1 __end1,_RAIter2 & __begin2,_RAIter2 __end2,_OutputIterator __target,_DifferenceTp __max_length,_Compare __comp)105*38fd1498Szrj     __merge_advance_movc(_RAIter1& __begin1, _RAIter1 __end1,
106*38fd1498Szrj 			 _RAIter2& __begin2, _RAIter2 __end2,
107*38fd1498Szrj 			 _OutputIterator __target,
108*38fd1498Szrj 			 _DifferenceTp __max_length, _Compare __comp)
109*38fd1498Szrj     {
110*38fd1498Szrj       typedef _DifferenceTp _DifferenceType;
111*38fd1498Szrj       typedef typename std::iterator_traits<_RAIter1>::value_type
112*38fd1498Szrj         _ValueType1;
113*38fd1498Szrj       typedef typename std::iterator_traits<_RAIter2>::value_type
114*38fd1498Szrj         _ValueType2;
115*38fd1498Szrj 
116*38fd1498Szrj #if _GLIBCXX_PARALLEL_ASSERTIONS
117*38fd1498Szrj       _GLIBCXX_PARALLEL_ASSERT(__max_length >= 0);
118*38fd1498Szrj #endif
119*38fd1498Szrj 
120*38fd1498Szrj       while (__begin1 != __end1 && __begin2 != __end2 && __max_length > 0)
121*38fd1498Szrj         {
122*38fd1498Szrj           _RAIter1 __next1 = __begin1 + 1;
123*38fd1498Szrj           _RAIter2 __next2 = __begin2 + 1;
124*38fd1498Szrj           _ValueType1 __element1 = *__begin1;
125*38fd1498Szrj           _ValueType2 __element2 = *__begin2;
126*38fd1498Szrj 
127*38fd1498Szrj           if (__comp(__element2, __element1))
128*38fd1498Szrj             {
129*38fd1498Szrj               __element1 = __element2;
130*38fd1498Szrj               __begin2 = __next2;
131*38fd1498Szrj             }
132*38fd1498Szrj           else
133*38fd1498Szrj             __begin1 = __next1;
134*38fd1498Szrj 
135*38fd1498Szrj           *__target = __element1;
136*38fd1498Szrj 
137*38fd1498Szrj           ++__target;
138*38fd1498Szrj           --__max_length;
139*38fd1498Szrj         }
140*38fd1498Szrj       if (__begin1 != __end1)
141*38fd1498Szrj         {
142*38fd1498Szrj           __target = std::copy(__begin1, __begin1 + __max_length, __target);
143*38fd1498Szrj           __begin1 += __max_length;
144*38fd1498Szrj         }
145*38fd1498Szrj       else
146*38fd1498Szrj         {
147*38fd1498Szrj           __target = std::copy(__begin2, __begin2 + __max_length, __target);
148*38fd1498Szrj           __begin2 += __max_length;
149*38fd1498Szrj         }
150*38fd1498Szrj       return __target;
151*38fd1498Szrj     }
152*38fd1498Szrj 
153*38fd1498Szrj   /** @brief Merge routine being able to merge only the @c __max_length
154*38fd1498Szrj    * smallest elements.
155*38fd1498Szrj    *
156*38fd1498Szrj    *  The @c __begin iterators are advanced accordingly, they might not
157*38fd1498Szrj    *  reach @c __end, in contrast to the usual variant.
158*38fd1498Szrj    *  Static switch on whether to use the conditional-move variant.
159*38fd1498Szrj    *  @param __begin1 Begin iterator of first sequence.
160*38fd1498Szrj    *  @param __end1 End iterator of first sequence.
161*38fd1498Szrj    *  @param __begin2 Begin iterator of second sequence.
162*38fd1498Szrj    *  @param __end2 End iterator of second sequence.
163*38fd1498Szrj    *  @param __target Target begin iterator.
164*38fd1498Szrj    *  @param __max_length Maximum number of elements to merge.
165*38fd1498Szrj    *  @param __comp Comparator.
166*38fd1498Szrj    *  @return Output end iterator. */
167*38fd1498Szrj   template<typename _RAIter1, typename _RAIter2,
168*38fd1498Szrj            typename _OutputIterator, typename _DifferenceTp,
169*38fd1498Szrj            typename _Compare>
170*38fd1498Szrj     inline _OutputIterator
__merge_advance(_RAIter1 & __begin1,_RAIter1 __end1,_RAIter2 & __begin2,_RAIter2 __end2,_OutputIterator __target,_DifferenceTp __max_length,_Compare __comp)171*38fd1498Szrj     __merge_advance(_RAIter1& __begin1, _RAIter1 __end1,
172*38fd1498Szrj 		    _RAIter2& __begin2, _RAIter2 __end2,
173*38fd1498Szrj 		    _OutputIterator __target, _DifferenceTp __max_length,
174*38fd1498Szrj 		    _Compare __comp)
175*38fd1498Szrj     {
176*38fd1498Szrj       _GLIBCXX_CALL(__max_length)
177*38fd1498Szrj 
178*38fd1498Szrj       return __merge_advance_movc(__begin1, __end1, __begin2, __end2,
179*38fd1498Szrj 				  __target, __max_length, __comp);
180*38fd1498Szrj     }
181*38fd1498Szrj 
182*38fd1498Szrj   /** @brief Merge routine fallback to sequential in case the
183*38fd1498Szrj       iterators of the two input sequences are of different type.
184*38fd1498Szrj       *  @param __begin1 Begin iterator of first sequence.
185*38fd1498Szrj       *  @param __end1 End iterator of first sequence.
186*38fd1498Szrj       *  @param __begin2 Begin iterator of second sequence.
187*38fd1498Szrj       *  @param __end2 End iterator of second sequence.
188*38fd1498Szrj       *  @param __target Target begin iterator.
189*38fd1498Szrj       *  @param __max_length Maximum number of elements to merge.
190*38fd1498Szrj       *  @param __comp Comparator.
191*38fd1498Szrj       *  @return Output end iterator. */
192*38fd1498Szrj   template<typename _RAIter1, typename _RAIter2,
193*38fd1498Szrj            typename _RAIter3, typename _Compare>
194*38fd1498Szrj     inline _RAIter3
__parallel_merge_advance(_RAIter1 & __begin1,_RAIter1 __end1,_RAIter2 & __begin2,_RAIter2 __end2,_RAIter3 __target,typename std::iterator_traits<_RAIter1>::difference_type __max_length,_Compare __comp)195*38fd1498Szrj     __parallel_merge_advance(_RAIter1& __begin1, _RAIter1 __end1,
196*38fd1498Szrj 			     _RAIter2& __begin2,
197*38fd1498Szrj 			     // different iterators, parallel implementation
198*38fd1498Szrj 			     // not available
199*38fd1498Szrj 			     _RAIter2 __end2, _RAIter3 __target, typename
200*38fd1498Szrj 			     std::iterator_traits<_RAIter1>::
201*38fd1498Szrj 			     difference_type __max_length, _Compare __comp)
202*38fd1498Szrj     { return __merge_advance(__begin1, __end1, __begin2, __end2, __target,
203*38fd1498Szrj 			     __max_length, __comp); }
204*38fd1498Szrj 
205*38fd1498Szrj   /** @brief Parallel merge routine being able to merge only the @c
206*38fd1498Szrj    * __max_length smallest elements.
207*38fd1498Szrj    *
208*38fd1498Szrj    *  The @c __begin iterators are advanced accordingly, they might not
209*38fd1498Szrj    *  reach @c __end, in contrast to the usual variant.
210*38fd1498Szrj    *  The functionality is projected onto parallel_multiway_merge.
211*38fd1498Szrj    *  @param __begin1 Begin iterator of first sequence.
212*38fd1498Szrj    *  @param __end1 End iterator of first sequence.
213*38fd1498Szrj    *  @param __begin2 Begin iterator of second sequence.
214*38fd1498Szrj    *  @param __end2 End iterator of second sequence.
215*38fd1498Szrj    *  @param __target Target begin iterator.
216*38fd1498Szrj    *  @param __max_length Maximum number of elements to merge.
217*38fd1498Szrj    *  @param __comp Comparator.
218*38fd1498Szrj    *  @return Output end iterator.
219*38fd1498Szrj    */
220*38fd1498Szrj   template<typename _RAIter1, typename _RAIter3,
221*38fd1498Szrj            typename _Compare>
222*38fd1498Szrj     inline _RAIter3
__parallel_merge_advance(_RAIter1 & __begin1,_RAIter1 __end1,_RAIter1 & __begin2,_RAIter1 __end2,_RAIter3 __target,typename std::iterator_traits<_RAIter1>::difference_type __max_length,_Compare __comp)223*38fd1498Szrj     __parallel_merge_advance(_RAIter1& __begin1, _RAIter1 __end1,
224*38fd1498Szrj 			     _RAIter1& __begin2, _RAIter1 __end2,
225*38fd1498Szrj 			     _RAIter3 __target, typename
226*38fd1498Szrj 			     std::iterator_traits<_RAIter1>::
227*38fd1498Szrj 			     difference_type __max_length, _Compare __comp)
228*38fd1498Szrj     {
229*38fd1498Szrj       typedef typename
230*38fd1498Szrj           std::iterator_traits<_RAIter1>::value_type _ValueType;
231*38fd1498Szrj       typedef typename std::iterator_traits<_RAIter1>::
232*38fd1498Szrj         difference_type _DifferenceType1 /* == difference_type2 */;
233*38fd1498Szrj       typedef typename std::iterator_traits<_RAIter3>::
234*38fd1498Szrj         difference_type _DifferenceType3;
235*38fd1498Szrj       typedef typename std::pair<_RAIter1, _RAIter1>
236*38fd1498Szrj         _IteratorPair;
237*38fd1498Szrj 
238*38fd1498Szrj       _IteratorPair __seqs[2] = { std::make_pair(__begin1, __end1),
239*38fd1498Szrj 				  std::make_pair(__begin2, __end2) };
240*38fd1498Szrj       _RAIter3 __target_end = parallel_multiway_merge
241*38fd1498Szrj 	< /* __stable = */ true, /* __sentinels = */ false>
242*38fd1498Szrj 	(__seqs, __seqs + 2, __target, multiway_merge_exact_splitting
243*38fd1498Szrj 	 < /* __stable = */ true, _IteratorPair*,
244*38fd1498Szrj 	 _Compare, _DifferenceType1>, __max_length, __comp,
245*38fd1498Szrj 	 omp_get_max_threads());
246*38fd1498Szrj 
247*38fd1498Szrj       return __target_end;
248*38fd1498Szrj     }
249*38fd1498Szrj }       //namespace __gnu_parallel
250*38fd1498Szrj 
251*38fd1498Szrj #endif /* _GLIBCXX_PARALLEL_MERGE_H */
252