rnd_index_node.hpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. /* Copyright 2003-2021 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_RND_INDEX_NODE_HPP
  9. #define BOOST_MULTI_INDEX_DETAIL_RND_INDEX_NODE_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 <algorithm>
  15. #include <boost/integer/common_factor_rt.hpp>
  16. #include <boost/multi_index/detail/allocator_traits.hpp>
  17. #include <boost/multi_index/detail/raw_ptr.hpp>
  18. #include <cstddef>
  19. #include <functional>
  20. namespace boost{
  21. namespace multi_index{
  22. namespace detail{
  23. template<typename Allocator>
  24. struct random_access_index_node_impl
  25. {
  26. typedef typename rebind_alloc_for<
  27. Allocator,random_access_index_node_impl
  28. >::type node_allocator;
  29. typedef allocator_traits<node_allocator> node_alloc_traits;
  30. typedef typename node_alloc_traits::pointer pointer;
  31. typedef typename node_alloc_traits::const_pointer const_pointer;
  32. typedef typename node_alloc_traits::difference_type difference_type;
  33. typedef typename rebind_alloc_for<
  34. Allocator,pointer
  35. >::type ptr_allocator;
  36. typedef allocator_traits<ptr_allocator> ptr_alloc_traits;
  37. typedef typename ptr_alloc_traits::pointer ptr_pointer;
  38. ptr_pointer& up(){return up_;}
  39. ptr_pointer up()const{return up_;}
  40. /* interoperability with rnd_node_iterator */
  41. static void increment(pointer& x)
  42. {
  43. x=*(x->up()+1);
  44. }
  45. static void decrement(pointer& x)
  46. {
  47. x=*(x->up()-1);
  48. }
  49. static void advance(pointer& x,difference_type n)
  50. {
  51. x=*(x->up()+n);
  52. }
  53. static difference_type distance(pointer x,pointer y)
  54. {
  55. return static_cast<difference_type>(y->up()-x->up());
  56. }
  57. /* algorithmic stuff */
  58. static void relocate(ptr_pointer pos,ptr_pointer x)
  59. {
  60. pointer n=*x;
  61. if(x<pos){
  62. extract(x,pos);
  63. *(pos-1)=n;
  64. n->up()=pos-1;
  65. }
  66. else{
  67. while(x!=pos){
  68. *x=*(x-1);
  69. (*x)->up()=x;
  70. --x;
  71. }
  72. *pos=n;
  73. n->up()=pos;
  74. }
  75. };
  76. static void relocate(ptr_pointer pos,ptr_pointer first,ptr_pointer last)
  77. {
  78. ptr_pointer begin,middle,end;
  79. if(pos<first){
  80. begin=pos;
  81. middle=first;
  82. end=last;
  83. }
  84. else{
  85. begin=first;
  86. middle=last;
  87. end=pos;
  88. }
  89. std::ptrdiff_t n=end-begin;
  90. std::ptrdiff_t m=middle-begin;
  91. std::ptrdiff_t n_m=n-m;
  92. std::ptrdiff_t p=integer::gcd(n,m);
  93. for(std::ptrdiff_t i=0;i<p;++i){
  94. pointer tmp=begin[i];
  95. for(std::ptrdiff_t j=i,k;;){
  96. if(j<n_m)k=j+m;
  97. else k=j-n_m;
  98. if(k==i){
  99. *(begin+j)=tmp;
  100. (*(begin+j))->up()=begin+j;
  101. break;
  102. }
  103. else{
  104. *(begin+j)=*(begin+k);
  105. (*(begin+j))->up()=begin+j;
  106. }
  107. if(k<n_m)j=k+m;
  108. else j=k-n_m;
  109. if(j==i){
  110. *(begin+k)=tmp;
  111. (*(begin+k))->up()=begin+k;
  112. break;
  113. }
  114. else{
  115. *(begin+k)=*(begin+j);
  116. (*(begin+k))->up()=begin+k;
  117. }
  118. }
  119. }
  120. };
  121. static void extract(ptr_pointer x,ptr_pointer pend)
  122. {
  123. --pend;
  124. while(x!=pend){
  125. *x=*(x+1);
  126. (*x)->up()=x;
  127. ++x;
  128. }
  129. }
  130. static void transfer(
  131. ptr_pointer pbegin0,ptr_pointer pend0,ptr_pointer pbegin1)
  132. {
  133. while(pbegin0!=pend0){
  134. *pbegin1=*pbegin0++;
  135. (*pbegin1)->up()=pbegin1;
  136. ++pbegin1;
  137. }
  138. }
  139. static void reverse(ptr_pointer pbegin,ptr_pointer pend)
  140. {
  141. std::ptrdiff_t d=(pend-pbegin)/2;
  142. for(std::ptrdiff_t i=0;i<d;++i){
  143. std::swap(*pbegin,*--pend);
  144. (*pbegin)->up()=pbegin;
  145. (*pend)->up()=pend;
  146. ++pbegin;
  147. }
  148. }
  149. static ptr_pointer gather_nulls(
  150. ptr_pointer pbegin,ptr_pointer pend,ptr_pointer x)
  151. {
  152. for(ptr_pointer p=pbegin;p!=x;++p){
  153. if(*p){
  154. *pbegin=*p;
  155. (*pbegin)->up()=pbegin;
  156. ++pbegin;
  157. }
  158. }
  159. for(ptr_pointer p=pend;p!=x;){
  160. if(*--p){
  161. *--pend=*p;
  162. (*pend)->up()=pend;
  163. }
  164. }
  165. return pbegin;
  166. }
  167. private:
  168. ptr_pointer up_;
  169. };
  170. template<typename Super>
  171. struct random_access_index_node_trampoline:
  172. random_access_index_node_impl<
  173. typename rebind_alloc_for<
  174. typename Super::allocator_type,
  175. char
  176. >::type
  177. >
  178. {
  179. typedef random_access_index_node_impl<
  180. typename rebind_alloc_for<
  181. typename Super::allocator_type,
  182. char
  183. >::type
  184. > impl_type;
  185. };
  186. template<typename Super>
  187. struct random_access_index_node:
  188. Super,random_access_index_node_trampoline<Super>
  189. {
  190. private:
  191. typedef random_access_index_node_trampoline<Super> trampoline;
  192. public:
  193. typedef typename trampoline::impl_type impl_type;
  194. typedef typename trampoline::pointer impl_pointer;
  195. typedef typename trampoline::const_pointer const_impl_pointer;
  196. typedef typename trampoline::difference_type difference_type;
  197. typedef typename trampoline::ptr_pointer impl_ptr_pointer;
  198. impl_ptr_pointer& up(){return trampoline::up();}
  199. impl_ptr_pointer up()const{return trampoline::up();}
  200. impl_pointer impl()
  201. {
  202. return static_cast<impl_pointer>(
  203. static_cast<impl_type*>(static_cast<trampoline*>(this)));
  204. }
  205. const_impl_pointer impl()const
  206. {
  207. return static_cast<const_impl_pointer>(
  208. static_cast<const impl_type*>(static_cast<const trampoline*>(this)));
  209. }
  210. static random_access_index_node* from_impl(impl_pointer x)
  211. {
  212. return
  213. static_cast<random_access_index_node*>(
  214. static_cast<trampoline*>(
  215. raw_ptr<impl_type*>(x)));
  216. }
  217. static const random_access_index_node* from_impl(const_impl_pointer x)
  218. {
  219. return
  220. static_cast<const random_access_index_node*>(
  221. static_cast<const trampoline*>(
  222. raw_ptr<const impl_type*>(x)));
  223. }
  224. /* interoperability with rnd_node_iterator */
  225. static void increment(random_access_index_node*& x)
  226. {
  227. impl_pointer xi=x->impl();
  228. trampoline::increment(xi);
  229. x=from_impl(xi);
  230. }
  231. static void decrement(random_access_index_node*& x)
  232. {
  233. impl_pointer xi=x->impl();
  234. trampoline::decrement(xi);
  235. x=from_impl(xi);
  236. }
  237. static void advance(random_access_index_node*& x,difference_type n)
  238. {
  239. impl_pointer xi=x->impl();
  240. trampoline::advance(xi,n);
  241. x=from_impl(xi);
  242. }
  243. static difference_type distance(
  244. random_access_index_node* x,random_access_index_node* y)
  245. {
  246. return trampoline::distance(x->impl(),y->impl());
  247. }
  248. };
  249. } /* namespace multi_index::detail */
  250. } /* namespace multi_index */
  251. } /* namespace boost */
  252. #endif