Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

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