3 // Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
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
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.
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.
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/>.
25 /** @file parallel/losertree.h
26 * @brief Many generic loser tree variants.
27 * This file is a GNU parallel extension to the Standard C++ Library.
30 // Written by Johannes Singler.
32 #ifndef _GLIBCXX_PARALLEL_LOSERTREE_H
33 #define _GLIBCXX_PARALLEL_LOSERTREE_H 1
37 #include <bits/stl_algobase.h>
38 #include <parallel/features.h>
39 #include <parallel/base.h>
41 namespace __gnu_parallel
45 * @brief Guarded loser/tournament tree.
47 * The smallest element is at the top.
49 * Guarding is done explicitly through one flag _M_sup per element,
50 * inf is not needed due to a better initialization routine. This
51 * is a well-performing variant.
53 * @param _Tp the element type
54 * @param _Compare the comparator to use, defaults to std::less<_Tp>
56 template<typename _Tp
, typename _Compare
>
60 /** @brief Internal representation of a _LoserTree element. */
63 /** @brief flag, true iff this is a "maximum" __sentinel. */
65 /** @brief __index of the _M_source __sequence. */
67 /** @brief _M_key of the element in the _LoserTree. */
71 unsigned int _M_ik
, _M_k
, _M_offset
;
74 unsigned int _M_log_k
;
76 /** @brief _LoserTree __elements. */
79 /** @brief _Compare to use. */
83 * @brief State flag that determines whether the _LoserTree is empty.
85 * Only used for building the _LoserTree.
91 * @brief The constructor.
93 * @param __k The number of sequences to merge.
94 * @param __comp The comparator to use.
96 _LoserTreeBase(unsigned int __k
, _Compare __comp
)
101 // Compute log_2{_M_k} for the _Loser Tree
102 _M_log_k
= __log2(_M_ik
- 1) + 1;
104 // Next greater power of 2.
105 _M_k
= 1 << _M_log_k
;
108 // Avoid default-constructing _M_losers[]._M_key
110 = static_cast<_Loser
*>(::operator new(2 * _M_k
* sizeof(_Loser
)));
111 for (unsigned int __i
= _M_ik
- 1; __i
< _M_k
; ++__i
)
112 _M_losers
[__i
+ _M_k
]._M_sup
= true;
114 _M_first_insert
= true;
118 * @brief The destructor.
121 { ::operator delete(_M_losers
); }
124 * @brief Initializes the sequence "_M_source" with the element "_M_key".
126 * @param _M_key the element to insert
127 * @param _M_source __index of the _M_source __sequence
128 * @param _M_sup flag that determines whether the value to insert is an
129 * explicit __supremum.
132 __insert_start(const _Tp
& _M_key
, int _M_source
, bool _M_sup
)
134 unsigned int __pos
= _M_k
+ _M_source
;
138 // Construct all keys, so we can easily deconstruct them.
139 for (unsigned int __i
= 0; __i
< (2 * _M_k
); ++__i
)
140 new(&(_M_losers
[__i
]._M_key
)) _Tp(_M_key
);
141 _M_first_insert
= false;
144 new(&(_M_losers
[__pos
]._M_key
)) _Tp(_M_key
);
146 _M_losers
[__pos
]._M_sup
= _M_sup
;
147 _M_losers
[__pos
]._M_source
= _M_source
;
151 * @return the index of the sequence with the smallest element.
153 int __get_min_source()
154 { return _M_losers
[0]._M_source
; }
158 * @brief Stable _LoserTree variant.
160 * Provides the stable implementations of insert_start, __init_winner,
161 * __init and __delete_min_insert.
163 * Unstable variant is done using partial specialisation below.
165 template<bool __stable
/* default == true */, typename _Tp
, typename _Compare
>
166 class _LoserTree
: public _LoserTreeBase
<_Tp
, _Compare
>
168 typedef _LoserTreeBase
<_Tp
, _Compare
> Base
;
170 using Base::_M_losers
;
171 using Base::_M_first_insert
;
174 _LoserTree(unsigned int __k
, _Compare __comp
)
175 : Base::_LoserTreeBase(__k
, __comp
)
179 __init_winner(unsigned int __root
)
187 unsigned int __left
= __init_winner (2 * __root
);
188 unsigned int __right
= __init_winner (2 * __root
+ 1);
189 if (_M_losers
[__right
]._M_sup
190 || (!_M_losers
[__left
]._M_sup
191 && !_M_comp(_M_losers
[__right
]._M_key
, _M_losers
[__left
]._M_key
)))
193 // Left one is less or equal.
194 _M_losers
[__root
] = _M_losers
[__right
];
199 // Right one is less.
200 _M_losers
[__root
] = _M_losers
[__left
];
207 { _M_losers
[0] = _M_losers
[__init_winner(1)]; }
210 * @brief Delete the smallest element and insert a new element from
211 * the previously smallest element's sequence.
213 * This implementation is stable.
215 // Do not pass a const reference since _M_key will be used as local variable.
216 void __delete_min_insert(_Tp _M_key
, bool _M_sup
)
218 #if _GLIBCXX_ASSERTIONS
219 // no dummy sequence can ever be at the top!
220 _GLIBCXX_PARALLEL_ASSERT(_M_losers
[0]._M_source
!= -1);
223 int _M_source
= _M_losers
[0]._M_source
;
224 for (unsigned int __pos
= (_M_k
+ _M_source
) / 2; __pos
> 0; __pos
/= 2)
226 // The smaller one gets promoted, ties are broken by _M_source.
227 if ((_M_sup
&& (!_M_losers
[__pos
]._M_sup
228 || _M_losers
[__pos
]._M_source
< _M_source
))
229 || (!_M_sup
&& !_M_losers
[__pos
]._M_sup
230 && ((_M_comp(_M_losers
[__pos
]._M_key
, _M_key
))
231 || (!_M_comp(_M_key
, _M_losers
[__pos
]._M_key
)
232 && _M_losers
[__pos
]._M_source
< _M_source
))))
234 // The other one is smaller.
235 std::swap(_M_losers
[__pos
]._M_sup
, _M_sup
);
236 std::swap(_M_losers
[__pos
]._M_source
, _M_source
);
237 std::swap(_M_losers
[__pos
]._M_key
, _M_key
);
241 _M_losers
[0]._M_sup
= _M_sup
;
242 _M_losers
[0]._M_source
= _M_source
;
243 _M_losers
[0]._M_key
= _M_key
;
248 * @brief Unstable _LoserTree variant.
250 * Stability (non-stable here) is selected with partial specialization.
252 template<typename _Tp
, typename _Compare
>
253 class _LoserTree
</* __stable == */false, _Tp
, _Compare
> :
254 public _LoserTreeBase
<_Tp
, _Compare
>
256 typedef _LoserTreeBase
<_Tp
, _Compare
> Base
;
257 using Base::_M_log_k
;
259 using Base::_M_losers
;
260 using Base::_M_first_insert
;
263 _LoserTree(unsigned int __k
, _Compare __comp
)
264 : Base::_LoserTreeBase(__k
, __comp
)
268 * Computes the winner of the competition at __position "__root".
270 * Called recursively (starting at 0) to build the initial tree.
272 * @param __root __index of the "game" to start.
275 __init_winner (unsigned int __root
)
283 unsigned int __left
= __init_winner (2 * __root
);
284 unsigned int __right
= __init_winner (2 * __root
+ 1);
285 if (_M_losers
[__right
]._M_sup
286 || (!_M_losers
[__left
]._M_sup
287 && !_M_comp(_M_losers
[__right
]._M_key
, _M_losers
[__left
]._M_key
)))
289 // Left one is less or equal.
290 _M_losers
[__root
] = _M_losers
[__right
];
295 // Right one is less.
296 _M_losers
[__root
] = _M_losers
[__left
];
304 { _M_losers
[0] = _M_losers
[__init_winner(1)]; }
307 * Delete the _M_key smallest element and insert the element _M_key instead.
309 * @param _M_key the _M_key to insert
310 * @param _M_sup true iff _M_key is an explicitly marked supremum
312 // Do not pass a const reference since _M_key will be used as local variable.
314 __delete_min_insert(_Tp _M_key
, bool _M_sup
)
316 #if _GLIBCXX_ASSERTIONS
317 // no dummy sequence can ever be at the top!
318 _GLIBCXX_PARALLEL_ASSERT(_M_losers
[0]._M_source
!= -1);
321 int _M_source
= _M_losers
[0]._M_source
;
322 for (unsigned int __pos
= (_M_k
+ _M_source
) / 2; __pos
> 0; __pos
/= 2)
324 // The smaller one gets promoted.
325 if (_M_sup
|| (!_M_losers
[__pos
]._M_sup
326 && _M_comp(_M_losers
[__pos
]._M_key
, _M_key
)))
328 // The other one is smaller.
329 std::swap(_M_losers
[__pos
]._M_sup
, _M_sup
);
330 std::swap(_M_losers
[__pos
]._M_source
, _M_source
);
331 std::swap(_M_losers
[__pos
]._M_key
, _M_key
);
335 _M_losers
[0]._M_sup
= _M_sup
;
336 _M_losers
[0]._M_source
= _M_source
;
337 _M_losers
[0]._M_key
= _M_key
;
343 * @brief Base class of _Loser Tree implementation using pointers.
345 template<typename _Tp
, typename _Compare
>
346 class _LoserTreePointerBase
349 /** @brief Internal representation of _LoserTree __elements. */
357 unsigned int _M_ik
, _M_k
, _M_offset
;
362 _LoserTreePointerBase(unsigned int __k
, _Compare __comp
= std::less
<_Tp
>())
367 // Next greater power of 2.
368 _M_k
= 1 << (__log2(_M_ik
- 1) + 1);
370 _M_losers
= new _Loser
[_M_k
* 2];
371 for (unsigned int __i
= _M_ik
- 1; __i
< _M_k
; __i
++)
372 _M_losers
[__i
+ _M_k
]._M_sup
= true;
375 ~_LoserTreePointerBase()
376 { ::operator delete[](_M_losers
); }
378 int __get_min_source()
379 { return _M_losers
[0]._M_source
; }
381 void __insert_start(const _Tp
& _M_key
, int _M_source
, bool _M_sup
)
383 unsigned int __pos
= _M_k
+ _M_source
;
385 _M_losers
[__pos
]._M_sup
= _M_sup
;
386 _M_losers
[__pos
]._M_source
= _M_source
;
387 _M_losers
[__pos
]._M_keyp
= &_M_key
;
392 * @brief Stable _LoserTree implementation.
394 * The unstable variant is implemented using partial instantiation below.
396 template<bool __stable
/* default == true */, typename _Tp
, typename _Compare
>
397 class _LoserTreePointer
: public _LoserTreePointerBase
<_Tp
, _Compare
>
399 typedef _LoserTreePointerBase
<_Tp
, _Compare
> Base
;
401 using Base::_M_losers
;
404 _LoserTreePointer(unsigned int __k
, _Compare __comp
= std::less
<_Tp
>())
405 : Base::_LoserTreePointerBase(__k
, __comp
)
409 __init_winner(unsigned int __root
)
417 unsigned int __left
= __init_winner (2 * __root
);
418 unsigned int __right
= __init_winner (2 * __root
+ 1);
419 if (_M_losers
[__right
]._M_sup
420 || (!_M_losers
[__left
]._M_sup
421 && !_M_comp(*_M_losers
[__right
]._M_keyp
,
422 *_M_losers
[__left
]._M_keyp
)))
424 // Left one is less or equal.
425 _M_losers
[__root
] = _M_losers
[__right
];
430 // Right one is less.
431 _M_losers
[__root
] = _M_losers
[__left
];
438 { _M_losers
[0] = _M_losers
[__init_winner(1)]; }
440 void __delete_min_insert(const _Tp
& _M_key
, bool _M_sup
)
442 #if _GLIBCXX_ASSERTIONS
443 // no dummy sequence can ever be at the top!
444 _GLIBCXX_PARALLEL_ASSERT(_M_losers
[0]._M_source
!= -1);
447 const _Tp
* _M_keyp
= &_M_key
;
448 int _M_source
= _M_losers
[0]._M_source
;
449 for (unsigned int __pos
= (_M_k
+ _M_source
) / 2; __pos
> 0; __pos
/= 2)
451 // The smaller one gets promoted, ties are broken by _M_source.
452 if ((_M_sup
&& (!_M_losers
[__pos
]._M_sup
||
453 _M_losers
[__pos
]._M_source
< _M_source
)) ||
454 (!_M_sup
&& !_M_losers
[__pos
]._M_sup
&&
455 ((_M_comp(*_M_losers
[__pos
]._M_keyp
, *_M_keyp
)) ||
456 (!_M_comp(*_M_keyp
, *_M_losers
[__pos
]._M_keyp
)
457 && _M_losers
[__pos
]._M_source
< _M_source
))))
459 // The other one is smaller.
460 std::swap(_M_losers
[__pos
]._M_sup
, _M_sup
);
461 std::swap(_M_losers
[__pos
]._M_source
, _M_source
);
462 std::swap(_M_losers
[__pos
]._M_keyp
, _M_keyp
);
466 _M_losers
[0]._M_sup
= _M_sup
;
467 _M_losers
[0]._M_source
= _M_source
;
468 _M_losers
[0]._M_keyp
= _M_keyp
;
473 * @brief Unstable _LoserTree implementation.
475 * The stable variant is above.
477 template<typename _Tp
, typename _Compare
>
478 class _LoserTreePointer
</* __stable == */false, _Tp
, _Compare
> :
479 public _LoserTreePointerBase
<_Tp
, _Compare
>
481 typedef _LoserTreePointerBase
<_Tp
, _Compare
> Base
;
483 using Base::_M_losers
;
486 _LoserTreePointer(unsigned int __k
, _Compare __comp
= std::less
<_Tp
>())
487 : Base::_LoserTreePointerBase(__k
, __comp
)
491 __init_winner(unsigned int __root
)
499 unsigned int __left
= __init_winner (2 * __root
);
500 unsigned int __right
= __init_winner (2 * __root
+ 1);
501 if (_M_losers
[__right
]._M_sup
502 || (!_M_losers
[__left
]._M_sup
503 && !_M_comp(*_M_losers
[__right
]._M_keyp
,
504 *_M_losers
[__left
]._M_keyp
)))
506 // Left one is less or equal.
507 _M_losers
[__root
] = _M_losers
[__right
];
512 // Right one is less.
513 _M_losers
[__root
] = _M_losers
[__left
];
520 { _M_losers
[0] = _M_losers
[__init_winner(1)]; }
522 void __delete_min_insert(const _Tp
& _M_key
, bool _M_sup
)
524 #if _GLIBCXX_ASSERTIONS
525 // no dummy sequence can ever be at the top!
526 _GLIBCXX_PARALLEL_ASSERT(_M_losers
[0]._M_source
!= -1);
529 const _Tp
* _M_keyp
= &_M_key
;
530 int _M_source
= _M_losers
[0]._M_source
;
531 for (unsigned int __pos
= (_M_k
+ _M_source
) / 2; __pos
> 0; __pos
/= 2)
533 // The smaller one gets promoted.
534 if (_M_sup
|| (!_M_losers
[__pos
]._M_sup
535 && _M_comp(*_M_losers
[__pos
]._M_keyp
, *_M_keyp
)))
537 // The other one is smaller.
538 std::swap(_M_losers
[__pos
]._M_sup
, _M_sup
);
539 std::swap(_M_losers
[__pos
]._M_source
, _M_source
);
540 std::swap(_M_losers
[__pos
]._M_keyp
, _M_keyp
);
544 _M_losers
[0]._M_sup
= _M_sup
;
545 _M_losers
[0]._M_source
= _M_source
;
546 _M_losers
[0]._M_keyp
= _M_keyp
;
550 /** @brief Base class for unguarded _LoserTree implementation.
552 * The whole element is copied into the tree structure.
554 * No guarding is done, therefore not a single input sequence must
555 * run empty. Unused __sequence heads are marked with a sentinel which
556 * is > all elements that are to be merged.
558 * This is a very fast variant.
560 template<typename _Tp
, typename _Compare
>
561 class _LoserTreeUnguardedBase
570 unsigned int _M_ik
, _M_k
, _M_offset
;
576 _LoserTreeUnguardedBase(unsigned int __k
, const _Tp _sentinel
,
577 _Compare __comp
= std::less
<_Tp
>())
582 // Next greater power of 2.
583 _M_k
= 1 << (__log2(_M_ik
- 1) + 1);
585 // Avoid default-constructing _M_losers[]._M_key
587 = static_cast<_Loser
*>(::operator new(2 * _M_k
* sizeof(_Loser
)));
589 for (unsigned int __i
= _M_k
+ _M_ik
- 1; __i
< (2 * _M_k
); ++__i
)
591 _M_losers
[__i
]._M_key
= _sentinel
;
592 _M_losers
[__i
]._M_source
= -1;
596 inline ~_LoserTreeUnguardedBase()
597 { ::operator delete(_M_losers
); }
602 #if _GLIBCXX_ASSERTIONS
603 // no dummy sequence can ever be at the top!
604 _GLIBCXX_PARALLEL_ASSERT(_M_losers
[0]._M_source
!= -1);
606 return _M_losers
[0]._M_source
;
610 __insert_start(const _Tp
& _M_key
, int _M_source
, bool)
612 unsigned int __pos
= _M_k
+ _M_source
;
614 new(&(_M_losers
[__pos
]._M_key
)) _Tp(_M_key
);
615 _M_losers
[__pos
]._M_source
= _M_source
;
620 * @brief Stable implementation of unguarded _LoserTree.
622 * Unstable variant is selected below with partial specialization.
624 template<bool __stable
/* default == true */, typename _Tp
, typename _Compare
>
625 class _LoserTreeUnguarded
: public _LoserTreeUnguardedBase
<_Tp
, _Compare
>
627 typedef _LoserTreeUnguardedBase
<_Tp
, _Compare
> Base
;
629 using Base::_M_losers
;
632 _LoserTreeUnguarded(unsigned int __k
, const _Tp _sentinel
,
633 _Compare __comp
= std::less
<_Tp
>())
634 : Base::_LoserTreeUnguardedBase(__k
, _sentinel
, __comp
)
638 __init_winner(unsigned int __root
)
646 unsigned int __left
= __init_winner (2 * __root
);
647 unsigned int __right
= __init_winner (2 * __root
+ 1);
648 if (!_M_comp(_M_losers
[__right
]._M_key
, _M_losers
[__left
]._M_key
))
650 // Left one is less or equal.
651 _M_losers
[__root
] = _M_losers
[__right
];
656 // Right one is less.
657 _M_losers
[__root
] = _M_losers
[__left
];
666 _M_losers
[0] = _M_losers
[__init_winner(1)];
668 #if _GLIBCXX_ASSERTIONS
669 // no dummy sequence can ever be at the top at the beginning (0 sequences!)
670 _GLIBCXX_PARALLEL_ASSERT(_M_losers
[0]._M_source
!= -1);
674 // Do not pass a const reference since _M_key will be used as local variable.
676 __delete_min_insert(_Tp _M_key
, bool)
678 #if _GLIBCXX_ASSERTIONS
679 // no dummy sequence can ever be at the top!
680 _GLIBCXX_PARALLEL_ASSERT(_M_losers
[0]._M_source
!= -1);
683 int _M_source
= _M_losers
[0]._M_source
;
684 for (unsigned int __pos
= (_M_k
+ _M_source
) / 2; __pos
> 0; __pos
/= 2)
686 // The smaller one gets promoted, ties are broken by _M_source.
687 if (_M_comp(_M_losers
[__pos
]._M_key
, _M_key
)
688 || (!_M_comp(_M_key
, _M_losers
[__pos
]._M_key
)
689 && _M_losers
[__pos
]._M_source
< _M_source
))
691 // The other one is smaller.
692 std::swap(_M_losers
[__pos
]._M_source
, _M_source
);
693 std::swap(_M_losers
[__pos
]._M_key
, _M_key
);
697 _M_losers
[0]._M_source
= _M_source
;
698 _M_losers
[0]._M_key
= _M_key
;
703 * @brief Non-Stable implementation of unguarded _LoserTree.
705 * Stable implementation is above.
707 template<typename _Tp
, typename _Compare
>
708 class _LoserTreeUnguarded
</* __stable == */false, _Tp
, _Compare
> :
709 public _LoserTreeUnguardedBase
<_Tp
, _Compare
>
711 typedef _LoserTreeUnguardedBase
<_Tp
, _Compare
> Base
;
713 using Base::_M_losers
;
716 _LoserTreeUnguarded(unsigned int __k
, const _Tp _sentinel
,
717 _Compare __comp
= std::less
<_Tp
>())
718 : Base::_LoserTreeUnguardedBase(__k
, _sentinel
, __comp
)
722 __init_winner (unsigned int __root
)
730 unsigned int __left
= __init_winner (2 * __root
);
731 unsigned int __right
= __init_winner (2 * __root
+ 1);
733 #if _GLIBCXX_ASSERTIONS
734 // If __left one is sentinel then __right one must be, too.
735 if (_M_losers
[__left
]._M_source
== -1)
736 _GLIBCXX_PARALLEL_ASSERT(_M_losers
[__right
]._M_source
== -1);
739 if (!_M_comp(_M_losers
[__right
]._M_key
, _M_losers
[__left
]._M_key
))
741 // Left one is less or equal.
742 _M_losers
[__root
] = _M_losers
[__right
];
747 // Right one is less.
748 _M_losers
[__root
] = _M_losers
[__left
];
757 _M_losers
[0] = _M_losers
[__init_winner(1)];
759 #if _GLIBCXX_ASSERTIONS
760 // no dummy sequence can ever be at the top at the beginning (0 sequences!)
761 _GLIBCXX_PARALLEL_ASSERT(_M_losers
[0]._M_source
!= -1);
765 // Do not pass a const reference since _M_key will be used as local variable.
767 __delete_min_insert(_Tp _M_key
, bool)
769 #if _GLIBCXX_ASSERTIONS
770 // no dummy sequence can ever be at the top!
771 _GLIBCXX_PARALLEL_ASSERT(_M_losers
[0]._M_source
!= -1);
774 int _M_source
= _M_losers
[0]._M_source
;
775 for (unsigned int __pos
= (_M_k
+ _M_source
) / 2; __pos
> 0; __pos
/= 2)
777 // The smaller one gets promoted.
778 if (_M_comp(_M_losers
[__pos
]._M_key
, _M_key
))
780 // The other one is smaller.
781 std::swap(_M_losers
[__pos
]._M_source
, _M_source
);
782 std::swap(_M_losers
[__pos
]._M_key
, _M_key
);
786 _M_losers
[0]._M_source
= _M_source
;
787 _M_losers
[0]._M_key
= _M_key
;
791 /** @brief Unguarded loser tree, keeping only pointers to the
792 * __elements in the tree structure.
794 * No guarding is done, therefore not a single input sequence must
795 * run empty. This is a very fast variant.
797 template<typename _Tp
, typename _Compare
>
798 class LoserTreePointerUnguardedBase
807 unsigned int _M_ik
, _M_k
, _M_offset
;
814 LoserTreePointerUnguardedBase(unsigned int __k
, const _Tp
& _sentinel
,
815 _Compare __comp
= std::less
<_Tp
>())
820 // Next greater power of 2.
821 _M_k
= 1 << (__log2(_M_ik
- 1) + 1);
823 // Avoid default-constructing _M_losers[]._M_key
824 _M_losers
= new _Loser
[2 * _M_k
];
826 for (unsigned int __i
= _M_k
+ _M_ik
- 1; __i
< (2 * _M_k
); ++__i
)
828 _M_losers
[__i
]._M_keyp
= &_sentinel
;
829 _M_losers
[__i
]._M_source
= -1;
833 inline ~LoserTreePointerUnguardedBase()
834 { delete[] _M_losers
; }
839 #if _GLIBCXX_ASSERTIONS
840 // no dummy sequence can ever be at the top!
841 _GLIBCXX_PARALLEL_ASSERT(_M_losers
[0]._M_source
!= -1);
843 return _M_losers
[0]._M_source
;
847 __insert_start(const _Tp
& _M_key
, int _M_source
, bool)
849 unsigned int __pos
= _M_k
+ _M_source
;
851 _M_losers
[__pos
]._M_keyp
= &_M_key
;
852 _M_losers
[__pos
]._M_source
= _M_source
;
857 * @brief Stable unguarded _LoserTree variant storing pointers.
859 * Unstable variant is implemented below using partial specialization.
861 template<bool __stable
/* default == true */, typename _Tp
, typename _Compare
>
862 class LoserTreePointerUnguarded
:
863 public LoserTreePointerUnguardedBase
<_Tp
, _Compare
>
865 typedef LoserTreePointerUnguardedBase
<_Tp
, _Compare
> Base
;
867 using Base::_M_losers
;
870 LoserTreePointerUnguarded(unsigned int __k
, const _Tp
& _sentinel
,
871 _Compare __comp
= std::less
<_Tp
>())
872 : Base::LoserTreePointerUnguardedBase(__k
, _sentinel
, __comp
)
876 __init_winner(unsigned int __root
)
884 unsigned int __left
= __init_winner (2 * __root
);
885 unsigned int __right
= __init_winner (2 * __root
+ 1);
886 if (!_M_comp(*_M_losers
[__right
]._M_keyp
, *_M_losers
[__left
]._M_keyp
))
888 // Left one is less or equal.
889 _M_losers
[__root
] = _M_losers
[__right
];
894 // Right one is less.
895 _M_losers
[__root
] = _M_losers
[__left
];
904 _M_losers
[0] = _M_losers
[__init_winner(1)];
906 #if _GLIBCXX_ASSERTIONS
907 // no dummy sequence can ever be at the top at the beginning (0 sequences!)
908 _GLIBCXX_PARALLEL_ASSERT(_M_losers
[0]._M_source
!= -1);
913 __delete_min_insert(const _Tp
& _M_key
, bool _M_sup
)
915 #if _GLIBCXX_ASSERTIONS
916 // no dummy sequence can ever be at the top!
917 _GLIBCXX_PARALLEL_ASSERT(_M_losers
[0]._M_source
!= -1);
920 const _Tp
* _M_keyp
= &_M_key
;
921 int _M_source
= _M_losers
[0]._M_source
;
922 for (unsigned int __pos
= (_M_k
+ _M_source
) / 2; __pos
> 0; __pos
/= 2)
924 // The smaller one gets promoted, ties are broken by _M_source.
925 if (_M_comp(*_M_losers
[__pos
]._M_keyp
, *_M_keyp
)
926 || (!_M_comp(*_M_keyp
, *_M_losers
[__pos
]._M_keyp
)
927 && _M_losers
[__pos
]._M_source
< _M_source
))
929 // The other one is smaller.
930 std::swap(_M_losers
[__pos
]._M_source
, _M_source
);
931 std::swap(_M_losers
[__pos
]._M_keyp
, _M_keyp
);
935 _M_losers
[0]._M_source
= _M_source
;
936 _M_losers
[0]._M_keyp
= _M_keyp
;
941 * @brief Unstable unguarded _LoserTree variant storing pointers.
943 * Stable variant is above.
945 template<typename _Tp
, typename _Compare
>
946 class LoserTreePointerUnguarded
</* __stable == */false, _Tp
, _Compare
> :
947 public LoserTreePointerUnguardedBase
<_Tp
, _Compare
>
949 typedef LoserTreePointerUnguardedBase
<_Tp
, _Compare
> Base
;
951 using Base::_M_losers
;
954 LoserTreePointerUnguarded(unsigned int __k
, const _Tp
& _sentinel
,
955 _Compare __comp
= std::less
<_Tp
>())
956 : Base::LoserTreePointerUnguardedBase(__k
, _sentinel
, __comp
)
960 __init_winner(unsigned int __root
)
968 unsigned int __left
= __init_winner (2 * __root
);
969 unsigned int __right
= __init_winner (2 * __root
+ 1);
971 #if _GLIBCXX_ASSERTIONS
972 // If __left one is sentinel then __right one must be, too.
973 if (_M_losers
[__left
]._M_source
== -1)
974 _GLIBCXX_PARALLEL_ASSERT(_M_losers
[__right
]._M_source
== -1);
977 if (!_M_comp(*_M_losers
[__right
]._M_keyp
, *_M_losers
[__left
]._M_keyp
))
979 // Left one is less or equal.
980 _M_losers
[__root
] = _M_losers
[__right
];
985 // Right one is less.
986 _M_losers
[__root
] = _M_losers
[__left
];
995 _M_losers
[0] = _M_losers
[__init_winner(1)];
997 #if _GLIBCXX_ASSERTIONS
998 // no dummy sequence can ever be at the top at the beginning (0 sequences!)
999 _GLIBCXX_PARALLEL_ASSERT(_M_losers
[0]._M_source
!= -1);
1004 __delete_min_insert(const _Tp
& _M_key
, bool _M_sup
)
1006 #if _GLIBCXX_ASSERTIONS
1007 // no dummy sequence can ever be at the top!
1008 _GLIBCXX_PARALLEL_ASSERT(_M_losers
[0]._M_source
!= -1);
1011 const _Tp
* _M_keyp
= &_M_key
;
1012 int _M_source
= _M_losers
[0]._M_source
;
1013 for (unsigned int __pos
= (_M_k
+ _M_source
) / 2; __pos
> 0; __pos
/= 2)
1015 // The smaller one gets promoted.
1016 if (_M_comp(*(_M_losers
[__pos
]._M_keyp
), *_M_keyp
))
1018 // The other one is smaller.
1019 std::swap(_M_losers
[__pos
]._M_source
, _M_source
);
1020 std::swap(_M_losers
[__pos
]._M_keyp
, _M_keyp
);
1024 _M_losers
[0]._M_source
= _M_source
;
1025 _M_losers
[0]._M_keyp
= _M_keyp
;
1029 } // namespace __gnu_parallel
1031 #endif /* _GLIBCXX_PARALLEL_LOSERTREE_H */