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