Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:38:40

0001 /////////////////////////////////////////////////////////////////////////////
0002 //
0003 // (C) Copyright Ion Gaztanaga  2007-2021
0004 // (C) Copyright Daniel Steck   2021
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_BSTREE_ALGORITHMS_HPP
0015 #define BOOST_INTRUSIVE_BSTREE_ALGORITHMS_HPP
0016 
0017 #include <cstddef>
0018 #include <boost/intrusive/detail/config_begin.hpp>
0019 #include <boost/intrusive/intrusive_fwd.hpp>
0020 #include <boost/intrusive/detail/bstree_algorithms_base.hpp>
0021 #include <boost/intrusive/detail/assert.hpp>
0022 #include <boost/intrusive/detail/uncast.hpp>
0023 #include <boost/intrusive/detail/math.hpp>
0024 #include <boost/intrusive/detail/algo_type.hpp>
0025 
0026 #include <boost/intrusive/detail/minimal_pair_header.hpp>
0027 
0028 #if defined(BOOST_HAS_PRAGMA_ONCE)
0029 #  pragma once
0030 #endif
0031 
0032 namespace boost {
0033 namespace intrusive {
0034 
0035 /// @cond
0036 
0037 //! This type is the information that will be filled by insert_unique_check
0038 template <class NodePtr>
0039 struct insert_commit_data_t
0040 {
0041    BOOST_INTRUSIVE_FORCEINLINE insert_commit_data_t()
0042       : link_left(false), node()
0043    {}
0044    bool     link_left;
0045    NodePtr  node;
0046 };
0047 
0048 template <class NodePtr>
0049 struct data_for_rebalance_t
0050 {
0051    NodePtr  x;
0052    NodePtr  x_parent;
0053    NodePtr  y;
0054 };
0055 
0056 namespace detail {
0057 
0058 template<class ValueTraits, class NodePtrCompare, class ExtraChecker>
0059 struct bstree_node_checker
0060    : public ExtraChecker
0061 {
0062    typedef ExtraChecker                            base_checker_t;
0063    typedef ValueTraits                             value_traits;
0064    typedef typename value_traits::node_traits      node_traits;
0065    typedef typename node_traits::const_node_ptr    const_node_ptr;
0066 
0067    struct return_type
0068       : public base_checker_t::return_type
0069    {
0070       BOOST_INTRUSIVE_FORCEINLINE return_type()
0071          : min_key_node_ptr(const_node_ptr()), max_key_node_ptr(const_node_ptr()), node_count(0)
0072       {}
0073 
0074       const_node_ptr min_key_node_ptr;
0075       const_node_ptr max_key_node_ptr;
0076       size_t   node_count;
0077    };
0078 
0079    BOOST_INTRUSIVE_FORCEINLINE bstree_node_checker(const NodePtrCompare& comp, ExtraChecker extra_checker)
0080       : base_checker_t(extra_checker), comp_(comp)
0081    {}
0082 
0083    void operator () (const_node_ptr p,
0084                      const return_type& check_return_left, const return_type& check_return_right,
0085                      return_type& check_return)
0086    {
0087       BOOST_INTRUSIVE_INVARIANT_ASSERT(!check_return_left.max_key_node_ptr || !comp_(p, check_return_left.max_key_node_ptr));
0088       BOOST_INTRUSIVE_INVARIANT_ASSERT(!check_return_right.min_key_node_ptr || !comp_(check_return_right.min_key_node_ptr, p));
0089       check_return.min_key_node_ptr = node_traits::get_left(p)? check_return_left.min_key_node_ptr : p;
0090       check_return.max_key_node_ptr = node_traits::get_right(p)? check_return_right.max_key_node_ptr : p;
0091       check_return.node_count = check_return_left.node_count + check_return_right.node_count + 1;
0092       base_checker_t::operator()(p, check_return_left, check_return_right, check_return);
0093    }
0094 
0095    const NodePtrCompare comp_;
0096 };
0097 
0098 } // namespace detail
0099 
0100 /// @endcond
0101 
0102 
0103 
0104 //!   This is an implementation of a binary search tree.
0105 //!   A node in the search tree has references to its children and its parent. This
0106 //!   is to allow traversal of the whole tree from a given node making the
0107 //!   implementation of iterator a pointer to a node.
0108 //!   At the top of the tree a node is used specially. This node's parent pointer
0109 //!   is pointing to the root of the tree. Its left pointer points to the
0110 //!   leftmost node in the tree and the right pointer to the rightmost one.
0111 //!   This node is used to represent the end-iterator.
0112 //!
0113 //!                                            +---------+
0114 //!       header------------------------------>|         |
0115 //!                                            |         |
0116 //!                   +----------(left)--------|         |--------(right)---------+
0117 //!                   |                        +---------+                        |
0118 //!                   |                             |                             |
0119 //!                   |                             | (parent)                    |
0120 //!                   |                             |                             |
0121 //!                   |                             |                             |
0122 //!                   |                        +---------+                        |
0123 //!    root of tree ..|......................> |         |                        |
0124 //!                   |                        |    D    |                        |
0125 //!                   |                        |         |                        |
0126 //!                   |                +-------+---------+-------+                |
0127 //!                   |                |                         |                |
0128 //!                   |                |                         |                |
0129 //!                   |                |                         |                |
0130 //!                   |                |                         |                |
0131 //!                   |                |                         |                |
0132 //!                   |          +---------+                 +---------+          |
0133 //!                   |          |         |                 |         |          |
0134 //!                   |          |    B    |                 |    F    |          |
0135 //!                   |          |         |                 |         |          |
0136 //!                   |       +--+---------+--+           +--+---------+--+       |
0137 //!                   |       |               |           |               |       |
0138 //!                   |       |               |           |               |       |
0139 //!                   |       |               |           |               |       |
0140 //!                   |   +---+-----+   +-----+---+   +---+-----+   +-----+---+   |
0141 //!                   +-->|         |   |         |   |         |   |         |<--+
0142 //!                       |    A    |   |    C    |   |    E    |   |    G    |
0143 //!                       |         |   |         |   |         |   |         |
0144 //!                       +---------+   +---------+   +---------+   +---------+
0145 //!
0146 //! bstree_algorithms is configured with a NodeTraits class, which encapsulates the
0147 //! information about the node to be manipulated. NodeTraits must support the
0148 //! following interface:
0149 //!
0150 //! <b>Typedefs</b>:
0151 //!
0152 //! <tt>node</tt>: The type of the node that forms the binary search tree
0153 //!
0154 //! <tt>node_ptr</tt>: A pointer to a node
0155 //!
0156 //! <tt>const_node_ptr</tt>: A pointer to a const node
0157 //!
0158 //! <b>Static functions</b>:
0159 //!
0160 //! <tt>static node_ptr get_parent(const_node_ptr n);</tt>
0161 //!
0162 //! <tt>static void set_parent(node_ptr n, node_ptr parent);</tt>
0163 //!
0164 //! <tt>static node_ptr get_left(const_node_ptr n);</tt>
0165 //!
0166 //! <tt>static void set_left(node_ptr n, node_ptr left);</tt>
0167 //!
0168 //! <tt>static node_ptr get_right(const_node_ptr n);</tt>
0169 //!
0170 //! <tt>static void set_right(node_ptr n, node_ptr right);</tt>
0171 template<class NodeTraits>
0172 class bstree_algorithms : public bstree_algorithms_base<NodeTraits>
0173 {
0174    public:
0175    typedef typename NodeTraits::node            node;
0176    typedef NodeTraits                           node_traits;
0177    typedef typename NodeTraits::node_ptr        node_ptr;
0178    typedef typename NodeTraits::const_node_ptr  const_node_ptr;
0179    typedef insert_commit_data_t<node_ptr>       insert_commit_data;
0180    typedef data_for_rebalance_t<node_ptr>       data_for_rebalance;
0181 
0182    /// @cond
0183    typedef bstree_algorithms<NodeTraits>        this_type;
0184    typedef bstree_algorithms_base<NodeTraits>   base_type;
0185    private:
0186    template<class Disposer>
0187    struct dispose_subtree_disposer
0188    {
0189       BOOST_INTRUSIVE_FORCEINLINE dispose_subtree_disposer(Disposer &disp, node_ptr subtree)
0190          : disposer_(&disp), subtree_(subtree)
0191       {}
0192 
0193       BOOST_INTRUSIVE_FORCEINLINE void release()
0194       {  disposer_ = 0;  }
0195 
0196       BOOST_INTRUSIVE_FORCEINLINE ~dispose_subtree_disposer()
0197       {
0198          if(disposer_){
0199             dispose_subtree(subtree_, *disposer_);
0200          }
0201       }
0202       Disposer *disposer_;
0203       const node_ptr subtree_;
0204    };
0205 
0206    /// @endcond
0207 
0208    public:
0209    //! <b>Requires</b>: 'header' is the header node of a tree.
0210    //!
0211    //! <b>Effects</b>: Returns the first node of the tree, the header if the tree is empty.
0212    //!
0213    //! <b>Complexity</b>: Constant time.
0214    //!
0215    //! <b>Throws</b>: Nothing.
0216    BOOST_INTRUSIVE_FORCEINLINE static node_ptr begin_node(const_node_ptr header) BOOST_NOEXCEPT
0217    {  return node_traits::get_left(header);   }
0218 
0219    //! <b>Requires</b>: 'header' is the header node of a tree.
0220    //!
0221    //! <b>Effects</b>: Returns the header of the tree.
0222    //!
0223    //! <b>Complexity</b>: Constant time.
0224    //!
0225    //! <b>Throws</b>: Nothing.
0226    BOOST_INTRUSIVE_FORCEINLINE static node_ptr end_node(const_node_ptr header) BOOST_NOEXCEPT
0227    {  return detail::uncast(header);   }
0228 
0229    //! <b>Requires</b>: 'header' is the header node of a tree.
0230    //!
0231    //! <b>Effects</b>: Returns the root of the tree if any, header otherwise
0232    //!
0233    //! <b>Complexity</b>: Constant time.
0234    //!
0235    //! <b>Throws</b>: Nothing.
0236    BOOST_INTRUSIVE_FORCEINLINE static node_ptr root_node(const_node_ptr header) BOOST_NOEXCEPT
0237    {
0238       node_ptr p = node_traits::get_parent(header);
0239       return p ? p : detail::uncast(header);
0240    }
0241 
0242    //! <b>Requires</b>: 'n' is a node of the tree or a node initialized
0243    //!   by init(...) or init_node.
0244    //!
0245    //! <b>Effects</b>: Returns true if the node is initialized by init() or init_node().
0246    //!
0247    //! <b>Complexity</b>: Constant time.
0248    //!
0249    //! <b>Throws</b>: Nothing.
0250    BOOST_INTRUSIVE_FORCEINLINE static bool unique(const_node_ptr n) BOOST_NOEXCEPT
0251    { return !NodeTraits::get_parent(n); }
0252 
0253    #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
0254    //! <b>Requires</b>: 'n' is a node of the tree or a header node.
0255    //!
0256    //! <b>Effects</b>: Returns the header of the tree.
0257    //!
0258    //! <b>Complexity</b>: Logarithmic.
0259    //!
0260    //! <b>Throws</b>: Nothing.
0261    static node_ptr get_header(const_node_ptr n);
0262    #endif
0263 
0264    //! <b>Requires</b>: node1 and node2 can't be header nodes
0265    //!  of two trees.
0266    //!
0267    //! <b>Effects</b>: Swaps two nodes. After the function node1 will be inserted
0268    //!   in the position node2 before the function. node2 will be inserted in the
0269    //!   position node1 had before the function.
0270    //!
0271    //! <b>Complexity</b>: Logarithmic.
0272    //!
0273    //! <b>Throws</b>: Nothing.
0274    //!
0275    //! <b>Note</b>: This function will break container ordering invariants if
0276    //!   node1 and node2 are not equivalent according to the ordering rules.
0277    //!
0278    //!Experimental function
0279    static void swap_nodes(node_ptr node1, node_ptr node2) BOOST_NOEXCEPT
0280    {
0281       if(node1 == node2)
0282          return;
0283 
0284       node_ptr header1(base_type::get_header(node1)), header2(base_type::get_header(node2));
0285       swap_nodes(node1, header1, node2, header2);
0286    }
0287 
0288    //! <b>Requires</b>: node1 and node2 can't be header nodes
0289    //!  of two trees with header header1 and header2.
0290    //!
0291    //! <b>Effects</b>: Swaps two nodes. After the function node1 will be inserted
0292    //!   in the position node2 before the function. node2 will be inserted in the
0293    //!   position node1 had before the function.
0294    //!
0295    //! <b>Complexity</b>: Constant.
0296    //!
0297    //! <b>Throws</b>: Nothing.
0298    //!
0299    //! <b>Note</b>: This function will break container ordering invariants if
0300    //!   node1 and node2 are not equivalent according to the ordering rules.
0301    //!
0302    //!Experimental function
0303    static void swap_nodes(node_ptr node1, node_ptr header1, node_ptr node2, node_ptr header2) BOOST_NOEXCEPT
0304    {
0305       if(node1 == node2)
0306          return;
0307 
0308       //node1 and node2 must not be header nodes
0309       //BOOST_INTRUSIVE_INVARIANT_ASSERT((header1 != node1 && header2 != node2));
0310       if(header1 != header2){
0311          //Update header1 if necessary
0312          if(node1 == NodeTraits::get_left(header1)){
0313             NodeTraits::set_left(header1, node2);
0314          }
0315 
0316          if(node1 == NodeTraits::get_right(header1)){
0317             NodeTraits::set_right(header1, node2);
0318          }
0319 
0320          if(node1 == NodeTraits::get_parent(header1)){
0321             NodeTraits::set_parent(header1, node2);
0322          }
0323 
0324          //Update header2 if necessary
0325          if(node2 == NodeTraits::get_left(header2)){
0326             NodeTraits::set_left(header2, node1);
0327          }
0328 
0329          if(node2 == NodeTraits::get_right(header2)){
0330             NodeTraits::set_right(header2, node1);
0331          }
0332 
0333          if(node2 == NodeTraits::get_parent(header2)){
0334             NodeTraits::set_parent(header2, node1);
0335          }
0336       }
0337       else{
0338          //If both nodes are from the same tree
0339          //Update header if necessary
0340          if(node1 == NodeTraits::get_left(header1)){
0341             NodeTraits::set_left(header1, node2);
0342          }
0343          else if(node2 == NodeTraits::get_left(header2)){
0344             NodeTraits::set_left(header2, node1);
0345          }
0346 
0347          if(node1 == NodeTraits::get_right(header1)){
0348             NodeTraits::set_right(header1, node2);
0349          }
0350          else if(node2 == NodeTraits::get_right(header2)){
0351             NodeTraits::set_right(header2, node1);
0352          }
0353 
0354          if(node1 == NodeTraits::get_parent(header1)){
0355             NodeTraits::set_parent(header1, node2);
0356          }
0357          else if(node2 == NodeTraits::get_parent(header2)){
0358             NodeTraits::set_parent(header2, node1);
0359          }
0360 
0361          //Adjust data in nodes to be swapped
0362          //so that final link swap works as expected
0363          if(node1 == NodeTraits::get_parent(node2)){
0364             NodeTraits::set_parent(node2, node2);
0365 
0366             if(node2 == NodeTraits::get_right(node1)){
0367                NodeTraits::set_right(node1, node1);
0368             }
0369             else{
0370                NodeTraits::set_left(node1, node1);
0371             }
0372          }
0373          else if(node2 == NodeTraits::get_parent(node1)){
0374             NodeTraits::set_parent(node1, node1);
0375 
0376             if(node1 == NodeTraits::get_right(node2)){
0377                NodeTraits::set_right(node2, node2);
0378             }
0379             else{
0380                NodeTraits::set_left(node2, node2);
0381             }
0382          }
0383       }
0384 
0385       //Now swap all the links
0386       node_ptr temp;
0387       //swap left link
0388       temp = NodeTraits::get_left(node1);
0389       NodeTraits::set_left(node1, NodeTraits::get_left(node2));
0390       NodeTraits::set_left(node2, temp);
0391       //swap right link
0392       temp = NodeTraits::get_right(node1);
0393       NodeTraits::set_right(node1, NodeTraits::get_right(node2));
0394       NodeTraits::set_right(node2, temp);
0395       //swap parent link
0396       temp = NodeTraits::get_parent(node1);
0397       NodeTraits::set_parent(node1, NodeTraits::get_parent(node2));
0398       NodeTraits::set_parent(node2, temp);
0399 
0400       //Now adjust child nodes for newly inserted node 1
0401       if((temp = NodeTraits::get_left(node1))){
0402          NodeTraits::set_parent(temp, node1);
0403       }
0404       if((temp = NodeTraits::get_right(node1))){
0405          NodeTraits::set_parent(temp, node1);
0406       }
0407       //Now adjust child nodes for newly inserted node 2
0408       if((temp = NodeTraits::get_left(node2))){
0409          NodeTraits::set_parent(temp, node2);
0410       }
0411       if((temp = NodeTraits::get_right(node2))){
0412          NodeTraits::set_parent(temp, node2);
0413       }
0414 
0415       //Finally adjust parent nodes
0416       if ((temp = NodeTraits::get_parent(node1)) == NodeTraits::get_parent(node2)) {
0417          // special logic for the case where the nodes are siblings
0418          const node_ptr left = NodeTraits::get_left(temp);
0419          NodeTraits::set_left(temp, NodeTraits::get_right(temp));
0420          NodeTraits::set_right(temp, left);
0421       } else {
0422          if ((temp = NodeTraits::get_parent(node1)) &&
0423             //The header has been already updated so avoid it
0424             temp != header2) {
0425             if (NodeTraits::get_left(temp) == node2) {
0426                NodeTraits::set_left(temp, node1);
0427             }
0428             if (NodeTraits::get_right(temp) == node2) {
0429                NodeTraits::set_right(temp, node1);
0430             }
0431          }
0432          if ((temp = NodeTraits::get_parent(node2)) &&
0433             //The header has been already updated so avoid it
0434             temp != header1) {
0435             if (NodeTraits::get_left(temp) == node1) {
0436                NodeTraits::set_left(temp, node2);
0437             }
0438             if (NodeTraits::get_right(temp) == node1) {
0439                NodeTraits::set_right(temp, node2);
0440             }
0441          }
0442       }
0443    }
0444 
0445    //! <b>Requires</b>: node_to_be_replaced must be inserted in a tree
0446    //!   and new_node must not be inserted in a tree.
0447    //!
0448    //! <b>Effects</b>: Replaces node_to_be_replaced in its position in the
0449    //!   tree with new_node. The tree does not need to be rebalanced
0450    //!
0451    //! <b>Complexity</b>: Logarithmic.
0452    //!
0453    //! <b>Throws</b>: Nothing.
0454    //!
0455    //! <b>Note</b>: This function will break container ordering invariants if
0456    //!   new_node is not equivalent to node_to_be_replaced according to the
0457    //!   ordering rules. This function is faster than erasing and inserting
0458    //!   the node, since no rebalancing and comparison is needed. Experimental function
0459    BOOST_INTRUSIVE_FORCEINLINE static void replace_node(node_ptr node_to_be_replaced, node_ptr new_node) BOOST_NOEXCEPT
0460    {
0461       replace_node(node_to_be_replaced, base_type::get_header(node_to_be_replaced), new_node);
0462    }
0463 
0464    //! <b>Requires</b>: node_to_be_replaced must be inserted in a tree
0465    //!   with header "header" and new_node must not be inserted in a tree.
0466    //!
0467    //! <b>Effects</b>: Replaces node_to_be_replaced in its position in the
0468    //!   tree with new_node. The tree does not need to be rebalanced
0469    //!
0470    //! <b>Complexity</b>: Constant.
0471    //!
0472    //! <b>Throws</b>: Nothing.
0473    //!
0474    //! <b>Note</b>: This function will break container ordering invariants if
0475    //!   new_node is not equivalent to node_to_be_replaced according to the
0476    //!   ordering rules. This function is faster than erasing and inserting
0477    //!   the node, since no rebalancing or comparison is needed. Experimental function
0478    static void replace_node(node_ptr node_to_be_replaced, node_ptr header, node_ptr new_node) BOOST_NOEXCEPT
0479    {
0480       BOOST_ASSERT(node_to_be_replaced != new_node);
0481 
0482       //Update header if necessary
0483       if(node_to_be_replaced == NodeTraits::get_left(header)){
0484          NodeTraits::set_left(header, new_node);
0485       }
0486 
0487       if(node_to_be_replaced == NodeTraits::get_right(header)){
0488          NodeTraits::set_right(header, new_node);
0489       }
0490 
0491       if(node_to_be_replaced == NodeTraits::get_parent(header)){
0492          NodeTraits::set_parent(header, new_node);
0493       }
0494 
0495       //Now set data from the original node
0496       node_ptr temp;
0497       NodeTraits::set_left(new_node, NodeTraits::get_left(node_to_be_replaced));
0498       NodeTraits::set_right(new_node, NodeTraits::get_right(node_to_be_replaced));
0499       NodeTraits::set_parent(new_node, NodeTraits::get_parent(node_to_be_replaced));
0500 
0501       //Now adjust adjacent nodes for newly inserted node
0502       if((temp = NodeTraits::get_left(new_node))){
0503          NodeTraits::set_parent(temp, new_node);
0504       }
0505       if((temp = NodeTraits::get_right(new_node))){
0506          NodeTraits::set_parent(temp, new_node);
0507       }
0508       if((temp = NodeTraits::get_parent(new_node)) &&
0509          //The header has been already updated so avoid it
0510          temp != header){
0511          if(NodeTraits::get_left(temp) == node_to_be_replaced){
0512             NodeTraits::set_left(temp, new_node);
0513          }
0514          if(NodeTraits::get_right(temp) == node_to_be_replaced){
0515             NodeTraits::set_right(temp, new_node);
0516          }
0517       }
0518    }
0519 
0520    #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
0521    //! <b>Requires</b>: 'n' is a node from the tree except the header.
0522    //!
0523    //! <b>Effects</b>: Returns the next node of the tree.
0524    //!
0525    //! <b>Complexity</b>: Average constant time.
0526    //!
0527    //! <b>Throws</b>: Nothing.
0528    static node_ptr next_node(node_ptr n) BOOST_NOEXCEPT;
0529 
0530    //! <b>Requires</b>: 'n' is a node from the tree except the leftmost node.
0531    //!
0532    //! <b>Effects</b>: Returns the previous node of the tree.
0533    //!
0534    //! <b>Complexity</b>: Average constant time.
0535    //!
0536    //! <b>Throws</b>: Nothing.
0537    static node_ptr prev_node(node_ptr n) BOOST_NOEXCEPT;
0538 
0539    //! <b>Requires</b>: 'n' is a node of a tree but not the header.
0540    //!
0541    //! <b>Effects</b>: Returns the minimum node of the subtree starting at p.
0542    //!
0543    //! <b>Complexity</b>: Logarithmic to the size of the subtree.
0544    //!
0545    //! <b>Throws</b>: Nothing.
0546    static node_ptr minimum(node_ptr n);
0547 
0548    //! <b>Requires</b>: 'n' is a node of a tree but not the header.
0549    //!
0550    //! <b>Effects</b>: Returns the maximum node of the subtree starting at p.
0551    //!
0552    //! <b>Complexity</b>: Logarithmic to the size of the subtree.
0553    //!
0554    //! <b>Throws</b>: Nothing.
0555    static node_ptr maximum(node_ptr n);
0556    #endif
0557 
0558    //! <b>Requires</b>: 'n' must not be part of any tree.
0559    //!
0560    //! <b>Effects</b>: After the function unique(node) == true.
0561    //!
0562    //! <b>Complexity</b>: Constant.
0563    //!
0564    //! <b>Throws</b>: Nothing.
0565    //!
0566    //! <b>Nodes</b>: If node is inserted in a tree, this function corrupts the tree.
0567    static void init(node_ptr n) BOOST_NOEXCEPT
0568    {
0569       NodeTraits::set_parent(n, node_ptr());
0570       NodeTraits::set_left(n, node_ptr());
0571       NodeTraits::set_right(n, node_ptr());
0572    }
0573 
0574    //! <b>Effects</b>: Returns true if node is in the same state as if called init(node)
0575    //!
0576    //! <b>Complexity</b>: Constant.
0577    //!
0578    //! <b>Throws</b>: Nothing.
0579    static bool inited(const_node_ptr n)
0580    {
0581       return !NodeTraits::get_parent(n) &&
0582              !NodeTraits::get_left(n)   &&
0583              !NodeTraits::get_right(n)  ;
0584    }
0585 
0586    //! <b>Requires</b>: header must not be part of any tree.
0587    //!
0588    //! <b>Effects</b>: Initializes the header to represent an empty tree.
0589    //!   unique(header) == true.
0590    //!
0591    //! <b>Complexity</b>: Constant.
0592    //!
0593    //! <b>Throws</b>: Nothing.
0594    //!
0595    //! <b>Nodes</b>: If header is inserted in a tree, this function corrupts the tree.
0596    static void init_header(node_ptr header) BOOST_NOEXCEPT
0597    {
0598       NodeTraits::set_parent(header, node_ptr());
0599       NodeTraits::set_left(header, header);
0600       NodeTraits::set_right(header, header);
0601    }
0602 
0603    //! <b>Requires</b>: "disposer" must be an object function
0604    //!   taking a node_ptr parameter and shouldn't throw.
0605    //!
0606    //! <b>Effects</b>: Empties the target tree calling
0607    //!   <tt>void disposer::operator()(node_ptr)</tt> for every node of the tree
0608    //!    except the header.
0609    //!
0610    //! <b>Complexity</b>: Linear to the number of element of the source tree plus the.
0611    //!   number of elements of tree target tree when calling this function.
0612    //!
0613    //! <b>Throws</b>: Nothing.
0614    template<class Disposer>
0615    static void clear_and_dispose(node_ptr header, Disposer disposer) BOOST_NOEXCEPT
0616    {
0617       node_ptr source_root = NodeTraits::get_parent(header);
0618       if(!source_root)
0619          return;
0620       dispose_subtree(source_root, disposer);
0621       init_header(header);
0622    }
0623 
0624    //! <b>Requires</b>: header is the header of a tree.
0625    //!
0626    //! <b>Effects</b>: Unlinks the leftmost node from the tree, and
0627    //!   updates the header link to the new leftmost node.
0628    //!
0629    //! <b>Complexity</b>: Average complexity is constant time.
0630    //!
0631    //! <b>Throws</b>: Nothing.
0632    //!
0633    //! <b>Notes</b>: This function breaks the tree and the tree can
0634    //!   only be used for more unlink_leftmost_without_rebalance calls.
0635    //!   This function is normally used to achieve a step by step
0636    //!   controlled destruction of the tree.
0637    static node_ptr unlink_leftmost_without_rebalance(node_ptr header) BOOST_NOEXCEPT
0638    {
0639       node_ptr leftmost = NodeTraits::get_left(header);
0640       if (leftmost == header)
0641          return node_ptr();
0642       node_ptr leftmost_parent(NodeTraits::get_parent(leftmost));
0643       node_ptr leftmost_right (NodeTraits::get_right(leftmost));
0644       bool is_root = leftmost_parent == header;
0645 
0646       if (leftmost_right){
0647          NodeTraits::set_parent(leftmost_right, leftmost_parent);
0648          NodeTraits::set_left(header, base_type::minimum(leftmost_right));
0649 
0650          if (is_root)
0651             NodeTraits::set_parent(header, leftmost_right);
0652          else
0653             NodeTraits::set_left(NodeTraits::get_parent(header), leftmost_right);
0654       }
0655       else if (is_root){
0656          NodeTraits::set_parent(header, node_ptr());
0657          NodeTraits::set_left(header,  header);
0658          NodeTraits::set_right(header, header);
0659       }
0660       else{
0661          NodeTraits::set_left(leftmost_parent, node_ptr());
0662          NodeTraits::set_left(header, leftmost_parent);
0663       }
0664       return leftmost;
0665    }
0666 
0667    //! <b>Requires</b>: 'header' the header of the tree.
0668    //!
0669    //! <b>Effects</b>: Returns the number of nodes of the tree.
0670    //!
0671    //! <b>Complexity</b>: Linear time.
0672    //!
0673    //! <b>Throws</b>: Nothing.
0674    static std::size_t size(const_node_ptr header) BOOST_NOEXCEPT
0675    {
0676       node_ptr beg(begin_node(header));
0677       node_ptr end(end_node(header));
0678       std::size_t i = 0;
0679       for(;beg != end; beg = base_type::next_node(beg)) ++i;
0680       return i;
0681    }
0682 
0683    //! <b>Requires</b>: header1 and header2 must be the header nodes
0684    //!  of two trees.
0685    //!
0686    //! <b>Effects</b>: Swaps two trees. After the function header1 will contain
0687    //!   links to the second tree and header2 will have links to the first tree.
0688    //!
0689    //! <b>Complexity</b>: Constant.
0690    //!
0691    //! <b>Throws</b>: Nothing.
0692    static void swap_tree(node_ptr header1, node_ptr header2) BOOST_NOEXCEPT
0693    {
0694       if(header1 == header2)
0695          return;
0696 
0697       node_ptr tmp;
0698 
0699       //Parent swap
0700       tmp = NodeTraits::get_parent(header1);
0701       NodeTraits::set_parent(header1, NodeTraits::get_parent(header2));
0702       NodeTraits::set_parent(header2, tmp);
0703       //Left swap
0704       tmp = NodeTraits::get_left(header1);
0705       NodeTraits::set_left(header1, NodeTraits::get_left(header2));
0706       NodeTraits::set_left(header2, tmp);
0707       //Right swap
0708       tmp = NodeTraits::get_right(header1);
0709       NodeTraits::set_right(header1, NodeTraits::get_right(header2));
0710       NodeTraits::set_right(header2, tmp);
0711 
0712       //Now test parent
0713       node_ptr h1_parent(NodeTraits::get_parent(header1));
0714       if(h1_parent){
0715          NodeTraits::set_parent(h1_parent, header1);
0716       }
0717       else{
0718          NodeTraits::set_left(header1, header1);
0719          NodeTraits::set_right(header1, header1);
0720       }
0721 
0722       node_ptr h2_parent(NodeTraits::get_parent(header2));
0723       if(h2_parent){
0724          NodeTraits::set_parent(h2_parent, header2);
0725       }
0726       else{
0727          NodeTraits::set_left(header2, header2);
0728          NodeTraits::set_right(header2, header2);
0729       }
0730    }
0731 
0732    #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
0733    //! <b>Requires</b>: p is a node of a tree.
0734    //!
0735    //! <b>Effects</b>: Returns true if p is the header of the tree.
0736    //!
0737    //! <b>Complexity</b>: Constant.
0738    //!
0739    //! <b>Throws</b>: Nothing.
0740    static bool is_header(const_node_ptr p) BOOST_NOEXCEPT;
0741    #endif
0742 
0743    //! <b>Requires</b>: "header" must be the header node of a tree.
0744    //!   KeyNodePtrCompare is a function object that induces a strict weak
0745    //!   ordering compatible with the strict weak ordering used to create the
0746    //!   the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs.
0747    //!
0748    //! <b>Effects</b>: Returns a node_ptr to the first element that is equivalent to
0749    //!   "key" according to "comp" or "header" if that element does not exist.
0750    //!
0751    //! <b>Complexity</b>: Logarithmic.
0752    //!
0753    //! <b>Throws</b>: If "comp" throws.
0754    template<class KeyType, class KeyNodePtrCompare>
0755    static node_ptr find
0756       (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp)
0757    {
0758       node_ptr end = detail::uncast(header);
0759       node_ptr y = lower_bound(header, key, comp);
0760       return (y == end || comp(key, y)) ? end : y;
0761    }
0762 
0763    //! <b>Requires</b>: "header" must be the header node of a tree.
0764    //!   KeyNodePtrCompare is a function object that induces a strict weak
0765    //!   ordering compatible with the strict weak ordering used to create the
0766    //!   the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs.
0767    //!   'lower_key' must not be greater than 'upper_key' according to 'comp'. If
0768    //!   'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be true.
0769    //!
0770    //! <b>Effects</b>: Returns an a pair with the following criteria:
0771    //!
0772    //!   first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise
0773    //!
0774    //!   second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise
0775    //!
0776    //! <b>Complexity</b>: Logarithmic.
0777    //!
0778    //! <b>Throws</b>: If "comp" throws.
0779    //!
0780    //! <b>Note</b>: This function can be more efficient than calling upper_bound
0781    //!   and lower_bound for lower_key and upper_key.
0782    //!
0783    //! <b>Note</b>: Experimental function, the interface might change.
0784    template< class KeyType, class KeyNodePtrCompare>
0785    static std::pair<node_ptr, node_ptr> bounded_range
0786       ( const_node_ptr header
0787       , const KeyType &lower_key
0788       , const KeyType &upper_key
0789       , KeyNodePtrCompare comp
0790       , bool left_closed
0791       , bool right_closed)
0792    {
0793       node_ptr y = detail::uncast(header);
0794       node_ptr x = NodeTraits::get_parent(header);
0795 
0796       while(x){
0797          //If x is less than lower_key the target
0798          //range is on the right part
0799          if(comp(x, lower_key)){
0800             //Check for invalid input range
0801             BOOST_INTRUSIVE_INVARIANT_ASSERT(comp(x, upper_key));
0802             x = NodeTraits::get_right(x);
0803          }
0804          //If the upper_key is less than x, the target
0805          //range is on the left part
0806          else if(comp(upper_key, x)){
0807             y = x;
0808             x = NodeTraits::get_left(x);
0809          }
0810          else{
0811             //x is inside the bounded range(lower_key <= x <= upper_key),
0812             //so we must split lower and upper searches
0813             //
0814             //Sanity check: if lower_key and upper_key are equal, then both left_closed and right_closed can't be false
0815             BOOST_INTRUSIVE_INVARIANT_ASSERT(left_closed || right_closed || comp(lower_key, x) || comp(x, upper_key));
0816             return std::pair<node_ptr,node_ptr>(
0817                left_closed
0818                   //If left_closed, then comp(x, lower_key) is already the lower_bound
0819                   //condition so we save one comparison and go to the next level
0820                   //following traditional lower_bound algo
0821                   ? lower_bound_loop(NodeTraits::get_left(x), x, lower_key, comp)
0822                   //If left-open, comp(x, lower_key) is not the upper_bound algo
0823                   //condition so we must recheck current 'x' node with upper_bound algo
0824                   : upper_bound_loop(x, y, lower_key, comp)
0825             ,
0826                right_closed
0827                   //If right_closed, then comp(upper_key, x) is already the upper_bound
0828                   //condition so we can save one comparison and go to the next level
0829                   //following lower_bound algo
0830                   ? upper_bound_loop(NodeTraits::get_right(x), y, upper_key, comp)
0831                   //If right-open, comp(upper_key, x) is not the lower_bound algo
0832                   //condition so we must recheck current 'x' node with lower_bound algo
0833                   : lower_bound_loop(x, y, upper_key, comp)
0834             );
0835          }
0836       }
0837       return std::pair<node_ptr,node_ptr> (y, y);
0838    }
0839 
0840    //! <b>Requires</b>: "header" must be the header node of a tree.
0841    //!   KeyNodePtrCompare is a function object that induces a strict weak
0842    //!   ordering compatible with the strict weak ordering used to create the
0843    //!   the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs.
0844    //!
0845    //! <b>Effects</b>: Returns the number of elements with a key equivalent to "key"
0846    //!   according to "comp".
0847    //!
0848    //! <b>Complexity</b>: Logarithmic.
0849    //!
0850    //! <b>Throws</b>: If "comp" throws.
0851    template<class KeyType, class KeyNodePtrCompare>
0852    static std::size_t count
0853       (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp)
0854    {
0855       std::pair<node_ptr, node_ptr> ret = equal_range(header, key, comp);
0856       std::size_t n = 0;
0857       while(ret.first != ret.second){
0858          ++n;
0859          ret.first = base_type::next_node(ret.first);
0860       }
0861       return n;
0862    }
0863 
0864    //! <b>Requires</b>: "header" must be the header node of a tree.
0865    //!   KeyNodePtrCompare is a function object that induces a strict weak
0866    //!   ordering compatible with the strict weak ordering used to create the
0867    //!   the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs.
0868    //!
0869    //! <b>Effects</b>: Returns an a pair of node_ptr delimiting a range containing
0870    //!   all elements that are equivalent to "key" according to "comp" or an
0871    //!   empty range that indicates the position where those elements would be
0872    //!   if there are no equivalent elements.
0873    //!
0874    //! <b>Complexity</b>: Logarithmic.
0875    //!
0876    //! <b>Throws</b>: If "comp" throws.
0877    template<class KeyType, class KeyNodePtrCompare>
0878    BOOST_INTRUSIVE_FORCEINLINE static std::pair<node_ptr, node_ptr> equal_range
0879       (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp)
0880    {
0881       return bounded_range(header, key, key, comp, true, true);
0882    }
0883 
0884    //! <b>Requires</b>: "header" must be the header node of a tree.
0885    //!   KeyNodePtrCompare is a function object that induces a strict weak
0886    //!   ordering compatible with the strict weak ordering used to create the
0887    //!   the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs.
0888    //!
0889    //! <b>Effects</b>: Returns an a pair of node_ptr delimiting a range containing
0890    //!   the first element that is equivalent to "key" according to "comp" or an
0891    //!   empty range that indicates the position where that element would be
0892    //!   if there are no equivalent elements.
0893    //!
0894    //! <b>Complexity</b>: Logarithmic.
0895    //!
0896    //! <b>Throws</b>: If "comp" throws.
0897    template<class KeyType, class KeyNodePtrCompare>
0898    static std::pair<node_ptr, node_ptr> lower_bound_range
0899       (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp)
0900    {
0901       node_ptr const lb(lower_bound(header, key, comp));
0902       std::pair<node_ptr, node_ptr> ret_ii(lb, lb);
0903       if(lb != header && !comp(key, lb)){
0904          ret_ii.second = base_type::next_node(ret_ii.second);
0905       }
0906       return ret_ii;
0907    }
0908 
0909    //! <b>Requires</b>: "header" must be the header node of a tree.
0910    //!   KeyNodePtrCompare is a function object that induces a strict weak
0911    //!   ordering compatible with the strict weak ordering used to create the
0912    //!   the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs.
0913    //!
0914    //! <b>Effects</b>: Returns a node_ptr to the first element that is
0915    //!   not less than "key" according to "comp" or "header" if that element does
0916    //!   not exist.
0917    //!
0918    //! <b>Complexity</b>: Logarithmic.
0919    //!
0920    //! <b>Throws</b>: If "comp" throws.
0921    template<class KeyType, class KeyNodePtrCompare>
0922    BOOST_INTRUSIVE_FORCEINLINE static node_ptr lower_bound
0923       (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp)
0924    {
0925       return lower_bound_loop(NodeTraits::get_parent(header), detail::uncast(header), key, comp);
0926    }
0927 
0928    //! <b>Requires</b>: "header" must be the header node of a tree.
0929    //!   KeyNodePtrCompare is a function object that induces a strict weak
0930    //!   ordering compatible with the strict weak ordering used to create the
0931    //!   the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs.
0932    //!
0933    //! <b>Effects</b>: Returns a node_ptr to the first element that is greater
0934    //!   than "key" according to "comp" or "header" if that element does not exist.
0935    //!
0936    //! <b>Complexity</b>: Logarithmic.
0937    //!
0938    //! <b>Throws</b>: If "comp" throws.
0939    template<class KeyType, class KeyNodePtrCompare>
0940    BOOST_INTRUSIVE_FORCEINLINE static node_ptr upper_bound
0941       (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp)
0942    {
0943       return upper_bound_loop(NodeTraits::get_parent(header), detail::uncast(header), key, comp);
0944    }
0945 
0946    //! <b>Requires</b>: "header" must be the header node of a tree.
0947    //!   "commit_data" must have been obtained from a previous call to
0948    //!   "insert_unique_check". No objects should have been inserted or erased
0949    //!   from the set between the "insert_unique_check" that filled "commit_data"
0950    //!   and the call to "insert_commit".
0951    //!
0952    //!
0953    //! <b>Effects</b>: Inserts new_node in the set using the information obtained
0954    //!   from the "commit_data" that a previous "insert_check" filled.
0955    //!
0956    //! <b>Complexity</b>: Constant time.
0957    //!
0958    //! <b>Throws</b>: Nothing.
0959    //!
0960    //! <b>Notes</b>: This function has only sense if a "insert_unique_check" has been
0961    //!   previously executed to fill "commit_data". No value should be inserted or
0962    //!   erased between the "insert_check" and "insert_commit" calls.
0963    BOOST_INTRUSIVE_FORCEINLINE static void insert_unique_commit
0964       (node_ptr header, node_ptr new_value, const insert_commit_data &commit_data) BOOST_NOEXCEPT
0965    {  return insert_commit(header, new_value, commit_data); }
0966 
0967    //! <b>Requires</b>: "header" must be the header node of a tree.
0968    //!   KeyNodePtrCompare is a function object that induces a strict weak
0969    //!   ordering compatible with the strict weak ordering used to create the
0970    //!   the tree. NodePtrCompare compares KeyType with a node_ptr.
0971    //!
0972    //! <b>Effects</b>: Checks if there is an equivalent node to "key" in the
0973    //!   tree according to "comp" and obtains the needed information to realize
0974    //!   a constant-time node insertion if there is no equivalent node.
0975    //!
0976    //! <b>Returns</b>: If there is an equivalent value
0977    //!   returns a pair containing a node_ptr to the already present node
0978    //!   and false. If there is not equivalent key can be inserted returns true
0979    //!   in the returned pair's boolean and fills "commit_data" that is meant to
0980    //!   be used with the "insert_commit" function to achieve a constant-time
0981    //!   insertion function.
0982    //!
0983    //! <b>Complexity</b>: Average complexity is at most logarithmic.
0984    //!
0985    //! <b>Throws</b>: If "comp" throws.
0986    //!
0987    //! <b>Notes</b>: This function is used to improve performance when constructing
0988    //!   a node is expensive and the user does not want to have two equivalent nodes
0989    //!   in the tree: if there is an equivalent value
0990    //!   the constructed object must be discarded. Many times, the part of the
0991    //!   node that is used to impose the order is much cheaper to construct
0992    //!   than the node and this function offers the possibility to use that part
0993    //!   to check if the insertion will be successful.
0994    //!
0995    //!   If the check is successful, the user can construct the node and use
0996    //!   "insert_commit" to insert the node in constant-time. This gives a total
0997    //!   logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)).
0998    //!
0999    //!   "commit_data" remains valid for a subsequent "insert_unique_commit" only
1000    //!   if no more objects are inserted or erased from the set.
1001    template<class KeyType, class KeyNodePtrCompare>
1002    static std::pair<node_ptr, bool> insert_unique_check
1003       (const_node_ptr header, const KeyType &key
1004       ,KeyNodePtrCompare comp, insert_commit_data &commit_data
1005          #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
1006          , std::size_t *pdepth = 0
1007          #endif
1008       )
1009    {
1010       std::size_t depth = 0;
1011       node_ptr h(detail::uncast(header));
1012       node_ptr y(h);
1013       node_ptr x(NodeTraits::get_parent(y));
1014       node_ptr prev = node_ptr();
1015 
1016       //Find the upper bound, cache the previous value and if we should
1017       //store it in the left or right node
1018       bool left_child = true;
1019       while(x){
1020          ++depth;
1021          y = x;
1022          left_child = comp(key, x);
1023          x = left_child ?
1024                NodeTraits::get_left(x) : (prev = y, NodeTraits::get_right(x));
1025       }
1026 
1027       if(pdepth)  *pdepth = depth;
1028 
1029       //Since we've found the upper bound there is no other value with the same key if:
1030       //    - There is no previous node
1031       //    - The previous node is less than the key
1032       const bool not_present = !prev || comp(prev, key);
1033       if(not_present){
1034          commit_data.link_left = left_child;
1035          commit_data.node      = y;
1036       }
1037       return std::pair<node_ptr, bool>(prev, not_present);
1038    }
1039 
1040    //! <b>Requires</b>: "header" must be the header node of a tree.
1041    //!   KeyNodePtrCompare is a function object that induces a strict weak
1042    //!   ordering compatible with the strict weak ordering used to create the
1043    //!   the tree. NodePtrCompare compares KeyType with a node_ptr.
1044    //!   "hint" is node from the "header"'s tree.
1045    //!
1046    //! <b>Effects</b>: Checks if there is an equivalent node to "key" in the
1047    //!   tree according to "comp" using "hint" as a hint to where it should be
1048    //!   inserted and obtains the needed information to realize
1049    //!   a constant-time node insertion if there is no equivalent node.
1050    //!   If "hint" is the upper_bound the function has constant time
1051    //!   complexity (two comparisons in the worst case).
1052    //!
1053    //! <b>Returns</b>: If there is an equivalent value
1054    //!   returns a pair containing a node_ptr to the already present node
1055    //!   and false. If there is not equivalent key can be inserted returns true
1056    //!   in the returned pair's boolean and fills "commit_data" that is meant to
1057    //!   be used with the "insert_commit" function to achieve a constant-time
1058    //!   insertion function.
1059    //!
1060    //! <b>Complexity</b>: Average complexity is at most logarithmic, but it is
1061    //!   amortized constant time if new_node should be inserted immediately before "hint".
1062    //!
1063    //! <b>Throws</b>: If "comp" throws.
1064    //!
1065    //! <b>Notes</b>: This function is used to improve performance when constructing
1066    //!   a node is expensive and the user does not want to have two equivalent nodes
1067    //!   in the tree: if there is an equivalent value
1068    //!   the constructed object must be discarded. Many times, the part of the
1069    //!   node that is used to impose the order is much cheaper to construct
1070    //!   than the node and this function offers the possibility to use that part
1071    //!   to check if the insertion will be successful.
1072    //!
1073    //!   If the check is successful, the user can construct the node and use
1074    //!   "insert_commit" to insert the node in constant-time. This gives a total
1075    //!   logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)).
1076    //!
1077    //!   "commit_data" remains valid for a subsequent "insert_unique_commit" only
1078    //!   if no more objects are inserted or erased from the set.
1079    template<class KeyType, class KeyNodePtrCompare>
1080    static std::pair<node_ptr, bool> insert_unique_check
1081       (const_node_ptr header, node_ptr hint, const KeyType &key
1082       ,KeyNodePtrCompare comp, insert_commit_data &commit_data
1083          #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
1084          , std::size_t *pdepth = 0
1085          #endif
1086       )
1087    {
1088       //hint must be bigger than the key
1089       if(hint == header || comp(key, hint)){
1090          node_ptr prev(hint);
1091          //Previous value should be less than the key
1092          if(hint == begin_node(header) || comp((prev = base_type::prev_node(hint)), key)){
1093             commit_data.link_left = unique(header) || !NodeTraits::get_left(hint);
1094             commit_data.node      = commit_data.link_left ? hint : prev;
1095             if(pdepth){
1096                *pdepth = commit_data.node == header ? 0 : depth(commit_data.node) + 1;
1097             }
1098             return std::pair<node_ptr, bool>(node_ptr(), true);
1099          }
1100       }
1101       //Hint was wrong, use hintless insertion
1102       return insert_unique_check(header, key, comp, commit_data, pdepth);
1103    }
1104 
1105    //! <b>Requires</b>: "header" must be the header node of a tree.
1106    //!   NodePtrCompare is a function object that induces a strict weak
1107    //!   ordering compatible with the strict weak ordering used to create the
1108    //!   the tree. NodePtrCompare compares two node_ptrs. "hint" is node from
1109    //!   the "header"'s tree.
1110    //!
1111    //! <b>Effects</b>: Inserts new_node into the tree, using "hint" as a hint to
1112    //!   where it will be inserted. If "hint" is the upper_bound
1113    //!   the insertion takes constant time (two comparisons in the worst case).
1114    //!
1115    //! <b>Complexity</b>: Logarithmic in general, but it is amortized
1116    //!   constant time if new_node is inserted immediately before "hint".
1117    //!
1118    //! <b>Throws</b>: If "comp" throws.
1119    template<class NodePtrCompare>
1120    static node_ptr insert_equal
1121       (node_ptr h, node_ptr hint, node_ptr new_node, NodePtrCompare comp
1122          #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
1123          , std::size_t *pdepth = 0
1124          #endif
1125       )
1126    {
1127       insert_commit_data commit_data;
1128       insert_equal_check(h, hint, new_node, comp, commit_data, pdepth);
1129       insert_commit(h, new_node, commit_data);
1130       return new_node;
1131    }
1132 
1133    //! <b>Requires</b>: "h" must be the header node of a tree.
1134    //!   NodePtrCompare is a function object that induces a strict weak
1135    //!   ordering compatible with the strict weak ordering used to create the
1136    //!   the tree. NodePtrCompare compares two node_ptrs.
1137    //!
1138    //! <b>Effects</b>: Inserts new_node into the tree before the upper bound
1139    //!   according to "comp".
1140    //!
1141    //! <b>Complexity</b>: Average complexity for insert element is at
1142    //!   most logarithmic.
1143    //!
1144    //! <b>Throws</b>: If "comp" throws.
1145    template<class NodePtrCompare>
1146    static node_ptr insert_equal_upper_bound
1147       (node_ptr h, node_ptr new_node, NodePtrCompare comp
1148          #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
1149          , std::size_t *pdepth = 0
1150          #endif
1151       )
1152    {
1153       insert_commit_data commit_data;
1154       insert_equal_upper_bound_check(h, new_node, comp, commit_data, pdepth);
1155       insert_commit(h, new_node, commit_data);
1156       return new_node;
1157    }
1158 
1159    //! <b>Requires</b>: "h" must be the header node of a tree.
1160    //!   NodePtrCompare is a function object that induces a strict weak
1161    //!   ordering compatible with the strict weak ordering used to create the
1162    //!   the tree. NodePtrCompare compares two node_ptrs.
1163    //!
1164    //! <b>Effects</b>: Inserts new_node into the tree before the lower bound
1165    //!   according to "comp".
1166    //!
1167    //! <b>Complexity</b>: Average complexity for insert element is at
1168    //!   most logarithmic.
1169    //!
1170    //! <b>Throws</b>: If "comp" throws.
1171    template<class NodePtrCompare>
1172    static node_ptr insert_equal_lower_bound
1173       (node_ptr h, node_ptr new_node, NodePtrCompare comp
1174          #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
1175          , std::size_t *pdepth = 0
1176          #endif
1177       )
1178    {
1179       insert_commit_data commit_data;
1180       insert_equal_lower_bound_check(h, new_node, comp, commit_data, pdepth);
1181       insert_commit(h, new_node, commit_data);
1182       return new_node;
1183    }
1184 
1185    //! <b>Requires</b>: "header" must be the header node of a tree.
1186    //!   "pos" must be a valid iterator or header (end) node.
1187    //!   "pos" must be an iterator pointing to the successor to "new_node"
1188    //!   once inserted according to the order of already inserted nodes. This function does not
1189    //!   check "pos" and this precondition must be guaranteed by the caller.
1190    //!
1191    //! <b>Effects</b>: Inserts new_node into the tree before "pos".
1192    //!
1193    //! <b>Complexity</b>: Constant-time.
1194    //!
1195    //! <b>Throws</b>: Nothing.
1196    //!
1197    //! <b>Note</b>: If "pos" is not the successor of the newly inserted "new_node"
1198    //! tree invariants might be broken.
1199    static node_ptr insert_before
1200       (node_ptr header, node_ptr pos, node_ptr new_node
1201          #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
1202          , std::size_t *pdepth = 0
1203          #endif
1204       ) BOOST_NOEXCEPT
1205    {
1206       insert_commit_data commit_data;
1207       insert_before_check(header, pos, commit_data, pdepth);
1208       insert_commit(header, new_node, commit_data);
1209       return new_node;
1210    }
1211 
1212    //! <b>Requires</b>: "header" must be the header node of a tree.
1213    //!   "new_node" must be, according to the used ordering no less than the
1214    //!   greatest inserted key.
1215    //!
1216    //! <b>Effects</b>: Inserts new_node into the tree before "pos".
1217    //!
1218    //! <b>Complexity</b>: Constant-time.
1219    //!
1220    //! <b>Throws</b>: Nothing.
1221    //!
1222    //! <b>Note</b>: If "new_node" is less than the greatest inserted key
1223    //! tree invariants are broken. This function is slightly faster than
1224    //! using "insert_before".
1225    static void push_back
1226       (node_ptr header, node_ptr new_node
1227          #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
1228          , std::size_t *pdepth = 0
1229          #endif
1230       ) BOOST_NOEXCEPT
1231    {
1232       insert_commit_data commit_data;
1233       push_back_check(header, commit_data, pdepth);
1234       insert_commit(header, new_node, commit_data);
1235    }
1236 
1237    //! <b>Requires</b>: "header" must be the header node of a tree.
1238    //!   "new_node" must be, according to the used ordering, no greater than the
1239    //!   lowest inserted key.
1240    //!
1241    //! <b>Effects</b>: Inserts new_node into the tree before "pos".
1242    //!
1243    //! <b>Complexity</b>: Constant-time.
1244    //!
1245    //! <b>Throws</b>: Nothing.
1246    //!
1247    //! <b>Note</b>: If "new_node" is greater than the lowest inserted key
1248    //! tree invariants are broken. This function is slightly faster than
1249    //! using "insert_before".
1250    static void push_front
1251       (node_ptr header, node_ptr new_node
1252          #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
1253          , std::size_t *pdepth = 0
1254          #endif
1255       ) BOOST_NOEXCEPT
1256    {
1257       insert_commit_data commit_data;
1258       push_front_check(header, commit_data, pdepth);
1259       insert_commit(header, new_node, commit_data);
1260    }
1261 
1262    //! <b>Requires</b>: 'n' can't be a header node.
1263    //!
1264    //! <b>Effects</b>: Calculates the depth of a node: the depth of a
1265    //! node is the length (number of edges) of the path from the root
1266    //! to that node. (The root node is at depth 0.)
1267    //!
1268    //! <b>Complexity</b>: Logarithmic to the number of nodes in the tree.
1269    //!
1270    //! <b>Throws</b>: Nothing.
1271    static std::size_t depth(const_node_ptr n) BOOST_NOEXCEPT
1272    {
1273       std::size_t depth = 0;
1274       node_ptr p_parent;
1275       while(n != NodeTraits::get_parent(p_parent = NodeTraits::get_parent(n))){
1276          ++depth;
1277          n = p_parent;
1278       }
1279       return depth;
1280    }
1281 
1282    //! <b>Requires</b>: "cloner" must be a function
1283    //!   object taking a node_ptr and returning a new cloned node of it. "disposer" must
1284    //!   take a node_ptr and shouldn't throw.
1285    //!
1286    //! <b>Effects</b>: First empties target tree calling
1287    //!   <tt>void disposer::operator()(node_ptr)</tt> for every node of the tree
1288    //!    except the header.
1289    //!
1290    //!   Then, duplicates the entire tree pointed by "source_header" cloning each
1291    //!   source node with <tt>node_ptr Cloner::operator()(node_ptr)</tt> to obtain
1292    //!   the nodes of the target tree. If "cloner" throws, the cloned target nodes
1293    //!   are disposed using <tt>void disposer(node_ptr )</tt>.
1294    //!
1295    //! <b>Complexity</b>: Linear to the number of element of the source tree plus the
1296    //!   number of elements of tree target tree when calling this function.
1297    //!
1298    //! <b>Throws</b>: If cloner functor throws. If this happens target nodes are disposed.
1299    template <class Cloner, class Disposer>
1300    static void clone
1301       (const_node_ptr source_header, node_ptr target_header, Cloner cloner, Disposer disposer)
1302    {
1303       if(!unique(target_header)){
1304          clear_and_dispose(target_header, disposer);
1305       }
1306 
1307       node_ptr leftmost, rightmost;
1308       node_ptr new_root = clone_subtree
1309          (source_header, target_header, cloner, disposer, leftmost, rightmost);
1310 
1311       //Now update header node
1312       NodeTraits::set_parent(target_header, new_root);
1313       NodeTraits::set_left  (target_header, leftmost);
1314       NodeTraits::set_right (target_header, rightmost);
1315    }
1316 
1317    //! <b>Requires</b>: header must be the header of a tree, z a node
1318    //!    of that tree and z != header.
1319    //!
1320    //! <b>Effects</b>: Erases node "z" from the tree with header "header".
1321    //!
1322    //! <b>Complexity</b>: Amortized constant time.
1323    //!
1324    //! <b>Throws</b>: Nothing.
1325    BOOST_INTRUSIVE_FORCEINLINE static void erase(node_ptr header, node_ptr z) BOOST_NOEXCEPT
1326    {
1327       data_for_rebalance ignored;
1328       erase(header, z, ignored);
1329    }
1330 
1331    //! <b>Requires</b>: header1 and header2 must be the headers of trees tree1 and tree2
1332    //!   respectively, z a non-header node of tree1. NodePtrCompare is the comparison
1333    //!   function of tree1..
1334    //!
1335    //! <b>Effects</b>: Transfers node "z" from tree1 to tree2 if tree1 does not contain
1336    //!   a node that is equivalent to z.
1337    //!
1338    //! <b>Returns</b>: True if the node was trasferred, false otherwise.
1339    //!
1340    //! <b>Complexity</b>: Logarithmic.
1341    //!
1342    //! <b>Throws</b>: If the comparison throws.
1343    template<class NodePtrCompare>
1344    BOOST_INTRUSIVE_FORCEINLINE static bool transfer_unique
1345       (node_ptr header1, NodePtrCompare comp, node_ptr header2, node_ptr z)
1346    {
1347       data_for_rebalance ignored;
1348       return transfer_unique(header1, comp, header2, z, ignored);
1349    }
1350 
1351    //! <b>Requires</b>: header1 and header2 must be the headers of trees tree1 and tree2
1352    //!   respectively, z a non-header node of tree1. NodePtrCompare is the comparison
1353    //!   function of tree1..
1354    //!
1355    //! <b>Effects</b>: Transfers node "z" from tree1 to tree2.
1356    //!
1357    //! <b>Complexity</b>: Logarithmic.
1358    //!
1359    //! <b>Throws</b>: If the comparison throws.
1360    template<class NodePtrCompare>
1361    BOOST_INTRUSIVE_FORCEINLINE static void transfer_equal
1362       (node_ptr header1, NodePtrCompare comp, node_ptr header2, node_ptr z)
1363    {
1364       data_for_rebalance ignored;
1365       transfer_equal(header1, comp, header2, z, ignored);
1366    }
1367 
1368    //! <b>Requires</b>: 'n' is a tree node but not the header.
1369    //!
1370    //! <b>Effects</b>: Unlinks the node and rebalances the tree.
1371    //!
1372    //! <b>Complexity</b>: Average complexity is constant time.
1373    //!
1374    //! <b>Throws</b>: Nothing.
1375    static void unlink(node_ptr n) BOOST_NOEXCEPT
1376    {
1377       node_ptr x = NodeTraits::get_parent(n);
1378       if(x){
1379          while(!base_type::is_header(x))
1380             x = NodeTraits::get_parent(x);
1381          erase(x, n);
1382       }
1383    }
1384 
1385    //! <b>Requires</b>: header must be the header of a tree.
1386    //!
1387    //! <b>Effects</b>: Rebalances the tree.
1388    //!
1389    //! <b>Throws</b>: Nothing.
1390    //!
1391    //! <b>Complexity</b>: Linear.
1392    static void rebalance(node_ptr header) BOOST_NOEXCEPT
1393    {
1394       node_ptr root = NodeTraits::get_parent(header);
1395       if(root){
1396          rebalance_subtree(root);
1397       }
1398    }
1399 
1400    //! <b>Requires</b>: old_root is a node of a tree. It shall not be null.
1401    //!
1402    //! <b>Effects</b>: Rebalances the subtree rooted at old_root.
1403    //!
1404    //! <b>Returns</b>: The new root of the subtree.
1405    //!
1406    //! <b>Throws</b>: Nothing.
1407    //!
1408    //! <b>Complexity</b>: Linear.
1409    static node_ptr rebalance_subtree(node_ptr old_root) BOOST_NOEXCEPT
1410    {
1411       //Taken from:
1412       //"Tree rebalancing in optimal time and space"
1413       //Quentin F. Stout and Bette L. Warren
1414 
1415       //To avoid irregularities in the algorithm (old_root can be a
1416       //left or right child or even the root of the tree) just put the
1417       //root as the right child of its parent. Before doing this backup
1418       //information to restore the original relationship after
1419       //the algorithm is applied.
1420       node_ptr super_root = NodeTraits::get_parent(old_root);
1421       BOOST_INTRUSIVE_INVARIANT_ASSERT(super_root);
1422 
1423       //Get root info
1424       node_ptr super_root_right_backup = NodeTraits::get_right(super_root);
1425       bool super_root_is_header = NodeTraits::get_parent(super_root) == old_root;
1426       bool old_root_is_right  = is_right_child(old_root);
1427       NodeTraits::set_right(super_root, old_root);
1428 
1429       std::size_t size;
1430       subtree_to_vine(super_root, size);
1431       vine_to_subtree(super_root, size);
1432       node_ptr new_root = NodeTraits::get_right(super_root);
1433 
1434       //Recover root
1435       if(super_root_is_header){
1436          NodeTraits::set_right(super_root, super_root_right_backup);
1437          NodeTraits::set_parent(super_root, new_root);
1438       }
1439       else if(old_root_is_right){
1440          NodeTraits::set_right(super_root, new_root);
1441       }
1442       else{
1443          NodeTraits::set_right(super_root, super_root_right_backup);
1444          NodeTraits::set_left(super_root, new_root);
1445       }
1446       return new_root;
1447    }
1448 
1449    //! <b>Effects</b>: Asserts the integrity of the container with additional checks provided by the user.
1450    //!
1451    //! <b>Requires</b>: header must be the header of a tree.
1452    //!
1453    //! <b>Complexity</b>: Linear time.
1454    //!
1455    //! <b>Note</b>: The method might not have effect when asserts are turned off (e.g., with NDEBUG).
1456    //!   Experimental function, interface might change in future versions.
1457    template<class Checker>
1458    static void check(const_node_ptr header, Checker checker, typename Checker::return_type& checker_return)
1459    {
1460       const_node_ptr root_node_ptr = NodeTraits::get_parent(header);
1461       if (!root_node_ptr){
1462          // check left&right header pointers
1463          BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_left(header) == header);
1464          BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_right(header) == header);
1465       }
1466       else{
1467          // check parent pointer of root node
1468          BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_parent(root_node_ptr) == header);
1469          // check subtree from root
1470          check_subtree(root_node_ptr, checker, checker_return);
1471          // check left&right header pointers
1472          const_node_ptr p = root_node_ptr;
1473          while (NodeTraits::get_left(p)) { p = NodeTraits::get_left(p); }
1474          BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_left(header) == p);
1475          p = root_node_ptr;
1476          while (NodeTraits::get_right(p)) { p = NodeTraits::get_right(p); }
1477          BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_right(header) == p);
1478       }
1479    }
1480 
1481    protected:
1482 
1483    template<class NodePtrCompare>
1484    static bool transfer_unique
1485       (node_ptr header1, NodePtrCompare comp, node_ptr header2, node_ptr z, data_for_rebalance &info)
1486    {
1487       insert_commit_data commit_data;
1488       bool const transferable = insert_unique_check(header1, z, comp, commit_data).second;
1489       if(transferable){
1490          erase(header2, z, info);
1491          insert_commit(header1, z, commit_data);
1492       }
1493       return transferable;
1494    }
1495 
1496    template<class NodePtrCompare>
1497    static void transfer_equal
1498       (node_ptr header1, NodePtrCompare comp, node_ptr header2, node_ptr z, data_for_rebalance &info)
1499    {
1500       insert_commit_data commit_data;
1501       insert_equal_upper_bound_check(header1, z, comp, commit_data);
1502       erase(header2, z, info);
1503       insert_commit(header1, z, commit_data);
1504    }
1505 
1506    static void erase(node_ptr header, node_ptr z, data_for_rebalance &info)
1507    {
1508       node_ptr y(z);
1509       node_ptr x;
1510       const node_ptr z_left(NodeTraits::get_left(z));
1511       const node_ptr z_right(NodeTraits::get_right(z));
1512 
1513       if(!z_left){
1514          x = z_right;    // x might be null.
1515       }
1516       else if(!z_right){ // z has exactly one non-null child. y == z.
1517          x = z_left;       // x is not null.
1518          BOOST_ASSERT(x);
1519       }
1520       else{ //make y != z
1521          // y = find z's successor
1522          y = base_type::minimum(z_right);
1523          x = NodeTraits::get_right(y);     // x might be null.
1524       }
1525 
1526       node_ptr x_parent;
1527       const node_ptr z_parent(NodeTraits::get_parent(z));
1528       const bool z_is_leftchild(NodeTraits::get_left(z_parent) == z);
1529 
1530       if(y != z){ //has two children and y is the minimum of z
1531          //y is z's successor and it has a null left child.
1532          //x is the right child of y (it can be null)
1533          //Relink y in place of z and link x with y's old parent
1534          NodeTraits::set_parent(z_left, y);
1535          NodeTraits::set_left(y, z_left);
1536          if(y != z_right){
1537             //Link y with the right tree of z
1538             NodeTraits::set_right(y, z_right);
1539             NodeTraits::set_parent(z_right, y);
1540             //Link x with y's old parent (y must be a left child)
1541             x_parent = NodeTraits::get_parent(y);
1542             BOOST_ASSERT(NodeTraits::get_left(x_parent) == y);
1543             if(x)
1544                NodeTraits::set_parent(x, x_parent);
1545             //Since y was the successor and not the right child of z, it must be a left child
1546             NodeTraits::set_left(x_parent, x);
1547          }
1548          else{ //y was the right child of y so no need to fix x's position
1549             x_parent = y;
1550          }
1551          NodeTraits::set_parent(y, z_parent);
1552          this_type::set_child(header, y, z_parent, z_is_leftchild);
1553       }
1554       else {  // z has zero or one child, x is one child (it can be null)
1555          //Just link x to z's parent
1556          x_parent = z_parent;
1557          if(x)
1558             NodeTraits::set_parent(x, z_parent);
1559          this_type::set_child(header, x, z_parent, z_is_leftchild);
1560 
1561          //Now update leftmost/rightmost in case z was one of them
1562          if(NodeTraits::get_left(header) == z){
1563             //z_left must be null because z is the leftmost
1564             BOOST_ASSERT(!z_left);
1565             NodeTraits::set_left(header, !z_right ?
1566                z_parent :  // makes leftmost == header if z == root
1567                base_type::minimum(z_right));
1568          }
1569          if(NodeTraits::get_right(header) == z){
1570             //z_right must be null because z is the rightmost
1571             BOOST_ASSERT(!z_right);
1572             NodeTraits::set_right(header, !z_left ?
1573                z_parent :  // makes rightmost == header if z == root
1574                base_type::maximum(z_left));
1575          }
1576       }
1577 
1578       //If z had 0/1 child, y == z and one of its children (and maybe null)
1579       //If z had 2 children, y is the successor of z and x is the right child of y
1580       info.x = x;
1581       info.y = y;
1582       //If z had 0/1 child, x_parent is the new parent of the old right child of y (z's successor)
1583       //If z had 2 children, x_parent is the new parent of y (z_parent)
1584       BOOST_ASSERT(!x || NodeTraits::get_parent(x) == x_parent);
1585       info.x_parent = x_parent;
1586    }
1587 
1588    //! <b>Requires</b>: 'subtree' is a node of the tree but it's not the header.
1589    //!
1590    //! <b>Effects</b>: Returns the number of nodes of the subtree.
1591    //!
1592    //! <b>Complexity</b>: Linear time.
1593    //!
1594    //! <b>Throws</b>: Nothing.
1595    static std::size_t subtree_size(const_node_ptr subtree) BOOST_NOEXCEPT
1596    {
1597       std::size_t count = 0;
1598       if (subtree){
1599          node_ptr n = detail::uncast(subtree);
1600          node_ptr m = NodeTraits::get_left(n);
1601          while(m){
1602             n = m;
1603             m = NodeTraits::get_left(n);
1604          }
1605 
1606          while(1){
1607             ++count;
1608             node_ptr n_right(NodeTraits::get_right(n));
1609             if(n_right){
1610                n = n_right;
1611                m = NodeTraits::get_left(n);
1612                while(m){
1613                   n = m;
1614                   m = NodeTraits::get_left(n);
1615                }
1616             }
1617             else {
1618                do{
1619                   if (n == subtree){
1620                      return count;
1621                   }
1622                   m = n;
1623                   n = NodeTraits::get_parent(n);
1624                }while(NodeTraits::get_left(n) != m);
1625             }
1626          }
1627       }
1628       return count;
1629    }
1630 
1631    //! <b>Requires</b>: p is a node of a tree.
1632    //!
1633    //! <b>Effects</b>: Returns true if p is a left child.
1634    //!
1635    //! <b>Complexity</b>: Constant.
1636    //!
1637    //! <b>Throws</b>: Nothing.
1638    BOOST_INTRUSIVE_FORCEINLINE static bool is_left_child(node_ptr p) BOOST_NOEXCEPT
1639    {  return NodeTraits::get_left(NodeTraits::get_parent(p)) == p;  }
1640 
1641    //! <b>Requires</b>: p is a node of a tree.
1642    //!
1643    //! <b>Effects</b>: Returns true if p is a right child.
1644    //!
1645    //! <b>Complexity</b>: Constant.
1646    //!
1647    //! <b>Throws</b>: Nothing.
1648    BOOST_INTRUSIVE_FORCEINLINE static bool is_right_child(node_ptr p) BOOST_NOEXCEPT
1649    {  return NodeTraits::get_right(NodeTraits::get_parent(p)) == p;  }
1650 
1651    static void insert_before_check
1652       (node_ptr header, node_ptr pos
1653       , insert_commit_data &commit_data
1654          #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
1655          , std::size_t *pdepth = 0
1656          #endif
1657       )
1658    {
1659       node_ptr prev(pos);
1660       if(pos != NodeTraits::get_left(header))
1661          prev = base_type::prev_node(pos);
1662       bool link_left = unique(header) || !NodeTraits::get_left(pos);
1663       commit_data.link_left = link_left;
1664       commit_data.node = link_left ? pos : prev;
1665       if(pdepth){
1666          *pdepth = commit_data.node == header ? 0 : depth(commit_data.node) + 1;
1667       }
1668    }
1669 
1670    static void push_back_check
1671       (node_ptr header, insert_commit_data &commit_data
1672          #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
1673          , std::size_t *pdepth = 0
1674          #endif
1675       ) BOOST_NOEXCEPT
1676    {
1677       node_ptr prev(NodeTraits::get_right(header));
1678       if(pdepth){
1679          *pdepth = prev == header ? 0 : depth(prev) + 1;
1680       }
1681       commit_data.link_left = false;
1682       commit_data.node = prev;
1683    }
1684 
1685    static void push_front_check
1686       (node_ptr header, insert_commit_data &commit_data
1687          #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
1688          , std::size_t *pdepth = 0
1689          #endif
1690       ) BOOST_NOEXCEPT
1691    {
1692       node_ptr pos(NodeTraits::get_left(header));
1693       if(pdepth){
1694          *pdepth = pos == header ? 0 : depth(pos) + 1;
1695       }
1696       commit_data.link_left = true;
1697       commit_data.node = pos;
1698    }
1699 
1700    template<class NodePtrCompare>
1701    static void insert_equal_check
1702       (node_ptr header, node_ptr hint, node_ptr new_node, NodePtrCompare comp
1703       , insert_commit_data &commit_data
1704       /// @cond
1705       , std::size_t *pdepth = 0
1706       /// @endcond
1707       )
1708    {
1709       if(hint == header || !comp(hint, new_node)){
1710          node_ptr prev(hint);
1711          if(hint == NodeTraits::get_left(header) ||
1712             !comp(new_node, (prev = base_type::prev_node(hint)))){
1713             bool link_left = unique(header) || !NodeTraits::get_left(hint);
1714             commit_data.link_left = link_left;
1715             commit_data.node = link_left ? hint : prev;
1716             if(pdepth){
1717                *pdepth = commit_data.node == header ? 0 : depth(commit_data.node) + 1;
1718             }
1719          }
1720          else{
1721             insert_equal_upper_bound_check(header, new_node, comp, commit_data, pdepth);
1722          }
1723       }
1724       else{
1725          insert_equal_lower_bound_check(header, new_node, comp, commit_data, pdepth);
1726       }
1727    }
1728 
1729    template<class NodePtrCompare>
1730    static void insert_equal_upper_bound_check
1731       (node_ptr h, node_ptr new_node, NodePtrCompare comp, insert_commit_data & commit_data, std::size_t *pdepth = 0)
1732    {
1733       std::size_t depth = 0;
1734       node_ptr y(h);
1735       node_ptr x(NodeTraits::get_parent(y));
1736 
1737       while(x){
1738          ++depth;
1739          y = x;
1740          x = comp(new_node, x) ?
1741                NodeTraits::get_left(x) : NodeTraits::get_right(x);
1742       }
1743       if(pdepth)  *pdepth = depth;
1744       commit_data.link_left = (y == h) || comp(new_node, y);
1745       commit_data.node = y;
1746    }
1747 
1748    template<class NodePtrCompare>
1749    static void insert_equal_lower_bound_check
1750       (node_ptr h, node_ptr new_node, NodePtrCompare comp, insert_commit_data & commit_data, std::size_t *pdepth = 0)
1751    {
1752       std::size_t depth = 0;
1753       node_ptr y(h);
1754       node_ptr x(NodeTraits::get_parent(y));
1755 
1756       while(x){
1757          ++depth;
1758          y = x;
1759          x = !comp(x, new_node) ?
1760                NodeTraits::get_left(x) : NodeTraits::get_right(x);
1761       }
1762       if(pdepth)  *pdepth = depth;
1763       commit_data.link_left = (y == h) || !comp(y, new_node);
1764       commit_data.node = y;
1765    }
1766 
1767    static void insert_commit
1768       (node_ptr header, node_ptr new_node, const insert_commit_data &commit_data) BOOST_NOEXCEPT
1769    {
1770       //Check if commit_data has not been initialized by a insert_unique_check call.
1771       BOOST_INTRUSIVE_INVARIANT_ASSERT(commit_data.node != node_ptr());
1772       node_ptr parent_node(commit_data.node);
1773       if(parent_node == header){
1774          NodeTraits::set_parent(header, new_node);
1775          NodeTraits::set_right(header, new_node);
1776          NodeTraits::set_left(header, new_node);
1777       }
1778       else if(commit_data.link_left){
1779          NodeTraits::set_left(parent_node, new_node);
1780          if(parent_node == NodeTraits::get_left(header))
1781              NodeTraits::set_left(header, new_node);
1782       }
1783       else{
1784          NodeTraits::set_right(parent_node, new_node);
1785          if(parent_node == NodeTraits::get_right(header))
1786              NodeTraits::set_right(header, new_node);
1787       }
1788       NodeTraits::set_parent(new_node, parent_node);
1789       NodeTraits::set_right(new_node, node_ptr());
1790       NodeTraits::set_left(new_node, node_ptr());
1791    }
1792 
1793    //Fix header and own's parent data when replacing x with own, providing own's old data with parent
1794    static void set_child(node_ptr header, node_ptr new_child, node_ptr new_parent, const bool link_left) BOOST_NOEXCEPT
1795    {
1796       if(new_parent == header)
1797          NodeTraits::set_parent(header, new_child);
1798       else if(link_left)
1799          NodeTraits::set_left(new_parent, new_child);
1800       else
1801          NodeTraits::set_right(new_parent, new_child);
1802    }
1803 
1804    // rotate p to left (no header and p's parent fixup)
1805    static void rotate_left_no_parent_fix(node_ptr p, node_ptr p_right) BOOST_NOEXCEPT
1806    {
1807       node_ptr p_right_left(NodeTraits::get_left(p_right));
1808       NodeTraits::set_right(p, p_right_left);
1809       if(p_right_left){
1810          NodeTraits::set_parent(p_right_left, p);
1811       }
1812       NodeTraits::set_left(p_right, p);
1813       NodeTraits::set_parent(p, p_right);
1814    }
1815 
1816    // rotate p to left (with header and p's parent fixup)
1817    static void rotate_left(node_ptr p, node_ptr p_right, node_ptr p_parent, node_ptr header) BOOST_NOEXCEPT
1818    {
1819       const bool p_was_left(NodeTraits::get_left(p_parent) == p);
1820       rotate_left_no_parent_fix(p, p_right);
1821       NodeTraits::set_parent(p_right, p_parent);
1822       set_child(header, p_right, p_parent, p_was_left);
1823    }
1824 
1825    // rotate p to right (no header and p's parent fixup)
1826    static void rotate_right_no_parent_fix(node_ptr p, node_ptr p_left) BOOST_NOEXCEPT
1827    {
1828       node_ptr p_left_right(NodeTraits::get_right(p_left));
1829       NodeTraits::set_left(p, p_left_right);
1830       if(p_left_right){
1831          NodeTraits::set_parent(p_left_right, p);
1832       }
1833       NodeTraits::set_right(p_left, p);
1834       NodeTraits::set_parent(p, p_left);
1835    }
1836 
1837    // rotate p to right (with header and p's parent fixup)
1838    static void rotate_right(node_ptr p, node_ptr p_left, node_ptr p_parent, node_ptr header) BOOST_NOEXCEPT
1839    {
1840       const bool p_was_left(NodeTraits::get_left(p_parent) == p);
1841       rotate_right_no_parent_fix(p, p_left);
1842       NodeTraits::set_parent(p_left, p_parent);
1843       set_child(header, p_left, p_parent, p_was_left);
1844    }
1845 
1846    private:
1847 
1848    static void subtree_to_vine(node_ptr vine_tail, std::size_t &size) BOOST_NOEXCEPT
1849    {
1850       //Inspired by LibAVL:
1851       //It uses a clever optimization for trees with parent pointers.
1852       //No parent pointer is updated when transforming a tree to a vine as
1853       //most of them will be overriten during compression rotations.
1854       //A final pass must be made after the rebalancing to updated those
1855       //pointers not updated by tree_to_vine + compression calls
1856       std::size_t len = 0;
1857       node_ptr remainder = NodeTraits::get_right(vine_tail);
1858       while(remainder){
1859          node_ptr tempptr = NodeTraits::get_left(remainder);
1860          if(!tempptr){   //move vine-tail down one
1861             vine_tail = remainder;
1862             remainder = NodeTraits::get_right(remainder);
1863             ++len;
1864          }
1865          else{ //rotate
1866             NodeTraits::set_left(remainder, NodeTraits::get_right(tempptr));
1867             NodeTraits::set_right(tempptr, remainder);
1868             remainder = tempptr;
1869             NodeTraits::set_right(vine_tail, tempptr);
1870          }
1871       }
1872       size = len;
1873    }
1874 
1875    static void compress_subtree(node_ptr scanner, std::size_t count) BOOST_NOEXCEPT
1876    {
1877       while(count--){   //compress "count" spine nodes in the tree with pseudo-root scanner
1878          node_ptr child = NodeTraits::get_right(scanner);
1879          node_ptr child_right = NodeTraits::get_right(child);
1880          NodeTraits::set_right(scanner, child_right);
1881          //Avoid setting the parent of child_right
1882          scanner = child_right;
1883          node_ptr scanner_left = NodeTraits::get_left(scanner);
1884          NodeTraits::set_right(child, scanner_left);
1885          if(scanner_left)
1886             NodeTraits::set_parent(scanner_left, child);
1887          NodeTraits::set_left(scanner, child);
1888          NodeTraits::set_parent(child, scanner);
1889       }
1890    }
1891 
1892    static void vine_to_subtree(node_ptr super_root, std::size_t count) BOOST_NOEXCEPT
1893    {
1894       const std::size_t one_szt = 1u;
1895       std::size_t leaf_nodes = count + one_szt - std::size_t(one_szt << detail::floor_log2(count + one_szt));
1896       compress_subtree(super_root, leaf_nodes);  //create deepest leaves
1897       std::size_t vine_nodes = count - leaf_nodes;
1898       while(vine_nodes > 1){
1899          vine_nodes /= 2;
1900          compress_subtree(super_root, vine_nodes);
1901       }
1902 
1903       //Update parents of nodes still in the in the original vine line
1904       //as those have not been updated by subtree_to_vine or compress_subtree
1905       for ( node_ptr q = super_root, p = NodeTraits::get_right(super_root)
1906           ; p
1907           ; q = p, p = NodeTraits::get_right(p)){
1908          NodeTraits::set_parent(p, q);
1909       }
1910    }
1911 
1912    //! <b>Requires</b>: "n" must be a node inserted in a tree.
1913    //!
1914    //! <b>Effects</b>: Returns a pointer to the header node of the tree.
1915    //!
1916    //! <b>Complexity</b>: Logarithmic.
1917    //!
1918    //! <b>Throws</b>: Nothing.
1919    static node_ptr get_root(node_ptr n) BOOST_NOEXCEPT
1920    {
1921       BOOST_INTRUSIVE_INVARIANT_ASSERT((!inited(n)));
1922       node_ptr x = NodeTraits::get_parent(n);
1923       if(x){
1924          while(!base_type::is_header(x)){
1925             x = NodeTraits::get_parent(x);
1926          }
1927          return x;
1928       }
1929       else{
1930          return n;
1931       }
1932    }
1933 
1934    template <class Cloner, class Disposer>
1935    static node_ptr clone_subtree
1936       (const_node_ptr source_parent, node_ptr target_parent
1937       , Cloner cloner, Disposer disposer
1938       , node_ptr &leftmost_out, node_ptr &rightmost_out
1939       )
1940    {
1941       node_ptr target_sub_root = target_parent;
1942       node_ptr source_root = NodeTraits::get_parent(source_parent);
1943       if(!source_root){
1944          leftmost_out = rightmost_out = source_root;
1945       }
1946       else{
1947          //We'll calculate leftmost and rightmost nodes while iterating
1948          node_ptr current = source_root;
1949          node_ptr insertion_point = target_sub_root = cloner(current);
1950 
1951          //We'll calculate leftmost and rightmost nodes while iterating
1952          node_ptr leftmost  = target_sub_root;
1953          node_ptr rightmost = target_sub_root;
1954 
1955          //First set the subroot
1956          NodeTraits::set_left(target_sub_root, node_ptr());
1957          NodeTraits::set_right(target_sub_root, node_ptr());
1958          NodeTraits::set_parent(target_sub_root, target_parent);
1959 
1960          dispose_subtree_disposer<Disposer> rollback(disposer, target_sub_root);
1961          while(true) {
1962             //First clone left nodes
1963             if( NodeTraits::get_left(current) &&
1964                !NodeTraits::get_left(insertion_point)) {
1965                current = NodeTraits::get_left(current);
1966                node_ptr temp = insertion_point;
1967                //Clone and mark as leaf
1968                insertion_point = cloner(current);
1969                NodeTraits::set_left  (insertion_point, node_ptr());
1970                NodeTraits::set_right (insertion_point, node_ptr());
1971                //Insert left
1972                NodeTraits::set_parent(insertion_point, temp);
1973                NodeTraits::set_left  (temp, insertion_point);
1974                //Update leftmost
1975                if(rightmost == target_sub_root)
1976                   leftmost = insertion_point;
1977             }
1978             //Then clone right nodes
1979             else if( NodeTraits::get_right(current) &&
1980                      !NodeTraits::get_right(insertion_point)){
1981                current = NodeTraits::get_right(current);
1982                node_ptr temp = insertion_point;
1983                //Clone and mark as leaf
1984                insertion_point = cloner(current);
1985                NodeTraits::set_left  (insertion_point, node_ptr());
1986                NodeTraits::set_right (insertion_point, node_ptr());
1987                //Insert right
1988                NodeTraits::set_parent(insertion_point, temp);
1989                NodeTraits::set_right (temp, insertion_point);
1990                //Update rightmost
1991                rightmost = insertion_point;
1992             }
1993             //If not, go up
1994             else if(current == source_root){
1995                break;
1996             }
1997             else{
1998                //Branch completed, go up searching more nodes to clone
1999                current = NodeTraits::get_parent(current);
2000                insertion_point = NodeTraits::get_parent(insertion_point);
2001             }
2002          }
2003          rollback.release();
2004          leftmost_out   = leftmost;
2005          rightmost_out  = rightmost;
2006       }
2007       return target_sub_root;
2008    }
2009 
2010    template<class Disposer>
2011    static void dispose_subtree(node_ptr x, Disposer disposer) BOOST_NOEXCEPT
2012    {
2013       while (x){
2014          node_ptr save(NodeTraits::get_left(x));
2015          if (save) {
2016             // Right rotation
2017             NodeTraits::set_left(x, NodeTraits::get_right(save));
2018             NodeTraits::set_right(save, x);
2019          }
2020          else {
2021             save = NodeTraits::get_right(x);
2022             init(x);
2023             disposer(x);
2024          }
2025          x = save;
2026       }
2027    }
2028 
2029    template<class KeyType, class KeyNodePtrCompare>
2030    static node_ptr lower_bound_loop
2031       (node_ptr x, node_ptr y, const KeyType &key, KeyNodePtrCompare comp)
2032    {
2033       while(x){
2034          if(comp(x, key)){
2035             x = NodeTraits::get_right(x);
2036          }
2037          else{
2038             y = x;
2039             x = NodeTraits::get_left(x);
2040          }
2041       }
2042       return y;
2043    }
2044 
2045    template<class KeyType, class KeyNodePtrCompare>
2046    static node_ptr upper_bound_loop
2047       (node_ptr x, node_ptr y, const KeyType &key, KeyNodePtrCompare comp)
2048    {
2049       while(x){
2050          if(comp(key, x)){
2051             y = x;
2052             x = NodeTraits::get_left(x);
2053          }
2054          else{
2055             x = NodeTraits::get_right(x);
2056          }
2057       }
2058       return y;
2059    }
2060 
2061    template<class Checker>
2062    static void check_subtree(const_node_ptr n, Checker checker, typename Checker::return_type& check_return)
2063    {
2064       const_node_ptr left = NodeTraits::get_left(n);
2065       const_node_ptr right = NodeTraits::get_right(n);
2066       typename Checker::return_type check_return_left;
2067       typename Checker::return_type check_return_right;
2068       if (left)
2069       {
2070          BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_parent(left) == n);
2071          check_subtree(left, checker, check_return_left);
2072       }
2073       if (right)
2074       {
2075          BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_parent(right) == n);
2076          check_subtree(right, checker, check_return_right);
2077       }
2078       checker(n, check_return_left, check_return_right, check_return);
2079    }
2080 };
2081 
2082 /// @cond
2083 
2084 template<class NodeTraits>
2085 struct get_algo<BsTreeAlgorithms, NodeTraits>
2086 {
2087    typedef bstree_algorithms<NodeTraits> type;
2088 };
2089 
2090 template <class ValueTraits, class NodePtrCompare, class ExtraChecker>
2091 struct get_node_checker<BsTreeAlgorithms, ValueTraits, NodePtrCompare, ExtraChecker>
2092 {
2093    typedef detail::bstree_node_checker<ValueTraits, NodePtrCompare, ExtraChecker> type;
2094 };
2095 
2096 /// @endcond
2097 
2098 }  //namespace intrusive
2099 }  //namespace boost
2100 
2101 #include <boost/intrusive/detail/config_end.hpp>
2102 
2103 #endif //BOOST_INTRUSIVE_BSTREE_ALGORITHMS_HPP