File indexing completed on 2025-01-18 09:42:11
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef BOOST_MULTI_INDEX_RANKED_INDEX_HPP
0010 #define BOOST_MULTI_INDEX_RANKED_INDEX_HPP
0011
0012 #if defined(_MSC_VER)
0013 #pragma once
0014 #endif
0015
0016 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
0017 #include <boost/multi_index/detail/ord_index_impl.hpp>
0018 #include <boost/multi_index/detail/rnk_index_ops.hpp>
0019 #include <boost/multi_index/ranked_index_fwd.hpp>
0020
0021 namespace boost{
0022
0023 namespace multi_index{
0024
0025 namespace detail{
0026
0027
0028
0029 template<typename OrderedIndexNodeImpl>
0030 struct ranked_node:OrderedIndexNodeImpl
0031 {
0032 typedef typename OrderedIndexNodeImpl::size_type size_type;
0033
0034 size_type size;
0035 };
0036
0037 template<typename OrderedIndexImpl>
0038 class ranked_index:public OrderedIndexImpl
0039 {
0040 typedef OrderedIndexImpl super;
0041
0042 protected:
0043 typedef typename super::index_node_type index_node_type;
0044 typedef typename super::node_impl_pointer node_impl_pointer;
0045
0046 public:
0047 typedef typename super::ctor_args_list ctor_args_list;
0048 typedef typename super::allocator_type allocator_type;
0049 typedef typename super::iterator iterator;
0050 typedef typename super::size_type size_type;
0051
0052
0053
0054 template<typename CompatibleKey>
0055 size_type count(const CompatibleKey& x)const
0056 {
0057 return count(x,this->comp_);
0058 }
0059
0060 template<typename CompatibleKey,typename CompatibleCompare>
0061 size_type count(const CompatibleKey& x,const CompatibleCompare& comp)const
0062 {
0063 std::pair<size_type,size_type> p=this->equal_range_rank(x,comp);
0064 return p.second-p.first;
0065 }
0066
0067
0068
0069 iterator nth(size_type n)const
0070 {
0071 return this->make_iterator(index_node_type::from_impl(
0072 ranked_index_nth(n,this->header()->impl())));
0073 }
0074
0075 size_type rank(iterator position)const
0076 {
0077 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
0078 BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
0079
0080 return ranked_index_rank(
0081 position.get_node()->impl(),this->header()->impl());
0082 }
0083
0084 template<typename CompatibleKey>
0085 size_type find_rank(const CompatibleKey& x)const
0086 {
0087 return ranked_index_find_rank(
0088 this->root(),this->header(),this->key,x,this->comp_);
0089 }
0090
0091 template<typename CompatibleKey,typename CompatibleCompare>
0092 size_type find_rank(
0093 const CompatibleKey& x,const CompatibleCompare& comp)const
0094 {
0095 return ranked_index_find_rank(
0096 this->root(),this->header(),this->key,x,comp);
0097 }
0098
0099 template<typename CompatibleKey>
0100 size_type lower_bound_rank(const CompatibleKey& x)const
0101 {
0102 return ranked_index_lower_bound_rank(
0103 this->root(),this->header(),this->key,x,this->comp_);
0104 }
0105
0106 template<typename CompatibleKey,typename CompatibleCompare>
0107 size_type lower_bound_rank(
0108 const CompatibleKey& x,const CompatibleCompare& comp)const
0109 {
0110 return ranked_index_lower_bound_rank(
0111 this->root(),this->header(),this->key,x,comp);
0112 }
0113
0114 template<typename CompatibleKey>
0115 size_type upper_bound_rank(const CompatibleKey& x)const
0116 {
0117 return ranked_index_upper_bound_rank(
0118 this->root(),this->header(),this->key,x,this->comp_);
0119 }
0120
0121 template<typename CompatibleKey,typename CompatibleCompare>
0122 size_type upper_bound_rank(
0123 const CompatibleKey& x,const CompatibleCompare& comp)const
0124 {
0125 return ranked_index_upper_bound_rank(
0126 this->root(),this->header(),this->key,x,comp);
0127 }
0128
0129 template<typename CompatibleKey>
0130 std::pair<size_type,size_type> equal_range_rank(
0131 const CompatibleKey& x)const
0132 {
0133 return ranked_index_equal_range_rank(
0134 this->root(),this->header(),this->key,x,this->comp_);
0135 }
0136
0137 template<typename CompatibleKey,typename CompatibleCompare>
0138 std::pair<size_type,size_type> equal_range_rank(
0139 const CompatibleKey& x,const CompatibleCompare& comp)const
0140 {
0141 return ranked_index_equal_range_rank(
0142 this->root(),this->header(),this->key,x,comp);
0143 }
0144
0145 template<typename LowerBounder,typename UpperBounder>
0146 std::pair<size_type,size_type>
0147 range_rank(LowerBounder lower,UpperBounder upper)const
0148 {
0149 typedef typename mpl::if_<
0150 is_same<LowerBounder,unbounded_type>,
0151 BOOST_DEDUCED_TYPENAME mpl::if_<
0152 is_same<UpperBounder,unbounded_type>,
0153 both_unbounded_tag,
0154 lower_unbounded_tag
0155 >::type,
0156 BOOST_DEDUCED_TYPENAME mpl::if_<
0157 is_same<UpperBounder,unbounded_type>,
0158 upper_unbounded_tag,
0159 none_unbounded_tag
0160 >::type
0161 >::type dispatch;
0162
0163 return range_rank(lower,upper,dispatch());
0164 }
0165
0166 protected:
0167 ranked_index(const ranked_index& x):super(x){};
0168
0169 ranked_index(const ranked_index& x,do_not_copy_elements_tag):
0170 super(x,do_not_copy_elements_tag()){};
0171
0172 ranked_index(
0173 const ctor_args_list& args_list,const allocator_type& al):
0174 super(args_list,al){}
0175
0176 private:
0177 template<typename LowerBounder,typename UpperBounder>
0178 std::pair<size_type,size_type>
0179 range_rank(LowerBounder lower,UpperBounder upper,none_unbounded_tag)const
0180 {
0181 index_node_type* y=this->header();
0182 index_node_type* z=this->root();
0183
0184 if(!z)return std::pair<size_type,size_type>(0,0);
0185
0186 size_type s=z->impl()->size;
0187
0188 do{
0189 if(!lower(this->key(z->value()))){
0190 z=index_node_type::from_impl(z->right());
0191 }
0192 else if(!upper(this->key(z->value()))){
0193 y=z;
0194 s-=ranked_node_size(y->right())+1;
0195 z=index_node_type::from_impl(z->left());
0196 }
0197 else{
0198 return std::pair<size_type,size_type>(
0199 s-z->impl()->size+
0200 lower_range_rank(index_node_type::from_impl(z->left()),z,lower),
0201 s-ranked_node_size(z->right())+
0202 upper_range_rank(index_node_type::from_impl(z->right()),y,upper));
0203 }
0204 }while(z);
0205
0206 return std::pair<size_type,size_type>(s,s);
0207 }
0208
0209 template<typename LowerBounder,typename UpperBounder>
0210 std::pair<size_type,size_type>
0211 range_rank(LowerBounder,UpperBounder upper,lower_unbounded_tag)const
0212 {
0213 return std::pair<size_type,size_type>(
0214 0,
0215 upper_range_rank(this->root(),this->header(),upper));
0216 }
0217
0218 template<typename LowerBounder,typename UpperBounder>
0219 std::pair<size_type,size_type>
0220 range_rank(LowerBounder lower,UpperBounder,upper_unbounded_tag)const
0221 {
0222 return std::pair<size_type,size_type>(
0223 lower_range_rank(this->root(),this->header(),lower),
0224 this->size());
0225 }
0226
0227 template<typename LowerBounder,typename UpperBounder>
0228 std::pair<size_type,size_type>
0229 range_rank(LowerBounder,UpperBounder,both_unbounded_tag)const
0230 {
0231 return std::pair<size_type,size_type>(0,this->size());
0232 }
0233
0234 template<typename LowerBounder>
0235 size_type
0236 lower_range_rank(
0237 index_node_type* top,index_node_type* y,LowerBounder lower)const
0238 {
0239 if(!top)return 0;
0240
0241 size_type s=top->impl()->size;
0242
0243 do{
0244 if(lower(this->key(top->value()))){
0245 y=top;
0246 s-=ranked_node_size(y->right())+1;
0247 top=index_node_type::from_impl(top->left());
0248 }
0249 else top=index_node_type::from_impl(top->right());
0250 }while(top);
0251
0252 return s;
0253 }
0254
0255 template<typename UpperBounder>
0256 size_type
0257 upper_range_rank(
0258 index_node_type* top,index_node_type* y,UpperBounder upper)const
0259 {
0260 if(!top)return 0;
0261
0262 size_type s=top->impl()->size;
0263
0264 do{
0265 if(!upper(this->key(top->value()))){
0266 y=top;
0267 s-=ranked_node_size(y->right())+1;
0268 top=index_node_type::from_impl(top->left());
0269 }
0270 else top=index_node_type::from_impl(top->right());
0271 }while(top);
0272
0273 return s;
0274 }
0275 };
0276
0277
0278
0279 struct rank_policy
0280 {
0281 template<typename OrderedIndexNodeImpl>
0282 struct augmented_node
0283 {
0284 typedef ranked_node<OrderedIndexNodeImpl> type;
0285 };
0286
0287 template<typename OrderedIndexImpl>
0288 struct augmented_interface
0289 {
0290 typedef ranked_index<OrderedIndexImpl> type;
0291 };
0292
0293
0294
0295 template<typename Pointer>
0296 static void add(Pointer x,Pointer root)
0297 {
0298 x->size=1;
0299 while(x!=root){
0300 x=x->parent();
0301 ++(x->size);
0302 }
0303 }
0304
0305 template<typename Pointer>
0306 static void remove(Pointer x,Pointer root)
0307 {
0308 while(x!=root){
0309 x=x->parent();
0310 --(x->size);
0311 }
0312 }
0313
0314 template<typename Pointer>
0315 static void copy(Pointer x,Pointer y)
0316 {
0317 y->size=x->size;
0318 }
0319
0320 template<typename Pointer>
0321 static void rotate_left(Pointer x,Pointer y)
0322 {
0323 y->size=x->size;
0324 x->size=ranked_node_size(x->left())+ranked_node_size(x->right())+1;
0325 }
0326
0327 template<typename Pointer>
0328 static void rotate_right(Pointer x,Pointer y)
0329 {
0330 rotate_left(x,y);
0331 }
0332
0333 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
0334
0335
0336 template<typename Pointer>
0337 static bool invariant(Pointer x)
0338 {
0339 return x->size==ranked_node_size(x->left())+ranked_node_size(x->right())+1;
0340 }
0341 #endif
0342 };
0343
0344 }
0345
0346
0347
0348 template<typename Arg1,typename Arg2,typename Arg3>
0349 struct ranked_unique
0350 {
0351 typedef typename detail::ordered_index_args<
0352 Arg1,Arg2,Arg3> index_args;
0353 typedef typename index_args::tag_list_type::type tag_list_type;
0354 typedef typename index_args::key_from_value_type key_from_value_type;
0355 typedef typename index_args::compare_type compare_type;
0356
0357 template<typename Super>
0358 struct node_class
0359 {
0360 typedef detail::ordered_index_node<detail::rank_policy,Super> type;
0361 };
0362
0363 template<typename SuperMeta>
0364 struct index_class
0365 {
0366 typedef detail::ordered_index<
0367 key_from_value_type,compare_type,
0368 SuperMeta,tag_list_type,detail::ordered_unique_tag,
0369 detail::rank_policy> type;
0370 };
0371 };
0372
0373 template<typename Arg1,typename Arg2,typename Arg3>
0374 struct ranked_non_unique
0375 {
0376 typedef detail::ordered_index_args<
0377 Arg1,Arg2,Arg3> index_args;
0378 typedef typename index_args::tag_list_type::type tag_list_type;
0379 typedef typename index_args::key_from_value_type key_from_value_type;
0380 typedef typename index_args::compare_type compare_type;
0381
0382 template<typename Super>
0383 struct node_class
0384 {
0385 typedef detail::ordered_index_node<detail::rank_policy,Super> type;
0386 };
0387
0388 template<typename SuperMeta>
0389 struct index_class
0390 {
0391 typedef detail::ordered_index<
0392 key_from_value_type,compare_type,
0393 SuperMeta,tag_list_type,detail::ordered_non_unique_tag,
0394 detail::rank_policy> type;
0395 };
0396 };
0397
0398 }
0399
0400 }
0401
0402 #endif