# 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