Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:42:08

0001 /* Copyright 2003-2020 Joaquin M Lopez Munoz.
0002  * Distributed under the Boost Software License, Version 1.0.
0003  * (See accompanying file LICENSE_1_0.txt or copy at
0004  * http://www.boost.org/LICENSE_1_0.txt)
0005  *
0006  * See http://www.boost.org/libs/multi_index for library home page.
0007  *
0008  * The internal implementation of red-black trees is based on that of SGI STL
0009  * stl_tree.h file: 
0010  *
0011  * Copyright (c) 1996,1997
0012  * Silicon Graphics Computer Systems, Inc.
0013  *
0014  * Permission to use, copy, modify, distribute and sell this software
0015  * and its documentation for any purpose is hereby granted without fee,
0016  * provided that the above copyright notice appear in all copies and
0017  * that both that copyright notice and this permission notice appear
0018  * in supporting documentation.  Silicon Graphics makes no
0019  * representations about the suitability of this software for any
0020  * purpose.  It is provided "as is" without express or implied warranty.
0021  *
0022  *
0023  * Copyright (c) 1994
0024  * Hewlett-Packard Company
0025  *
0026  * Permission to use, copy, modify, distribute and sell this software
0027  * and its documentation for any purpose is hereby granted without fee,
0028  * provided that the above copyright notice appear in all copies and
0029  * that both that copyright notice and this permission notice appear
0030  * in supporting documentation.  Hewlett-Packard Company makes no
0031  * representations about the suitability of this software for any
0032  * purpose.  It is provided "as is" without express or implied warranty.
0033  *
0034  */
0035 
0036 #ifndef BOOST_MULTI_INDEX_DETAIL_ORD_INDEX_NODE_HPP
0037 #define BOOST_MULTI_INDEX_DETAIL_ORD_INDEX_NODE_HPP
0038 
0039 #if defined(_MSC_VER)
0040 #pragma once
0041 #endif
0042 
0043 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
0044 #include <cstddef>
0045 #include <boost/multi_index/detail/allocator_traits.hpp>
0046 #include <boost/multi_index/detail/raw_ptr.hpp>
0047 
0048 #if !defined(BOOST_MULTI_INDEX_DISABLE_COMPRESSED_ORDERED_INDEX_NODES)
0049 #include <boost/mpl/and.hpp>
0050 #include <boost/mpl/if.hpp>
0051 #include <boost/multi_index/detail/uintptr_type.hpp>
0052 #include <boost/type_traits/alignment_of.hpp>
0053 #include <boost/type_traits/is_same.hpp>
0054 #endif
0055 
0056 namespace boost{
0057 
0058 namespace multi_index{
0059 
0060 namespace detail{
0061 
0062 /* definition of red-black nodes for ordered_index */
0063 
0064 enum ordered_index_color{red=false,black=true};
0065 enum ordered_index_side{to_left=false,to_right=true};
0066 
0067 template<typename AugmentPolicy,typename Allocator>
0068 struct ordered_index_node_impl; /* fwd decl. */
0069 
0070 template<typename AugmentPolicy,typename Allocator>
0071 struct ordered_index_node_traits
0072 {
0073   typedef typename rebind_alloc_for<
0074     Allocator,
0075     ordered_index_node_impl<AugmentPolicy,Allocator>
0076   >::type                                            allocator;
0077   typedef allocator_traits<allocator>                alloc_traits;
0078   typedef typename alloc_traits::pointer             pointer;
0079   typedef typename alloc_traits::const_pointer       const_pointer;
0080   typedef typename alloc_traits::difference_type     difference_type;
0081   typedef typename alloc_traits::size_type           size_type;
0082 };
0083 
0084 template<typename AugmentPolicy,typename Allocator>
0085 struct ordered_index_node_std_base
0086 {
0087   typedef ordered_index_node_traits<
0088     AugmentPolicy,Allocator>                    node_traits;
0089   typedef typename node_traits::allocator       node_allocator;
0090   typedef typename node_traits::pointer         pointer;
0091   typedef typename node_traits::const_pointer   const_pointer;
0092   typedef typename node_traits::difference_type difference_type;
0093   typedef typename node_traits::size_type       size_type;
0094   typedef ordered_index_color&                  color_ref;
0095   typedef pointer&                              parent_ref;
0096 
0097   ordered_index_color& color(){return color_;}
0098   ordered_index_color  color()const{return color_;}
0099   pointer&             parent(){return parent_;}
0100   pointer              parent()const{return parent_;}
0101   pointer&             left(){return left_;}
0102   pointer              left()const{return left_;}
0103   pointer&             right(){return right_;}
0104   pointer              right()const{return right_;}
0105 
0106 private:
0107   ordered_index_color color_; 
0108   pointer             parent_;
0109   pointer             left_;
0110   pointer             right_;
0111 };
0112 
0113 #if !defined(BOOST_MULTI_INDEX_DISABLE_COMPRESSED_ORDERED_INDEX_NODES)
0114 /* If ordered_index_node_impl has even alignment, we can use the least
0115  * significant bit of one of the ordered_index_node_impl pointers to
0116  * store color information. This typically reduces the size of
0117  * ordered_index_node_impl by 25%.
0118  */
0119 
0120 #if defined(BOOST_MSVC)
0121 /* This code casts pointers to an integer type that has been computed
0122  * to be large enough to hold the pointer, however the metaprogramming
0123  * logic is not always spotted by the VC++ code analyser that issues a
0124  * long list of warnings.
0125  */
0126 
0127 #pragma warning(push)
0128 #pragma warning(disable:4312 4311)
0129 #endif
0130 
0131 template<typename AugmentPolicy,typename Allocator>
0132 struct ordered_index_node_compressed_base
0133 {
0134   typedef ordered_index_node_traits<
0135     AugmentPolicy,Allocator>                    node_traits;
0136   typedef ordered_index_node_impl<
0137     AugmentPolicy,Allocator>*                   pointer;
0138   typedef const ordered_index_node_impl<
0139     AugmentPolicy,Allocator>*                   const_pointer;
0140   typedef typename node_traits::difference_type difference_type;
0141   typedef typename node_traits::size_type       size_type;
0142 
0143   struct color_ref
0144   {
0145     color_ref(uintptr_type* r_):r(r_){}
0146     color_ref(const color_ref& x):r(x.r){}
0147     
0148     operator ordered_index_color()const
0149     {
0150       return ordered_index_color(*r&uintptr_type(1));
0151     }
0152     
0153     color_ref& operator=(ordered_index_color c)
0154     {
0155       *r&=~uintptr_type(1);
0156       *r|=uintptr_type(c);
0157       return *this;
0158     }
0159     
0160     color_ref& operator=(const color_ref& x)
0161     {
0162       return operator=(x.operator ordered_index_color());
0163     }
0164     
0165   private:
0166     uintptr_type* r;
0167   };
0168   
0169   struct parent_ref
0170   {
0171     parent_ref(uintptr_type* r_):r(r_){}
0172     parent_ref(const parent_ref& x):r(x.r){}
0173     
0174     operator pointer()const
0175     {
0176       return (pointer)(void*)(*r&~uintptr_type(1));
0177     }
0178     
0179     parent_ref& operator=(pointer p)
0180     {
0181       *r=((uintptr_type)(void*)p)|(*r&uintptr_type(1));
0182       return *this;
0183     }
0184     
0185     parent_ref& operator=(const parent_ref& x)
0186     {
0187       return operator=(x.operator pointer());
0188     }
0189 
0190     pointer operator->()const
0191     {
0192       return operator pointer();
0193     }
0194 
0195   private:
0196     uintptr_type* r;
0197   };
0198   
0199   color_ref           color(){return color_ref(&parentcolor_);}
0200   ordered_index_color color()const
0201   {
0202     return ordered_index_color(parentcolor_&uintptr_type(1));
0203   }
0204 
0205   parent_ref parent(){return parent_ref(&parentcolor_);}
0206   pointer    parent()const
0207   {
0208     return (pointer)(void*)(parentcolor_&~uintptr_type(1));
0209   }
0210 
0211   pointer& left(){return left_;}
0212   pointer  left()const{return left_;}
0213   pointer& right(){return right_;}
0214   pointer  right()const{return right_;}
0215 
0216 private:
0217   uintptr_type parentcolor_;
0218   pointer      left_;
0219   pointer      right_;
0220 };
0221 #if defined(BOOST_MSVC)
0222 #pragma warning(pop)
0223 #endif
0224 #endif
0225 
0226 template<typename AugmentPolicy,typename Allocator>
0227 struct ordered_index_node_impl_base:
0228 
0229 #if !defined(BOOST_MULTI_INDEX_DISABLE_COMPRESSED_ORDERED_INDEX_NODES)
0230   AugmentPolicy::template augmented_node<
0231     typename mpl::if_c<
0232       !(has_uintptr_type::value)||
0233       (alignment_of<
0234         ordered_index_node_compressed_base<AugmentPolicy,Allocator>
0235        >::value%2)||
0236       !(is_same<
0237         typename ordered_index_node_traits<AugmentPolicy,Allocator>::pointer,
0238         ordered_index_node_impl<AugmentPolicy,Allocator>*>::value),
0239       ordered_index_node_std_base<AugmentPolicy,Allocator>,
0240       ordered_index_node_compressed_base<AugmentPolicy,Allocator>
0241     >::type
0242   >::type
0243 #else
0244   AugmentPolicy::template augmented_node<
0245     ordered_index_node_std_base<AugmentPolicy,Allocator>
0246   >::type
0247 #endif
0248 
0249 {};
0250 
0251 template<typename AugmentPolicy,typename Allocator>
0252 struct ordered_index_node_impl:
0253   ordered_index_node_impl_base<AugmentPolicy,Allocator>
0254 {
0255 private:
0256   typedef ordered_index_node_impl_base<AugmentPolicy,Allocator> super;
0257 
0258 public:
0259   typedef typename super::color_ref                             color_ref;
0260   typedef typename super::parent_ref                            parent_ref;
0261   typedef typename super::pointer                               pointer;
0262   typedef typename super::const_pointer                         const_pointer;
0263 
0264   /* interoperability with bidir_node_iterator */
0265 
0266   static void increment(pointer& x)
0267   {
0268     if(x->right()!=pointer(0)){
0269       x=x->right();
0270       while(x->left()!=pointer(0))x=x->left();
0271     }
0272     else{
0273       pointer y=x->parent();
0274       while(x==y->right()){
0275         x=y;
0276         y=y->parent();
0277       }
0278       if(x->right()!=y)x=y;
0279     }
0280   }
0281 
0282   static void decrement(pointer& x)
0283   {
0284     if(x->color()==red&&x->parent()->parent()==x){
0285       x=x->right();
0286     }
0287     else if(x->left()!=pointer(0)){
0288       pointer y=x->left();
0289       while(y->right()!=pointer(0))y=y->right();
0290       x=y;
0291     }else{
0292       pointer y=x->parent();
0293       while(x==y->left()){
0294         x=y;
0295         y=y->parent();
0296       }
0297       x=y;
0298     }
0299   }
0300 
0301   /* algorithmic stuff */
0302 
0303   static void rotate_left(pointer x,parent_ref root)
0304   {
0305     pointer y=x->right();
0306     x->right()=y->left();
0307     if(y->left()!=pointer(0))y->left()->parent()=x;
0308     y->parent()=x->parent();
0309     
0310     if(x==root)                    root=y;
0311     else if(x==x->parent()->left())x->parent()->left()=y;
0312     else                           x->parent()->right()=y;
0313     y->left()=x;
0314     x->parent()=y;
0315     AugmentPolicy::rotate_left(x,y);
0316   }
0317 
0318   static pointer minimum(pointer x)
0319   {
0320     while(x->left()!=pointer(0))x=x->left();
0321     return x;
0322   }
0323 
0324   static pointer maximum(pointer x)
0325   {
0326     while(x->right()!=pointer(0))x=x->right();
0327     return x;
0328   }
0329 
0330   static void rotate_right(pointer x,parent_ref root)
0331   {
0332     pointer y=x->left();
0333     x->left()=y->right();
0334     if(y->right()!=pointer(0))y->right()->parent()=x;
0335     y->parent()=x->parent();
0336 
0337     if(x==root)                     root=y;
0338     else if(x==x->parent()->right())x->parent()->right()=y;
0339     else                            x->parent()->left()=y;
0340     y->right()=x;
0341     x->parent()=y;
0342     AugmentPolicy::rotate_right(x,y);
0343   }
0344 
0345   static void rebalance(pointer x,parent_ref root)
0346   {
0347     x->color()=red;
0348     while(x!=root&&x->parent()->color()==red){
0349       if(x->parent()==x->parent()->parent()->left()){
0350         pointer y=x->parent()->parent()->right();
0351         if(y!=pointer(0)&&y->color()==red){
0352           x->parent()->color()=black;
0353           y->color()=black;
0354           x->parent()->parent()->color()=red;
0355           x=x->parent()->parent();
0356         }
0357         else{
0358           if(x==x->parent()->right()){
0359             x=x->parent();
0360             rotate_left(x,root);
0361           }
0362           x->parent()->color()=black;
0363           x->parent()->parent()->color()=red;
0364           rotate_right(x->parent()->parent(),root);
0365         }
0366       }
0367       else{
0368         pointer y=x->parent()->parent()->left();
0369         if(y!=pointer(0)&&y->color()==red){
0370           x->parent()->color()=black;
0371           y->color()=black;
0372           x->parent()->parent()->color()=red;
0373           x=x->parent()->parent();
0374         }
0375         else{
0376           if(x==x->parent()->left()){
0377             x=x->parent();
0378             rotate_right(x,root);
0379           }
0380           x->parent()->color()=black;
0381           x->parent()->parent()->color()=red;
0382           rotate_left(x->parent()->parent(),root);
0383         }
0384       }
0385     }
0386     root->color()=black;
0387   }
0388 
0389   static void link(
0390     pointer x,ordered_index_side side,pointer position,pointer header)
0391   {
0392     if(side==to_left){
0393       position->left()=x;  /* also makes leftmost=x when parent==header */
0394       if(position==header){
0395         header->parent()=x;
0396         header->right()=x;
0397       }
0398       else if(position==header->left()){
0399         header->left()=x;  /* maintain leftmost pointing to min node */
0400       }
0401     }
0402     else{
0403       position->right()=x;
0404       if(position==header->right()){
0405         header->right()=x; /* maintain rightmost pointing to max node */
0406       }
0407     }
0408     x->parent()=position;
0409     x->left()=pointer(0);
0410     x->right()=pointer(0);
0411     AugmentPolicy::add(x,pointer(header->parent()));
0412     ordered_index_node_impl::rebalance(x,header->parent());
0413   }
0414 
0415   static pointer rebalance_for_extract(
0416     pointer z,parent_ref root,pointer& leftmost,pointer& rightmost)
0417   {
0418     pointer y=z;
0419     pointer x=pointer(0);
0420     pointer x_parent=pointer(0);
0421     if(y->left()==pointer(0)){    /* z has at most one non-null child. y==z. */
0422       x=y->right();               /* x might be null */
0423     }
0424     else{
0425       if(y->right()==pointer(0)){ /* z has exactly one non-null child. y==z. */
0426         x=y->left();              /* x is not null */
0427       }
0428       else{                       /* z has two non-null children.  Set y to */
0429         y=y->right();             /* z's successor. x might be null.        */
0430         while(y->left()!=pointer(0))y=y->left();
0431         x=y->right();
0432       }
0433     }
0434     AugmentPolicy::remove(y,pointer(root));
0435     if(y!=z){
0436       AugmentPolicy::copy(z,y);
0437       z->left()->parent()=y;   /* relink y in place of z. y is z's successor */
0438       y->left()=z->left();
0439       if(y!=z->right()){
0440         x_parent=y->parent();
0441         if(x!=pointer(0))x->parent()=y->parent();
0442         y->parent()->left()=x; /* y must be a child of left */
0443         y->right()=z->right();
0444         z->right()->parent()=y;
0445       }
0446       else{
0447         x_parent=y;
0448       }
0449 
0450       if(root==z)                    root=y;
0451       else if(z->parent()->left()==z)z->parent()->left()=y;
0452       else                           z->parent()->right()=y;
0453       y->parent()=z->parent();
0454       ordered_index_color c=y->color();
0455       y->color()=z->color();
0456       z->color()=c;
0457       y=z;                    /* y now points to node to be actually deleted */
0458     }
0459     else{                     /* y==z */
0460       x_parent=y->parent();
0461       if(x!=pointer(0))x->parent()=y->parent();   
0462       if(root==z){
0463         root=x;
0464       }
0465       else{
0466         if(z->parent()->left()==z)z->parent()->left()=x;
0467         else                      z->parent()->right()=x;
0468       }
0469       if(leftmost==z){
0470         if(z->right()==pointer(0)){ /* z->left() must be null also */
0471           leftmost=z->parent();
0472         }
0473         else{              
0474           leftmost=minimum(x);      /* makes leftmost==header if z==root */
0475         }
0476       }
0477       if(rightmost==z){
0478         if(z->left()==pointer(0)){  /* z->right() must be null also */
0479           rightmost=z->parent();
0480         }
0481         else{                   /* x==z->left() */
0482           rightmost=maximum(x); /* makes rightmost==header if z==root */
0483         }
0484       }
0485     }
0486     if(y->color()!=red){
0487       while(x!=root&&(x==pointer(0)|| x->color()==black)){
0488         if(x==x_parent->left()){
0489           pointer w=x_parent->right();
0490           if(w->color()==red){
0491             w->color()=black;
0492             x_parent->color()=red;
0493             rotate_left(x_parent,root);
0494             w=x_parent->right();
0495           }
0496           if((w->left()==pointer(0)||w->left()->color()==black) &&
0497              (w->right()==pointer(0)||w->right()->color()==black)){
0498             w->color()=red;
0499             x=x_parent;
0500             x_parent=x_parent->parent();
0501           } 
0502           else{
0503             if(w->right()==pointer(0 )
0504                 || w->right()->color()==black){
0505               if(w->left()!=pointer(0)) w->left()->color()=black;
0506               w->color()=red;
0507               rotate_right(w,root);
0508               w=x_parent->right();
0509             }
0510             w->color()=x_parent->color();
0511             x_parent->color()=black;
0512             if(w->right()!=pointer(0))w->right()->color()=black;
0513             rotate_left(x_parent,root);
0514             break;
0515           }
0516         } 
0517         else{                   /* same as above,with right <-> left */
0518           pointer w=x_parent->left();
0519           if(w->color()==red){
0520             w->color()=black;
0521             x_parent->color()=red;
0522             rotate_right(x_parent,root);
0523             w=x_parent->left();
0524           }
0525           if((w->right()==pointer(0)||w->right()->color()==black) &&
0526              (w->left()==pointer(0)||w->left()->color()==black)){
0527             w->color()=red;
0528             x=x_parent;
0529             x_parent=x_parent->parent();
0530           }
0531           else{
0532             if(w->left()==pointer(0)||w->left()->color()==black){
0533               if(w->right()!=pointer(0))w->right()->color()=black;
0534               w->color()=red;
0535               rotate_left(w,root);
0536               w=x_parent->left();
0537             }
0538             w->color()=x_parent->color();
0539             x_parent->color()=black;
0540             if(w->left()!=pointer(0))w->left()->color()=black;
0541             rotate_right(x_parent,root);
0542             break;
0543           }
0544         }
0545       }
0546       if(x!=pointer(0))x->color()=black;
0547     }
0548     return y;
0549   }
0550 
0551   static void restore(pointer x,pointer position,pointer header)
0552   {
0553     if(position->left()==pointer(0)||position->left()==header){
0554       link(x,to_left,position,header);
0555     }
0556     else{
0557       decrement(position);
0558       link(x,to_right,position,header);
0559     }
0560   }
0561 
0562 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
0563   /* invariant stuff */
0564 
0565   static std::size_t black_count(pointer node,pointer root)
0566   {
0567     if(node==pointer(0))return 0;
0568     std::size_t sum=0;
0569     for(;;){
0570       if(node->color()==black)++sum;
0571       if(node==root)break;
0572       node=node->parent();
0573     } 
0574     return sum;
0575   }
0576 #endif
0577 };
0578 
0579 template<typename AugmentPolicy,typename Super>
0580 struct ordered_index_node_trampoline:
0581   ordered_index_node_impl<
0582     AugmentPolicy,
0583     typename rebind_alloc_for<
0584       typename Super::allocator_type,
0585       char
0586     >::type
0587   >
0588 {
0589   typedef ordered_index_node_impl<
0590     AugmentPolicy,
0591     typename rebind_alloc_for<
0592       typename Super::allocator_type,
0593       char
0594     >::type
0595   > impl_type;
0596 };
0597 
0598 template<typename AugmentPolicy,typename Super>
0599 struct ordered_index_node:
0600   Super,ordered_index_node_trampoline<AugmentPolicy,Super>
0601 {
0602 private:
0603   typedef ordered_index_node_trampoline<AugmentPolicy,Super> trampoline;
0604 
0605 public:
0606   typedef typename trampoline::impl_type       impl_type;
0607   typedef typename trampoline::color_ref       impl_color_ref;
0608   typedef typename trampoline::parent_ref      impl_parent_ref;
0609   typedef typename trampoline::pointer         impl_pointer;
0610   typedef typename trampoline::const_pointer   const_impl_pointer;
0611   typedef typename trampoline::difference_type difference_type;
0612   typedef typename trampoline::size_type       size_type;
0613 
0614   impl_color_ref      color(){return trampoline::color();}
0615   ordered_index_color color()const{return trampoline::color();}
0616   impl_parent_ref     parent(){return trampoline::parent();}
0617   impl_pointer        parent()const{return trampoline::parent();}
0618   impl_pointer&       left(){return trampoline::left();}
0619   impl_pointer        left()const{return trampoline::left();}
0620   impl_pointer&       right(){return trampoline::right();}
0621   impl_pointer        right()const{return trampoline::right();}
0622 
0623   impl_pointer impl()
0624   {
0625     return static_cast<impl_pointer>(
0626       static_cast<impl_type*>(static_cast<trampoline*>(this)));
0627   }
0628 
0629   const_impl_pointer impl()const
0630   {
0631     return static_cast<const_impl_pointer>(
0632       static_cast<const impl_type*>(static_cast<const trampoline*>(this)));
0633   }
0634 
0635   static ordered_index_node* from_impl(impl_pointer x)
0636   {
0637     return
0638       static_cast<ordered_index_node*>(
0639         static_cast<trampoline*>(
0640           raw_ptr<impl_type*>(x)));
0641   }
0642 
0643   static const ordered_index_node* from_impl(const_impl_pointer x)
0644   {
0645     return
0646       static_cast<const ordered_index_node*>(
0647         static_cast<const trampoline*>(
0648           raw_ptr<const impl_type*>(x)));
0649   }
0650 
0651   /* interoperability with bidir_node_iterator */
0652 
0653   static void increment(ordered_index_node*& x)
0654   {
0655     impl_pointer xi=x->impl();
0656     trampoline::increment(xi);
0657     x=from_impl(xi);
0658   }
0659 
0660   static void decrement(ordered_index_node*& x)
0661   {
0662     impl_pointer xi=x->impl();
0663     trampoline::decrement(xi);
0664     x=from_impl(xi);
0665   }
0666 };
0667 
0668 } /* namespace multi_index::detail */
0669 
0670 } /* namespace multi_index */
0671 
0672 } /* namespace boost */
0673 
0674 #endif