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