xref: /dflybsd-src/contrib/gcc-8.0/libstdc++-v3/include/parallel/multiseq_selection.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/multiseq_selection.h
26*38fd1498Szrj  *  @brief Functions to find elements of a certain global __rank in
27*38fd1498Szrj  *  multiple sorted sequences.  Also serves for splitting such
28*38fd1498Szrj  *  sequence sets.
29*38fd1498Szrj  *
30*38fd1498Szrj  *  The algorithm description can be found in
31*38fd1498Szrj  *
32*38fd1498Szrj  *  P. J. Varman, S. D. Scheufler, B. R. Iyer, and G. R. Ricard.
33*38fd1498Szrj  *  Merging Multiple Lists on Hierarchical-Memory Multiprocessors.
34*38fd1498Szrj  *  Journal of Parallel and Distributed Computing, 12(2):171–177, 1991.
35*38fd1498Szrj  *
36*38fd1498Szrj  *  This file is a GNU parallel extension to the Standard C++ Library.
37*38fd1498Szrj  */
38*38fd1498Szrj 
39*38fd1498Szrj // Written by Johannes Singler.
40*38fd1498Szrj 
41*38fd1498Szrj #ifndef _GLIBCXX_PARALLEL_MULTISEQ_SELECTION_H
42*38fd1498Szrj #define _GLIBCXX_PARALLEL_MULTISEQ_SELECTION_H 1
43*38fd1498Szrj 
44*38fd1498Szrj #include <vector>
45*38fd1498Szrj #include <queue>
46*38fd1498Szrj 
47*38fd1498Szrj #include <bits/stl_algo.h>
48*38fd1498Szrj 
49*38fd1498Szrj namespace __gnu_parallel
50*38fd1498Szrj {
51*38fd1498Szrj   /** @brief Compare __a pair of types lexicographically, ascending. */
52*38fd1498Szrj   template<typename _T1, typename _T2, typename _Compare>
53*38fd1498Szrj     class _Lexicographic
54*38fd1498Szrj     : public std::binary_function<std::pair<_T1, _T2>,
55*38fd1498Szrj 				  std::pair<_T1, _T2>, bool>
56*38fd1498Szrj     {
57*38fd1498Szrj     private:
58*38fd1498Szrj       _Compare& _M_comp;
59*38fd1498Szrj 
60*38fd1498Szrj     public:
_Lexicographic(_Compare & __comp)61*38fd1498Szrj       _Lexicographic(_Compare& __comp) : _M_comp(__comp) { }
62*38fd1498Szrj 
63*38fd1498Szrj       bool
operator()64*38fd1498Szrj       operator()(const std::pair<_T1, _T2>& __p1,
65*38fd1498Szrj                  const std::pair<_T1, _T2>& __p2) const
66*38fd1498Szrj       {
67*38fd1498Szrj         if (_M_comp(__p1.first, __p2.first))
68*38fd1498Szrj           return true;
69*38fd1498Szrj 
70*38fd1498Szrj         if (_M_comp(__p2.first, __p1.first))
71*38fd1498Szrj           return false;
72*38fd1498Szrj 
73*38fd1498Szrj         // Firsts are equal.
74*38fd1498Szrj         return __p1.second < __p2.second;
75*38fd1498Szrj       }
76*38fd1498Szrj     };
77*38fd1498Szrj 
78*38fd1498Szrj   /** @brief Compare __a pair of types lexicographically, descending. */
79*38fd1498Szrj   template<typename _T1, typename _T2, typename _Compare>
80*38fd1498Szrj     class _LexicographicReverse : public std::binary_function<_T1, _T2, bool>
81*38fd1498Szrj     {
82*38fd1498Szrj     private:
83*38fd1498Szrj       _Compare& _M_comp;
84*38fd1498Szrj 
85*38fd1498Szrj     public:
_LexicographicReverse(_Compare & __comp)86*38fd1498Szrj       _LexicographicReverse(_Compare& __comp) : _M_comp(__comp) { }
87*38fd1498Szrj 
88*38fd1498Szrj       bool
operator()89*38fd1498Szrj       operator()(const std::pair<_T1, _T2>& __p1,
90*38fd1498Szrj                  const std::pair<_T1, _T2>& __p2) const
91*38fd1498Szrj       {
92*38fd1498Szrj         if (_M_comp(__p2.first, __p1.first))
93*38fd1498Szrj           return true;
94*38fd1498Szrj 
95*38fd1498Szrj         if (_M_comp(__p1.first, __p2.first))
96*38fd1498Szrj           return false;
97*38fd1498Szrj 
98*38fd1498Szrj         // Firsts are equal.
99*38fd1498Szrj         return __p2.second < __p1.second;
100*38fd1498Szrj       }
101*38fd1498Szrj     };
102*38fd1498Szrj 
103*38fd1498Szrj   /**
104*38fd1498Szrj    *  @brief Splits several sorted sequences at a certain global __rank,
105*38fd1498Szrj    *  resulting in a splitting point for each sequence.
106*38fd1498Szrj    *  The sequences are passed via a sequence of random-access
107*38fd1498Szrj    *  iterator pairs, none of the sequences may be empty.  If there
108*38fd1498Szrj    *  are several equal elements across the split, the ones on the
109*38fd1498Szrj    *  __left side will be chosen from sequences with smaller number.
110*38fd1498Szrj    *  @param __begin_seqs Begin of the sequence of iterator pairs.
111*38fd1498Szrj    *  @param __end_seqs End of the sequence of iterator pairs.
112*38fd1498Szrj    *  @param __rank The global rank to partition at.
113*38fd1498Szrj    *  @param __begin_offsets A random-access __sequence __begin where the
114*38fd1498Szrj    *  __result will be stored in. Each element of the sequence is an
115*38fd1498Szrj    *  iterator that points to the first element on the greater part of
116*38fd1498Szrj    *  the respective __sequence.
117*38fd1498Szrj    *  @param __comp The ordering functor, defaults to std::less<_Tp>.
118*38fd1498Szrj    */
119*38fd1498Szrj   template<typename _RanSeqs, typename _RankType, typename _RankIterator,
120*38fd1498Szrj             typename _Compare>
121*38fd1498Szrj     void
122*38fd1498Szrj     multiseq_partition(_RanSeqs __begin_seqs, _RanSeqs __end_seqs,
123*38fd1498Szrj                        _RankType __rank,
124*38fd1498Szrj                        _RankIterator __begin_offsets,
125*38fd1498Szrj                        _Compare __comp = std::less<
126*38fd1498Szrj                        typename std::iterator_traits<typename
127*38fd1498Szrj                        std::iterator_traits<_RanSeqs>::value_type::
128*38fd1498Szrj                        first_type>::value_type>()) // std::less<_Tp>
129*38fd1498Szrj     {
130*38fd1498Szrj       _GLIBCXX_CALL(__end_seqs - __begin_seqs)
131*38fd1498Szrj 
132*38fd1498Szrj       typedef typename std::iterator_traits<_RanSeqs>::value_type::first_type
133*38fd1498Szrj         _It;
134*38fd1498Szrj       typedef typename std::iterator_traits<_RanSeqs>::difference_type
135*38fd1498Szrj         _SeqNumber;
136*38fd1498Szrj       typedef typename std::iterator_traits<_It>::difference_type
137*38fd1498Szrj                _DifferenceType;
138*38fd1498Szrj       typedef typename std::iterator_traits<_It>::value_type _ValueType;
139*38fd1498Szrj 
140*38fd1498Szrj       _Lexicographic<_ValueType, _SeqNumber, _Compare> __lcomp(__comp);
141*38fd1498Szrj       _LexicographicReverse<_ValueType, _SeqNumber, _Compare> __lrcomp(__comp);
142*38fd1498Szrj 
143*38fd1498Szrj       // Number of sequences, number of elements in total (possibly
144*38fd1498Szrj       // including padding).
145*38fd1498Szrj       _DifferenceType __m = std::distance(__begin_seqs, __end_seqs), __nn = 0,
146*38fd1498Szrj                       __nmax, __n, __r;
147*38fd1498Szrj 
148*38fd1498Szrj       for (_SeqNumber __i = 0; __i < __m; __i++)
149*38fd1498Szrj         {
150*38fd1498Szrj           __nn += std::distance(__begin_seqs[__i].first,
151*38fd1498Szrj                                __begin_seqs[__i].second);
152*38fd1498Szrj           _GLIBCXX_PARALLEL_ASSERT(
153*38fd1498Szrj             std::distance(__begin_seqs[__i].first,
154*38fd1498Szrj                           __begin_seqs[__i].second) > 0);
155*38fd1498Szrj         }
156*38fd1498Szrj 
157*38fd1498Szrj       if (__rank == __nn)
158*38fd1498Szrj         {
159*38fd1498Szrj           for (_SeqNumber __i = 0; __i < __m; __i++)
160*38fd1498Szrj             __begin_offsets[__i] = __begin_seqs[__i].second; // Very end.
161*38fd1498Szrj           // Return __m - 1;
162*38fd1498Szrj           return;
163*38fd1498Szrj         }
164*38fd1498Szrj 
165*38fd1498Szrj       _GLIBCXX_PARALLEL_ASSERT(__m != 0);
166*38fd1498Szrj       _GLIBCXX_PARALLEL_ASSERT(__nn != 0);
167*38fd1498Szrj       _GLIBCXX_PARALLEL_ASSERT(__rank >= 0);
168*38fd1498Szrj       _GLIBCXX_PARALLEL_ASSERT(__rank < __nn);
169*38fd1498Szrj 
170*38fd1498Szrj       _DifferenceType* __ns = new _DifferenceType[__m];
171*38fd1498Szrj       _DifferenceType* __a = new _DifferenceType[__m];
172*38fd1498Szrj       _DifferenceType* __b = new _DifferenceType[__m];
173*38fd1498Szrj       _DifferenceType __l;
174*38fd1498Szrj 
175*38fd1498Szrj       __ns[0] = std::distance(__begin_seqs[0].first, __begin_seqs[0].second);
176*38fd1498Szrj       __nmax = __ns[0];
177*38fd1498Szrj       for (_SeqNumber __i = 0; __i < __m; __i++)
178*38fd1498Szrj         {
179*38fd1498Szrj           __ns[__i] = std::distance(__begin_seqs[__i].first,
180*38fd1498Szrj                                     __begin_seqs[__i].second);
181*38fd1498Szrj           __nmax = std::max(__nmax, __ns[__i]);
182*38fd1498Szrj         }
183*38fd1498Szrj 
184*38fd1498Szrj       __r = __rd_log2(__nmax) + 1;
185*38fd1498Szrj 
186*38fd1498Szrj       // Pad all lists to this length, at least as long as any ns[__i],
187*38fd1498Szrj       // equality iff __nmax = 2^__k - 1.
188*38fd1498Szrj       __l = (1ULL << __r) - 1;
189*38fd1498Szrj 
190*38fd1498Szrj       for (_SeqNumber __i = 0; __i < __m; __i++)
191*38fd1498Szrj         {
192*38fd1498Szrj           __a[__i] = 0;
193*38fd1498Szrj           __b[__i] = __l;
194*38fd1498Szrj         }
195*38fd1498Szrj       __n = __l / 2;
196*38fd1498Szrj 
197*38fd1498Szrj       // Invariants:
198*38fd1498Szrj       // 0 <= __a[__i] <= __ns[__i], 0 <= __b[__i] <= __l
199*38fd1498Szrj 
200*38fd1498Szrj #define __S(__i) (__begin_seqs[__i].first)
201*38fd1498Szrj 
202*38fd1498Szrj       // Initial partition.
203*38fd1498Szrj       std::vector<std::pair<_ValueType, _SeqNumber> > __sample;
204*38fd1498Szrj 
205*38fd1498Szrj       for (_SeqNumber __i = 0; __i < __m; __i++)
206*38fd1498Szrj         if (__n < __ns[__i])    //__sequence long enough
207*38fd1498Szrj           __sample.push_back(std::make_pair(__S(__i)[__n], __i));
208*38fd1498Szrj       __gnu_sequential::sort(__sample.begin(), __sample.end(), __lcomp);
209*38fd1498Szrj 
210*38fd1498Szrj       for (_SeqNumber __i = 0; __i < __m; __i++)       //conceptual infinity
211*38fd1498Szrj         if (__n >= __ns[__i])   //__sequence too short, conceptual infinity
212*38fd1498Szrj           __sample.push_back(
213*38fd1498Szrj             std::make_pair(__S(__i)[0] /*__dummy element*/, __i));
214*38fd1498Szrj 
215*38fd1498Szrj       _DifferenceType __localrank = __rank / __l;
216*38fd1498Szrj 
217*38fd1498Szrj       _SeqNumber __j;
218*38fd1498Szrj       for (__j = 0;
219*38fd1498Szrj            __j < __localrank && ((__n + 1) <= __ns[__sample[__j].second]);
220*38fd1498Szrj            ++__j)
221*38fd1498Szrj         __a[__sample[__j].second] += __n + 1;
222*38fd1498Szrj       for (; __j < __m; __j++)
223*38fd1498Szrj         __b[__sample[__j].second] -= __n + 1;
224*38fd1498Szrj 
225*38fd1498Szrj       // Further refinement.
226*38fd1498Szrj       while (__n > 0)
227*38fd1498Szrj         {
228*38fd1498Szrj           __n /= 2;
229*38fd1498Szrj 
230*38fd1498Szrj           _SeqNumber __lmax_seq = -1;  // to avoid warning
231*38fd1498Szrj           const _ValueType* __lmax = 0; // impossible to avoid the warning?
232*38fd1498Szrj           for (_SeqNumber __i = 0; __i < __m; __i++)
233*38fd1498Szrj             {
234*38fd1498Szrj               if (__a[__i] > 0)
235*38fd1498Szrj                 {
236*38fd1498Szrj                   if (!__lmax)
237*38fd1498Szrj                     {
238*38fd1498Szrj                       __lmax = &(__S(__i)[__a[__i] - 1]);
239*38fd1498Szrj                       __lmax_seq = __i;
240*38fd1498Szrj                     }
241*38fd1498Szrj                   else
242*38fd1498Szrj                     {
243*38fd1498Szrj                       // Max, favor rear sequences.
244*38fd1498Szrj                       if (!__comp(__S(__i)[__a[__i] - 1], *__lmax))
245*38fd1498Szrj                         {
246*38fd1498Szrj                           __lmax = &(__S(__i)[__a[__i] - 1]);
247*38fd1498Szrj                           __lmax_seq = __i;
248*38fd1498Szrj                         }
249*38fd1498Szrj                     }
250*38fd1498Szrj                 }
251*38fd1498Szrj             }
252*38fd1498Szrj 
253*38fd1498Szrj           _SeqNumber __i;
254*38fd1498Szrj           for (__i = 0; __i < __m; __i++)
255*38fd1498Szrj             {
256*38fd1498Szrj               _DifferenceType __middle = (__b[__i] + __a[__i]) / 2;
257*38fd1498Szrj               if (__lmax && __middle < __ns[__i] &&
258*38fd1498Szrj                   __lcomp(std::make_pair(__S(__i)[__middle], __i),
259*38fd1498Szrj                         std::make_pair(*__lmax, __lmax_seq)))
260*38fd1498Szrj                 __a[__i] = std::min(__a[__i] + __n + 1, __ns[__i]);
261*38fd1498Szrj               else
262*38fd1498Szrj                 __b[__i] -= __n + 1;
263*38fd1498Szrj             }
264*38fd1498Szrj 
265*38fd1498Szrj           _DifferenceType __leftsize = 0;
266*38fd1498Szrj           for (_SeqNumber __i = 0; __i < __m; __i++)
267*38fd1498Szrj               __leftsize += __a[__i] / (__n + 1);
268*38fd1498Szrj 
269*38fd1498Szrj           _DifferenceType __skew = __rank / (__n + 1) - __leftsize;
270*38fd1498Szrj 
271*38fd1498Szrj           if (__skew > 0)
272*38fd1498Szrj             {
273*38fd1498Szrj               // Move to the left, find smallest.
274*38fd1498Szrj               std::priority_queue<std::pair<_ValueType, _SeqNumber>,
275*38fd1498Szrj                 std::vector<std::pair<_ValueType, _SeqNumber> >,
276*38fd1498Szrj                 _LexicographicReverse<_ValueType, _SeqNumber, _Compare> >
277*38fd1498Szrj                 __pq(__lrcomp);
278*38fd1498Szrj 
279*38fd1498Szrj               for (_SeqNumber __i = 0; __i < __m; __i++)
280*38fd1498Szrj                 if (__b[__i] < __ns[__i])
281*38fd1498Szrj                   __pq.push(std::make_pair(__S(__i)[__b[__i]], __i));
282*38fd1498Szrj 
283*38fd1498Szrj               for (; __skew != 0 && !__pq.empty(); --__skew)
284*38fd1498Szrj                 {
285*38fd1498Szrj                   _SeqNumber __source = __pq.top().second;
286*38fd1498Szrj                   __pq.pop();
287*38fd1498Szrj 
288*38fd1498Szrj                   __a[__source]
289*38fd1498Szrj                       = std::min(__a[__source] + __n + 1, __ns[__source]);
290*38fd1498Szrj                   __b[__source] += __n + 1;
291*38fd1498Szrj 
292*38fd1498Szrj                   if (__b[__source] < __ns[__source])
293*38fd1498Szrj                     __pq.push(
294*38fd1498Szrj                       std::make_pair(__S(__source)[__b[__source]], __source));
295*38fd1498Szrj                 }
296*38fd1498Szrj             }
297*38fd1498Szrj           else if (__skew < 0)
298*38fd1498Szrj             {
299*38fd1498Szrj               // Move to the right, find greatest.
300*38fd1498Szrj               std::priority_queue<std::pair<_ValueType, _SeqNumber>,
301*38fd1498Szrj                 std::vector<std::pair<_ValueType, _SeqNumber> >,
302*38fd1498Szrj                 _Lexicographic<_ValueType, _SeqNumber, _Compare> >
303*38fd1498Szrj                   __pq(__lcomp);
304*38fd1498Szrj 
305*38fd1498Szrj               for (_SeqNumber __i = 0; __i < __m; __i++)
306*38fd1498Szrj                 if (__a[__i] > 0)
307*38fd1498Szrj                   __pq.push(std::make_pair(__S(__i)[__a[__i] - 1], __i));
308*38fd1498Szrj 
309*38fd1498Szrj               for (; __skew != 0; ++__skew)
310*38fd1498Szrj                 {
311*38fd1498Szrj                   _SeqNumber __source = __pq.top().second;
312*38fd1498Szrj                   __pq.pop();
313*38fd1498Szrj 
314*38fd1498Szrj                   __a[__source] -= __n + 1;
315*38fd1498Szrj                   __b[__source] -= __n + 1;
316*38fd1498Szrj 
317*38fd1498Szrj                   if (__a[__source] > 0)
318*38fd1498Szrj                     __pq.push(std::make_pair(
319*38fd1498Szrj                         __S(__source)[__a[__source] - 1], __source));
320*38fd1498Szrj                 }
321*38fd1498Szrj             }
322*38fd1498Szrj         }
323*38fd1498Szrj 
324*38fd1498Szrj       // Postconditions:
325*38fd1498Szrj       // __a[__i] == __b[__i] in most cases, except when __a[__i] has been
326*38fd1498Szrj       // clamped because of having reached the boundary
327*38fd1498Szrj 
328*38fd1498Szrj       // Now return the result, calculate the offset.
329*38fd1498Szrj 
330*38fd1498Szrj       // Compare the keys on both edges of the border.
331*38fd1498Szrj 
332*38fd1498Szrj       // Maximum of left edge, minimum of right edge.
333*38fd1498Szrj       _ValueType* __maxleft = 0;
334*38fd1498Szrj       _ValueType* __minright = 0;
335*38fd1498Szrj       for (_SeqNumber __i = 0; __i < __m; __i++)
336*38fd1498Szrj         {
337*38fd1498Szrj           if (__a[__i] > 0)
338*38fd1498Szrj             {
339*38fd1498Szrj               if (!__maxleft)
340*38fd1498Szrj                 __maxleft = &(__S(__i)[__a[__i] - 1]);
341*38fd1498Szrj               else
342*38fd1498Szrj                 {
343*38fd1498Szrj                   // Max, favor rear sequences.
344*38fd1498Szrj                   if (!__comp(__S(__i)[__a[__i] - 1], *__maxleft))
345*38fd1498Szrj                     __maxleft = &(__S(__i)[__a[__i] - 1]);
346*38fd1498Szrj                 }
347*38fd1498Szrj             }
348*38fd1498Szrj           if (__b[__i] < __ns[__i])
349*38fd1498Szrj             {
350*38fd1498Szrj               if (!__minright)
351*38fd1498Szrj                 __minright = &(__S(__i)[__b[__i]]);
352*38fd1498Szrj               else
353*38fd1498Szrj                 {
354*38fd1498Szrj                   // Min, favor fore sequences.
355*38fd1498Szrj                   if (__comp(__S(__i)[__b[__i]], *__minright))
356*38fd1498Szrj                     __minright = &(__S(__i)[__b[__i]]);
357*38fd1498Szrj                 }
358*38fd1498Szrj             }
359*38fd1498Szrj         }
360*38fd1498Szrj 
361*38fd1498Szrj       _SeqNumber __seq = 0;
362*38fd1498Szrj       for (_SeqNumber __i = 0; __i < __m; __i++)
363*38fd1498Szrj         __begin_offsets[__i] = __S(__i) + __a[__i];
364*38fd1498Szrj 
365*38fd1498Szrj       delete[] __ns;
366*38fd1498Szrj       delete[] __a;
367*38fd1498Szrj       delete[] __b;
368*38fd1498Szrj     }
369*38fd1498Szrj 
370*38fd1498Szrj 
371*38fd1498Szrj   /**
372*38fd1498Szrj    *  @brief Selects the element at a certain global __rank from several
373*38fd1498Szrj    *  sorted sequences.
374*38fd1498Szrj    *
375*38fd1498Szrj    *  The sequences are passed via a sequence of random-access
376*38fd1498Szrj    *  iterator pairs, none of the sequences may be empty.
377*38fd1498Szrj    *  @param __begin_seqs Begin of the sequence of iterator pairs.
378*38fd1498Szrj    *  @param __end_seqs End of the sequence of iterator pairs.
379*38fd1498Szrj    *  @param __rank The global rank to partition at.
380*38fd1498Szrj    *  @param __offset The rank of the selected element in the global
381*38fd1498Szrj    *  subsequence of elements equal to the selected element. If the
382*38fd1498Szrj    *  selected element is unique, this number is 0.
383*38fd1498Szrj    *  @param __comp The ordering functor, defaults to std::less.
384*38fd1498Szrj    */
385*38fd1498Szrj   template<typename _Tp, typename _RanSeqs, typename _RankType,
386*38fd1498Szrj            typename _Compare>
387*38fd1498Szrj     _Tp
388*38fd1498Szrj     multiseq_selection(_RanSeqs __begin_seqs, _RanSeqs __end_seqs,
389*38fd1498Szrj                        _RankType __rank,
390*38fd1498Szrj                        _RankType& __offset, _Compare __comp = std::less<_Tp>())
391*38fd1498Szrj     {
392*38fd1498Szrj       _GLIBCXX_CALL(__end_seqs - __begin_seqs)
393*38fd1498Szrj 
394*38fd1498Szrj       typedef typename std::iterator_traits<_RanSeqs>::value_type::first_type
395*38fd1498Szrj         _It;
396*38fd1498Szrj       typedef typename std::iterator_traits<_RanSeqs>::difference_type
397*38fd1498Szrj         _SeqNumber;
398*38fd1498Szrj       typedef typename std::iterator_traits<_It>::difference_type
399*38fd1498Szrj         _DifferenceType;
400*38fd1498Szrj 
401*38fd1498Szrj       _Lexicographic<_Tp, _SeqNumber, _Compare> __lcomp(__comp);
402*38fd1498Szrj       _LexicographicReverse<_Tp, _SeqNumber, _Compare> __lrcomp(__comp);
403*38fd1498Szrj 
404*38fd1498Szrj       // Number of sequences, number of elements in total (possibly
405*38fd1498Szrj       // including padding).
406*38fd1498Szrj       _DifferenceType __m = std::distance(__begin_seqs, __end_seqs);
407*38fd1498Szrj       _DifferenceType __nn = 0;
408*38fd1498Szrj       _DifferenceType __nmax, __n, __r;
409*38fd1498Szrj 
410*38fd1498Szrj       for (_SeqNumber __i = 0; __i < __m; __i++)
411*38fd1498Szrj         __nn += std::distance(__begin_seqs[__i].first,
412*38fd1498Szrj 			      __begin_seqs[__i].second);
413*38fd1498Szrj 
414*38fd1498Szrj       if (__m == 0 || __nn == 0 || __rank < 0 || __rank >= __nn)
415*38fd1498Szrj         {
416*38fd1498Szrj           // result undefined if there is no data or __rank is outside bounds
417*38fd1498Szrj           throw std::exception();
418*38fd1498Szrj         }
419*38fd1498Szrj 
420*38fd1498Szrj 
421*38fd1498Szrj       _DifferenceType* __ns = new _DifferenceType[__m];
422*38fd1498Szrj       _DifferenceType* __a = new _DifferenceType[__m];
423*38fd1498Szrj       _DifferenceType* __b = new _DifferenceType[__m];
424*38fd1498Szrj       _DifferenceType __l;
425*38fd1498Szrj 
426*38fd1498Szrj       __ns[0] = std::distance(__begin_seqs[0].first, __begin_seqs[0].second);
427*38fd1498Szrj       __nmax = __ns[0];
428*38fd1498Szrj       for (_SeqNumber __i = 0; __i < __m; ++__i)
429*38fd1498Szrj         {
430*38fd1498Szrj           __ns[__i] = std::distance(__begin_seqs[__i].first,
431*38fd1498Szrj                                     __begin_seqs[__i].second);
432*38fd1498Szrj           __nmax = std::max(__nmax, __ns[__i]);
433*38fd1498Szrj         }
434*38fd1498Szrj 
435*38fd1498Szrj       __r = __rd_log2(__nmax) + 1;
436*38fd1498Szrj 
437*38fd1498Szrj       // Pad all lists to this length, at least as long as any ns[__i],
438*38fd1498Szrj       // equality iff __nmax = 2^__k - 1
439*38fd1498Szrj       __l = __round_up_to_pow2(__r) - 1;
440*38fd1498Szrj 
441*38fd1498Szrj       for (_SeqNumber __i = 0; __i < __m; ++__i)
442*38fd1498Szrj         {
443*38fd1498Szrj           __a[__i] = 0;
444*38fd1498Szrj           __b[__i] = __l;
445*38fd1498Szrj         }
446*38fd1498Szrj       __n = __l / 2;
447*38fd1498Szrj 
448*38fd1498Szrj       // Invariants:
449*38fd1498Szrj       // 0 <= __a[__i] <= __ns[__i], 0 <= __b[__i] <= __l
450*38fd1498Szrj 
451*38fd1498Szrj #define __S(__i) (__begin_seqs[__i].first)
452*38fd1498Szrj 
453*38fd1498Szrj       // Initial partition.
454*38fd1498Szrj       std::vector<std::pair<_Tp, _SeqNumber> > __sample;
455*38fd1498Szrj 
456*38fd1498Szrj       for (_SeqNumber __i = 0; __i < __m; __i++)
457*38fd1498Szrj         if (__n < __ns[__i])
458*38fd1498Szrj           __sample.push_back(std::make_pair(__S(__i)[__n], __i));
459*38fd1498Szrj       __gnu_sequential::sort(__sample.begin(), __sample.end(),
460*38fd1498Szrj                              __lcomp, sequential_tag());
461*38fd1498Szrj 
462*38fd1498Szrj       // Conceptual infinity.
463*38fd1498Szrj       for (_SeqNumber __i = 0; __i < __m; __i++)
464*38fd1498Szrj         if (__n >= __ns[__i])
465*38fd1498Szrj           __sample.push_back(
466*38fd1498Szrj             std::make_pair(__S(__i)[0] /*__dummy element*/, __i));
467*38fd1498Szrj 
468*38fd1498Szrj       _DifferenceType __localrank = __rank / __l;
469*38fd1498Szrj 
470*38fd1498Szrj       _SeqNumber __j;
471*38fd1498Szrj       for (__j = 0;
472*38fd1498Szrj            __j < __localrank && ((__n + 1) <= __ns[__sample[__j].second]);
473*38fd1498Szrj            ++__j)
474*38fd1498Szrj         __a[__sample[__j].second] += __n + 1;
475*38fd1498Szrj       for (; __j < __m; ++__j)
476*38fd1498Szrj         __b[__sample[__j].second] -= __n + 1;
477*38fd1498Szrj 
478*38fd1498Szrj       // Further refinement.
479*38fd1498Szrj       while (__n > 0)
480*38fd1498Szrj         {
481*38fd1498Szrj           __n /= 2;
482*38fd1498Szrj 
483*38fd1498Szrj           const _Tp* __lmax = 0;
484*38fd1498Szrj           for (_SeqNumber __i = 0; __i < __m; ++__i)
485*38fd1498Szrj             {
486*38fd1498Szrj               if (__a[__i] > 0)
487*38fd1498Szrj                 {
488*38fd1498Szrj                   if (!__lmax)
489*38fd1498Szrj                     __lmax = &(__S(__i)[__a[__i] - 1]);
490*38fd1498Szrj                   else
491*38fd1498Szrj                     {
492*38fd1498Szrj                       if (__comp(*__lmax, __S(__i)[__a[__i] - 1]))      //max
493*38fd1498Szrj                         __lmax = &(__S(__i)[__a[__i] - 1]);
494*38fd1498Szrj                     }
495*38fd1498Szrj                 }
496*38fd1498Szrj             }
497*38fd1498Szrj 
498*38fd1498Szrj           _SeqNumber __i;
499*38fd1498Szrj           for (__i = 0; __i < __m; __i++)
500*38fd1498Szrj             {
501*38fd1498Szrj               _DifferenceType __middle = (__b[__i] + __a[__i]) / 2;
502*38fd1498Szrj               if (__lmax && __middle < __ns[__i]
503*38fd1498Szrj                   && __comp(__S(__i)[__middle], *__lmax))
504*38fd1498Szrj                 __a[__i] = std::min(__a[__i] + __n + 1, __ns[__i]);
505*38fd1498Szrj               else
506*38fd1498Szrj                 __b[__i] -= __n + 1;
507*38fd1498Szrj             }
508*38fd1498Szrj 
509*38fd1498Szrj           _DifferenceType __leftsize = 0;
510*38fd1498Szrj           for (_SeqNumber __i = 0; __i < __m; ++__i)
511*38fd1498Szrj               __leftsize += __a[__i] / (__n + 1);
512*38fd1498Szrj 
513*38fd1498Szrj           _DifferenceType __skew = __rank / (__n + 1) - __leftsize;
514*38fd1498Szrj 
515*38fd1498Szrj           if (__skew > 0)
516*38fd1498Szrj             {
517*38fd1498Szrj               // Move to the left, find smallest.
518*38fd1498Szrj               std::priority_queue<std::pair<_Tp, _SeqNumber>,
519*38fd1498Szrj                 std::vector<std::pair<_Tp, _SeqNumber> >,
520*38fd1498Szrj                 _LexicographicReverse<_Tp, _SeqNumber, _Compare> >
521*38fd1498Szrj                   __pq(__lrcomp);
522*38fd1498Szrj 
523*38fd1498Szrj               for (_SeqNumber __i = 0; __i < __m; ++__i)
524*38fd1498Szrj                 if (__b[__i] < __ns[__i])
525*38fd1498Szrj                   __pq.push(std::make_pair(__S(__i)[__b[__i]], __i));
526*38fd1498Szrj 
527*38fd1498Szrj               for (; __skew != 0 && !__pq.empty(); --__skew)
528*38fd1498Szrj                 {
529*38fd1498Szrj                   _SeqNumber __source = __pq.top().second;
530*38fd1498Szrj                   __pq.pop();
531*38fd1498Szrj 
532*38fd1498Szrj                   __a[__source]
533*38fd1498Szrj                       = std::min(__a[__source] + __n + 1, __ns[__source]);
534*38fd1498Szrj                   __b[__source] += __n + 1;
535*38fd1498Szrj 
536*38fd1498Szrj                   if (__b[__source] < __ns[__source])
537*38fd1498Szrj                     __pq.push(
538*38fd1498Szrj                       std::make_pair(__S(__source)[__b[__source]], __source));
539*38fd1498Szrj                 }
540*38fd1498Szrj             }
541*38fd1498Szrj           else if (__skew < 0)
542*38fd1498Szrj             {
543*38fd1498Szrj               // Move to the right, find greatest.
544*38fd1498Szrj               std::priority_queue<std::pair<_Tp, _SeqNumber>,
545*38fd1498Szrj                 std::vector<std::pair<_Tp, _SeqNumber> >,
546*38fd1498Szrj                 _Lexicographic<_Tp, _SeqNumber, _Compare> > __pq(__lcomp);
547*38fd1498Szrj 
548*38fd1498Szrj               for (_SeqNumber __i = 0; __i < __m; ++__i)
549*38fd1498Szrj                 if (__a[__i] > 0)
550*38fd1498Szrj                   __pq.push(std::make_pair(__S(__i)[__a[__i] - 1], __i));
551*38fd1498Szrj 
552*38fd1498Szrj               for (; __skew != 0; ++__skew)
553*38fd1498Szrj                 {
554*38fd1498Szrj                   _SeqNumber __source = __pq.top().second;
555*38fd1498Szrj                   __pq.pop();
556*38fd1498Szrj 
557*38fd1498Szrj                   __a[__source] -= __n + 1;
558*38fd1498Szrj                   __b[__source] -= __n + 1;
559*38fd1498Szrj 
560*38fd1498Szrj                   if (__a[__source] > 0)
561*38fd1498Szrj                     __pq.push(std::make_pair(
562*38fd1498Szrj                         __S(__source)[__a[__source] - 1], __source));
563*38fd1498Szrj                 }
564*38fd1498Szrj             }
565*38fd1498Szrj         }
566*38fd1498Szrj 
567*38fd1498Szrj       // Postconditions:
568*38fd1498Szrj       // __a[__i] == __b[__i] in most cases, except when __a[__i] has been
569*38fd1498Szrj       // clamped because of having reached the boundary
570*38fd1498Szrj 
571*38fd1498Szrj       // Now return the result, calculate the offset.
572*38fd1498Szrj 
573*38fd1498Szrj       // Compare the keys on both edges of the border.
574*38fd1498Szrj 
575*38fd1498Szrj       // Maximum of left edge, minimum of right edge.
576*38fd1498Szrj       bool __maxleftset = false, __minrightset = false;
577*38fd1498Szrj 
578*38fd1498Szrj       // Impossible to avoid the warning?
579*38fd1498Szrj       _Tp __maxleft, __minright;
580*38fd1498Szrj       for (_SeqNumber __i = 0; __i < __m; ++__i)
581*38fd1498Szrj         {
582*38fd1498Szrj           if (__a[__i] > 0)
583*38fd1498Szrj             {
584*38fd1498Szrj               if (!__maxleftset)
585*38fd1498Szrj                 {
586*38fd1498Szrj                   __maxleft = __S(__i)[__a[__i] - 1];
587*38fd1498Szrj                   __maxleftset = true;
588*38fd1498Szrj                 }
589*38fd1498Szrj               else
590*38fd1498Szrj                 {
591*38fd1498Szrj                   // Max.
592*38fd1498Szrj                   if (__comp(__maxleft, __S(__i)[__a[__i] - 1]))
593*38fd1498Szrj                     __maxleft = __S(__i)[__a[__i] - 1];
594*38fd1498Szrj                 }
595*38fd1498Szrj             }
596*38fd1498Szrj           if (__b[__i] < __ns[__i])
597*38fd1498Szrj             {
598*38fd1498Szrj               if (!__minrightset)
599*38fd1498Szrj                 {
600*38fd1498Szrj                   __minright = __S(__i)[__b[__i]];
601*38fd1498Szrj                   __minrightset = true;
602*38fd1498Szrj                 }
603*38fd1498Szrj               else
604*38fd1498Szrj                 {
605*38fd1498Szrj                   // Min.
606*38fd1498Szrj                   if (__comp(__S(__i)[__b[__i]], __minright))
607*38fd1498Szrj                     __minright = __S(__i)[__b[__i]];
608*38fd1498Szrj                 }
609*38fd1498Szrj             }
610*38fd1498Szrj       }
611*38fd1498Szrj 
612*38fd1498Szrj       // Minright is the __splitter, in any case.
613*38fd1498Szrj 
614*38fd1498Szrj       if (!__maxleftset || __comp(__minright, __maxleft))
615*38fd1498Szrj         {
616*38fd1498Szrj           // Good luck, everything is split unambiguously.
617*38fd1498Szrj           __offset = 0;
618*38fd1498Szrj         }
619*38fd1498Szrj       else
620*38fd1498Szrj         {
621*38fd1498Szrj           // We have to calculate an offset.
622*38fd1498Szrj           __offset = 0;
623*38fd1498Szrj 
624*38fd1498Szrj           for (_SeqNumber __i = 0; __i < __m; ++__i)
625*38fd1498Szrj             {
626*38fd1498Szrj               _DifferenceType lb
627*38fd1498Szrj                 = std::lower_bound(__S(__i), __S(__i) + __ns[__i],
628*38fd1498Szrj                                    __minright,
629*38fd1498Szrj                                    __comp) - __S(__i);
630*38fd1498Szrj               __offset += __a[__i] - lb;
631*38fd1498Szrj             }
632*38fd1498Szrj         }
633*38fd1498Szrj 
634*38fd1498Szrj       delete[] __ns;
635*38fd1498Szrj       delete[] __a;
636*38fd1498Szrj       delete[] __b;
637*38fd1498Szrj 
638*38fd1498Szrj       return __minright;
639*38fd1498Szrj     }
640*38fd1498Szrj }
641*38fd1498Szrj 
642*38fd1498Szrj #undef __S
643*38fd1498Szrj 
644*38fd1498Szrj #endif /* _GLIBCXX_PARALLEL_MULTISEQ_SELECTION_H */
645