Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. // -*- C++ -*-
  2.  
  3. // Copyright (C) 2007-2015 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):171–177, 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.