136ac495dSmrg // -*- C++ -*- 236ac495dSmrg 3*8feb0f0bSmrg // Copyright (C) 2007-2020 Free Software Foundation, Inc. 436ac495dSmrg // 536ac495dSmrg // This file is part of the GNU ISO C++ Library. This library is free 636ac495dSmrg // software; you can redistribute it and/or modify it under the terms 736ac495dSmrg // of the GNU General Public License as published by the Free Software 836ac495dSmrg // Foundation; either version 3, or (at your option) any later 936ac495dSmrg // version. 1036ac495dSmrg 1136ac495dSmrg // This library is distributed in the hope that it will be useful, but 1236ac495dSmrg // WITHOUT ANY WARRANTY; without even the implied warranty of 1336ac495dSmrg // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1436ac495dSmrg // General Public License for more details. 1536ac495dSmrg 1636ac495dSmrg // Under Section 7 of GPL version 3, you are granted additional 1736ac495dSmrg // permissions described in the GCC Runtime Library Exception, version 1836ac495dSmrg // 3.1, as published by the Free Software Foundation. 1936ac495dSmrg 2036ac495dSmrg // You should have received a copy of the GNU General Public License and 2136ac495dSmrg // a copy of the GCC Runtime Library Exception along with this program; 2236ac495dSmrg // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 2336ac495dSmrg // <http://www.gnu.org/licenses/>. 2436ac495dSmrg 2536ac495dSmrg /** @file parallel/merge.h 2636ac495dSmrg * @brief Parallel implementation of std::merge(). 2736ac495dSmrg * This file is a GNU parallel extension to the Standard C++ Library. 2836ac495dSmrg */ 2936ac495dSmrg 3036ac495dSmrg // Written by Johannes Singler. 3136ac495dSmrg 3236ac495dSmrg #ifndef _GLIBCXX_PARALLEL_MERGE_H 3336ac495dSmrg #define _GLIBCXX_PARALLEL_MERGE_H 1 3436ac495dSmrg 3536ac495dSmrg #include <parallel/basic_iterator.h> 3636ac495dSmrg #include <bits/stl_algo.h> 3736ac495dSmrg 3836ac495dSmrg namespace __gnu_parallel 3936ac495dSmrg { 4036ac495dSmrg /** @brief Merge routine being able to merge only the @c __max_length 4136ac495dSmrg * smallest elements. 4236ac495dSmrg * 4336ac495dSmrg * The @c __begin iterators are advanced accordingly, they might not 4436ac495dSmrg * reach @c __end, in contrast to the usual variant. 4536ac495dSmrg * @param __begin1 Begin iterator of first sequence. 4636ac495dSmrg * @param __end1 End iterator of first sequence. 4736ac495dSmrg * @param __begin2 Begin iterator of second sequence. 4836ac495dSmrg * @param __end2 End iterator of second sequence. 4936ac495dSmrg * @param __target Target begin iterator. 5036ac495dSmrg * @param __max_length Maximum number of elements to merge. 5136ac495dSmrg * @param __comp Comparator. 5236ac495dSmrg * @return Output end iterator. */ 5336ac495dSmrg template<typename _RAIter1, typename _RAIter2, 5436ac495dSmrg typename _OutputIterator, typename _DifferenceTp, 5536ac495dSmrg typename _Compare> 5636ac495dSmrg _OutputIterator __merge_advance_usual(_RAIter1 & __begin1,_RAIter1 __end1,_RAIter2 & __begin2,_RAIter2 __end2,_OutputIterator __target,_DifferenceTp __max_length,_Compare __comp)5736ac495dSmrg __merge_advance_usual(_RAIter1& __begin1, _RAIter1 __end1, 5836ac495dSmrg _RAIter2& __begin2, _RAIter2 __end2, 5936ac495dSmrg _OutputIterator __target, 6036ac495dSmrg _DifferenceTp __max_length, _Compare __comp) 6136ac495dSmrg { 6236ac495dSmrg typedef _DifferenceTp _DifferenceType; 6336ac495dSmrg while (__begin1 != __end1 && __begin2 != __end2 && __max_length > 0) 6436ac495dSmrg { 6536ac495dSmrg // array1[__i1] < array0[i0] 6636ac495dSmrg if (__comp(*__begin2, *__begin1)) 6736ac495dSmrg *__target++ = *__begin2++; 6836ac495dSmrg else 6936ac495dSmrg *__target++ = *__begin1++; 7036ac495dSmrg --__max_length; 7136ac495dSmrg } 7236ac495dSmrg 7336ac495dSmrg if (__begin1 != __end1) 7436ac495dSmrg { 7536ac495dSmrg __target = std::copy(__begin1, __begin1 + __max_length, __target); 7636ac495dSmrg __begin1 += __max_length; 7736ac495dSmrg } 7836ac495dSmrg else 7936ac495dSmrg { 8036ac495dSmrg __target = std::copy(__begin2, __begin2 + __max_length, __target); 8136ac495dSmrg __begin2 += __max_length; 8236ac495dSmrg } 8336ac495dSmrg return __target; 8436ac495dSmrg } 8536ac495dSmrg 8636ac495dSmrg /** @brief Merge routine being able to merge only the @c __max_length 8736ac495dSmrg * smallest elements. 8836ac495dSmrg * 8936ac495dSmrg * The @c __begin iterators are advanced accordingly, they might not 9036ac495dSmrg * reach @c __end, in contrast to the usual variant. 9136ac495dSmrg * Specially designed code should allow the compiler to generate 9236ac495dSmrg * conditional moves instead of branches. 9336ac495dSmrg * @param __begin1 Begin iterator of first sequence. 9436ac495dSmrg * @param __end1 End iterator of first sequence. 9536ac495dSmrg * @param __begin2 Begin iterator of second sequence. 9636ac495dSmrg * @param __end2 End iterator of second sequence. 9736ac495dSmrg * @param __target Target begin iterator. 9836ac495dSmrg * @param __max_length Maximum number of elements to merge. 9936ac495dSmrg * @param __comp Comparator. 10036ac495dSmrg * @return Output end iterator. */ 10136ac495dSmrg template<typename _RAIter1, typename _RAIter2, 10236ac495dSmrg typename _OutputIterator, typename _DifferenceTp, 10336ac495dSmrg typename _Compare> 10436ac495dSmrg _OutputIterator __merge_advance_movc(_RAIter1 & __begin1,_RAIter1 __end1,_RAIter2 & __begin2,_RAIter2 __end2,_OutputIterator __target,_DifferenceTp __max_length,_Compare __comp)10536ac495dSmrg __merge_advance_movc(_RAIter1& __begin1, _RAIter1 __end1, 10636ac495dSmrg _RAIter2& __begin2, _RAIter2 __end2, 10736ac495dSmrg _OutputIterator __target, 10836ac495dSmrg _DifferenceTp __max_length, _Compare __comp) 10936ac495dSmrg { 11036ac495dSmrg typedef _DifferenceTp _DifferenceType; 11136ac495dSmrg typedef typename std::iterator_traits<_RAIter1>::value_type 11236ac495dSmrg _ValueType1; 11336ac495dSmrg typedef typename std::iterator_traits<_RAIter2>::value_type 11436ac495dSmrg _ValueType2; 11536ac495dSmrg 11636ac495dSmrg #if _GLIBCXX_PARALLEL_ASSERTIONS 11736ac495dSmrg _GLIBCXX_PARALLEL_ASSERT(__max_length >= 0); 11836ac495dSmrg #endif 11936ac495dSmrg 12036ac495dSmrg while (__begin1 != __end1 && __begin2 != __end2 && __max_length > 0) 12136ac495dSmrg { 12236ac495dSmrg _RAIter1 __next1 = __begin1 + 1; 12336ac495dSmrg _RAIter2 __next2 = __begin2 + 1; 12436ac495dSmrg _ValueType1 __element1 = *__begin1; 12536ac495dSmrg _ValueType2 __element2 = *__begin2; 12636ac495dSmrg 12736ac495dSmrg if (__comp(__element2, __element1)) 12836ac495dSmrg { 12936ac495dSmrg __element1 = __element2; 13036ac495dSmrg __begin2 = __next2; 13136ac495dSmrg } 13236ac495dSmrg else 13336ac495dSmrg __begin1 = __next1; 13436ac495dSmrg 13536ac495dSmrg *__target = __element1; 13636ac495dSmrg 13736ac495dSmrg ++__target; 13836ac495dSmrg --__max_length; 13936ac495dSmrg } 14036ac495dSmrg if (__begin1 != __end1) 14136ac495dSmrg { 14236ac495dSmrg __target = std::copy(__begin1, __begin1 + __max_length, __target); 14336ac495dSmrg __begin1 += __max_length; 14436ac495dSmrg } 14536ac495dSmrg else 14636ac495dSmrg { 14736ac495dSmrg __target = std::copy(__begin2, __begin2 + __max_length, __target); 14836ac495dSmrg __begin2 += __max_length; 14936ac495dSmrg } 15036ac495dSmrg return __target; 15136ac495dSmrg } 15236ac495dSmrg 15336ac495dSmrg /** @brief Merge routine being able to merge only the @c __max_length 15436ac495dSmrg * smallest elements. 15536ac495dSmrg * 15636ac495dSmrg * The @c __begin iterators are advanced accordingly, they might not 15736ac495dSmrg * reach @c __end, in contrast to the usual variant. 15836ac495dSmrg * Static switch on whether to use the conditional-move variant. 15936ac495dSmrg * @param __begin1 Begin iterator of first sequence. 16036ac495dSmrg * @param __end1 End iterator of first sequence. 16136ac495dSmrg * @param __begin2 Begin iterator of second sequence. 16236ac495dSmrg * @param __end2 End iterator of second sequence. 16336ac495dSmrg * @param __target Target begin iterator. 16436ac495dSmrg * @param __max_length Maximum number of elements to merge. 16536ac495dSmrg * @param __comp Comparator. 16636ac495dSmrg * @return Output end iterator. */ 16736ac495dSmrg template<typename _RAIter1, typename _RAIter2, 16836ac495dSmrg typename _OutputIterator, typename _DifferenceTp, 16936ac495dSmrg typename _Compare> 17036ac495dSmrg inline _OutputIterator __merge_advance(_RAIter1 & __begin1,_RAIter1 __end1,_RAIter2 & __begin2,_RAIter2 __end2,_OutputIterator __target,_DifferenceTp __max_length,_Compare __comp)17136ac495dSmrg __merge_advance(_RAIter1& __begin1, _RAIter1 __end1, 17236ac495dSmrg _RAIter2& __begin2, _RAIter2 __end2, 17336ac495dSmrg _OutputIterator __target, _DifferenceTp __max_length, 17436ac495dSmrg _Compare __comp) 17536ac495dSmrg { 17636ac495dSmrg _GLIBCXX_CALL(__max_length) 17736ac495dSmrg 17836ac495dSmrg return __merge_advance_movc(__begin1, __end1, __begin2, __end2, 17936ac495dSmrg __target, __max_length, __comp); 18036ac495dSmrg } 18136ac495dSmrg 18236ac495dSmrg /** @brief Merge routine fallback to sequential in case the 18336ac495dSmrg iterators of the two input sequences are of different type. 18436ac495dSmrg * @param __begin1 Begin iterator of first sequence. 18536ac495dSmrg * @param __end1 End iterator of first sequence. 18636ac495dSmrg * @param __begin2 Begin iterator of second sequence. 18736ac495dSmrg * @param __end2 End iterator of second sequence. 18836ac495dSmrg * @param __target Target begin iterator. 18936ac495dSmrg * @param __max_length Maximum number of elements to merge. 19036ac495dSmrg * @param __comp Comparator. 19136ac495dSmrg * @return Output end iterator. */ 19236ac495dSmrg template<typename _RAIter1, typename _RAIter2, 19336ac495dSmrg typename _RAIter3, typename _Compare> 19436ac495dSmrg inline _RAIter3 __parallel_merge_advance(_RAIter1 & __begin1,_RAIter1 __end1,_RAIter2 & __begin2,_RAIter2 __end2,_RAIter3 __target,typename std::iterator_traits<_RAIter1>::difference_type __max_length,_Compare __comp)19536ac495dSmrg __parallel_merge_advance(_RAIter1& __begin1, _RAIter1 __end1, 19636ac495dSmrg _RAIter2& __begin2, 19736ac495dSmrg // different iterators, parallel implementation 19836ac495dSmrg // not available 19936ac495dSmrg _RAIter2 __end2, _RAIter3 __target, typename 20036ac495dSmrg std::iterator_traits<_RAIter1>:: 20136ac495dSmrg difference_type __max_length, _Compare __comp) 20236ac495dSmrg { return __merge_advance(__begin1, __end1, __begin2, __end2, __target, 20336ac495dSmrg __max_length, __comp); } 20436ac495dSmrg 20536ac495dSmrg /** @brief Parallel merge routine being able to merge only the @c 20636ac495dSmrg * __max_length smallest elements. 20736ac495dSmrg * 20836ac495dSmrg * The @c __begin iterators are advanced accordingly, they might not 20936ac495dSmrg * reach @c __end, in contrast to the usual variant. 21036ac495dSmrg * The functionality is projected onto parallel_multiway_merge. 21136ac495dSmrg * @param __begin1 Begin iterator of first sequence. 21236ac495dSmrg * @param __end1 End iterator of first sequence. 21336ac495dSmrg * @param __begin2 Begin iterator of second sequence. 21436ac495dSmrg * @param __end2 End iterator of second sequence. 21536ac495dSmrg * @param __target Target begin iterator. 21636ac495dSmrg * @param __max_length Maximum number of elements to merge. 21736ac495dSmrg * @param __comp Comparator. 21836ac495dSmrg * @return Output end iterator. 21936ac495dSmrg */ 22036ac495dSmrg template<typename _RAIter1, typename _RAIter3, 22136ac495dSmrg typename _Compare> 22236ac495dSmrg inline _RAIter3 __parallel_merge_advance(_RAIter1 & __begin1,_RAIter1 __end1,_RAIter1 & __begin2,_RAIter1 __end2,_RAIter3 __target,typename std::iterator_traits<_RAIter1>::difference_type __max_length,_Compare __comp)22336ac495dSmrg __parallel_merge_advance(_RAIter1& __begin1, _RAIter1 __end1, 22436ac495dSmrg _RAIter1& __begin2, _RAIter1 __end2, 22536ac495dSmrg _RAIter3 __target, typename 22636ac495dSmrg std::iterator_traits<_RAIter1>:: 22736ac495dSmrg difference_type __max_length, _Compare __comp) 22836ac495dSmrg { 22936ac495dSmrg typedef typename 23036ac495dSmrg std::iterator_traits<_RAIter1>::value_type _ValueType; 23136ac495dSmrg typedef typename std::iterator_traits<_RAIter1>:: 23236ac495dSmrg difference_type _DifferenceType1 /* == difference_type2 */; 23336ac495dSmrg typedef typename std::iterator_traits<_RAIter3>:: 23436ac495dSmrg difference_type _DifferenceType3; 23536ac495dSmrg typedef typename std::pair<_RAIter1, _RAIter1> 23636ac495dSmrg _IteratorPair; 23736ac495dSmrg 23836ac495dSmrg _IteratorPair __seqs[2] = { std::make_pair(__begin1, __end1), 23936ac495dSmrg std::make_pair(__begin2, __end2) }; 24036ac495dSmrg _RAIter3 __target_end = parallel_multiway_merge 24136ac495dSmrg < /* __stable = */ true, /* __sentinels = */ false> 24236ac495dSmrg (__seqs, __seqs + 2, __target, multiway_merge_exact_splitting 24336ac495dSmrg < /* __stable = */ true, _IteratorPair*, 24436ac495dSmrg _Compare, _DifferenceType1>, __max_length, __comp, 24536ac495dSmrg omp_get_max_threads()); 24636ac495dSmrg 24736ac495dSmrg return __target_end; 24836ac495dSmrg } 24936ac495dSmrg } //namespace __gnu_parallel 25036ac495dSmrg 25136ac495dSmrg #endif /* _GLIBCXX_PARALLEL_MERGE_H */ 252