Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:44:16

0001 /////////////////////////////////////////////////////////////////////////////
0002 //
0003 // (C) Copyright Daniel K. O. 2005.
0004 // (C) Copyright Ion Gaztanaga 2007-2014
0005 //
0006 // Distributed under the Boost Software License, Version 1.0.
0007 //    (See accompanying file LICENSE_1_0.txt or copy at
0008 //          http://www.boost.org/LICENSE_1_0.txt)
0009 //
0010 // See http://www.boost.org/libs/intrusive for documentation.
0011 //
0012 /////////////////////////////////////////////////////////////////////////////
0013 
0014 #ifndef BOOST_INTRUSIVE_AVLTREE_ALGORITHMS_HPP
0015 #define BOOST_INTRUSIVE_AVLTREE_ALGORITHMS_HPP
0016 
0017 #include <boost/intrusive/detail/config_begin.hpp>
0018 #include <boost/intrusive/intrusive_fwd.hpp>
0019 
0020 #include <cstddef>
0021 
0022 #include <boost/intrusive/detail/assert.hpp>
0023 #include <boost/intrusive/detail/algo_type.hpp>
0024 #include <boost/intrusive/detail/ebo_functor_holder.hpp>
0025 #include <boost/intrusive/bstree_algorithms.hpp>
0026 
0027 #if defined(BOOST_HAS_PRAGMA_ONCE)
0028 #  pragma once
0029 #endif
0030 
0031 
0032 namespace boost {
0033 namespace intrusive {
0034 
0035 /// @cond
0036 
0037 template<class NodeTraits, class F>
0038 struct avltree_node_cloner
0039    //Use public inheritance to avoid MSVC bugs with closures
0040    :  public detail::ebo_functor_holder<F>
0041 {
0042    typedef typename NodeTraits::node_ptr  node_ptr;
0043    typedef detail::ebo_functor_holder<F>  base_t;
0044 
0045    BOOST_INTRUSIVE_FORCEINLINE avltree_node_cloner(F f)
0046       :  base_t(f)
0047    {}
0048 
0049    node_ptr operator()(node_ptr p)
0050    {
0051       node_ptr n = base_t::get()(p);
0052       NodeTraits::set_balance(n, NodeTraits::get_balance(p));
0053       return n;
0054    }
0055 
0056    node_ptr operator()(node_ptr p) const
0057    {
0058       node_ptr n = base_t::get()(p);
0059       NodeTraits::set_balance(n, NodeTraits::get_balance(p));
0060       return n;
0061    }
0062 };
0063 
0064 namespace detail {
0065 
0066 template<class ValueTraits, class NodePtrCompare, class ExtraChecker>
0067 struct avltree_node_checker
0068       : public bstree_node_checker<ValueTraits, NodePtrCompare, ExtraChecker>
0069 {
0070    typedef bstree_node_checker<ValueTraits, NodePtrCompare, ExtraChecker> base_checker_t;
0071    typedef ValueTraits                             value_traits;
0072    typedef typename value_traits::node_traits      node_traits;
0073    typedef typename node_traits::const_node_ptr    const_node_ptr;
0074 
0075    struct return_type
0076          : public base_checker_t::return_type
0077    {
0078       return_type() : height(0) {}
0079       int height;
0080    };
0081 
0082    avltree_node_checker(const NodePtrCompare& comp, ExtraChecker extra_checker)
0083       : base_checker_t(comp, extra_checker)
0084    {}
0085 
0086    void operator () (const_node_ptr p,
0087                      const return_type& check_return_left, const return_type& check_return_right,
0088                      return_type& check_return)
0089    {
0090       const int height_diff = check_return_right.height - check_return_left.height; (void)height_diff;
0091       BOOST_INTRUSIVE_INVARIANT_ASSERT(
0092          (height_diff == -1 && node_traits::get_balance(p) == node_traits::negative()) ||
0093          (height_diff ==  0 && node_traits::get_balance(p) == node_traits::zero()) ||
0094          (height_diff ==  1 && node_traits::get_balance(p) == node_traits::positive())
0095       );
0096       check_return.height = 1 +
0097          (check_return_left.height > check_return_right.height ? check_return_left.height : check_return_right.height);
0098       base_checker_t::operator()(p, check_return_left, check_return_right, check_return);
0099    }
0100 };
0101 
0102 } // namespace detail
0103 
0104 /// @endcond
0105 
0106 //! avltree_algorithms is configured with a NodeTraits class, which encapsulates the
0107 //! information about the node to be manipulated. NodeTraits must support the
0108 //! following interface:
0109 //!
0110 //! <b>Typedefs</b>:
0111 //!
0112 //! <tt>node</tt>: The type of the node that forms the binary search tree
0113 //!
0114 //! <tt>node_ptr</tt>: A pointer to a node
0115 //!
0116 //! <tt>const_node_ptr</tt>: A pointer to a const node
0117 //!
0118 //! <tt>balance</tt>: The type of the balance factor
0119 //!
0120 //! <b>Static functions</b>:
0121 //!
0122 //! <tt>static node_ptr get_parent(const_node_ptr n);</tt>
0123 //!
0124 //! <tt>static void set_parent(node_ptr n, node_ptr parent);</tt>
0125 //!
0126 //! <tt>static node_ptr get_left(const_node_ptr n);</tt>
0127 //!
0128 //! <tt>static void set_left(node_ptr n, node_ptr left);</tt>
0129 //!
0130 //! <tt>static node_ptr get_right(const_node_ptr n);</tt>
0131 //!
0132 //! <tt>static void set_right(node_ptr n, node_ptr right);</tt>
0133 //!
0134 //! <tt>static balance get_balance(const_node_ptr n);</tt>
0135 //!
0136 //! <tt>static void set_balance(node_ptr n, balance b);</tt>
0137 //!
0138 //! <tt>static balance negative();</tt>
0139 //!
0140 //! <tt>static balance zero();</tt>
0141 //!
0142 //! <tt>static balance positive();</tt>
0143 template<class NodeTraits>
0144 class avltree_algorithms
0145    #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
0146    : public bstree_algorithms<NodeTraits>
0147    #endif
0148 {
0149    public:
0150    typedef typename NodeTraits::node            node;
0151    typedef NodeTraits                           node_traits;
0152    typedef typename NodeTraits::node_ptr        node_ptr;
0153    typedef typename NodeTraits::const_node_ptr  const_node_ptr;
0154    typedef typename NodeTraits::balance         balance;
0155 
0156    /// @cond
0157    private:
0158    typedef bstree_algorithms<NodeTraits>  bstree_algo;
0159 
0160    /// @endcond
0161 
0162    public:
0163    //! This type is the information that will be
0164    //! filled by insert_unique_check
0165    typedef typename bstree_algo::insert_commit_data insert_commit_data;
0166 
0167    #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
0168 
0169    //! @copydoc ::boost::intrusive::bstree_algorithms::get_header(const_node_ptr)
0170    static node_ptr get_header(const_node_ptr n) BOOST_NOEXCEPT;
0171 
0172    //! @copydoc ::boost::intrusive::bstree_algorithms::begin_node
0173    static node_ptr begin_node(const_node_ptr header) BOOST_NOEXCEPT;
0174 
0175    //! @copydoc ::boost::intrusive::bstree_algorithms::end_node
0176    static node_ptr end_node(const_node_ptr header) BOOST_NOEXCEPT;
0177 
0178    //! @copydoc ::boost::intrusive::bstree_algorithms::swap_tree
0179    static void swap_tree(node_ptr header1, node_ptr header2) BOOST_NOEXCEPT;
0180 
0181    #endif   //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
0182 
0183    //! @copydoc ::boost::intrusive::bstree_algorithms::swap_nodes(node_ptr,node_ptr)
0184    static void swap_nodes(node_ptr node1, node_ptr node2) BOOST_NOEXCEPT
0185    {
0186       if(node1 == node2)
0187          return;
0188 
0189       node_ptr header1(bstree_algo::get_header(node1)), header2(bstree_algo::get_header(node2));
0190       swap_nodes(node1, header1, node2, header2);
0191    }
0192 
0193    //! @copydoc ::boost::intrusive::bstree_algorithms::swap_nodes(node_ptr,node_ptr,node_ptr,node_ptr)
0194    static void swap_nodes(node_ptr node1, node_ptr header1, node_ptr node2, node_ptr header2) BOOST_NOEXCEPT
0195    {
0196       if(node1 == node2)   return;
0197 
0198       bstree_algo::swap_nodes(node1, header1, node2, header2);
0199       //Swap balance
0200       balance c = NodeTraits::get_balance(node1);
0201       NodeTraits::set_balance(node1, NodeTraits::get_balance(node2));
0202       NodeTraits::set_balance(node2, c);
0203    }
0204 
0205    //! @copydoc ::boost::intrusive::bstree_algorithms::replace_node(node_ptr,node_ptr)
0206    static void replace_node(node_ptr node_to_be_replaced, node_ptr new_node) BOOST_NOEXCEPT
0207    {
0208       if(node_to_be_replaced == new_node)
0209          return;
0210       replace_node(node_to_be_replaced, bstree_algo::get_header(node_to_be_replaced), new_node);
0211    }
0212 
0213    //! @copydoc ::boost::intrusive::bstree_algorithms::replace_node(node_ptr,node_ptr,node_ptr)
0214    static void replace_node(node_ptr node_to_be_replaced, node_ptr header, node_ptr new_node) BOOST_NOEXCEPT
0215    {
0216       bstree_algo::replace_node(node_to_be_replaced, header, new_node);
0217       NodeTraits::set_balance(new_node, NodeTraits::get_balance(node_to_be_replaced));
0218    }
0219 
0220    //! @copydoc ::boost::intrusive::bstree_algorithms::unlink(node_ptr)
0221    static void unlink(node_ptr n) BOOST_NOEXCEPT
0222    {
0223       node_ptr x = NodeTraits::get_parent(n);
0224       if(x){
0225          while(!is_header(x))
0226             x = NodeTraits::get_parent(x);
0227          erase(x, n);
0228       }
0229    }
0230 
0231    #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
0232    //! @copydoc ::boost::intrusive::bstree_algorithms::unlink_leftmost_without_rebalance
0233    static node_ptr unlink_leftmost_without_rebalance(node_ptr header) BOOST_NOEXCEPT;
0234 
0235    //! @copydoc ::boost::intrusive::bstree_algorithms::unique(const_node_ptr)
0236    static bool unique(const_node_ptr n) BOOST_NOEXCEPT;
0237 
0238    //! @copydoc ::boost::intrusive::bstree_algorithms::size(const_node_ptr)
0239    static std::size_t size(const_node_ptr header) BOOST_NOEXCEPT;
0240 
0241    //! @copydoc ::boost::intrusive::bstree_algorithms::next_node(node_ptr)
0242    static node_ptr next_node(node_ptr n) BOOST_NOEXCEPT;
0243 
0244    //! @copydoc ::boost::intrusive::bstree_algorithms::prev_node(node_ptr)
0245    static node_ptr prev_node(node_ptr n) BOOST_NOEXCEPT;
0246 
0247    //! @copydoc ::boost::intrusive::bstree_algorithms::init(node_ptr)
0248    static void init(node_ptr n) BOOST_NOEXCEPT;
0249    #endif   //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
0250 
0251    //! <b>Requires</b>: header must not be part of any tree.
0252    //!
0253    //! <b>Effects</b>: Initializes the header to represent an empty tree.
0254    //!   unique(header) == true.
0255    //!
0256    //! <b>Complexity</b>: Constant.
0257    //!
0258    //! <b>Throws</b>: Nothing.
0259    //!
0260    //! <b>Nodes</b>: If header is inserted in a tree, this function corrupts the tree.
0261    static void init_header(node_ptr header) BOOST_NOEXCEPT
0262    {
0263       bstree_algo::init_header(header);
0264       NodeTraits::set_balance(header, NodeTraits::zero());
0265    }
0266 
0267    //! @copydoc ::boost::intrusive::bstree_algorithms::erase(node_ptr,node_ptr)
0268    static node_ptr erase(node_ptr header, node_ptr z) BOOST_NOEXCEPT
0269    {
0270       typename bstree_algo::data_for_rebalance info;
0271       bstree_algo::erase(header, z, info);
0272       rebalance_after_erasure(header, z, info);
0273       return z;
0274    }
0275 
0276    //! @copydoc ::boost::intrusive::bstree_algorithms::transfer_unique
0277    template<class NodePtrCompare>
0278    static bool transfer_unique
0279       (node_ptr header1, NodePtrCompare comp, node_ptr header2, node_ptr z)
0280    {
0281       typename bstree_algo::data_for_rebalance info;
0282       bool const transferred = bstree_algo::transfer_unique(header1, comp, header2, z, info);
0283       if(transferred){
0284          rebalance_after_erasure(header2, z, info);
0285          rebalance_after_insertion(header1, z);
0286       }
0287       return transferred;
0288    }
0289 
0290    //! @copydoc ::boost::intrusive::bstree_algorithms::transfer_equal
0291    template<class NodePtrCompare>
0292    static void transfer_equal
0293       (node_ptr header1, NodePtrCompare comp, node_ptr header2, node_ptr z)
0294    {
0295       typename bstree_algo::data_for_rebalance info;
0296       bstree_algo::transfer_equal(header1, comp, header2, z, info);
0297       rebalance_after_erasure(header2, z, info);
0298       rebalance_after_insertion(header1, z);
0299    }
0300 
0301    //! @copydoc ::boost::intrusive::bstree_algorithms::clone(const_node_ptr,node_ptr,Cloner,Disposer)
0302    template <class Cloner, class Disposer>
0303    static void clone
0304       (const_node_ptr source_header, node_ptr target_header, Cloner cloner, Disposer disposer)
0305    {
0306       avltree_node_cloner<NodeTraits, Cloner> new_cloner(cloner);
0307       bstree_algo::clone(source_header, target_header, new_cloner, disposer);
0308    }
0309 
0310    #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
0311    //! @copydoc ::boost::intrusive::bstree_algorithms::clear_and_dispose(node_ptr,Disposer)
0312    template<class Disposer>
0313    static void clear_and_dispose(node_ptr header, Disposer disposer) BOOST_NOEXCEPT;
0314 
0315    //! @copydoc ::boost::intrusive::bstree_algorithms::lower_bound(const_node_ptr,const KeyType&,KeyNodePtrCompare)
0316    template<class KeyType, class KeyNodePtrCompare>
0317    static node_ptr lower_bound
0318       (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp);
0319 
0320    //! @copydoc ::boost::intrusive::bstree_algorithms::upper_bound(const_node_ptr,const KeyType&,KeyNodePtrCompare)
0321    template<class KeyType, class KeyNodePtrCompare>
0322    static node_ptr upper_bound
0323       (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp);
0324 
0325    //! @copydoc ::boost::intrusive::bstree_algorithms::find(const_node_ptr,const KeyType&,KeyNodePtrCompare)
0326    template<class KeyType, class KeyNodePtrCompare>
0327    static node_ptr find
0328       (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp);
0329 
0330    //! @copydoc ::boost::intrusive::bstree_algorithms::equal_range(const_node_ptr,const KeyType&,KeyNodePtrCompare)
0331    template<class KeyType, class KeyNodePtrCompare>
0332    static std::pair<node_ptr, node_ptr> equal_range
0333       (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp);
0334 
0335    //! @copydoc ::boost::intrusive::bstree_algorithms::bounded_range(const_node_ptr,const KeyType&,const KeyType&,KeyNodePtrCompare,bool,bool)
0336    template<class KeyType, class KeyNodePtrCompare>
0337    static std::pair<node_ptr, node_ptr> bounded_range
0338       (const_node_ptr header, const KeyType &lower_key, const KeyType &upper_key, KeyNodePtrCompare comp
0339       , bool left_closed, bool right_closed);
0340 
0341    //! @copydoc ::boost::intrusive::bstree_algorithms::count(const_node_ptr,const KeyType&,KeyNodePtrCompare)
0342    template<class KeyType, class KeyNodePtrCompare>
0343    static std::size_t count(const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp);
0344 
0345    #endif   //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
0346 
0347    //! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal_upper_bound(node_ptr,node_ptr,NodePtrCompare)
0348    template<class NodePtrCompare>
0349    static node_ptr insert_equal_upper_bound
0350       (node_ptr h, node_ptr new_node, NodePtrCompare comp)
0351    {
0352       bstree_algo::insert_equal_upper_bound(h, new_node, comp);
0353       rebalance_after_insertion(h, new_node);
0354       return new_node;
0355    }
0356 
0357    //! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal_lower_bound(node_ptr,node_ptr,NodePtrCompare)
0358    template<class NodePtrCompare>
0359    static node_ptr insert_equal_lower_bound
0360       (node_ptr h, node_ptr new_node, NodePtrCompare comp)
0361    {
0362       bstree_algo::insert_equal_lower_bound(h, new_node, comp);
0363       rebalance_after_insertion(h, new_node);
0364       return new_node;
0365    }
0366 
0367    //! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal(node_ptr,node_ptr,node_ptr,NodePtrCompare)
0368    template<class NodePtrCompare>
0369    static node_ptr insert_equal
0370       (node_ptr header, node_ptr hint, node_ptr new_node, NodePtrCompare comp)
0371    {
0372       bstree_algo::insert_equal(header, hint, new_node, comp);
0373       rebalance_after_insertion(header, new_node);
0374       return new_node;
0375    }
0376 
0377    //! @copydoc ::boost::intrusive::bstree_algorithms::insert_before(node_ptr,node_ptr,node_ptr)
0378    static node_ptr insert_before
0379       (node_ptr header, node_ptr pos, node_ptr new_node) BOOST_NOEXCEPT
0380    {
0381       bstree_algo::insert_before(header, pos, new_node);
0382       rebalance_after_insertion(header, new_node);
0383       return new_node;
0384    }
0385 
0386    //! @copydoc ::boost::intrusive::bstree_algorithms::push_back(node_ptr,node_ptr)
0387    static void push_back(node_ptr header, node_ptr new_node) BOOST_NOEXCEPT
0388    {
0389       bstree_algo::push_back(header, new_node);
0390       rebalance_after_insertion(header, new_node);
0391    }
0392 
0393    //! @copydoc ::boost::intrusive::bstree_algorithms::push_front(node_ptr,node_ptr)
0394    static void push_front(node_ptr header, node_ptr new_node) BOOST_NOEXCEPT
0395    {
0396       bstree_algo::push_front(header, new_node);
0397       rebalance_after_insertion(header, new_node);
0398    }
0399 
0400    #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
0401    //! @copydoc ::boost::intrusive::bstree_algorithms::insert_unique_check(const_node_ptr,const KeyType&,KeyNodePtrCompare,insert_commit_data&)
0402    template<class KeyType, class KeyNodePtrCompare>
0403    static std::pair<node_ptr, bool> insert_unique_check
0404       (const_node_ptr header,  const KeyType &key
0405       ,KeyNodePtrCompare comp, insert_commit_data &commit_data);
0406 
0407    //! @copydoc ::boost::intrusive::bstree_algorithms::insert_unique_check(const_node_ptr,node_ptr,const KeyType&,KeyNodePtrCompare,insert_commit_data&)
0408    template<class KeyType, class KeyNodePtrCompare>
0409    static std::pair<node_ptr, bool> insert_unique_check
0410       (const_node_ptr header, node_ptr hint, const KeyType &key
0411       ,KeyNodePtrCompare comp, insert_commit_data &commit_data);
0412    #endif   //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
0413 
0414    //! @copydoc ::boost::intrusive::bstree_algorithms::insert_unique_commit(node_ptr,node_ptr,const insert_commit_data &)
0415    static void insert_unique_commit
0416       (node_ptr header, node_ptr new_value, const insert_commit_data &commit_data) BOOST_NOEXCEPT
0417    {
0418       bstree_algo::insert_unique_commit(header, new_value, commit_data);
0419       rebalance_after_insertion(header, new_value);
0420    }
0421 
0422    //! @copydoc ::boost::intrusive::bstree_algorithms::is_header
0423    static bool is_header(const_node_ptr p) BOOST_NOEXCEPT
0424    {  return NodeTraits::get_balance(p) == NodeTraits::zero() && bstree_algo::is_header(p);  }
0425 
0426 
0427    /// @cond
0428    static bool verify(node_ptr header)
0429    {
0430       std::size_t height;
0431       std::size_t count;
0432       return verify_recursion(NodeTraits::get_parent(header), count, height);
0433    }
0434 
0435    private:
0436 
0437    static bool verify_recursion(node_ptr n, std::size_t &count, std::size_t &height)
0438    {
0439       if (!n){
0440          count = 0;
0441          height = 0;
0442          return true;
0443       }
0444       std::size_t leftcount, rightcount;
0445       std::size_t leftheight, rightheight;
0446       if(!verify_recursion(NodeTraits::get_left (n), leftcount,  leftheight) ||
0447          !verify_recursion(NodeTraits::get_right(n), rightcount, rightheight) ){
0448          return false;
0449       }
0450       count = 1u + leftcount + rightcount;
0451       height = 1u + (leftheight > rightheight ? leftheight : rightheight);
0452 
0453       //If equal height, balance must be zero
0454       if(rightheight == leftheight){
0455          if(NodeTraits::get_balance(n) != NodeTraits::zero()){
0456             BOOST_ASSERT(0);
0457             return false;
0458          }
0459       }
0460       //If right is taller than left, then the difference must be at least 1 and the balance positive
0461       else if(rightheight > leftheight){
0462          if(rightheight - leftheight > 1 ){
0463             BOOST_ASSERT(0);
0464             return false;
0465          }
0466          else if(NodeTraits::get_balance(n) != NodeTraits::positive()){
0467             BOOST_ASSERT(0);
0468             return false;
0469          }
0470       }
0471       //If left is taller than right, then the difference must be at least 1 and the balance negative
0472       else{
0473          if(leftheight - rightheight > 1 ){
0474             BOOST_ASSERT(0);
0475             return false;
0476          }
0477          else if(NodeTraits::get_balance(n) != NodeTraits::negative()){
0478             BOOST_ASSERT(0);
0479             return false;
0480          }
0481       }
0482       return true;
0483    }
0484 
0485    static void rebalance_after_erasure
0486       ( node_ptr header, node_ptr z, const typename bstree_algo::data_for_rebalance &info) BOOST_NOEXCEPT
0487    {
0488       if(info.y != z){
0489          NodeTraits::set_balance(info.y, NodeTraits::get_balance(z));
0490       }
0491       //Rebalance avltree
0492       rebalance_after_erasure_restore_invariants(header, info.x, info.x_parent);
0493    }
0494 
0495    static void rebalance_after_erasure_restore_invariants(node_ptr header, node_ptr x, node_ptr x_parent) BOOST_NOEXCEPT
0496    {
0497       for ( node_ptr root = NodeTraits::get_parent(header)
0498           ; x != root
0499           ; root = NodeTraits::get_parent(header), x_parent = NodeTraits::get_parent(x)) {
0500          const balance x_parent_balance = NodeTraits::get_balance(x_parent);
0501          //Don't cache x_is_leftchild or similar because x can be null and
0502          //equal to both x_parent_left and x_parent_right
0503          const node_ptr x_parent_left (NodeTraits::get_left(x_parent));
0504          const node_ptr x_parent_right(NodeTraits::get_right(x_parent));
0505 
0506          if(x_parent_balance == NodeTraits::zero()){
0507             NodeTraits::set_balance( x_parent, x == x_parent_right ? NodeTraits::negative() : NodeTraits::positive() );
0508             break;       // the height didn't change, let's stop here
0509          }
0510          else if(x_parent_balance == NodeTraits::negative()){
0511             if (x == x_parent_left) {  ////x is left child or x and sibling are null
0512                NodeTraits::set_balance(x_parent, NodeTraits::zero()); // balanced
0513                x = x_parent;
0514             }
0515             else {
0516                // x is right child (x_parent_left is the left child)
0517                BOOST_INTRUSIVE_INVARIANT_ASSERT(x_parent_left);
0518                if (NodeTraits::get_balance(x_parent_left) == NodeTraits::positive()) {
0519                   // x_parent_left MUST have a right child
0520                   BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_right(x_parent_left));
0521                   x = avl_rotate_left_right(x_parent, x_parent_left, header);
0522                }
0523                else {
0524                   avl_rotate_right(x_parent, x_parent_left, header);
0525                   x = x_parent_left;
0526                }
0527 
0528                // if changed from negative to NodeTraits::positive(), no need to check above
0529                if (NodeTraits::get_balance(x) == NodeTraits::positive()){
0530                   break;
0531                }
0532             }
0533          }
0534          else if(x_parent_balance == NodeTraits::positive()){
0535             if (x == x_parent_right) { //x is right child or x and sibling are null
0536                NodeTraits::set_balance(x_parent, NodeTraits::zero()); // balanced
0537                x = x_parent;
0538             }
0539             else {
0540                // x is left child (x_parent_right is the right child)
0541                BOOST_INTRUSIVE_INVARIANT_ASSERT(x_parent_right);
0542                if (NodeTraits::get_balance(x_parent_right) == NodeTraits::negative()) {
0543                   // x_parent_right MUST have then a left child
0544                   BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_left(x_parent_right));
0545                   x = avl_rotate_right_left(x_parent, x_parent_right, header);
0546                }
0547                else {
0548                   avl_rotate_left(x_parent, x_parent_right, header);
0549                   x = x_parent_right;
0550                }
0551                // if changed from NodeTraits::positive() to negative, no need to check above
0552                if (NodeTraits::get_balance(x) == NodeTraits::negative()){
0553                   break;
0554                }
0555             }
0556          }
0557          else{
0558             BOOST_INTRUSIVE_INVARIANT_ASSERT(false);  // never reached
0559          }
0560       }
0561    }
0562 
0563    static void rebalance_after_insertion(node_ptr header, node_ptr x) BOOST_NOEXCEPT
0564    {
0565       NodeTraits::set_balance(x, NodeTraits::zero());
0566       // Rebalance.
0567       for(node_ptr root = NodeTraits::get_parent(header); x != root; root = NodeTraits::get_parent(header)){
0568          node_ptr const x_parent(NodeTraits::get_parent(x));
0569          node_ptr const x_parent_left(NodeTraits::get_left(x_parent));
0570          const balance x_parent_balance = NodeTraits::get_balance(x_parent);
0571          const bool x_is_leftchild(x == x_parent_left);
0572          if(x_parent_balance == NodeTraits::zero()){
0573             // if x is left, parent will have parent->bal_factor = negative
0574             // else, parent->bal_factor = NodeTraits::positive()
0575             NodeTraits::set_balance( x_parent, x_is_leftchild ? NodeTraits::negative() : NodeTraits::positive()  );
0576             x = x_parent;
0577          }
0578          else if(x_parent_balance == NodeTraits::positive()){
0579             // if x is a left child, parent->bal_factor = zero
0580             if (x_is_leftchild)
0581                NodeTraits::set_balance(x_parent, NodeTraits::zero());
0582             else{        // x is a right child, needs rebalancing
0583                if (NodeTraits::get_balance(x) == NodeTraits::negative())
0584                   avl_rotate_right_left(x_parent, x, header);
0585                else
0586                   avl_rotate_left(x_parent, x, header);
0587             }
0588             break;
0589          }
0590          else if(x_parent_balance == NodeTraits::negative()){
0591             // if x is a left child, needs rebalancing
0592             if (x_is_leftchild) {
0593                if (NodeTraits::get_balance(x) == NodeTraits::positive())
0594                   avl_rotate_left_right(x_parent, x, header);
0595                else
0596                   avl_rotate_right(x_parent, x, header);
0597             }
0598             else
0599                NodeTraits::set_balance(x_parent, NodeTraits::zero());
0600             break;
0601          }
0602          else{
0603             BOOST_INTRUSIVE_INVARIANT_ASSERT(false);  // never reached
0604          }
0605       }
0606    }
0607 
0608    static void left_right_balancing(node_ptr a, node_ptr b, node_ptr c) BOOST_NOEXCEPT
0609    {
0610       // balancing...
0611       const balance c_balance = NodeTraits::get_balance(c);
0612       const balance zero_balance = NodeTraits::zero();
0613       const balance posi_balance = NodeTraits::positive();
0614       const balance nega_balance = NodeTraits::negative();
0615       NodeTraits::set_balance(c, zero_balance);
0616       if(c_balance == nega_balance){
0617          NodeTraits::set_balance(a, posi_balance);
0618          NodeTraits::set_balance(b, zero_balance);
0619       }
0620       else if(c_balance == zero_balance){
0621          NodeTraits::set_balance(a, zero_balance);
0622          NodeTraits::set_balance(b, zero_balance);
0623       }
0624       else if(c_balance == posi_balance){
0625          NodeTraits::set_balance(a, zero_balance);
0626          NodeTraits::set_balance(b, nega_balance);
0627       }
0628       else{
0629          BOOST_INTRUSIVE_INVARIANT_ASSERT(false); // never reached
0630       }
0631    }
0632 
0633    static node_ptr avl_rotate_left_right(const node_ptr a, const node_ptr a_oldleft, node_ptr hdr) BOOST_NOEXCEPT
0634    {  // [note: 'a_oldleft' is 'b']
0635       //             |                               |         //
0636       //             a(-2)                           c         //
0637       //            / \                             / \        //
0638       //           /   \        ==>                /   \       //
0639       //      (pos)b    [g]                       b     a      //
0640       //          / \                            / \   / \     //
0641       //        [d]  c                         [d]  e f  [g]   //
0642       //            / \                                        //
0643       //           e   f                                       //
0644       const node_ptr c = NodeTraits::get_right(a_oldleft);
0645       bstree_algo::rotate_left_no_parent_fix(a_oldleft, c);
0646       //No need to link c with a [NodeTraits::set_parent(c, a) + NodeTraits::set_left(a, c)]
0647       //as c is not root and another rotation is coming
0648       bstree_algo::rotate_right(a, c, NodeTraits::get_parent(a), hdr);
0649       left_right_balancing(a, a_oldleft, c);
0650       return c;
0651    }
0652 
0653    static node_ptr avl_rotate_right_left(const node_ptr a, const node_ptr a_oldright, node_ptr hdr) BOOST_NOEXCEPT
0654    {  // [note: 'a_oldright' is 'b']
0655       //              |                               |           //
0656       //              a(pos)                          c           //
0657       //             / \                             / \          //
0658       //            /   \                           /   \         //
0659       //          [d]   b(neg)         ==>         a     b        //
0660       //               / \                        / \   / \       //
0661       //              c  [g]                    [d] e  f  [g]     //
0662       //             / \                                          //
0663       //            e   f                                         //
0664       const node_ptr c (NodeTraits::get_left(a_oldright));
0665       bstree_algo::rotate_right_no_parent_fix(a_oldright, c);
0666       //No need to link c with a [NodeTraits::set_parent(c, a) + NodeTraits::set_right(a, c)]
0667       //as c is not root and another rotation is coming.
0668       bstree_algo::rotate_left(a, c, NodeTraits::get_parent(a), hdr);
0669       left_right_balancing(a_oldright, a, c);
0670       return c;
0671    }
0672 
0673    static void avl_rotate_left(node_ptr x, node_ptr x_oldright, node_ptr hdr) BOOST_NOEXCEPT
0674    {
0675       bstree_algo::rotate_left(x, x_oldright, NodeTraits::get_parent(x), hdr);
0676 
0677       // reset the balancing factor
0678       if (NodeTraits::get_balance(x_oldright) == NodeTraits::positive()) {
0679          NodeTraits::set_balance(x, NodeTraits::zero());
0680          NodeTraits::set_balance(x_oldright, NodeTraits::zero());
0681       }
0682       else {        // this doesn't happen during insertions
0683          NodeTraits::set_balance(x, NodeTraits::positive());
0684          NodeTraits::set_balance(x_oldright, NodeTraits::negative());
0685       }
0686    }
0687 
0688    static void avl_rotate_right(node_ptr x, node_ptr x_oldleft, node_ptr hdr) BOOST_NOEXCEPT
0689    {
0690       bstree_algo::rotate_right(x, x_oldleft, NodeTraits::get_parent(x), hdr);
0691 
0692       // reset the balancing factor
0693       if (NodeTraits::get_balance(x_oldleft) == NodeTraits::negative()) {
0694          NodeTraits::set_balance(x, NodeTraits::zero());
0695          NodeTraits::set_balance(x_oldleft, NodeTraits::zero());
0696       }
0697       else {        // this doesn't happen during insertions
0698          NodeTraits::set_balance(x, NodeTraits::negative());
0699          NodeTraits::set_balance(x_oldleft, NodeTraits::positive());
0700       }
0701    }
0702 
0703    /// @endcond
0704 };
0705 
0706 /// @cond
0707 
0708 template<class NodeTraits>
0709 struct get_algo<AvlTreeAlgorithms, NodeTraits>
0710 {
0711    typedef avltree_algorithms<NodeTraits> type;
0712 };
0713 
0714 template <class ValueTraits, class NodePtrCompare, class ExtraChecker>
0715 struct get_node_checker<AvlTreeAlgorithms, ValueTraits, NodePtrCompare, ExtraChecker>
0716 {
0717    typedef detail::avltree_node_checker<ValueTraits, NodePtrCompare, ExtraChecker> type;
0718 };
0719 
0720 /// @endcond
0721 
0722 } //namespace intrusive
0723 } //namespace boost
0724 
0725 #include <boost/intrusive/detail/config_end.hpp>
0726 
0727 #endif //BOOST_INTRUSIVE_AVLTREE_ALGORITHMS_HPP