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 > 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