rnd_index_node.hpp 6.4 KB

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