losertree.h

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 // Copyright (C) 2007, 2008 Free Software Foundation, Inc.
00004 //
00005 // This file is part of the GNU ISO C++ Library.  This library is free
00006 // software; you can redistribute it and/or modify it under the terms
00007 // of the GNU General Public License as published by the Free Software
00008 // Foundation; either version 2, or (at your option) any later
00009 // version.
00010 
00011 // This library is distributed in the hope that it will be useful, but
00012 // WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // General Public License for more details.
00015 
00016 // You should have received a copy of the GNU General Public License
00017 // along with this library; see the file COPYING.  If not, write to
00018 // the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
00019 // MA 02111-1307, USA.
00020 
00021 // As a special exception, you may use this file as part of a free
00022 // software library without restriction.  Specifically, if other files
00023 // instantiate templates or use macros or inline functions from this
00024 // file, or you compile this file and link it with other files to
00025 // produce an executable, this file does not by itself cause the
00026 // resulting executable to be covered by the GNU General Public
00027 // License.  This exception does not however invalidate any other
00028 // reasons why the executable file might be covered by the GNU General
00029 // Public License.
00030 
00031 /** @file parallel/losertree.h
00032 *  @brief Many generic loser tree variants.
00033 *  This file is a GNU parallel extension to the Standard C++ Library.
00034 */
00035 
00036 // Written by Johannes Singler.
00037 
00038 #ifndef _GLIBCXX_PARALLEL_LOSERTREE_H
00039 #define _GLIBCXX_PARALLEL_LOSERTREE_H 1
00040 
00041 #include <functional>
00042 
00043 #include <bits/stl_algobase.h>
00044 #include <parallel/features.h>
00045 #include <parallel/base.h>
00046 
00047 namespace __gnu_parallel
00048 {
00049 
00050 #if _GLIBCXX_LOSER_TREE_EXPLICIT
00051 
00052 /** @brief Guarded loser tree, copying the whole element into the
00053 * tree structure.
00054 *
00055 *  Guarding is done explicitly through two flags per element, inf
00056 *  and sup This is a quite slow variant.
00057 */
00058 template<typename T, typename Comparator = std::less<T> >
00059   class LoserTreeExplicit
00060   {
00061   private:
00062     struct Loser
00063     {
00064       // The relevant element.
00065       T key;
00066 
00067       // Is this an infimum or supremum element?
00068       bool inf, sup;
00069 
00070       // Number of the sequence the element comes from.
00071       int source;
00072     };
00073 
00074     unsigned int size, offset;
00075     Loser* losers;
00076     Comparator comp;
00077 
00078   public:
00079     LoserTreeExplicit(unsigned int _size, Comparator _comp = std::less<T>())
00080     : comp(_comp)
00081     {
00082       size = _size;
00083       offset = size;
00084       losers = new Loser[size];
00085       for (unsigned int l = 0; l < size; ++l)
00086         {
00087           //losers[l].key = ...     stays unset
00088           losers[l].inf = true;
00089           losers[l].sup = false;
00090           //losers[l].source = -1;  //sentinel
00091         }
00092     }
00093 
00094     ~LoserTreeExplicit()
00095     { delete[] losers; }
00096 
00097     int
00098     get_min_source()
00099     { return losers[0].source; }
00100 
00101     void
00102     insert_start(T key, int source, bool sup)
00103     {
00104       bool inf = false;
00105       for (unsigned int pos = (offset + source) / 2; pos > 0; pos /= 2)
00106         {
00107           if ((!inf && !losers[pos].inf && !sup && !losers[pos].sup
00108                && comp(losers[pos].key, key)) || losers[pos].inf || sup)
00109             {
00110               // The other one is smaller.
00111               std::swap(losers[pos].key, key);
00112               std::swap(losers[pos].inf, inf);
00113               std::swap(losers[pos].sup, sup);
00114               std::swap(losers[pos].source, source);
00115             }
00116         }
00117 
00118       losers[0].key = key;
00119       losers[0].inf = inf;
00120       losers[0].sup = sup;
00121       losers[0].source = source;
00122     }
00123 
00124     void
00125     init() { }
00126 
00127     void
00128     delete_min_insert(T key, bool sup)
00129     {
00130       bool inf = false;
00131       int source = losers[0].source;
00132       for (unsigned int pos = (offset + source) / 2; pos > 0; pos /= 2)
00133         {
00134           // The smaller one gets promoted.
00135           if ((!inf && !losers[pos].inf && !sup && !losers[pos].sup
00136               && comp(losers[pos].key, key))
00137               || losers[pos].inf || sup)
00138             {
00139               // The other one is smaller.
00140               std::swap(losers[pos].key, key);
00141               std::swap(losers[pos].inf, inf);
00142               std::swap(losers[pos].sup, sup);
00143               std::swap(losers[pos].source, source);
00144             }
00145         }
00146 
00147       losers[0].key = key;
00148       losers[0].inf = inf;
00149       losers[0].sup = sup;
00150       losers[0].source = source;
00151     }
00152 
00153     void
00154     insert_start_stable(T key, int source, bool sup)
00155     {
00156       bool inf = false;
00157       for (unsigned int pos = (offset + source) / 2; pos > 0; pos /= 2)
00158         {
00159           if ((!inf && !losers[pos].inf && !sup && !losers[pos].sup
00160            && ((comp(losers[pos].key, key))
00161            || (!comp(key, losers[pos].key)
00162                && losers[pos].source < source)))
00163               || losers[pos].inf || sup)
00164             {
00165               // Take next key.
00166               std::swap(losers[pos].key, key);
00167               std::swap(losers[pos].inf, inf);
00168               std::swap(losers[pos].sup, sup);
00169               std::swap(losers[pos].source, source);
00170             }
00171         }
00172 
00173       losers[0].key = key;
00174       losers[0].inf = inf;
00175       losers[0].sup = sup;
00176       losers[0].source = source;
00177     }
00178 
00179     void
00180     init_stable() { }
00181 
00182     void
00183     delete_min_insert_stable(T key, bool sup)
00184     {
00185       bool inf = false;
00186       int source = losers[0].source;
00187       for (unsigned int pos = (offset + source) / 2; pos > 0; pos /= 2)
00188         {
00189           if ((!inf && !losers[pos].inf && !sup && !losers[pos].sup
00190               && ((comp(losers[pos].key, key))
00191           || (!comp(key, losers[pos].key)
00192               && losers[pos].source < source)))
00193               || losers[pos].inf || sup)
00194             {
00195               std::swap(losers[pos].key, key);
00196               std::swap(losers[pos].inf, inf);
00197               std::swap(losers[pos].sup, sup);
00198               std::swap(losers[pos].source, source);
00199             }
00200         }
00201 
00202       losers[0].key = key;
00203       losers[0].inf = inf;
00204       losers[0].sup = sup;
00205       losers[0].source = source;
00206     }
00207   };
00208 
00209 #endif
00210 
00211 #if _GLIBCXX_LOSER_TREE
00212 
00213 /** @brief Guarded loser tree, either copying the whole element into
00214 * the tree structure, or looking up the element via the index.
00215 *
00216 *  Guarding is done explicitly through one flag sup per element,
00217 *  inf is not needed due to a better initialization routine.  This
00218 *  is a well-performing variant.
00219 */
00220 template<typename T, typename Comparator = std::less<T> >
00221   class LoserTree
00222   {
00223   private:
00224     struct Loser
00225     {
00226       bool sup;
00227       int source;
00228       T key;
00229     };
00230 
00231     unsigned int ik, k, offset;
00232     Loser* losers;
00233     Comparator comp;
00234     bool first_insert;
00235 
00236   public:
00237     LoserTree(unsigned int _k, Comparator _comp = std::less<T>())
00238     : comp(_comp)
00239     {
00240       ik = _k;
00241 
00242       // Next greater power of 2.
00243       k = 1 << (log2(ik - 1) + 1);
00244       offset = k;
00245       // Avoid default-constructing losers[].key
00246       losers = static_cast<Loser*>(::operator new(2 * k * sizeof(Loser)));
00247       for (unsigned int i = ik - 1; i < k; ++i)
00248         losers[i + k].sup = true;
00249 
00250       first_insert = true;
00251     }
00252 
00253     ~LoserTree()
00254     { ::operator delete(losers); }
00255 
00256     int
00257     get_min_source()
00258     { return losers[0].source; }
00259 
00260     void
00261     insert_start(const T& key, int source, bool sup)
00262     {
00263       unsigned int pos = k + source;
00264 
00265       if(first_insert)
00266         {
00267           // Construct all keys, so we can easily deconstruct them.
00268           for (unsigned int i = 0; i < (2 * k); ++i)
00269             ::new(&(losers[i].key)) T(key);
00270           first_insert = false;
00271         }
00272       else
00273         ::new(&(losers[pos].key)) T(key);
00274 
00275       losers[pos].sup = sup;
00276       losers[pos].source = source;
00277     }
00278 
00279     unsigned int
00280     init_winner (unsigned int root)
00281     {
00282       if (root >= k)
00283         {
00284           return root;
00285         }
00286       else
00287         {
00288           unsigned int left = init_winner (2 * root);
00289           unsigned int right = init_winner (2 * root + 1);
00290           if (losers[right].sup
00291           || (!losers[left].sup
00292           && !comp(losers[right].key, losers[left].key)))
00293             {
00294               // Left one is less or equal.
00295               losers[root] = losers[right];
00296               return left;
00297             }
00298           else
00299             {
00300               // Right one is less.
00301               losers[root] = losers[left];
00302               return right;
00303             }
00304         }
00305     }
00306 
00307     void
00308     init()
00309     { losers[0] = losers[init_winner(1)]; }
00310 
00311     // Do not pass const reference since key will be used as local variable.
00312     void
00313     delete_min_insert(T key, bool sup)
00314     {
00315       int source = losers[0].source;
00316       for (unsigned int pos = (k + source) / 2; pos > 0; pos /= 2)
00317         {
00318           // The smaller one gets promoted.
00319           if (sup || (!losers[pos].sup && comp(losers[pos].key, key)))
00320             {
00321               // The other one is smaller.
00322               std::swap(losers[pos].sup, sup);
00323               std::swap(losers[pos].source, source);
00324               std::swap(losers[pos].key, key);
00325             }
00326         }
00327 
00328       losers[0].sup = sup;
00329       losers[0].source = source;
00330       losers[0].key = key;
00331     }
00332 
00333     void
00334     insert_start_stable(const T& key, int source, bool sup)
00335     { return insert_start(key, source, sup); }
00336 
00337     unsigned int
00338     init_winner_stable (unsigned int root)
00339     {
00340       if (root >= k)
00341         {
00342           return root;
00343         }
00344       else
00345         {
00346           unsigned int left = init_winner (2 * root);
00347           unsigned int right = init_winner (2 * root + 1);
00348           if (losers[right].sup
00349               || (!losers[left].sup
00350           && !comp(losers[right].key, losers[left].key)))
00351             {
00352               // Left one is less or equal.
00353               losers[root] = losers[right];
00354               return left;
00355             }
00356           else
00357             {
00358               // Right one is less.
00359               losers[root] = losers[left];
00360               return right;
00361             }
00362         }
00363     }
00364 
00365     void
00366     init_stable()
00367     { losers[0] = losers[init_winner_stable(1)]; }
00368 
00369     // Do not pass const reference since key will be used as local variable.
00370     void
00371     delete_min_insert_stable(T key, bool sup)
00372     {
00373       int source = losers[0].source;
00374       for (unsigned int pos = (k + source) / 2; pos > 0; pos /= 2)
00375         {
00376           // The smaller one gets promoted, ties are broken by source.
00377           if (  (sup && (!losers[pos].sup || losers[pos].source < source))
00378                 || (!sup && !losers[pos].sup
00379                   && ((comp(losers[pos].key, key))
00380                     || (!comp(key, losers[pos].key)
00381                       && losers[pos].source < source))))
00382             {
00383               // The other one is smaller.
00384               std::swap(losers[pos].sup, sup);
00385               std::swap(losers[pos].source, source);
00386               std::swap(losers[pos].key, key);
00387             }
00388         }
00389 
00390       losers[0].sup = sup;
00391       losers[0].source = source;
00392       losers[0].key = key;
00393     }
00394   };
00395 
00396 #endif
00397 
00398 #if _GLIBCXX_LOSER_TREE_REFERENCE
00399 
00400 /** @brief Guarded loser tree, either copying the whole element into
00401 * the tree structure, or looking up the element via the index.
00402 *
00403 *  Guarding is done explicitly through one flag sup per element,
00404 *  inf is not needed due to a better initialization routine.  This
00405 *  is a well-performing variant.
00406 */
00407 template<typename T, typename Comparator = std::less<T> >
00408   class LoserTreeReference
00409   {
00410 #undef COPY
00411 #ifdef COPY
00412 #define KEY(i) losers[i].key
00413 #define KEY_SOURCE(i) key
00414 #else
00415 #define KEY(i) keys[losers[i].source]
00416 #define KEY_SOURCE(i) keys[i]
00417 #endif
00418   private:
00419     struct Loser
00420     {
00421       bool sup;
00422       int source;
00423 #ifdef COPY
00424       T key;
00425 #endif
00426     };
00427 
00428     unsigned int ik, k, offset;
00429     Loser* losers;
00430 #ifndef COPY
00431     T* keys;
00432 #endif
00433     Comparator comp;
00434 
00435   public:
00436     LoserTreeReference(unsigned int _k, Comparator _comp = std::less<T>())
00437     : comp(_comp)
00438     {
00439       ik = _k;
00440 
00441       // Next greater power of 2.
00442       k = 1 << (log2(ik - 1) + 1);
00443       offset = k;
00444       losers = new Loser[k * 2];
00445 #ifndef COPY
00446       keys = new T[ik];
00447 #endif
00448       for (unsigned int i = ik - 1; i < k; ++i)
00449         losers[i + k].sup = true;
00450     }
00451 
00452     ~LoserTreeReference()
00453     {
00454       delete[] losers;
00455 #ifndef COPY
00456       delete[] keys;
00457 #endif
00458     }
00459 
00460     int
00461     get_min_source()
00462     { return losers[0].source; }
00463 
00464     void
00465     insert_start(T key, int source, bool sup)
00466     {
00467       unsigned int pos = k + source;
00468 
00469       losers[pos].sup = sup;
00470       losers[pos].source = source;
00471       KEY(pos) = key;
00472     }
00473 
00474     unsigned int
00475     init_winner(unsigned int root)
00476     {
00477       if (root >= k)
00478         {
00479           return root;
00480         }
00481       else
00482         {
00483           unsigned int left = init_winner (2 * root);
00484           unsigned int right = init_winner (2 * root + 1);
00485           if (  losers[right].sup ||
00486                 (!losers[left].sup && !comp(KEY(right), KEY(left))))
00487             {
00488               // Left one is less or equal.
00489               losers[root] = losers[right];
00490               return left;
00491             }
00492           else
00493             {
00494               // Right one is less.
00495               losers[root] = losers[left];
00496               return right;
00497             }
00498         }
00499     }
00500 
00501     void
00502     init()
00503     {
00504       losers[0] = losers[init_winner(1)];
00505     }
00506 
00507     void
00508     delete_min_insert(T key, bool sup)
00509     {
00510       int source = losers[0].source;
00511       for (unsigned int pos = (k + source) / 2; pos > 0; pos /= 2)
00512         {
00513           // The smaller one gets promoted.
00514           if (sup || (!losers[pos].sup && comp(KEY(pos), KEY_SOURCE(source))))
00515             {
00516               // The other one is smaller.
00517               std::swap(losers[pos].sup, sup);
00518               std::swap(losers[pos].source, source);
00519 #ifdef COPY
00520               std::swap(KEY(pos), KEY_SOURCE(source));
00521 #endif
00522             }
00523         }
00524 
00525       losers[0].sup = sup;
00526       losers[0].source = source;
00527 #ifdef COPY
00528       KEY(0) = KEY_SOURCE(source);
00529 #endif
00530     }
00531 
00532     void
00533     insert_start_stable(T key, int source, bool sup)
00534     { return insert_start(key, source, sup); }
00535 
00536     unsigned int
00537     init_winner_stable(unsigned int root)
00538     {
00539       if (root >= k)
00540         {
00541           return root;
00542         }
00543       else
00544         {
00545           unsigned int left = init_winner (2 * root);
00546           unsigned int right = init_winner (2 * root + 1);
00547           if (losers[right].sup
00548               || (!losers[left].sup && !comp(KEY(right), KEY(left))))
00549             {
00550               // Left one is less or equal.
00551               losers[root] = losers[right];
00552               return left;
00553             }
00554           else
00555             {
00556               // Right one is less.
00557               losers[root] = losers[left];
00558               return right;
00559             }
00560         }
00561     }
00562 
00563     void
00564     init_stable()
00565     { losers[0] = losers[init_winner_stable(1)]; }
00566 
00567     void
00568     delete_min_insert_stable(T key, bool sup)
00569     {
00570       int source = losers[0].source;
00571       for (unsigned int pos = (k + source) / 2; pos > 0; pos /= 2)
00572         {
00573           // The smaller one gets promoted, ties are broken by source.
00574           if ((sup && (!losers[pos].sup || losers[pos].source < source))
00575           || (!sup && !losers[pos].sup
00576           && ((comp(KEY(pos), KEY_SOURCE(source)))
00577               || (!comp(KEY_SOURCE(source), KEY(pos))
00578               && losers[pos].source < source))))
00579             {
00580               // The other one is smaller.
00581               std::swap(losers[pos].sup, sup);
00582               std::swap(losers[pos].source, source);
00583 #ifdef COPY
00584               std::swap(KEY(pos), KEY_SOURCE(source));
00585 #endif
00586             }
00587         }
00588 
00589       losers[0].sup = sup;
00590       losers[0].source = source;
00591 #ifdef COPY
00592       KEY(0) = KEY_SOURCE(source);
00593 #endif
00594     }
00595   };
00596 #undef KEY
00597 #undef KEY_SOURCE
00598 
00599 #endif
00600 
00601 #if _GLIBCXX_LOSER_TREE_POINTER
00602 
00603 /** @brief Guarded loser tree, either copying the whole element into
00604     the tree structure, or looking up the element via the index.
00605 *  Guarding is done explicitly through one flag sup per element,
00606 *  inf is not needed due to a better initialization routine.
00607 *  This is a well-performing variant.
00608 */
00609 template<typename T, typename Comparator = std::less<T> >
00610   class LoserTreePointer
00611   {
00612   private:
00613     struct Loser
00614     {
00615       bool sup;
00616       int source;
00617       const T* keyp;
00618     };
00619 
00620     unsigned int ik, k, offset;
00621     Loser* losers;
00622     Comparator comp;
00623 
00624   public:
00625     LoserTreePointer(unsigned int _k, Comparator _comp = std::less<T>())
00626       : comp(_comp)
00627     {
00628       ik = _k;
00629 
00630       // Next greater power of 2.
00631       k = 1 << (log2(ik - 1) + 1);
00632       offset = k;
00633       losers = new Loser[k * 2];
00634       for (unsigned int i = ik - 1; i < k; ++i)
00635         losers[i + k].sup = true;
00636     }
00637 
00638     ~LoserTreePointer()
00639     { delete[] losers; }
00640 
00641     int
00642     get_min_source()
00643     { return losers[0].source; }
00644 
00645     void
00646     insert_start(const T& key, int source, bool sup)
00647     {
00648       unsigned int pos = k + source;
00649 
00650       losers[pos].sup = sup;
00651       losers[pos].source = source;
00652       losers[pos].keyp = &key;
00653     }
00654 
00655     unsigned int
00656     init_winner(unsigned int root)
00657     {
00658       if (root >= k)
00659     return root;
00660       else
00661         {
00662           unsigned int left = init_winner (2 * root);
00663           unsigned int right = init_winner (2 * root + 1);
00664           if (losers[right].sup
00665                 || (!losers[left].sup
00666                   && !comp(*losers[right].keyp, *losers[left].keyp)))
00667             {
00668               // Left one is less or equal.
00669               losers[root] = losers[right];
00670               return left;
00671             }
00672           else
00673             {
00674               // Right one is less.
00675               losers[root] = losers[left];
00676               return right;
00677             }
00678         }
00679     }
00680 
00681     void
00682     init()
00683     { losers[0] = losers[init_winner(1)]; }
00684 
00685     void
00686     delete_min_insert(const T& key, bool sup)
00687     {
00688       const T* keyp = &key;
00689       int source = losers[0].source;
00690       for (unsigned int pos = (k + source) / 2; pos > 0; pos /= 2)
00691         {
00692           // The smaller one gets promoted.
00693           if (sup || (!losers[pos].sup && comp(*losers[pos].keyp, *keyp)))
00694             {
00695               // The other one is smaller.
00696               std::swap(losers[pos].sup, sup);
00697               std::swap(losers[pos].source, source);
00698               std::swap(losers[pos].keyp, keyp);
00699             }
00700         }
00701 
00702       losers[0].sup = sup;
00703       losers[0].source = source;
00704       losers[0].keyp = keyp;
00705     }
00706 
00707     void
00708     insert_start_stable(const T& key, int source, bool sup)
00709     { return insert_start(key, source, sup); }
00710 
00711     unsigned int
00712     init_winner_stable(unsigned int root)
00713     {
00714       if (root >= k)
00715         {
00716           return root;
00717         }
00718       else
00719         {
00720           unsigned int left = init_winner (2 * root);
00721           unsigned int right = init_winner (2 * root + 1);
00722           if (losers[right].sup
00723               || (!losers[left].sup && !comp(*losers[right].keyp,
00724                                             *losers[left].keyp)))
00725             {
00726               // Left one is less or equal.
00727               losers[root] = losers[right];
00728               return left;
00729             }
00730           else
00731             {
00732               // Right one is less.
00733               losers[root] = losers[left];
00734               return right;
00735             }
00736         }
00737     }
00738 
00739     void
00740     init_stable()
00741     { losers[0] = losers[init_winner_stable(1)]; }
00742 
00743     void
00744     delete_min_insert_stable(const T& key, bool sup)
00745     {
00746       const T* keyp = &key;
00747       int source = losers[0].source;
00748       for (unsigned int pos = (k + source) / 2; pos > 0; pos /= 2)
00749         {
00750           // The smaller one gets promoted, ties are broken by source.
00751           if (  (sup && (!losers[pos].sup || losers[pos].source < source))
00752         || (!sup && !losers[pos].sup &&
00753             ((comp(*losers[pos].keyp, *keyp))
00754              || (!comp(*keyp, *losers[pos].keyp)
00755              && losers[pos].source < source))))
00756             {
00757               // The other one is smaller.
00758               std::swap(losers[pos].sup, sup);
00759               std::swap(losers[pos].source, source);
00760               std::swap(losers[pos].keyp, keyp);
00761             }
00762         }
00763 
00764       losers[0].sup = sup;
00765       losers[0].source = source;
00766       losers[0].keyp = keyp;
00767     }
00768   };
00769 
00770 #endif
00771 
00772 #if _GLIBCXX_LOSER_TREE_UNGUARDED
00773 
00774 /** @brief Unguarded loser tree, copying the whole element into the
00775 * tree structure.
00776 *
00777 *  No guarding is done, therefore not a single input sequence must
00778 *  run empty.  This is a very fast variant.
00779 */
00780 template<typename T, typename Comparator = std::less<T> >
00781   class LoserTreeUnguarded
00782   {
00783   private:
00784     struct Loser
00785     {
00786       int source;
00787       T key;
00788     };
00789 
00790     unsigned int ik, k, offset;
00791     unsigned int* mapping;
00792     Loser* losers;
00793     Comparator comp;
00794 
00795     void
00796     map(unsigned int root, unsigned int begin, unsigned int end)
00797     {
00798       if (begin + 1 == end)
00799         mapping[begin] = root;
00800       else
00801         {
00802           // Next greater or equal power of 2.
00803           unsigned int left = 1 << (log2(end - begin - 1));
00804           map(root * 2, begin, begin + left);
00805           map(root * 2 + 1, begin + left, end);
00806         }
00807     }
00808 
00809   public:
00810     LoserTreeUnguarded(unsigned int _k, Comparator _comp = std::less<T>())
00811     : comp(_comp)
00812     {
00813       ik = _k;
00814       // Next greater or equal power of 2.
00815       k = 1 << (log2(ik - 1) + 1);
00816       offset = k;
00817       losers = new Loser[k + ik];
00818       mapping = new unsigned int[ik];
00819       map(1, 0, ik);
00820     }
00821 
00822     ~LoserTreeUnguarded()
00823     {
00824       delete[] losers;
00825       delete[] mapping;
00826     }
00827 
00828     int
00829     get_min_source()
00830     { return losers[0].source; }
00831 
00832     void
00833     insert_start(const T& key, int source, bool)
00834     {
00835       unsigned int pos = mapping[source];
00836       losers[pos].source = source;
00837       losers[pos].key = key;
00838     }
00839 
00840     unsigned int
00841     init_winner(unsigned int root, unsigned int begin, unsigned int end)
00842     {
00843       if (begin + 1 == end)
00844         return mapping[begin];
00845       else
00846         {
00847           // Next greater or equal power of 2.
00848           unsigned int division = 1 << (log2(end - begin - 1));
00849           unsigned int left = init_winner(2 * root, begin, begin + division);
00850           unsigned int right =
00851                           init_winner(2 * root + 1, begin + division, end);
00852           if (!comp(losers[right].key, losers[left].key))
00853             {
00854               // Left one is less or equal.
00855               losers[root] = losers[right];
00856               return left;
00857             }
00858           else
00859             {
00860               // Right one is less.
00861               losers[root] = losers[left];
00862               return right;
00863             }
00864         }
00865     }
00866 
00867     void
00868     init()
00869     { losers[0] = losers[init_winner(1, 0, ik)]; }
00870 
00871     // Do not pass const reference since key will be used as local variable.
00872     void
00873     delete_min_insert(const T& key, bool)
00874     {
00875       losers[0].key = key;
00876       T& keyr = losers[0].key;
00877       int& source = losers[0].source;
00878       for (int pos = mapping[source] / 2; pos > 0; pos /= 2)
00879         {
00880           // The smaller one gets promoted.
00881           if (comp(losers[pos].key, keyr))
00882             {
00883               // The other one is smaller.
00884               std::swap(losers[pos].source, source);
00885               std::swap(losers[pos].key, keyr);
00886             }
00887         }
00888     }
00889 
00890     void
00891     insert_start_stable(const T& key, int source, bool)
00892     { return insert_start(key, source, false); }
00893 
00894     void
00895     init_stable()
00896     { init(); }
00897 
00898     void
00899     delete_min_insert_stable(const T& key, bool)
00900     {
00901       losers[0].key = key;
00902       T& keyr = losers[0].key;
00903       int& source = losers[0].source;
00904       for (int pos = mapping[source] / 2; pos > 0; pos /= 2)
00905         {
00906           // The smaller one gets promoted, ties are broken by source.
00907           if (comp(losers[pos].key, keyr)
00908               || (!comp(keyr, losers[pos].key)
00909                 && losers[pos].source < source))
00910             {
00911               // The other one is smaller.
00912               std::swap(losers[pos].source, source);
00913               std::swap(losers[pos].key, keyr);
00914             }
00915         }
00916     }
00917   };
00918 
00919 #endif
00920 
00921 #if _GLIBCXX_LOSER_TREE_POINTER_UNGUARDED
00922 
00923 /** @brief Unguarded loser tree, keeping only pointers to the
00924 * elements in the tree structure.
00925 *
00926 *  No guarding is done, therefore not a single input sequence must
00927 *  run empty.  This is a very fast variant.
00928 */
00929 template<typename T, typename Comparator = std::less<T> >
00930   class LoserTreePointerUnguarded
00931   {
00932   private:
00933     struct Loser
00934     {
00935       int source;
00936       const T* keyp;
00937     };
00938 
00939     unsigned int ik, k, offset;
00940     unsigned int* mapping;
00941     Loser* losers;
00942     Comparator comp;
00943 
00944     void map(unsigned int root, unsigned int begin, unsigned int end)
00945     {
00946       if (begin + 1 == end)
00947         mapping[begin] = root;
00948       else
00949         {
00950           // Next greater or equal power of 2.
00951           unsigned int left = 1 << (log2(end - begin - 1));
00952           map(root * 2, begin, begin + left);
00953           map(root * 2 + 1, begin + left, end);
00954         }
00955     }
00956 
00957   public:
00958     LoserTreePointerUnguarded(unsigned int _k,
00959                               Comparator _comp = std::less<T>())
00960     : comp(_comp)
00961     {
00962       ik = _k;
00963 
00964       // Next greater power of 2.
00965       k = 1 << (log2(ik - 1) + 1);
00966       offset = k;
00967       losers = new Loser[k + ik];
00968       mapping = new unsigned int[ik];
00969       map(1, 0, ik);
00970     }
00971 
00972     ~LoserTreePointerUnguarded()
00973     {
00974       delete[] losers;
00975       delete[] mapping;
00976     }
00977 
00978     int
00979     get_min_source()
00980     { return losers[0].source; }
00981 
00982     void
00983     insert_start(const T& key, int source, bool)
00984     {
00985       unsigned int pos = mapping[source];
00986       losers[pos].source = source;
00987       losers[pos].keyp = &key;
00988     }
00989 
00990     unsigned int
00991     init_winner(unsigned int root, unsigned int begin, unsigned int end)
00992     {
00993       if (begin + 1 == end)
00994         return mapping[begin];
00995       else
00996         {
00997           // Next greater or equal power of 2.
00998           unsigned int division = 1 << (log2(end - begin - 1));
00999           unsigned int left = init_winner(2 * root, begin, begin + division);
01000           unsigned int right = init_winner(2 * root + 1,
01001                        begin + division, end);
01002           if (!comp(*losers[right].keyp, *losers[left].keyp))
01003             {
01004               // Left one is less or equal.
01005               losers[root] = losers[right];
01006               return left;
01007             }
01008           else
01009             {
01010               // Right one is less.
01011               losers[root] = losers[left];
01012               return right;
01013             }
01014         }
01015     }
01016 
01017     void
01018     init()
01019     { losers[0] = losers[init_winner(1, 0, ik)]; }
01020 
01021     void
01022     delete_min_insert(const T& key, bool)
01023     {
01024       const T* keyp = &key;
01025       int& source = losers[0].source;
01026       for (int pos = mapping[source] / 2; pos > 0; pos /= 2)
01027         {
01028           // The smaller one gets promoted.
01029           if (comp(*losers[pos].keyp, *keyp))
01030             {
01031               // The other one is smaller.
01032               std::swap(losers[pos].source, source);
01033               std::swap(losers[pos].keyp, keyp);
01034             }
01035         }
01036 
01037       losers[0].keyp = keyp;
01038     }
01039 
01040     void
01041     insert_start_stable(const T& key, int source, bool)
01042     { return insert_start(key, source, false); }
01043 
01044     void
01045     init_stable()
01046     { init(); }
01047 
01048     void
01049     delete_min_insert_stable(const T& key, bool)
01050     {
01051       int& source = losers[0].source;
01052       const T* keyp = &key;
01053       for (int pos = mapping[source] / 2; pos > 0; pos /= 2)
01054         {
01055           // The smaller one gets promoted, ties are broken by source.
01056           if (comp(*losers[pos].keyp, *keyp)
01057               || (!comp(*keyp, *losers[pos].keyp)
01058                   && losers[pos].source < source))
01059             {
01060               // The other one is smaller.
01061               std::swap(losers[pos].source, source);
01062               std::swap(losers[pos].keyp, keyp);
01063             }
01064         }
01065       losers[0].keyp = keyp;
01066     }
01067   };
01068 #endif
01069 
01070 template<typename _ValueTp, class Comparator>
01071   struct loser_tree_traits
01072   {
01073 #if _GLIBCXX_LOSER_TREE
01074     typedef LoserTree<_ValueTp, Comparator> LT;
01075 #else
01076 #  if _GLIBCXX_LOSER_TREE_POINTER
01077     typedef LoserTreePointer<_ValueTp, Comparator> LT;
01078 #  else
01079 #    error Must define some type in losertree.h.
01080 #  endif
01081 #endif
01082   };
01083 
01084 template<typename _ValueTp, class Comparator>
01085   struct loser_tree_unguarded_traits
01086   {
01087 #if _GLIBCXX_LOSER_TREE_UNGUARDED
01088     typedef LoserTreeUnguarded<_ValueTp, Comparator> LT;
01089 #else
01090 #  if _GLIBCXX_LOSER_TREE_POINTER_UNGUARDED
01091     typedef LoserTreePointerUnguarded<_ValueTp, Comparator> LT;
01092 #  else
01093 #    error Must define some unguarded type in losertree.h.
01094 #  endif
01095 #endif
01096   };
01097 
01098 }
01099 
01100 #endif

Generated on Wed Mar 26 00:43:00 2008 for libstdc++ by  doxygen 1.5.1