rnd_index_node.hpp 6.2 KB

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