39 #ifndef _GLIBCXX_PARALLEL_MULTIWAY_MERGE_H
40 #define _GLIBCXX_PARALLEL_MULTIWAY_MERGE_H
49 #if _GLIBCXX_ASSERTIONS
54 #define _GLIBCXX_PARALLEL_LENGTH(__s) ((__s).second - (__s).first)
56 namespace __gnu_parallel
58 template<
typename _RAIter1,
typename _RAIter2,
typename _OutputIterator,
59 typename _DifferenceTp,
typename _Compare>
62 _OutputIterator, _DifferenceTp, _Compare);
72 template<
typename _RAIter,
typename _Compare>
92 : _M_current(__begin), _M_end(__end), __comp(__comp)
106 typename std::iterator_traits<_RAIter>::value_type&
108 {
return *_M_current; }
113 {
return _M_current; }
120 operator<(_GuardedIterator<_RAIter, _Compare>& __bi1,
123 if (__bi1._M_current == __bi1._M_end)
124 return __bi2._M_current == __bi2._M_end;
125 if (__bi2._M_current == __bi2._M_end)
127 return (__bi1.__comp)(*__bi1, *__bi2);
135 operator<=(_GuardedIterator<_RAIter, _Compare>& __bi1,
138 if (__bi2._M_current == __bi2._M_end)
139 return __bi1._M_current != __bi1._M_end;
140 if (__bi1._M_current == __bi1._M_end)
142 return !(__bi1.__comp)(*__bi2, *__bi1);
146 template<
typename _RAIter,
typename _Compare>
147 class _UnguardedIterator
160 _UnguardedIterator(_RAIter __begin,
161 _RAIter , _Compare& __comp)
162 : _M_current(__begin), __comp(__comp)
167 _UnguardedIterator<_RAIter, _Compare>&
176 typename std::iterator_traits<_RAIter>::value_type&
178 {
return *_M_current; }
183 {
return _M_current; }
190 operator<(_UnguardedIterator<_RAIter, _Compare>& __bi1,
191 _UnguardedIterator<_RAIter, _Compare>& __bi2)
194 return (__bi1.__comp)(*__bi1, *__bi2);
202 operator<=(_UnguardedIterator<_RAIter, _Compare>& __bi1,
203 _UnguardedIterator<_RAIter, _Compare>& __bi2)
206 return !(__bi1.__comp)(*__bi2, *__bi1);
235 template<
template<
typename RAI,
typename C>
class iterator,
236 typename _RAIterIterator,
238 typename _DifferenceTp,
242 _RAIterIterator __seqs_end,
244 _DifferenceTp __length, _Compare __comp)
248 typedef _DifferenceTp _DifferenceType;
250 typedef typename std::iterator_traits<_RAIterIterator>
251 ::value_type::first_type
253 typedef typename std::iterator_traits<_RAIter1>::value_type
259 #if _GLIBCXX_ASSERTIONS
260 _DifferenceTp __orig_length = __length;
263 iterator<_RAIter1, _Compare>
264 __seq0(__seqs_begin[0].first, __seqs_begin[0].second, __comp),
265 __seq1(__seqs_begin[1].first, __seqs_begin[1].second, __comp),
266 __seq2(__seqs_begin[2].first, __seqs_begin[2].second, __comp);
268 if (__seq0 <= __seq1)
270 if (__seq1 <= __seq2)
280 if (__seq1 <= __seq2)
282 if (__seq0 <= __seq2)
290 #define _GLIBCXX_PARALLEL_MERGE_3_CASE(__a, __b, __c, __c0, __c1) \
291 __s ## __a ## __b ## __c : \
292 *__target = *__seq ## __a; \
296 if (__length == 0) goto __finish; \
297 if (__seq ## __a __c0 __seq ## __b) goto __s ## __a ## __b ## __c; \
298 if (__seq ## __a __c1 __seq ## __c) goto __s ## __b ## __a ## __c; \
299 goto __s ## __b ## __c ## __a;
301 _GLIBCXX_PARALLEL_MERGE_3_CASE(0, 1, 2, <=, <=);
302 _GLIBCXX_PARALLEL_MERGE_3_CASE(1, 2, 0, <=, < );
303 _GLIBCXX_PARALLEL_MERGE_3_CASE(2, 0, 1, < , < );
304 _GLIBCXX_PARALLEL_MERGE_3_CASE(1, 0, 2, < , <=);
305 _GLIBCXX_PARALLEL_MERGE_3_CASE(0, 2, 1, <=, <=);
306 _GLIBCXX_PARALLEL_MERGE_3_CASE(2, 1, 0, < , < );
308 #undef _GLIBCXX_PARALLEL_MERGE_3_CASE
313 #if _GLIBCXX_ASSERTIONS
314 _GLIBCXX_PARALLEL_ASSERT(
315 ((_RAIter1)__seq0 - __seqs_begin[0].first) +
316 ((_RAIter1)__seq1 - __seqs_begin[1].first) +
317 ((_RAIter1)__seq2 - __seqs_begin[2].first)
321 __seqs_begin[0].first = __seq0;
322 __seqs_begin[1].first = __seq1;
323 __seqs_begin[2].first = __seq2;
354 template<
template<
typename RAI,
typename C>
class iterator,
355 typename _RAIterIterator,
357 typename _DifferenceTp,
361 _RAIterIterator __seqs_end,
363 _DifferenceTp __length, _Compare __comp)
366 typedef _DifferenceTp _DifferenceType;
368 typedef typename std::iterator_traits<_RAIterIterator>
369 ::value_type::first_type
371 typedef typename std::iterator_traits<_RAIter1>::value_type
374 iterator<_RAIter1, _Compare>
375 __seq0(__seqs_begin[0].first, __seqs_begin[0].second, __comp),
376 __seq1(__seqs_begin[1].first, __seqs_begin[1].second, __comp),
377 __seq2(__seqs_begin[2].first, __seqs_begin[2].second, __comp),
378 __seq3(__seqs_begin[3].first, __seqs_begin[3].second, __comp);
380 #define _GLIBCXX_PARALLEL_DECISION(__a, __b, __c, __d) { \
381 if (__seq ## __d < __seq ## __a) \
382 goto __s ## __d ## __a ## __b ## __c; \
383 if (__seq ## __d < __seq ## __b) \
384 goto __s ## __a ## __d ## __b ## __c; \
385 if (__seq ## __d < __seq ## __c) \
386 goto __s ## __a ## __b ## __d ## __c; \
387 goto __s ## __a ## __b ## __c ## __d; }
389 if (__seq0 <= __seq1)
391 if (__seq1 <= __seq2)
392 _GLIBCXX_PARALLEL_DECISION(0,1,2,3)
395 _GLIBCXX_PARALLEL_DECISION(2,0,1,3)
397 _GLIBCXX_PARALLEL_DECISION(0,2,1,3)
401 if (__seq1 <= __seq2)
403 if (__seq0 <= __seq2)
404 _GLIBCXX_PARALLEL_DECISION(1,0,2,3)
406 _GLIBCXX_PARALLEL_DECISION(1,2,0,3)
409 _GLIBCXX_PARALLEL_DECISION(2,1,0,3)
412 #define _GLIBCXX_PARALLEL_MERGE_4_CASE(__a, __b, __c, __d, \
414 __s ## __a ## __b ## __c ## __d: \
415 if (__length == 0) goto __finish; \
416 *__target = *__seq ## __a; \
420 if (__seq ## __a __c0 __seq ## __b) \
421 goto __s ## __a ## __b ## __c ## __d; \
422 if (__seq ## __a __c1 __seq ## __c) \
423 goto __s ## __b ## __a ## __c ## __d; \
424 if (__seq ## __a __c2 __seq ## __d) \
425 goto __s ## __b ## __c ## __a ## __d; \
426 goto __s ## __b ## __c ## __d ## __a;
428 _GLIBCXX_PARALLEL_MERGE_4_CASE(0, 1, 2, 3, <=, <=, <=);
429 _GLIBCXX_PARALLEL_MERGE_4_CASE(0, 1, 3, 2, <=, <=, <=);
430 _GLIBCXX_PARALLEL_MERGE_4_CASE(0, 2, 1, 3, <=, <=, <=);
431 _GLIBCXX_PARALLEL_MERGE_4_CASE(0, 2, 3, 1, <=, <=, <=);
432 _GLIBCXX_PARALLEL_MERGE_4_CASE(0, 3, 1, 2, <=, <=, <=);
433 _GLIBCXX_PARALLEL_MERGE_4_CASE(0, 3, 2, 1, <=, <=, <=);
434 _GLIBCXX_PARALLEL_MERGE_4_CASE(1, 0, 2, 3, < , <=, <=);
435 _GLIBCXX_PARALLEL_MERGE_4_CASE(1, 0, 3, 2, < , <=, <=);
436 _GLIBCXX_PARALLEL_MERGE_4_CASE(1, 2, 0, 3, <=, < , <=);
437 _GLIBCXX_PARALLEL_MERGE_4_CASE(1, 2, 3, 0, <=, <=, < );
438 _GLIBCXX_PARALLEL_MERGE_4_CASE(1, 3, 0, 2, <=, < , <=);
439 _GLIBCXX_PARALLEL_MERGE_4_CASE(1, 3, 2, 0, <=, <=, < );
440 _GLIBCXX_PARALLEL_MERGE_4_CASE(2, 0, 1, 3, < , < , <=);
441 _GLIBCXX_PARALLEL_MERGE_4_CASE(2, 0, 3, 1, < , <=, < );
442 _GLIBCXX_PARALLEL_MERGE_4_CASE(2, 1, 0, 3, < , < , <=);
443 _GLIBCXX_PARALLEL_MERGE_4_CASE(2, 1, 3, 0, < , <=, < );
444 _GLIBCXX_PARALLEL_MERGE_4_CASE(2, 3, 0, 1, <=, < , < );
445 _GLIBCXX_PARALLEL_MERGE_4_CASE(2, 3, 1, 0, <=, < , < );
446 _GLIBCXX_PARALLEL_MERGE_4_CASE(3, 0, 1, 2, < , < , < );
447 _GLIBCXX_PARALLEL_MERGE_4_CASE(3, 0, 2, 1, < , < , < );
448 _GLIBCXX_PARALLEL_MERGE_4_CASE(3, 1, 0, 2, < , < , < );
449 _GLIBCXX_PARALLEL_MERGE_4_CASE(3, 1, 2, 0, < , < , < );
450 _GLIBCXX_PARALLEL_MERGE_4_CASE(3, 2, 0, 1, < , < , < );
451 _GLIBCXX_PARALLEL_MERGE_4_CASE(3, 2, 1, 0, < , < , < );
453 #undef _GLIBCXX_PARALLEL_MERGE_4_CASE
454 #undef _GLIBCXX_PARALLEL_DECISION
459 __seqs_begin[0].first = __seq0;
460 __seqs_begin[1].first = __seq1;
461 __seqs_begin[2].first = __seq2;
462 __seqs_begin[3].first = __seq3;
485 template<
typename _LT,
486 typename _RAIterIterator,
488 typename _DifferenceTp,
492 _RAIterIterator __seqs_end,
494 _DifferenceTp __length, _Compare __comp)
498 typedef _DifferenceTp _DifferenceType;
499 typedef typename std::iterator_traits<_RAIterIterator>
500 ::difference_type _SeqNumber;
501 typedef typename std::iterator_traits<_RAIterIterator>
502 ::value_type::first_type
504 typedef typename std::iterator_traits<_RAIter1>::value_type
507 _SeqNumber __k =
static_cast<_SeqNumber
>(__seqs_end - __seqs_begin);
509 _LT __lt(__k, __comp);
512 _ValueType* __arbitrary_element = 0;
514 for (_SeqNumber __t = 0; __t < __k; ++__t)
516 if(!__arbitrary_element
518 __arbitrary_element = &(*__seqs_begin[__t].first);
521 for (_SeqNumber __t = 0; __t < __k; ++__t)
523 if (__seqs_begin[__t].first == __seqs_begin[__t].second)
524 __lt.__insert_start(*__arbitrary_element, __t,
true);
526 __lt.__insert_start(*__seqs_begin[__t].first, __t,
false);
533 for (_DifferenceType __i = 0; __i < __length; ++__i)
536 __source = __lt.__get_min_source();
538 *(__target++) = *(__seqs_begin[__source].first++);
541 if (__seqs_begin[__source].first == __seqs_begin[__source].second)
542 __lt.__delete_min_insert(*__arbitrary_element,
true);
545 __lt.__delete_min_insert(*__seqs_begin[__source].first,
false);
569 template<
typename _LT,
570 typename _RAIterIterator,
572 typename _DifferenceTp,
typename _Compare>
575 _RAIterIterator __seqs_end,
577 const typename std::iterator_traits<
typename std::iterator_traits<
578 _RAIterIterator>::value_type::first_type>::value_type&
580 _DifferenceTp __length,
584 typedef _DifferenceTp _DifferenceType;
586 typedef typename std::iterator_traits<_RAIterIterator>
587 ::difference_type _SeqNumber;
588 typedef typename std::iterator_traits<_RAIterIterator>
589 ::value_type::first_type
591 typedef typename std::iterator_traits<_RAIter1>::value_type
594 _SeqNumber __k = __seqs_end - __seqs_begin;
596 _LT __lt(__k, __sentinel, __comp);
598 for (_SeqNumber __t = 0; __t < __k; ++__t)
600 #if _GLIBCXX_ASSERTIONS
601 _GLIBCXX_PARALLEL_ASSERT(__seqs_begin[__t].first
602 != __seqs_begin[__t].second);
604 __lt.__insert_start(*__seqs_begin[__t].first, __t,
false);
611 #if _GLIBCXX_ASSERTIONS
612 _DifferenceType __i = 0;
615 _RAIter3 __target_end = __target + __length;
616 while (__target < __target_end)
619 __source = __lt.__get_min_source();
621 #if _GLIBCXX_ASSERTIONS
622 _GLIBCXX_PARALLEL_ASSERT(0 <= __source && __source < __k);
623 _GLIBCXX_PARALLEL_ASSERT(__i == 0
624 || !__comp(*(__seqs_begin[__source].first), *(__target - 1)));
628 *(__target++) = *(__seqs_begin[__source].first++);
630 #if _GLIBCXX_ASSERTIONS
634 __lt.__delete_min_insert(*__seqs_begin[__source].first,
false);
656 template<
typename UnguardedLoserTree,
657 typename _RAIterIterator,
659 typename _DifferenceTp,
663 _RAIterIterator __seqs_end,
665 const typename std::iterator_traits<
typename std::iterator_traits<
666 _RAIterIterator>::value_type::first_type>::value_type&
668 _DifferenceTp __length,
673 typedef _DifferenceTp _DifferenceType;
674 typedef std::iterator_traits<_RAIterIterator> _TraitsType;
675 typedef typename std::iterator_traits<_RAIterIterator>
676 ::value_type::first_type
678 typedef typename std::iterator_traits<_RAIter1>::value_type
681 _RAIter3 __target_end;
683 for (_RAIterIterator __s = __seqs_begin; __s != __seqs_end; ++__s)
690 __target_end = multiway_merge_loser_tree_unguarded<UnguardedLoserTree>
691 (__seqs_begin, __seqs_end, __target, __sentinel, __length, __comp);
693 #if _GLIBCXX_ASSERTIONS
694 _GLIBCXX_PARALLEL_ASSERT(__target_end == __target + __length);
695 _GLIBCXX_PARALLEL_ASSERT(
__is_sorted(__target, __target_end, __comp));
700 for (_RAIterIterator __s = __seqs_begin; __s != __seqs_end; ++__s)
730 template <
typename _Tp>
747 template<
bool __sentinels ,
748 typename _RAIterIterator,
750 typename _DifferenceTp,
755 operator()(_RAIterIterator __seqs_begin,
756 _RAIterIterator __seqs_end,
758 _DifferenceTp __length, _Compare __comp)
759 {
return multiway_merge_3_variant<_GuardedIterator>
760 (__seqs_begin, __seqs_end, __target, __length, __comp); }
768 template<
typename _RAIterIterator,
770 typename _DifferenceTp,
773 _RAIter3, _DifferenceTp,
777 operator()(_RAIterIterator __seqs_begin,
778 _RAIterIterator __seqs_end,
780 _DifferenceTp __length, _Compare __comp)
781 {
return multiway_merge_3_variant<_UnguardedIterator>
782 (__seqs_begin, __seqs_end, __target, __length, __comp); }
790 template<
bool __sentinels ,
791 typename _RAIterIterator,
793 typename _DifferenceTp,
798 operator()(_RAIterIterator __seqs_begin,
799 _RAIterIterator __seqs_end,
801 _DifferenceTp __length, _Compare __comp)
802 {
return multiway_merge_4_variant<_GuardedIterator>
803 (__seqs_begin, __seqs_end, __target, __length, __comp); }
811 template<
typename _RAIterIterator,
813 typename _DifferenceTp,
816 _RAIter3, _DifferenceTp,
820 operator()(_RAIterIterator __seqs_begin,
821 _RAIterIterator __seqs_end,
823 _DifferenceTp __length, _Compare __comp)
824 {
return multiway_merge_4_variant<_UnguardedIterator>
825 (__seqs_begin, __seqs_end, __target, __length, __comp); }
831 template<
bool __sentinels,
833 typename _RAIterIterator,
835 typename _DifferenceTp,
840 operator()(_RAIterIterator __seqs_begin,
841 _RAIterIterator __seqs_end,
843 const typename std::iterator_traits<
typename std::iterator_traits<
844 _RAIterIterator>::value_type::first_type>::value_type&
846 _DifferenceTp __length, _Compare __comp)
848 typedef typename std::iterator_traits<_RAIterIterator>
849 ::value_type::first_type
851 typedef typename std::iterator_traits<_RAIter1>::value_type
855 typename __gnu_cxx::__conditional_type<
860 (__seqs_begin, __seqs_end, __target, __sentinel, __length, __comp);
867 template<
bool __stable,
868 typename _RAIterIterator,
870 typename _DifferenceTp,
874 _RAIter3, _DifferenceTp,
878 operator()(_RAIterIterator __seqs_begin,
879 _RAIterIterator __seqs_end,
881 const typename std::iterator_traits<
typename std::iterator_traits<
882 _RAIterIterator>::value_type::first_type>::value_type&
884 _DifferenceTp __length, _Compare __comp)
886 typedef typename std::iterator_traits<_RAIterIterator>
887 ::value_type::first_type
889 typedef typename std::iterator_traits<_RAIter1>::value_type
893 typename __gnu_cxx::__conditional_type<
897 >::__type >(__seqs_begin, __seqs_end, __target, __length, __comp);
913 template<
bool __stable,
915 typename _RAIterIterator,
917 typename _DifferenceTp,
921 _RAIterIterator __seqs_end,
923 const typename std::iterator_traits<
typename std::iterator_traits<
924 _RAIterIterator>::value_type::first_type>::value_type&
926 _DifferenceTp __length, _Compare __comp)
930 typedef _DifferenceTp _DifferenceType;
931 typedef typename std::iterator_traits<_RAIterIterator>
932 ::difference_type _SeqNumber;
933 typedef typename std::iterator_traits<_RAIterIterator>
934 ::value_type::first_type
936 typedef typename std::iterator_traits<_RAIter1>::value_type
939 #if _GLIBCXX_ASSERTIONS
940 for (_RAIterIterator __s = __seqs_begin; __s != __seqs_end; ++__s)
943 (*__s).second, __comp));
947 _DifferenceTp __total_length = 0;
948 for (_RAIterIterator __s = __seqs_begin; __s != __seqs_end; ++__s)
951 __length = std::min<_DifferenceTp>(__length, __total_length);
956 _RAIter3 __return_target = __target;
957 _SeqNumber __k =
static_cast<_SeqNumber
>(__seqs_end - __seqs_begin);
964 __return_target = std::copy(__seqs_begin[0].first,
965 __seqs_begin[0].first + __length,
967 __seqs_begin[0].first += __length;
971 __seqs_begin[0].second,
972 __seqs_begin[1].first,
973 __seqs_begin[1].second,
974 __target, __length, __comp);
978 <__sentinels, _RAIterIterator, _RAIter3, _DifferenceTp, _Compare>()
979 (__seqs_begin, __seqs_end, __target, __length, __comp);
983 <__sentinels, _RAIterIterator, _RAIter3, _DifferenceTp, _Compare>()
984 (__seqs_begin, __seqs_end, __target, __length, __comp);
988 <__sentinels, __stable, _RAIterIterator, _RAIter3, _DifferenceTp,
990 (__seqs_begin, __seqs_end, __target, __sentinel, __length, __comp);
993 #if _GLIBCXX_ASSERTIONS
994 _GLIBCXX_PARALLEL_ASSERT(
995 __is_sorted(__target, __target + __length, __comp));
998 return __return_target;
1006 template<
bool __stable,
class _RAIter,
class _StrictWeakOrdering>
1010 operator()(_RAIter __first, _RAIter __last, _StrictWeakOrdering __comp)
1011 { __gnu_sequential::stable_sort(__first, __last, __comp); }
1019 template<
class _RAIter,
class _StrictWeakOrdering>
1023 operator()(_RAIter __first, _RAIter __last, _StrictWeakOrdering __comp)
1024 { __gnu_sequential::sort(__first, __last, __comp); }
1030 template<
bool __stable,
1031 typename _RAIterIterator,
1033 typename _DifferenceType>
1036 _RAIterIterator __seqs_end,
1037 _DifferenceType __length,
1038 _DifferenceType __total_length,
1042 typedef typename std::iterator_traits<_RAIterIterator>
1043 ::difference_type _SeqNumber;
1044 typedef typename std::iterator_traits<_RAIterIterator>
1045 ::value_type::first_type
1047 typedef typename std::iterator_traits<_RAIter1>::value_type
1051 const _SeqNumber __k
1052 =
static_cast<_SeqNumber
>(__seqs_end - __seqs_begin);
1054 const _ThreadIndex __num_threads = omp_get_num_threads();
1056 const _DifferenceType __num_samples =
1059 _ValueType* __samples =
static_cast<_ValueType*
>
1060 (::operator
new(
sizeof(_ValueType) * __k * __num_samples));
1062 for (_SeqNumber __s = 0; __s < __k; ++__s)
1063 for (_DifferenceType __i = 0; __i < __num_samples; ++__i)
1065 _DifferenceType sample_index =
static_cast<_DifferenceType
>
1067 * (double(__i + 1) / (__num_samples + 1))
1068 * (double(__length) / __total_length));
1069 new(&(__samples[__s * __num_samples + __i]))
1070 _ValueType(__seqs_begin[__s].first[sample_index]);
1076 (__samples, __samples + (__num_samples * __k), __comp);
1078 for (
_ThreadIndex __slab = 0; __slab < __num_threads; ++__slab)
1080 for (_SeqNumber __seq = 0; __seq < __k; ++__seq)
1084 __pieces[__slab][__seq].first = std::upper_bound
1085 (__seqs_begin[__seq].first, __seqs_begin[__seq].second,
1086 __samples[__num_samples * __k * __slab / __num_threads],
1088 - __seqs_begin[__seq].first;
1091 __pieces[__slab][__seq].first = 0;
1092 if ((__slab + 1) < __num_threads)
1093 __pieces[__slab][__seq].second = std::upper_bound
1094 (__seqs_begin[__seq].first, __seqs_begin[__seq].second,
1095 __samples[__num_samples * __k * (__slab + 1) / __num_threads],
1097 - __seqs_begin[__seq].first;
1100 __pieces[__slab][__seq].second =
1104 for (_SeqNumber __s = 0; __s < __k; ++__s)
1105 for (_DifferenceType __i = 0; __i < __num_samples; ++__i)
1106 __samples[__s * __num_samples + __i].~_ValueType();
1107 ::operator
delete(__samples);
1115 template<
bool __stable,
1116 typename _RAIterIterator,
1118 typename _DifferenceType>
1121 _RAIterIterator __seqs_end,
1122 _DifferenceType __length,
1123 _DifferenceType __total_length,
1127 typedef typename std::iterator_traits<_RAIterIterator>
1128 ::difference_type _SeqNumber;
1129 typedef typename std::iterator_traits<_RAIterIterator>
1130 ::value_type::first_type
1133 const bool __tight = (__total_length == __length);
1136 const _SeqNumber __k = __seqs_end - __seqs_begin;
1138 const _ThreadIndex __num_threads = omp_get_num_threads();
1146 copy(__seqs_begin, __seqs_end, __se.
begin());
1148 _DifferenceType* __borders =
1149 new _DifferenceType[__num_threads + 1];
1152 for (
_ThreadIndex __s = 0; __s < (__num_threads - 1); ++__s)
1154 __offsets[__s].
resize(__k);
1156 __offsets[__s].
begin(), __comp);
1161 __offsets[__num_threads - 1].
resize(__k);
1163 _DifferenceType(__length),
1164 __offsets[__num_threads - 1].
begin(),
1170 for (
_ThreadIndex __slab = 0; __slab < __num_threads; ++__slab)
1173 for (_SeqNumber __seq = 0; __seq < __k; ++__seq)
1179 __pieces[__slab][__seq].first = 0;
1182 __pieces[__slab][__seq].first =
1183 __pieces[__slab - 1][__seq].second;
1184 if (!__tight || __slab < (__num_threads - 1))
1185 __pieces[__slab][__seq].second =
1186 __offsets[__slab][__seq] - __seqs_begin[__seq].first;
1190 __pieces[__slab][__seq].second =
1217 template<
bool __stable,
1219 typename _RAIterIterator,
1221 typename _DifferenceTp,
1226 _RAIterIterator __seqs_end,
1228 _Splitter __splitter,
1229 _DifferenceTp __length,
1233 #if _GLIBCXX_ASSERTIONS
1234 _GLIBCXX_PARALLEL_ASSERT(__seqs_end - __seqs_begin > 1);
1239 typedef _DifferenceTp _DifferenceType;
1240 typedef typename std::iterator_traits<_RAIterIterator>
1241 ::difference_type _SeqNumber;
1242 typedef typename std::iterator_traits<_RAIterIterator>
1243 ::value_type::first_type
1246 std::iterator_traits<_RAIter1>::value_type _ValueType;
1250 seq_type* __ne_seqs =
new seq_type[__seqs_end - __seqs_begin];
1252 _DifferenceType __total_length = 0;
1253 for (_RAIterIterator __raii = __seqs_begin;
1254 __raii != __seqs_end; ++__raii)
1257 if(__seq_length > 0)
1259 __total_length += __seq_length;
1260 __ne_seqs[__k++] = *__raii;
1266 __length = std::min<_DifferenceTp>(__length, __total_length);
1268 if (__total_length == 0 || __k == 0)
1277 (std::min<_DifferenceType>(__num_threads, __total_length));
1279 # pragma omp parallel num_threads (__num_threads)
1283 __num_threads = omp_get_num_threads();
1288 __pieces[__s].resize(__k);
1290 _DifferenceType __num_samples =
1294 __splitter(__ne_seqs, __ne_seqs + __k, __length, __total_length,
1300 _DifferenceType __target_position = 0;
1302 for (_SeqNumber __c = 0; __c < __k; ++__c)
1303 __target_position += __pieces[__iam][__c].first;
1305 seq_type* __chunks =
new seq_type[__k];
1307 for (_SeqNumber __s = 0; __s < __k; ++__s)
1309 + __pieces[__iam][__s].first,
1310 __ne_seqs[__s].first
1311 + __pieces[__iam][__s].second);
1313 if(__length > __target_position)
1314 __sequential_multiway_merge<__stable, __sentinels>
1315 (__chunks, __chunks + __k, __target + __target_position,
1316 *(__seqs_begin->second), __length - __target_position, __comp);
1321 #if _GLIBCXX_ASSERTIONS
1322 _GLIBCXX_PARALLEL_ASSERT(
1323 __is_sorted(__target, __target + __length, __comp));
1328 for (_RAIterIterator __raii = __seqs_begin;
1329 __raii != __seqs_end; ++__raii)
1333 (*__raii).first += __pieces[__num_threads - 1][__k++].second;
1339 return __target + __length;
1413 template<
typename _RAIterPairIterator,
1414 typename _RAIterOut,
1415 typename _DifferenceTp,
1419 _RAIterPairIterator __seqs_end,
1420 _RAIterOut __target,
1421 _DifferenceTp __length, _Compare __comp,
1424 typedef _DifferenceTp _DifferenceType;
1428 if (__seqs_begin == __seqs_end)
1434 (__seqs_begin, __seqs_end, __target,
1435 *(__seqs_begin->second), __length, __comp);
1439 template<
typename _RAIterPairIterator,
1440 typename _RAIterOut,
1441 typename _DifferenceTp,
1445 _RAIterPairIterator __seqs_end,
1446 _RAIterOut __target,
1447 _DifferenceTp __length, _Compare __comp,
1450 typedef _DifferenceTp _DifferenceType;
1454 if (__seqs_begin == __seqs_end)
1460 if ((__seqs_end - __seqs_begin > 1)
1462 ((__seqs_end - __seqs_begin) >=
1463 __gnu_parallel::_Settings::get().multiway_merge_minimal_k)
1465 __gnu_parallel::_Settings::get().multiway_merge_minimal_n)))
1468 (__seqs_begin, __seqs_end, __target,
1470 typename std::iterator_traits<_RAIterPairIterator>
1471 ::value_type*, _Compare, _DifferenceTp>,
1472 static_cast<_DifferenceType>(__length), __comp,
1473 __tag.__get_num_threads());
1477 (__seqs_begin, __seqs_end, __target,
1478 *(__seqs_begin->second), __length, __comp);
1482 template<typename _RAIterPairIterator,
1483 typename _RAIterOut,
1484 typename _DifferenceTp,
1488 _RAIterPairIterator __seqs_end,
1489 _RAIterOut __target,
1490 _DifferenceTp __length, _Compare __comp,
1491 __gnu_parallel::sampling_tag __tag)
1493 typedef _DifferenceTp _DifferenceType;
1497 if (__seqs_begin == __seqs_end)
1503 if ((__seqs_end - __seqs_begin > 1)
1505 ((__seqs_end - __seqs_begin) >=
1506 __gnu_parallel::_Settings::get().multiway_merge_minimal_k)
1508 __gnu_parallel::_Settings::get().multiway_merge_minimal_n)))
1511 (__seqs_begin, __seqs_end, __target,
1513 typename std::iterator_traits<_RAIterPairIterator>
1514 ::value_type*, _Compare, _DifferenceTp>,
1515 static_cast<_DifferenceType>(__length), __comp,
1516 __tag.__get_num_threads());
1520 (__seqs_begin, __seqs_end, __target,
1521 *(__seqs_begin->second), __length, __comp);
1525 template<typename _RAIterPairIterator,
1526 typename _RAIterOut,
1527 typename _DifferenceTp,
1531 _RAIterPairIterator __seqs_end,
1532 _RAIterOut __target,
1533 _DifferenceTp __length, _Compare __comp,
1534 parallel_tag __tag = parallel_tag(0))
1535 {
return multiway_merge(__seqs_begin, __seqs_end, __target, __length,
1536 __comp, exact_tag(__tag.__get_num_threads())); }
1539 template<
typename _RAIterPairIterator,
1540 typename _RAIterOut,
1541 typename _DifferenceTp,
1545 _RAIterPairIterator __seqs_end,
1546 _RAIterOut __target,
1547 _DifferenceTp __length, _Compare __comp,
1548 default_parallel_tag __tag)
1549 {
return multiway_merge(__seqs_begin, __seqs_end, __target, __length,
1550 __comp, exact_tag(__tag.__get_num_threads())); }
1554 template<
typename _RAIterPairIterator,
1555 typename _RAIterOut,
1556 typename _DifferenceTp,
1559 stable_multiway_merge(_RAIterPairIterator __seqs_begin,
1560 _RAIterPairIterator __seqs_end,
1561 _RAIterOut __target,
1562 _DifferenceTp __length, _Compare __comp,
1565 typedef _DifferenceTp _DifferenceType;
1569 if (__seqs_begin == __seqs_end)
1575 (__seqs_begin, __seqs_end, __target,
1576 *(__seqs_begin->second), __length, __comp);
1580 template<typename _RAIterPairIterator,
1581 typename _RAIterOut,
1582 typename _DifferenceTp,
1585 stable_multiway_merge(_RAIterPairIterator __seqs_begin,
1586 _RAIterPairIterator __seqs_end,
1587 _RAIterOut __target,
1588 _DifferenceTp __length, _Compare __comp,
1589 __gnu_parallel::exact_tag __tag)
1591 typedef _DifferenceTp _DifferenceType;
1595 if (__seqs_begin == __seqs_end)
1601 if ((__seqs_end - __seqs_begin > 1)
1603 ((__seqs_end - __seqs_begin) >=
1604 __gnu_parallel::_Settings::get().multiway_merge_minimal_k)
1606 __gnu_parallel::_Settings::get().multiway_merge_minimal_n)))
1609 (__seqs_begin, __seqs_end, __target,
1611 typename std::iterator_traits<_RAIterPairIterator>
1612 ::value_type*, _Compare, _DifferenceTp>,
1613 static_cast<_DifferenceType>(__length), __comp,
1614 __tag.__get_num_threads());
1618 (__seqs_begin, __seqs_end, __target,
1619 *(__seqs_begin->second), __length, __comp);
1623 template<typename _RAIterPairIterator,
1624 typename _RAIterOut,
1625 typename _DifferenceTp,
1628 stable_multiway_merge(_RAIterPairIterator __seqs_begin,
1629 _RAIterPairIterator __seqs_end,
1630 _RAIterOut __target,
1631 _DifferenceTp __length, _Compare __comp,
1634 typedef _DifferenceTp _DifferenceType;
1638 if (__seqs_begin == __seqs_end)
1644 if ((__seqs_end - __seqs_begin > 1)
1646 ((__seqs_end - __seqs_begin) >=
1647 __gnu_parallel::_Settings::get().multiway_merge_minimal_k)
1649 __gnu_parallel::_Settings::get().multiway_merge_minimal_n)))
1652 (__seqs_begin, __seqs_end, __target,
1654 typename std::iterator_traits<_RAIterPairIterator>
1655 ::value_type*, _Compare, _DifferenceTp>,
1656 static_cast<_DifferenceType>(__length), __comp,
1657 __tag.__get_num_threads());
1661 (__seqs_begin, __seqs_end, __target,
1662 *(__seqs_begin->second), __length, __comp);
1666 template<typename _RAIterPairIterator,
1667 typename _RAIterOut,
1668 typename _DifferenceTp,
1671 stable_multiway_merge(_RAIterPairIterator __seqs_begin,
1672 _RAIterPairIterator __seqs_end,
1673 _RAIterOut __target,
1674 _DifferenceTp __length, _Compare __comp,
1675 parallel_tag __tag = parallel_tag(0))
1677 return stable_multiway_merge
1678 (__seqs_begin, __seqs_end, __target, __length, __comp,
1679 exact_tag(__tag.__get_num_threads()));
1683 template<
typename _RAIterPairIterator,
1684 typename _RAIterOut,
1685 typename _DifferenceTp,
1688 stable_multiway_merge(_RAIterPairIterator __seqs_begin,
1689 _RAIterPairIterator __seqs_end,
1690 _RAIterOut __target,
1691 _DifferenceTp __length, _Compare __comp,
1692 default_parallel_tag __tag)
1694 return stable_multiway_merge
1695 (__seqs_begin, __seqs_end, __target, __length, __comp,
1696 exact_tag(__tag.__get_num_threads()));
1777 template<
typename _RAIterPairIterator,
1778 typename _RAIterOut,
1779 typename _DifferenceTp,
1783 _RAIterPairIterator __seqs_end,
1784 _RAIterOut __target,
1785 _DifferenceTp __length, _Compare __comp,
1788 typedef _DifferenceTp _DifferenceType;
1792 if (__seqs_begin == __seqs_end)
1798 (__seqs_begin, __seqs_end,
1799 __target, *(__seqs_begin->second), __length, __comp);
1803 template<
typename _RAIterPairIterator,
1804 typename _RAIterOut,
1805 typename _DifferenceTp,
1809 _RAIterPairIterator __seqs_end,
1810 _RAIterOut __target,
1811 _DifferenceTp __length, _Compare __comp,
1814 typedef _DifferenceTp _DifferenceType;
1818 if (__seqs_begin == __seqs_end)
1824 if ((__seqs_end - __seqs_begin > 1)
1826 ((__seqs_end - __seqs_begin) >=
1827 __gnu_parallel::_Settings::get().multiway_merge_minimal_k)
1829 __gnu_parallel::_Settings::get().multiway_merge_minimal_n)))
1832 (__seqs_begin, __seqs_end, __target,
1834 typename std::iterator_traits<_RAIterPairIterator>
1835 ::value_type*, _Compare, _DifferenceTp>,
1836 static_cast<_DifferenceType>(__length), __comp,
1837 __tag.__get_num_threads());
1841 (__seqs_begin, __seqs_end, __target,
1842 *(__seqs_begin->second), __length, __comp);
1846 template<typename _RAIterPairIterator,
1847 typename _RAIterOut,
1848 typename _DifferenceTp,
1852 _RAIterPairIterator __seqs_end,
1853 _RAIterOut __target,
1854 _DifferenceTp __length, _Compare __comp,
1857 typedef _DifferenceTp _DifferenceType;
1861 if (__seqs_begin == __seqs_end)
1867 if ((__seqs_end - __seqs_begin > 1)
1869 ((__seqs_end - __seqs_begin) >=
1870 __gnu_parallel::_Settings::get().multiway_merge_minimal_k)
1872 __gnu_parallel::_Settings::get().multiway_merge_minimal_n)))
1875 (__seqs_begin, __seqs_end, __target,
1877 typename std::iterator_traits<_RAIterPairIterator>
1878 ::value_type*, _Compare, _DifferenceTp>,
1879 static_cast<_DifferenceType>(__length), __comp,
1880 __tag.__get_num_threads());
1884 __seqs_begin, __seqs_end, __target,
1885 *(__seqs_begin->second), __length, __comp);
1889 template<typename _RAIterPairIterator,
1890 typename _RAIterOut,
1891 typename _DifferenceTp,
1895 _RAIterPairIterator __seqs_end,
1896 _RAIterOut __target,
1897 _DifferenceTp __length, _Compare __comp,
1898 parallel_tag __tag = parallel_tag(0))
1901 (__seqs_begin, __seqs_end, __target, __length, __comp,
1902 exact_tag(__tag.__get_num_threads()));
1906 template<
typename _RAIterPairIterator,
1907 typename _RAIterOut,
1908 typename _DifferenceTp,
1912 _RAIterPairIterator __seqs_end,
1913 _RAIterOut __target,
1914 _DifferenceTp __length, _Compare __comp,
1915 default_parallel_tag __tag)
1918 (__seqs_begin, __seqs_end, __target, __length, __comp,
1919 exact_tag(__tag.__get_num_threads()));
1924 template<
typename _RAIterPairIterator,
1925 typename _RAIterOut,
1926 typename _DifferenceTp,
1929 stable_multiway_merge_sentinels(_RAIterPairIterator __seqs_begin,
1930 _RAIterPairIterator __seqs_end,
1931 _RAIterOut __target,
1932 _DifferenceTp __length, _Compare __comp,
1935 typedef _DifferenceTp _DifferenceType;
1939 if (__seqs_begin == __seqs_end)
1945 (__seqs_begin, __seqs_end, __target,
1946 *(__seqs_begin->second), __length, __comp);
1950 template<typename _RAIterPairIterator,
1951 typename _RAIterOut,
1952 typename _DifferenceTp,
1955 stable_multiway_merge_sentinels(_RAIterPairIterator __seqs_begin,
1956 _RAIterPairIterator __seqs_end,
1957 _RAIterOut __target,
1958 _DifferenceTp __length, _Compare __comp,
1959 __gnu_parallel::exact_tag __tag)
1961 typedef _DifferenceTp _DifferenceType;
1965 if (__seqs_begin == __seqs_end)
1971 if ((__seqs_end - __seqs_begin > 1)
1973 ((__seqs_end - __seqs_begin) >=
1974 __gnu_parallel::_Settings::get().multiway_merge_minimal_k)
1976 __gnu_parallel::_Settings::get().multiway_merge_minimal_n)))
1979 (__seqs_begin, __seqs_end, __target,
1981 typename std::iterator_traits<_RAIterPairIterator>
1982 ::value_type*, _Compare, _DifferenceTp>,
1983 static_cast<_DifferenceType>(__length), __comp,
1984 __tag.__get_num_threads());
1988 (__seqs_begin, __seqs_end, __target,
1989 *(__seqs_begin->second), __length, __comp);
1993 template<typename _RAIterPairIterator,
1994 typename _RAIterOut,
1995 typename _DifferenceTp,
1998 stable_multiway_merge_sentinels(_RAIterPairIterator __seqs_begin,
1999 _RAIterPairIterator __seqs_end,
2000 _RAIterOut __target,
2001 _DifferenceTp __length,
2005 typedef _DifferenceTp _DifferenceType;
2009 if (__seqs_begin == __seqs_end)
2015 if ((__seqs_end - __seqs_begin > 1)
2017 ((__seqs_end - __seqs_begin) >=
2018 __gnu_parallel::_Settings::get().multiway_merge_minimal_k)
2020 __gnu_parallel::_Settings::get().multiway_merge_minimal_n)))
2023 (__seqs_begin, __seqs_end, __target,
2025 typename std::iterator_traits<_RAIterPairIterator>
2026 ::value_type*, _Compare, _DifferenceTp>,
2027 static_cast<_DifferenceType>(__length), __comp,
2028 __tag.__get_num_threads());
2032 (__seqs_begin, __seqs_end, __target,
2033 *(__seqs_begin->second), __length, __comp);
2037 template<typename _RAIterPairIterator,
2038 typename _RAIterOut,
2039 typename _DifferenceTp,
2042 stable_multiway_merge_sentinels(_RAIterPairIterator __seqs_begin,
2043 _RAIterPairIterator __seqs_end,
2044 _RAIterOut __target,
2045 _DifferenceTp __length,
2047 parallel_tag __tag = parallel_tag(0))
2049 return stable_multiway_merge_sentinels
2050 (__seqs_begin, __seqs_end, __target, __length, __comp,
2051 exact_tag(__tag.__get_num_threads()));
2055 template<
typename _RAIterPairIterator,
2056 typename _RAIterOut,
2057 typename _DifferenceTp,
2060 stable_multiway_merge_sentinels(_RAIterPairIterator __seqs_begin,
2061 _RAIterPairIterator __seqs_end,
2062 _RAIterOut __target,
2063 _DifferenceTp __length, _Compare __comp,
2064 default_parallel_tag __tag)
2066 return stable_multiway_merge_sentinels
2067 (__seqs_begin, __seqs_end, __target, __length, __comp,
2068 exact_tag(__tag.__get_num_threads()));
static const _Settings & get()
Get the global settings.
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)
Exact splitting for parallel multiway-merge routine.
_OutputIterator __merge_advance(_RAIter1 &__begin1, _RAIter1 __end1, _RAIter2 &__begin2, _RAIter2 __end2, _OutputIterator __target, _DifferenceTp __max_length, _Compare __comp)
Merge routine being able to merge only the __max_length smallest elements.
_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)
Sequential multi-way merging switch.
uint16_t _ThreadIndex
Unsigned integer to index a thread number. The maximum thread number (for each processor) must fit in...
_Iterator wrapper supporting an implicit supremum at the end of the sequence, dominating all comparis...
constexpr pair< typename __decay_and_strip< _T1 >::__type, typename __decay_and_strip< _T2 >::__type > make_pair(_T1 &&__x, _T2 &&__y)
A convenience wrapper for creating a pair from two objects.
unsigned int merge_oversampling
Oversampling factor for merge.
_RAIterOut multiway_merge_sentinels(_RAIterPairIterator __seqs_begin, _RAIterPairIterator __seqs_end, _RAIterOut __target, _DifferenceTp __length, _Compare __comp, __gnu_parallel::sequential_tag)
Multiway Merge Frontend.
_GuardedIterator< _RAIter, _Compare > & operator++()
Pre-increment operator.
_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)
Multi-way merging procedure for a high branching factor, unguarded case.
Struct holding two objects of arbitrary type.
_RAIter3 multiway_merge_loser_tree(_RAIterIterator __seqs_begin, _RAIterIterator __seqs_end, _RAIter3 __target, _DifferenceTp __length, _Compare __comp)
Multi-way merging procedure for a high branching factor, guarded case.
_RAIter3 multiway_merge_4_variant(_RAIterIterator __seqs_begin, _RAIterIterator __seqs_end, _RAIter3 __target, _DifferenceTp __length, _Compare __comp)
Highly efficient 4-way merging procedure.
Forces sequential execution at compile time.
Switch for k-way merging with __sentinels turned on.
#define _GLIBCXX_PARALLEL_CONDITION(__c)
Determine at compile(?)-time if the parallel variant of an algorithm should be called.
Stable _LoserTree implementation.
_GuardedIterator(_RAIter __begin, _RAIter __end, _Compare &__comp)
Constructor. Sets iterator to beginning of sequence.
uint64_t _SequenceIndex
Unsigned integer to index __elements. The total number of elements for each algorithm must fit into t...
_OutputIterator __equally_split(_DifferenceType __n, _ThreadIndex __num_threads, _OutputIterator __s)
function to split a sequence into parts of almost equal size.
Switch for 3-way merging with __sentinels turned off.
iterator begin() noexcept
Defines on whether to include algorithm variants.
_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)
Multi-way merging procedure for a high branching factor, requiring sentinels to exist.
#define _GLIBCXX_PARALLEL_LENGTH(__s)
Length of a sequence described by a pair of iterators.
Stable implementation of unguarded _LoserTree.
Stable _LoserTree variant.
static const bool _M_use_pointer
True iff to use pointers instead of values in loser trees.
_RAIter3 multiway_merge_3_variant(_RAIterIterator __seqs_begin, _RAIterIterator __seqs_end, _RAIter3 __target, _DifferenceTp __length, _Compare __comp)
Highly efficient 3-way merging procedure.
void resize(size_type __new_size)
Resizes the vector to the specified number of elements.
Routines for checking the correctness of algorithm results. This file is a GNU parallel extension to ...
void multiseq_partition(_RanSeqs __begin_seqs, _RanSeqs __end_seqs, _RankType __rank, _RankIterator __begin_offsets, _Compare __comp=std::less< typename std::iterator_traits< typename std::iterator_traits< _RanSeqs >::value_type::first_type >::value_type >())
Splits several sorted sequences at a certain global __rank, resulting in a splitting point for each s...
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)
Sampling based splitting for parallel multiway-merge routine.
#define _GLIBCXX_CALL(__n)
Macro to produce log message when entering a function.
Functions to find elements of a certain global __rank in multiple sorted sequences. Also serves for splitting such sequence sets.
Stable unguarded _LoserTree variant storing pointers.
End-user include file. Provides advanced settings and tuning options. This file is a GNU parallel ext...
std::iterator_traits< _RAIter >::value_type & operator*()
Dereference operator.
Many generic loser tree variants. This file is a GNU parallel extension to the Standard C++ Library...
A standard container which offers fixed time access to individual elements in any order...
_RAIter3 parallel_multiway_merge(_RAIterIterator __seqs_begin, _RAIterIterator __seqs_end, _RAIter3 __target, _Splitter __splitter, _DifferenceTp __length, _Compare __comp, _ThreadIndex __num_threads)
Parallel multi-way merge routine.
Switch for 4-way merging with __sentinels turned off.
bool __is_sorted(_IIter __begin, _IIter __end, _Compare __comp)
Check whether [__begin, __end) is sorted according to __comp.
_RAIterOut multiway_merge(_RAIterPairIterator __seqs_begin, _RAIterPairIterator __seqs_end, _RAIterOut __target, _DifferenceTp __length, _Compare __comp, __gnu_parallel::sequential_tag)
Multiway Merge Frontend.
Forces parallel merging with exact splitting, at compile time.
Traits for determining whether the loser tree should use pointers or copies.