aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.4.3/libstdc++-v3/include/parallel/multiway_merge.h
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.4.3/libstdc++-v3/include/parallel/multiway_merge.h')
-rw-r--r--gcc-4.4.3/libstdc++-v3/include/parallel/multiway_merge.h2140
1 files changed, 0 insertions, 2140 deletions
diff --git a/gcc-4.4.3/libstdc++-v3/include/parallel/multiway_merge.h b/gcc-4.4.3/libstdc++-v3/include/parallel/multiway_merge.h
deleted file mode 100644
index fe32053d6..000000000
--- a/gcc-4.4.3/libstdc++-v3/include/parallel/multiway_merge.h
+++ /dev/null
@@ -1,2140 +0,0 @@
-// -*- C++ -*-
-
-// Copyright (C) 2007, 2008, 2009 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
-// of the GNU General Public License as published by the Free Software
-// Foundation; either version 3, or (at your option) any later
-// version.
-
-// This library is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// General Public License for more details.
-
-// Under Section 7 of GPL version 3, you are granted additional
-// permissions described in the GCC Runtime Library Exception, version
-// 3.1, as published by the Free Software Foundation.
-
-// You should have received a copy of the GNU General Public License and
-// a copy of the GCC Runtime Library Exception along with this program;
-// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-// <http://www.gnu.org/licenses/>.
-
-/** @file parallel/multiway_merge.h
-* @brief Implementation of sequential and parallel multiway merge.
-*
-* Explanations on the high-speed merging routines in the appendix of
-*
-* P. Sanders.
-* Fast priority queues for cached memory.
-* ACM Journal of Experimental Algorithmics, 5, 2000.
-*
-* This file is a GNU parallel extension to the Standard C++ Library.
-*/
-
-// Written by Johannes Singler and Manuel Holtgrewe.
-
-#ifndef _GLIBCXX_PARALLEL_MULTIWAY_MERGE_H
-#define _GLIBCXX_PARALLEL_MULTIWAY_MERGE_H
-
-#include <vector>
-
-#include <bits/stl_algo.h>
-#include <parallel/features.h>
-#include <parallel/parallel.h>
-#include <parallel/losertree.h>
-#if _GLIBCXX_ASSERTIONS
-#include <parallel/checkers.h>
-#endif
-
-/** @brief Length of a sequence described by a pair of iterators. */
-#define _GLIBCXX_PARALLEL_LENGTH(s) ((s).second - (s).first)
-
-namespace __gnu_parallel
-{
-
-// Announce guarded and unguarded iterator.
-
-template<typename RandomAccessIterator, typename Comparator>
- class guarded_iterator;
-
-// Making the arguments const references seems to dangerous,
-// the user-defined comparator might not be const.
-template<typename RandomAccessIterator, typename Comparator>
- inline bool
- operator<(guarded_iterator<RandomAccessIterator, Comparator>& bi1,
- guarded_iterator<RandomAccessIterator, Comparator>& bi2);
-
-template<typename RandomAccessIterator, typename Comparator>
- inline bool
- operator<=(guarded_iterator<RandomAccessIterator, Comparator>& bi1,
- guarded_iterator<RandomAccessIterator, Comparator>& bi2);
-
-/** @brief Iterator wrapper supporting an implicit supremum at the end
- * of the sequence, dominating all comparisons.
- *
- * The implicit supremum comes with a performance cost.
- *
- * Deriving from RandomAccessIterator is not possible since
- * RandomAccessIterator need not be a class.
- */
-template<typename RandomAccessIterator, typename Comparator>
- class guarded_iterator
- {
- private:
- /** @brief Current iterator position. */
- RandomAccessIterator current;
-
- /** @brief End iterator of the sequence. */
- RandomAccessIterator end;
-
- /** @brief Comparator. */
- Comparator& comp;
-
- public:
- /** @brief Constructor. Sets iterator to beginning of sequence.
- * @param begin Begin iterator of sequence.
- * @param end End iterator of sequence.
- * @param comp Comparator provided for associated overloaded
- * compare operators. */
- guarded_iterator(RandomAccessIterator begin,
- RandomAccessIterator end, Comparator& comp)
- : current(begin), end(end), comp(comp)
- { }
-
- /** @brief Pre-increment operator.
- * @return This. */
- guarded_iterator<RandomAccessIterator, Comparator>&
- operator++()
- {
- ++current;
- return *this;
- }
-
- /** @brief Dereference operator.
- * @return Referenced element. */
- typename std::iterator_traits<RandomAccessIterator>::value_type&
- operator*()
- { return *current; }
-
- /** @brief Convert to wrapped iterator.
- * @return Wrapped iterator. */
- operator RandomAccessIterator()
- { return current; }
-
- friend bool
- operator< <RandomAccessIterator, Comparator>(
- guarded_iterator<RandomAccessIterator, Comparator>& bi1,
- guarded_iterator<RandomAccessIterator, Comparator>& bi2);
-
- friend bool
- operator<= <RandomAccessIterator, Comparator>(
- guarded_iterator<RandomAccessIterator, Comparator>& bi1,
- guarded_iterator<RandomAccessIterator, Comparator>& bi2);
- };
-
-/** @brief Compare two elements referenced by guarded iterators.
- * @param bi1 First iterator.
- * @param bi2 Second iterator.
- * @return @c True if less. */
-template<typename RandomAccessIterator, typename Comparator>
- inline bool
- operator<(guarded_iterator<RandomAccessIterator, Comparator>& bi1,
- guarded_iterator<RandomAccessIterator, Comparator>& bi2)
- {
- if (bi1.current == bi1.end) //bi1 is sup
- return bi2.current == bi2.end; //bi2 is not sup
- if (bi2.current == bi2.end) //bi2 is sup
- return true;
- return (bi1.comp)(*bi1, *bi2); //normal compare
- }
-
-/** @brief Compare two elements referenced by guarded iterators.
- * @param bi1 First iterator.
- * @param bi2 Second iterator.
- * @return @c True if less equal. */
-template<typename RandomAccessIterator, typename Comparator>
- inline bool
- operator<=(guarded_iterator<RandomAccessIterator, Comparator>& bi1,
- guarded_iterator<RandomAccessIterator, Comparator>& bi2)
- {
- if (bi2.current == bi2.end) //bi1 is sup
- return bi1.current != bi1.end; //bi2 is not sup
- if (bi1.current == bi1.end) //bi2 is sup
- return false;
- return !(bi1.comp)(*bi2, *bi1); //normal compare
- }
-
-template<typename RandomAccessIterator, typename Comparator>
- class unguarded_iterator;
-
-template<typename RandomAccessIterator, typename Comparator>
- inline bool
- operator<(unguarded_iterator<RandomAccessIterator, Comparator>& bi1,
- unguarded_iterator<RandomAccessIterator, Comparator>& bi2);
-
-template<typename RandomAccessIterator, typename Comparator>
- inline bool
- operator<=(unguarded_iterator<RandomAccessIterator, Comparator>& bi1,
- unguarded_iterator<RandomAccessIterator, Comparator>& bi2);
-
-template<typename RandomAccessIterator, typename Comparator>
- class unguarded_iterator
- {
- private:
- /** @brief Current iterator position. */
- RandomAccessIterator current;
- /** @brief Comparator. */
- mutable Comparator& comp;
-
- public:
- /** @brief Constructor. Sets iterator to beginning of sequence.
- * @param begin Begin iterator of sequence.
- * @param end Unused, only for compatibility.
- * @param comp Unused, only for compatibility. */
- unguarded_iterator(RandomAccessIterator begin,
- RandomAccessIterator end, Comparator& comp)
- : current(begin), comp(comp)
- { }
-
- /** @brief Pre-increment operator.
- * @return This. */
- unguarded_iterator<RandomAccessIterator, Comparator>&
- operator++()
- {
- ++current;
- return *this;
- }
-
- /** @brief Dereference operator.
- * @return Referenced element. */
- typename std::iterator_traits<RandomAccessIterator>::value_type&
- operator*()
- { return *current; }
-
- /** @brief Convert to wrapped iterator.
- * @return Wrapped iterator. */
- operator RandomAccessIterator()
- { return current; }
-
- friend bool
- operator< <RandomAccessIterator, Comparator>(
- unguarded_iterator<RandomAccessIterator, Comparator>& bi1,
- unguarded_iterator<RandomAccessIterator, Comparator>& bi2);
-
- friend bool
- operator<= <RandomAccessIterator, Comparator>(
- unguarded_iterator<RandomAccessIterator, Comparator>& bi1,
- unguarded_iterator<RandomAccessIterator, Comparator>& bi2);
- };
-
-/** @brief Compare two elements referenced by unguarded iterators.
- * @param bi1 First iterator.
- * @param bi2 Second iterator.
- * @return @c True if less. */
-template<typename RandomAccessIterator, typename Comparator>
- inline bool
- operator<(unguarded_iterator<RandomAccessIterator, Comparator>& bi1,
- unguarded_iterator<RandomAccessIterator, Comparator>& bi2)
- {
- // Normal compare.
- return (bi1.comp)(*bi1, *bi2);
- }
-
-/** @brief Compare two elements referenced by unguarded iterators.
- * @param bi1 First iterator.
- * @param bi2 Second iterator.
- * @return @c True if less equal. */
-template<typename RandomAccessIterator, typename Comparator>
- inline bool
- operator<=(unguarded_iterator<RandomAccessIterator, Comparator>& bi1,
- unguarded_iterator<RandomAccessIterator, Comparator>& bi2)
- {
- // Normal compare.
- return !(bi1.comp)(*bi2, *bi1);
- }
-
-/** @brief Highly efficient 3-way merging procedure.
- *
- * Merging is done with the algorithm implementation described by Peter
- * Sanders. Basically, the idea is to minimize the number of necessary
- * comparison after merging out an element. The implementation trick
- * that makes this fast is that the order of the sequences is stored
- * in the instruction pointer (translated into labels in C++).
- *
- * This works well for merging up to 4 sequences.
- *
- * Note that making the merging stable does <em>not</em> come at a
- * performance hit.
- *
- * Whether the merging is done guarded or unguarded is selected by the
- * used iterator class.
- *
- * @param seqs_begin Begin iterator of iterator pair input sequence.
- * @param seqs_end End iterator of iterator pair input sequence.
- * @param target Begin iterator out output sequence.
- * @param comp Comparator.
- * @param length Maximum length to merge, less equal than the
- * total number of elements available.
- *
- * @return End iterator of output sequence.
- */
-template<template<typename RAI, typename C> class iterator,
- typename RandomAccessIteratorIterator,
- typename RandomAccessIterator3,
- typename _DifferenceTp,
- typename Comparator>
- RandomAccessIterator3
- multiway_merge_3_variant(
- RandomAccessIteratorIterator seqs_begin,
- RandomAccessIteratorIterator seqs_end,
- RandomAccessIterator3 target,
- _DifferenceTp length, Comparator comp)
- {
- _GLIBCXX_CALL(length);
-
- typedef _DifferenceTp difference_type;
-
- typedef typename std::iterator_traits<RandomAccessIteratorIterator>
- ::value_type::first_type
- RandomAccessIterator1;
- typedef typename std::iterator_traits<RandomAccessIterator1>::value_type
- value_type;
-
- if (length == 0)
- return target;
-
-#if _GLIBCXX_ASSERTIONS
- _DifferenceTp orig_length = length;
-#endif
-
- iterator<RandomAccessIterator1, Comparator>
- seq0(seqs_begin[0].first, seqs_begin[0].second, comp),
- seq1(seqs_begin[1].first, seqs_begin[1].second, comp),
- seq2(seqs_begin[2].first, seqs_begin[2].second, comp);
-
- if (seq0 <= seq1)
- {
- if (seq1 <= seq2)
- goto s012;
- else
- if (seq2 < seq0)
- goto s201;
- else
- goto s021;
- }
- else
- {
- if (seq1 <= seq2)
- {
- if (seq0 <= seq2)
- goto s102;
- else
- goto s120;
- }
- else
- goto s210;
- }
-#define _GLIBCXX_PARALLEL_MERGE_3_CASE(a,b,c,c0,c1) \
- s ## a ## b ## c : \
- *target = *seq ## a; \
- ++target; \
- --length; \
- ++seq ## a; \
- if (length == 0) goto finish; \
- if (seq ## a c0 seq ## b) goto s ## a ## b ## c; \
- if (seq ## a c1 seq ## c) goto s ## b ## a ## c; \
- goto s ## b ## c ## a;
-
- _GLIBCXX_PARALLEL_MERGE_3_CASE(0, 1, 2, <=, <=);
- _GLIBCXX_PARALLEL_MERGE_3_CASE(1, 2, 0, <=, < );
- _GLIBCXX_PARALLEL_MERGE_3_CASE(2, 0, 1, < , < );
- _GLIBCXX_PARALLEL_MERGE_3_CASE(1, 0, 2, < , <=);
- _GLIBCXX_PARALLEL_MERGE_3_CASE(0, 2, 1, <=, <=);
- _GLIBCXX_PARALLEL_MERGE_3_CASE(2, 1, 0, < , < );
-
-#undef _GLIBCXX_PARALLEL_MERGE_3_CASE
-
- finish:
- ;
-
-#if _GLIBCXX_ASSERTIONS
- _GLIBCXX_PARALLEL_ASSERT(
- ((RandomAccessIterator1)seq0 - seqs_begin[0].first) +
- ((RandomAccessIterator1)seq1 - seqs_begin[1].first) +
- ((RandomAccessIterator1)seq2 - seqs_begin[2].first)
- == orig_length);
-#endif
-
- seqs_begin[0].first = seq0;
- seqs_begin[1].first = seq1;
- seqs_begin[2].first = seq2;
-
- return target;
- }
-
-/**
- * @brief Highly efficient 4-way merging procedure.
- *
- * Merging is done with the algorithm implementation described by Peter
- * Sanders. Basically, the idea is to minimize the number of necessary
- * comparison after merging out an element. The implementation trick
- * that makes this fast is that the order of the sequences is stored
- * in the instruction pointer (translated into goto labels in C++).
- *
- * This works well for merging up to 4 sequences.
- *
- * Note that making the merging stable does <em>not</em> come at a
- * performance hit.
- *
- * Whether the merging is done guarded or unguarded is selected by the
- * used iterator class.
- *
- * @param seqs_begin Begin iterator of iterator pair input sequence.
- * @param seqs_end End iterator of iterator pair input sequence.
- * @param target Begin iterator out output sequence.
- * @param comp Comparator.
- * @param length Maximum length to merge, less equal than the
- * total number of elements available.
- *
- * @return End iterator of output sequence.
- */
-template<template<typename RAI, typename C> class iterator,
- typename RandomAccessIteratorIterator,
- typename RandomAccessIterator3,
- typename _DifferenceTp,
- typename Comparator>
- RandomAccessIterator3
- multiway_merge_4_variant(RandomAccessIteratorIterator seqs_begin,
- RandomAccessIteratorIterator seqs_end,
- RandomAccessIterator3 target,
- _DifferenceTp length, Comparator comp)
- {
- _GLIBCXX_CALL(length);
- typedef _DifferenceTp difference_type;
-
- typedef typename std::iterator_traits<RandomAccessIteratorIterator>
- ::value_type::first_type
- RandomAccessIterator1;
- typedef typename std::iterator_traits<RandomAccessIterator1>::value_type
- value_type;
-
- iterator<RandomAccessIterator1, Comparator>
- seq0(seqs_begin[0].first, seqs_begin[0].second, comp),
- seq1(seqs_begin[1].first, seqs_begin[1].second, comp),
- seq2(seqs_begin[2].first, seqs_begin[2].second, comp),
- seq3(seqs_begin[3].first, seqs_begin[3].second, comp);
-
-#define _GLIBCXX_PARALLEL_DECISION(a,b,c,d) { \
- if (seq ## d < seq ## a) goto s ## d ## a ## b ## c; \
- if (seq ## d < seq ## b) goto s ## a ## d ## b ## c; \
- if (seq ## d < seq ## c) goto s ## a ## b ## d ## c; \
- goto s ## a ## b ## c ## d; }
-
- if (seq0 <= seq1)
- {
- if (seq1 <= seq2)
- _GLIBCXX_PARALLEL_DECISION(0,1,2,3)
- else
- if (seq2 < seq0)
- _GLIBCXX_PARALLEL_DECISION(2,0,1,3)
- else
- _GLIBCXX_PARALLEL_DECISION(0,2,1,3)
- }
- else
- {
- if (seq1 <= seq2)
- {
- if (seq0 <= seq2)
- _GLIBCXX_PARALLEL_DECISION(1,0,2,3)
- else
- _GLIBCXX_PARALLEL_DECISION(1,2,0,3)
- }
- else
- _GLIBCXX_PARALLEL_DECISION(2,1,0,3)
- }
-
-#define _GLIBCXX_PARALLEL_MERGE_4_CASE(a,b,c,d,c0,c1,c2) \
- s ## a ## b ## c ## d: \
- if (length == 0) goto finish; \
- *target = *seq ## a; \
- ++target; \
- --length; \
- ++seq ## a; \
- if (seq ## a c0 seq ## b) goto s ## a ## b ## c ## d; \
- if (seq ## a c1 seq ## c) goto s ## b ## a ## c ## d; \
- if (seq ## a c2 seq ## d) goto s ## b ## c ## a ## d; \
- goto s ## b ## c ## d ## a;
-
- _GLIBCXX_PARALLEL_MERGE_4_CASE(0, 1, 2, 3, <=, <=, <=);
- _GLIBCXX_PARALLEL_MERGE_4_CASE(0, 1, 3, 2, <=, <=, <=);
- _GLIBCXX_PARALLEL_MERGE_4_CASE(0, 2, 1, 3, <=, <=, <=);
- _GLIBCXX_PARALLEL_MERGE_4_CASE(0, 2, 3, 1, <=, <=, <=);
- _GLIBCXX_PARALLEL_MERGE_4_CASE(0, 3, 1, 2, <=, <=, <=);
- _GLIBCXX_PARALLEL_MERGE_4_CASE(0, 3, 2, 1, <=, <=, <=);
- _GLIBCXX_PARALLEL_MERGE_4_CASE(1, 0, 2, 3, < , <=, <=);
- _GLIBCXX_PARALLEL_MERGE_4_CASE(1, 0, 3, 2, < , <=, <=);
- _GLIBCXX_PARALLEL_MERGE_4_CASE(1, 2, 0, 3, <=, < , <=);
- _GLIBCXX_PARALLEL_MERGE_4_CASE(1, 2, 3, 0, <=, <=, < );
- _GLIBCXX_PARALLEL_MERGE_4_CASE(1, 3, 0, 2, <=, < , <=);
- _GLIBCXX_PARALLEL_MERGE_4_CASE(1, 3, 2, 0, <=, <=, < );
- _GLIBCXX_PARALLEL_MERGE_4_CASE(2, 0, 1, 3, < , < , <=);
- _GLIBCXX_PARALLEL_MERGE_4_CASE(2, 0, 3, 1, < , <=, < );
- _GLIBCXX_PARALLEL_MERGE_4_CASE(2, 1, 0, 3, < , < , <=);
- _GLIBCXX_PARALLEL_MERGE_4_CASE(2, 1, 3, 0, < , <=, < );
- _GLIBCXX_PARALLEL_MERGE_4_CASE(2, 3, 0, 1, <=, < , < );
- _GLIBCXX_PARALLEL_MERGE_4_CASE(2, 3, 1, 0, <=, < , < );
- _GLIBCXX_PARALLEL_MERGE_4_CASE(3, 0, 1, 2, < , < , < );
- _GLIBCXX_PARALLEL_MERGE_4_CASE(3, 0, 2, 1, < , < , < );
- _GLIBCXX_PARALLEL_MERGE_4_CASE(3, 1, 0, 2, < , < , < );
- _GLIBCXX_PARALLEL_MERGE_4_CASE(3, 1, 2, 0, < , < , < );
- _GLIBCXX_PARALLEL_MERGE_4_CASE(3, 2, 0, 1, < , < , < );
- _GLIBCXX_PARALLEL_MERGE_4_CASE(3, 2, 1, 0, < , < , < );
-
-#undef _GLIBCXX_PARALLEL_MERGE_4_CASE
-#undef _GLIBCXX_PARALLEL_DECISION
-
- finish:
- ;
-
- seqs_begin[0].first = seq0;
- seqs_begin[1].first = seq1;
- seqs_begin[2].first = seq2;
- seqs_begin[3].first = seq3;
-
- return target;
- }
-
-/** @brief Multi-way merging procedure for a high branching factor,
- * guarded case.
- *
- * This merging variant uses a LoserTree class as selected by <tt>LT</tt>.
- *
- * Stability is selected through the used LoserTree class <tt>LT</tt>.
- *
- * At least one non-empty sequence is required.
- *
- * @param seqs_begin Begin iterator of iterator pair input sequence.
- * @param seqs_end End iterator of iterator pair input sequence.
- * @param target Begin iterator out output sequence.
- * @param comp Comparator.
- * @param length Maximum length to merge, less equal than the
- * total number of elements available.
- *
- * @return End iterator of output sequence.
- */
-template<typename LT,
- typename RandomAccessIteratorIterator,
- typename RandomAccessIterator3,
- typename _DifferenceTp,
- typename Comparator>
- RandomAccessIterator3
- multiway_merge_loser_tree(RandomAccessIteratorIterator seqs_begin,
- RandomAccessIteratorIterator seqs_end,
- RandomAccessIterator3 target,
- _DifferenceTp length, Comparator comp)
- {
- _GLIBCXX_CALL(length)
-
- typedef _DifferenceTp difference_type;
- typedef typename std::iterator_traits<RandomAccessIteratorIterator>
- ::value_type::first_type
- RandomAccessIterator1;
- typedef typename std::iterator_traits<RandomAccessIterator1>::value_type
- value_type;
-
- int k = static_cast<int>(seqs_end - seqs_begin);
-
- LT lt(k, comp);
-
- // Default value for potentially non-default-constructible types.
- value_type* arbitrary_element = NULL;
-
- for (int t = 0; t < k; ++t)
- {
- if(arbitrary_element == NULL
- && _GLIBCXX_PARALLEL_LENGTH(seqs_begin[t]) > 0)
- arbitrary_element = &(*seqs_begin[t].first);
- }
-
- for (int t = 0; t < k; ++t)
- {
- if (seqs_begin[t].first == seqs_begin[t].second)
- lt.insert_start(*arbitrary_element, t, true);
- else
- lt.insert_start(*seqs_begin[t].first, t, false);
- }
-
- lt.init();
-
- int source;
-
- for (difference_type i = 0; i < length; ++i)
- {
- //take out
- source = lt.get_min_source();
-
- *(target++) = *(seqs_begin[source].first++);
-
- // Feed.
- if (seqs_begin[source].first == seqs_begin[source].second)
- lt.delete_min_insert(*arbitrary_element, true);
- else
- // Replace from same source.
- lt.delete_min_insert(*seqs_begin[source].first, false);
- }
-
- return target;
- }
-
-/** @brief Multi-way merging procedure for a high branching factor,
- * unguarded case.
- *
- * Merging is done using the LoserTree class <tt>LT</tt>.
- *
- * Stability is selected by the used LoserTrees.
- *
- * @pre No input will run out of elements during the merge.
- *
- * @param seqs_begin Begin iterator of iterator pair input sequence.
- * @param seqs_end End iterator of iterator pair input sequence.
- * @param target Begin iterator out output sequence.
- * @param comp Comparator.
- * @param length Maximum length to merge, less equal than the
- * total number of elements available.
- *
- * @return End iterator of output sequence.
- */
-template<typename LT,
- typename RandomAccessIteratorIterator,
- typename RandomAccessIterator3,
- typename _DifferenceTp, typename Comparator>
- RandomAccessIterator3
- multiway_merge_loser_tree_unguarded(
- RandomAccessIteratorIterator seqs_begin,
- RandomAccessIteratorIterator seqs_end,
- RandomAccessIterator3 target,
- const typename std::iterator_traits<typename std::iterator_traits<
- RandomAccessIteratorIterator>::value_type::first_type>::value_type&
- sentinel,
- _DifferenceTp length,
- Comparator comp)
- {
- _GLIBCXX_CALL(length)
- typedef _DifferenceTp difference_type;
-
- typedef typename std::iterator_traits<RandomAccessIteratorIterator>
- ::value_type::first_type
- RandomAccessIterator1;
- typedef typename std::iterator_traits<RandomAccessIterator1>::value_type
- value_type;
-
- int k = seqs_end - seqs_begin;
-
- LT lt(k, sentinel, comp);
-
- for (int t = 0; t < k; ++t)
- {
-#if _GLIBCXX_ASSERTIONS
- _GLIBCXX_PARALLEL_ASSERT(seqs_begin[t].first != seqs_begin[t].second);
-#endif
- lt.insert_start(*seqs_begin[t].first, t, false);
- }
-
- lt.init();
-
- int source;
-
-#if _GLIBCXX_ASSERTIONS
- difference_type i = 0;
-#endif
-
- RandomAccessIterator3 target_end = target + length;
- while (target < target_end)
- {
- // Take out.
- source = lt.get_min_source();
-
-#if _GLIBCXX_ASSERTIONS
- _GLIBCXX_PARALLEL_ASSERT(0 <= source && source < k);
- _GLIBCXX_PARALLEL_ASSERT(i == 0
- || !comp(*(seqs_begin[source].first), *(target - 1)));
-#endif
-
- // Feed.
- *(target++) = *(seqs_begin[source].first++);
-
-#if _GLIBCXX_ASSERTIONS
- ++i;
-#endif
- // Replace from same source.
- lt.delete_min_insert(*seqs_begin[source].first, false);
- }
-
- return target;
- }
-
-
-/** @brief Multi-way merging procedure for a high branching factor,
- * requiring sentinels to exist.
- *
- * @param stable The value must the same as for the used LoserTrees.
- * @param UnguardedLoserTree Loser Tree variant to use for the unguarded
- * merging.
- * @param GuardedLoserTree Loser Tree variant to use for the guarded
- * merging.
- *
- * @param seqs_begin Begin iterator of iterator pair input sequence.
- * @param seqs_end End iterator of iterator pair input sequence.
- * @param target Begin iterator out output sequence.
- * @param comp Comparator.
- * @param length Maximum length to merge, less equal than the
- * total number of elements available.
- *
- * @return End iterator of output sequence.
- */
-template<
- typename UnguardedLoserTree,
- typename RandomAccessIteratorIterator,
- typename RandomAccessIterator3,
- typename _DifferenceTp,
- typename Comparator>
- RandomAccessIterator3
- multiway_merge_loser_tree_sentinel(
- RandomAccessIteratorIterator seqs_begin,
- RandomAccessIteratorIterator seqs_end,
- RandomAccessIterator3 target,
- const typename std::iterator_traits<typename std::iterator_traits<
- RandomAccessIteratorIterator>::value_type::first_type>::value_type&
- sentinel,
- _DifferenceTp length,
- Comparator comp)
- {
- _GLIBCXX_CALL(length)
-
- typedef _DifferenceTp difference_type;
- typedef std::iterator_traits<RandomAccessIteratorIterator> traits_type;
- typedef typename std::iterator_traits<RandomAccessIteratorIterator>
- ::value_type::first_type
- RandomAccessIterator1;
- typedef typename std::iterator_traits<RandomAccessIterator1>::value_type
- value_type;
-
- RandomAccessIterator3 target_end;
-
- for (RandomAccessIteratorIterator s = seqs_begin; s != seqs_end; ++s)
- // Move the sequends end behind the sentinel spots. This has the
- // effect that the sentinel appears to be within the sequence. Then,
- // we can use the unguarded variant if we merge out as many
- // non-sentinel elements as we have.
- ++((*s).second);
-
- target_end = multiway_merge_loser_tree_unguarded
- <UnguardedLoserTree>
- (seqs_begin, seqs_end, target, sentinel, length, comp);
-
-#if _GLIBCXX_ASSERTIONS
- _GLIBCXX_PARALLEL_ASSERT(target_end == target + length);
- _GLIBCXX_PARALLEL_ASSERT(is_sorted(target, target_end, comp));
-#endif
-
- // Restore the sequence ends so the sentinels are not contained in the
- // sequence any more (see comment in loop above).
- for (RandomAccessIteratorIterator s = seqs_begin; s != seqs_end; ++s)
- --((*s).second);
-
- return target_end;
- }
-
-/**
- * @brief Traits for determining whether the loser tree should
- * use pointers or copies.
- *
- * The field "use_pointer" is used to determine whether to use pointers in
- * the loser trees or whether to copy the values into the loser tree.
- *
- * The default behavior is to use pointers if the data type is 4 times as
- * big as the pointer to it.
- *
- * Specialize for your data type to customize the behavior.
- *
- * Example:
- *
- * template<>
- * struct loser_tree_traits<int>
- * { static const bool use_pointer = false; };
- *
- * template<>
- * struct loser_tree_traits<heavyweight_type>
- * { static const bool use_pointer = true; };
- *
- * @param T type to give the loser tree traits for.
- */
-template <typename T>
-struct loser_tree_traits
-{
- /**
- * @brief True iff to use pointers instead of values in loser trees.
- *
- * The default behavior is to use pointers if the data type is four
- * times as big as the pointer to it.
- */
- static const bool use_pointer = (sizeof(T) > 4 * sizeof(T*));
-};
-
-/**
- * @brief Switch for 3-way merging with sentinels turned off.
- *
- * Note that 3-way merging is always stable!
- */
-template<
- bool sentinels /*default == false*/,
- typename RandomAccessIteratorIterator,
- typename RandomAccessIterator3,
- typename _DifferenceTp,
- typename Comparator>
-struct multiway_merge_3_variant_sentinel_switch
-{
- RandomAccessIterator3 operator()(
- RandomAccessIteratorIterator seqs_begin,
- RandomAccessIteratorIterator seqs_end,
- RandomAccessIterator3 target,
- _DifferenceTp length, Comparator comp)
- {
- return multiway_merge_3_variant<guarded_iterator>(
- seqs_begin, seqs_end, target, length, comp);
- }
-};
-
-/**
- * @brief Switch for 3-way merging with sentinels turned on.
- *
- * Note that 3-way merging is always stable!
- */
-template<
- typename RandomAccessIteratorIterator,
- typename RandomAccessIterator3,
- typename _DifferenceTp,
- typename Comparator>
-struct multiway_merge_3_variant_sentinel_switch
- <true, RandomAccessIteratorIterator, RandomAccessIterator3,
- _DifferenceTp, Comparator>
-{
- RandomAccessIterator3 operator()(
- RandomAccessIteratorIterator seqs_begin,
- RandomAccessIteratorIterator seqs_end,
- RandomAccessIterator3 target,
- _DifferenceTp length, Comparator comp)
- {
- return multiway_merge_3_variant<unguarded_iterator>(
- seqs_begin, seqs_end, target, length, comp);
- }
-};
-
-/**
- * @brief Switch for 4-way merging with sentinels turned off.
- *
- * Note that 4-way merging is always stable!
- */
-template<
- bool sentinels /*default == false*/,
- typename RandomAccessIteratorIterator,
- typename RandomAccessIterator3,
- typename _DifferenceTp,
- typename Comparator>
-struct multiway_merge_4_variant_sentinel_switch
-{
- RandomAccessIterator3 operator()(
- RandomAccessIteratorIterator seqs_begin,
- RandomAccessIteratorIterator seqs_end,
- RandomAccessIterator3 target,
- _DifferenceTp length, Comparator comp)
- {
- return multiway_merge_4_variant<guarded_iterator>(
- seqs_begin, seqs_end, target, length, comp);
- }
-};
-
-/**
- * @brief Switch for 4-way merging with sentinels turned on.
- *
- * Note that 4-way merging is always stable!
- */
-template<
- typename RandomAccessIteratorIterator,
- typename RandomAccessIterator3,
- typename _DifferenceTp,
- typename Comparator>
-struct multiway_merge_4_variant_sentinel_switch
- <true, RandomAccessIteratorIterator, RandomAccessIterator3,
- _DifferenceTp, Comparator>
-{
- RandomAccessIterator3 operator()(
- RandomAccessIteratorIterator seqs_begin,
- RandomAccessIteratorIterator seqs_end,
- RandomAccessIterator3 target,
- _DifferenceTp length, Comparator comp)
- {
- return multiway_merge_4_variant<unguarded_iterator>(
- seqs_begin, seqs_end, target, length, comp);
- }
-};
-
-/**
- * @brief Switch for k-way merging with sentinels turned on.
- */
-template<
- bool sentinels,
- bool stable,
- typename RandomAccessIteratorIterator,
- typename RandomAccessIterator3,
- typename _DifferenceTp,
- typename Comparator>
-struct multiway_merge_k_variant_sentinel_switch
-{
- RandomAccessIterator3 operator()(
- RandomAccessIteratorIterator seqs_begin,
- RandomAccessIteratorIterator seqs_end,
- RandomAccessIterator3 target,
- const typename std::iterator_traits<typename std::iterator_traits<
- RandomAccessIteratorIterator>::value_type::first_type>::value_type&
- sentinel,
- _DifferenceTp length, Comparator comp)
- {
- typedef typename std::iterator_traits<RandomAccessIteratorIterator>
- ::value_type::first_type
- RandomAccessIterator1;
- typedef typename std::iterator_traits<RandomAccessIterator1>::value_type
- value_type;
-
- return multiway_merge_loser_tree_sentinel<
- typename __gnu_cxx::__conditional_type<
- loser_tree_traits<value_type>::use_pointer
- , LoserTreePointerUnguarded<stable, value_type, Comparator>
- , LoserTreeUnguarded<stable, value_type, Comparator>
- >::__type>(seqs_begin, seqs_end, target, sentinel, length, comp);
- }
-};
-
-/**
- * @brief Switch for k-way merging with sentinels turned off.
- */
-template<
- bool stable,
- typename RandomAccessIteratorIterator,
- typename RandomAccessIterator3,
- typename _DifferenceTp,
- typename Comparator>
-struct multiway_merge_k_variant_sentinel_switch
- <false, stable, RandomAccessIteratorIterator, RandomAccessIterator3,
- _DifferenceTp, Comparator>
-{
- RandomAccessIterator3 operator()(
- RandomAccessIteratorIterator seqs_begin,
- RandomAccessIteratorIterator seqs_end,
- RandomAccessIterator3 target,
- const typename std::iterator_traits<typename std::iterator_traits<
- RandomAccessIteratorIterator>::value_type::first_type>::value_type&
- sentinel,
- _DifferenceTp length, Comparator comp)
- {
- typedef typename std::iterator_traits<RandomAccessIteratorIterator>
- ::value_type::first_type
- RandomAccessIterator1;
- typedef typename std::iterator_traits<RandomAccessIterator1>::value_type
- value_type;
-
- return multiway_merge_loser_tree<
- typename __gnu_cxx::__conditional_type<
- loser_tree_traits<value_type>::use_pointer
- , LoserTreePointer<stable, value_type, Comparator>
- , LoserTree<stable, value_type, Comparator>
- >::__type >(seqs_begin, seqs_end, target, length, comp);
- }
-};
-
-/** @brief Sequential multi-way merging switch.
- *
- * The _GLIBCXX_PARALLEL_DECISION is based on the branching factor and
- * runtime settings.
- * @param seqs_begin Begin iterator of iterator pair input sequence.
- * @param seqs_end End iterator of iterator pair input sequence.
- * @param target Begin iterator out output sequence.
- * @param comp Comparator.
- * @param length Maximum length to merge, possibly larger than the
- * number of elements available.
- * @param stable Stable merging incurs a performance penalty.
- * @param sentinel The sequences have a sentinel element.
- * @return End iterator of output sequence. */
-template<
- bool stable,
- bool sentinels,
- typename RandomAccessIteratorIterator,
- typename RandomAccessIterator3,
- typename _DifferenceTp,
- typename Comparator>
- RandomAccessIterator3
- sequential_multiway_merge(
- RandomAccessIteratorIterator seqs_begin,
- RandomAccessIteratorIterator seqs_end,
- RandomAccessIterator3 target,
- const typename std::iterator_traits<typename std::iterator_traits<
- RandomAccessIteratorIterator>::value_type::first_type>::value_type&
- sentinel,
- _DifferenceTp length, Comparator comp)
- {
- _GLIBCXX_CALL(length)
-
- typedef _DifferenceTp difference_type;
- typedef typename std::iterator_traits<RandomAccessIteratorIterator>
- ::value_type::first_type
- RandomAccessIterator1;
- typedef typename std::iterator_traits<RandomAccessIterator1>::value_type
- value_type;
-
-#if _GLIBCXX_ASSERTIONS
- for (RandomAccessIteratorIterator s = seqs_begin; s != seqs_end; ++s)
- {
- _GLIBCXX_PARALLEL_ASSERT(is_sorted((*s).first, (*s).second, comp));
- }
-#endif
-
- _DifferenceTp total_length = 0;
- for (RandomAccessIteratorIterator s = seqs_begin; s != seqs_end; ++s)
- total_length += _GLIBCXX_PARALLEL_LENGTH(*s);
-
- length = std::min<_DifferenceTp>(length, total_length);
-
- if(length == 0)
- return target;
-
- RandomAccessIterator3 return_target = target;
- int k = static_cast<int>(seqs_end - seqs_begin);
-
- switch (k)
- {
- case 0:
- break;
- case 1:
- return_target = std::copy(seqs_begin[0].first,
- seqs_begin[0].first + length,
- target);
- seqs_begin[0].first += length;
- break;
- case 2:
- return_target = merge_advance(seqs_begin[0].first,
- seqs_begin[0].second,
- seqs_begin[1].first,
- seqs_begin[1].second,
- target, length, comp);
- break;
- case 3:
- return_target = multiway_merge_3_variant_sentinel_switch<
- sentinels
- , RandomAccessIteratorIterator
- , RandomAccessIterator3
- , _DifferenceTp
- , Comparator>()(seqs_begin, seqs_end, target, length, comp);
- break;
- case 4:
- return_target = multiway_merge_4_variant_sentinel_switch<
- sentinels
- , RandomAccessIteratorIterator
- , RandomAccessIterator3
- , _DifferenceTp
- , Comparator>()(seqs_begin, seqs_end, target, length, comp);
- break;
- default:
- return_target = multiway_merge_k_variant_sentinel_switch<
- sentinels
- , stable
- , RandomAccessIteratorIterator
- , RandomAccessIterator3
- , _DifferenceTp
- , Comparator>()(seqs_begin, seqs_end, target, sentinel, length, comp);
- break;
- }
-#if _GLIBCXX_ASSERTIONS
- _GLIBCXX_PARALLEL_ASSERT(is_sorted(target, target + length, comp));
-#endif
-
- return return_target;
- }
-
-/**
- * @brief Stable sorting functor.
- *
- * Used to reduce code instanciation in multiway_merge_sampling_splitting.
- */
-template<bool stable, class RandomAccessIterator, class StrictWeakOrdering>
-struct sampling_sorter
-{
- void operator()(RandomAccessIterator first, RandomAccessIterator last,
- StrictWeakOrdering comp)
- { __gnu_sequential::stable_sort(first, last, comp); }
-};
-
-/**
- * @brief Non-stable sorting functor.
- *
- * Used to reduce code instantiation in multiway_merge_sampling_splitting.
- */
-template<class RandomAccessIterator, class StrictWeakOrdering>
-struct sampling_sorter<false, RandomAccessIterator, StrictWeakOrdering>
-{
- void operator()(RandomAccessIterator first, RandomAccessIterator last,
- StrictWeakOrdering comp)
- { __gnu_sequential::sort(first, last, comp); }
-};
-
-/**
- * @brief Sampling based splitting for parallel multiway-merge routine.
- */
-template<
- bool stable
- , typename RandomAccessIteratorIterator
- , typename Comparator
- , typename difference_type>
-void multiway_merge_sampling_splitting(
- RandomAccessIteratorIterator seqs_begin,
- RandomAccessIteratorIterator seqs_end,
- difference_type length, difference_type total_length, Comparator comp,
- std::vector<std::pair<difference_type, difference_type> > *pieces)
-{
- typedef typename std::iterator_traits<RandomAccessIteratorIterator>
- ::value_type::first_type
- RandomAccessIterator1;
- typedef typename std::iterator_traits<RandomAccessIterator1>::value_type
- value_type;
-
- // k sequences.
- int k = static_cast<int>(seqs_end - seqs_begin);
-
- int num_threads = omp_get_num_threads();
-
- difference_type num_samples =
- __gnu_parallel::_Settings::get().merge_oversampling * num_threads;
-
- value_type* samples = static_cast<value_type*>(
- ::operator new(sizeof(value_type) * k * num_samples));
- // Sample.
- for (int s = 0; s < k; ++s)
- for (difference_type i = 0; i < num_samples; ++i)
- {
- difference_type sample_index =
- static_cast<difference_type>(
- _GLIBCXX_PARALLEL_LENGTH(seqs_begin[s])
- * (double(i + 1) / (num_samples + 1))
- * (double(length) / total_length));
- new(&(samples[s * num_samples + i]))
- value_type(seqs_begin[s].first[sample_index]);
- }
-
- // Sort stable or non-stable, depending on value of template parameter
- // "stable".
- sampling_sorter<stable, value_type*, Comparator>()(
- samples, samples + (num_samples * k), comp);
-
- for (int slab = 0; slab < num_threads; ++slab)
- // For each slab / processor.
- for (int seq = 0; seq < k; ++seq)
- {
- // For each sequence.
- if (slab > 0)
- pieces[slab][seq].first =
- std::upper_bound(
- seqs_begin[seq].first,
- seqs_begin[seq].second,
- samples[num_samples * k * slab / num_threads],
- comp)
- - seqs_begin[seq].first;
- else
- // Absolute beginning.
- pieces[slab][seq].first = 0;
- if ((slab + 1) < num_threads)
- pieces[slab][seq].second =
- std::upper_bound(
- seqs_begin[seq].first,
- seqs_begin[seq].second,
- samples[num_samples * k * (slab + 1) /
- num_threads], comp)
- - seqs_begin[seq].first;
- else
- // Absolute end.
- pieces[slab][seq].second = _GLIBCXX_PARALLEL_LENGTH(seqs_begin[seq]);
- }
- ::operator delete(samples);
-}
-
-/**
- * @brief Exact splitting for parallel multiway-merge routine.
- *
- * None of the passed sequences may be empty.
- */
-template<
- bool stable
- , typename RandomAccessIteratorIterator
- , typename Comparator
- , typename difference_type>
-void multiway_merge_exact_splitting(
- RandomAccessIteratorIterator seqs_begin,
- RandomAccessIteratorIterator seqs_end,
- difference_type length, difference_type total_length, Comparator comp,
- std::vector<std::pair<difference_type, difference_type> > *pieces)
-{
- typedef typename std::iterator_traits<RandomAccessIteratorIterator>
- ::value_type::first_type
- RandomAccessIterator1;
-
- const bool tight = (total_length == length);
-
- // k sequences.
- const int k = static_cast<int>(seqs_end - seqs_begin);
-
- const int num_threads = omp_get_num_threads();
-
- // (Settings::multiway_merge_splitting == __gnu_parallel::_Settings::EXACT).
- std::vector<RandomAccessIterator1>* offsets =
- new std::vector<RandomAccessIterator1>[num_threads];
- std::vector<
- std::pair<RandomAccessIterator1, RandomAccessIterator1>
- > se(k);
-
- copy(seqs_begin, seqs_end, se.begin());
-
- difference_type* borders =
- new difference_type[num_threads + 1];
- equally_split(length, num_threads, borders);
-
- for (int s = 0; s < (num_threads - 1); ++s)
- {
- offsets[s].resize(k);
- multiseq_partition(
- se.begin(), se.end(), borders[s + 1],
- offsets[s].begin(), comp);
-
- // Last one also needed and available.
- if (!tight)
- {
- offsets[num_threads - 1].resize(k);
- multiseq_partition(se.begin(), se.end(),
- difference_type(length),
- offsets[num_threads - 1].begin(), comp);
- }
- }
- delete[] borders;
-
- for (int slab = 0; slab < num_threads; ++slab)
- {
- // For each slab / processor.
- for (int seq = 0; seq < k; ++seq)
- {
- // For each sequence.
- if (slab == 0)
- {
- // Absolute beginning.
- pieces[slab][seq].first = 0;
- }
- else
- pieces[slab][seq].first =
- pieces[slab - 1][seq].second;
- if (!tight || slab < (num_threads - 1))
- pieces[slab][seq].second =
- offsets[slab][seq] - seqs_begin[seq].first;
- else
- {
- // slab == num_threads - 1
- pieces[slab][seq].second =
- _GLIBCXX_PARALLEL_LENGTH(seqs_begin[seq]);
- }
- }
- }
- delete[] offsets;
-}
-
-/** @brief Parallel multi-way merge routine.
- *
- * The _GLIBCXX_PARALLEL_DECISION is based on the branching factor
- * and runtime settings.
- *
- * Must not be called if the number of sequences is 1.
- *
- * @param Splitter functor to split input (either exact or sampling based)
- *
- * @param seqs_begin Begin iterator of iterator pair input sequence.
- * @param seqs_end End iterator of iterator pair input sequence.
- * @param target Begin iterator out output sequence.
- * @param comp Comparator.
- * @param length Maximum length to merge, possibly larger than the
- * number of elements available.
- * @param stable Stable merging incurs a performance penalty.
- * @param sentinel Ignored.
- * @return End iterator of output sequence.
- */
-template<
- bool stable,
- bool sentinels,
- typename RandomAccessIteratorIterator,
- typename RandomAccessIterator3,
- typename _DifferenceTp,
- typename Splitter,
- typename Comparator
- >
- RandomAccessIterator3
- parallel_multiway_merge(RandomAccessIteratorIterator seqs_begin,
- RandomAccessIteratorIterator seqs_end,
- RandomAccessIterator3 target,
- Splitter splitter,
- _DifferenceTp length,
- Comparator comp,
- thread_index_t num_threads)
- {
-#if _GLIBCXX_ASSERTIONS
- _GLIBCXX_PARALLEL_ASSERT(seqs_end - seqs_begin > 1);
-#endif
-
- _GLIBCXX_CALL(length)
-
- typedef _DifferenceTp difference_type;
- typedef typename std::iterator_traits<RandomAccessIteratorIterator>
- ::value_type::first_type
- RandomAccessIterator1;
- typedef typename
- std::iterator_traits<RandomAccessIterator1>::value_type value_type;
-
- // Leave only non-empty sequences.
- typedef std::pair<RandomAccessIterator1, RandomAccessIterator1> seq_type;
- seq_type* ne_seqs = new seq_type[seqs_end - seqs_begin];
- int k = 0;
- difference_type total_length = 0;
- for (RandomAccessIteratorIterator raii = seqs_begin;
- raii != seqs_end; ++raii)
- {
- _DifferenceTp seq_length = _GLIBCXX_PARALLEL_LENGTH(*raii);
- if(seq_length > 0)
- {
- total_length += seq_length;
- ne_seqs[k++] = *raii;
- }
- }
-
- _GLIBCXX_CALL(total_length)
-
- length = std::min<_DifferenceTp>(length, total_length);
-
- if (total_length == 0 || k == 0)
- {
- delete[] ne_seqs;
- return target;
- }
-
- std::vector<std::pair<difference_type, difference_type> >* pieces;
-
- num_threads = static_cast<thread_index_t>
- (std::min<difference_type>(num_threads, total_length));
-
-# pragma omp parallel num_threads (num_threads)
- {
-# pragma omp single
- {
- num_threads = omp_get_num_threads();
- // Thread t will have to merge pieces[iam][0..k - 1]
- pieces = new std::vector<
- std::pair<difference_type, difference_type> >[num_threads];
- for (int s = 0; s < num_threads; ++s)
- pieces[s].resize(k);
-
- difference_type num_samples =
- __gnu_parallel::_Settings::get().merge_oversampling *
- num_threads;
-
- splitter(ne_seqs, ne_seqs + k, length, total_length,
- comp, pieces);
- } //single
-
- thread_index_t iam = omp_get_thread_num();
-
- difference_type target_position = 0;
-
- for (int c = 0; c < k; ++c)
- target_position += pieces[iam][c].first;
-
- seq_type* chunks = new seq_type[k];
-
- for (int s = 0; s < k; ++s)
- {
- chunks[s] = std::make_pair(
- ne_seqs[s].first + pieces[iam][s].first,
- ne_seqs[s].first + pieces[iam][s].second);
- }
-
- if(length > target_position)
- sequential_multiway_merge<stable, sentinels>(
- chunks, chunks + k, target + target_position,
- *(seqs_begin->second), length - target_position, comp);
-
- delete[] chunks;
- } // parallel
-
-#if _GLIBCXX_ASSERTIONS
- _GLIBCXX_PARALLEL_ASSERT(is_sorted(target, target + length, comp));
-#endif
-
- k = 0;
- // Update ends of sequences.
- for (RandomAccessIteratorIterator raii = seqs_begin;
- raii != seqs_end; ++raii)
- {
- _DifferenceTp length = _GLIBCXX_PARALLEL_LENGTH(*raii);
- if(length > 0)
- (*raii).first += pieces[num_threads - 1][k++].second;
- }
-
- delete[] pieces;
- delete[] ne_seqs;
-
- return target + length;
- }
-
-/**
- * @brief Multiway Merge Frontend.
- *
- * Merge the sequences specified by seqs_begin and seqs_end into
- * target. seqs_begin and seqs_end must point to a sequence of
- * pairs. These pairs must contain an iterator to the beginning
- * of a sequence in their first entry and an iterator the end of
- * the same sequence in their second entry.
- *
- * Ties are broken arbitrarily. See stable_multiway_merge for a variant
- * that breaks ties by sequence number but is slower.
- *
- * The first entries of the pairs (i.e. the begin iterators) will be moved
- * forward.
- *
- * The output sequence has to provide enough space for all elements
- * that are written to it.
- *
- * This function will merge the input sequences:
- *
- * - not stable
- * - parallel, depending on the input size and Settings
- * - using sampling for splitting
- * - not using sentinels
- *
- * Example:
- *
- * <pre>
- * int sequences[10][10];
- * for (int i = 0; i < 10; ++i)
- * for (int j = 0; i < 10; ++j)
- * sequences[i][j] = j;
- *
- * int out[33];
- * std::vector<std::pair<int*> > seqs;
- * for (int i = 0; i < 10; ++i)
- * { seqs.push(std::make_pair<int*>(sequences[i], sequences[i] + 10)) }
- *
- * multiway_merge(seqs.begin(), seqs.end(), target, std::less<int>(), 33);
- * </pre>
- *
- * @see stable_multiway_merge
- *
- * @pre All input sequences must be sorted.
- * @pre Target must provide enough space to merge out length elements or
- * the number of elements in all sequences, whichever is smaller.
- *
- * @post [target, return value) contains merged elements from the
- * input sequences.
- * @post return value - target = min(length, number of elements in all
- * sequences).
- *
- * @param RandomAccessIteratorPairIterator iterator over sequence
- * of pairs of iterators
- * @param RandomAccessIteratorOut iterator over target sequence
- * @param _DifferenceTp difference type for the sequence
- * @param Comparator strict weak ordering type to compare elements
- * in sequences
- *
- * @param seqs_begin begin of sequence sequence
- * @param seqs_end end of sequence sequence
- * @param target target sequence to merge to.
- * @param comp strict weak ordering to use for element comparison.
- * @param length Maximum length to merge, possibly larger than the
- * number of elements available.
- *
- * @return end iterator of output sequence
- */
-// multiway_merge
-// public interface
-template<
- typename RandomAccessIteratorPairIterator
- , typename RandomAccessIteratorOut
- , typename _DifferenceTp
- , typename Comparator>
-RandomAccessIteratorOut
-multiway_merge(RandomAccessIteratorPairIterator seqs_begin
- , RandomAccessIteratorPairIterator seqs_end
- , RandomAccessIteratorOut target
- , _DifferenceTp length, Comparator comp
- , __gnu_parallel::sequential_tag)
-{
- typedef _DifferenceTp difference_type;
- _GLIBCXX_CALL(seqs_end - seqs_begin)
-
- // catch special case: no sequences
- if (seqs_begin == seqs_end)
- return target;
-
- // Execute multiway merge *sequentially*.
- return sequential_multiway_merge
- </* stable = */ false, /* sentinels = */ false>
- (seqs_begin, seqs_end, target, *(seqs_begin->second), length, comp);
-}
-
-// public interface
-template<
- typename RandomAccessIteratorPairIterator
- , typename RandomAccessIteratorOut
- , typename _DifferenceTp
- , typename Comparator>
-RandomAccessIteratorOut
-multiway_merge(RandomAccessIteratorPairIterator seqs_begin
- , RandomAccessIteratorPairIterator seqs_end
- , RandomAccessIteratorOut target
- , _DifferenceTp length, Comparator comp
- , __gnu_parallel::exact_tag tag)
-{
- typedef _DifferenceTp difference_type;
- _GLIBCXX_CALL(seqs_end - seqs_begin)
-
- // catch special case: no sequences
- if (seqs_begin == seqs_end)
- return target;
-
- // Execute merge; maybe parallel, depending on the number of merged
- // elements and the number of sequences and global thresholds in
- // Settings.
- if ((seqs_end - seqs_begin > 1) &&
- _GLIBCXX_PARALLEL_CONDITION(
- ((seqs_end - seqs_begin) >=
- __gnu_parallel::_Settings::get().multiway_merge_minimal_k)
- && ((sequence_index_t)length >=
- __gnu_parallel::_Settings::get().multiway_merge_minimal_n)))
- return parallel_multiway_merge
- </* stable = */ false, /* sentinels = */ false>(
- seqs_begin, seqs_end, target,
- multiway_merge_exact_splitting</* stable = */ false,
- typename std::iterator_traits<RandomAccessIteratorPairIterator>
- ::value_type*, Comparator, _DifferenceTp>,
- static_cast<difference_type>(length), comp, tag.get_num_threads());
- else
- return sequential_multiway_merge
- </* stable = */ false, /* sentinels = */ false>(
- seqs_begin, seqs_end, target, *(seqs_begin->second), length, comp);
-}
-
-// public interface
-template<
- typename RandomAccessIteratorPairIterator
- , typename RandomAccessIteratorOut
- , typename _DifferenceTp
- , typename Comparator>
-RandomAccessIteratorOut
-multiway_merge(RandomAccessIteratorPairIterator seqs_begin
- , RandomAccessIteratorPairIterator seqs_end
- , RandomAccessIteratorOut target
- , _DifferenceTp length, Comparator comp
- , __gnu_parallel::sampling_tag tag)
-{
- typedef _DifferenceTp difference_type;
- _GLIBCXX_CALL(seqs_end - seqs_begin)
-
- // catch special case: no sequences
- if (seqs_begin == seqs_end)
- return target;
-
- // Execute merge; maybe parallel, depending on the number of merged
- // elements and the number of sequences and global thresholds in
- // Settings.
- if ((seqs_end - seqs_begin > 1) &&
- _GLIBCXX_PARALLEL_CONDITION(
- ((seqs_end - seqs_begin) >=
- __gnu_parallel::_Settings::get().multiway_merge_minimal_k)
- && ((sequence_index_t)length >=
- __gnu_parallel::_Settings::get().multiway_merge_minimal_n)))
- return parallel_multiway_merge
- </* stable = */ false, /* sentinels = */ false>(
- seqs_begin, seqs_end,
- target,
- multiway_merge_exact_splitting</* stable = */ false,
- typename std::iterator_traits<RandomAccessIteratorPairIterator>
- ::value_type*, Comparator, _DifferenceTp>,
- static_cast<difference_type>(length), comp, tag.get_num_threads());
- else
- return sequential_multiway_merge
- </* stable = */ false, /* sentinels = */ false>(
- seqs_begin, seqs_end,
- target, *(seqs_begin->second), length, comp);
-}
-
-// public interface
-template<
- typename RandomAccessIteratorPairIterator
- , typename RandomAccessIteratorOut
- , typename _DifferenceTp
- , typename Comparator>
-RandomAccessIteratorOut
-multiway_merge(RandomAccessIteratorPairIterator seqs_begin
- , RandomAccessIteratorPairIterator seqs_end
- , RandomAccessIteratorOut target
- , _DifferenceTp length, Comparator comp
- , parallel_tag tag = parallel_tag(0))
-{
- return multiway_merge(seqs_begin, seqs_end, target, length, comp,
- exact_tag(tag.get_num_threads()));
-}
-
-// public interface
-template<
- typename RandomAccessIteratorPairIterator
- , typename RandomAccessIteratorOut
- , typename _DifferenceTp
- , typename Comparator>
-RandomAccessIteratorOut
-multiway_merge(RandomAccessIteratorPairIterator seqs_begin
- , RandomAccessIteratorPairIterator seqs_end
- , RandomAccessIteratorOut target
- , _DifferenceTp length, Comparator comp
- , default_parallel_tag tag)
-{
- return multiway_merge(seqs_begin, seqs_end, target, length, comp,
- exact_tag(tag.get_num_threads()));
-}
-
-// stable_multiway_merge
-// public interface
-template<
- typename RandomAccessIteratorPairIterator
- , typename RandomAccessIteratorOut
- , typename _DifferenceTp
- , typename Comparator>
-RandomAccessIteratorOut
-stable_multiway_merge(RandomAccessIteratorPairIterator seqs_begin
- , RandomAccessIteratorPairIterator seqs_end
- , RandomAccessIteratorOut target
- , _DifferenceTp length, Comparator comp
- , __gnu_parallel::sequential_tag)
-{
- typedef _DifferenceTp difference_type;
- _GLIBCXX_CALL(seqs_end - seqs_begin)
-
- // catch special case: no sequences
- if (seqs_begin == seqs_end)
- return target;
-
- // Execute multiway merge *sequentially*.
- return sequential_multiway_merge
- </* stable = */ true, /* sentinels = */ false>
- (seqs_begin, seqs_end, target, *(seqs_begin->second), length, comp);
-}
-
-// public interface
-template<
- typename RandomAccessIteratorPairIterator
- , typename RandomAccessIteratorOut
- , typename _DifferenceTp
- , typename Comparator>
-RandomAccessIteratorOut
-stable_multiway_merge(RandomAccessIteratorPairIterator seqs_begin
- , RandomAccessIteratorPairIterator seqs_end
- , RandomAccessIteratorOut target
- , _DifferenceTp length, Comparator comp
- , __gnu_parallel::exact_tag tag)
-{
- typedef _DifferenceTp difference_type;
- _GLIBCXX_CALL(seqs_end - seqs_begin)
-
- // catch special case: no sequences
- if (seqs_begin == seqs_end)
- return target;
-
- // Execute merge; maybe parallel, depending on the number of merged
- // elements and the number of sequences and global thresholds in
- // Settings.
- if ((seqs_end - seqs_begin > 1) &&
- _GLIBCXX_PARALLEL_CONDITION(
- ((seqs_end - seqs_begin) >=
- __gnu_parallel::_Settings::get().multiway_merge_minimal_k)
- && ((sequence_index_t)length >=
- __gnu_parallel::_Settings::get().multiway_merge_minimal_n)))
- return parallel_multiway_merge
- </* stable = */ true, /* sentinels = */ false>(
- seqs_begin, seqs_end,
- target,
- multiway_merge_exact_splitting</* stable = */ true,
- typename std::iterator_traits<RandomAccessIteratorPairIterator>
- ::value_type*, Comparator, _DifferenceTp>,
- static_cast<difference_type>(length), comp, tag.get_num_threads());
- else
- return sequential_multiway_merge</* stable = */ true,
- /* sentinels = */ false>(
- seqs_begin, seqs_end,
- target, *(seqs_begin->second), length, comp);
-}
-
-// public interface
-template<
- typename RandomAccessIteratorPairIterator
- , typename RandomAccessIteratorOut
- , typename _DifferenceTp
- , typename Comparator>
-RandomAccessIteratorOut
-stable_multiway_merge(RandomAccessIteratorPairIterator seqs_begin
- , RandomAccessIteratorPairIterator seqs_end
- , RandomAccessIteratorOut target
- , _DifferenceTp length, Comparator comp
- , sampling_tag tag)
-{
- typedef _DifferenceTp difference_type;
- _GLIBCXX_CALL(seqs_end - seqs_begin)
-
- // catch special case: no sequences
- if (seqs_begin == seqs_end)
- return target;
-
- // Execute merge; maybe parallel, depending on the number of merged
- // elements and the number of sequences and global thresholds in
- // Settings.
- if ((seqs_end - seqs_begin > 1) &&
- _GLIBCXX_PARALLEL_CONDITION(
- ((seqs_end - seqs_begin) >=
- __gnu_parallel::_Settings::get().multiway_merge_minimal_k)
- && ((sequence_index_t)length >=
- __gnu_parallel::_Settings::get().multiway_merge_minimal_n)))
- return parallel_multiway_merge
- </* stable = */ true, /* sentinels = */ false>(
- seqs_begin, seqs_end,
- target,
- multiway_merge_sampling_splitting</* stable = */ true,
- typename std::iterator_traits<RandomAccessIteratorPairIterator>
- ::value_type*, Comparator, _DifferenceTp>,
- static_cast<difference_type>(length), comp, tag.get_num_threads());
- else
- return sequential_multiway_merge
- </* stable = */ true, /* sentinels = */ false>(
- seqs_begin, seqs_end,
- target, *(seqs_begin->second), length, comp);
-}
-
-
-// public interface
-template<
- typename RandomAccessIteratorPairIterator
- , typename RandomAccessIteratorOut
- , typename _DifferenceTp
- , typename Comparator>
-RandomAccessIteratorOut
-stable_multiway_merge(RandomAccessIteratorPairIterator seqs_begin
- , RandomAccessIteratorPairIterator seqs_end
- , RandomAccessIteratorOut target
- , _DifferenceTp length, Comparator comp
- , parallel_tag tag = parallel_tag(0))
-{
- return stable_multiway_merge(seqs_begin, seqs_end, target, length, comp,
- exact_tag(tag.get_num_threads()));
-}
-
-// public interface
-template<
- typename RandomAccessIteratorPairIterator
- , typename RandomAccessIteratorOut
- , typename _DifferenceTp
- , typename Comparator>
-RandomAccessIteratorOut
-stable_multiway_merge(RandomAccessIteratorPairIterator seqs_begin
- , RandomAccessIteratorPairIterator seqs_end
- , RandomAccessIteratorOut target
- , _DifferenceTp length, Comparator comp
- , default_parallel_tag tag)
-{
- return stable_multiway_merge(seqs_begin, seqs_end, target, length, comp,
- exact_tag(tag.get_num_threads()));
-}
-
-/**
- * @brief Multiway Merge Frontend.
- *
- * Merge the sequences specified by seqs_begin and seqs_end into
- * target. seqs_begin and seqs_end must point to a sequence of
- * pairs. These pairs must contain an iterator to the beginning
- * of a sequence in their first entry and an iterator the end of
- * the same sequence in their second entry.
- *
- * Ties are broken arbitrarily. See stable_multiway_merge for a variant
- * that breaks ties by sequence number but is slower.
- *
- * The first entries of the pairs (i.e. the begin iterators) will be moved
- * forward accordingly.
- *
- * The output sequence has to provide enough space for all elements
- * that are written to it.
- *
- * This function will merge the input sequences:
- *
- * - not stable
- * - parallel, depending on the input size and Settings
- * - using sampling for splitting
- * - using sentinels
- *
- * You have to take care that the element the end iterator points to is
- * readable and contains a value that is greater than any other non-sentinel
- * value in all sequences.
- *
- * Example:
- *
- * <pre>
- * int sequences[10][11];
- * for (int i = 0; i < 10; ++i)
- * for (int j = 0; i < 11; ++j)
- * sequences[i][j] = j; // last one is sentinel!
- *
- * int out[33];
- * std::vector<std::pair<int*> > seqs;
- * for (int i = 0; i < 10; ++i)
- * { seqs.push(std::make_pair<int*>(sequences[i], sequences[i] + 10)) }
- *
- * multiway_merge(seqs.begin(), seqs.end(), target, std::less<int>(), 33);
- * </pre>
- *
- * @pre All input sequences must be sorted.
- * @pre Target must provide enough space to merge out length elements or
- * the number of elements in all sequences, whichever is smaller.
- * @pre For each @c i, @c seqs_begin[i].second must be the end
- * marker of the sequence, but also reference the one more sentinel
- * element.
- *
- * @post [target, return value) contains merged elements from the
- * input sequences.
- * @post return value - target = min(length, number of elements in all
- * sequences).
- *
- * @see stable_multiway_merge_sentinels
- *
- * @param RandomAccessIteratorPairIterator iterator over sequence
- * of pairs of iterators
- * @param RandomAccessIteratorOut iterator over target sequence
- * @param _DifferenceTp difference type for the sequence
- * @param Comparator strict weak ordering type to compare elements
- * in sequences
- *
- * @param seqs_begin begin of sequence sequence
- * @param seqs_end end of sequence sequence
- * @param target target sequence to merge to.
- * @param comp strict weak ordering to use for element comparison.
- * @param length Maximum length to merge, possibly larger than the
- * number of elements available.
- *
- * @return end iterator of output sequence
- */
-// multiway_merge_sentinels
-// public interface
-template<
- typename RandomAccessIteratorPairIterator
- , typename RandomAccessIteratorOut
- , typename _DifferenceTp
- , typename Comparator>
-RandomAccessIteratorOut
-multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin
- , RandomAccessIteratorPairIterator seqs_end
- , RandomAccessIteratorOut target
- , _DifferenceTp length, Comparator comp
- , __gnu_parallel::sequential_tag)
-{
- typedef _DifferenceTp difference_type;
- _GLIBCXX_CALL(seqs_end - seqs_begin)
-
- // catch special case: no sequences
- if (seqs_begin == seqs_end)
- return target;
-
- // Execute multiway merge *sequentially*.
- return sequential_multiway_merge
- </* stable = */ false, /* sentinels = */ true>
- (seqs_begin, seqs_end,
- target, *(seqs_begin->second), length, comp);
-}
-
-// public interface
-template<
- typename RandomAccessIteratorPairIterator
- , typename RandomAccessIteratorOut
- , typename _DifferenceTp
- , typename Comparator>
-RandomAccessIteratorOut
-multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin
- , RandomAccessIteratorPairIterator seqs_end
- , RandomAccessIteratorOut target
- , _DifferenceTp length, Comparator comp
- , __gnu_parallel::exact_tag tag)
-{
- typedef _DifferenceTp difference_type;
- _GLIBCXX_CALL(seqs_end - seqs_begin)
-
- // catch special case: no sequences
- if (seqs_begin == seqs_end)
- return target;
-
- // Execute merge; maybe parallel, depending on the number of merged
- // elements and the number of sequences and global thresholds in
- // Settings.
- if ((seqs_end - seqs_begin > 1) &&
- _GLIBCXX_PARALLEL_CONDITION(
- ((seqs_end - seqs_begin) >=
- __gnu_parallel::_Settings::get().multiway_merge_minimal_k)
- && ((sequence_index_t)length >=
- __gnu_parallel::_Settings::get().multiway_merge_minimal_n)))
- return parallel_multiway_merge
- </* stable = */ false, /* sentinels = */ true>(
- seqs_begin, seqs_end,
- target,
- multiway_merge_exact_splitting</* stable = */ false,
- typename std::iterator_traits<RandomAccessIteratorPairIterator>
- ::value_type*, Comparator, _DifferenceTp>,
- static_cast<difference_type>(length), comp, tag.get_num_threads());
- else
- return sequential_multiway_merge
- </* stable = */ false, /* sentinels = */ true>(
- seqs_begin, seqs_end,
- target, *(seqs_begin->second), length, comp);
-}
-
-// public interface
-template<
- typename RandomAccessIteratorPairIterator
- , typename RandomAccessIteratorOut
- , typename _DifferenceTp
- , typename Comparator>
-RandomAccessIteratorOut
-multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin
- , RandomAccessIteratorPairIterator seqs_end
- , RandomAccessIteratorOut target
- , _DifferenceTp length, Comparator comp
- , sampling_tag tag)
-{
- typedef _DifferenceTp difference_type;
- _GLIBCXX_CALL(seqs_end - seqs_begin)
-
- // catch special case: no sequences
- if (seqs_begin == seqs_end)
- return target;
-
- // Execute merge; maybe parallel, depending on the number of merged
- // elements and the number of sequences and global thresholds in
- // Settings.
- if ((seqs_end - seqs_begin > 1) &&
- _GLIBCXX_PARALLEL_CONDITION(
- ((seqs_end - seqs_begin) >=
- __gnu_parallel::_Settings::get().multiway_merge_minimal_k)
- && ((sequence_index_t)length >=
- __gnu_parallel::_Settings::get().multiway_merge_minimal_n)))
- return parallel_multiway_merge
- </* stable = */ false, /* sentinels = */ true>
- (seqs_begin, seqs_end, target,
- multiway_merge_sampling_splitting</* stable = */ false,
- typename std::iterator_traits<RandomAccessIteratorPairIterator>
- ::value_type*, Comparator, _DifferenceTp>,
- static_cast<difference_type>(length), comp, tag.get_num_threads());
- else
- return sequential_multiway_merge
- </* stable = */false, /* sentinels = */ true>(
- seqs_begin, seqs_end,
- target, *(seqs_begin->second), length, comp);
-}
-
-// public interface
-template<
- typename RandomAccessIteratorPairIterator
- , typename RandomAccessIteratorOut
- , typename _DifferenceTp
- , typename Comparator>
-RandomAccessIteratorOut
-multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin
- , RandomAccessIteratorPairIterator seqs_end
- , RandomAccessIteratorOut target
- , _DifferenceTp length, Comparator comp
- , parallel_tag tag = parallel_tag(0))
-{
- return multiway_merge_sentinels(seqs_begin, seqs_end, target, length, comp,
- exact_tag(tag.get_num_threads()));
-}
-
-// public interface
-template<
- typename RandomAccessIteratorPairIterator
- , typename RandomAccessIteratorOut
- , typename _DifferenceTp
- , typename Comparator>
-RandomAccessIteratorOut
-multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin
- , RandomAccessIteratorPairIterator seqs_end
- , RandomAccessIteratorOut target
- , _DifferenceTp length, Comparator comp
- , default_parallel_tag tag)
-{
- return multiway_merge_sentinels(seqs_begin, seqs_end, target, length, comp,
- exact_tag(tag.get_num_threads()));
-}
-
-// stable_multiway_merge_sentinels
-// public interface
-template<
- typename RandomAccessIteratorPairIterator
- , typename RandomAccessIteratorOut
- , typename _DifferenceTp
- , typename Comparator>
-RandomAccessIteratorOut
-stable_multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin
- , RandomAccessIteratorPairIterator seqs_end
- , RandomAccessIteratorOut target
- , _DifferenceTp length, Comparator comp
- , __gnu_parallel::sequential_tag)
-{
- typedef _DifferenceTp difference_type;
- _GLIBCXX_CALL(seqs_end - seqs_begin)
-
- // catch special case: no sequences
- if (seqs_begin == seqs_end)
- return target;
-
- // Execute multiway merge *sequentially*.
- return sequential_multiway_merge
- </* stable = */ true, /* sentinels = */ true>
- (seqs_begin, seqs_end, target, *(seqs_begin->second), length, comp);
-}
-
-// public interface
-template<
- typename RandomAccessIteratorPairIterator
- , typename RandomAccessIteratorOut
- , typename _DifferenceTp
- , typename Comparator>
-RandomAccessIteratorOut
-stable_multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin
- , RandomAccessIteratorPairIterator seqs_end
- , RandomAccessIteratorOut target
- , _DifferenceTp length, Comparator comp
- , __gnu_parallel::exact_tag tag)
-{
- typedef _DifferenceTp difference_type;
- _GLIBCXX_CALL(seqs_end - seqs_begin)
-
- // catch special case: no sequences
- if (seqs_begin == seqs_end)
- return target;
-
- // Execute merge; maybe parallel, depending on the number of merged
- // elements and the number of sequences and global thresholds in
- // Settings.
- if ((seqs_end - seqs_begin > 1) &&
- _GLIBCXX_PARALLEL_CONDITION(
- ((seqs_end - seqs_begin) >=
- __gnu_parallel::_Settings::get().multiway_merge_minimal_k)
- && ((sequence_index_t)length >=
- __gnu_parallel::_Settings::get().multiway_merge_minimal_n)))
- return parallel_multiway_merge
- </* stable = */ true, /* sentinels = */ true>(
- seqs_begin, seqs_end,
- target,
- multiway_merge_exact_splitting</* stable = */ true,
- typename std::iterator_traits<RandomAccessIteratorPairIterator>
- ::value_type*, Comparator, _DifferenceTp>,
- static_cast<difference_type>(length), comp, tag.get_num_threads());
- else
- return sequential_multiway_merge
- </* stable = */ true, /* sentinels = */ true>(
- seqs_begin, seqs_end, target, *(seqs_begin->second), length, comp);
-}
-
-// public interface
-template<
- typename RandomAccessIteratorPairIterator
- , typename RandomAccessIteratorOut
- , typename _DifferenceTp
- , typename Comparator>
-RandomAccessIteratorOut
-stable_multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin
- , RandomAccessIteratorPairIterator seqs_end
- , RandomAccessIteratorOut target
- , _DifferenceTp length, Comparator comp
- , sampling_tag tag)
-{
- typedef _DifferenceTp difference_type;
- _GLIBCXX_CALL(seqs_end - seqs_begin)
-
- // catch special case: no sequences
- if (seqs_begin == seqs_end)
- return target;
-
- // Execute merge; maybe parallel, depending on the number of merged
- // elements and the number of sequences and global thresholds in
- // Settings.
- if ((seqs_end - seqs_begin > 1) &&
- _GLIBCXX_PARALLEL_CONDITION(
- ((seqs_end - seqs_begin) >=
- __gnu_parallel::_Settings::get().multiway_merge_minimal_k)
- && ((sequence_index_t)length >=
- __gnu_parallel::_Settings::get().multiway_merge_minimal_n)))
- return parallel_multiway_merge
- </* stable = */ true, /* sentinels = */ true>(
- seqs_begin, seqs_end,
- target,
- multiway_merge_sampling_splitting</* stable = */ true,
- typename std::iterator_traits<RandomAccessIteratorPairIterator>
- ::value_type*, Comparator, _DifferenceTp>,
- static_cast<difference_type>(length), comp, tag.get_num_threads());
- else
- return sequential_multiway_merge
- </* stable = */ true, /* sentinels = */ true>(
- seqs_begin, seqs_end,
- target, *(seqs_begin->second), length, comp);
-}
-
-// public interface
-template<
- typename RandomAccessIteratorPairIterator
- , typename RandomAccessIteratorOut
- , typename _DifferenceTp
- , typename Comparator>
-RandomAccessIteratorOut
-stable_multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin
- , RandomAccessIteratorPairIterator seqs_end
- , RandomAccessIteratorOut target
- , _DifferenceTp length, Comparator comp
- , parallel_tag tag = parallel_tag(0))
-{
- return stable_multiway_merge_sentinels(seqs_begin, seqs_end, target, length, comp,
- exact_tag(tag.get_num_threads()));
-}
-
-// public interface
-template<
- typename RandomAccessIteratorPairIterator
- , typename RandomAccessIteratorOut
- , typename _DifferenceTp
- , typename Comparator>
-RandomAccessIteratorOut
-stable_multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin
- , RandomAccessIteratorPairIterator seqs_end
- , RandomAccessIteratorOut target
- , _DifferenceTp length, Comparator comp
- , default_parallel_tag tag)
-{
- return stable_multiway_merge_sentinels(seqs_begin, seqs_end, target, length, comp,
- exact_tag(tag.get_num_threads()));
-}
-
-}; // namespace __gnu_parallel
-
-#endif /* _GLIBCXX_PARALLEL_MULTIWAY_MERGE_H */