STXXL  1.4-dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
merge.h
Go to the documentation of this file.
1 /***************************************************************************
2  * include/stxxl/bits/parallel/merge.h
3  *
4  * Parallel implementation of std::merge().
5  * Extracted from MCSTL - http://algo2.iti.uni-karlsruhe.de/singler/mcstl/
6  *
7  * Part of the STXXL. See http://stxxl.sourceforge.net
8  *
9  * Copyright (C) 2007 Johannes Singler <[email protected]>
10  * Copyright (C) 2014 Timo Bingmann <[email protected]>
11  *
12  * Distributed under the Boost Software License, Version 1.0.
13  * (See accompanying file LICENSE_1_0.txt or copy at
14  * http://www.boost.org/LICENSE_1_0.txt)
15  **************************************************************************/
16 
17 #ifndef STXXL_PARALLEL_MERGE_HEADER
18 #define STXXL_PARALLEL_MERGE_HEADER
19 
20 #include <stxxl/bits/namespace.h>
22 #include <iterator>
23 #include <cassert>
24 
26 
27 namespace parallel {
28 
29 /*!
30  * Merge routine being able to merge only the \c max_length smallest elements.
31  *
32  * The \c begin iterators are advanced accordingly, they might not reach \c
33  * end, in contrast to the usual variant.
34  *
35  * \param begin1 Begin iterator of first sequence.
36  * \param end1 End iterator of first sequence.
37  * \param begin2 Begin iterator of second sequence.
38  * \param end2 End iterator of second sequence.
39  * \param target Target begin iterator.
40  * \param max_length Maximum number of elements to merge.
41  * \param comp Comparator.
42  * \return Output end iterator.
43  */
44 template <typename RandomAccessIterator1, typename RandomAccessIterator2,
45  typename OutputIterator,
46  typename DiffType, typename Comparator>
47 OutputIterator
48 merge_advance_usual(RandomAccessIterator1& begin1, RandomAccessIterator1 end1,
49  RandomAccessIterator2& begin2, RandomAccessIterator2 end2,
50  OutputIterator target, DiffType max_length,
51  Comparator comp)
52 {
53  while (begin1 != end1 && begin2 != end2 && max_length > 0)
54  {
55  // array1[i1] < array0[i0]
56  if (comp(*begin2, *begin1))
57  *target++ = *begin2++;
58  else
59  *target++ = *begin1++;
60  --max_length;
61  }
62 
63  if (begin1 != end1)
64  {
65  target = std::copy(begin1, begin1 + max_length, target);
66  begin1 += max_length;
67  }
68  else
69  {
70  target = std::copy(begin2, begin2 + max_length, target);
71  begin2 += max_length;
72  }
73  return target;
74 }
75 
76 /*!
77  * Merge routine being able to merge only the \c max_length smallest elements.
78  *
79  * The \c begin iterators are advanced accordingly, they might not reach \c
80  * end, in contrast to the usual variant. Specially designed code should allow
81  * the compiler to generate conditional moves instead of branches.
82  *
83  * \param begin1 Begin iterator of first sequence.
84  * \param end1 End iterator of first sequence.
85  * \param begin2 Begin iterator of second sequence.
86  * \param end2 End iterator of second sequence.
87  * \param target Target begin iterator.
88  * \param max_length Maximum number of elements to merge.
89  * \param comp Comparator.
90  * \return Output end iterator.
91  */
92 template <typename RandomAccessIterator1, typename RandomAccessIterator2,
93  typename OutputIterator,
94  typename DiffType, typename Comparator>
95 OutputIterator
96 merge_advance_movc(RandomAccessIterator1& begin1, RandomAccessIterator1 end1,
97  RandomAccessIterator2& begin2, RandomAccessIterator2 end2,
98  OutputIterator target,
99  DiffType max_length, Comparator comp)
100 {
101  typedef typename std::iterator_traits<RandomAccessIterator1>::value_type ValueType1;
102  typedef typename std::iterator_traits<RandomAccessIterator2>::value_type ValueType2;
103 
104  while (begin1 != end1 && begin2 != end2 && max_length > 0)
105  {
106  RandomAccessIterator1 next1 = begin1 + 1;
107  RandomAccessIterator2 next2 = begin2 + 1;
108  ValueType1 element1 = *begin1;
109  ValueType2 element2 = *begin2;
110 
111  if (comp(element2, element1))
112  {
113  element1 = element2;
114  begin2 = next2;
115  }
116  else
117  {
118  begin1 = next1;
119  }
120 
121  *target = element1;
122 
123  ++target;
124  --max_length;
125  }
126 
127  if (begin1 != end1)
128  {
129  target = std::copy(begin1, begin1 + max_length, target);
130  begin1 += max_length;
131  }
132  else
133  {
134  target = std::copy(begin2, begin2 + max_length, target);
135  begin2 += max_length;
136  }
137 
138  return target;
139 }
140 
141 /*!
142  * Merge routine being able to merge only the \c max_length smallest elements.
143  *
144  * The \c begin iterators are advanced accordingly, they might not reach \c
145  * end, in contrast to the usual variant. Static switch on whether to use the
146  * conditional-move variant.
147  *
148  * \param begin1 Begin iterator of first sequence.
149  * \param end1 End iterator of first sequence.
150  * \param begin2 Begin iterator of second sequence.
151  * \param end2 End iterator of second sequence.
152  * \param target Target begin iterator.
153  * \param max_length Maximum number of elements to merge.
154  * \param comp Comparator.
155  * \return Output end iterator.
156  */
157 template <typename RandomAccessIterator1, typename RandomAccessIterator2,
158  typename OutputIterator,
159  typename DiffType, typename Comparator>
160 OutputIterator
161 merge_advance(RandomAccessIterator1& begin1, RandomAccessIterator1 end1,
162  RandomAccessIterator2& begin2, RandomAccessIterator2 end2,
163  OutputIterator target,
164  DiffType max_length, Comparator comp)
165 {
166  STXXL_PARALLEL_PCALL(max_length);
167 
168  return merge_advance_movc(begin1, end1, begin2, end2, target, max_length, comp);
169 }
170 
171 /*!
172  * Merge routine fallback to sequential in case the iterators of the two input
173  * sequences are of different type.
174  *
175  * \param begin1 Begin iterator of first sequence.
176  * \param end1 End iterator of first sequence.
177  * \param begin2 Begin iterator of second sequence.
178  * \param end2 End iterator of second sequence.
179  * \param target Target begin iterator.
180  * \param max_length Maximum number of elements to merge.
181  * \param comp Comparator.
182  * \return Output end iterator.
183  */
184 template <typename RandomAccessIterator1, typename RandomAccessIterator2,
185  typename RandomAccessIterator3, typename Comparator>
186 RandomAccessIterator3
188  RandomAccessIterator1& begin1, RandomAccessIterator1 end1,
189  RandomAccessIterator2& begin2, RandomAccessIterator2 end2,
190  // different iterators, parallel implementation not available
191  RandomAccessIterator3 target,
192  typename std::iterator_traits<RandomAccessIterator1>::difference_type max_length,
193  Comparator comp)
194 {
195  return merge_advance(begin1, end1, begin2, end2, target, max_length, comp);
196 }
197 
198 /*!
199  * Parallel merge routine being able to merge only the \c max_length smallest
200  * elements.
201  *
202  * The \c begin iterators are advanced accordingly, they might not reach \c
203  * end, in contrast to the usual variant. The functionality is projected onto
204  * parallel_multiway_merge.
205  *
206  * \param begin1 Begin iterator of first sequence.
207  * \param end1 End iterator of first sequence.
208  * \param begin2 Begin iterator of second sequence.
209  * \param end2 End iterator of second sequence.
210  * \param target Target begin iterator.
211  * \param max_length Maximum number of elements to merge.
212  * \param comp Comparator.
213  * \return Output end iterator.
214  */
215 template <typename RandomAccessIterator1, typename RandomAccessIterator3,
216  typename Comparator>
217 RandomAccessIterator3
219  RandomAccessIterator1& begin1, RandomAccessIterator1 end1,
220  RandomAccessIterator1& begin2, RandomAccessIterator1 end2,
221  RandomAccessIterator3 target,
222  typename std::iterator_traits<RandomAccessIterator1>::difference_type max_length,
223  Comparator comp)
224 {
225  std::pair<RandomAccessIterator1, RandomAccessIterator1> seqs[2] = {
226  std::make_pair(begin1, end1), std::make_pair(begin2, end2)
227  };
228  RandomAccessIterator3 target_end = parallel_multiway_merge(
229  seqs, seqs + 2, target, comp, max_length, true, false
230  );
231 
232  return target_end;
233 }
234 
235 } // namespace parallel
236 
238 
239 #endif // !STXXL_PARALLEL_MERGE_HEADER
OutputIterator merge_advance(RandomAccessIterator1 &begin1, RandomAccessIterator1 end1, RandomAccessIterator2 &begin2, RandomAccessIterator2 end2, OutputIterator target, DiffType max_length, Comparator comp)
Merge routine being able to merge only the max_length smallest elements.
Definition: merge.h:161
#define STXXL_BEGIN_NAMESPACE
Definition: namespace.h:16
#define STXXL_PARALLEL_PCALL(n)
OutputIterator merge_advance_movc(RandomAccessIterator1 &begin1, RandomAccessIterator1 end1, RandomAccessIterator2 &begin2, RandomAccessIterator2 end2, OutputIterator target, DiffType max_length, Comparator comp)
Merge routine being able to merge only the max_length smallest elements.
Definition: merge.h:96
RandomAccessIterator3 parallel_merge_advance(RandomAccessIterator1 &begin1, RandomAccessIterator1 end1, RandomAccessIterator2 &begin2, RandomAccessIterator2 end2, RandomAccessIterator3 target, typename std::iterator_traits< RandomAccessIterator1 >::difference_type max_length, Comparator comp)
Merge routine fallback to sequential in case the iterators of the two input sequences are of differen...
Definition: merge.h:187
OutputIterator merge_advance_usual(RandomAccessIterator1 &begin1, RandomAccessIterator1 end1, RandomAccessIterator2 &begin2, RandomAccessIterator2 end2, OutputIterator target, DiffType max_length, Comparator comp)
Merge routine being able to merge only the max_length smallest elements.
Definition: merge.h:48
#define STXXL_END_NAMESPACE
Definition: namespace.h:17