libstdc++
multiseq_selection.h
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 // Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
00004 //
00005 // This file is part of the GNU ISO C++ Library.  This library is free
00006 // software; you can redistribute it and/or modify it under the terms
00007 // of the GNU General Public License as published by the Free Software
00008 // Foundation; either version 3, or (at your option) any later
00009 // version.
00010 
00011 // This library is distributed in the hope that it will be useful, but
00012 // WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // General Public License for more details.
00015 
00016 // Under Section 7 of GPL version 3, you are granted additional
00017 // permissions described in the GCC Runtime Library Exception, version
00018 // 3.1, as published by the Free Software Foundation.
00019 
00020 // You should have received a copy of the GNU General Public License and
00021 // a copy of the GCC Runtime Library Exception along with this program;
00022 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
00023 // <http://www.gnu.org/licenses/>.
00024 
00025 /** @file parallel/multiseq_selection.h
00026  *  @brief Functions to find elements of a certain global __rank in
00027  *  multiple sorted sequences.  Also serves for splitting such
00028  *  sequence sets.
00029  *
00030  *  The algorithm description can be found in 
00031  *
00032  *  P. J. Varman, S. D. Scheufler, B. R. Iyer, and G. R. Ricard.
00033  *  Merging Multiple Lists on Hierarchical-Memory Multiprocessors.
00034  *  Journal of Parallel and Distributed Computing, 12(2):171–177, 1991.
00035  *
00036  *  This file is a GNU parallel extension to the Standard C++ Library.
00037  */
00038 
00039 // Written by Johannes Singler.
00040 
00041 #ifndef _GLIBCXX_PARALLEL_MULTISEQ_SELECTION_H
00042 #define _GLIBCXX_PARALLEL_MULTISEQ_SELECTION_H 1
00043 
00044 #include <vector>
00045 #include <queue>
00046 
00047 #include <bits/stl_algo.h>
00048 
00049 #include <parallel/sort.h>
00050 
00051 namespace __gnu_parallel
00052 {
00053   /** @brief Compare __a pair of types lexicographically, ascending. */
00054   template<typename _T1, typename _T2, typename _Compare>
00055     class _Lexicographic
00056     : public std::binary_function<std::pair<_T1, _T2>,
00057                   std::pair<_T1, _T2>, bool>
00058     {
00059     private:
00060       _Compare& _M_comp;
00061 
00062     public:
00063       _Lexicographic(_Compare& __comp) : _M_comp(__comp) { }
00064 
00065       bool
00066       operator()(const std::pair<_T1, _T2>& __p1,
00067                  const std::pair<_T1, _T2>& __p2) const
00068       {
00069         if (_M_comp(__p1.first, __p2.first))
00070           return true;
00071 
00072         if (_M_comp(__p2.first, __p1.first))
00073           return false;
00074 
00075         // Firsts are equal.
00076         return __p1.second < __p2.second;
00077       }
00078     };
00079 
00080   /** @brief Compare __a pair of types lexicographically, descending. */
00081   template<typename _T1, typename _T2, typename _Compare>
00082     class _LexicographicReverse : public std::binary_function<_T1, _T2, bool>
00083     {
00084     private:
00085       _Compare& _M_comp;
00086 
00087     public:
00088       _LexicographicReverse(_Compare& __comp) : _M_comp(__comp) { }
00089 
00090       bool
00091       operator()(const std::pair<_T1, _T2>& __p1,
00092                  const std::pair<_T1, _T2>& __p2) const
00093       {
00094         if (_M_comp(__p2.first, __p1.first))
00095           return true;
00096 
00097         if (_M_comp(__p1.first, __p2.first))
00098           return false;
00099 
00100         // Firsts are equal.
00101         return __p2.second < __p1.second;
00102       }
00103     };
00104 
00105   /** 
00106    *  @brief Splits several sorted sequences at a certain global __rank,
00107    *  resulting in a splitting point for each sequence.
00108    *  The sequences are passed via a sequence of random-access
00109    *  iterator pairs, none of the sequences may be empty.  If there
00110    *  are several equal elements across the split, the ones on the
00111    *  __left side will be chosen from sequences with smaller number.
00112    *  @param __begin_seqs Begin of the sequence of iterator pairs.
00113    *  @param __end_seqs End of the sequence of iterator pairs.
00114    *  @param __rank The global rank to partition at.
00115    *  @param __begin_offsets A random-access __sequence __begin where the
00116    *  __result will be stored in. Each element of the sequence is an
00117    *  iterator that points to the first element on the greater part of
00118    *  the respective __sequence.
00119    *  @param __comp The ordering functor, defaults to std::less<_Tp>. 
00120    */
00121   template<typename _RanSeqs, typename _RankType, typename _RankIterator,
00122             typename _Compare>
00123     void
00124     multiseq_partition(_RanSeqs __begin_seqs, _RanSeqs __end_seqs,
00125                        _RankType __rank,
00126                        _RankIterator __begin_offsets,
00127                        _Compare __comp = std::less<
00128                        typename std::iterator_traits<typename
00129                        std::iterator_traits<_RanSeqs>::value_type::
00130                        first_type>::value_type>()) // std::less<_Tp>
00131     {
00132       _GLIBCXX_CALL(__end_seqs - __begin_seqs)
00133 
00134       typedef typename std::iterator_traits<_RanSeqs>::value_type::first_type
00135         _It;
00136       typedef typename std::iterator_traits<_RanSeqs>::difference_type
00137         _SeqNumber;
00138       typedef typename std::iterator_traits<_It>::difference_type
00139                _DifferenceType;
00140       typedef typename std::iterator_traits<_It>::value_type _ValueType;
00141 
00142       _Lexicographic<_ValueType, _SeqNumber, _Compare> __lcomp(__comp);
00143       _LexicographicReverse<_ValueType, _SeqNumber, _Compare> __lrcomp(__comp);
00144 
00145       // Number of sequences, number of elements in total (possibly
00146       // including padding).
00147       _DifferenceType __m = std::distance(__begin_seqs, __end_seqs), __nn = 0,
00148                       __nmax, __n, __r;
00149 
00150       for (_SeqNumber __i = 0; __i < __m; __i++)
00151         {
00152           __nn += std::distance(__begin_seqs[__i].first,
00153                                __begin_seqs[__i].second);
00154           _GLIBCXX_PARALLEL_ASSERT(
00155             std::distance(__begin_seqs[__i].first,
00156                           __begin_seqs[__i].second) > 0);
00157         }
00158 
00159       if (__rank == __nn)
00160         {
00161           for (_SeqNumber __i = 0; __i < __m; __i++)
00162             __begin_offsets[__i] = __begin_seqs[__i].second; // Very end.
00163           // Return __m - 1;
00164           return;
00165         }
00166 
00167       _GLIBCXX_PARALLEL_ASSERT(__m != 0);
00168       _GLIBCXX_PARALLEL_ASSERT(__nn != 0);
00169       _GLIBCXX_PARALLEL_ASSERT(__rank >= 0);
00170       _GLIBCXX_PARALLEL_ASSERT(__rank < __nn);
00171 
00172       _DifferenceType* __ns = new _DifferenceType[__m];
00173       _DifferenceType* __a = new _DifferenceType[__m];
00174       _DifferenceType* __b = new _DifferenceType[__m];
00175       _DifferenceType __l;
00176 
00177       __ns[0] = std::distance(__begin_seqs[0].first, __begin_seqs[0].second);
00178       __nmax = __ns[0];
00179       for (_SeqNumber __i = 0; __i < __m; __i++)
00180         {
00181           __ns[__i] = std::distance(__begin_seqs[__i].first,
00182                                     __begin_seqs[__i].second);
00183           __nmax = std::max(__nmax, __ns[__i]);
00184         }
00185 
00186       __r = __rd_log2(__nmax) + 1;
00187 
00188       // Pad all lists to this length, at least as long as any ns[__i],
00189       // equality iff __nmax = 2^__k - 1.
00190       __l = (1ULL << __r) - 1;
00191 
00192       for (_SeqNumber __i = 0; __i < __m; __i++)
00193         {
00194           __a[__i] = 0;
00195           __b[__i] = __l;
00196         }
00197       __n = __l / 2;
00198 
00199       // Invariants:
00200       // 0 <= __a[__i] <= __ns[__i], 0 <= __b[__i] <= __l
00201 
00202 #define __S(__i) (__begin_seqs[__i].first)
00203 
00204       // Initial partition.
00205       std::vector<std::pair<_ValueType, _SeqNumber> > __sample;
00206 
00207       for (_SeqNumber __i = 0; __i < __m; __i++)
00208         if (__n < __ns[__i])    //__sequence long enough
00209           __sample.push_back(std::make_pair(__S(__i)[__n], __i));
00210       __gnu_sequential::sort(__sample.begin(), __sample.end(), __lcomp);
00211 
00212       for (_SeqNumber __i = 0; __i < __m; __i++)       //conceptual infinity
00213         if (__n >= __ns[__i])   //__sequence too short, conceptual infinity
00214           __sample.push_back(
00215             std::make_pair(__S(__i)[0] /*__dummy element*/, __i));
00216 
00217       _DifferenceType __localrank = __rank / __l;
00218 
00219       _SeqNumber __j;
00220       for (__j = 0;
00221            __j < __localrank && ((__n + 1) <= __ns[__sample[__j].second]);
00222            ++__j)
00223         __a[__sample[__j].second] += __n + 1;
00224       for (; __j < __m; __j++)
00225         __b[__sample[__j].second] -= __n + 1;
00226       
00227       // Further refinement.
00228       while (__n > 0)
00229         {
00230           __n /= 2;
00231 
00232           _SeqNumber __lmax_seq = -1;  // to avoid warning
00233           const _ValueType* __lmax = 0; // impossible to avoid the warning?
00234           for (_SeqNumber __i = 0; __i < __m; __i++)
00235             {
00236               if (__a[__i] > 0)
00237                 {
00238                   if (!__lmax)
00239                     {
00240                       __lmax = &(__S(__i)[__a[__i] - 1]);
00241                       __lmax_seq = __i;
00242                     }
00243                   else
00244                     {
00245                       // Max, favor rear sequences.
00246                       if (!__comp(__S(__i)[__a[__i] - 1], *__lmax))
00247                         {
00248                           __lmax = &(__S(__i)[__a[__i] - 1]);
00249                           __lmax_seq = __i;
00250                         }
00251                     }
00252                 }
00253             }
00254 
00255           _SeqNumber __i;
00256           for (__i = 0; __i < __m; __i++)
00257             {
00258               _DifferenceType __middle = (__b[__i] + __a[__i]) / 2;
00259               if (__lmax && __middle < __ns[__i] &&
00260                   __lcomp(std::make_pair(__S(__i)[__middle], __i),
00261                         std::make_pair(*__lmax, __lmax_seq)))
00262                 __a[__i] = std::min(__a[__i] + __n + 1, __ns[__i]);
00263               else
00264                 __b[__i] -= __n + 1;
00265             }
00266 
00267           _DifferenceType __leftsize = 0;
00268           for (_SeqNumber __i = 0; __i < __m; __i++)
00269               __leftsize += __a[__i] / (__n + 1);
00270 
00271           _DifferenceType __skew = __rank / (__n + 1) - __leftsize;
00272 
00273           if (__skew > 0)
00274             {
00275               // Move to the left, find smallest.
00276               std::priority_queue<std::pair<_ValueType, _SeqNumber>,
00277                 std::vector<std::pair<_ValueType, _SeqNumber> >,
00278                 _LexicographicReverse<_ValueType, _SeqNumber, _Compare> >
00279                 __pq(__lrcomp);
00280               
00281               for (_SeqNumber __i = 0; __i < __m; __i++)
00282                 if (__b[__i] < __ns[__i])
00283                   __pq.push(std::make_pair(__S(__i)[__b[__i]], __i));
00284 
00285               for (; __skew != 0 && !__pq.empty(); --__skew)
00286                 {
00287                   _SeqNumber __source = __pq.top().second;
00288                   __pq.pop();
00289 
00290                   __a[__source]
00291                       = std::min(__a[__source] + __n + 1, __ns[__source]);
00292                   __b[__source] += __n + 1;
00293 
00294                   if (__b[__source] < __ns[__source])
00295                     __pq.push(
00296                       std::make_pair(__S(__source)[__b[__source]], __source));
00297                 }
00298             }
00299           else if (__skew < 0)
00300             {
00301               // Move to the right, find greatest.
00302               std::priority_queue<std::pair<_ValueType, _SeqNumber>,
00303                 std::vector<std::pair<_ValueType, _SeqNumber> >,
00304                 _Lexicographic<_ValueType, _SeqNumber, _Compare> >
00305                   __pq(__lcomp);
00306 
00307               for (_SeqNumber __i = 0; __i < __m; __i++)
00308                 if (__a[__i] > 0)
00309                   __pq.push(std::make_pair(__S(__i)[__a[__i] - 1], __i));
00310 
00311               for (; __skew != 0; ++__skew)
00312                 {
00313                   _SeqNumber __source = __pq.top().second;
00314                   __pq.pop();
00315 
00316                   __a[__source] -= __n + 1;
00317                   __b[__source] -= __n + 1;
00318 
00319                   if (__a[__source] > 0)
00320                     __pq.push(std::make_pair(
00321                         __S(__source)[__a[__source] - 1], __source));
00322                 }
00323             }
00324         }
00325 
00326       // Postconditions:
00327       // __a[__i] == __b[__i] in most cases, except when __a[__i] has been
00328       // clamped because of having reached the boundary
00329 
00330       // Now return the result, calculate the offset.
00331 
00332       // Compare the keys on both edges of the border.
00333 
00334       // Maximum of left edge, minimum of right edge.
00335       _ValueType* __maxleft = 0;
00336       _ValueType* __minright = 0;
00337       for (_SeqNumber __i = 0; __i < __m; __i++)
00338         {
00339           if (__a[__i] > 0)
00340             {
00341               if (!__maxleft)
00342                 __maxleft = &(__S(__i)[__a[__i] - 1]);
00343               else
00344                 {
00345                   // Max, favor rear sequences.
00346                   if (!__comp(__S(__i)[__a[__i] - 1], *__maxleft))
00347                     __maxleft = &(__S(__i)[__a[__i] - 1]);
00348                 }
00349             }
00350           if (__b[__i] < __ns[__i])
00351             {
00352               if (!__minright)
00353                 __minright = &(__S(__i)[__b[__i]]);
00354               else
00355                 {
00356                   // Min, favor fore sequences.
00357                   if (__comp(__S(__i)[__b[__i]], *__minright))
00358                     __minright = &(__S(__i)[__b[__i]]);
00359                 }
00360             }
00361         }
00362 
00363       _SeqNumber __seq = 0;
00364       for (_SeqNumber __i = 0; __i < __m; __i++)
00365         __begin_offsets[__i] = __S(__i) + __a[__i];
00366 
00367       delete[] __ns;
00368       delete[] __a;
00369       delete[] __b;
00370     }
00371 
00372 
00373   /** 
00374    *  @brief Selects the element at a certain global __rank from several
00375    *  sorted sequences.
00376    *
00377    *  The sequences are passed via a sequence of random-access
00378    *  iterator pairs, none of the sequences may be empty.
00379    *  @param __begin_seqs Begin of the sequence of iterator pairs.
00380    *  @param __end_seqs End of the sequence of iterator pairs.
00381    *  @param __rank The global rank to partition at.
00382    *  @param __offset The rank of the selected element in the global
00383    *  subsequence of elements equal to the selected element. If the
00384    *  selected element is unique, this number is 0.
00385    *  @param __comp The ordering functor, defaults to std::less. 
00386    */
00387   template<typename _Tp, typename _RanSeqs, typename _RankType,
00388            typename _Compare>
00389     _Tp
00390     multiseq_selection(_RanSeqs __begin_seqs, _RanSeqs __end_seqs,
00391                        _RankType __rank,
00392                        _RankType& __offset, _Compare __comp = std::less<_Tp>())
00393     {
00394       _GLIBCXX_CALL(__end_seqs - __begin_seqs)
00395 
00396       typedef typename std::iterator_traits<_RanSeqs>::value_type::first_type
00397         _It;
00398       typedef typename std::iterator_traits<_RanSeqs>::difference_type
00399         _SeqNumber;
00400       typedef typename std::iterator_traits<_It>::difference_type
00401         _DifferenceType;
00402 
00403       _Lexicographic<_Tp, _SeqNumber, _Compare> __lcomp(__comp);
00404       _LexicographicReverse<_Tp, _SeqNumber, _Compare> __lrcomp(__comp);
00405 
00406       // Number of sequences, number of elements in total (possibly
00407       // including padding).
00408       _DifferenceType __m = std::distance(__begin_seqs, __end_seqs);
00409       _DifferenceType __nn = 0;
00410       _DifferenceType __nmax, __n, __r;
00411 
00412       for (_SeqNumber __i = 0; __i < __m; __i++)
00413         __nn += std::distance(__begin_seqs[__i].first,
00414                   __begin_seqs[__i].second);
00415 
00416       if (__m == 0 || __nn == 0 || __rank < 0 || __rank >= __nn)
00417         {
00418           // result undefined if there is no data or __rank is outside bounds
00419           throw std::exception();
00420         }
00421 
00422 
00423       _DifferenceType* __ns = new _DifferenceType[__m];
00424       _DifferenceType* __a = new _DifferenceType[__m];
00425       _DifferenceType* __b = new _DifferenceType[__m];
00426       _DifferenceType __l;
00427 
00428       __ns[0] = std::distance(__begin_seqs[0].first, __begin_seqs[0].second);
00429       __nmax = __ns[0];
00430       for (_SeqNumber __i = 0; __i < __m; ++__i)
00431         {
00432           __ns[__i] = std::distance(__begin_seqs[__i].first,
00433                                     __begin_seqs[__i].second);
00434           __nmax = std::max(__nmax, __ns[__i]);
00435         }
00436 
00437       __r = __rd_log2(__nmax) + 1;
00438 
00439       // Pad all lists to this length, at least as long as any ns[__i],
00440       // equality iff __nmax = 2^__k - 1
00441       __l = __round_up_to_pow2(__r) - 1;
00442 
00443       for (_SeqNumber __i = 0; __i < __m; ++__i)
00444         {
00445           __a[__i] = 0;
00446           __b[__i] = __l;
00447         }
00448       __n = __l / 2;
00449 
00450       // Invariants:
00451       // 0 <= __a[__i] <= __ns[__i], 0 <= __b[__i] <= __l
00452 
00453 #define __S(__i) (__begin_seqs[__i].first)
00454 
00455       // Initial partition.
00456       std::vector<std::pair<_Tp, _SeqNumber> > __sample;
00457 
00458       for (_SeqNumber __i = 0; __i < __m; __i++)
00459         if (__n < __ns[__i])
00460           __sample.push_back(std::make_pair(__S(__i)[__n], __i));
00461       __gnu_sequential::sort(__sample.begin(), __sample.end(),
00462                              __lcomp, sequential_tag());
00463 
00464       // Conceptual infinity.
00465       for (_SeqNumber __i = 0; __i < __m; __i++)
00466         if (__n >= __ns[__i])
00467           __sample.push_back(
00468             std::make_pair(__S(__i)[0] /*__dummy element*/, __i));
00469 
00470       _DifferenceType __localrank = __rank / __l;
00471 
00472       _SeqNumber __j;
00473       for (__j = 0;
00474            __j < __localrank && ((__n + 1) <= __ns[__sample[__j].second]);
00475            ++__j)
00476         __a[__sample[__j].second] += __n + 1;
00477       for (; __j < __m; ++__j)
00478         __b[__sample[__j].second] -= __n + 1;
00479 
00480       // Further refinement.
00481       while (__n > 0)
00482         {
00483           __n /= 2;
00484 
00485           const _Tp* __lmax = 0;
00486           for (_SeqNumber __i = 0; __i < __m; ++__i)
00487             {
00488               if (__a[__i] > 0)
00489                 {
00490                   if (!__lmax)
00491                     __lmax = &(__S(__i)[__a[__i] - 1]);
00492                   else
00493                     {
00494                       if (__comp(*__lmax, __S(__i)[__a[__i] - 1]))      //max
00495                         __lmax = &(__S(__i)[__a[__i] - 1]);
00496                     }
00497                 }
00498             }
00499 
00500           _SeqNumber __i;
00501           for (__i = 0; __i < __m; __i++)
00502             {
00503               _DifferenceType __middle = (__b[__i] + __a[__i]) / 2;
00504               if (__lmax && __middle < __ns[__i]
00505                   && __comp(__S(__i)[__middle], *__lmax))
00506                 __a[__i] = std::min(__a[__i] + __n + 1, __ns[__i]);
00507               else
00508                 __b[__i] -= __n + 1;
00509             }
00510 
00511           _DifferenceType __leftsize = 0;
00512           for (_SeqNumber __i = 0; __i < __m; ++__i)
00513               __leftsize += __a[__i] / (__n + 1);
00514 
00515           _DifferenceType __skew = __rank / (__n + 1) - __leftsize;
00516 
00517           if (__skew > 0)
00518             {
00519               // Move to the left, find smallest.
00520               std::priority_queue<std::pair<_Tp, _SeqNumber>,
00521                 std::vector<std::pair<_Tp, _SeqNumber> >,
00522                 _LexicographicReverse<_Tp, _SeqNumber, _Compare> >
00523                   __pq(__lrcomp);
00524 
00525               for (_SeqNumber __i = 0; __i < __m; ++__i)
00526                 if (__b[__i] < __ns[__i])
00527                   __pq.push(std::make_pair(__S(__i)[__b[__i]], __i));
00528 
00529               for (; __skew != 0 && !__pq.empty(); --__skew)
00530                 {
00531                   _SeqNumber __source = __pq.top().second;
00532                   __pq.pop();
00533 
00534                   __a[__source]
00535                       = std::min(__a[__source] + __n + 1, __ns[__source]);
00536                   __b[__source] += __n + 1;
00537 
00538                   if (__b[__source] < __ns[__source])
00539                     __pq.push(
00540                       std::make_pair(__S(__source)[__b[__source]], __source));
00541                 }
00542             }
00543           else if (__skew < 0)
00544             {
00545               // Move to the right, find greatest.
00546               std::priority_queue<std::pair<_Tp, _SeqNumber>,
00547                 std::vector<std::pair<_Tp, _SeqNumber> >,
00548                 _Lexicographic<_Tp, _SeqNumber, _Compare> > __pq(__lcomp);
00549 
00550               for (_SeqNumber __i = 0; __i < __m; ++__i)
00551                 if (__a[__i] > 0)
00552                   __pq.push(std::make_pair(__S(__i)[__a[__i] - 1], __i));
00553 
00554               for (; __skew != 0; ++__skew)
00555                 {
00556                   _SeqNumber __source = __pq.top().second;
00557                   __pq.pop();
00558 
00559                   __a[__source] -= __n + 1;
00560                   __b[__source] -= __n + 1;
00561 
00562                   if (__a[__source] > 0)
00563                     __pq.push(std::make_pair(
00564                         __S(__source)[__a[__source] - 1], __source));
00565                 }
00566             }
00567         }
00568 
00569       // Postconditions:
00570       // __a[__i] == __b[__i] in most cases, except when __a[__i] has been
00571       // clamped because of having reached the boundary
00572 
00573       // Now return the result, calculate the offset.
00574 
00575       // Compare the keys on both edges of the border.
00576 
00577       // Maximum of left edge, minimum of right edge.
00578       bool __maxleftset = false, __minrightset = false;
00579 
00580       // Impossible to avoid the warning?
00581       _Tp __maxleft, __minright;
00582       for (_SeqNumber __i = 0; __i < __m; ++__i)
00583         {
00584           if (__a[__i] > 0)
00585             {
00586               if (!__maxleftset)
00587                 {
00588                   __maxleft = __S(__i)[__a[__i] - 1];
00589                   __maxleftset = true;
00590                 }
00591               else
00592                 {
00593                   // Max.
00594                   if (__comp(__maxleft, __S(__i)[__a[__i] - 1]))
00595                     __maxleft = __S(__i)[__a[__i] - 1];
00596                 }
00597             }
00598           if (__b[__i] < __ns[__i])
00599             {
00600               if (!__minrightset)
00601                 {
00602                   __minright = __S(__i)[__b[__i]];
00603                   __minrightset = true;
00604                 }
00605               else
00606                 {
00607                   // Min.
00608                   if (__comp(__S(__i)[__b[__i]], __minright))
00609                     __minright = __S(__i)[__b[__i]];
00610                 }
00611             }
00612       }
00613 
00614       // Minright is the __splitter, in any case.
00615 
00616       if (!__maxleftset || __comp(__minright, __maxleft))
00617         {
00618           // Good luck, everything is split unambiguously.
00619           __offset = 0;
00620         }
00621       else
00622         {
00623           // We have to calculate an offset.
00624           __offset = 0;
00625 
00626           for (_SeqNumber __i = 0; __i < __m; ++__i)
00627             {
00628               _DifferenceType lb
00629                 = std::lower_bound(__S(__i), __S(__i) + __ns[__i],
00630                                    __minright,
00631                                    __comp) - __S(__i);
00632               __offset += __a[__i] - lb;
00633             }
00634         }
00635 
00636       delete[] __ns;
00637       delete[] __a;
00638       delete[] __b;
00639 
00640       return __minright;
00641     }
00642 }
00643 
00644 #undef __S
00645 
00646 #endif /* _GLIBCXX_PARALLEL_MULTISEQ_SELECTION_H */