Warning: That file was not part of the compilation database. It may have many parsing errors.
1 | // -*- C++ -*- |
---|---|
2 | |
3 | // Copyright (C) 2007-2017 Free Software Foundation, Inc. |
4 | // |
5 | // This file is part of the GNU ISO C++ Library. This library is free |
6 | // software; you can redistribute it and/or modify it under the terms |
7 | // of the GNU General Public License as published by the Free Software |
8 | // Foundation; either version 3, or (at your option) any later |
9 | // version. |
10 | |
11 | // This library is distributed in the hope that it will be useful, but |
12 | // WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | // General Public License for more details. |
15 | |
16 | // Under Section 7 of GPL version 3, you are granted additional |
17 | // permissions described in the GCC Runtime Library Exception, version |
18 | // 3.1, as published by the Free Software Foundation. |
19 | |
20 | // You should have received a copy of the GNU General Public License and |
21 | // a copy of the GCC Runtime Library Exception along with this program; |
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
23 | // <http://www.gnu.org/licenses/>. |
24 | |
25 | /** @file parallel/multiway_merge.h |
26 | * @brief Implementation of sequential and parallel multiway merge. |
27 | * |
28 | * Explanations on the high-speed merging routines in the appendix of |
29 | * |
30 | * P. Sanders. |
31 | * Fast priority queues for cached memory. |
32 | * ACM Journal of Experimental Algorithmics, 5, 2000. |
33 | * |
34 | * This file is a GNU parallel extension to the Standard C++ Library. |
35 | */ |
36 | |
37 | // Written by Johannes Singler and Manuel Holtgrewe. |
38 | |
39 | #ifndef _GLIBCXX_PARALLEL_MULTIWAY_MERGE_H |
40 | #define _GLIBCXX_PARALLEL_MULTIWAY_MERGE_H |
41 | |
42 | #include <vector> |
43 | |
44 | #include <bits/stl_algo.h> |
45 | #include <parallel/features.h> |
46 | #include <parallel/parallel.h> |
47 | #include <parallel/losertree.h> |
48 | #include <parallel/multiseq_selection.h> |
49 | #if _GLIBCXX_PARALLEL_ASSERTIONS |
50 | #include <parallel/checkers.h> |
51 | #endif |
52 | |
53 | /** @brief Length of a sequence described by a pair of iterators. */ |
54 | #define _GLIBCXX_PARALLEL_LENGTH(__s) ((__s).second - (__s).first) |
55 | |
56 | namespace __gnu_parallel |
57 | { |
58 | template<typename _RAIter1, typename _RAIter2, typename _OutputIterator, |
59 | typename _DifferenceTp, typename _Compare> |
60 | _OutputIterator |
61 | __merge_advance(_RAIter1&, _RAIter1, _RAIter2&, _RAIter2, |
62 | _OutputIterator, _DifferenceTp, _Compare); |
63 | |
64 | /** @brief _Iterator wrapper supporting an implicit supremum at the end |
65 | * of the sequence, dominating all comparisons. |
66 | * |
67 | * The implicit supremum comes with a performance cost. |
68 | * |
69 | * Deriving from _RAIter is not possible since |
70 | * _RAIter need not be a class. |
71 | */ |
72 | template<typename _RAIter, typename _Compare> |
73 | class _GuardedIterator |
74 | { |
75 | private: |
76 | /** @brief Current iterator __position. */ |
77 | _RAIter _M_current; |
78 | |
79 | /** @brief End iterator of the sequence. */ |
80 | _RAIter _M_end; |
81 | |
82 | /** @brief _Compare. */ |
83 | _Compare& __comp; |
84 | |
85 | public: |
86 | /** @brief Constructor. Sets iterator to beginning of sequence. |
87 | * @param __begin Begin iterator of sequence. |
88 | * @param __end End iterator of sequence. |
89 | * @param __comp Comparator provided for associated overloaded |
90 | * compare operators. */ |
91 | _GuardedIterator(_RAIter __begin, _RAIter __end, _Compare& __comp) |
92 | : _M_current(__begin), _M_end(__end), __comp(__comp) |
93 | { } |
94 | |
95 | /** @brief Pre-increment operator. |
96 | * @return This. */ |
97 | _GuardedIterator<_RAIter, _Compare>& |
98 | operator++() |
99 | { |
100 | ++_M_current; |
101 | return *this; |
102 | } |
103 | |
104 | /** @brief Dereference operator. |
105 | * @return Referenced element. */ |
106 | typename std::iterator_traits<_RAIter>::value_type& |
107 | operator*() |
108 | { return *_M_current; } |
109 | |
110 | /** @brief Convert to wrapped iterator. |
111 | * @return Wrapped iterator. */ |
112 | operator _RAIter() |
113 | { return _M_current; } |
114 | |
115 | /** @brief Compare two elements referenced by guarded iterators. |
116 | * @param __bi1 First iterator. |
117 | * @param __bi2 Second iterator. |
118 | * @return @c true if less. */ |
119 | friend bool |
120 | operator<(_GuardedIterator<_RAIter, _Compare>& __bi1, |
121 | _GuardedIterator<_RAIter, _Compare>& __bi2) |
122 | { |
123 | if (__bi1._M_current == __bi1._M_end) // __bi1 is sup |
124 | return __bi2._M_current == __bi2._M_end; // __bi2 is not sup |
125 | if (__bi2._M_current == __bi2._M_end) // __bi2 is sup |
126 | return true; |
127 | return (__bi1.__comp)(*__bi1, *__bi2); // normal compare |
128 | } |
129 | |
130 | /** @brief Compare two elements referenced by guarded iterators. |
131 | * @param __bi1 First iterator. |
132 | * @param __bi2 Second iterator. |
133 | * @return @c True if less equal. */ |
134 | friend bool |
135 | operator<=(_GuardedIterator<_RAIter, _Compare>& __bi1, |
136 | _GuardedIterator<_RAIter, _Compare>& __bi2) |
137 | { |
138 | if (__bi2._M_current == __bi2._M_end) // __bi1 is sup |
139 | return __bi1._M_current != __bi1._M_end; // __bi2 is not sup |
140 | if (__bi1._M_current == __bi1._M_end) // __bi2 is sup |
141 | return false; |
142 | return !(__bi1.__comp)(*__bi2, *__bi1); // normal compare |
143 | } |
144 | }; |
145 | |
146 | template<typename _RAIter, typename _Compare> |
147 | class _UnguardedIterator |
148 | { |
149 | private: |
150 | /** @brief Current iterator __position. */ |
151 | _RAIter _M_current; |
152 | /** @brief _Compare. */ |
153 | _Compare& __comp; |
154 | |
155 | public: |
156 | /** @brief Constructor. Sets iterator to beginning of sequence. |
157 | * @param __begin Begin iterator of sequence. |
158 | * @param __end Unused, only for compatibility. |
159 | * @param __comp Unused, only for compatibility. */ |
160 | _UnguardedIterator(_RAIter __begin, |
161 | _RAIter /* __end */, _Compare& __comp) |
162 | : _M_current(__begin), __comp(__comp) |
163 | { } |
164 | |
165 | /** @brief Pre-increment operator. |
166 | * @return This. */ |
167 | _UnguardedIterator<_RAIter, _Compare>& |
168 | operator++() |
169 | { |
170 | ++_M_current; |
171 | return *this; |
172 | } |
173 | |
174 | /** @brief Dereference operator. |
175 | * @return Referenced element. */ |
176 | typename std::iterator_traits<_RAIter>::value_type& |
177 | operator*() |
178 | { return *_M_current; } |
179 | |
180 | /** @brief Convert to wrapped iterator. |
181 | * @return Wrapped iterator. */ |
182 | operator _RAIter() |
183 | { return _M_current; } |
184 | |
185 | /** @brief Compare two elements referenced by unguarded iterators. |
186 | * @param __bi1 First iterator. |
187 | * @param __bi2 Second iterator. |
188 | * @return @c true if less. */ |
189 | friend bool |
190 | operator<(_UnguardedIterator<_RAIter, _Compare>& __bi1, |
191 | _UnguardedIterator<_RAIter, _Compare>& __bi2) |
192 | { |
193 | // Normal compare. |
194 | return (__bi1.__comp)(*__bi1, *__bi2); |
195 | } |
196 | |
197 | /** @brief Compare two elements referenced by unguarded iterators. |
198 | * @param __bi1 First iterator. |
199 | * @param __bi2 Second iterator. |
200 | * @return @c True if less equal. */ |
201 | friend bool |
202 | operator<=(_UnguardedIterator<_RAIter, _Compare>& __bi1, |
203 | _UnguardedIterator<_RAIter, _Compare>& __bi2) |
204 | { |
205 | // Normal compare. |
206 | return !(__bi1.__comp)(*__bi2, *__bi1); |
207 | } |
208 | }; |
209 | |
210 | /** @brief Highly efficient 3-way merging procedure. |
211 | * |
212 | * Merging is done with the algorithm implementation described by Peter |
213 | * Sanders. Basically, the idea is to minimize the number of necessary |
214 | * comparison after merging an element. The implementation trick |
215 | * that makes this fast is that the order of the sequences is stored |
216 | * in the instruction pointer (translated into labels in C++). |
217 | * |
218 | * This works well for merging up to 4 sequences. |
219 | * |
220 | * Note that making the merging stable does @a not come at a |
221 | * performance hit. |
222 | * |
223 | * Whether the merging is done guarded or unguarded is selected by the |
224 | * used iterator class. |
225 | * |
226 | * @param __seqs_begin Begin iterator of iterator pair input sequence. |
227 | * @param __seqs_end End iterator of iterator pair input sequence. |
228 | * @param __target Begin iterator of output sequence. |
229 | * @param __comp Comparator. |
230 | * @param __length Maximum length to merge, less equal than the |
231 | * total number of elements available. |
232 | * |
233 | * @return End iterator of output sequence. |
234 | */ |
235 | template<template<typename RAI, typename C> class iterator, |
236 | typename _RAIterIterator, |
237 | typename _RAIter3, |
238 | typename _DifferenceTp, |
239 | typename _Compare> |
240 | _RAIter3 |
241 | multiway_merge_3_variant(_RAIterIterator __seqs_begin, |
242 | _RAIterIterator __seqs_end, |
243 | _RAIter3 __target, |
244 | _DifferenceTp __length, _Compare __comp) |
245 | { |
246 | _GLIBCXX_CALL(__length); |
247 | |
248 | typedef _DifferenceTp _DifferenceType; |
249 | |
250 | typedef typename std::iterator_traits<_RAIterIterator> |
251 | ::value_type::first_type |
252 | _RAIter1; |
253 | typedef typename std::iterator_traits<_RAIter1>::value_type |
254 | _ValueType; |
255 | |
256 | if (__length == 0) |
257 | return __target; |
258 | |
259 | #if _GLIBCXX_PARALLEL_ASSERTIONS |
260 | _DifferenceTp __orig_length = __length; |
261 | #endif |
262 | |
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); |
267 | |
268 | if (__seq0 <= __seq1) |
269 | { |
270 | if (__seq1 <= __seq2) |
271 | goto __s012; |
272 | else |
273 | if (__seq2 < __seq0) |
274 | goto __s201; |
275 | else |
276 | goto __s021; |
277 | } |
278 | else |
279 | { |
280 | if (__seq1 <= __seq2) |
281 | { |
282 | if (__seq0 <= __seq2) |
283 | goto __s102; |
284 | else |
285 | goto __s120; |
286 | } |
287 | else |
288 | goto __s210; |
289 | } |
290 | #define _GLIBCXX_PARALLEL_MERGE_3_CASE(__a, __b, __c, __c0, __c1) \ |
291 | __s ## __a ## __b ## __c : \ |
292 | *__target = *__seq ## __a; \ |
293 | ++__target; \ |
294 | --__length; \ |
295 | ++__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; |
300 | |
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, < , < ); |
307 | |
308 | #undef _GLIBCXX_PARALLEL_MERGE_3_CASE |
309 | |
310 | __finish: |
311 | ; |
312 | |
313 | #if _GLIBCXX_PARALLEL_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) |
318 | == __orig_length); |
319 | #endif |
320 | |
321 | __seqs_begin[0].first = __seq0; |
322 | __seqs_begin[1].first = __seq1; |
323 | __seqs_begin[2].first = __seq2; |
324 | |
325 | return __target; |
326 | } |
327 | |
328 | /** |
329 | * @brief Highly efficient 4-way merging procedure. |
330 | * |
331 | * Merging is done with the algorithm implementation described by Peter |
332 | * Sanders. Basically, the idea is to minimize the number of necessary |
333 | * comparison after merging an element. The implementation trick |
334 | * that makes this fast is that the order of the sequences is stored |
335 | * in the instruction pointer (translated into goto labels in C++). |
336 | * |
337 | * This works well for merging up to 4 sequences. |
338 | * |
339 | * Note that making the merging stable does @a not come at a |
340 | * performance hit. |
341 | * |
342 | * Whether the merging is done guarded or unguarded is selected by the |
343 | * used iterator class. |
344 | * |
345 | * @param __seqs_begin Begin iterator of iterator pair input sequence. |
346 | * @param __seqs_end End iterator of iterator pair input sequence. |
347 | * @param __target Begin iterator of output sequence. |
348 | * @param __comp Comparator. |
349 | * @param __length Maximum length to merge, less equal than the |
350 | * total number of elements available. |
351 | * |
352 | * @return End iterator of output sequence. |
353 | */ |
354 | template<template<typename RAI, typename C> class iterator, |
355 | typename _RAIterIterator, |
356 | typename _RAIter3, |
357 | typename _DifferenceTp, |
358 | typename _Compare> |
359 | _RAIter3 |
360 | multiway_merge_4_variant(_RAIterIterator __seqs_begin, |
361 | _RAIterIterator __seqs_end, |
362 | _RAIter3 __target, |
363 | _DifferenceTp __length, _Compare __comp) |
364 | { |
365 | _GLIBCXX_CALL(__length); |
366 | typedef _DifferenceTp _DifferenceType; |
367 | |
368 | typedef typename std::iterator_traits<_RAIterIterator> |
369 | ::value_type::first_type |
370 | _RAIter1; |
371 | typedef typename std::iterator_traits<_RAIter1>::value_type |
372 | _ValueType; |
373 | |
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); |
379 | |
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; } |
388 | |
389 | if (__seq0 <= __seq1) |
390 | { |
391 | if (__seq1 <= __seq2) |
392 | _GLIBCXX_PARALLEL_DECISION(0,1,2,3) |
393 | else |
394 | if (__seq2 < __seq0) |
395 | _GLIBCXX_PARALLEL_DECISION(2,0,1,3) |
396 | else |
397 | _GLIBCXX_PARALLEL_DECISION(0,2,1,3) |
398 | } |
399 | else |
400 | { |
401 | if (__seq1 <= __seq2) |
402 | { |
403 | if (__seq0 <= __seq2) |
404 | _GLIBCXX_PARALLEL_DECISION(1,0,2,3) |
405 | else |
406 | _GLIBCXX_PARALLEL_DECISION(1,2,0,3) |
407 | } |
408 | else |
409 | _GLIBCXX_PARALLEL_DECISION(2,1,0,3) |
410 | } |
411 | |
412 | #define _GLIBCXX_PARALLEL_MERGE_4_CASE(__a, __b, __c, __d, \ |
413 | __c0, __c1, __c2) \ |
414 | __s ## __a ## __b ## __c ## __d: \ |
415 | if (__length == 0) goto __finish; \ |
416 | *__target = *__seq ## __a; \ |
417 | ++__target; \ |
418 | --__length; \ |
419 | ++__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; |
427 | |
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, < , < , < ); |
452 | |
453 | #undef _GLIBCXX_PARALLEL_MERGE_4_CASE |
454 | #undef _GLIBCXX_PARALLEL_DECISION |
455 | |
456 | __finish: |
457 | ; |
458 | |
459 | __seqs_begin[0].first = __seq0; |
460 | __seqs_begin[1].first = __seq1; |
461 | __seqs_begin[2].first = __seq2; |
462 | __seqs_begin[3].first = __seq3; |
463 | |
464 | return __target; |
465 | } |
466 | |
467 | /** @brief Multi-way merging procedure for a high branching factor, |
468 | * guarded case. |
469 | * |
470 | * This merging variant uses a LoserTree class as selected by <tt>_LT</tt>. |
471 | * |
472 | * Stability is selected through the used LoserTree class <tt>_LT</tt>. |
473 | * |
474 | * At least one non-empty sequence is required. |
475 | * |
476 | * @param __seqs_begin Begin iterator of iterator pair input sequence. |
477 | * @param __seqs_end End iterator of iterator pair input sequence. |
478 | * @param __target Begin iterator of output sequence. |
479 | * @param __comp Comparator. |
480 | * @param __length Maximum length to merge, less equal than the |
481 | * total number of elements available. |
482 | * |
483 | * @return End iterator of output sequence. |
484 | */ |
485 | template<typename _LT, |
486 | typename _RAIterIterator, |
487 | typename _RAIter3, |
488 | typename _DifferenceTp, |
489 | typename _Compare> |
490 | _RAIter3 |
491 | multiway_merge_loser_tree(_RAIterIterator __seqs_begin, |
492 | _RAIterIterator __seqs_end, |
493 | _RAIter3 __target, |
494 | _DifferenceTp __length, _Compare __comp) |
495 | { |
496 | _GLIBCXX_CALL(__length) |
497 | |
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 |
503 | _RAIter1; |
504 | typedef typename std::iterator_traits<_RAIter1>::value_type |
505 | _ValueType; |
506 | |
507 | _SeqNumber __k = static_cast<_SeqNumber>(__seqs_end - __seqs_begin); |
508 | |
509 | _LT __lt(__k, __comp); |
510 | |
511 | // Default value for potentially non-default-constructible types. |
512 | _ValueType* __arbitrary_element = 0; |
513 | |
514 | for (_SeqNumber __t = 0; __t < __k; ++__t) |
515 | { |
516 | if(!__arbitrary_element |
517 | && _GLIBCXX_PARALLEL_LENGTH(__seqs_begin[__t]) > 0) |
518 | __arbitrary_element = &(*__seqs_begin[__t].first); |
519 | } |
520 | |
521 | for (_SeqNumber __t = 0; __t < __k; ++__t) |
522 | { |
523 | if (__seqs_begin[__t].first == __seqs_begin[__t].second) |
524 | __lt.__insert_start(*__arbitrary_element, __t, true); |
525 | else |
526 | __lt.__insert_start(*__seqs_begin[__t].first, __t, false); |
527 | } |
528 | |
529 | __lt.__init(); |
530 | |
531 | _SeqNumber __source; |
532 | |
533 | for (_DifferenceType __i = 0; __i < __length; ++__i) |
534 | { |
535 | //take out |
536 | __source = __lt.__get_min_source(); |
537 | |
538 | *(__target++) = *(__seqs_begin[__source].first++); |
539 | |
540 | // Feed. |
541 | if (__seqs_begin[__source].first == __seqs_begin[__source].second) |
542 | __lt.__delete_min_insert(*__arbitrary_element, true); |
543 | else |
544 | // Replace from same __source. |
545 | __lt.__delete_min_insert(*__seqs_begin[__source].first, false); |
546 | } |
547 | |
548 | return __target; |
549 | } |
550 | |
551 | /** @brief Multi-way merging procedure for a high branching factor, |
552 | * unguarded case. |
553 | * |
554 | * Merging is done using the LoserTree class <tt>_LT</tt>. |
555 | * |
556 | * Stability is selected by the used LoserTrees. |
557 | * |
558 | * @pre No input will run out of elements during the merge. |
559 | * |
560 | * @param __seqs_begin Begin iterator of iterator pair input sequence. |
561 | * @param __seqs_end End iterator of iterator pair input sequence. |
562 | * @param __target Begin iterator of output sequence. |
563 | * @param __comp Comparator. |
564 | * @param __length Maximum length to merge, less equal than the |
565 | * total number of elements available. |
566 | * |
567 | * @return End iterator of output sequence. |
568 | */ |
569 | template<typename _LT, |
570 | typename _RAIterIterator, |
571 | typename _RAIter3, |
572 | typename _DifferenceTp, typename _Compare> |
573 | _RAIter3 |
574 | multiway_merge_loser_tree_unguarded(_RAIterIterator __seqs_begin, |
575 | _RAIterIterator __seqs_end, |
576 | _RAIter3 __target, |
577 | const typename std::iterator_traits<typename std::iterator_traits< |
578 | _RAIterIterator>::value_type::first_type>::value_type& |
579 | __sentinel, |
580 | _DifferenceTp __length, |
581 | _Compare __comp) |
582 | { |
583 | _GLIBCXX_CALL(__length) |
584 | typedef _DifferenceTp _DifferenceType; |
585 | |
586 | typedef typename std::iterator_traits<_RAIterIterator> |
587 | ::difference_type _SeqNumber; |
588 | typedef typename std::iterator_traits<_RAIterIterator> |
589 | ::value_type::first_type |
590 | _RAIter1; |
591 | typedef typename std::iterator_traits<_RAIter1>::value_type |
592 | _ValueType; |
593 | |
594 | _SeqNumber __k = __seqs_end - __seqs_begin; |
595 | |
596 | _LT __lt(__k, __sentinel, __comp); |
597 | |
598 | for (_SeqNumber __t = 0; __t < __k; ++__t) |
599 | { |
600 | #if _GLIBCXX_PARALLEL_ASSERTIONS |
601 | _GLIBCXX_PARALLEL_ASSERT(__seqs_begin[__t].first |
602 | != __seqs_begin[__t].second); |
603 | #endif |
604 | __lt.__insert_start(*__seqs_begin[__t].first, __t, false); |
605 | } |
606 | |
607 | __lt.__init(); |
608 | |
609 | _SeqNumber __source; |
610 | |
611 | #if _GLIBCXX_PARALLEL_ASSERTIONS |
612 | _DifferenceType __i = 0; |
613 | #endif |
614 | |
615 | _RAIter3 __target_end = __target + __length; |
616 | while (__target < __target_end) |
617 | { |
618 | // Take out. |
619 | __source = __lt.__get_min_source(); |
620 | |
621 | #if _GLIBCXX_PARALLEL_ASSERTIONS |
622 | _GLIBCXX_PARALLEL_ASSERT(0 <= __source && __source < __k); |
623 | _GLIBCXX_PARALLEL_ASSERT(__i == 0 |
624 | || !__comp(*(__seqs_begin[__source].first), *(__target - 1))); |
625 | #endif |
626 | |
627 | // Feed. |
628 | *(__target++) = *(__seqs_begin[__source].first++); |
629 | |
630 | #if _GLIBCXX_PARALLEL_ASSERTIONS |
631 | ++__i; |
632 | #endif |
633 | // Replace from same __source. |
634 | __lt.__delete_min_insert(*__seqs_begin[__source].first, false); |
635 | } |
636 | |
637 | return __target; |
638 | } |
639 | |
640 | |
641 | /** @brief Multi-way merging procedure for a high branching factor, |
642 | * requiring sentinels to exist. |
643 | * |
644 | * @tparam UnguardedLoserTree _Loser Tree variant to use for the unguarded |
645 | * merging. |
646 | * |
647 | * @param __seqs_begin Begin iterator of iterator pair input sequence. |
648 | * @param __seqs_end End iterator of iterator pair input sequence. |
649 | * @param __target Begin iterator of output sequence. |
650 | * @param __comp Comparator. |
651 | * @param __length Maximum length to merge, less equal than the |
652 | * total number of elements available. |
653 | * |
654 | * @return End iterator of output sequence. |
655 | */ |
656 | template<typename UnguardedLoserTree, |
657 | typename _RAIterIterator, |
658 | typename _RAIter3, |
659 | typename _DifferenceTp, |
660 | typename _Compare> |
661 | _RAIter3 |
662 | multiway_merge_loser_tree_sentinel(_RAIterIterator __seqs_begin, |
663 | _RAIterIterator __seqs_end, |
664 | _RAIter3 __target, |
665 | const typename std::iterator_traits<typename std::iterator_traits< |
666 | _RAIterIterator>::value_type::first_type>::value_type& |
667 | __sentinel, |
668 | _DifferenceTp __length, |
669 | _Compare __comp) |
670 | { |
671 | _GLIBCXX_CALL(__length) |
672 | |
673 | typedef _DifferenceTp _DifferenceType; |
674 | typedef std::iterator_traits<_RAIterIterator> _TraitsType; |
675 | typedef typename std::iterator_traits<_RAIterIterator> |
676 | ::value_type::first_type |
677 | _RAIter1; |
678 | typedef typename std::iterator_traits<_RAIter1>::value_type |
679 | _ValueType; |
680 | |
681 | _RAIter3 __target_end; |
682 | |
683 | for (_RAIterIterator __s = __seqs_begin; __s != __seqs_end; ++__s) |
684 | // Move the sequence ends to the sentinel. This has the |
685 | // effect that the sentinel appears to be within the sequence. Then, |
686 | // we can use the unguarded variant if we merge out as many |
687 | // non-sentinel elements as we have. |
688 | ++((*__s).second); |
689 | |
690 | __target_end = multiway_merge_loser_tree_unguarded<UnguardedLoserTree> |
691 | (__seqs_begin, __seqs_end, __target, __sentinel, __length, __comp); |
692 | |
693 | #if _GLIBCXX_PARALLEL_ASSERTIONS |
694 | _GLIBCXX_PARALLEL_ASSERT(__target_end == __target + __length); |
695 | _GLIBCXX_PARALLEL_ASSERT(__is_sorted(__target, __target_end, __comp)); |
696 | #endif |
697 | |
698 | // Restore the sequence ends so the sentinels are not contained in the |
699 | // sequence any more (see comment in loop above). |
700 | for (_RAIterIterator __s = __seqs_begin; __s != __seqs_end; ++__s) |
701 | --((*__s).second); |
702 | |
703 | return __target_end; |
704 | } |
705 | |
706 | /** |
707 | * @brief Traits for determining whether the loser tree should |
708 | * use pointers or copies. |
709 | * |
710 | * The field "_M_use_pointer" is used to determine whether to use pointers |
711 | * in he loser trees or whether to copy the values into the loser tree. |
712 | * |
713 | * The default behavior is to use pointers if the data type is 4 times as |
714 | * big as the pointer to it. |
715 | * |
716 | * Specialize for your data type to customize the behavior. |
717 | * |
718 | * Example: |
719 | * |
720 | * template<> |
721 | * struct _LoserTreeTraits<int> |
722 | * { static const bool _M_use_pointer = false; }; |
723 | * |
724 | * template<> |
725 | * struct _LoserTreeTraits<heavyweight_type> |
726 | * { static const bool _M_use_pointer = true; }; |
727 | * |
728 | * @param _Tp type to give the loser tree traits for. |
729 | */ |
730 | template <typename _Tp> |
731 | struct _LoserTreeTraits |
732 | { |
733 | /** |
734 | * @brief True iff to use pointers instead of values in loser trees. |
735 | * |
736 | * The default behavior is to use pointers if the data type is four |
737 | * times as big as the pointer to it. |
738 | */ |
739 | static const bool _M_use_pointer = (sizeof(_Tp) > 4 * sizeof(_Tp*)); |
740 | }; |
741 | |
742 | /** |
743 | * @brief Switch for 3-way merging with __sentinels turned off. |
744 | * |
745 | * Note that 3-way merging is always stable! |
746 | */ |
747 | template<bool __sentinels /*default == false*/, |
748 | typename _RAIterIterator, |
749 | typename _RAIter3, |
750 | typename _DifferenceTp, |
751 | typename _Compare> |
752 | struct __multiway_merge_3_variant_sentinel_switch |
753 | { |
754 | _RAIter3 |
755 | operator()(_RAIterIterator __seqs_begin, |
756 | _RAIterIterator __seqs_end, |
757 | _RAIter3 __target, |
758 | _DifferenceTp __length, _Compare __comp) |
759 | { return multiway_merge_3_variant<_GuardedIterator> |
760 | (__seqs_begin, __seqs_end, __target, __length, __comp); } |
761 | }; |
762 | |
763 | /** |
764 | * @brief Switch for 3-way merging with __sentinels turned on. |
765 | * |
766 | * Note that 3-way merging is always stable! |
767 | */ |
768 | template<typename _RAIterIterator, |
769 | typename _RAIter3, |
770 | typename _DifferenceTp, |
771 | typename _Compare> |
772 | struct __multiway_merge_3_variant_sentinel_switch<true, _RAIterIterator, |
773 | _RAIter3, _DifferenceTp, |
774 | _Compare> |
775 | { |
776 | _RAIter3 |
777 | operator()(_RAIterIterator __seqs_begin, |
778 | _RAIterIterator __seqs_end, |
779 | _RAIter3 __target, |
780 | _DifferenceTp __length, _Compare __comp) |
781 | { return multiway_merge_3_variant<_UnguardedIterator> |
782 | (__seqs_begin, __seqs_end, __target, __length, __comp); } |
783 | }; |
784 | |
785 | /** |
786 | * @brief Switch for 4-way merging with __sentinels turned off. |
787 | * |
788 | * Note that 4-way merging is always stable! |
789 | */ |
790 | template<bool __sentinels /*default == false*/, |
791 | typename _RAIterIterator, |
792 | typename _RAIter3, |
793 | typename _DifferenceTp, |
794 | typename _Compare> |
795 | struct __multiway_merge_4_variant_sentinel_switch |
796 | { |
797 | _RAIter3 |
798 | operator()(_RAIterIterator __seqs_begin, |
799 | _RAIterIterator __seqs_end, |
800 | _RAIter3 __target, |
801 | _DifferenceTp __length, _Compare __comp) |
802 | { return multiway_merge_4_variant<_GuardedIterator> |
803 | (__seqs_begin, __seqs_end, __target, __length, __comp); } |
804 | }; |
805 | |
806 | /** |
807 | * @brief Switch for 4-way merging with __sentinels turned on. |
808 | * |
809 | * Note that 4-way merging is always stable! |
810 | */ |
811 | template<typename _RAIterIterator, |
812 | typename _RAIter3, |
813 | typename _DifferenceTp, |
814 | typename _Compare> |
815 | struct __multiway_merge_4_variant_sentinel_switch<true, _RAIterIterator, |
816 | _RAIter3, _DifferenceTp, |
817 | _Compare> |
818 | { |
819 | _RAIter3 |
820 | operator()(_RAIterIterator __seqs_begin, |
821 | _RAIterIterator __seqs_end, |
822 | _RAIter3 __target, |
823 | _DifferenceTp __length, _Compare __comp) |
824 | { return multiway_merge_4_variant<_UnguardedIterator> |
825 | (__seqs_begin, __seqs_end, __target, __length, __comp); } |
826 | }; |
827 | |
828 | /** |
829 | * @brief Switch for k-way merging with __sentinels turned on. |
830 | */ |
831 | template<bool __sentinels, |
832 | bool __stable, |
833 | typename _RAIterIterator, |
834 | typename _RAIter3, |
835 | typename _DifferenceTp, |
836 | typename _Compare> |
837 | struct __multiway_merge_k_variant_sentinel_switch |
838 | { |
839 | _RAIter3 |
840 | operator()(_RAIterIterator __seqs_begin, |
841 | _RAIterIterator __seqs_end, |
842 | _RAIter3 __target, |
843 | const typename std::iterator_traits<typename std::iterator_traits< |
844 | _RAIterIterator>::value_type::first_type>::value_type& |
845 | __sentinel, |
846 | _DifferenceTp __length, _Compare __comp) |
847 | { |
848 | typedef typename std::iterator_traits<_RAIterIterator> |
849 | ::value_type::first_type |
850 | _RAIter1; |
851 | typedef typename std::iterator_traits<_RAIter1>::value_type |
852 | _ValueType; |
853 | |
854 | return multiway_merge_loser_tree_sentinel< |
855 | typename __gnu_cxx::__conditional_type< |
856 | _LoserTreeTraits<_ValueType>::_M_use_pointer, |
857 | _LoserTreePointerUnguarded<__stable, _ValueType, _Compare>, |
858 | _LoserTreeUnguarded<__stable, _ValueType, _Compare> |
859 | >::__type> |
860 | (__seqs_begin, __seqs_end, __target, __sentinel, __length, __comp); |
861 | } |
862 | }; |
863 | |
864 | /** |
865 | * @brief Switch for k-way merging with __sentinels turned off. |
866 | */ |
867 | template<bool __stable, |
868 | typename _RAIterIterator, |
869 | typename _RAIter3, |
870 | typename _DifferenceTp, |
871 | typename _Compare> |
872 | struct __multiway_merge_k_variant_sentinel_switch<false, __stable, |
873 | _RAIterIterator, |
874 | _RAIter3, _DifferenceTp, |
875 | _Compare> |
876 | { |
877 | _RAIter3 |
878 | operator()(_RAIterIterator __seqs_begin, |
879 | _RAIterIterator __seqs_end, |
880 | _RAIter3 __target, |
881 | const typename std::iterator_traits<typename std::iterator_traits< |
882 | _RAIterIterator>::value_type::first_type>::value_type& |
883 | __sentinel, |
884 | _DifferenceTp __length, _Compare __comp) |
885 | { |
886 | typedef typename std::iterator_traits<_RAIterIterator> |
887 | ::value_type::first_type |
888 | _RAIter1; |
889 | typedef typename std::iterator_traits<_RAIter1>::value_type |
890 | _ValueType; |
891 | |
892 | return multiway_merge_loser_tree< |
893 | typename __gnu_cxx::__conditional_type< |
894 | _LoserTreeTraits<_ValueType>::_M_use_pointer, |
895 | _LoserTreePointer<__stable, _ValueType, _Compare>, |
896 | _LoserTree<__stable, _ValueType, _Compare> |
897 | >::__type >(__seqs_begin, __seqs_end, __target, __length, __comp); |
898 | } |
899 | }; |
900 | |
901 | /** @brief Sequential multi-way merging switch. |
902 | * |
903 | * The _GLIBCXX_PARALLEL_DECISION is based on the branching factor and |
904 | * runtime settings. |
905 | * @param __seqs_begin Begin iterator of iterator pair input sequence. |
906 | * @param __seqs_end End iterator of iterator pair input sequence. |
907 | * @param __target Begin iterator of output sequence. |
908 | * @param __comp Comparator. |
909 | * @param __length Maximum length to merge, possibly larger than the |
910 | * number of elements available. |
911 | * @param __sentinel The sequences have __a __sentinel element. |
912 | * @return End iterator of output sequence. */ |
913 | template<bool __stable, |
914 | bool __sentinels, |
915 | typename _RAIterIterator, |
916 | typename _RAIter3, |
917 | typename _DifferenceTp, |
918 | typename _Compare> |
919 | _RAIter3 |
920 | __sequential_multiway_merge(_RAIterIterator __seqs_begin, |
921 | _RAIterIterator __seqs_end, |
922 | _RAIter3 __target, |
923 | const typename std::iterator_traits<typename std::iterator_traits< |
924 | _RAIterIterator>::value_type::first_type>::value_type& |
925 | __sentinel, |
926 | _DifferenceTp __length, _Compare __comp) |
927 | { |
928 | _GLIBCXX_CALL(__length) |
929 | |
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 |
935 | _RAIter1; |
936 | typedef typename std::iterator_traits<_RAIter1>::value_type |
937 | _ValueType; |
938 | |
939 | #if _GLIBCXX_PARALLEL_ASSERTIONS |
940 | for (_RAIterIterator __s = __seqs_begin; __s != __seqs_end; ++__s) |
941 | { |
942 | _GLIBCXX_PARALLEL_ASSERT(__is_sorted((*__s).first, |
943 | (*__s).second, __comp)); |
944 | } |
945 | #endif |
946 | |
947 | _DifferenceTp __total_length = 0; |
948 | for (_RAIterIterator __s = __seqs_begin; __s != __seqs_end; ++__s) |
949 | __total_length += _GLIBCXX_PARALLEL_LENGTH(*__s); |
950 | |
951 | __length = std::min<_DifferenceTp>(__length, __total_length); |
952 | |
953 | if(__length == 0) |
954 | return __target; |
955 | |
956 | _RAIter3 __return_target = __target; |
957 | _SeqNumber __k = static_cast<_SeqNumber>(__seqs_end - __seqs_begin); |
958 | |
959 | switch (__k) |
960 | { |
961 | case 0: |
962 | break; |
963 | case 1: |
964 | __return_target = std::copy(__seqs_begin[0].first, |
965 | __seqs_begin[0].first + __length, |
966 | __target); |
967 | __seqs_begin[0].first += __length; |
968 | break; |
969 | case 2: |
970 | __return_target = __merge_advance(__seqs_begin[0].first, |
971 | __seqs_begin[0].second, |
972 | __seqs_begin[1].first, |
973 | __seqs_begin[1].second, |
974 | __target, __length, __comp); |
975 | break; |
976 | case 3: |
977 | __return_target = __multiway_merge_3_variant_sentinel_switch |
978 | <__sentinels, _RAIterIterator, _RAIter3, _DifferenceTp, _Compare>() |
979 | (__seqs_begin, __seqs_end, __target, __length, __comp); |
980 | break; |
981 | case 4: |
982 | __return_target = __multiway_merge_4_variant_sentinel_switch |
983 | <__sentinels, _RAIterIterator, _RAIter3, _DifferenceTp, _Compare>() |
984 | (__seqs_begin, __seqs_end, __target, __length, __comp); |
985 | break; |
986 | default: |
987 | __return_target = __multiway_merge_k_variant_sentinel_switch |
988 | <__sentinels, __stable, _RAIterIterator, _RAIter3, _DifferenceTp, |
989 | _Compare>() |
990 | (__seqs_begin, __seqs_end, __target, __sentinel, __length, __comp); |
991 | break; |
992 | } |
993 | #if _GLIBCXX_PARALLEL_ASSERTIONS |
994 | _GLIBCXX_PARALLEL_ASSERT( |
995 | __is_sorted(__target, __target + __length, __comp)); |
996 | #endif |
997 | |
998 | return __return_target; |
999 | } |
1000 | |
1001 | /** |
1002 | * @brief Stable sorting functor. |
1003 | * |
1004 | * Used to reduce code instanciation in multiway_merge_sampling_splitting. |
1005 | */ |
1006 | template<bool __stable, class _RAIter, class _StrictWeakOrdering> |
1007 | struct _SamplingSorter |
1008 | { |
1009 | void |
1010 | operator()(_RAIter __first, _RAIter __last, _StrictWeakOrdering __comp) |
1011 | { __gnu_sequential::stable_sort(__first, __last, __comp); } |
1012 | }; |
1013 | |
1014 | /** |
1015 | * @brief Non-__stable sorting functor. |
1016 | * |
1017 | * Used to reduce code instantiation in multiway_merge_sampling_splitting. |
1018 | */ |
1019 | template<class _RAIter, class _StrictWeakOrdering> |
1020 | struct _SamplingSorter<false, _RAIter, _StrictWeakOrdering> |
1021 | { |
1022 | void |
1023 | operator()(_RAIter __first, _RAIter __last, _StrictWeakOrdering __comp) |
1024 | { __gnu_sequential::sort(__first, __last, __comp); } |
1025 | }; |
1026 | |
1027 | /** |
1028 | * @brief Sampling based splitting for parallel multiway-merge routine. |
1029 | */ |
1030 | template<bool __stable, |
1031 | typename _RAIterIterator, |
1032 | typename _Compare, |
1033 | typename _DifferenceType> |
1034 | void |
1035 | multiway_merge_sampling_splitting(_RAIterIterator __seqs_begin, |
1036 | _RAIterIterator __seqs_end, |
1037 | _DifferenceType __length, |
1038 | _DifferenceType __total_length, |
1039 | _Compare __comp, |
1040 | std::vector<std::pair<_DifferenceType, _DifferenceType> > *__pieces) |
1041 | { |
1042 | typedef typename std::iterator_traits<_RAIterIterator> |
1043 | ::difference_type _SeqNumber; |
1044 | typedef typename std::iterator_traits<_RAIterIterator> |
1045 | ::value_type::first_type |
1046 | _RAIter1; |
1047 | typedef typename std::iterator_traits<_RAIter1>::value_type |
1048 | _ValueType; |
1049 | |
1050 | // __k sequences. |
1051 | const _SeqNumber __k |
1052 | = static_cast<_SeqNumber>(__seqs_end - __seqs_begin); |
1053 | |
1054 | const _ThreadIndex __num_threads = omp_get_num_threads(); |
1055 | |
1056 | const _DifferenceType __num_samples = |
1057 | __gnu_parallel::_Settings::get().merge_oversampling * __num_threads; |
1058 | |
1059 | _ValueType* __samples = static_cast<_ValueType*> |
1060 | (::operator new(sizeof(_ValueType) * __k * __num_samples)); |
1061 | // Sample. |
1062 | for (_SeqNumber __s = 0; __s < __k; ++__s) |
1063 | for (_DifferenceType __i = 0; __i < __num_samples; ++__i) |
1064 | { |
1065 | _DifferenceType sample_index = static_cast<_DifferenceType> |
1066 | (_GLIBCXX_PARALLEL_LENGTH(__seqs_begin[__s]) |
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]); |
1071 | } |
1072 | |
1073 | // Sort stable or non-stable, depending on value of template parameter |
1074 | // "__stable". |
1075 | _SamplingSorter<__stable, _ValueType*, _Compare>() |
1076 | (__samples, __samples + (__num_samples * __k), __comp); |
1077 | |
1078 | for (_ThreadIndex __slab = 0; __slab < __num_threads; ++__slab) |
1079 | // For each slab / processor. |
1080 | for (_SeqNumber __seq = 0; __seq < __k; ++__seq) |
1081 | { |
1082 | // For each sequence. |
1083 | if (__slab > 0) |
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], |
1087 | __comp) |
1088 | - __seqs_begin[__seq].first; |
1089 | else |
1090 | // Absolute beginning. |
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], |
1096 | __comp) |
1097 | - __seqs_begin[__seq].first; |
1098 | else |
1099 | // Absolute end. |
1100 | __pieces[__slab][__seq].second = |
1101 | _GLIBCXX_PARALLEL_LENGTH(__seqs_begin[__seq]); |
1102 | } |
1103 | |
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); |
1108 | } |
1109 | |
1110 | /** |
1111 | * @brief Exact splitting for parallel multiway-merge routine. |
1112 | * |
1113 | * None of the passed sequences may be empty. |
1114 | */ |
1115 | template<bool __stable, |
1116 | typename _RAIterIterator, |
1117 | typename _Compare, |
1118 | typename _DifferenceType> |
1119 | void |
1120 | multiway_merge_exact_splitting(_RAIterIterator __seqs_begin, |
1121 | _RAIterIterator __seqs_end, |
1122 | _DifferenceType __length, |
1123 | _DifferenceType __total_length, |
1124 | _Compare __comp, |
1125 | std::vector<std::pair<_DifferenceType, _DifferenceType> > *__pieces) |
1126 | { |
1127 | typedef typename std::iterator_traits<_RAIterIterator> |
1128 | ::difference_type _SeqNumber; |
1129 | typedef typename std::iterator_traits<_RAIterIterator> |
1130 | ::value_type::first_type |
1131 | _RAIter1; |
1132 | |
1133 | const bool __tight = (__total_length == __length); |
1134 | |
1135 | // __k sequences. |
1136 | const _SeqNumber __k = __seqs_end - __seqs_begin; |
1137 | |
1138 | const _ThreadIndex __num_threads = omp_get_num_threads(); |
1139 | |
1140 | // (Settings::multiway_merge_splitting |
1141 | // == __gnu_parallel::_Settings::EXACT). |
1142 | std::vector<_RAIter1>* __offsets = |
1143 | new std::vector<_RAIter1>[__num_threads]; |
1144 | std::vector<std::pair<_RAIter1, _RAIter1> > __se(__k); |
1145 | |
1146 | copy(__seqs_begin, __seqs_end, __se.begin()); |
1147 | |
1148 | _DifferenceType* __borders = |
1149 | new _DifferenceType[__num_threads + 1]; |
1150 | __equally_split(__length, __num_threads, __borders); |
1151 | |
1152 | for (_ThreadIndex __s = 0; __s < (__num_threads - 1); ++__s) |
1153 | { |
1154 | __offsets[__s].resize(__k); |
1155 | multiseq_partition(__se.begin(), __se.end(), __borders[__s + 1], |
1156 | __offsets[__s].begin(), __comp); |
1157 | |
1158 | // Last one also needed and available. |
1159 | if (!__tight) |
1160 | { |
1161 | __offsets[__num_threads - 1].resize(__k); |
1162 | multiseq_partition(__se.begin(), __se.end(), |
1163 | _DifferenceType(__length), |
1164 | __offsets[__num_threads - 1].begin(), |
1165 | __comp); |
1166 | } |
1167 | } |
1168 | delete[] __borders; |
1169 | |
1170 | for (_ThreadIndex __slab = 0; __slab < __num_threads; ++__slab) |
1171 | { |
1172 | // For each slab / processor. |
1173 | for (_SeqNumber __seq = 0; __seq < __k; ++__seq) |
1174 | { |
1175 | // For each sequence. |
1176 | if (__slab == 0) |
1177 | { |
1178 | // Absolute beginning. |
1179 | __pieces[__slab][__seq].first = 0; |
1180 | } |
1181 | else |
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; |
1187 | else |
1188 | { |
1189 | // __slab == __num_threads - 1 |
1190 | __pieces[__slab][__seq].second = |
1191 | _GLIBCXX_PARALLEL_LENGTH(__seqs_begin[__seq]); |
1192 | } |
1193 | } |
1194 | } |
1195 | delete[] __offsets; |
1196 | } |
1197 | |
1198 | /** @brief Parallel multi-way merge routine. |
1199 | * |
1200 | * The _GLIBCXX_PARALLEL_DECISION is based on the branching factor |
1201 | * and runtime settings. |
1202 | * |
1203 | * Must not be called if the number of sequences is 1. |
1204 | * |
1205 | * @tparam _Splitter functor to split input (either __exact or sampling based) |
1206 | * @tparam __stable Stable merging incurs a performance penalty. |
1207 | * @tparam __sentinel Ignored. |
1208 | * |
1209 | * @param __seqs_begin Begin iterator of iterator pair input sequence. |
1210 | * @param __seqs_end End iterator of iterator pair input sequence. |
1211 | * @param __target Begin iterator of output sequence. |
1212 | * @param __comp Comparator. |
1213 | * @param __length Maximum length to merge, possibly larger than the |
1214 | * number of elements available. |
1215 | * @return End iterator of output sequence. |
1216 | */ |
1217 | template<bool __stable, |
1218 | bool __sentinels, |
1219 | typename _RAIterIterator, |
1220 | typename _RAIter3, |
1221 | typename _DifferenceTp, |
1222 | typename _Splitter, |
1223 | typename _Compare> |
1224 | _RAIter3 |
1225 | parallel_multiway_merge(_RAIterIterator __seqs_begin, |
1226 | _RAIterIterator __seqs_end, |
1227 | _RAIter3 __target, |
1228 | _Splitter __splitter, |
1229 | _DifferenceTp __length, |
1230 | _Compare __comp, |
1231 | _ThreadIndex __num_threads) |
1232 | { |
1233 | #if _GLIBCXX_PARALLEL_ASSERTIONS |
1234 | _GLIBCXX_PARALLEL_ASSERT(__seqs_end - __seqs_begin > 1); |
1235 | #endif |
1236 | |
1237 | _GLIBCXX_CALL(__length) |
1238 | |
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 |
1244 | _RAIter1; |
1245 | typedef typename |
1246 | std::iterator_traits<_RAIter1>::value_type _ValueType; |
1247 | |
1248 | // Leave only non-empty sequences. |
1249 | typedef std::pair<_RAIter1, _RAIter1> seq_type; |
1250 | seq_type* __ne_seqs = new seq_type[__seqs_end - __seqs_begin]; |
1251 | _SeqNumber __k = 0; |
1252 | _DifferenceType __total_length = 0; |
1253 | for (_RAIterIterator __raii = __seqs_begin; |
1254 | __raii != __seqs_end; ++__raii) |
1255 | { |
1256 | _DifferenceTp __seq_length = _GLIBCXX_PARALLEL_LENGTH(*__raii); |
1257 | if(__seq_length > 0) |
1258 | { |
1259 | __total_length += __seq_length; |
1260 | __ne_seqs[__k++] = *__raii; |
1261 | } |
1262 | } |
1263 | |
1264 | _GLIBCXX_CALL(__total_length) |
1265 | |
1266 | __length = std::min<_DifferenceTp>(__length, __total_length); |
1267 | |
1268 | if (__total_length == 0 || __k == 0) |
1269 | { |
1270 | delete[] __ne_seqs; |
1271 | return __target; |
1272 | } |
1273 | |
1274 | std::vector<std::pair<_DifferenceType, _DifferenceType> >* __pieces; |
1275 | |
1276 | __num_threads = static_cast<_ThreadIndex> |
1277 | (std::min<_DifferenceType>(__num_threads, __total_length)); |
1278 | |
1279 | # pragma omp parallel num_threads (__num_threads) |
1280 | { |
1281 | # pragma omp single |
1282 | { |
1283 | __num_threads = omp_get_num_threads(); |
1284 | // Thread __t will have to merge pieces[__iam][0..__k - 1] |
1285 | __pieces = new std::vector< |
1286 | std::pair<_DifferenceType, _DifferenceType> >[__num_threads]; |
1287 | for (_ThreadIndex __s = 0; __s < __num_threads; ++__s) |
1288 | __pieces[__s].resize(__k); |
1289 | |
1290 | _DifferenceType __num_samples = |
1291 | __gnu_parallel::_Settings::get().merge_oversampling |
1292 | * __num_threads; |
1293 | |
1294 | __splitter(__ne_seqs, __ne_seqs + __k, __length, __total_length, |
1295 | __comp, __pieces); |
1296 | } //single |
1297 | |
1298 | _ThreadIndex __iam = omp_get_thread_num(); |
1299 | |
1300 | _DifferenceType __target_position = 0; |
1301 | |
1302 | for (_SeqNumber __c = 0; __c < __k; ++__c) |
1303 | __target_position += __pieces[__iam][__c].first; |
1304 | |
1305 | seq_type* __chunks = new seq_type[__k]; |
1306 | |
1307 | for (_SeqNumber __s = 0; __s < __k; ++__s) |
1308 | __chunks[__s] = std::make_pair(__ne_seqs[__s].first |
1309 | + __pieces[__iam][__s].first, |
1310 | __ne_seqs[__s].first |
1311 | + __pieces[__iam][__s].second); |
1312 | |
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); |
1317 | |
1318 | delete[] __chunks; |
1319 | } // parallel |
1320 | |
1321 | #if _GLIBCXX_PARALLEL_ASSERTIONS |
1322 | _GLIBCXX_PARALLEL_ASSERT( |
1323 | __is_sorted(__target, __target + __length, __comp)); |
1324 | #endif |
1325 | |
1326 | __k = 0; |
1327 | // Update ends of sequences. |
1328 | for (_RAIterIterator __raii = __seqs_begin; |
1329 | __raii != __seqs_end; ++__raii) |
1330 | { |
1331 | _DifferenceTp __length = _GLIBCXX_PARALLEL_LENGTH(*__raii); |
1332 | if(__length > 0) |
1333 | (*__raii).first += __pieces[__num_threads - 1][__k++].second; |
1334 | } |
1335 | |
1336 | delete[] __pieces; |
1337 | delete[] __ne_seqs; |
1338 | |
1339 | return __target + __length; |
1340 | } |
1341 | |
1342 | /** |
1343 | * @brief Multiway Merge Frontend. |
1344 | * |
1345 | * Merge the sequences specified by seqs_begin and __seqs_end into |
1346 | * __target. __seqs_begin and __seqs_end must point to a sequence of |
1347 | * pairs. These pairs must contain an iterator to the beginning |
1348 | * of a sequence in their first entry and an iterator the _M_end of |
1349 | * the same sequence in their second entry. |
1350 | * |
1351 | * Ties are broken arbitrarily. See stable_multiway_merge for a variant |
1352 | * that breaks ties by sequence number but is slower. |
1353 | * |
1354 | * The first entries of the pairs (i.e. the begin iterators) will be moved |
1355 | * forward. |
1356 | * |
1357 | * The output sequence has to provide enough space for all elements |
1358 | * that are written to it. |
1359 | * |
1360 | * This function will merge the input sequences: |
1361 | * |
1362 | * - not stable |
1363 | * - parallel, depending on the input size and Settings |
1364 | * - using sampling for splitting |
1365 | * - not using sentinels |
1366 | * |
1367 | * Example: |
1368 | * |
1369 | * <pre> |
1370 | * int sequences[10][10]; |
1371 | * for (int __i = 0; __i < 10; ++__i) |
1372 | * for (int __j = 0; __i < 10; ++__j) |
1373 | * sequences[__i][__j] = __j; |
1374 | * |
1375 | * int __out[33]; |
1376 | * std::vector<std::pair<int*> > seqs; |
1377 | * for (int __i = 0; __i < 10; ++__i) |
1378 | * { seqs.push(std::make_pair<int*>(sequences[__i], |
1379 | * sequences[__i] + 10)) } |
1380 | * |
1381 | * multiway_merge(seqs.begin(), seqs.end(), __target, std::less<int>(), 33); |
1382 | * </pre> |
1383 | * |
1384 | * @see stable_multiway_merge |
1385 | * |
1386 | * @pre All input sequences must be sorted. |
1387 | * @pre Target must provide enough space to merge out length elements or |
1388 | * the number of elements in all sequences, whichever is smaller. |
1389 | * |
1390 | * @post [__target, return __value) contains merged __elements from the |
1391 | * input sequences. |
1392 | * @post return __value - __target = min(__length, number of elements in all |
1393 | * sequences). |
1394 | * |
1395 | * @tparam _RAIterPairIterator iterator over sequence |
1396 | * of pairs of iterators |
1397 | * @tparam _RAIterOut iterator over target sequence |
1398 | * @tparam _DifferenceTp difference type for the sequence |
1399 | * @tparam _Compare strict weak ordering type to compare elements |
1400 | * in sequences |
1401 | * |
1402 | * @param __seqs_begin __begin of sequence __sequence |
1403 | * @param __seqs_end _M_end of sequence __sequence |
1404 | * @param __target target sequence to merge to. |
1405 | * @param __comp strict weak ordering to use for element comparison. |
1406 | * @param __length Maximum length to merge, possibly larger than the |
1407 | * number of elements available. |
1408 | * |
1409 | * @return _M_end iterator of output sequence |
1410 | */ |
1411 | // multiway_merge |
1412 | // public interface |
1413 | template<typename _RAIterPairIterator, |
1414 | typename _RAIterOut, |
1415 | typename _DifferenceTp, |
1416 | typename _Compare> |
1417 | _RAIterOut |
1418 | multiway_merge(_RAIterPairIterator __seqs_begin, |
1419 | _RAIterPairIterator __seqs_end, |
1420 | _RAIterOut __target, |
1421 | _DifferenceTp __length, _Compare __comp, |
1422 | __gnu_parallel::sequential_tag) |
1423 | { |
1424 | typedef _DifferenceTp _DifferenceType; |
1425 | _GLIBCXX_CALL(__seqs_end - __seqs_begin) |
1426 | |
1427 | // catch special case: no sequences |
1428 | if (__seqs_begin == __seqs_end) |
1429 | return __target; |
1430 | |
1431 | // Execute multiway merge *sequentially*. |
1432 | return __sequential_multiway_merge |
1433 | </* __stable = */ false, /* __sentinels = */ false> |
1434 | (__seqs_begin, __seqs_end, __target, |
1435 | *(__seqs_begin->second), __length, __comp); |
1436 | } |
1437 | |
1438 | // public interface |
1439 | template<typename _RAIterPairIterator, |
1440 | typename _RAIterOut, |
1441 | typename _DifferenceTp, |
1442 | typename _Compare> |
1443 | _RAIterOut |
1444 | multiway_merge(_RAIterPairIterator __seqs_begin, |
1445 | _RAIterPairIterator __seqs_end, |
1446 | _RAIterOut __target, |
1447 | _DifferenceTp __length, _Compare __comp, |
1448 | __gnu_parallel::exact_tag __tag) |
1449 | { |
1450 | typedef _DifferenceTp _DifferenceType; |
1451 | _GLIBCXX_CALL(__seqs_end - __seqs_begin) |
1452 | |
1453 | // catch special case: no sequences |
1454 | if (__seqs_begin == __seqs_end) |
1455 | return __target; |
1456 | |
1457 | // Execute merge; maybe parallel, depending on the number of merged |
1458 | // elements and the number of sequences and global thresholds in |
1459 | // Settings. |
1460 | if ((__seqs_end - __seqs_begin > 1) |
1461 | && _GLIBCXX_PARALLEL_CONDITION( |
1462 | ((__seqs_end - __seqs_begin) >= |
1463 | __gnu_parallel::_Settings::get().multiway_merge_minimal_k) |
1464 | && ((_SequenceIndex)__length >= |
1465 | __gnu_parallel::_Settings::get().multiway_merge_minimal_n))) |
1466 | return parallel_multiway_merge |
1467 | </* __stable = */ false, /* __sentinels = */ false> |
1468 | (__seqs_begin, __seqs_end, __target, |
1469 | multiway_merge_exact_splitting</* __stable = */ false, |
1470 | typename std::iterator_traits<_RAIterPairIterator> |
1471 | ::value_type*, _Compare, _DifferenceTp>, |
1472 | static_cast<_DifferenceType>(__length), __comp, |
1473 | __tag.__get_num_threads()); |
1474 | else |
1475 | return __sequential_multiway_merge |
1476 | </* __stable = */ false, /* __sentinels = */ false> |
1477 | (__seqs_begin, __seqs_end, __target, |
1478 | *(__seqs_begin->second), __length, __comp); |
1479 | } |
1480 | |
1481 | // public interface |
1482 | template<typename _RAIterPairIterator, |
1483 | typename _RAIterOut, |
1484 | typename _DifferenceTp, |
1485 | typename _Compare> |
1486 | _RAIterOut |
1487 | multiway_merge(_RAIterPairIterator __seqs_begin, |
1488 | _RAIterPairIterator __seqs_end, |
1489 | _RAIterOut __target, |
1490 | _DifferenceTp __length, _Compare __comp, |
1491 | __gnu_parallel::sampling_tag __tag) |
1492 | { |
1493 | typedef _DifferenceTp _DifferenceType; |
1494 | _GLIBCXX_CALL(__seqs_end - __seqs_begin) |
1495 | |
1496 | // catch special case: no sequences |
1497 | if (__seqs_begin == __seqs_end) |
1498 | return __target; |
1499 | |
1500 | // Execute merge; maybe parallel, depending on the number of merged |
1501 | // elements and the number of sequences and global thresholds in |
1502 | // Settings. |
1503 | if ((__seqs_end - __seqs_begin > 1) |
1504 | && _GLIBCXX_PARALLEL_CONDITION( |
1505 | ((__seqs_end - __seqs_begin) >= |
1506 | __gnu_parallel::_Settings::get().multiway_merge_minimal_k) |
1507 | && ((_SequenceIndex)__length >= |
1508 | __gnu_parallel::_Settings::get().multiway_merge_minimal_n))) |
1509 | return parallel_multiway_merge |
1510 | </* __stable = */ false, /* __sentinels = */ false> |
1511 | (__seqs_begin, __seqs_end, __target, |
1512 | multiway_merge_exact_splitting</* __stable = */ false, |
1513 | typename std::iterator_traits<_RAIterPairIterator> |
1514 | ::value_type*, _Compare, _DifferenceTp>, |
1515 | static_cast<_DifferenceType>(__length), __comp, |
1516 | __tag.__get_num_threads()); |
1517 | else |
1518 | return __sequential_multiway_merge |
1519 | </* __stable = */ false, /* __sentinels = */ false> |
1520 | (__seqs_begin, __seqs_end, __target, |
1521 | *(__seqs_begin->second), __length, __comp); |
1522 | } |
1523 | |
1524 | // public interface |
1525 | template<typename _RAIterPairIterator, |
1526 | typename _RAIterOut, |
1527 | typename _DifferenceTp, |
1528 | typename _Compare> |
1529 | _RAIterOut |
1530 | multiway_merge(_RAIterPairIterator __seqs_begin, |
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())); } |
1537 | |
1538 | // public interface |
1539 | template<typename _RAIterPairIterator, |
1540 | typename _RAIterOut, |
1541 | typename _DifferenceTp, |
1542 | typename _Compare> |
1543 | _RAIterOut |
1544 | multiway_merge(_RAIterPairIterator __seqs_begin, |
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())); } |
1551 | |
1552 | // stable_multiway_merge |
1553 | // public interface |
1554 | template<typename _RAIterPairIterator, |
1555 | typename _RAIterOut, |
1556 | typename _DifferenceTp, |
1557 | typename _Compare> |
1558 | _RAIterOut |
1559 | stable_multiway_merge(_RAIterPairIterator __seqs_begin, |
1560 | _RAIterPairIterator __seqs_end, |
1561 | _RAIterOut __target, |
1562 | _DifferenceTp __length, _Compare __comp, |
1563 | __gnu_parallel::sequential_tag) |
1564 | { |
1565 | typedef _DifferenceTp _DifferenceType; |
1566 | _GLIBCXX_CALL(__seqs_end - __seqs_begin) |
1567 | |
1568 | // catch special case: no sequences |
1569 | if (__seqs_begin == __seqs_end) |
1570 | return __target; |
1571 | |
1572 | // Execute multiway merge *sequentially*. |
1573 | return __sequential_multiway_merge |
1574 | </* __stable = */ true, /* __sentinels = */ false> |
1575 | (__seqs_begin, __seqs_end, __target, |
1576 | *(__seqs_begin->second), __length, __comp); |
1577 | } |
1578 | |
1579 | // public interface |
1580 | template<typename _RAIterPairIterator, |
1581 | typename _RAIterOut, |
1582 | typename _DifferenceTp, |
1583 | typename _Compare> |
1584 | _RAIterOut |
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) |
1590 | { |
1591 | typedef _DifferenceTp _DifferenceType; |
1592 | _GLIBCXX_CALL(__seqs_end - __seqs_begin) |
1593 | |
1594 | // catch special case: no sequences |
1595 | if (__seqs_begin == __seqs_end) |
1596 | return __target; |
1597 | |
1598 | // Execute merge; maybe parallel, depending on the number of merged |
1599 | // elements and the number of sequences and global thresholds in |
1600 | // Settings. |
1601 | if ((__seqs_end - __seqs_begin > 1) |
1602 | && _GLIBCXX_PARALLEL_CONDITION( |
1603 | ((__seqs_end - __seqs_begin) >= |
1604 | __gnu_parallel::_Settings::get().multiway_merge_minimal_k) |
1605 | && ((_SequenceIndex)__length >= |
1606 | __gnu_parallel::_Settings::get().multiway_merge_minimal_n))) |
1607 | return parallel_multiway_merge |
1608 | </* __stable = */ true, /* __sentinels = */ false> |
1609 | (__seqs_begin, __seqs_end, __target, |
1610 | multiway_merge_exact_splitting</* __stable = */ true, |
1611 | typename std::iterator_traits<_RAIterPairIterator> |
1612 | ::value_type*, _Compare, _DifferenceTp>, |
1613 | static_cast<_DifferenceType>(__length), __comp, |
1614 | __tag.__get_num_threads()); |
1615 | else |
1616 | return __sequential_multiway_merge |
1617 | </* __stable = */ true, /* __sentinels = */ false> |
1618 | (__seqs_begin, __seqs_end, __target, |
1619 | *(__seqs_begin->second), __length, __comp); |
1620 | } |
1621 | |
1622 | // public interface |
1623 | template<typename _RAIterPairIterator, |
1624 | typename _RAIterOut, |
1625 | typename _DifferenceTp, |
1626 | typename _Compare> |
1627 | _RAIterOut |
1628 | stable_multiway_merge(_RAIterPairIterator __seqs_begin, |
1629 | _RAIterPairIterator __seqs_end, |
1630 | _RAIterOut __target, |
1631 | _DifferenceTp __length, _Compare __comp, |
1632 | sampling_tag __tag) |
1633 | { |
1634 | typedef _DifferenceTp _DifferenceType; |
1635 | _GLIBCXX_CALL(__seqs_end - __seqs_begin) |
1636 | |
1637 | // catch special case: no sequences |
1638 | if (__seqs_begin == __seqs_end) |
1639 | return __target; |
1640 | |
1641 | // Execute merge; maybe parallel, depending on the number of merged |
1642 | // elements and the number of sequences and global thresholds in |
1643 | // Settings. |
1644 | if ((__seqs_end - __seqs_begin > 1) |
1645 | && _GLIBCXX_PARALLEL_CONDITION( |
1646 | ((__seqs_end - __seqs_begin) >= |
1647 | __gnu_parallel::_Settings::get().multiway_merge_minimal_k) |
1648 | && ((_SequenceIndex)__length >= |
1649 | __gnu_parallel::_Settings::get().multiway_merge_minimal_n))) |
1650 | return parallel_multiway_merge |
1651 | </* __stable = */ true, /* __sentinels = */ false> |
1652 | (__seqs_begin, __seqs_end, __target, |
1653 | multiway_merge_sampling_splitting</* __stable = */ true, |
1654 | typename std::iterator_traits<_RAIterPairIterator> |
1655 | ::value_type*, _Compare, _DifferenceTp>, |
1656 | static_cast<_DifferenceType>(__length), __comp, |
1657 | __tag.__get_num_threads()); |
1658 | else |
1659 | return __sequential_multiway_merge |
1660 | </* __stable = */ true, /* __sentinels = */ false> |
1661 | (__seqs_begin, __seqs_end, __target, |
1662 | *(__seqs_begin->second), __length, __comp); |
1663 | } |
1664 | |
1665 | // public interface |
1666 | template<typename _RAIterPairIterator, |
1667 | typename _RAIterOut, |
1668 | typename _DifferenceTp, |
1669 | typename _Compare> |
1670 | _RAIterOut |
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)) |
1676 | { |
1677 | return stable_multiway_merge |
1678 | (__seqs_begin, __seqs_end, __target, __length, __comp, |
1679 | exact_tag(__tag.__get_num_threads())); |
1680 | } |
1681 | |
1682 | // public interface |
1683 | template<typename _RAIterPairIterator, |
1684 | typename _RAIterOut, |
1685 | typename _DifferenceTp, |
1686 | typename _Compare> |
1687 | _RAIterOut |
1688 | stable_multiway_merge(_RAIterPairIterator __seqs_begin, |
1689 | _RAIterPairIterator __seqs_end, |
1690 | _RAIterOut __target, |
1691 | _DifferenceTp __length, _Compare __comp, |
1692 | default_parallel_tag __tag) |
1693 | { |
1694 | return stable_multiway_merge |
1695 | (__seqs_begin, __seqs_end, __target, __length, __comp, |
1696 | exact_tag(__tag.__get_num_threads())); |
1697 | } |
1698 | |
1699 | /** |
1700 | * @brief Multiway Merge Frontend. |
1701 | * |
1702 | * Merge the sequences specified by seqs_begin and __seqs_end into |
1703 | * __target. __seqs_begin and __seqs_end must point to a sequence of |
1704 | * pairs. These pairs must contain an iterator to the beginning |
1705 | * of a sequence in their first entry and an iterator the _M_end of |
1706 | * the same sequence in their second entry. |
1707 | * |
1708 | * Ties are broken arbitrarily. See stable_multiway_merge for a variant |
1709 | * that breaks ties by sequence number but is slower. |
1710 | * |
1711 | * The first entries of the pairs (i.e. the begin iterators) will be moved |
1712 | * forward accordingly. |
1713 | * |
1714 | * The output sequence has to provide enough space for all elements |
1715 | * that are written to it. |
1716 | * |
1717 | * This function will merge the input sequences: |
1718 | * |
1719 | * - not stable |
1720 | * - parallel, depending on the input size and Settings |
1721 | * - using sampling for splitting |
1722 | * - using sentinels |
1723 | * |
1724 | * You have to take care that the element the _M_end iterator points to is |
1725 | * readable and contains a value that is greater than any other non-sentinel |
1726 | * value in all sequences. |
1727 | * |
1728 | * Example: |
1729 | * |
1730 | * <pre> |
1731 | * int sequences[10][11]; |
1732 | * for (int __i = 0; __i < 10; ++__i) |
1733 | * for (int __j = 0; __i < 11; ++__j) |
1734 | * sequences[__i][__j] = __j; // __last one is sentinel! |
1735 | * |
1736 | * int __out[33]; |
1737 | * std::vector<std::pair<int*> > seqs; |
1738 | * for (int __i = 0; __i < 10; ++__i) |
1739 | * { seqs.push(std::make_pair<int*>(sequences[__i], |
1740 | * sequences[__i] + 10)) } |
1741 | * |
1742 | * multiway_merge(seqs.begin(), seqs.end(), __target, std::less<int>(), 33); |
1743 | * </pre> |
1744 | * |
1745 | * @pre All input sequences must be sorted. |
1746 | * @pre Target must provide enough space to merge out length elements or |
1747 | * the number of elements in all sequences, whichever is smaller. |
1748 | * @pre For each @c __i, @c __seqs_begin[__i].second must be the end |
1749 | * marker of the sequence, but also reference the one more __sentinel |
1750 | * element. |
1751 | * |
1752 | * @post [__target, return __value) contains merged __elements from the |
1753 | * input sequences. |
1754 | * @post return __value - __target = min(__length, number of elements in all |
1755 | * sequences). |
1756 | * |
1757 | * @see stable_multiway_merge_sentinels |
1758 | * |
1759 | * @tparam _RAIterPairIterator iterator over sequence |
1760 | * of pairs of iterators |
1761 | * @tparam _RAIterOut iterator over target sequence |
1762 | * @tparam _DifferenceTp difference type for the sequence |
1763 | * @tparam _Compare strict weak ordering type to compare elements |
1764 | * in sequences |
1765 | * |
1766 | * @param __seqs_begin __begin of sequence __sequence |
1767 | * @param __seqs_end _M_end of sequence __sequence |
1768 | * @param __target target sequence to merge to. |
1769 | * @param __comp strict weak ordering to use for element comparison. |
1770 | * @param __length Maximum length to merge, possibly larger than the |
1771 | * number of elements available. |
1772 | * |
1773 | * @return _M_end iterator of output sequence |
1774 | */ |
1775 | // multiway_merge_sentinels |
1776 | // public interface |
1777 | template<typename _RAIterPairIterator, |
1778 | typename _RAIterOut, |
1779 | typename _DifferenceTp, |
1780 | typename _Compare> |
1781 | _RAIterOut |
1782 | multiway_merge_sentinels(_RAIterPairIterator __seqs_begin, |
1783 | _RAIterPairIterator __seqs_end, |
1784 | _RAIterOut __target, |
1785 | _DifferenceTp __length, _Compare __comp, |
1786 | __gnu_parallel::sequential_tag) |
1787 | { |
1788 | typedef _DifferenceTp _DifferenceType; |
1789 | _GLIBCXX_CALL(__seqs_end - __seqs_begin) |
1790 | |
1791 | // catch special case: no sequences |
1792 | if (__seqs_begin == __seqs_end) |
1793 | return __target; |
1794 | |
1795 | // Execute multiway merge *sequentially*. |
1796 | return __sequential_multiway_merge |
1797 | </* __stable = */ false, /* __sentinels = */ true> |
1798 | (__seqs_begin, __seqs_end, |
1799 | __target, *(__seqs_begin->second), __length, __comp); |
1800 | } |
1801 | |
1802 | // public interface |
1803 | template<typename _RAIterPairIterator, |
1804 | typename _RAIterOut, |
1805 | typename _DifferenceTp, |
1806 | typename _Compare> |
1807 | _RAIterOut |
1808 | multiway_merge_sentinels(_RAIterPairIterator __seqs_begin, |
1809 | _RAIterPairIterator __seqs_end, |
1810 | _RAIterOut __target, |
1811 | _DifferenceTp __length, _Compare __comp, |
1812 | __gnu_parallel::exact_tag __tag) |
1813 | { |
1814 | typedef _DifferenceTp _DifferenceType; |
1815 | _GLIBCXX_CALL(__seqs_end - __seqs_begin) |
1816 | |
1817 | // catch special case: no sequences |
1818 | if (__seqs_begin == __seqs_end) |
1819 | return __target; |
1820 | |
1821 | // Execute merge; maybe parallel, depending on the number of merged |
1822 | // elements and the number of sequences and global thresholds in |
1823 | // Settings. |
1824 | if ((__seqs_end - __seqs_begin > 1) |
1825 | && _GLIBCXX_PARALLEL_CONDITION( |
1826 | ((__seqs_end - __seqs_begin) >= |
1827 | __gnu_parallel::_Settings::get().multiway_merge_minimal_k) |
1828 | && ((_SequenceIndex)__length >= |
1829 | __gnu_parallel::_Settings::get().multiway_merge_minimal_n))) |
1830 | return parallel_multiway_merge |
1831 | </* __stable = */ false, /* __sentinels = */ true> |
1832 | (__seqs_begin, __seqs_end, __target, |
1833 | multiway_merge_exact_splitting</* __stable = */ false, |
1834 | typename std::iterator_traits<_RAIterPairIterator> |
1835 | ::value_type*, _Compare, _DifferenceTp>, |
1836 | static_cast<_DifferenceType>(__length), __comp, |
1837 | __tag.__get_num_threads()); |
1838 | else |
1839 | return __sequential_multiway_merge |
1840 | </* __stable = */ false, /* __sentinels = */ true> |
1841 | (__seqs_begin, __seqs_end, __target, |
1842 | *(__seqs_begin->second), __length, __comp); |
1843 | } |
1844 | |
1845 | // public interface |
1846 | template<typename _RAIterPairIterator, |
1847 | typename _RAIterOut, |
1848 | typename _DifferenceTp, |
1849 | typename _Compare> |
1850 | _RAIterOut |
1851 | multiway_merge_sentinels(_RAIterPairIterator __seqs_begin, |
1852 | _RAIterPairIterator __seqs_end, |
1853 | _RAIterOut __target, |
1854 | _DifferenceTp __length, _Compare __comp, |
1855 | sampling_tag __tag) |
1856 | { |
1857 | typedef _DifferenceTp _DifferenceType; |
1858 | _GLIBCXX_CALL(__seqs_end - __seqs_begin) |
1859 | |
1860 | // catch special case: no sequences |
1861 | if (__seqs_begin == __seqs_end) |
1862 | return __target; |
1863 | |
1864 | // Execute merge; maybe parallel, depending on the number of merged |
1865 | // elements and the number of sequences and global thresholds in |
1866 | // Settings. |
1867 | if ((__seqs_end - __seqs_begin > 1) |
1868 | && _GLIBCXX_PARALLEL_CONDITION( |
1869 | ((__seqs_end - __seqs_begin) >= |
1870 | __gnu_parallel::_Settings::get().multiway_merge_minimal_k) |
1871 | && ((_SequenceIndex)__length >= |
1872 | __gnu_parallel::_Settings::get().multiway_merge_minimal_n))) |
1873 | return parallel_multiway_merge |
1874 | </* __stable = */ false, /* __sentinels = */ true> |
1875 | (__seqs_begin, __seqs_end, __target, |
1876 | multiway_merge_sampling_splitting</* __stable = */ false, |
1877 | typename std::iterator_traits<_RAIterPairIterator> |
1878 | ::value_type*, _Compare, _DifferenceTp>, |
1879 | static_cast<_DifferenceType>(__length), __comp, |
1880 | __tag.__get_num_threads()); |
1881 | else |
1882 | return __sequential_multiway_merge |
1883 | </* __stable = */false, /* __sentinels = */ true>( |
1884 | __seqs_begin, __seqs_end, __target, |
1885 | *(__seqs_begin->second), __length, __comp); |
1886 | } |
1887 | |
1888 | // public interface |
1889 | template<typename _RAIterPairIterator, |
1890 | typename _RAIterOut, |
1891 | typename _DifferenceTp, |
1892 | typename _Compare> |
1893 | _RAIterOut |
1894 | multiway_merge_sentinels(_RAIterPairIterator __seqs_begin, |
1895 | _RAIterPairIterator __seqs_end, |
1896 | _RAIterOut __target, |
1897 | _DifferenceTp __length, _Compare __comp, |
1898 | parallel_tag __tag = parallel_tag(0)) |
1899 | { |
1900 | return multiway_merge_sentinels |
1901 | (__seqs_begin, __seqs_end, __target, __length, __comp, |
1902 | exact_tag(__tag.__get_num_threads())); |
1903 | } |
1904 | |
1905 | // public interface |
1906 | template<typename _RAIterPairIterator, |
1907 | typename _RAIterOut, |
1908 | typename _DifferenceTp, |
1909 | typename _Compare> |
1910 | _RAIterOut |
1911 | multiway_merge_sentinels(_RAIterPairIterator __seqs_begin, |
1912 | _RAIterPairIterator __seqs_end, |
1913 | _RAIterOut __target, |
1914 | _DifferenceTp __length, _Compare __comp, |
1915 | default_parallel_tag __tag) |
1916 | { |
1917 | return multiway_merge_sentinels |
1918 | (__seqs_begin, __seqs_end, __target, __length, __comp, |
1919 | exact_tag(__tag.__get_num_threads())); |
1920 | } |
1921 | |
1922 | // stable_multiway_merge_sentinels |
1923 | // public interface |
1924 | template<typename _RAIterPairIterator, |
1925 | typename _RAIterOut, |
1926 | typename _DifferenceTp, |
1927 | typename _Compare> |
1928 | _RAIterOut |
1929 | stable_multiway_merge_sentinels(_RAIterPairIterator __seqs_begin, |
1930 | _RAIterPairIterator __seqs_end, |
1931 | _RAIterOut __target, |
1932 | _DifferenceTp __length, _Compare __comp, |
1933 | __gnu_parallel::sequential_tag) |
1934 | { |
1935 | typedef _DifferenceTp _DifferenceType; |
1936 | _GLIBCXX_CALL(__seqs_end - __seqs_begin) |
1937 | |
1938 | // catch special case: no sequences |
1939 | if (__seqs_begin == __seqs_end) |
1940 | return __target; |
1941 | |
1942 | // Execute multiway merge *sequentially*. |
1943 | return __sequential_multiway_merge |
1944 | </* __stable = */ true, /* __sentinels = */ true> |
1945 | (__seqs_begin, __seqs_end, __target, |
1946 | *(__seqs_begin->second), __length, __comp); |
1947 | } |
1948 | |
1949 | // public interface |
1950 | template<typename _RAIterPairIterator, |
1951 | typename _RAIterOut, |
1952 | typename _DifferenceTp, |
1953 | typename _Compare> |
1954 | _RAIterOut |
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) |
1960 | { |
1961 | typedef _DifferenceTp _DifferenceType; |
1962 | _GLIBCXX_CALL(__seqs_end - __seqs_begin) |
1963 | |
1964 | // catch special case: no sequences |
1965 | if (__seqs_begin == __seqs_end) |
1966 | return __target; |
1967 | |
1968 | // Execute merge; maybe parallel, depending on the number of merged |
1969 | // elements and the number of sequences and global thresholds in |
1970 | // Settings. |
1971 | if ((__seqs_end - __seqs_begin > 1) |
1972 | && _GLIBCXX_PARALLEL_CONDITION( |
1973 | ((__seqs_end - __seqs_begin) >= |
1974 | __gnu_parallel::_Settings::get().multiway_merge_minimal_k) |
1975 | && ((_SequenceIndex)__length >= |
1976 | __gnu_parallel::_Settings::get().multiway_merge_minimal_n))) |
1977 | return parallel_multiway_merge |
1978 | </* __stable = */ true, /* __sentinels = */ true> |
1979 | (__seqs_begin, __seqs_end, __target, |
1980 | multiway_merge_exact_splitting</* __stable = */ true, |
1981 | typename std::iterator_traits<_RAIterPairIterator> |
1982 | ::value_type*, _Compare, _DifferenceTp>, |
1983 | static_cast<_DifferenceType>(__length), __comp, |
1984 | __tag.__get_num_threads()); |
1985 | else |
1986 | return __sequential_multiway_merge |
1987 | </* __stable = */ true, /* __sentinels = */ true> |
1988 | (__seqs_begin, __seqs_end, __target, |
1989 | *(__seqs_begin->second), __length, __comp); |
1990 | } |
1991 | |
1992 | // public interface |
1993 | template<typename _RAIterPairIterator, |
1994 | typename _RAIterOut, |
1995 | typename _DifferenceTp, |
1996 | typename _Compare> |
1997 | _RAIterOut |
1998 | stable_multiway_merge_sentinels(_RAIterPairIterator __seqs_begin, |
1999 | _RAIterPairIterator __seqs_end, |
2000 | _RAIterOut __target, |
2001 | _DifferenceTp __length, |
2002 | _Compare __comp, |
2003 | sampling_tag __tag) |
2004 | { |
2005 | typedef _DifferenceTp _DifferenceType; |
2006 | _GLIBCXX_CALL(__seqs_end - __seqs_begin) |
2007 | |
2008 | // catch special case: no sequences |
2009 | if (__seqs_begin == __seqs_end) |
2010 | return __target; |
2011 | |
2012 | // Execute merge; maybe parallel, depending on the number of merged |
2013 | // elements and the number of sequences and global thresholds in |
2014 | // Settings. |
2015 | if ((__seqs_end - __seqs_begin > 1) |
2016 | && _GLIBCXX_PARALLEL_CONDITION( |
2017 | ((__seqs_end - __seqs_begin) >= |
2018 | __gnu_parallel::_Settings::get().multiway_merge_minimal_k) |
2019 | && ((_SequenceIndex)__length >= |
2020 | __gnu_parallel::_Settings::get().multiway_merge_minimal_n))) |
2021 | return parallel_multiway_merge |
2022 | </* __stable = */ true, /* __sentinels = */ true> |
2023 | (__seqs_begin, __seqs_end, __target, |
2024 | multiway_merge_sampling_splitting</* __stable = */ true, |
2025 | typename std::iterator_traits<_RAIterPairIterator> |
2026 | ::value_type*, _Compare, _DifferenceTp>, |
2027 | static_cast<_DifferenceType>(__length), __comp, |
2028 | __tag.__get_num_threads()); |
2029 | else |
2030 | return __sequential_multiway_merge |
2031 | </* __stable = */ true, /* __sentinels = */ true> |
2032 | (__seqs_begin, __seqs_end, __target, |
2033 | *(__seqs_begin->second), __length, __comp); |
2034 | } |
2035 | |
2036 | // public interface |
2037 | template<typename _RAIterPairIterator, |
2038 | typename _RAIterOut, |
2039 | typename _DifferenceTp, |
2040 | typename _Compare> |
2041 | _RAIterOut |
2042 | stable_multiway_merge_sentinels(_RAIterPairIterator __seqs_begin, |
2043 | _RAIterPairIterator __seqs_end, |
2044 | _RAIterOut __target, |
2045 | _DifferenceTp __length, |
2046 | _Compare __comp, |
2047 | parallel_tag __tag = parallel_tag(0)) |
2048 | { |
2049 | return stable_multiway_merge_sentinels |
2050 | (__seqs_begin, __seqs_end, __target, __length, __comp, |
2051 | exact_tag(__tag.__get_num_threads())); |
2052 | } |
2053 | |
2054 | // public interface |
2055 | template<typename _RAIterPairIterator, |
2056 | typename _RAIterOut, |
2057 | typename _DifferenceTp, |
2058 | typename _Compare> |
2059 | _RAIterOut |
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) |
2065 | { |
2066 | return stable_multiway_merge_sentinels |
2067 | (__seqs_begin, __seqs_end, __target, __length, __comp, |
2068 | exact_tag(__tag.__get_num_threads())); |
2069 | } |
2070 | }; // namespace __gnu_parallel |
2071 | |
2072 | #endif /* _GLIBCXX_PARALLEL_MULTIWAY_MERGE_H */ |
2073 |
Warning: That file was not part of the compilation database. It may have many parsing errors.