|
- // -*- C++ -*-
-
- // Copyright (C) 2007-2020 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>
- #include <parallel/multiseq_selection.h>
- #if _GLIBCXX_PARALLEL_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
- {
- template<typename _RAIter1, typename _RAIter2, typename _OutputIterator,
- typename _DifferenceTp, typename _Compare>
- _OutputIterator
- __merge_advance(_RAIter1&, _RAIter1, _RAIter2&, _RAIter2,
- _OutputIterator, _DifferenceTp, _Compare);
-
- /** @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 _RAIter is not possible since
- * _RAIter need not be a class.
- */
- template<typename _RAIter, typename _Compare>
- class _GuardedIterator
- {
- private:
- /** @brief Current iterator __position. */
- _RAIter _M_current;
-
- /** @brief End iterator of the sequence. */
- _RAIter _M_end;
-
- /** @brief _Compare. */
- _Compare& __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. */
- _GuardedIterator(_RAIter __begin, _RAIter __end, _Compare& __comp)
- : _M_current(__begin), _M_end(__end), __comp(__comp)
- { }
-
- /** @brief Pre-increment operator.
- * @return This. */
- _GuardedIterator<_RAIter, _Compare>&
- operator++()
- {
- ++_M_current;
- return *this;
- }
-
- /** @brief Dereference operator.
- * @return Referenced element. */
- typename std::iterator_traits<_RAIter>::value_type&
- operator*()
- { return *_M_current; }
-
- /** @brief Convert to wrapped iterator.
- * @return Wrapped iterator. */
- operator _RAIter()
- { return _M_current; }
-
- /** @brief Compare two elements referenced by guarded iterators.
- * @param __bi1 First iterator.
- * @param __bi2 Second iterator.
- * @return @c true if less. */
- friend bool
- operator<(_GuardedIterator<_RAIter, _Compare>& __bi1,
- _GuardedIterator<_RAIter, _Compare>& __bi2)
- {
- if (__bi1._M_current == __bi1._M_end) // __bi1 is sup
- return __bi2._M_current == __bi2._M_end; // __bi2 is not sup
- if (__bi2._M_current == __bi2._M_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. */
- friend bool
- operator<=(_GuardedIterator<_RAIter, _Compare>& __bi1,
- _GuardedIterator<_RAIter, _Compare>& __bi2)
- {
- if (__bi2._M_current == __bi2._M_end) // __bi1 is sup
- return __bi1._M_current != __bi1._M_end; // __bi2 is not sup
- if (__bi1._M_current == __bi1._M_end) // __bi2 is sup
- return false;
- return !(__bi1.__comp)(*__bi2, *__bi1); // normal compare
- }
- };
-
- template<typename _RAIter, typename _Compare>
- class _UnguardedIterator
- {
- private:
- /** @brief Current iterator __position. */
- _RAIter _M_current;
- /** @brief _Compare. */
- _Compare& __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. */
- _UnguardedIterator(_RAIter __begin,
- _RAIter /* __end */, _Compare& __comp)
- : _M_current(__begin), __comp(__comp)
- { }
-
- /** @brief Pre-increment operator.
- * @return This. */
- _UnguardedIterator<_RAIter, _Compare>&
- operator++()
- {
- ++_M_current;
- return *this;
- }
-
- /** @brief Dereference operator.
- * @return Referenced element. */
- typename std::iterator_traits<_RAIter>::value_type&
- operator*()
- { return *_M_current; }
-
- /** @brief Convert to wrapped iterator.
- * @return Wrapped iterator. */
- operator _RAIter()
- { return _M_current; }
-
- /** @brief Compare two elements referenced by unguarded iterators.
- * @param __bi1 First iterator.
- * @param __bi2 Second iterator.
- * @return @c true if less. */
- friend bool
- operator<(_UnguardedIterator<_RAIter, _Compare>& __bi1,
- _UnguardedIterator<_RAIter, _Compare>& __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. */
- friend bool
- operator<=(_UnguardedIterator<_RAIter, _Compare>& __bi1,
- _UnguardedIterator<_RAIter, _Compare>& __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 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 @a not 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 of 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 _Cp> class iterator,
- typename _RAIterIterator,
- typename _RAIter3,
- typename _DifferenceTp,
- typename _Compare>
- _RAIter3
- multiway_merge_3_variant(_RAIterIterator __seqs_begin,
- _RAIterIterator __seqs_end,
- _RAIter3 __target,
- _DifferenceTp __length, _Compare __comp)
- {
- _GLIBCXX_CALL(__length);
-
- typedef _DifferenceTp _DifferenceType;
-
- typedef typename std::iterator_traits<_RAIterIterator>
- ::value_type::first_type
- _RAIter1;
- typedef typename std::iterator_traits<_RAIter1>::value_type
- _ValueType;
-
- if (__length == 0)
- return __target;
-
- #if _GLIBCXX_PARALLEL_ASSERTIONS
- _DifferenceTp __orig_length = __length;
- #endif
-
- iterator<_RAIter1, _Compare>
- __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_PARALLEL_ASSERTIONS
- _GLIBCXX_PARALLEL_ASSERT(
- ((_RAIter1)__seq0 - __seqs_begin[0].first) +
- ((_RAIter1)__seq1 - __seqs_begin[1].first) +
- ((_RAIter1)__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 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 @a not 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 of 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 _Cp> class iterator,
- typename _RAIterIterator,
- typename _RAIter3,
- typename _DifferenceTp,
- typename _Compare>
- _RAIter3
- multiway_merge_4_variant(_RAIterIterator __seqs_begin,
- _RAIterIterator __seqs_end,
- _RAIter3 __target,
- _DifferenceTp __length, _Compare __comp)
- {
- _GLIBCXX_CALL(__length);
- typedef _DifferenceTp _DifferenceType;
-
- typedef typename std::iterator_traits<_RAIterIterator>
- ::value_type::first_type
- _RAIter1;
- typedef typename std::iterator_traits<_RAIter1>::value_type
- _ValueType;
-
- iterator<_RAIter1, _Compare>
- __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 of 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 _RAIterIterator,
- typename _RAIter3,
- typename _DifferenceTp,
- typename _Compare>
- _RAIter3
- multiway_merge_loser_tree(_RAIterIterator __seqs_begin,
- _RAIterIterator __seqs_end,
- _RAIter3 __target,
- _DifferenceTp __length, _Compare __comp)
- {
- _GLIBCXX_CALL(__length)
-
- typedef _DifferenceTp _DifferenceType;
- typedef typename std::iterator_traits<_RAIterIterator>
- ::difference_type _SeqNumber;
- typedef typename std::iterator_traits<_RAIterIterator>
- ::value_type::first_type
- _RAIter1;
- typedef typename std::iterator_traits<_RAIter1>::value_type
- _ValueType;
-
- _SeqNumber __k = static_cast<_SeqNumber>(__seqs_end - __seqs_begin);
-
- _LT __lt(__k, __comp);
-
- // Default value for potentially non-default-constructible types.
- _ValueType* __arbitrary_element = 0;
-
- for (_SeqNumber __t = 0; __t < __k; ++__t)
- {
- if(!__arbitrary_element
- && _GLIBCXX_PARALLEL_LENGTH(__seqs_begin[__t]) > 0)
- __arbitrary_element = &(*__seqs_begin[__t].first);
- }
-
- for (_SeqNumber __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();
-
- _SeqNumber __source;
-
- for (_DifferenceType __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 of 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 _RAIterIterator,
- typename _RAIter3,
- typename _DifferenceTp, typename _Compare>
- _RAIter3
- multiway_merge_loser_tree_unguarded(_RAIterIterator __seqs_begin,
- _RAIterIterator __seqs_end,
- _RAIter3 __target,
- const typename std::iterator_traits<typename std::iterator_traits<
- _RAIterIterator>::value_type::first_type>::value_type&
- __sentinel,
- _DifferenceTp __length,
- _Compare __comp)
- {
- _GLIBCXX_CALL(__length)
- typedef _DifferenceTp _DifferenceType;
-
- typedef typename std::iterator_traits<_RAIterIterator>
- ::difference_type _SeqNumber;
- typedef typename std::iterator_traits<_RAIterIterator>
- ::value_type::first_type
- _RAIter1;
- typedef typename std::iterator_traits<_RAIter1>::value_type
- _ValueType;
-
- _SeqNumber __k = __seqs_end - __seqs_begin;
-
- _LT __lt(__k, __sentinel, __comp);
-
- for (_SeqNumber __t = 0; __t < __k; ++__t)
- {
- #if _GLIBCXX_PARALLEL_ASSERTIONS
- _GLIBCXX_PARALLEL_ASSERT(__seqs_begin[__t].first
- != __seqs_begin[__t].second);
- #endif
- __lt.__insert_start(*__seqs_begin[__t].first, __t, false);
- }
-
- __lt.__init();
-
- _SeqNumber __source;
-
- #if _GLIBCXX_PARALLEL_ASSERTIONS
- _DifferenceType __i = 0;
- #endif
-
- _RAIter3 __target_end = __target + __length;
- while (__target < __target_end)
- {
- // Take out.
- __source = __lt.__get_min_source();
-
- #if _GLIBCXX_PARALLEL_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_PARALLEL_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.
- *
- * @tparam _UnguardedLoserTree Loser Tree variant to use for the unguarded
- * 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 of 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 _RAIterIterator,
- typename _RAIter3,
- typename _DifferenceTp,
- typename _Compare>
- _RAIter3
- multiway_merge_loser_tree_sentinel(_RAIterIterator __seqs_begin,
- _RAIterIterator __seqs_end,
- _RAIter3 __target,
- const typename std::iterator_traits<typename std::iterator_traits<
- _RAIterIterator>::value_type::first_type>::value_type&
- __sentinel,
- _DifferenceTp __length,
- _Compare __comp)
- {
- _GLIBCXX_CALL(__length)
-
- typedef _DifferenceTp _DifferenceType;
- typedef std::iterator_traits<_RAIterIterator> _TraitsType;
- typedef typename std::iterator_traits<_RAIterIterator>
- ::value_type::first_type
- _RAIter1;
- typedef typename std::iterator_traits<_RAIter1>::value_type
- _ValueType;
-
- _RAIter3 __target_end;
-
- for (_RAIterIterator __s = __seqs_begin; __s != __seqs_end; ++__s)
- // Move the sequence ends to the sentinel. 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_PARALLEL_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 (_RAIterIterator __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 "_M_use_pointer" is used to determine whether to use pointers
- * in he 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 _LoserTreeTraits<int>
- * { static const bool _M_use_pointer = false; };
- *
- * template<>
- * struct _LoserTreeTraits<heavyweight_type>
- * { static const bool _M_use_pointer = true; };
- *
- * @param _Tp type to give the loser tree traits for.
- */
- template <typename _Tp>
- struct _LoserTreeTraits
- {
- /**
- * @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 _M_use_pointer = (sizeof(_Tp) > 4 * sizeof(_Tp*));
- };
-
- /**
- * @brief Switch for 3-way merging with __sentinels turned off.
- *
- * Note that 3-way merging is always stable!
- */
- template<bool __sentinels /*default == false*/,
- typename _RAIterIterator,
- typename _RAIter3,
- typename _DifferenceTp,
- typename _Compare>
- struct __multiway_merge_3_variant_sentinel_switch
- {
- _RAIter3
- operator()(_RAIterIterator __seqs_begin,
- _RAIterIterator __seqs_end,
- _RAIter3 __target,
- _DifferenceTp __length, _Compare __comp)
- { return multiway_merge_3_variant<_GuardedIterator>
- (__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 _RAIterIterator,
- typename _RAIter3,
- typename _DifferenceTp,
- typename _Compare>
- struct __multiway_merge_3_variant_sentinel_switch<true, _RAIterIterator,
- _RAIter3, _DifferenceTp,
- _Compare>
- {
- _RAIter3
- operator()(_RAIterIterator __seqs_begin,
- _RAIterIterator __seqs_end,
- _RAIter3 __target,
- _DifferenceTp __length, _Compare __comp)
- { return multiway_merge_3_variant<_UnguardedIterator>
- (__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 _RAIterIterator,
- typename _RAIter3,
- typename _DifferenceTp,
- typename _Compare>
- struct __multiway_merge_4_variant_sentinel_switch
- {
- _RAIter3
- operator()(_RAIterIterator __seqs_begin,
- _RAIterIterator __seqs_end,
- _RAIter3 __target,
- _DifferenceTp __length, _Compare __comp)
- { return multiway_merge_4_variant<_GuardedIterator>
- (__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 _RAIterIterator,
- typename _RAIter3,
- typename _DifferenceTp,
- typename _Compare>
- struct __multiway_merge_4_variant_sentinel_switch<true, _RAIterIterator,
- _RAIter3, _DifferenceTp,
- _Compare>
- {
- _RAIter3
- operator()(_RAIterIterator __seqs_begin,
- _RAIterIterator __seqs_end,
- _RAIter3 __target,
- _DifferenceTp __length, _Compare __comp)
- { return multiway_merge_4_variant<_UnguardedIterator>
- (__seqs_begin, __seqs_end, __target, __length, __comp); }
- };
-
- /**
- * @brief Switch for k-way merging with __sentinels turned on.
- */
- template<bool __sentinels,
- bool __stable,
- typename _RAIterIterator,
- typename _RAIter3,
- typename _DifferenceTp,
- typename _Compare>
- struct __multiway_merge_k_variant_sentinel_switch
- {
- _RAIter3
- operator()(_RAIterIterator __seqs_begin,
- _RAIterIterator __seqs_end,
- _RAIter3 __target,
- const typename std::iterator_traits<typename std::iterator_traits<
- _RAIterIterator>::value_type::first_type>::value_type&
- __sentinel,
- _DifferenceTp __length, _Compare __comp)
- {
- typedef typename std::iterator_traits<_RAIterIterator>
- ::value_type::first_type
- _RAIter1;
- typedef typename std::iterator_traits<_RAIter1>::value_type
- _ValueType;
-
- return multiway_merge_loser_tree_sentinel<
- typename __gnu_cxx::__conditional_type<
- _LoserTreeTraits<_ValueType>::_M_use_pointer,
- _LoserTreePointerUnguarded<__stable, _ValueType, _Compare>,
- _LoserTreeUnguarded<__stable, _ValueType, _Compare>
- >::__type>
- (__seqs_begin, __seqs_end, __target, __sentinel, __length, __comp);
- }
- };
-
- /**
- * @brief Switch for k-way merging with __sentinels turned off.
- */
- template<bool __stable,
- typename _RAIterIterator,
- typename _RAIter3,
- typename _DifferenceTp,
- typename _Compare>
- struct __multiway_merge_k_variant_sentinel_switch<false, __stable,
- _RAIterIterator,
- _RAIter3, _DifferenceTp,
- _Compare>
- {
- _RAIter3
- operator()(_RAIterIterator __seqs_begin,
- _RAIterIterator __seqs_end,
- _RAIter3 __target,
- const typename std::iterator_traits<typename std::iterator_traits<
- _RAIterIterator>::value_type::first_type>::value_type&
- __sentinel,
- _DifferenceTp __length, _Compare __comp)
- {
- typedef typename std::iterator_traits<_RAIterIterator>
- ::value_type::first_type
- _RAIter1;
- typedef typename std::iterator_traits<_RAIter1>::value_type
- _ValueType;
-
- return multiway_merge_loser_tree<
- typename __gnu_cxx::__conditional_type<
- _LoserTreeTraits<_ValueType>::_M_use_pointer,
- _LoserTreePointer<__stable, _ValueType, _Compare>,
- _LoserTree<__stable, _ValueType, _Compare>
- >::__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 of output sequence.
- * @param __comp Comparator.
- * @param __length Maximum length to merge, possibly larger than the
- * number of elements available.
- * @param __sentinel The sequences have __a __sentinel element.
- * @return End iterator of output sequence. */
- template<bool __stable,
- bool __sentinels,
- typename _RAIterIterator,
- typename _RAIter3,
- typename _DifferenceTp,
- typename _Compare>
- _RAIter3
- __sequential_multiway_merge(_RAIterIterator __seqs_begin,
- _RAIterIterator __seqs_end,
- _RAIter3 __target,
- const typename std::iterator_traits<typename std::iterator_traits<
- _RAIterIterator>::value_type::first_type>::value_type&
- __sentinel,
- _DifferenceTp __length, _Compare __comp)
- {
- _GLIBCXX_CALL(__length)
-
- typedef _DifferenceTp _DifferenceType;
- typedef typename std::iterator_traits<_RAIterIterator>
- ::difference_type _SeqNumber;
- typedef typename std::iterator_traits<_RAIterIterator>
- ::value_type::first_type
- _RAIter1;
- typedef typename std::iterator_traits<_RAIter1>::value_type
- _ValueType;
-
- #if _GLIBCXX_PARALLEL_ASSERTIONS
- for (_RAIterIterator __s = __seqs_begin; __s != __seqs_end; ++__s)
- {
- _GLIBCXX_PARALLEL_ASSERT(__is_sorted((*__s).first,
- (*__s).second, __comp));
- }
- #endif
-
- _DifferenceTp __total_length = 0;
- for (_RAIterIterator __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;
-
- _RAIter3 __return_target = __target;
- _SeqNumber __k = static_cast<_SeqNumber>(__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, _RAIterIterator, _RAIter3, _DifferenceTp, _Compare>()
- (__seqs_begin, __seqs_end, __target, __length, __comp);
- break;
- case 4:
- __return_target = __multiway_merge_4_variant_sentinel_switch
- <__sentinels, _RAIterIterator, _RAIter3, _DifferenceTp, _Compare>()
- (__seqs_begin, __seqs_end, __target, __length, __comp);
- break;
- default:
- __return_target = __multiway_merge_k_variant_sentinel_switch
- <__sentinels, __stable, _RAIterIterator, _RAIter3, _DifferenceTp,
- _Compare>()
- (__seqs_begin, __seqs_end, __target, __sentinel, __length, __comp);
- break;
- }
- #if _GLIBCXX_PARALLEL_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 _RAIter, class _StrictWeakOrdering>
- struct _SamplingSorter
- {
- void
- operator()(_RAIter __first, _RAIter __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 _RAIter, class _StrictWeakOrdering>
- struct _SamplingSorter<false, _RAIter, _StrictWeakOrdering>
- {
- void
- operator()(_RAIter __first, _RAIter __last, _StrictWeakOrdering __comp)
- { __gnu_sequential::sort(__first, __last, __comp); }
- };
-
- /**
- * @brief Sampling based splitting for parallel multiway-merge routine.
- */
- template<bool __stable,
- typename _RAIterIterator,
- typename _Compare,
- typename _DifferenceType>
- void
- multiway_merge_sampling_splitting(_RAIterIterator __seqs_begin,
- _RAIterIterator __seqs_end,
- _DifferenceType __length,
- _DifferenceType __total_length,
- _Compare __comp,
- std::vector<std::pair<_DifferenceType, _DifferenceType> > *__pieces)
- {
- typedef typename std::iterator_traits<_RAIterIterator>
- ::difference_type _SeqNumber;
- typedef typename std::iterator_traits<_RAIterIterator>
- ::value_type::first_type
- _RAIter1;
- typedef typename std::iterator_traits<_RAIter1>::value_type
- _ValueType;
-
- // __k sequences.
- const _SeqNumber __k
- = static_cast<_SeqNumber>(__seqs_end - __seqs_begin);
-
- const _ThreadIndex __num_threads = omp_get_num_threads();
-
- const _DifferenceType __num_samples =
- __gnu_parallel::_Settings::get().merge_oversampling * __num_threads;
-
- _ValueType* __samples = static_cast<_ValueType*>
- (::operator new(sizeof(_ValueType) * __k * __num_samples));
- // Sample.
- for (_SeqNumber __s = 0; __s < __k; ++__s)
- for (_DifferenceType __i = 0; __i < __num_samples; ++__i)
- {
- _DifferenceType sample_index = static_cast<_DifferenceType>
- (_GLIBCXX_PARALLEL_LENGTH(__seqs_begin[__s])
- * (double(__i + 1) / (__num_samples + 1))
- * (double(__length) / __total_length));
- new(&(__samples[__s * __num_samples + __i]))
- _ValueType(__seqs_begin[__s].first[sample_index]);
- }
-
- // Sort stable or non-stable, depending on value of template parameter
- // "__stable".
- _SamplingSorter<__stable, _ValueType*, _Compare>()
- (__samples, __samples + (__num_samples * __k), __comp);
-
- for (_ThreadIndex __slab = 0; __slab < __num_threads; ++__slab)
- // For each slab / processor.
- for (_SeqNumber __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]);
- }
-
- for (_SeqNumber __s = 0; __s < __k; ++__s)
- for (_DifferenceType __i = 0; __i < __num_samples; ++__i)
- __samples[__s * __num_samples + __i].~_ValueType();
- ::operator delete(__samples);
- }
-
- /**
- * @brief Exact splitting for parallel multiway-merge routine.
- *
- * None of the passed sequences may be empty.
- */
- template<bool __stable,
- typename _RAIterIterator,
- typename _Compare,
- typename _DifferenceType>
- void
- multiway_merge_exact_splitting(_RAIterIterator __seqs_begin,
- _RAIterIterator __seqs_end,
- _DifferenceType __length,
- _DifferenceType __total_length,
- _Compare __comp,
- std::vector<std::pair<_DifferenceType, _DifferenceType> > *__pieces)
- {
- typedef typename std::iterator_traits<_RAIterIterator>
- ::difference_type _SeqNumber;
- typedef typename std::iterator_traits<_RAIterIterator>
- ::value_type::first_type
- _RAIter1;
-
- const bool __tight = (__total_length == __length);
-
- // __k sequences.
- const _SeqNumber __k = __seqs_end - __seqs_begin;
-
- const _ThreadIndex __num_threads = omp_get_num_threads();
-
- // (Settings::multiway_merge_splitting
- // == __gnu_parallel::_Settings::EXACT).
- std::vector<_RAIter1>* __offsets =
- new std::vector<_RAIter1>[__num_threads];
- std::vector<std::pair<_RAIter1, _RAIter1> > __se(__k);
-
- copy(__seqs_begin, __seqs_end, __se.begin());
-
- _DifferenceType* __borders =
- new _DifferenceType[__num_threads + 1];
- __equally_split(__length, __num_threads, __borders);
-
- for (_ThreadIndex __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(),
- _DifferenceType(__length),
- __offsets[__num_threads - 1].begin(),
- __comp);
- }
- }
- delete[] __borders;
-
- for (_ThreadIndex __slab = 0; __slab < __num_threads; ++__slab)
- {
- // For each slab / processor.
- for (_SeqNumber __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.
- *
- * @tparam _Splitter functor to split input (either __exact or sampling based)
- * @tparam __stable Stable merging incurs a performance penalty.
- * @tparam __sentinel Ignored.
- *
- * @param __seqs_begin Begin iterator of iterator pair input sequence.
- * @param __seqs_end End iterator of iterator pair input sequence.
- * @param __target Begin iterator of output sequence.
- * @param __comp Comparator.
- * @param __length Maximum length to merge, possibly larger than the
- * number of elements available.
- * @return End iterator of output sequence.
- */
- template<bool __stable,
- bool __sentinels,
- typename _RAIterIterator,
- typename _RAIter3,
- typename _DifferenceTp,
- typename _Splitter,
- typename _Compare>
- _RAIter3
- parallel_multiway_merge(_RAIterIterator __seqs_begin,
- _RAIterIterator __seqs_end,
- _RAIter3 __target,
- _Splitter __splitter,
- _DifferenceTp __length,
- _Compare __comp,
- _ThreadIndex __num_threads)
- {
- #if _GLIBCXX_PARALLEL_ASSERTIONS
- _GLIBCXX_PARALLEL_ASSERT(__seqs_end - __seqs_begin > 1);
- #endif
-
- _GLIBCXX_CALL(__length)
-
- typedef _DifferenceTp _DifferenceType;
- typedef typename std::iterator_traits<_RAIterIterator>
- ::difference_type _SeqNumber;
- typedef typename std::iterator_traits<_RAIterIterator>
- ::value_type::first_type
- _RAIter1;
- typedef typename
- std::iterator_traits<_RAIter1>::value_type _ValueType;
-
- // Leave only non-empty sequences.
- typedef std::pair<_RAIter1, _RAIter1> seq_type;
- seq_type* __ne_seqs = new seq_type[__seqs_end - __seqs_begin];
- _SeqNumber __k = 0;
- _DifferenceType __total_length = 0;
- for (_RAIterIterator __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<_DifferenceType, _DifferenceType> >* __pieces;
-
- __num_threads = static_cast<_ThreadIndex>
- (std::min<_DifferenceType>(__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<_DifferenceType, _DifferenceType> >[__num_threads];
- for (_ThreadIndex __s = 0; __s < __num_threads; ++__s)
- __pieces[__s].resize(__k);
-
- _DifferenceType __num_samples =
- __gnu_parallel::_Settings::get().merge_oversampling
- * __num_threads;
-
- __splitter(__ne_seqs, __ne_seqs + __k, __length, __total_length,
- __comp, __pieces);
- } //single
-
- _ThreadIndex __iam = omp_get_thread_num();
-
- _DifferenceType __target_position = 0;
-
- for (_SeqNumber __c = 0; __c < __k; ++__c)
- __target_position += __pieces[__iam][__c].first;
-
- seq_type* __chunks = new seq_type[__k];
-
- for (_SeqNumber __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_PARALLEL_ASSERTIONS
- _GLIBCXX_PARALLEL_ASSERT(
- __is_sorted(__target, __target + __length, __comp));
- #endif
-
- __k = 0;
- // Update ends of sequences.
- for (_RAIterIterator __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 _M_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).
- *
- * @tparam _RAIterPairIterator iterator over sequence
- * of pairs of iterators
- * @tparam _RAIterOut iterator over target sequence
- * @tparam _DifferenceTp difference type for the sequence
- * @tparam _Compare strict weak ordering type to compare elements
- * in sequences
- *
- * @param __seqs_begin __begin of sequence __sequence
- * @param __seqs_end _M_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 _M_end iterator of output sequence
- */
- // multiway_merge
- // public interface
- template<typename _RAIterPairIterator,
- typename _RAIterOut,
- typename _DifferenceTp,
- typename _Compare>
- _RAIterOut
- multiway_merge(_RAIterPairIterator __seqs_begin,
- _RAIterPairIterator __seqs_end,
- _RAIterOut __target,
- _DifferenceTp __length, _Compare __comp,
- __gnu_parallel::sequential_tag)
- {
- typedef _DifferenceTp _DifferenceType;
- _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 _RAIterPairIterator,
- typename _RAIterOut,
- typename _DifferenceTp,
- typename _Compare>
- _RAIterOut
- multiway_merge(_RAIterPairIterator __seqs_begin,
- _RAIterPairIterator __seqs_end,
- _RAIterOut __target,
- _DifferenceTp __length, _Compare __comp,
- __gnu_parallel::exact_tag __tag)
- {
- typedef _DifferenceTp _DifferenceType;
- _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)
- && ((_SequenceIndex)__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<_RAIterPairIterator>
- ::value_type*, _Compare, _DifferenceTp>,
- static_cast<_DifferenceType>(__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 _RAIterPairIterator,
- typename _RAIterOut,
- typename _DifferenceTp,
- typename _Compare>
- _RAIterOut
- multiway_merge(_RAIterPairIterator __seqs_begin,
- _RAIterPairIterator __seqs_end,
- _RAIterOut __target,
- _DifferenceTp __length, _Compare __comp,
- __gnu_parallel::sampling_tag __tag)
- {
- typedef _DifferenceTp _DifferenceType;
- _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)
- && ((_SequenceIndex)__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<_RAIterPairIterator>
- ::value_type*, _Compare, _DifferenceTp>,
- static_cast<_DifferenceType>(__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 _RAIterPairIterator,
- typename _RAIterOut,
- typename _DifferenceTp,
- typename _Compare>
- _RAIterOut
- multiway_merge(_RAIterPairIterator __seqs_begin,
- _RAIterPairIterator __seqs_end,
- _RAIterOut __target,
- _DifferenceTp __length, _Compare __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 _RAIterPairIterator,
- typename _RAIterOut,
- typename _DifferenceTp,
- typename _Compare>
- _RAIterOut
- multiway_merge(_RAIterPairIterator __seqs_begin,
- _RAIterPairIterator __seqs_end,
- _RAIterOut __target,
- _DifferenceTp __length, _Compare __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 _RAIterPairIterator,
- typename _RAIterOut,
- typename _DifferenceTp,
- typename _Compare>
- _RAIterOut
- stable_multiway_merge(_RAIterPairIterator __seqs_begin,
- _RAIterPairIterator __seqs_end,
- _RAIterOut __target,
- _DifferenceTp __length, _Compare __comp,
- __gnu_parallel::sequential_tag)
- {
- typedef _DifferenceTp _DifferenceType;
- _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 _RAIterPairIterator,
- typename _RAIterOut,
- typename _DifferenceTp,
- typename _Compare>
- _RAIterOut
- stable_multiway_merge(_RAIterPairIterator __seqs_begin,
- _RAIterPairIterator __seqs_end,
- _RAIterOut __target,
- _DifferenceTp __length, _Compare __comp,
- __gnu_parallel::exact_tag __tag)
- {
- typedef _DifferenceTp _DifferenceType;
- _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)
- && ((_SequenceIndex)__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<_RAIterPairIterator>
- ::value_type*, _Compare, _DifferenceTp>,
- static_cast<_DifferenceType>(__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 _RAIterPairIterator,
- typename _RAIterOut,
- typename _DifferenceTp,
- typename _Compare>
- _RAIterOut
- stable_multiway_merge(_RAIterPairIterator __seqs_begin,
- _RAIterPairIterator __seqs_end,
- _RAIterOut __target,
- _DifferenceTp __length, _Compare __comp,
- sampling_tag __tag)
- {
- typedef _DifferenceTp _DifferenceType;
- _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)
- && ((_SequenceIndex)__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<_RAIterPairIterator>
- ::value_type*, _Compare, _DifferenceTp>,
- static_cast<_DifferenceType>(__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 _RAIterPairIterator,
- typename _RAIterOut,
- typename _DifferenceTp,
- typename _Compare>
- _RAIterOut
- stable_multiway_merge(_RAIterPairIterator __seqs_begin,
- _RAIterPairIterator __seqs_end,
- _RAIterOut __target,
- _DifferenceTp __length, _Compare __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 _RAIterPairIterator,
- typename _RAIterOut,
- typename _DifferenceTp,
- typename _Compare>
- _RAIterOut
- stable_multiway_merge(_RAIterPairIterator __seqs_begin,
- _RAIterPairIterator __seqs_end,
- _RAIterOut __target,
- _DifferenceTp __length, _Compare __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 _M_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 _M_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
- *
- * @tparam _RAIterPairIterator iterator over sequence
- * of pairs of iterators
- * @tparam _RAIterOut iterator over target sequence
- * @tparam _DifferenceTp difference type for the sequence
- * @tparam _Compare strict weak ordering type to compare elements
- * in sequences
- *
- * @param __seqs_begin __begin of sequence __sequence
- * @param __seqs_end _M_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 _M_end iterator of output sequence
- */
- // multiway_merge_sentinels
- // public interface
- template<typename _RAIterPairIterator,
- typename _RAIterOut,
- typename _DifferenceTp,
- typename _Compare>
- _RAIterOut
- multiway_merge_sentinels(_RAIterPairIterator __seqs_begin,
- _RAIterPairIterator __seqs_end,
- _RAIterOut __target,
- _DifferenceTp __length, _Compare __comp,
- __gnu_parallel::sequential_tag)
- {
- typedef _DifferenceTp _DifferenceType;
- _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 _RAIterPairIterator,
- typename _RAIterOut,
- typename _DifferenceTp,
- typename _Compare>
- _RAIterOut
- multiway_merge_sentinels(_RAIterPairIterator __seqs_begin,
- _RAIterPairIterator __seqs_end,
- _RAIterOut __target,
- _DifferenceTp __length, _Compare __comp,
- __gnu_parallel::exact_tag __tag)
- {
- typedef _DifferenceTp _DifferenceType;
- _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)
- && ((_SequenceIndex)__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<_RAIterPairIterator>
- ::value_type*, _Compare, _DifferenceTp>,
- static_cast<_DifferenceType>(__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 _RAIterPairIterator,
- typename _RAIterOut,
- typename _DifferenceTp,
- typename _Compare>
- _RAIterOut
- multiway_merge_sentinels(_RAIterPairIterator __seqs_begin,
- _RAIterPairIterator __seqs_end,
- _RAIterOut __target,
- _DifferenceTp __length, _Compare __comp,
- sampling_tag __tag)
- {
- typedef _DifferenceTp _DifferenceType;
- _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)
- && ((_SequenceIndex)__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<_RAIterPairIterator>
- ::value_type*, _Compare, _DifferenceTp>,
- static_cast<_DifferenceType>(__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 _RAIterPairIterator,
- typename _RAIterOut,
- typename _DifferenceTp,
- typename _Compare>
- _RAIterOut
- multiway_merge_sentinels(_RAIterPairIterator __seqs_begin,
- _RAIterPairIterator __seqs_end,
- _RAIterOut __target,
- _DifferenceTp __length, _Compare __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 _RAIterPairIterator,
- typename _RAIterOut,
- typename _DifferenceTp,
- typename _Compare>
- _RAIterOut
- multiway_merge_sentinels(_RAIterPairIterator __seqs_begin,
- _RAIterPairIterator __seqs_end,
- _RAIterOut __target,
- _DifferenceTp __length, _Compare __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 _RAIterPairIterator,
- typename _RAIterOut,
- typename _DifferenceTp,
- typename _Compare>
- _RAIterOut
- stable_multiway_merge_sentinels(_RAIterPairIterator __seqs_begin,
- _RAIterPairIterator __seqs_end,
- _RAIterOut __target,
- _DifferenceTp __length, _Compare __comp,
- __gnu_parallel::sequential_tag)
- {
- typedef _DifferenceTp _DifferenceType;
- _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 _RAIterPairIterator,
- typename _RAIterOut,
- typename _DifferenceTp,
- typename _Compare>
- _RAIterOut
- stable_multiway_merge_sentinels(_RAIterPairIterator __seqs_begin,
- _RAIterPairIterator __seqs_end,
- _RAIterOut __target,
- _DifferenceTp __length, _Compare __comp,
- __gnu_parallel::exact_tag __tag)
- {
- typedef _DifferenceTp _DifferenceType;
- _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)
- && ((_SequenceIndex)__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<_RAIterPairIterator>
- ::value_type*, _Compare, _DifferenceTp>,
- static_cast<_DifferenceType>(__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 _RAIterPairIterator,
- typename _RAIterOut,
- typename _DifferenceTp,
- typename _Compare>
- _RAIterOut
- stable_multiway_merge_sentinels(_RAIterPairIterator __seqs_begin,
- _RAIterPairIterator __seqs_end,
- _RAIterOut __target,
- _DifferenceTp __length,
- _Compare __comp,
- sampling_tag __tag)
- {
- typedef _DifferenceTp _DifferenceType;
- _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)
- && ((_SequenceIndex)__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<_RAIterPairIterator>
- ::value_type*, _Compare, _DifferenceTp>,
- static_cast<_DifferenceType>(__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 _RAIterPairIterator,
- typename _RAIterOut,
- typename _DifferenceTp,
- typename _Compare>
- _RAIterOut
- stable_multiway_merge_sentinels(_RAIterPairIterator __seqs_begin,
- _RAIterPairIterator __seqs_end,
- _RAIterOut __target,
- _DifferenceTp __length,
- _Compare __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 _RAIterPairIterator,
- typename _RAIterOut,
- typename _DifferenceTp,
- typename _Compare>
- _RAIterOut
- stable_multiway_merge_sentinels(_RAIterPairIterator __seqs_begin,
- _RAIterPairIterator __seqs_end,
- _RAIterOut __target,
- _DifferenceTp __length, _Compare __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 */
|