rnk_index_ops.hpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. /* Copyright 2003-2018 Joaquin M Lopez Munoz.
  2. * Distributed under the Boost Software License, Version 1.0.
  3. * (See accompanying file LICENSE_1_0.txt or copy at
  4. * http://www.boost.org/LICENSE_1_0.txt)
  5. *
  6. * See http://www.boost.org/libs/multi_index for library home page.
  7. */
  8. #ifndef BOOST_MULTI_INDEX_DETAIL_RNK_INDEX_OPS_HPP
  9. #define BOOST_MULTI_INDEX_DETAIL_RNK_INDEX_OPS_HPP
  10. #if defined(_MSC_VER)
  11. #pragma once
  12. #endif
  13. #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
  14. #include <boost/core/pointer_traits.hpp>
  15. #include <boost/mpl/and.hpp>
  16. #include <boost/multi_index/detail/promotes_arg.hpp>
  17. #include <utility>
  18. namespace boost{
  19. namespace multi_index{
  20. namespace detail{
  21. /* Common code for ranked_index memfuns having templatized and
  22. * non-templatized versions.
  23. */
  24. template<typename Pointer>
  25. struct ranked_node_size_type
  26. {
  27. typedef typename boost::pointer_traits<Pointer>::
  28. element_type::size_type type;
  29. };
  30. template<typename Pointer>
  31. inline typename ranked_node_size_type<Pointer>::type
  32. ranked_node_size(Pointer x)
  33. {
  34. return x!=Pointer(0)?x->size:0;
  35. }
  36. template<typename Pointer>
  37. inline Pointer ranked_index_nth(
  38. BOOST_DEDUCED_TYPENAME ranked_node_size_type<Pointer>::type n,Pointer end_)
  39. {
  40. typedef typename ranked_node_size_type<Pointer>::type size_type;
  41. Pointer top=end_->parent();
  42. if(top==Pointer(0)||n>=top->size)return end_;
  43. for(;;){
  44. size_type s=ranked_node_size(top->left());
  45. if(n==s)return top;
  46. if(n<s)top=top->left();
  47. else{
  48. top=top->right();
  49. n-=s+1;
  50. }
  51. }
  52. }
  53. template<typename Pointer>
  54. inline typename ranked_node_size_type<Pointer>::type
  55. ranked_index_rank(Pointer x,Pointer end_)
  56. {
  57. typedef typename ranked_node_size_type<Pointer>::type size_type;
  58. Pointer top=end_->parent();
  59. if(top==Pointer(0))return 0;
  60. if(x==end_)return top->size;
  61. size_type s=ranked_node_size(x->left());
  62. while(x!=top){
  63. Pointer z=x->parent();
  64. if(x==z->right()){
  65. s+=ranked_node_size(z->left())+1;
  66. }
  67. x=z;
  68. }
  69. return s;
  70. }
  71. template<
  72. typename Node,typename KeyFromValue,
  73. typename CompatibleKey,typename CompatibleCompare
  74. >
  75. inline typename Node::size_type ranked_index_find_rank(
  76. Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
  77. const CompatibleCompare& comp)
  78. {
  79. typedef typename KeyFromValue::result_type key_type;
  80. return ranked_index_find_rank(
  81. top,y,key,x,comp,
  82. mpl::and_<
  83. promotes_1st_arg<CompatibleCompare,CompatibleKey,key_type>,
  84. promotes_2nd_arg<CompatibleCompare,key_type,CompatibleKey> >());
  85. }
  86. template<
  87. typename Node,typename KeyFromValue,
  88. typename CompatibleCompare
  89. >
  90. inline typename Node::size_type ranked_index_find_rank(
  91. Node* top,Node* y,const KeyFromValue& key,
  92. const BOOST_DEDUCED_TYPENAME KeyFromValue::result_type& x,
  93. const CompatibleCompare& comp,mpl::true_)
  94. {
  95. return ranked_index_find_rank(top,y,key,x,comp,mpl::false_());
  96. }
  97. template<
  98. typename Node,typename KeyFromValue,
  99. typename CompatibleKey,typename CompatibleCompare
  100. >
  101. inline typename Node::size_type ranked_index_find_rank(
  102. Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
  103. const CompatibleCompare& comp,mpl::false_)
  104. {
  105. typedef typename Node::size_type size_type;
  106. if(!top)return 0;
  107. size_type s=top->impl()->size,
  108. s0=s;
  109. Node* y0=y;
  110. do{
  111. if(!comp(key(top->value()),x)){
  112. y=top;
  113. s-=ranked_node_size(y->right())+1;
  114. top=Node::from_impl(top->left());
  115. }
  116. else top=Node::from_impl(top->right());
  117. }while(top);
  118. return (y==y0||comp(x,key(y->value())))?s0:s;
  119. }
  120. template<
  121. typename Node,typename KeyFromValue,
  122. typename CompatibleKey,typename CompatibleCompare
  123. >
  124. inline typename Node::size_type ranked_index_lower_bound_rank(
  125. Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
  126. const CompatibleCompare& comp)
  127. {
  128. typedef typename KeyFromValue::result_type key_type;
  129. return ranked_index_lower_bound_rank(
  130. top,y,key,x,comp,
  131. promotes_2nd_arg<CompatibleCompare,key_type,CompatibleKey>());
  132. }
  133. template<
  134. typename Node,typename KeyFromValue,
  135. typename CompatibleCompare
  136. >
  137. inline typename Node::size_type ranked_index_lower_bound_rank(
  138. Node* top,Node* y,const KeyFromValue& key,
  139. const BOOST_DEDUCED_TYPENAME KeyFromValue::result_type& x,
  140. const CompatibleCompare& comp,mpl::true_)
  141. {
  142. return ranked_index_lower_bound_rank(top,y,key,x,comp,mpl::false_());
  143. }
  144. template<
  145. typename Node,typename KeyFromValue,
  146. typename CompatibleKey,typename CompatibleCompare
  147. >
  148. inline typename Node::size_type ranked_index_lower_bound_rank(
  149. Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
  150. const CompatibleCompare& comp,mpl::false_)
  151. {
  152. typedef typename Node::size_type size_type;
  153. if(!top)return 0;
  154. size_type s=top->impl()->size;
  155. do{
  156. if(!comp(key(top->value()),x)){
  157. y=top;
  158. s-=ranked_node_size(y->right())+1;
  159. top=Node::from_impl(top->left());
  160. }
  161. else top=Node::from_impl(top->right());
  162. }while(top);
  163. return s;
  164. }
  165. template<
  166. typename Node,typename KeyFromValue,
  167. typename CompatibleKey,typename CompatibleCompare
  168. >
  169. inline typename Node::size_type ranked_index_upper_bound_rank(
  170. Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
  171. const CompatibleCompare& comp)
  172. {
  173. typedef typename KeyFromValue::result_type key_type;
  174. return ranked_index_upper_bound_rank(
  175. top,y,key,x,comp,
  176. promotes_1st_arg<CompatibleCompare,CompatibleKey,key_type>());
  177. }
  178. template<
  179. typename Node,typename KeyFromValue,
  180. typename CompatibleCompare
  181. >
  182. inline typename Node::size_type ranked_index_upper_bound_rank(
  183. Node* top,Node* y,const KeyFromValue& key,
  184. const BOOST_DEDUCED_TYPENAME KeyFromValue::result_type& x,
  185. const CompatibleCompare& comp,mpl::true_)
  186. {
  187. return ranked_index_upper_bound_rank(top,y,key,x,comp,mpl::false_());
  188. }
  189. template<
  190. typename Node,typename KeyFromValue,
  191. typename CompatibleKey,typename CompatibleCompare
  192. >
  193. inline typename Node::size_type ranked_index_upper_bound_rank(
  194. Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
  195. const CompatibleCompare& comp,mpl::false_)
  196. {
  197. typedef typename Node::size_type size_type;
  198. if(!top)return 0;
  199. size_type s=top->impl()->size;
  200. do{
  201. if(comp(x,key(top->value()))){
  202. y=top;
  203. s-=ranked_node_size(y->right())+1;
  204. top=Node::from_impl(top->left());
  205. }
  206. else top=Node::from_impl(top->right());
  207. }while(top);
  208. return s;
  209. }
  210. template<
  211. typename Node,typename KeyFromValue,
  212. typename CompatibleKey,typename CompatibleCompare
  213. >
  214. inline std::pair<typename Node::size_type,typename Node::size_type>
  215. ranked_index_equal_range_rank(
  216. Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
  217. const CompatibleCompare& comp)
  218. {
  219. typedef typename KeyFromValue::result_type key_type;
  220. return ranked_index_equal_range_rank(
  221. top,y,key,x,comp,
  222. mpl::and_<
  223. promotes_1st_arg<CompatibleCompare,CompatibleKey,key_type>,
  224. promotes_2nd_arg<CompatibleCompare,key_type,CompatibleKey> >());
  225. }
  226. template<
  227. typename Node,typename KeyFromValue,
  228. typename CompatibleCompare
  229. >
  230. inline std::pair<typename Node::size_type,typename Node::size_type>
  231. ranked_index_equal_range_rank(
  232. Node* top,Node* y,const KeyFromValue& key,
  233. const BOOST_DEDUCED_TYPENAME KeyFromValue::result_type& x,
  234. const CompatibleCompare& comp,mpl::true_)
  235. {
  236. return ranked_index_equal_range_rank(top,y,key,x,comp,mpl::false_());
  237. }
  238. template<
  239. typename Node,typename KeyFromValue,
  240. typename CompatibleKey,typename CompatibleCompare
  241. >
  242. inline std::pair<typename Node::size_type,typename Node::size_type>
  243. ranked_index_equal_range_rank(
  244. Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
  245. const CompatibleCompare& comp,mpl::false_)
  246. {
  247. typedef typename Node::size_type size_type;
  248. if(!top)return std::pair<size_type,size_type>(0,0);
  249. size_type s=top->impl()->size;
  250. do{
  251. if(comp(key(top->value()),x)){
  252. top=Node::from_impl(top->right());
  253. }
  254. else if(comp(x,key(top->value()))){
  255. y=top;
  256. s-=ranked_node_size(y->right())+1;
  257. top=Node::from_impl(top->left());
  258. }
  259. else{
  260. return std::pair<size_type,size_type>(
  261. s-top->impl()->size+
  262. ranked_index_lower_bound_rank(
  263. Node::from_impl(top->left()),top,key,x,comp,mpl::false_()),
  264. s-ranked_node_size(top->right())+
  265. ranked_index_upper_bound_rank(
  266. Node::from_impl(top->right()),y,key,x,comp,mpl::false_()));
  267. }
  268. }while(top);
  269. return std::pair<size_type,size_type>(s,s);
  270. }
  271. } /* namespace multi_index::detail */
  272. } /* namespace multi_index */
  273. } /* namespace boost */
  274. #endif