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