xref: /netbsd-src/external/gpl3/gcc.old/dist/libstdc++-v3/include/parallel/merge.h (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
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