rnd_index_node.hpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  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_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. private:
  150. ptr_pointer up_;
  151. };
  152. template<typename Super>
  153. struct random_access_index_node_trampoline:
  154. random_access_index_node_impl<
  155. typename rebind_alloc_for<
  156. typename Super::allocator_type,
  157. char
  158. >::type
  159. >
  160. {
  161. typedef random_access_index_node_impl<
  162. typename rebind_alloc_for<
  163. typename Super::allocator_type,
  164. char
  165. >::type
  166. > impl_type;
  167. };
  168. template<typename Super>
  169. struct random_access_index_node:
  170. Super,random_access_index_node_trampoline<Super>
  171. {
  172. private:
  173. typedef random_access_index_node_trampoline<Super> trampoline;
  174. public:
  175. typedef typename trampoline::impl_type impl_type;
  176. typedef typename trampoline::pointer impl_pointer;
  177. typedef typename trampoline::const_pointer const_impl_pointer;
  178. typedef typename trampoline::difference_type difference_type;
  179. typedef typename trampoline::ptr_pointer impl_ptr_pointer;
  180. impl_ptr_pointer& up(){return trampoline::up();}
  181. impl_ptr_pointer up()const{return trampoline::up();}
  182. impl_pointer impl()
  183. {
  184. return static_cast<impl_pointer>(
  185. static_cast<impl_type*>(static_cast<trampoline*>(this)));
  186. }
  187. const_impl_pointer impl()const
  188. {
  189. return static_cast<const_impl_pointer>(
  190. static_cast<const impl_type*>(static_cast<const trampoline*>(this)));
  191. }
  192. static random_access_index_node* from_impl(impl_pointer x)
  193. {
  194. return
  195. static_cast<random_access_index_node*>(
  196. static_cast<trampoline*>(
  197. raw_ptr<impl_type*>(x)));
  198. }
  199. static const random_access_index_node* from_impl(const_impl_pointer x)
  200. {
  201. return
  202. static_cast<const random_access_index_node*>(
  203. static_cast<const trampoline*>(
  204. raw_ptr<const impl_type*>(x)));
  205. }
  206. /* interoperability with rnd_node_iterator */
  207. static void increment(random_access_index_node*& x)
  208. {
  209. impl_pointer xi=x->impl();
  210. trampoline::increment(xi);
  211. x=from_impl(xi);
  212. }
  213. static void decrement(random_access_index_node*& x)
  214. {
  215. impl_pointer xi=x->impl();
  216. trampoline::decrement(xi);
  217. x=from_impl(xi);
  218. }
  219. static void advance(random_access_index_node*& x,difference_type n)
  220. {
  221. impl_pointer xi=x->impl();
  222. trampoline::advance(xi,n);
  223. x=from_impl(xi);
  224. }
  225. static difference_type distance(
  226. random_access_index_node* x,random_access_index_node* y)
  227. {
  228. return trampoline::distance(x->impl(),y->impl());
  229. }
  230. };
  231. } /* namespace multi_index::detail */
  232. } /* namespace multi_index */
  233. } /* namespace boost */
  234. #endif