1*38fd1498Szrj // -*- C++ -*- 2*38fd1498Szrj 3*38fd1498Szrj // Copyright (C) 2007-2018 Free Software Foundation, Inc. 4*38fd1498Szrj // 5*38fd1498Szrj // This file is part of the GNU ISO C++ Library. This library is free 6*38fd1498Szrj // software; you can redistribute it and/or modify it under the terms 7*38fd1498Szrj // of the GNU General Public License as published by the Free Software 8*38fd1498Szrj // Foundation; either version 3, or (at your option) any later 9*38fd1498Szrj // version. 10*38fd1498Szrj 11*38fd1498Szrj // This library is distributed in the hope that it will be useful, but 12*38fd1498Szrj // WITHOUT ANY WARRANTY; without even the implied warranty of 13*38fd1498Szrj // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14*38fd1498Szrj // General Public License for more details. 15*38fd1498Szrj 16*38fd1498Szrj // Under Section 7 of GPL version 3, you are granted additional 17*38fd1498Szrj // permissions described in the GCC Runtime Library Exception, version 18*38fd1498Szrj // 3.1, as published by the Free Software Foundation. 19*38fd1498Szrj 20*38fd1498Szrj // You should have received a copy of the GNU General Public License and 21*38fd1498Szrj // a copy of the GCC Runtime Library Exception along with this program; 22*38fd1498Szrj // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23*38fd1498Szrj // <http://www.gnu.org/licenses/>. 24*38fd1498Szrj 25*38fd1498Szrj /** @file parallel/merge.h 26*38fd1498Szrj * @brief Parallel implementation of std::merge(). 27*38fd1498Szrj * This file is a GNU parallel extension to the Standard C++ Library. 28*38fd1498Szrj */ 29*38fd1498Szrj 30*38fd1498Szrj // Written by Johannes Singler. 31*38fd1498Szrj 32*38fd1498Szrj #ifndef _GLIBCXX_PARALLEL_MERGE_H 33*38fd1498Szrj #define _GLIBCXX_PARALLEL_MERGE_H 1 34*38fd1498Szrj 35*38fd1498Szrj #include <parallel/basic_iterator.h> 36*38fd1498Szrj #include <bits/stl_algo.h> 37*38fd1498Szrj 38*38fd1498Szrj namespace __gnu_parallel 39*38fd1498Szrj { 40*38fd1498Szrj /** @brief Merge routine being able to merge only the @c __max_length 41*38fd1498Szrj * smallest elements. 42*38fd1498Szrj * 43*38fd1498Szrj * The @c __begin iterators are advanced accordingly, they might not 44*38fd1498Szrj * reach @c __end, in contrast to the usual variant. 45*38fd1498Szrj * @param __begin1 Begin iterator of first sequence. 46*38fd1498Szrj * @param __end1 End iterator of first sequence. 47*38fd1498Szrj * @param __begin2 Begin iterator of second sequence. 48*38fd1498Szrj * @param __end2 End iterator of second sequence. 49*38fd1498Szrj * @param __target Target begin iterator. 50*38fd1498Szrj * @param __max_length Maximum number of elements to merge. 51*38fd1498Szrj * @param __comp Comparator. 52*38fd1498Szrj * @return Output end iterator. */ 53*38fd1498Szrj template<typename _RAIter1, typename _RAIter2, 54*38fd1498Szrj typename _OutputIterator, typename _DifferenceTp, 55*38fd1498Szrj typename _Compare> 56*38fd1498Szrj _OutputIterator __merge_advance_usual(_RAIter1 & __begin1,_RAIter1 __end1,_RAIter2 & __begin2,_RAIter2 __end2,_OutputIterator __target,_DifferenceTp __max_length,_Compare __comp)57*38fd1498Szrj __merge_advance_usual(_RAIter1& __begin1, _RAIter1 __end1, 58*38fd1498Szrj _RAIter2& __begin2, _RAIter2 __end2, 59*38fd1498Szrj _OutputIterator __target, 60*38fd1498Szrj _DifferenceTp __max_length, _Compare __comp) 61*38fd1498Szrj { 62*38fd1498Szrj typedef _DifferenceTp _DifferenceType; 63*38fd1498Szrj while (__begin1 != __end1 && __begin2 != __end2 && __max_length > 0) 64*38fd1498Szrj { 65*38fd1498Szrj // array1[__i1] < array0[i0] 66*38fd1498Szrj if (__comp(*__begin2, *__begin1)) 67*38fd1498Szrj *__target++ = *__begin2++; 68*38fd1498Szrj else 69*38fd1498Szrj *__target++ = *__begin1++; 70*38fd1498Szrj --__max_length; 71*38fd1498Szrj } 72*38fd1498Szrj 73*38fd1498Szrj if (__begin1 != __end1) 74*38fd1498Szrj { 75*38fd1498Szrj __target = std::copy(__begin1, __begin1 + __max_length, __target); 76*38fd1498Szrj __begin1 += __max_length; 77*38fd1498Szrj } 78*38fd1498Szrj else 79*38fd1498Szrj { 80*38fd1498Szrj __target = std::copy(__begin2, __begin2 + __max_length, __target); 81*38fd1498Szrj __begin2 += __max_length; 82*38fd1498Szrj } 83*38fd1498Szrj return __target; 84*38fd1498Szrj } 85*38fd1498Szrj 86*38fd1498Szrj /** @brief Merge routine being able to merge only the @c __max_length 87*38fd1498Szrj * smallest elements. 88*38fd1498Szrj * 89*38fd1498Szrj * The @c __begin iterators are advanced accordingly, they might not 90*38fd1498Szrj * reach @c __end, in contrast to the usual variant. 91*38fd1498Szrj * Specially designed code should allow the compiler to generate 92*38fd1498Szrj * conditional moves instead of branches. 93*38fd1498Szrj * @param __begin1 Begin iterator of first sequence. 94*38fd1498Szrj * @param __end1 End iterator of first sequence. 95*38fd1498Szrj * @param __begin2 Begin iterator of second sequence. 96*38fd1498Szrj * @param __end2 End iterator of second sequence. 97*38fd1498Szrj * @param __target Target begin iterator. 98*38fd1498Szrj * @param __max_length Maximum number of elements to merge. 99*38fd1498Szrj * @param __comp Comparator. 100*38fd1498Szrj * @return Output end iterator. */ 101*38fd1498Szrj template<typename _RAIter1, typename _RAIter2, 102*38fd1498Szrj typename _OutputIterator, typename _DifferenceTp, 103*38fd1498Szrj typename _Compare> 104*38fd1498Szrj _OutputIterator __merge_advance_movc(_RAIter1 & __begin1,_RAIter1 __end1,_RAIter2 & __begin2,_RAIter2 __end2,_OutputIterator __target,_DifferenceTp __max_length,_Compare __comp)105*38fd1498Szrj __merge_advance_movc(_RAIter1& __begin1, _RAIter1 __end1, 106*38fd1498Szrj _RAIter2& __begin2, _RAIter2 __end2, 107*38fd1498Szrj _OutputIterator __target, 108*38fd1498Szrj _DifferenceTp __max_length, _Compare __comp) 109*38fd1498Szrj { 110*38fd1498Szrj typedef _DifferenceTp _DifferenceType; 111*38fd1498Szrj typedef typename std::iterator_traits<_RAIter1>::value_type 112*38fd1498Szrj _ValueType1; 113*38fd1498Szrj typedef typename std::iterator_traits<_RAIter2>::value_type 114*38fd1498Szrj _ValueType2; 115*38fd1498Szrj 116*38fd1498Szrj #if _GLIBCXX_PARALLEL_ASSERTIONS 117*38fd1498Szrj _GLIBCXX_PARALLEL_ASSERT(__max_length >= 0); 118*38fd1498Szrj #endif 119*38fd1498Szrj 120*38fd1498Szrj while (__begin1 != __end1 && __begin2 != __end2 && __max_length > 0) 121*38fd1498Szrj { 122*38fd1498Szrj _RAIter1 __next1 = __begin1 + 1; 123*38fd1498Szrj _RAIter2 __next2 = __begin2 + 1; 124*38fd1498Szrj _ValueType1 __element1 = *__begin1; 125*38fd1498Szrj _ValueType2 __element2 = *__begin2; 126*38fd1498Szrj 127*38fd1498Szrj if (__comp(__element2, __element1)) 128*38fd1498Szrj { 129*38fd1498Szrj __element1 = __element2; 130*38fd1498Szrj __begin2 = __next2; 131*38fd1498Szrj } 132*38fd1498Szrj else 133*38fd1498Szrj __begin1 = __next1; 134*38fd1498Szrj 135*38fd1498Szrj *__target = __element1; 136*38fd1498Szrj 137*38fd1498Szrj ++__target; 138*38fd1498Szrj --__max_length; 139*38fd1498Szrj } 140*38fd1498Szrj if (__begin1 != __end1) 141*38fd1498Szrj { 142*38fd1498Szrj __target = std::copy(__begin1, __begin1 + __max_length, __target); 143*38fd1498Szrj __begin1 += __max_length; 144*38fd1498Szrj } 145*38fd1498Szrj else 146*38fd1498Szrj { 147*38fd1498Szrj __target = std::copy(__begin2, __begin2 + __max_length, __target); 148*38fd1498Szrj __begin2 += __max_length; 149*38fd1498Szrj } 150*38fd1498Szrj return __target; 151*38fd1498Szrj } 152*38fd1498Szrj 153*38fd1498Szrj /** @brief Merge routine being able to merge only the @c __max_length 154*38fd1498Szrj * smallest elements. 155*38fd1498Szrj * 156*38fd1498Szrj * The @c __begin iterators are advanced accordingly, they might not 157*38fd1498Szrj * reach @c __end, in contrast to the usual variant. 158*38fd1498Szrj * Static switch on whether to use the conditional-move variant. 159*38fd1498Szrj * @param __begin1 Begin iterator of first sequence. 160*38fd1498Szrj * @param __end1 End iterator of first sequence. 161*38fd1498Szrj * @param __begin2 Begin iterator of second sequence. 162*38fd1498Szrj * @param __end2 End iterator of second sequence. 163*38fd1498Szrj * @param __target Target begin iterator. 164*38fd1498Szrj * @param __max_length Maximum number of elements to merge. 165*38fd1498Szrj * @param __comp Comparator. 166*38fd1498Szrj * @return Output end iterator. */ 167*38fd1498Szrj template<typename _RAIter1, typename _RAIter2, 168*38fd1498Szrj typename _OutputIterator, typename _DifferenceTp, 169*38fd1498Szrj typename _Compare> 170*38fd1498Szrj inline _OutputIterator __merge_advance(_RAIter1 & __begin1,_RAIter1 __end1,_RAIter2 & __begin2,_RAIter2 __end2,_OutputIterator __target,_DifferenceTp __max_length,_Compare __comp)171*38fd1498Szrj __merge_advance(_RAIter1& __begin1, _RAIter1 __end1, 172*38fd1498Szrj _RAIter2& __begin2, _RAIter2 __end2, 173*38fd1498Szrj _OutputIterator __target, _DifferenceTp __max_length, 174*38fd1498Szrj _Compare __comp) 175*38fd1498Szrj { 176*38fd1498Szrj _GLIBCXX_CALL(__max_length) 177*38fd1498Szrj 178*38fd1498Szrj return __merge_advance_movc(__begin1, __end1, __begin2, __end2, 179*38fd1498Szrj __target, __max_length, __comp); 180*38fd1498Szrj } 181*38fd1498Szrj 182*38fd1498Szrj /** @brief Merge routine fallback to sequential in case the 183*38fd1498Szrj iterators of the two input sequences are of different type. 184*38fd1498Szrj * @param __begin1 Begin iterator of first sequence. 185*38fd1498Szrj * @param __end1 End iterator of first sequence. 186*38fd1498Szrj * @param __begin2 Begin iterator of second sequence. 187*38fd1498Szrj * @param __end2 End iterator of second sequence. 188*38fd1498Szrj * @param __target Target begin iterator. 189*38fd1498Szrj * @param __max_length Maximum number of elements to merge. 190*38fd1498Szrj * @param __comp Comparator. 191*38fd1498Szrj * @return Output end iterator. */ 192*38fd1498Szrj template<typename _RAIter1, typename _RAIter2, 193*38fd1498Szrj typename _RAIter3, typename _Compare> 194*38fd1498Szrj 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)195*38fd1498Szrj __parallel_merge_advance(_RAIter1& __begin1, _RAIter1 __end1, 196*38fd1498Szrj _RAIter2& __begin2, 197*38fd1498Szrj // different iterators, parallel implementation 198*38fd1498Szrj // not available 199*38fd1498Szrj _RAIter2 __end2, _RAIter3 __target, typename 200*38fd1498Szrj std::iterator_traits<_RAIter1>:: 201*38fd1498Szrj difference_type __max_length, _Compare __comp) 202*38fd1498Szrj { return __merge_advance(__begin1, __end1, __begin2, __end2, __target, 203*38fd1498Szrj __max_length, __comp); } 204*38fd1498Szrj 205*38fd1498Szrj /** @brief Parallel merge routine being able to merge only the @c 206*38fd1498Szrj * __max_length smallest elements. 207*38fd1498Szrj * 208*38fd1498Szrj * The @c __begin iterators are advanced accordingly, they might not 209*38fd1498Szrj * reach @c __end, in contrast to the usual variant. 210*38fd1498Szrj * The functionality is projected onto parallel_multiway_merge. 211*38fd1498Szrj * @param __begin1 Begin iterator of first sequence. 212*38fd1498Szrj * @param __end1 End iterator of first sequence. 213*38fd1498Szrj * @param __begin2 Begin iterator of second sequence. 214*38fd1498Szrj * @param __end2 End iterator of second sequence. 215*38fd1498Szrj * @param __target Target begin iterator. 216*38fd1498Szrj * @param __max_length Maximum number of elements to merge. 217*38fd1498Szrj * @param __comp Comparator. 218*38fd1498Szrj * @return Output end iterator. 219*38fd1498Szrj */ 220*38fd1498Szrj template<typename _RAIter1, typename _RAIter3, 221*38fd1498Szrj typename _Compare> 222*38fd1498Szrj 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)223*38fd1498Szrj __parallel_merge_advance(_RAIter1& __begin1, _RAIter1 __end1, 224*38fd1498Szrj _RAIter1& __begin2, _RAIter1 __end2, 225*38fd1498Szrj _RAIter3 __target, typename 226*38fd1498Szrj std::iterator_traits<_RAIter1>:: 227*38fd1498Szrj difference_type __max_length, _Compare __comp) 228*38fd1498Szrj { 229*38fd1498Szrj typedef typename 230*38fd1498Szrj std::iterator_traits<_RAIter1>::value_type _ValueType; 231*38fd1498Szrj typedef typename std::iterator_traits<_RAIter1>:: 232*38fd1498Szrj difference_type _DifferenceType1 /* == difference_type2 */; 233*38fd1498Szrj typedef typename std::iterator_traits<_RAIter3>:: 234*38fd1498Szrj difference_type _DifferenceType3; 235*38fd1498Szrj typedef typename std::pair<_RAIter1, _RAIter1> 236*38fd1498Szrj _IteratorPair; 237*38fd1498Szrj 238*38fd1498Szrj _IteratorPair __seqs[2] = { std::make_pair(__begin1, __end1), 239*38fd1498Szrj std::make_pair(__begin2, __end2) }; 240*38fd1498Szrj _RAIter3 __target_end = parallel_multiway_merge 241*38fd1498Szrj < /* __stable = */ true, /* __sentinels = */ false> 242*38fd1498Szrj (__seqs, __seqs + 2, __target, multiway_merge_exact_splitting 243*38fd1498Szrj < /* __stable = */ true, _IteratorPair*, 244*38fd1498Szrj _Compare, _DifferenceType1>, __max_length, __comp, 245*38fd1498Szrj omp_get_max_threads()); 246*38fd1498Szrj 247*38fd1498Szrj return __target_end; 248*38fd1498Szrj } 249*38fd1498Szrj } //namespace __gnu_parallel 250*38fd1498Szrj 251*38fd1498Szrj #endif /* _GLIBCXX_PARALLEL_MERGE_H */ 252