aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/include/parallel/multiseq_selection.h
diff options
context:
space:
mode:
Diffstat (limited to 'libstdc++-v3/include/parallel/multiseq_selection.h')
-rw-r--r--libstdc++-v3/include/parallel/multiseq_selection.h963
1 files changed, 494 insertions, 469 deletions
diff --git a/libstdc++-v3/include/parallel/multiseq_selection.h b/libstdc++-v3/include/parallel/multiseq_selection.h
index 10f4c73929d..df5bb870a5c 100644
--- a/libstdc++-v3/include/parallel/multiseq_selection.h
+++ b/libstdc++-v3/include/parallel/multiseq_selection.h
@@ -1,6 +1,6 @@
// -*- C++ -*-
-// Copyright (C) 2007 Free Software Foundation, Inc.
+// Copyright (C) 2007, 2008 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -58,52 +58,55 @@ namespace __gnu_parallel
{
/** @brief Compare a pair of types lexicographically, ascending. */
template<typename T1, typename T2, typename Comparator>
- class lexicographic : public std::binary_function<std::pair<T1, T2>, std::pair<T1, T2>, bool>
- {
- private:
- Comparator& comp;
+ class lexicographic
+ : public std::binary_function<std::pair<T1, T2>, std::pair<T1, T2>, bool>
+ {
+ private:
+ Comparator& comp;
- public:
- lexicographic(Comparator& _comp) : comp(_comp) { }
+ public:
+ lexicographic(Comparator& _comp) : comp(_comp) { }
- // XXX const
- inline bool
- operator()(const std::pair<T1, T2>& p1, const std::pair<T1, T2>& p2) const
- {
- if (comp(p1.first, p2.first))
- return true;
+ // XXX const
+ bool
+ operator()(const std::pair<T1, T2>& p1,
+ const std::pair<T1, T2>& p2) const
+ {
+ if (comp(p1.first, p2.first))
+ return true;
- if (comp(p2.first, p1.first))
- return false;
+ if (comp(p2.first, p1.first))
+ return false;
- // Firsts are equal.
- return p1.second < p2.second;
- }
- };
+ // Firsts are equal.
+ return p1.second < p2.second;
+ }
+ };
/** @brief Compare a pair of types lexicographically, descending. */
template<typename T1, typename T2, typename Comparator>
- class lexicographic_reverse : public std::binary_function<T1, T2, bool>
- {
- private:
- Comparator& comp;
+ class lexicographic_reverse : public std::binary_function<T1, T2, bool>
+ {
+ private:
+ Comparator& comp;
- public:
- lexicographic_reverse(Comparator& _comp) : comp(_comp) { }
+ public:
+ lexicographic_reverse(Comparator& _comp) : comp(_comp) { }
- inline bool
- operator()(const std::pair<T1, T2>& p1, const std::pair<T1, T2>& p2) const
- {
- if (comp(p2.first, p1.first))
- return true;
+ bool
+ operator()(const std::pair<T1, T2>& p1,
+ const std::pair<T1, T2>& p2) const
+ {
+ if (comp(p2.first, p1.first))
+ return true;
- if (comp(p1.first, p2.first))
- return false;
+ if (comp(p1.first, p2.first))
+ return false;
- // Firsts are equal.
- return p2.second < p1.second;
- }
- };
+ // Firsts are equal.
+ return p2.second < p1.second;
+ }
+ };
/**
* @brief Splits several sorted sequences at a certain global rank,
@@ -121,229 +124,243 @@ namespace __gnu_parallel
* the respective sequence.
* @param comp The ordering functor, defaults to std::less<T>.
*/
- template<typename RanSeqs, typename RankType, typename RankIterator, typename Comparator>
- void
- multiseq_partition(RanSeqs begin_seqs, RanSeqs end_seqs, RankType rank,
- RankIterator begin_offsets,
- Comparator comp = std::less<
- typename std::iterator_traits<typename std::iterator_traits<RanSeqs>::value_type::first_type>::value_type>()) // std::less<T>
- {
- _GLIBCXX_CALL(end_seqs - begin_seqs)
-
- typedef typename std::iterator_traits<RanSeqs>::value_type::first_type It;
- typedef typename std::iterator_traits<It>::difference_type difference_type;
- typedef typename std::iterator_traits<It>::value_type value_type;
-
- lexicographic<value_type, int, Comparator> lcomp(comp);
- lexicographic_reverse<value_type, int, Comparator> lrcomp(comp);
-
- // Number of sequences, number of elements in total (possibly
- // including padding).
- difference_type m = std::distance(begin_seqs, end_seqs), N = 0, nmax, n, r;
-
- for (int i = 0; i < m; i++)
- N += std::distance(begin_seqs[i].first, begin_seqs[i].second);
-
- if (rank == N)
- {
- for (int i = 0; i < m; i++)
- begin_offsets[i] = begin_seqs[i].second; // Very end.
- // Return m - 1;
- }
-
- _GLIBCXX_PARALLEL_ASSERT(m != 0 && N != 0 && rank >= 0 && rank < N);
-
- difference_type* ns = new difference_type[m];
- difference_type* a = new difference_type[m];
- difference_type* b = new difference_type[m];
- difference_type l;
-
- ns[0] = std::distance(begin_seqs[0].first, begin_seqs[0].second);
- nmax = ns[0];
- for (int i = 0; i < m; i++)
- {
- ns[i] = std::distance(begin_seqs[i].first, begin_seqs[i].second);
- nmax = std::max(nmax, ns[i]);
- }
-
- r = log2(nmax) + 1;
-
- // Pad all lists to this length, at least as long as any ns[i],
- // equality iff nmax = 2^k - 1.
- l = (1ULL << r) - 1;
-
- // From now on, including padding.
- N = l * m;
-
- for (int i = 0; i < m; i++)
- {
- a[i] = 0;
- b[i] = l;
- }
- n = l / 2;
-
- // Invariants:
- // 0 <= a[i] <= ns[i], 0 <= b[i] <= l
+ template<typename RanSeqs, typename RankType, typename RankIterator,
+ typename Comparator>
+ void
+ multiseq_partition(RanSeqs begin_seqs, RanSeqs end_seqs,
+ RankType rank,
+ RankIterator begin_offsets,
+ Comparator comp = std::less<
+ typename std::iterator_traits<typename
+ std::iterator_traits<RanSeqs>::value_type::
+ first_type>::value_type>()) // std::less<T>
+ {
+ _GLIBCXX_CALL(end_seqs - begin_seqs)
+
+ typedef typename std::iterator_traits<RanSeqs>::value_type::first_type
+ It;
+ typedef typename std::iterator_traits<It>::difference_type
+ difference_type;
+ typedef typename std::iterator_traits<It>::value_type value_type;
+
+ lexicographic<value_type, int, Comparator> lcomp(comp);
+ lexicographic_reverse<value_type, int, Comparator> lrcomp(comp);
+
+ // Number of sequences, number of elements in total (possibly
+ // including padding).
+ difference_type m = std::distance(begin_seqs, end_seqs), N = 0,
+ nmax, n, r;
+
+ for (int i = 0; i < m; i++)
+ N += std::distance(begin_seqs[i].first, begin_seqs[i].second);
+
+ if (rank == N)
+ {
+ for (int i = 0; i < m; i++)
+ begin_offsets[i] = begin_seqs[i].second; // Very end.
+ // Return m - 1;
+ }
+
+ _GLIBCXX_PARALLEL_ASSERT(m != 0 && N != 0 && rank >= 0 && rank < N);
+
+ difference_type* ns = new difference_type[m];
+ difference_type* a = new difference_type[m];
+ difference_type* b = new difference_type[m];
+ difference_type l;
+
+ ns[0] = std::distance(begin_seqs[0].first, begin_seqs[0].second);
+ nmax = ns[0];
+ for (int i = 0; i < m; i++)
+ {
+ ns[i] = std::distance(begin_seqs[i].first, begin_seqs[i].second);
+ nmax = std::max(nmax, ns[i]);
+ }
+
+ r = log2(nmax) + 1;
+
+ // Pad all lists to this length, at least as long as any ns[i],
+ // equality iff nmax = 2^k - 1.
+ l = (1ULL << r) - 1;
+
+ // From now on, including padding.
+ N = l * m;
+
+ for (int i = 0; i < m; i++)
+ {
+ a[i] = 0;
+ b[i] = l;
+ }
+ n = l / 2;
+
+ // Invariants:
+ // 0 <= a[i] <= ns[i], 0 <= b[i] <= l
#define S(i) (begin_seqs[i].first)
- // Initial partition.
- std::vector<std::pair<value_type, int> > sample;
-
- for (int i = 0; i < m; i++)
- if (n < ns[i]) //sequence long enough
- sample.push_back(std::make_pair(S(i)[n], i));
- __gnu_sequential::sort(sample.begin(), sample.end(), lcomp);
-
- for (int i = 0; i < m; i++) //conceptual infinity
- if (n >= ns[i]) //sequence too short, conceptual infinity
- sample.push_back(std::make_pair(S(i)[0] /*dummy element*/, i));
-
- difference_type localrank = rank * m / N ;
-
- int j;
- for (j = 0; j < localrank && ((n + 1) <= ns[sample[j].second]); j++)
- a[sample[j].second] += n + 1;
- for (; j < m; j++)
- b[sample[j].second] -= n + 1;
-
- // Further refinement.
- while (n > 0)
- {
- n /= 2;
-
- int lmax_seq = -1; // to avoid warning
- const value_type* lmax = NULL; // impossible to avoid the warning?
- for (int i = 0; i < m; i++)
- {
- if (a[i] > 0)
- {
- if (!lmax)
- {
- lmax = &(S(i)[a[i] - 1]);
- lmax_seq = i;
- }
- else
- {
- // Max, favor rear sequences.
- if (!comp(S(i)[a[i] - 1], *lmax))
- {
- lmax = &(S(i)[a[i] - 1]);
- lmax_seq = i;
- }
- }
- }
- }
-
- int i;
- for (i = 0; i < m; i++)
- {
- difference_type middle = (b[i] + a[i]) / 2;
- if (lmax && middle < ns[i] &&
- lcomp(std::make_pair(S(i)[middle], i), std::make_pair(*lmax, lmax_seq)))
- a[i] = std::min(a[i] + n + 1, ns[i]);
- else
- b[i] -= n + 1;
- }
-
- difference_type leftsize = 0, total = 0;
- for (int i = 0; i < m; i++)
- {
- leftsize += a[i] / (n + 1);
- total += l / (n + 1);
- }
-
- difference_type skew = static_cast<difference_type>(static_cast<uint64>(total) * rank / N - leftsize);
-
- if (skew > 0)
- {
- // Move to the left, find smallest.
- std::priority_queue<std::pair<value_type, int>, std::vector<std::pair<value_type, int> >, lexicographic_reverse<value_type, int, Comparator> > pq(lrcomp);
-
- for (int i = 0; i < m; i++)
- if (b[i] < ns[i])
- pq.push(std::make_pair(S(i)[b[i]], i));
-
- for (; skew != 0 && !pq.empty(); skew--)
- {
- int source = pq.top().second;
- pq.pop();
-
- a[source] = std::min(a[source] + n + 1, ns[source]);
- b[source] += n + 1;
-
- if (b[source] < ns[source])
- pq.push(std::make_pair(S(source)[b[source]], source));
- }
- }
- else if (skew < 0)
- {
- // Move to the right, find greatest.
- std::priority_queue<std::pair<value_type, int>, std::vector<std::pair<value_type, int> >, lexicographic<value_type, int, Comparator> > pq(lcomp);
-
- for (int i = 0; i < m; i++)
+ // Initial partition.
+ std::vector<std::pair<value_type, int> > sample;
+
+ for (int i = 0; i < m; i++)
+ if (n < ns[i]) //sequence long enough
+ sample.push_back(std::make_pair(S(i)[n], i));
+ __gnu_sequential::sort(sample.begin(), sample.end(), lcomp);
+
+ for (int i = 0; i < m; i++) //conceptual infinity
+ if (n >= ns[i]) //sequence too short, conceptual infinity
+ sample.push_back(std::make_pair(S(i)[0] /*dummy element*/, i));
+
+ difference_type localrank = rank * m / N ;
+
+ int j;
+ for (j = 0; j < localrank && ((n + 1) <= ns[sample[j].second]); j++)
+ a[sample[j].second] += n + 1;
+ for (; j < m; j++)
+ b[sample[j].second] -= n + 1;
+
+ // Further refinement.
+ while (n > 0)
+ {
+ n /= 2;
+
+ int lmax_seq = -1; // to avoid warning
+ const value_type* lmax = NULL; // impossible to avoid the warning?
+ for (int i = 0; i < m; i++)
+ {
if (a[i] > 0)
- pq.push(std::make_pair(S(i)[a[i] - 1], i));
-
- for (; skew != 0; skew++)
- {
- int source = pq.top().second;
- pq.pop();
-
- a[source] -= n + 1;
- b[source] -= n + 1;
-
- if (a[source] > 0)
- pq.push(std::make_pair(S(source)[a[source] - 1], source));
- }
- }
- }
-
- // Postconditions:
- // a[i] == b[i] in most cases, except when a[i] has been clamped
- // because of having reached the boundary
-
- // Now return the result, calculate the offset.
-
- // Compare the keys on both edges of the border.
-
- // Maximum of left edge, minimum of right edge.
- value_type* maxleft = NULL;
- value_type* minright = NULL;
- for (int i = 0; i < m; i++)
- {
- if (a[i] > 0)
- {
- if (!maxleft)
- maxleft = &(S(i)[a[i] - 1]);
- else
- {
- // Max, favor rear sequences.
- if (!comp(S(i)[a[i] - 1], *maxleft))
- maxleft = &(S(i)[a[i] - 1]);
- }
- }
- if (b[i] < ns[i])
- {
- if (!minright)
- minright = &(S(i)[b[i]]);
- else
- {
- // Min, favor fore sequences.
- if (comp(S(i)[b[i]], *minright))
- minright = &(S(i)[b[i]]);
- }
- }
- }
-
- int seq = 0;
- for (int i = 0; i < m; i++)
- begin_offsets[i] = S(i) + a[i];
-
- delete[] ns;
- delete[] a;
- delete[] b;
- }
+ {
+ if (!lmax)
+ {
+ lmax = &(S(i)[a[i] - 1]);
+ lmax_seq = i;
+ }
+ else
+ {
+ // Max, favor rear sequences.
+ if (!comp(S(i)[a[i] - 1], *lmax))
+ {
+ lmax = &(S(i)[a[i] - 1]);
+ lmax_seq = i;
+ }
+ }
+ }
+ }
+
+ int i;
+ for (i = 0; i < m; i++)
+ {
+ difference_type middle = (b[i] + a[i]) / 2;
+ if (lmax && middle < ns[i] &&
+ lcomp(std::make_pair(S(i)[middle], i),
+ std::make_pair(*lmax, lmax_seq)))
+ a[i] = std::min(a[i] + n + 1, ns[i]);
+ else
+ b[i] -= n + 1;
+ }
+
+ difference_type leftsize = 0, total = 0;
+ for (int i = 0; i < m; i++)
+ {
+ leftsize += a[i] / (n + 1);
+ total += l / (n + 1);
+ }
+
+ difference_type skew = static_cast<difference_type>
+ (static_cast<uint64>(total) * rank / N - leftsize);
+
+ if (skew > 0)
+ {
+ // Move to the left, find smallest.
+ std::priority_queue<std::pair<value_type, int>,
+ std::vector<std::pair<value_type, int> >,
+ lexicographic_reverse<value_type, int, Comparator> >
+ pq(lrcomp);
+
+ for (int i = 0; i < m; i++)
+ if (b[i] < ns[i])
+ pq.push(std::make_pair(S(i)[b[i]], i));
+
+ for (; skew != 0 && !pq.empty(); skew--)
+ {
+ int source = pq.top().second;
+ pq.pop();
+
+ a[source] = std::min(a[source] + n + 1, ns[source]);
+ b[source] += n + 1;
+
+ if (b[source] < ns[source])
+ pq.push(std::make_pair(S(source)[b[source]], source));
+ }
+ }
+ else if (skew < 0)
+ {
+ // Move to the right, find greatest.
+ std::priority_queue<std::pair<value_type, int>,
+ std::vector<std::pair<value_type, int> >,
+ lexicographic<value_type, int, Comparator> > pq(lcomp);
+
+ for (int i = 0; i < m; i++)
+ if (a[i] > 0)
+ pq.push(std::make_pair(S(i)[a[i] - 1], i));
+
+ for (; skew != 0; skew++)
+ {
+ int source = pq.top().second;
+ pq.pop();
+
+ a[source] -= n + 1;
+ b[source] -= n + 1;
+
+ if (a[source] > 0)
+ pq.push(std::make_pair(S(source)[a[source] - 1], source));
+ }
+ }
+ }
+
+ // Postconditions:
+ // a[i] == b[i] in most cases, except when a[i] has been clamped
+ // because of having reached the boundary
+
+ // Now return the result, calculate the offset.
+
+ // Compare the keys on both edges of the border.
+
+ // Maximum of left edge, minimum of right edge.
+ value_type* maxleft = NULL;
+ value_type* minright = NULL;
+ for (int i = 0; i < m; i++)
+ {
+ if (a[i] > 0)
+ {
+ if (!maxleft)
+ maxleft = &(S(i)[a[i] - 1]);
+ else
+ {
+ // Max, favor rear sequences.
+ if (!comp(S(i)[a[i] - 1], *maxleft))
+ maxleft = &(S(i)[a[i] - 1]);
+ }
+ }
+ if (b[i] < ns[i])
+ {
+ if (!minright)
+ minright = &(S(i)[b[i]]);
+ else
+ {
+ // Min, favor fore sequences.
+ if (comp(S(i)[b[i]], *minright))
+ minright = &(S(i)[b[i]]);
+ }
+ }
+ }
+
+ int seq = 0;
+ for (int i = 0; i < m; i++)
+ begin_offsets[i] = S(i) + a[i];
+
+ delete[] ns;
+ delete[] a;
+ delete[] b;
+ }
/**
@@ -360,246 +377,254 @@ namespace __gnu_parallel
* selected element is unique, this number is 0.
* @param comp The ordering functor, defaults to std::less.
*/
- template<typename T, typename RanSeqs, typename RankType, typename Comparator>
- T
- multiseq_selection(RanSeqs begin_seqs, RanSeqs end_seqs, RankType rank,
- RankType& offset, Comparator comp = std::less<T>())
- {
- _GLIBCXX_CALL(end_seqs - begin_seqs)
+ template<typename T, typename RanSeqs, typename RankType,
+ typename Comparator>
+ T
+ multiseq_selection(RanSeqs begin_seqs, RanSeqs end_seqs, RankType rank,
+ RankType& offset, Comparator comp = std::less<T>())
+ {
+ _GLIBCXX_CALL(end_seqs - begin_seqs)
- typedef typename std::iterator_traits<RanSeqs>::value_type::first_type It;
- typedef typename std::iterator_traits<It>::difference_type difference_type;
+ typedef typename std::iterator_traits<RanSeqs>::value_type::first_type
+ It;
+ typedef typename std::iterator_traits<It>::difference_type
+ difference_type;
- lexicographic<T, int, Comparator> lcomp(comp);
- lexicographic_reverse<T, int, Comparator> lrcomp(comp);
+ lexicographic<T, int, Comparator> lcomp(comp);
+ lexicographic_reverse<T, int, Comparator> lrcomp(comp);
- // Number of sequences, number of elements in total (possibly
- // including padding).
- difference_type m = std::distance(begin_seqs, end_seqs);
- difference_type N = 0;
- difference_type nmax, n, r;
+ // Number of sequences, number of elements in total (possibly
+ // including padding).
+ difference_type m = std::distance(begin_seqs, end_seqs);
+ difference_type N = 0;
+ difference_type nmax, n, r;
- for (int i = 0; i < m; i++)
- N += std::distance(begin_seqs[i].first, begin_seqs[i].second);
+ for (int i = 0; i < m; i++)
+ N += std::distance(begin_seqs[i].first, begin_seqs[i].second);
- if (m == 0 || N == 0 || rank < 0 || rank >= N)
- {
- // Result undefined when there is no data or rank is outside bounds.
- throw std::exception();
- }
+ if (m == 0 || N == 0 || rank < 0 || rank >= N)
+ {
+ // Result undefined when there is no data or rank is outside bounds.
+ throw std::exception();
+ }
- difference_type* ns = new difference_type[m];
- difference_type* a = new difference_type[m];
- difference_type* b = new difference_type[m];
- difference_type l;
+ difference_type* ns = new difference_type[m];
+ difference_type* a = new difference_type[m];
+ difference_type* b = new difference_type[m];
+ difference_type l;
- ns[0] = std::distance(begin_seqs[0].first, begin_seqs[0].second);
- nmax = ns[0];
- for (int i = 0; i < m; i++)
- {
- ns[i] = std::distance(begin_seqs[i].first, begin_seqs[i].second);
- nmax = std::max(nmax, ns[i]);
- }
+ ns[0] = std::distance(begin_seqs[0].first, begin_seqs[0].second);
+ nmax = ns[0];
+ for (int i = 0; i < m; i++)
+ {
+ ns[i] = std::distance(begin_seqs[i].first, begin_seqs[i].second);
+ nmax = std::max(nmax, ns[i]);
+ }
- r = log2(nmax) + 1;
+ r = log2(nmax) + 1;
- // Pad all lists to this length, at least as long as any ns[i],
- // equality iff nmax = 2^k - 1
- l = pow2(r) - 1;
+ // Pad all lists to this length, at least as long as any ns[i],
+ // equality iff nmax = 2^k - 1
+ l = pow2(r) - 1;
- // From now on, including padding.
- N = l * m;
+ // From now on, including padding.
+ N = l * m;
- for (int i = 0; i < m; i++)
- {
- a[i] = 0;
- b[i] = l;
- }
- n = l / 2;
+ for (int i = 0; i < m; i++)
+ {
+ a[i] = 0;
+ b[i] = l;
+ }
+ n = l / 2;
- // Invariants:
- // 0 <= a[i] <= ns[i], 0 <= b[i] <= l
+ // Invariants:
+ // 0 <= a[i] <= ns[i], 0 <= b[i] <= l
#define S(i) (begin_seqs[i].first)
- // Initial partition.
- std::vector<std::pair<T, int> > sample;
+ // Initial partition.
+ std::vector<std::pair<T, int> > sample;
- for (int i = 0; i < m; i++)
- if (n < ns[i])
- sample.push_back(std::make_pair(S(i)[n], i));
- __gnu_sequential::sort(sample.begin(), sample.end(), lcomp, sequential_tag());
+ for (int i = 0; i < m; i++)
+ if (n < ns[i])
+ sample.push_back(std::make_pair(S(i)[n], i));
+ __gnu_sequential::sort(sample.begin(), sample.end(),
+ lcomp, sequential_tag());
- // Conceptual infinity.
- for (int i = 0; i < m; i++)
- if (n >= ns[i])
- sample.push_back(std::make_pair(S(i)[0] /*dummy element*/, i));
+ // Conceptual infinity.
+ for (int i = 0; i < m; i++)
+ if (n >= ns[i])
+ sample.push_back(std::make_pair(S(i)[0] /*dummy element*/, i));
- difference_type localrank = rank * m / N ;
+ difference_type localrank = rank * m / N ;
- int j;
- for (j = 0; j < localrank && ((n + 1) <= ns[sample[j].second]); j++)
- a[sample[j].second] += n + 1;
- for (; j < m; j++)
- b[sample[j].second] -= n + 1;
-
- // Further refinement.
- while (n > 0)
- {
- n /= 2;
-
- const T* lmax = NULL;
- for (int i = 0; i < m; i++)
- {
- if (a[i] > 0)
- {
- if (!lmax)
- {
- lmax = &(S(i)[a[i] - 1]);
- }
- else
- {
- if (comp(*lmax, S(i)[a[i] - 1])) //max
- lmax = &(S(i)[a[i] - 1]);
- }
- }
- }
-
- int i;
- for (i = 0; i < m; i++)
- {
- difference_type middle = (b[i] + a[i]) / 2;
- if (lmax && middle < ns[i] && comp(S(i)[middle], *lmax))
- a[i] = std::min(a[i] + n + 1, ns[i]);
- else
- b[i] -= n + 1;
- }
-
- difference_type leftsize = 0, total = 0;
- for (int i = 0; i < m; i++)
- {
- leftsize += a[i] / (n + 1);
- total += l / (n + 1);
- }
-
- difference_type skew = (unsigned long long)total * rank / N - leftsize;
-
- if (skew > 0)
- {
- // Move to the left, find smallest.
- std::priority_queue<std::pair<T, int>, std::vector<std::pair<T, int> >, lexicographic_reverse<T, int, Comparator> > pq(lrcomp);
-
- for (int i = 0; i < m; i++)
- if (b[i] < ns[i])
- pq.push(std::make_pair(S(i)[b[i]], i));
-
- for (; skew != 0 && !pq.empty(); skew--)
- {
- int source = pq.top().second;
- pq.pop();
-
- a[source] = std::min(a[source] + n + 1, ns[source]);
- b[source] += n + 1;
-
- if (b[source] < ns[source])
- pq.push(std::make_pair(S(source)[b[source]], source));
- }
- }
- else if (skew < 0)
- {
- // Move to the right, find greatest.
- std::priority_queue<std::pair<T, int>, std::vector<std::pair<T, int> >, lexicographic<T, int, Comparator> > pq(lcomp);
-
- for (int i = 0; i < m; i++)
- if (a[i] > 0)
- pq.push(std::make_pair(S(i)[a[i] - 1], i));
+ int j;
+ for (j = 0; j < localrank && ((n + 1) <= ns[sample[j].second]); j++)
+ a[sample[j].second] += n + 1;
+ for (; j < m; j++)
+ b[sample[j].second] -= n + 1;
- for (; skew != 0; skew++)
- {
- int source = pq.top().second;
- pq.pop();
+ // Further refinement.
+ while (n > 0)
+ {
+ n /= 2;
- a[source] -= n + 1;
- b[source] -= n + 1;
-
- if (a[source] > 0)
- pq.push(std::make_pair(S(source)[a[source] - 1], source));
- }
- }
- }
-
- // Postconditions:
- // a[i] == b[i] in most cases, except when a[i] has been clamped
- // because of having reached the boundary
-
- // Now return the result, calculate the offset.
-
- // Compare the keys on both edges of the border.
-
- // Maximum of left edge, minimum of right edge.
- bool maxleftset = false, minrightset = false;
-
- // Impossible to avoid the warning?
- T maxleft, minright;
- for (int i = 0; i < m; i++)
- {
- if (a[i] > 0)
- {
- if (!maxleftset)
- {
- maxleft = S(i)[a[i] - 1];
- maxleftset = true;
- }
- else
- {
- // Max.
- if (comp(maxleft, S(i)[a[i] - 1]))
+ const T* lmax = NULL;
+ for (int i = 0; i < m; i++)
+ {
+ if (a[i] > 0)
+ {
+ if (!lmax)
+ lmax = &(S(i)[a[i] - 1]);
+ else
+ {
+ if (comp(*lmax, S(i)[a[i] - 1])) //max
+ lmax = &(S(i)[a[i] - 1]);
+ }
+ }
+ }
+
+ int i;
+ for (i = 0; i < m; i++)
+ {
+ difference_type middle = (b[i] + a[i]) / 2;
+ if (lmax && middle < ns[i] && comp(S(i)[middle], *lmax))
+ a[i] = std::min(a[i] + n + 1, ns[i]);
+ else
+ b[i] -= n + 1;
+ }
+
+ difference_type leftsize = 0, total = 0;
+ for (int i = 0; i < m; i++)
+ {
+ leftsize += a[i] / (n + 1);
+ total += l / (n + 1);
+ }
+
+ difference_type skew = ((unsigned long long)total * rank / N
+ - leftsize);
+
+ if (skew > 0)
+ {
+ // Move to the left, find smallest.
+ std::priority_queue<std::pair<T, int>,
+ std::vector<std::pair<T, int> >,
+ lexicographic_reverse<T, int, Comparator> > pq(lrcomp);
+
+ for (int i = 0; i < m; i++)
+ if (b[i] < ns[i])
+ pq.push(std::make_pair(S(i)[b[i]], i));
+
+ for (; skew != 0 && !pq.empty(); --skew)
+ {
+ int source = pq.top().second;
+ pq.pop();
+
+ a[source] = std::min(a[source] + n + 1, ns[source]);
+ b[source] += n + 1;
+
+ if (b[source] < ns[source])
+ pq.push(std::make_pair(S(source)[b[source]], source));
+ }
+ }
+ else if (skew < 0)
+ {
+ // Move to the right, find greatest.
+ std::priority_queue<std::pair<T, int>,
+ std::vector<std::pair<T, int> >,
+ lexicographic<T, int, Comparator> > pq(lcomp);
+
+ for (int i = 0; i < m; i++)
+ if (a[i] > 0)
+ pq.push(std::make_pair(S(i)[a[i] - 1], i));
+
+ for (; skew != 0; ++skew)
+ {
+ int source = pq.top().second;
+ pq.pop();
+
+ a[source] -= n + 1;
+ b[source] -= n + 1;
+
+ if (a[source] > 0)
+ pq.push(std::make_pair(S(source)[a[source] - 1], source));
+ }
+ }
+ }
+
+ // Postconditions:
+ // a[i] == b[i] in most cases, except when a[i] has been clamped
+ // because of having reached the boundary
+
+ // Now return the result, calculate the offset.
+
+ // Compare the keys on both edges of the border.
+
+ // Maximum of left edge, minimum of right edge.
+ bool maxleftset = false, minrightset = false;
+
+ // Impossible to avoid the warning?
+ T maxleft, minright;
+ for (int i = 0; i < m; i++)
+ {
+ if (a[i] > 0)
+ {
+ if (!maxleftset)
+ {
maxleft = S(i)[a[i] - 1];
- }
- }
- if (b[i] < ns[i])
- {
- if (!minrightset)
- {
- minright = S(i)[b[i]];
- minrightset = true;
- }
- else
- {
- // Min.
- if (comp(S(i)[b[i]], minright))
+ maxleftset = true;
+ }
+ else
+ {
+ // Max.
+ if (comp(maxleft, S(i)[a[i] - 1]))
+ maxleft = S(i)[a[i] - 1];
+ }
+ }
+ if (b[i] < ns[i])
+ {
+ if (!minrightset)
+ {
minright = S(i)[b[i]];
- }
- }
+ minrightset = true;
+ }
+ else
+ {
+ // Min.
+ if (comp(S(i)[b[i]], minright))
+ minright = S(i)[b[i]];
+ }
+ }
}
- // Minright is the splitter, in any case.
-
- if (!maxleftset || comp(minright, maxleft))
- {
- // Good luck, everything is split unambigiously.
- offset = 0;
- }
- else
- {
- // We have to calculate an offset.
- offset = 0;
-
- for (int i = 0; i < m; i++)
- {
- difference_type lb = std::lower_bound(S(i), S(i) + ns[i], minright,
- comp) - S(i);
- offset += a[i] - lb;
- }
- }
-
- delete[] ns;
- delete[] a;
- delete[] b;
-
- return minright;
- }
+ // Minright is the splitter, in any case.
+
+ if (!maxleftset || comp(minright, maxleft))
+ {
+ // Good luck, everything is split unambigiously.
+ offset = 0;
+ }
+ else
+ {
+ // We have to calculate an offset.
+ offset = 0;
+
+ for (int i = 0; i < m; i++)
+ {
+ difference_type lb = std::lower_bound(S(i), S(i) + ns[i],
+ minright,
+ comp) - S(i);
+ offset += a[i] - lb;
+ }
+ }
+
+ delete[] ns;
+ delete[] a;
+ delete[] b;
+
+ return minright;
+ }
}
#undef S