xref: /dflybsd-src/contrib/gcc-4.7/libstdc++-v3/include/parallel/losertree.h (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
1*e4b17023SJohn Marino // -*- C++ -*-
2*e4b17023SJohn Marino 
3*e4b17023SJohn Marino // Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
4*e4b17023SJohn Marino //
5*e4b17023SJohn Marino // This file is part of the GNU ISO C++ Library.  This library is free
6*e4b17023SJohn Marino // software; you can redistribute it and/or modify it under the terms
7*e4b17023SJohn Marino // of the GNU General Public License as published by the Free Software
8*e4b17023SJohn Marino // Foundation; either version 3, or (at your option) any later
9*e4b17023SJohn Marino // version.
10*e4b17023SJohn Marino 
11*e4b17023SJohn Marino // This library is distributed in the hope that it will be useful, but
12*e4b17023SJohn Marino // WITHOUT ANY WARRANTY; without even the implied warranty of
13*e4b17023SJohn Marino // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14*e4b17023SJohn Marino // General Public License for more details.
15*e4b17023SJohn Marino 
16*e4b17023SJohn Marino // Under Section 7 of GPL version 3, you are granted additional
17*e4b17023SJohn Marino // permissions described in the GCC Runtime Library Exception, version
18*e4b17023SJohn Marino // 3.1, as published by the Free Software Foundation.
19*e4b17023SJohn Marino 
20*e4b17023SJohn Marino // You should have received a copy of the GNU General Public License and
21*e4b17023SJohn Marino // a copy of the GCC Runtime Library Exception along with this program;
22*e4b17023SJohn Marino // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23*e4b17023SJohn Marino // <http://www.gnu.org/licenses/>.
24*e4b17023SJohn Marino 
25*e4b17023SJohn Marino /** @file parallel/losertree.h
26*e4b17023SJohn Marino *  @brief Many generic loser tree variants.
27*e4b17023SJohn Marino *  This file is a GNU parallel extension to the Standard C++ Library.
28*e4b17023SJohn Marino */
29*e4b17023SJohn Marino 
30*e4b17023SJohn Marino // Written by Johannes Singler.
31*e4b17023SJohn Marino 
32*e4b17023SJohn Marino #ifndef _GLIBCXX_PARALLEL_LOSERTREE_H
33*e4b17023SJohn Marino #define _GLIBCXX_PARALLEL_LOSERTREE_H 1
34*e4b17023SJohn Marino 
35*e4b17023SJohn Marino #include <bits/stl_algobase.h>
36*e4b17023SJohn Marino #include <bits/stl_function.h>
37*e4b17023SJohn Marino #include <parallel/features.h>
38*e4b17023SJohn Marino #include <parallel/base.h>
39*e4b17023SJohn Marino 
40*e4b17023SJohn Marino namespace __gnu_parallel
41*e4b17023SJohn Marino {
42*e4b17023SJohn Marino   /**
43*e4b17023SJohn Marino    * @brief Guarded loser/tournament tree.
44*e4b17023SJohn Marino    *
45*e4b17023SJohn Marino    * The smallest element is at the top.
46*e4b17023SJohn Marino    *
47*e4b17023SJohn Marino    * Guarding is done explicitly through one flag _M_sup per element,
48*e4b17023SJohn Marino    * inf is not needed due to a better initialization routine.  This
49*e4b17023SJohn Marino    * is a well-performing variant.
50*e4b17023SJohn Marino    *
51*e4b17023SJohn Marino    * @param _Tp the element type
52*e4b17023SJohn Marino    * @param _Compare the comparator to use, defaults to std::less<_Tp>
53*e4b17023SJohn Marino    */
54*e4b17023SJohn Marino   template<typename _Tp, typename _Compare>
55*e4b17023SJohn Marino     class _LoserTreeBase
56*e4b17023SJohn Marino     {
57*e4b17023SJohn Marino     protected:
58*e4b17023SJohn Marino       /** @brief Internal representation of a _LoserTree element. */
59*e4b17023SJohn Marino       struct _Loser
60*e4b17023SJohn Marino       {
61*e4b17023SJohn Marino 	/** @brief flag, true iff this is a "maximum" __sentinel. */
62*e4b17023SJohn Marino 	bool _M_sup;
63*e4b17023SJohn Marino 	/** @brief __index of the __source __sequence. */
64*e4b17023SJohn Marino 	int _M_source;
65*e4b17023SJohn Marino 	/** @brief _M_key of the element in the _LoserTree. */
66*e4b17023SJohn Marino 	_Tp _M_key;
67*e4b17023SJohn Marino       };
68*e4b17023SJohn Marino 
69*e4b17023SJohn Marino       unsigned int _M_ik, _M_k, _M_offset;
70*e4b17023SJohn Marino 
71*e4b17023SJohn Marino       /** log_2{_M_k} */
72*e4b17023SJohn Marino       unsigned int _M_log_k;
73*e4b17023SJohn Marino 
74*e4b17023SJohn Marino       /** @brief _LoserTree __elements. */
75*e4b17023SJohn Marino       _Loser* _M_losers;
76*e4b17023SJohn Marino 
77*e4b17023SJohn Marino       /** @brief _Compare to use. */
78*e4b17023SJohn Marino       _Compare _M_comp;
79*e4b17023SJohn Marino 
80*e4b17023SJohn Marino       /**
81*e4b17023SJohn Marino        * @brief State flag that determines whether the _LoserTree is empty.
82*e4b17023SJohn Marino        *
83*e4b17023SJohn Marino        * Only used for building the _LoserTree.
84*e4b17023SJohn Marino        */
85*e4b17023SJohn Marino       bool _M_first_insert;
86*e4b17023SJohn Marino 
87*e4b17023SJohn Marino     public:
88*e4b17023SJohn Marino       /**
89*e4b17023SJohn Marino        * @brief The constructor.
90*e4b17023SJohn Marino        *
91*e4b17023SJohn Marino        * @param __k The number of sequences to merge.
92*e4b17023SJohn Marino        * @param __comp The comparator to use.
93*e4b17023SJohn Marino        */
_LoserTreeBase(unsigned int __k,_Compare __comp)94*e4b17023SJohn Marino       _LoserTreeBase(unsigned int __k, _Compare __comp)
95*e4b17023SJohn Marino       : _M_comp(__comp)
96*e4b17023SJohn Marino       {
97*e4b17023SJohn Marino 	_M_ik = __k;
98*e4b17023SJohn Marino 
99*e4b17023SJohn Marino 	// Compute log_2{_M_k} for the _Loser Tree
100*e4b17023SJohn Marino 	_M_log_k = __rd_log2(_M_ik - 1) + 1;
101*e4b17023SJohn Marino 
102*e4b17023SJohn Marino 	// Next greater power of 2.
103*e4b17023SJohn Marino 	_M_k = 1 << _M_log_k;
104*e4b17023SJohn Marino 	_M_offset = _M_k;
105*e4b17023SJohn Marino 
106*e4b17023SJohn Marino 	// Avoid default-constructing _M_losers[]._M_key
107*e4b17023SJohn Marino 	_M_losers = static_cast<_Loser*>(::operator new(2 * _M_k
108*e4b17023SJohn Marino 							* sizeof(_Loser)));
109*e4b17023SJohn Marino 	for (unsigned int __i = _M_ik - 1; __i < _M_k; ++__i)
110*e4b17023SJohn Marino 	  _M_losers[__i + _M_k]._M_sup = true;
111*e4b17023SJohn Marino 
112*e4b17023SJohn Marino 	_M_first_insert = true;
113*e4b17023SJohn Marino       }
114*e4b17023SJohn Marino 
115*e4b17023SJohn Marino       /**
116*e4b17023SJohn Marino        * @brief The destructor.
117*e4b17023SJohn Marino        */
~_LoserTreeBase()118*e4b17023SJohn Marino       ~_LoserTreeBase()
119*e4b17023SJohn Marino       {
120*e4b17023SJohn Marino 	for (unsigned int __i = 0; __i < (2 * _M_k); ++__i)
121*e4b17023SJohn Marino 	  _M_losers[__i].~_Loser();
122*e4b17023SJohn Marino 	::operator delete(_M_losers);
123*e4b17023SJohn Marino       }
124*e4b17023SJohn Marino 
125*e4b17023SJohn Marino       /**
126*e4b17023SJohn Marino        * @brief Initializes the sequence "_M_source" with the element "__key".
127*e4b17023SJohn Marino        *
128*e4b17023SJohn Marino        * @param __key the element to insert
129*e4b17023SJohn Marino        * @param __source __index of the __source __sequence
130*e4b17023SJohn Marino        * @param __sup flag that determines whether the value to insert is an
131*e4b17023SJohn Marino        *   explicit __supremum.
132*e4b17023SJohn Marino        */
133*e4b17023SJohn Marino       void
__insert_start(const _Tp & __key,int __source,bool __sup)134*e4b17023SJohn Marino       __insert_start(const _Tp& __key, int __source, bool __sup)
135*e4b17023SJohn Marino       {
136*e4b17023SJohn Marino 	unsigned int __pos = _M_k + __source;
137*e4b17023SJohn Marino 
138*e4b17023SJohn Marino 	if (_M_first_insert)
139*e4b17023SJohn Marino 	  {
140*e4b17023SJohn Marino 	    // Construct all keys, so we can easily destruct them.
141*e4b17023SJohn Marino 	    for (unsigned int __i = 0; __i < (2 * _M_k); ++__i)
142*e4b17023SJohn Marino 	      ::new(&(_M_losers[__i]._M_key)) _Tp(__key);
143*e4b17023SJohn Marino 	    _M_first_insert = false;
144*e4b17023SJohn Marino 	  }
145*e4b17023SJohn Marino 	else
146*e4b17023SJohn Marino 	  _M_losers[__pos]._M_key = __key;
147*e4b17023SJohn Marino 
148*e4b17023SJohn Marino 	_M_losers[__pos]._M_sup = __sup;
149*e4b17023SJohn Marino 	_M_losers[__pos]._M_source = __source;
150*e4b17023SJohn Marino       }
151*e4b17023SJohn Marino 
152*e4b17023SJohn Marino       /**
153*e4b17023SJohn Marino        * @return the index of the sequence with the smallest element.
154*e4b17023SJohn Marino        */
__get_min_source()155*e4b17023SJohn Marino       int __get_min_source()
156*e4b17023SJohn Marino       { return _M_losers[0]._M_source; }
157*e4b17023SJohn Marino     };
158*e4b17023SJohn Marino 
159*e4b17023SJohn Marino     /**
160*e4b17023SJohn Marino      * @brief Stable _LoserTree variant.
161*e4b17023SJohn Marino      *
162*e4b17023SJohn Marino      * Provides the stable implementations of insert_start, __init_winner,
163*e4b17023SJohn Marino      * __init and __delete_min_insert.
164*e4b17023SJohn Marino      *
165*e4b17023SJohn Marino      * Unstable variant is done using partial specialisation below.
166*e4b17023SJohn Marino      */
167*e4b17023SJohn Marino   template<bool __stable/* default == true */, typename _Tp,
168*e4b17023SJohn Marino 	   typename _Compare>
169*e4b17023SJohn Marino     class _LoserTree
170*e4b17023SJohn Marino     : public _LoserTreeBase<_Tp, _Compare>
171*e4b17023SJohn Marino     {
172*e4b17023SJohn Marino       typedef _LoserTreeBase<_Tp, _Compare> _Base;
173*e4b17023SJohn Marino       using _Base::_M_k;
174*e4b17023SJohn Marino       using _Base::_M_comp;
175*e4b17023SJohn Marino       using _Base::_M_losers;
176*e4b17023SJohn Marino       using _Base::_M_first_insert;
177*e4b17023SJohn Marino 
178*e4b17023SJohn Marino     public:
_LoserTree(unsigned int __k,_Compare __comp)179*e4b17023SJohn Marino       _LoserTree(unsigned int __k, _Compare __comp)
180*e4b17023SJohn Marino       : _Base::_LoserTreeBase(__k, __comp)
181*e4b17023SJohn Marino       { }
182*e4b17023SJohn Marino 
183*e4b17023SJohn Marino       unsigned int
__init_winner(unsigned int __root)184*e4b17023SJohn Marino       __init_winner(unsigned int __root)
185*e4b17023SJohn Marino       {
186*e4b17023SJohn Marino 	if (__root >= _M_k)
187*e4b17023SJohn Marino 	  return __root;
188*e4b17023SJohn Marino 	else
189*e4b17023SJohn Marino 	  {
190*e4b17023SJohn Marino 	    unsigned int __left = __init_winner(2 * __root);
191*e4b17023SJohn Marino 	    unsigned int __right = __init_winner(2 * __root + 1);
192*e4b17023SJohn Marino 	    if (_M_losers[__right]._M_sup
193*e4b17023SJohn Marino 		|| (!_M_losers[__left]._M_sup
194*e4b17023SJohn Marino 		    && !_M_comp(_M_losers[__right]._M_key,
195*e4b17023SJohn Marino 				_M_losers[__left]._M_key)))
196*e4b17023SJohn Marino 	      {
197*e4b17023SJohn Marino 		// Left one is less or equal.
198*e4b17023SJohn Marino 		_M_losers[__root] = _M_losers[__right];
199*e4b17023SJohn Marino 		return __left;
200*e4b17023SJohn Marino 	      }
201*e4b17023SJohn Marino 	    else
202*e4b17023SJohn Marino 	      {
203*e4b17023SJohn Marino 		// Right one is less.
204*e4b17023SJohn Marino 		_M_losers[__root] = _M_losers[__left];
205*e4b17023SJohn Marino 		return __right;
206*e4b17023SJohn Marino 	      }
207*e4b17023SJohn Marino 	  }
208*e4b17023SJohn Marino       }
209*e4b17023SJohn Marino 
__init()210*e4b17023SJohn Marino       void __init()
211*e4b17023SJohn Marino       { _M_losers[0] = _M_losers[__init_winner(1)]; }
212*e4b17023SJohn Marino 
213*e4b17023SJohn Marino       /**
214*e4b17023SJohn Marino        * @brief Delete the smallest element and insert a new element from
215*e4b17023SJohn Marino        *   the previously smallest element's sequence.
216*e4b17023SJohn Marino        *
217*e4b17023SJohn Marino        * This implementation is stable.
218*e4b17023SJohn Marino        */
219*e4b17023SJohn Marino       // Do not pass a const reference since __key will be used as
220*e4b17023SJohn Marino       // local variable.
221*e4b17023SJohn Marino       void
__delete_min_insert(_Tp __key,bool __sup)222*e4b17023SJohn Marino       __delete_min_insert(_Tp __key, bool __sup)
223*e4b17023SJohn Marino       {
224*e4b17023SJohn Marino         using std::swap;
225*e4b17023SJohn Marino #if _GLIBCXX_ASSERTIONS
226*e4b17023SJohn Marino 	// no dummy sequence can ever be at the top!
227*e4b17023SJohn Marino 	_GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1);
228*e4b17023SJohn Marino #endif
229*e4b17023SJohn Marino 
230*e4b17023SJohn Marino 	int __source = _M_losers[0]._M_source;
231*e4b17023SJohn Marino 	for (unsigned int __pos = (_M_k + __source) / 2; __pos > 0;
232*e4b17023SJohn Marino 	     __pos /= 2)
233*e4b17023SJohn Marino 	  {
234*e4b17023SJohn Marino 	    // The smaller one gets promoted, ties are broken by _M_source.
235*e4b17023SJohn Marino 	    if ((__sup && (!_M_losers[__pos]._M_sup
236*e4b17023SJohn Marino 			   || _M_losers[__pos]._M_source < __source))
237*e4b17023SJohn Marino 		|| (!__sup && !_M_losers[__pos]._M_sup
238*e4b17023SJohn Marino 		    && ((_M_comp(_M_losers[__pos]._M_key, __key))
239*e4b17023SJohn Marino 			|| (!_M_comp(__key, _M_losers[__pos]._M_key)
240*e4b17023SJohn Marino 			    && _M_losers[__pos]._M_source < __source))))
241*e4b17023SJohn Marino 	      {
242*e4b17023SJohn Marino 		// The other one is smaller.
243*e4b17023SJohn Marino 		std::swap(_M_losers[__pos]._M_sup, __sup);
244*e4b17023SJohn Marino 		std::swap(_M_losers[__pos]._M_source, __source);
245*e4b17023SJohn Marino 		swap(_M_losers[__pos]._M_key, __key);
246*e4b17023SJohn Marino 	      }
247*e4b17023SJohn Marino 	  }
248*e4b17023SJohn Marino 
249*e4b17023SJohn Marino 	_M_losers[0]._M_sup = __sup;
250*e4b17023SJohn Marino 	_M_losers[0]._M_source = __source;
251*e4b17023SJohn Marino 	_M_losers[0]._M_key = __key;
252*e4b17023SJohn Marino       }
253*e4b17023SJohn Marino     };
254*e4b17023SJohn Marino 
255*e4b17023SJohn Marino     /**
256*e4b17023SJohn Marino      * @brief Unstable _LoserTree variant.
257*e4b17023SJohn Marino      *
258*e4b17023SJohn Marino      * Stability (non-stable here) is selected with partial specialization.
259*e4b17023SJohn Marino      */
260*e4b17023SJohn Marino   template<typename _Tp, typename _Compare>
261*e4b17023SJohn Marino     class _LoserTree</* __stable == */false, _Tp, _Compare>
262*e4b17023SJohn Marino     : public _LoserTreeBase<_Tp, _Compare>
263*e4b17023SJohn Marino     {
264*e4b17023SJohn Marino       typedef _LoserTreeBase<_Tp, _Compare> _Base;
265*e4b17023SJohn Marino       using _Base::_M_log_k;
266*e4b17023SJohn Marino       using _Base::_M_k;
267*e4b17023SJohn Marino       using _Base::_M_comp;
268*e4b17023SJohn Marino       using _Base::_M_losers;
269*e4b17023SJohn Marino       using _Base::_M_first_insert;
270*e4b17023SJohn Marino 
271*e4b17023SJohn Marino     public:
_LoserTree(unsigned int __k,_Compare __comp)272*e4b17023SJohn Marino       _LoserTree(unsigned int __k, _Compare __comp)
273*e4b17023SJohn Marino       : _Base::_LoserTreeBase(__k, __comp)
274*e4b17023SJohn Marino       { }
275*e4b17023SJohn Marino 
276*e4b17023SJohn Marino       /**
277*e4b17023SJohn Marino        * Computes the winner of the competition at position "__root".
278*e4b17023SJohn Marino        *
279*e4b17023SJohn Marino        * Called recursively (starting at 0) to build the initial tree.
280*e4b17023SJohn Marino        *
281*e4b17023SJohn Marino        * @param __root __index of the "game" to start.
282*e4b17023SJohn Marino        */
283*e4b17023SJohn Marino       unsigned int
__init_winner(unsigned int __root)284*e4b17023SJohn Marino       __init_winner(unsigned int __root)
285*e4b17023SJohn Marino       {
286*e4b17023SJohn Marino 	if (__root >= _M_k)
287*e4b17023SJohn Marino 	  return __root;
288*e4b17023SJohn Marino 	else
289*e4b17023SJohn Marino 	  {
290*e4b17023SJohn Marino 	    unsigned int __left = __init_winner(2 * __root);
291*e4b17023SJohn Marino 	    unsigned int __right = __init_winner(2 * __root + 1);
292*e4b17023SJohn Marino 	    if (_M_losers[__right]._M_sup
293*e4b17023SJohn Marino 		|| (!_M_losers[__left]._M_sup
294*e4b17023SJohn Marino 		    && !_M_comp(_M_losers[__right]._M_key,
295*e4b17023SJohn Marino 				_M_losers[__left]._M_key)))
296*e4b17023SJohn Marino 	      {
297*e4b17023SJohn Marino 		// Left one is less or equal.
298*e4b17023SJohn Marino 		_M_losers[__root] = _M_losers[__right];
299*e4b17023SJohn Marino 		return __left;
300*e4b17023SJohn Marino 	      }
301*e4b17023SJohn Marino 	    else
302*e4b17023SJohn Marino 	      {
303*e4b17023SJohn Marino 		// Right one is less.
304*e4b17023SJohn Marino 		_M_losers[__root] = _M_losers[__left];
305*e4b17023SJohn Marino 		return __right;
306*e4b17023SJohn Marino 	      }
307*e4b17023SJohn Marino 	  }
308*e4b17023SJohn Marino       }
309*e4b17023SJohn Marino 
310*e4b17023SJohn Marino       void
__init()311*e4b17023SJohn Marino       __init()
312*e4b17023SJohn Marino       { _M_losers[0] = _M_losers[__init_winner(1)]; }
313*e4b17023SJohn Marino 
314*e4b17023SJohn Marino       /**
315*e4b17023SJohn Marino        * Delete the _M_key smallest element and insert the element __key
316*e4b17023SJohn Marino        * instead.
317*e4b17023SJohn Marino        *
318*e4b17023SJohn Marino        * @param __key the _M_key to insert
319*e4b17023SJohn Marino        * @param __sup true iff __key is an explicitly marked supremum
320*e4b17023SJohn Marino        */
321*e4b17023SJohn Marino       // Do not pass a const reference since __key will be used as local
322*e4b17023SJohn Marino       // variable.
323*e4b17023SJohn Marino       void
__delete_min_insert(_Tp __key,bool __sup)324*e4b17023SJohn Marino       __delete_min_insert(_Tp __key, bool __sup)
325*e4b17023SJohn Marino       {
326*e4b17023SJohn Marino         using std::swap;
327*e4b17023SJohn Marino #if _GLIBCXX_ASSERTIONS
328*e4b17023SJohn Marino 	// no dummy sequence can ever be at the top!
329*e4b17023SJohn Marino 	_GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1);
330*e4b17023SJohn Marino #endif
331*e4b17023SJohn Marino 
332*e4b17023SJohn Marino 	int __source = _M_losers[0]._M_source;
333*e4b17023SJohn Marino 	for (unsigned int __pos = (_M_k + __source) / 2; __pos > 0;
334*e4b17023SJohn Marino 	     __pos /= 2)
335*e4b17023SJohn Marino 	  {
336*e4b17023SJohn Marino 	    // The smaller one gets promoted.
337*e4b17023SJohn Marino 	    if (__sup || (!_M_losers[__pos]._M_sup
338*e4b17023SJohn Marino 			  && _M_comp(_M_losers[__pos]._M_key, __key)))
339*e4b17023SJohn Marino 	      {
340*e4b17023SJohn Marino 		// The other one is smaller.
341*e4b17023SJohn Marino 		std::swap(_M_losers[__pos]._M_sup, __sup);
342*e4b17023SJohn Marino 		std::swap(_M_losers[__pos]._M_source, __source);
343*e4b17023SJohn Marino 		swap(_M_losers[__pos]._M_key, __key);
344*e4b17023SJohn Marino 	      }
345*e4b17023SJohn Marino 	  }
346*e4b17023SJohn Marino 
347*e4b17023SJohn Marino 	_M_losers[0]._M_sup = __sup;
348*e4b17023SJohn Marino 	_M_losers[0]._M_source = __source;
349*e4b17023SJohn Marino 	_M_losers[0]._M_key = __key;
350*e4b17023SJohn Marino       }
351*e4b17023SJohn Marino     };
352*e4b17023SJohn Marino 
353*e4b17023SJohn Marino   /**
354*e4b17023SJohn Marino    * @brief Base class of _Loser Tree implementation using pointers.
355*e4b17023SJohn Marino    */
356*e4b17023SJohn Marino   template<typename _Tp, typename _Compare>
357*e4b17023SJohn Marino     class _LoserTreePointerBase
358*e4b17023SJohn Marino     {
359*e4b17023SJohn Marino     protected:
360*e4b17023SJohn Marino       /** @brief Internal representation of _LoserTree __elements. */
361*e4b17023SJohn Marino       struct _Loser
362*e4b17023SJohn Marino       {
363*e4b17023SJohn Marino 	bool _M_sup;
364*e4b17023SJohn Marino 	int _M_source;
365*e4b17023SJohn Marino 	const _Tp* _M_keyp;
366*e4b17023SJohn Marino       };
367*e4b17023SJohn Marino 
368*e4b17023SJohn Marino       unsigned int _M_ik, _M_k, _M_offset;
369*e4b17023SJohn Marino       _Loser* _M_losers;
370*e4b17023SJohn Marino       _Compare _M_comp;
371*e4b17023SJohn Marino 
372*e4b17023SJohn Marino     public:
373*e4b17023SJohn Marino       _LoserTreePointerBase(unsigned int __k,
374*e4b17023SJohn Marino 			    _Compare __comp = std::less<_Tp>())
_M_comp(__comp)375*e4b17023SJohn Marino       : _M_comp(__comp)
376*e4b17023SJohn Marino       {
377*e4b17023SJohn Marino 	_M_ik = __k;
378*e4b17023SJohn Marino 
379*e4b17023SJohn Marino 	// Next greater power of 2.
380*e4b17023SJohn Marino 	_M_k = 1 << (__rd_log2(_M_ik - 1) + 1);
381*e4b17023SJohn Marino 	_M_offset = _M_k;
382*e4b17023SJohn Marino 	_M_losers = new _Loser[_M_k * 2];
383*e4b17023SJohn Marino 	for (unsigned int __i = _M_ik - 1; __i < _M_k; __i++)
384*e4b17023SJohn Marino 	  _M_losers[__i + _M_k]._M_sup = true;
385*e4b17023SJohn Marino       }
386*e4b17023SJohn Marino 
~_LoserTreePointerBase()387*e4b17023SJohn Marino       ~_LoserTreePointerBase()
388*e4b17023SJohn Marino       { delete[] _M_losers; }
389*e4b17023SJohn Marino 
__get_min_source()390*e4b17023SJohn Marino       int __get_min_source()
391*e4b17023SJohn Marino       { return _M_losers[0]._M_source; }
392*e4b17023SJohn Marino 
__insert_start(const _Tp & __key,int __source,bool __sup)393*e4b17023SJohn Marino       void __insert_start(const _Tp& __key, int __source, bool __sup)
394*e4b17023SJohn Marino       {
395*e4b17023SJohn Marino 	unsigned int __pos = _M_k + __source;
396*e4b17023SJohn Marino 
397*e4b17023SJohn Marino 	_M_losers[__pos]._M_sup = __sup;
398*e4b17023SJohn Marino 	_M_losers[__pos]._M_source = __source;
399*e4b17023SJohn Marino 	_M_losers[__pos]._M_keyp = &__key;
400*e4b17023SJohn Marino       }
401*e4b17023SJohn Marino     };
402*e4b17023SJohn Marino 
403*e4b17023SJohn Marino   /**
404*e4b17023SJohn Marino    * @brief Stable _LoserTree implementation.
405*e4b17023SJohn Marino    *
406*e4b17023SJohn Marino    * The unstable variant is implemented using partial instantiation below.
407*e4b17023SJohn Marino    */
408*e4b17023SJohn Marino   template<bool __stable/* default == true */, typename _Tp, typename _Compare>
409*e4b17023SJohn Marino     class _LoserTreePointer
410*e4b17023SJohn Marino     : public _LoserTreePointerBase<_Tp, _Compare>
411*e4b17023SJohn Marino     {
412*e4b17023SJohn Marino       typedef _LoserTreePointerBase<_Tp, _Compare> _Base;
413*e4b17023SJohn Marino       using _Base::_M_k;
414*e4b17023SJohn Marino       using _Base::_M_comp;
415*e4b17023SJohn Marino       using _Base::_M_losers;
416*e4b17023SJohn Marino 
417*e4b17023SJohn Marino     public:
418*e4b17023SJohn Marino       _LoserTreePointer(unsigned int __k, _Compare __comp = std::less<_Tp>())
_LoserTreePointerBase(__k,__comp)419*e4b17023SJohn Marino       : _Base::_LoserTreePointerBase(__k, __comp)
420*e4b17023SJohn Marino       { }
421*e4b17023SJohn Marino 
422*e4b17023SJohn Marino       unsigned int
__init_winner(unsigned int __root)423*e4b17023SJohn Marino       __init_winner(unsigned int __root)
424*e4b17023SJohn Marino       {
425*e4b17023SJohn Marino 	if (__root >= _M_k)
426*e4b17023SJohn Marino 	  return __root;
427*e4b17023SJohn Marino 	else
428*e4b17023SJohn Marino 	  {
429*e4b17023SJohn Marino 	    unsigned int __left = __init_winner(2 * __root);
430*e4b17023SJohn Marino 	    unsigned int __right = __init_winner(2 * __root + 1);
431*e4b17023SJohn Marino 	    if (_M_losers[__right]._M_sup
432*e4b17023SJohn Marino 		|| (!_M_losers[__left]._M_sup
433*e4b17023SJohn Marino 		    && !_M_comp(*_M_losers[__right]._M_keyp,
434*e4b17023SJohn Marino 				*_M_losers[__left]._M_keyp)))
435*e4b17023SJohn Marino 	      {
436*e4b17023SJohn Marino 		// Left one is less or equal.
437*e4b17023SJohn Marino 		_M_losers[__root] = _M_losers[__right];
438*e4b17023SJohn Marino 		return __left;
439*e4b17023SJohn Marino 	      }
440*e4b17023SJohn Marino 	    else
441*e4b17023SJohn Marino 	      {
442*e4b17023SJohn Marino 		// Right one is less.
443*e4b17023SJohn Marino 		_M_losers[__root] = _M_losers[__left];
444*e4b17023SJohn Marino 		return __right;
445*e4b17023SJohn Marino 	      }
446*e4b17023SJohn Marino 	  }
447*e4b17023SJohn Marino       }
448*e4b17023SJohn Marino 
__init()449*e4b17023SJohn Marino       void __init()
450*e4b17023SJohn Marino       { _M_losers[0] = _M_losers[__init_winner(1)]; }
451*e4b17023SJohn Marino 
__delete_min_insert(const _Tp & __key,bool __sup)452*e4b17023SJohn Marino       void __delete_min_insert(const _Tp& __key, bool __sup)
453*e4b17023SJohn Marino       {
454*e4b17023SJohn Marino #if _GLIBCXX_ASSERTIONS
455*e4b17023SJohn Marino 	// no dummy sequence can ever be at the top!
456*e4b17023SJohn Marino 	_GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1);
457*e4b17023SJohn Marino #endif
458*e4b17023SJohn Marino 
459*e4b17023SJohn Marino 	const _Tp* __keyp = &__key;
460*e4b17023SJohn Marino 	int __source = _M_losers[0]._M_source;
461*e4b17023SJohn Marino 	for (unsigned int __pos = (_M_k + __source) / 2; __pos > 0;
462*e4b17023SJohn Marino 	     __pos /= 2)
463*e4b17023SJohn Marino 	  {
464*e4b17023SJohn Marino 	    // The smaller one gets promoted, ties are broken by __source.
465*e4b17023SJohn Marino 	    if ((__sup && (!_M_losers[__pos]._M_sup
466*e4b17023SJohn Marino 			   || _M_losers[__pos]._M_source < __source))
467*e4b17023SJohn Marino 		|| (!__sup && !_M_losers[__pos]._M_sup &&
468*e4b17023SJohn Marino 		    ((_M_comp(*_M_losers[__pos]._M_keyp, *__keyp))
469*e4b17023SJohn Marino 		     || (!_M_comp(*__keyp, *_M_losers[__pos]._M_keyp)
470*e4b17023SJohn Marino 			 && _M_losers[__pos]._M_source < __source))))
471*e4b17023SJohn Marino 	      {
472*e4b17023SJohn Marino 		// The other one is smaller.
473*e4b17023SJohn Marino 		std::swap(_M_losers[__pos]._M_sup, __sup);
474*e4b17023SJohn Marino 		std::swap(_M_losers[__pos]._M_source, __source);
475*e4b17023SJohn Marino 		std::swap(_M_losers[__pos]._M_keyp, __keyp);
476*e4b17023SJohn Marino 	      }
477*e4b17023SJohn Marino 	  }
478*e4b17023SJohn Marino 
479*e4b17023SJohn Marino 	_M_losers[0]._M_sup = __sup;
480*e4b17023SJohn Marino 	_M_losers[0]._M_source = __source;
481*e4b17023SJohn Marino 	_M_losers[0]._M_keyp = __keyp;
482*e4b17023SJohn Marino       }
483*e4b17023SJohn Marino     };
484*e4b17023SJohn Marino 
485*e4b17023SJohn Marino   /**
486*e4b17023SJohn Marino    * @brief Unstable _LoserTree implementation.
487*e4b17023SJohn Marino    *
488*e4b17023SJohn Marino    * The stable variant is above.
489*e4b17023SJohn Marino    */
490*e4b17023SJohn Marino   template<typename _Tp, typename _Compare>
491*e4b17023SJohn Marino     class _LoserTreePointer</* __stable == */false, _Tp, _Compare>
492*e4b17023SJohn Marino     : public _LoserTreePointerBase<_Tp, _Compare>
493*e4b17023SJohn Marino     {
494*e4b17023SJohn Marino       typedef _LoserTreePointerBase<_Tp, _Compare> _Base;
495*e4b17023SJohn Marino       using _Base::_M_k;
496*e4b17023SJohn Marino       using _Base::_M_comp;
497*e4b17023SJohn Marino       using _Base::_M_losers;
498*e4b17023SJohn Marino 
499*e4b17023SJohn Marino     public:
500*e4b17023SJohn Marino       _LoserTreePointer(unsigned int __k, _Compare __comp = std::less<_Tp>())
_LoserTreePointerBase(__k,__comp)501*e4b17023SJohn Marino       : _Base::_LoserTreePointerBase(__k, __comp)
502*e4b17023SJohn Marino       { }
503*e4b17023SJohn Marino 
504*e4b17023SJohn Marino       unsigned int
__init_winner(unsigned int __root)505*e4b17023SJohn Marino       __init_winner(unsigned int __root)
506*e4b17023SJohn Marino       {
507*e4b17023SJohn Marino 	if (__root >= _M_k)
508*e4b17023SJohn Marino 	  return __root;
509*e4b17023SJohn Marino 	else
510*e4b17023SJohn Marino 	  {
511*e4b17023SJohn Marino 	    unsigned int __left = __init_winner(2 * __root);
512*e4b17023SJohn Marino 	    unsigned int __right = __init_winner(2 * __root + 1);
513*e4b17023SJohn Marino 	    if (_M_losers[__right]._M_sup
514*e4b17023SJohn Marino         	|| (!_M_losers[__left]._M_sup
515*e4b17023SJohn Marino 		    && !_M_comp(*_M_losers[__right]._M_keyp,
516*e4b17023SJohn Marino 				*_M_losers[__left]._M_keyp)))
517*e4b17023SJohn Marino 	      {
518*e4b17023SJohn Marino 		// Left one is less or equal.
519*e4b17023SJohn Marino 		_M_losers[__root] = _M_losers[__right];
520*e4b17023SJohn Marino 		return __left;
521*e4b17023SJohn Marino 	      }
522*e4b17023SJohn Marino 	    else
523*e4b17023SJohn Marino 	      {
524*e4b17023SJohn Marino 		// Right one is less.
525*e4b17023SJohn Marino 		_M_losers[__root] = _M_losers[__left];
526*e4b17023SJohn Marino 		return __right;
527*e4b17023SJohn Marino 	      }
528*e4b17023SJohn Marino 	  }
529*e4b17023SJohn Marino       }
530*e4b17023SJohn Marino 
__init()531*e4b17023SJohn Marino       void __init()
532*e4b17023SJohn Marino       { _M_losers[0] = _M_losers[__init_winner(1)]; }
533*e4b17023SJohn Marino 
__delete_min_insert(const _Tp & __key,bool __sup)534*e4b17023SJohn Marino       void __delete_min_insert(const _Tp& __key, bool __sup)
535*e4b17023SJohn Marino       {
536*e4b17023SJohn Marino #if _GLIBCXX_ASSERTIONS
537*e4b17023SJohn Marino 	// no dummy sequence can ever be at the top!
538*e4b17023SJohn Marino 	_GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1);
539*e4b17023SJohn Marino #endif
540*e4b17023SJohn Marino 
541*e4b17023SJohn Marino 	const _Tp* __keyp = &__key;
542*e4b17023SJohn Marino 	int __source = _M_losers[0]._M_source;
543*e4b17023SJohn Marino 	for (unsigned int __pos = (_M_k + __source) / 2; __pos > 0;
544*e4b17023SJohn Marino 	     __pos /= 2)
545*e4b17023SJohn Marino 	  {
546*e4b17023SJohn Marino 	    // The smaller one gets promoted.
547*e4b17023SJohn Marino 	    if (__sup || (!_M_losers[__pos]._M_sup
548*e4b17023SJohn Marino 			  && _M_comp(*_M_losers[__pos]._M_keyp, *__keyp)))
549*e4b17023SJohn Marino 	      {
550*e4b17023SJohn Marino 		// The other one is smaller.
551*e4b17023SJohn Marino 		std::swap(_M_losers[__pos]._M_sup, __sup);
552*e4b17023SJohn Marino 		std::swap(_M_losers[__pos]._M_source, __source);
553*e4b17023SJohn Marino 		std::swap(_M_losers[__pos]._M_keyp, __keyp);
554*e4b17023SJohn Marino 	      }
555*e4b17023SJohn Marino 	  }
556*e4b17023SJohn Marino 
557*e4b17023SJohn Marino 	_M_losers[0]._M_sup = __sup;
558*e4b17023SJohn Marino 	_M_losers[0]._M_source = __source;
559*e4b17023SJohn Marino 	_M_losers[0]._M_keyp = __keyp;
560*e4b17023SJohn Marino       }
561*e4b17023SJohn Marino     };
562*e4b17023SJohn Marino 
563*e4b17023SJohn Marino   /** @brief Base class for unguarded _LoserTree implementation.
564*e4b17023SJohn Marino    *
565*e4b17023SJohn Marino    * The whole element is copied into the tree structure.
566*e4b17023SJohn Marino    *
567*e4b17023SJohn Marino    * No guarding is done, therefore not a single input sequence must
568*e4b17023SJohn Marino    * run empty.  Unused __sequence heads are marked with a sentinel which
569*e4b17023SJohn Marino    * is &gt; all elements that are to be merged.
570*e4b17023SJohn Marino    *
571*e4b17023SJohn Marino    * This is a very fast variant.
572*e4b17023SJohn Marino    */
573*e4b17023SJohn Marino   template<typename _Tp, typename _Compare>
574*e4b17023SJohn Marino     class _LoserTreeUnguardedBase
575*e4b17023SJohn Marino     {
576*e4b17023SJohn Marino     protected:
577*e4b17023SJohn Marino       struct _Loser
578*e4b17023SJohn Marino       {
579*e4b17023SJohn Marino 	int _M_source;
580*e4b17023SJohn Marino 	_Tp _M_key;
581*e4b17023SJohn Marino       };
582*e4b17023SJohn Marino 
583*e4b17023SJohn Marino       unsigned int _M_ik, _M_k, _M_offset;
584*e4b17023SJohn Marino       _Loser* _M_losers;
585*e4b17023SJohn Marino       _Compare _M_comp;
586*e4b17023SJohn Marino 
587*e4b17023SJohn Marino     public:
588*e4b17023SJohn Marino       _LoserTreeUnguardedBase(unsigned int __k, const _Tp& __sentinel,
589*e4b17023SJohn Marino 			      _Compare __comp = std::less<_Tp>())
_M_comp(__comp)590*e4b17023SJohn Marino       : _M_comp(__comp)
591*e4b17023SJohn Marino       {
592*e4b17023SJohn Marino 	_M_ik = __k;
593*e4b17023SJohn Marino 
594*e4b17023SJohn Marino 	// Next greater power of 2.
595*e4b17023SJohn Marino 	_M_k = 1 << (__rd_log2(_M_ik - 1) + 1);
596*e4b17023SJohn Marino 	_M_offset = _M_k;
597*e4b17023SJohn Marino 	// Avoid default-constructing _M_losers[]._M_key
598*e4b17023SJohn Marino 	_M_losers = static_cast<_Loser*>(::operator new(2 * _M_k
599*e4b17023SJohn Marino 							* sizeof(_Loser)));
600*e4b17023SJohn Marino 
601*e4b17023SJohn Marino         for (unsigned int __i = 0; __i < _M_k; ++__i)
602*e4b17023SJohn Marino           {
603*e4b17023SJohn Marino 	    ::new(&(_M_losers[__i]._M_key)) _Tp(__sentinel);
604*e4b17023SJohn Marino 	    _M_losers[__i]._M_source = -1;
605*e4b17023SJohn Marino 	  }
606*e4b17023SJohn Marino         for (unsigned int __i = _M_k + _M_ik - 1; __i < (2 * _M_k); ++__i)
607*e4b17023SJohn Marino           {
608*e4b17023SJohn Marino 	    ::new(&(_M_losers[__i]._M_key)) _Tp(__sentinel);
609*e4b17023SJohn Marino 	    _M_losers[__i]._M_source = -1;
610*e4b17023SJohn Marino 	  }
611*e4b17023SJohn Marino       }
612*e4b17023SJohn Marino 
~_LoserTreeUnguardedBase()613*e4b17023SJohn Marino       ~_LoserTreeUnguardedBase()
614*e4b17023SJohn Marino       {
615*e4b17023SJohn Marino 	for (unsigned int __i = 0; __i < (2 * _M_k); ++__i)
616*e4b17023SJohn Marino 	  _M_losers[__i].~_Loser();
617*e4b17023SJohn Marino 	::operator delete(_M_losers);
618*e4b17023SJohn Marino       }
619*e4b17023SJohn Marino 
620*e4b17023SJohn Marino       int
__get_min_source()621*e4b17023SJohn Marino       __get_min_source()
622*e4b17023SJohn Marino       {
623*e4b17023SJohn Marino #if _GLIBCXX_ASSERTIONS
624*e4b17023SJohn Marino 	// no dummy sequence can ever be at the top!
625*e4b17023SJohn Marino 	_GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1);
626*e4b17023SJohn Marino #endif
627*e4b17023SJohn Marino 	return _M_losers[0]._M_source;
628*e4b17023SJohn Marino       }
629*e4b17023SJohn Marino 
630*e4b17023SJohn Marino       void
__insert_start(const _Tp & __key,int __source,bool)631*e4b17023SJohn Marino       __insert_start(const _Tp& __key, int __source, bool)
632*e4b17023SJohn Marino       {
633*e4b17023SJohn Marino 	unsigned int __pos = _M_k + __source;
634*e4b17023SJohn Marino 
635*e4b17023SJohn Marino 	::new(&(_M_losers[__pos]._M_key)) _Tp(__key);
636*e4b17023SJohn Marino 	_M_losers[__pos]._M_source = __source;
637*e4b17023SJohn Marino       }
638*e4b17023SJohn Marino     };
639*e4b17023SJohn Marino 
640*e4b17023SJohn Marino   /**
641*e4b17023SJohn Marino    * @brief Stable implementation of unguarded _LoserTree.
642*e4b17023SJohn Marino    *
643*e4b17023SJohn Marino    * Unstable variant is selected below with partial specialization.
644*e4b17023SJohn Marino    */
645*e4b17023SJohn Marino   template<bool __stable/* default == true */, typename _Tp, typename _Compare>
646*e4b17023SJohn Marino     class _LoserTreeUnguarded
647*e4b17023SJohn Marino     : public _LoserTreeUnguardedBase<_Tp, _Compare>
648*e4b17023SJohn Marino     {
649*e4b17023SJohn Marino       typedef _LoserTreeUnguardedBase<_Tp, _Compare> _Base;
650*e4b17023SJohn Marino       using _Base::_M_k;
651*e4b17023SJohn Marino       using _Base::_M_comp;
652*e4b17023SJohn Marino       using _Base::_M_losers;
653*e4b17023SJohn Marino 
654*e4b17023SJohn Marino   public:
655*e4b17023SJohn Marino       _LoserTreeUnguarded(unsigned int __k, const _Tp& __sentinel,
656*e4b17023SJohn Marino 			  _Compare __comp = std::less<_Tp>())
_LoserTreeUnguardedBase(__k,__sentinel,__comp)657*e4b17023SJohn Marino       : _Base::_LoserTreeUnguardedBase(__k, __sentinel, __comp)
658*e4b17023SJohn Marino       { }
659*e4b17023SJohn Marino 
660*e4b17023SJohn Marino       unsigned int
__init_winner(unsigned int __root)661*e4b17023SJohn Marino       __init_winner(unsigned int __root)
662*e4b17023SJohn Marino       {
663*e4b17023SJohn Marino 	if (__root >= _M_k)
664*e4b17023SJohn Marino 	  return __root;
665*e4b17023SJohn Marino 	else
666*e4b17023SJohn Marino 	  {
667*e4b17023SJohn Marino 	    unsigned int __left = __init_winner(2 * __root);
668*e4b17023SJohn Marino 	    unsigned int __right = __init_winner(2 * __root + 1);
669*e4b17023SJohn Marino 	    if (!_M_comp(_M_losers[__right]._M_key,
670*e4b17023SJohn Marino 			 _M_losers[__left]._M_key))
671*e4b17023SJohn Marino 	      {
672*e4b17023SJohn Marino 		// Left one is less or equal.
673*e4b17023SJohn Marino 		_M_losers[__root] = _M_losers[__right];
674*e4b17023SJohn Marino 		return __left;
675*e4b17023SJohn Marino 	      }
676*e4b17023SJohn Marino 	    else
677*e4b17023SJohn Marino 	      {
678*e4b17023SJohn Marino 		// Right one is less.
679*e4b17023SJohn Marino 		_M_losers[__root] = _M_losers[__left];
680*e4b17023SJohn Marino 		return __right;
681*e4b17023SJohn Marino 	      }
682*e4b17023SJohn Marino 	  }
683*e4b17023SJohn Marino       }
684*e4b17023SJohn Marino 
685*e4b17023SJohn Marino       void
__init()686*e4b17023SJohn Marino       __init()
687*e4b17023SJohn Marino       {
688*e4b17023SJohn Marino 	_M_losers[0] = _M_losers[__init_winner(1)];
689*e4b17023SJohn Marino 
690*e4b17023SJohn Marino #if _GLIBCXX_ASSERTIONS
691*e4b17023SJohn Marino 	// no dummy sequence can ever be at the top at the beginning
692*e4b17023SJohn Marino 	// (0 sequences!)
693*e4b17023SJohn Marino 	_GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1);
694*e4b17023SJohn Marino #endif
695*e4b17023SJohn Marino       }
696*e4b17023SJohn Marino 
697*e4b17023SJohn Marino       // Do not pass a const reference since __key will be used as
698*e4b17023SJohn Marino       // local variable.
699*e4b17023SJohn Marino       void
__delete_min_insert(_Tp __key,bool)700*e4b17023SJohn Marino       __delete_min_insert(_Tp __key, bool)
701*e4b17023SJohn Marino       {
702*e4b17023SJohn Marino         using std::swap;
703*e4b17023SJohn Marino #if _GLIBCXX_ASSERTIONS
704*e4b17023SJohn Marino 	// no dummy sequence can ever be at the top!
705*e4b17023SJohn Marino 	_GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1);
706*e4b17023SJohn Marino #endif
707*e4b17023SJohn Marino 
708*e4b17023SJohn Marino 	int __source = _M_losers[0]._M_source;
709*e4b17023SJohn Marino 	for (unsigned int __pos = (_M_k + __source) / 2; __pos > 0;
710*e4b17023SJohn Marino 	     __pos /= 2)
711*e4b17023SJohn Marino 	  {
712*e4b17023SJohn Marino 	    // The smaller one gets promoted, ties are broken by _M_source.
713*e4b17023SJohn Marino 	    if (_M_comp(_M_losers[__pos]._M_key, __key)
714*e4b17023SJohn Marino         	|| (!_M_comp(__key, _M_losers[__pos]._M_key)
715*e4b17023SJohn Marino                     && _M_losers[__pos]._M_source < __source))
716*e4b17023SJohn Marino 	      {
717*e4b17023SJohn Marino 		// The other one is smaller.
718*e4b17023SJohn Marino 		std::swap(_M_losers[__pos]._M_source, __source);
719*e4b17023SJohn Marino 		swap(_M_losers[__pos]._M_key, __key);
720*e4b17023SJohn Marino 	      }
721*e4b17023SJohn Marino 	  }
722*e4b17023SJohn Marino 
723*e4b17023SJohn Marino 	_M_losers[0]._M_source = __source;
724*e4b17023SJohn Marino 	_M_losers[0]._M_key = __key;
725*e4b17023SJohn Marino       }
726*e4b17023SJohn Marino     };
727*e4b17023SJohn Marino 
728*e4b17023SJohn Marino   /**
729*e4b17023SJohn Marino    * @brief Non-Stable implementation of unguarded _LoserTree.
730*e4b17023SJohn Marino    *
731*e4b17023SJohn Marino    * Stable implementation is above.
732*e4b17023SJohn Marino    */
733*e4b17023SJohn Marino   template<typename _Tp, typename _Compare>
734*e4b17023SJohn Marino     class _LoserTreeUnguarded</* __stable == */false, _Tp, _Compare>
735*e4b17023SJohn Marino     : public _LoserTreeUnguardedBase<_Tp, _Compare>
736*e4b17023SJohn Marino     {
737*e4b17023SJohn Marino       typedef _LoserTreeUnguardedBase<_Tp, _Compare> _Base;
738*e4b17023SJohn Marino       using _Base::_M_k;
739*e4b17023SJohn Marino       using _Base::_M_comp;
740*e4b17023SJohn Marino       using _Base::_M_losers;
741*e4b17023SJohn Marino 
742*e4b17023SJohn Marino     public:
743*e4b17023SJohn Marino       _LoserTreeUnguarded(unsigned int __k, const _Tp& __sentinel,
744*e4b17023SJohn Marino 			  _Compare __comp = std::less<_Tp>())
_LoserTreeUnguardedBase(__k,__sentinel,__comp)745*e4b17023SJohn Marino       : _Base::_LoserTreeUnguardedBase(__k, __sentinel, __comp)
746*e4b17023SJohn Marino       { }
747*e4b17023SJohn Marino 
748*e4b17023SJohn Marino       unsigned int
__init_winner(unsigned int __root)749*e4b17023SJohn Marino       __init_winner(unsigned int __root)
750*e4b17023SJohn Marino       {
751*e4b17023SJohn Marino 	if (__root >= _M_k)
752*e4b17023SJohn Marino 	  return __root;
753*e4b17023SJohn Marino 	else
754*e4b17023SJohn Marino 	  {
755*e4b17023SJohn Marino 	    unsigned int __left = __init_winner(2 * __root);
756*e4b17023SJohn Marino 	    unsigned int __right = __init_winner(2 * __root + 1);
757*e4b17023SJohn Marino 
758*e4b17023SJohn Marino #if _GLIBCXX_ASSERTIONS
759*e4b17023SJohn Marino 	    // If __left one is sentinel then __right one must be, too.
760*e4b17023SJohn Marino 	    if (_M_losers[__left]._M_source == -1)
761*e4b17023SJohn Marino 	      _GLIBCXX_PARALLEL_ASSERT(_M_losers[__right]._M_source == -1);
762*e4b17023SJohn Marino #endif
763*e4b17023SJohn Marino 
764*e4b17023SJohn Marino 	    if (!_M_comp(_M_losers[__right]._M_key,
765*e4b17023SJohn Marino 			 _M_losers[__left]._M_key))
766*e4b17023SJohn Marino 	      {
767*e4b17023SJohn Marino 		// Left one is less or equal.
768*e4b17023SJohn Marino 		_M_losers[__root] = _M_losers[__right];
769*e4b17023SJohn Marino 		return __left;
770*e4b17023SJohn Marino 	      }
771*e4b17023SJohn Marino 	    else
772*e4b17023SJohn Marino 	      {
773*e4b17023SJohn Marino 		// Right one is less.
774*e4b17023SJohn Marino 		_M_losers[__root] = _M_losers[__left];
775*e4b17023SJohn Marino 		return __right;
776*e4b17023SJohn Marino 	      }
777*e4b17023SJohn Marino 	  }
778*e4b17023SJohn Marino       }
779*e4b17023SJohn Marino 
780*e4b17023SJohn Marino       void
__init()781*e4b17023SJohn Marino       __init()
782*e4b17023SJohn Marino       {
783*e4b17023SJohn Marino 	_M_losers[0] = _M_losers[__init_winner(1)];
784*e4b17023SJohn Marino 
785*e4b17023SJohn Marino #if _GLIBCXX_ASSERTIONS
786*e4b17023SJohn Marino 	// no dummy sequence can ever be at the top at the beginning
787*e4b17023SJohn Marino 	// (0 sequences!)
788*e4b17023SJohn Marino 	_GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1);
789*e4b17023SJohn Marino #endif
790*e4b17023SJohn Marino       }
791*e4b17023SJohn Marino 
792*e4b17023SJohn Marino       // Do not pass a const reference since __key will be used as
793*e4b17023SJohn Marino       // local variable.
794*e4b17023SJohn Marino       void
__delete_min_insert(_Tp __key,bool)795*e4b17023SJohn Marino       __delete_min_insert(_Tp __key, bool)
796*e4b17023SJohn Marino       {
797*e4b17023SJohn Marino         using std::swap;
798*e4b17023SJohn Marino #if _GLIBCXX_ASSERTIONS
799*e4b17023SJohn Marino 	// no dummy sequence can ever be at the top!
800*e4b17023SJohn Marino 	_GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1);
801*e4b17023SJohn Marino #endif
802*e4b17023SJohn Marino 
803*e4b17023SJohn Marino 	int __source = _M_losers[0]._M_source;
804*e4b17023SJohn Marino 	for (unsigned int __pos = (_M_k + __source) / 2; __pos > 0;
805*e4b17023SJohn Marino 	     __pos /= 2)
806*e4b17023SJohn Marino 	  {
807*e4b17023SJohn Marino 	    // The smaller one gets promoted.
808*e4b17023SJohn Marino 	    if (_M_comp(_M_losers[__pos]._M_key, __key))
809*e4b17023SJohn Marino 	      {
810*e4b17023SJohn Marino 		// The other one is smaller.
811*e4b17023SJohn Marino 		std::swap(_M_losers[__pos]._M_source, __source);
812*e4b17023SJohn Marino 		swap(_M_losers[__pos]._M_key, __key);
813*e4b17023SJohn Marino 	      }
814*e4b17023SJohn Marino 	  }
815*e4b17023SJohn Marino 
816*e4b17023SJohn Marino 	_M_losers[0]._M_source = __source;
817*e4b17023SJohn Marino 	_M_losers[0]._M_key = __key;
818*e4b17023SJohn Marino       }
819*e4b17023SJohn Marino     };
820*e4b17023SJohn Marino 
821*e4b17023SJohn Marino   /** @brief Unguarded loser tree, keeping only pointers to the
822*e4b17023SJohn Marino   * elements in the tree structure.
823*e4b17023SJohn Marino   *
824*e4b17023SJohn Marino   *  No guarding is done, therefore not a single input sequence must
825*e4b17023SJohn Marino   *  run empty.  This is a very fast variant.
826*e4b17023SJohn Marino   */
827*e4b17023SJohn Marino   template<typename _Tp, typename _Compare>
828*e4b17023SJohn Marino     class _LoserTreePointerUnguardedBase
829*e4b17023SJohn Marino     {
830*e4b17023SJohn Marino     protected:
831*e4b17023SJohn Marino       struct _Loser
832*e4b17023SJohn Marino       {
833*e4b17023SJohn Marino 	int _M_source;
834*e4b17023SJohn Marino 	const _Tp* _M_keyp;
835*e4b17023SJohn Marino       };
836*e4b17023SJohn Marino 
837*e4b17023SJohn Marino       unsigned int _M_ik, _M_k, _M_offset;
838*e4b17023SJohn Marino       _Loser* _M_losers;
839*e4b17023SJohn Marino       _Compare _M_comp;
840*e4b17023SJohn Marino 
841*e4b17023SJohn Marino     public:
842*e4b17023SJohn Marino 
843*e4b17023SJohn Marino       _LoserTreePointerUnguardedBase(unsigned int __k, const _Tp& __sentinel,
844*e4b17023SJohn Marino 				     _Compare __comp = std::less<_Tp>())
_M_comp(__comp)845*e4b17023SJohn Marino       : _M_comp(__comp)
846*e4b17023SJohn Marino       {
847*e4b17023SJohn Marino 	_M_ik = __k;
848*e4b17023SJohn Marino 
849*e4b17023SJohn Marino 	// Next greater power of 2.
850*e4b17023SJohn Marino 	_M_k = 1 << (__rd_log2(_M_ik - 1) + 1);
851*e4b17023SJohn Marino 	_M_offset = _M_k;
852*e4b17023SJohn Marino 	// Avoid default-constructing _M_losers[]._M_key
853*e4b17023SJohn Marino 	_M_losers = new _Loser[2 * _M_k];
854*e4b17023SJohn Marino 
855*e4b17023SJohn Marino 	for (unsigned int __i = _M_k + _M_ik - 1; __i < (2 * _M_k); ++__i)
856*e4b17023SJohn Marino 	  {
857*e4b17023SJohn Marino 	    _M_losers[__i]._M_keyp = &__sentinel;
858*e4b17023SJohn Marino 	    _M_losers[__i]._M_source = -1;
859*e4b17023SJohn Marino 	  }
860*e4b17023SJohn Marino       }
861*e4b17023SJohn Marino 
~_LoserTreePointerUnguardedBase()862*e4b17023SJohn Marino       ~_LoserTreePointerUnguardedBase()
863*e4b17023SJohn Marino       { delete[] _M_losers; }
864*e4b17023SJohn Marino 
865*e4b17023SJohn Marino       int
__get_min_source()866*e4b17023SJohn Marino       __get_min_source()
867*e4b17023SJohn Marino       {
868*e4b17023SJohn Marino #if _GLIBCXX_ASSERTIONS
869*e4b17023SJohn Marino 	// no dummy sequence can ever be at the top!
870*e4b17023SJohn Marino 	_GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1);
871*e4b17023SJohn Marino #endif
872*e4b17023SJohn Marino 	return _M_losers[0]._M_source;
873*e4b17023SJohn Marino       }
874*e4b17023SJohn Marino 
875*e4b17023SJohn Marino       void
__insert_start(const _Tp & __key,int __source,bool)876*e4b17023SJohn Marino       __insert_start(const _Tp& __key, int __source, bool)
877*e4b17023SJohn Marino       {
878*e4b17023SJohn Marino 	unsigned int __pos = _M_k + __source;
879*e4b17023SJohn Marino 
880*e4b17023SJohn Marino 	_M_losers[__pos]._M_keyp = &__key;
881*e4b17023SJohn Marino 	_M_losers[__pos]._M_source = __source;
882*e4b17023SJohn Marino       }
883*e4b17023SJohn Marino     };
884*e4b17023SJohn Marino 
885*e4b17023SJohn Marino   /**
886*e4b17023SJohn Marino    * @brief Stable unguarded _LoserTree variant storing pointers.
887*e4b17023SJohn Marino    *
888*e4b17023SJohn Marino    * Unstable variant is implemented below using partial specialization.
889*e4b17023SJohn Marino    */
890*e4b17023SJohn Marino   template<bool __stable/* default == true */, typename _Tp, typename _Compare>
891*e4b17023SJohn Marino     class _LoserTreePointerUnguarded
892*e4b17023SJohn Marino     : public _LoserTreePointerUnguardedBase<_Tp, _Compare>
893*e4b17023SJohn Marino     {
894*e4b17023SJohn Marino       typedef _LoserTreePointerUnguardedBase<_Tp, _Compare> _Base;
895*e4b17023SJohn Marino       using _Base::_M_k;
896*e4b17023SJohn Marino       using _Base::_M_comp;
897*e4b17023SJohn Marino       using _Base::_M_losers;
898*e4b17023SJohn Marino 
899*e4b17023SJohn Marino     public:
900*e4b17023SJohn Marino       _LoserTreePointerUnguarded(unsigned int __k, const _Tp& __sentinel,
901*e4b17023SJohn Marino 				 _Compare __comp = std::less<_Tp>())
_LoserTreePointerUnguardedBase(__k,__sentinel,__comp)902*e4b17023SJohn Marino       : _Base::_LoserTreePointerUnguardedBase(__k, __sentinel, __comp)
903*e4b17023SJohn Marino       { }
904*e4b17023SJohn Marino 
905*e4b17023SJohn Marino       unsigned int
__init_winner(unsigned int __root)906*e4b17023SJohn Marino       __init_winner(unsigned int __root)
907*e4b17023SJohn Marino       {
908*e4b17023SJohn Marino 	if (__root >= _M_k)
909*e4b17023SJohn Marino 	  return __root;
910*e4b17023SJohn Marino 	else
911*e4b17023SJohn Marino 	  {
912*e4b17023SJohn Marino 	    unsigned int __left = __init_winner(2 * __root);
913*e4b17023SJohn Marino 	    unsigned int __right = __init_winner(2 * __root + 1);
914*e4b17023SJohn Marino 	    if (!_M_comp(*_M_losers[__right]._M_keyp,
915*e4b17023SJohn Marino 			 *_M_losers[__left]._M_keyp))
916*e4b17023SJohn Marino 	      {
917*e4b17023SJohn Marino 		// Left one is less or equal.
918*e4b17023SJohn Marino 		_M_losers[__root] = _M_losers[__right];
919*e4b17023SJohn Marino 		return __left;
920*e4b17023SJohn Marino 	      }
921*e4b17023SJohn Marino 	    else
922*e4b17023SJohn Marino 	      {
923*e4b17023SJohn Marino 		// Right one is less.
924*e4b17023SJohn Marino 		_M_losers[__root] = _M_losers[__left];
925*e4b17023SJohn Marino 		return __right;
926*e4b17023SJohn Marino 	      }
927*e4b17023SJohn Marino 	  }
928*e4b17023SJohn Marino       }
929*e4b17023SJohn Marino 
930*e4b17023SJohn Marino       void
__init()931*e4b17023SJohn Marino       __init()
932*e4b17023SJohn Marino       {
933*e4b17023SJohn Marino 	_M_losers[0] = _M_losers[__init_winner(1)];
934*e4b17023SJohn Marino 
935*e4b17023SJohn Marino #if _GLIBCXX_ASSERTIONS
936*e4b17023SJohn Marino 	// no dummy sequence can ever be at the top at the beginning
937*e4b17023SJohn Marino 	// (0 sequences!)
938*e4b17023SJohn Marino 	_GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1);
939*e4b17023SJohn Marino #endif
940*e4b17023SJohn Marino       }
941*e4b17023SJohn Marino 
942*e4b17023SJohn Marino       void
__delete_min_insert(const _Tp & __key,bool __sup)943*e4b17023SJohn Marino       __delete_min_insert(const _Tp& __key, bool __sup)
944*e4b17023SJohn Marino       {
945*e4b17023SJohn Marino #if _GLIBCXX_ASSERTIONS
946*e4b17023SJohn Marino 	// no dummy sequence can ever be at the top!
947*e4b17023SJohn Marino 	_GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1);
948*e4b17023SJohn Marino #endif
949*e4b17023SJohn Marino 
950*e4b17023SJohn Marino 	const _Tp* __keyp = &__key;
951*e4b17023SJohn Marino 	int __source = _M_losers[0]._M_source;
952*e4b17023SJohn Marino 	for (unsigned int __pos = (_M_k + __source) / 2; __pos > 0;
953*e4b17023SJohn Marino 	     __pos /= 2)
954*e4b17023SJohn Marino 	  {
955*e4b17023SJohn Marino 	    // The smaller one gets promoted, ties are broken by _M_source.
956*e4b17023SJohn Marino 	    if (_M_comp(*_M_losers[__pos]._M_keyp, *__keyp)
957*e4b17023SJohn Marino 		|| (!_M_comp(*__keyp, *_M_losers[__pos]._M_keyp)
958*e4b17023SJohn Marino 		    && _M_losers[__pos]._M_source < __source))
959*e4b17023SJohn Marino 	      {
960*e4b17023SJohn Marino 		// The other one is smaller.
961*e4b17023SJohn Marino 		std::swap(_M_losers[__pos]._M_source, __source);
962*e4b17023SJohn Marino 		std::swap(_M_losers[__pos]._M_keyp, __keyp);
963*e4b17023SJohn Marino 	      }
964*e4b17023SJohn Marino 	  }
965*e4b17023SJohn Marino 
966*e4b17023SJohn Marino 	_M_losers[0]._M_source = __source;
967*e4b17023SJohn Marino 	_M_losers[0]._M_keyp = __keyp;
968*e4b17023SJohn Marino       }
969*e4b17023SJohn Marino     };
970*e4b17023SJohn Marino 
971*e4b17023SJohn Marino   /**
972*e4b17023SJohn Marino    * @brief Unstable unguarded _LoserTree variant storing pointers.
973*e4b17023SJohn Marino    *
974*e4b17023SJohn Marino    * Stable variant is above.
975*e4b17023SJohn Marino    */
976*e4b17023SJohn Marino   template<typename _Tp, typename _Compare>
977*e4b17023SJohn Marino     class _LoserTreePointerUnguarded</* __stable == */false, _Tp, _Compare>
978*e4b17023SJohn Marino     : public _LoserTreePointerUnguardedBase<_Tp, _Compare>
979*e4b17023SJohn Marino     {
980*e4b17023SJohn Marino       typedef _LoserTreePointerUnguardedBase<_Tp, _Compare> _Base;
981*e4b17023SJohn Marino       using _Base::_M_k;
982*e4b17023SJohn Marino       using _Base::_M_comp;
983*e4b17023SJohn Marino       using _Base::_M_losers;
984*e4b17023SJohn Marino 
985*e4b17023SJohn Marino   public:
986*e4b17023SJohn Marino       _LoserTreePointerUnguarded(unsigned int __k, const _Tp& __sentinel,
987*e4b17023SJohn Marino 				 _Compare __comp = std::less<_Tp>())
_LoserTreePointerUnguardedBase(__k,__sentinel,__comp)988*e4b17023SJohn Marino       : _Base::_LoserTreePointerUnguardedBase(__k, __sentinel, __comp)
989*e4b17023SJohn Marino       { }
990*e4b17023SJohn Marino 
991*e4b17023SJohn Marino       unsigned int
__init_winner(unsigned int __root)992*e4b17023SJohn Marino       __init_winner(unsigned int __root)
993*e4b17023SJohn Marino       {
994*e4b17023SJohn Marino 	if (__root >= _M_k)
995*e4b17023SJohn Marino 	  return __root;
996*e4b17023SJohn Marino 	else
997*e4b17023SJohn Marino 	  {
998*e4b17023SJohn Marino 	    unsigned int __left = __init_winner(2 * __root);
999*e4b17023SJohn Marino 	    unsigned int __right = __init_winner(2 * __root + 1);
1000*e4b17023SJohn Marino 
1001*e4b17023SJohn Marino #if _GLIBCXX_ASSERTIONS
1002*e4b17023SJohn Marino 	    // If __left one is sentinel then __right one must be, too.
1003*e4b17023SJohn Marino 	    if (_M_losers[__left]._M_source == -1)
1004*e4b17023SJohn Marino 	      _GLIBCXX_PARALLEL_ASSERT(_M_losers[__right]._M_source == -1);
1005*e4b17023SJohn Marino #endif
1006*e4b17023SJohn Marino 
1007*e4b17023SJohn Marino 	    if (!_M_comp(*_M_losers[__right]._M_keyp,
1008*e4b17023SJohn Marino 			 *_M_losers[__left]._M_keyp))
1009*e4b17023SJohn Marino 	      {
1010*e4b17023SJohn Marino 		// Left one is less or equal.
1011*e4b17023SJohn Marino 		_M_losers[__root] = _M_losers[__right];
1012*e4b17023SJohn Marino 		return __left;
1013*e4b17023SJohn Marino 	      }
1014*e4b17023SJohn Marino 	    else
1015*e4b17023SJohn Marino 	      {
1016*e4b17023SJohn Marino 		// Right one is less.
1017*e4b17023SJohn Marino 		_M_losers[__root] = _M_losers[__left];
1018*e4b17023SJohn Marino 		return __right;
1019*e4b17023SJohn Marino 	      }
1020*e4b17023SJohn Marino 	  }
1021*e4b17023SJohn Marino       }
1022*e4b17023SJohn Marino 
1023*e4b17023SJohn Marino       void
__init()1024*e4b17023SJohn Marino       __init()
1025*e4b17023SJohn Marino       {
1026*e4b17023SJohn Marino 	_M_losers[0] = _M_losers[__init_winner(1)];
1027*e4b17023SJohn Marino 
1028*e4b17023SJohn Marino #if _GLIBCXX_ASSERTIONS
1029*e4b17023SJohn Marino 	// no dummy sequence can ever be at the top at the beginning
1030*e4b17023SJohn Marino 	// (0 sequences!)
1031*e4b17023SJohn Marino 	_GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1);
1032*e4b17023SJohn Marino #endif
1033*e4b17023SJohn Marino       }
1034*e4b17023SJohn Marino 
1035*e4b17023SJohn Marino       void
__delete_min_insert(const _Tp & __key,bool __sup)1036*e4b17023SJohn Marino       __delete_min_insert(const _Tp& __key, bool __sup)
1037*e4b17023SJohn Marino       {
1038*e4b17023SJohn Marino #if _GLIBCXX_ASSERTIONS
1039*e4b17023SJohn Marino 	// no dummy sequence can ever be at the top!
1040*e4b17023SJohn Marino 	_GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1);
1041*e4b17023SJohn Marino #endif
1042*e4b17023SJohn Marino 
1043*e4b17023SJohn Marino 	const _Tp* __keyp = &__key;
1044*e4b17023SJohn Marino 	int __source = _M_losers[0]._M_source;
1045*e4b17023SJohn Marino 	for (unsigned int __pos = (_M_k + __source) / 2; __pos > 0;
1046*e4b17023SJohn Marino 	     __pos /= 2)
1047*e4b17023SJohn Marino 	  {
1048*e4b17023SJohn Marino 	    // The smaller one gets promoted.
1049*e4b17023SJohn Marino 	    if (_M_comp(*(_M_losers[__pos]._M_keyp), *__keyp))
1050*e4b17023SJohn Marino 	      {
1051*e4b17023SJohn Marino 		// The other one is smaller.
1052*e4b17023SJohn Marino 		std::swap(_M_losers[__pos]._M_source, __source);
1053*e4b17023SJohn Marino 		std::swap(_M_losers[__pos]._M_keyp, __keyp);
1054*e4b17023SJohn Marino 	      }
1055*e4b17023SJohn Marino 	  }
1056*e4b17023SJohn Marino 
1057*e4b17023SJohn Marino 	_M_losers[0]._M_source = __source;
1058*e4b17023SJohn Marino 	_M_losers[0]._M_keyp = __keyp;
1059*e4b17023SJohn Marino       }
1060*e4b17023SJohn Marino     };
1061*e4b17023SJohn Marino } // namespace __gnu_parallel
1062*e4b17023SJohn Marino 
1063*e4b17023SJohn Marino #endif /* _GLIBCXX_PARALLEL_LOSERTREE_H */
1064