epoc32/include/stdapis/boost/multi_index/detail/rnd_index_node.hpp
author William Roberts <williamr@symbian.org>
Wed, 31 Mar 2010 12:27:01 +0100
branchSymbian2
changeset 3 e1b950c65cb4
permissions -rw-r--r--
Attempt to represent the S^2->S^3 header reorganisation as a series of "hg rename" operations
     1 /* Copyright 2003-2006 Joaquín M López Muñoz.
     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 
     9 #ifndef BOOST_MULTI_INDEX_DETAIL_RND_INDEX_NODE_HPP
    10 #define BOOST_MULTI_INDEX_DETAIL_RND_INDEX_NODE_HPP
    11 
    12 #if defined(_MSC_VER)&&(_MSC_VER>=1200)
    13 #pragma once
    14 #endif
    15 
    16 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
    17 #include <algorithm>
    18 #include <boost/math/common_factor_rt.hpp>
    19 #include <cstddef>
    20 #include <functional>
    21 
    22 namespace boost{
    23 
    24 namespace multi_index{
    25 
    26 namespace detail{
    27 
    28 struct random_access_index_node_impl
    29 {
    30   random_access_index_node_impl**& up(){return up_;}
    31   random_access_index_node_impl**  up()const{return up_;}
    32 
    33   /* interoperability with rnd_node_iterator */
    34 
    35   static void increment(random_access_index_node_impl*& x)
    36   {
    37     x=*(x->up()+1);
    38   }
    39 
    40   static void decrement(random_access_index_node_impl*& x)
    41   {
    42     x=*(x->up()-1);
    43   }
    44 
    45   static void advance(
    46     random_access_index_node_impl*& x,std::ptrdiff_t n)
    47   {
    48     x=*(x->up()+n);
    49   }
    50 
    51   static std::ptrdiff_t distance(
    52     random_access_index_node_impl* x,random_access_index_node_impl* y)
    53   {
    54     return y->up()-x->up();
    55   }
    56 
    57   /* algorithmic stuff */
    58 
    59   static void relocate(
    60     random_access_index_node_impl** pos,
    61     random_access_index_node_impl** x)
    62   {
    63     random_access_index_node_impl* n=*x;
    64     if(x<pos){
    65       extract(x,pos);
    66       *(pos-1)=n;
    67       n->up()=pos-1;
    68     }
    69     else{
    70       while(x!=pos){
    71         *x=*(x-1);
    72         (*x)->up()=x;
    73         --x;
    74       }
    75       *pos=n;
    76       n->up()=pos;
    77     }
    78   };
    79 
    80   static void relocate(
    81     random_access_index_node_impl** pos,
    82     random_access_index_node_impl** first,
    83     random_access_index_node_impl** last)
    84   {
    85     random_access_index_node_impl** begin,**middle,**end;
    86     if(pos<first){
    87       begin=pos;
    88       middle=first;
    89       end=last;
    90     }
    91     else{
    92       begin=first;
    93       middle=last;
    94       end=pos;
    95     }
    96 
    97     std::ptrdiff_t n=end-begin;
    98     std::ptrdiff_t m=middle-begin;
    99     std::ptrdiff_t n_m=n-m;
   100     std::ptrdiff_t p=math::gcd(n,m);
   101 
   102     for(std::ptrdiff_t i=0;i<p;++i){
   103       random_access_index_node_impl* tmp=begin[i];
   104       for(std::ptrdiff_t j=i,k;;){
   105         if(j<n_m)k=j+m;
   106         else     k=j-n_m;
   107         if(k==i){
   108           begin[j]=tmp;
   109           begin[j]->up()=&begin[j];
   110           break;
   111         }
   112         else{
   113           begin[j]=begin[k];
   114           begin[j]->up()=&begin[j];
   115         }
   116 
   117         if(k<n_m)j=k+m;
   118         else     j=k-n_m;
   119         if(j==i){
   120           begin[k]=tmp;
   121           begin[k]->up()=&begin[k];
   122           break;
   123         }
   124         else{
   125           begin[k]=begin[j];
   126           begin[k]->up()=&begin[k];
   127         }
   128       }
   129     }
   130   };
   131 
   132   static void extract(
   133     random_access_index_node_impl** x,
   134     random_access_index_node_impl** pend)
   135   {
   136     --pend;
   137     while(x!=pend){
   138       *x=*(x+1);
   139       (*x)->up()=x;
   140       ++x;
   141     }
   142   }
   143 
   144   static void transfer(
   145     random_access_index_node_impl** pbegin0,
   146     random_access_index_node_impl** pend0,
   147     random_access_index_node_impl** pbegin1)
   148   {
   149     while(pbegin0!=pend0){
   150       *pbegin1=*pbegin0++;
   151       (*pbegin1)->up()=pbegin1;
   152       ++pbegin1;
   153     }
   154   }
   155 
   156   static void reverse(
   157     random_access_index_node_impl** pbegin,
   158     random_access_index_node_impl** pend)
   159   {
   160     std::ptrdiff_t d=(pend-pbegin)/2;
   161     for(std::ptrdiff_t i=0;i<d;++i){
   162       std::swap(*pbegin,*--pend);
   163       (*pbegin)->up()=pbegin;
   164       (*pend)->up()=pend;
   165       ++pbegin;
   166     }
   167   }
   168 
   169 private:
   170   random_access_index_node_impl** up_;
   171 };
   172 
   173 template<typename Super>
   174 struct random_access_index_node_trampoline:random_access_index_node_impl{};
   175 
   176 template<typename Super>
   177 struct random_access_index_node:
   178   Super,random_access_index_node_trampoline<Super>
   179 {
   180   random_access_index_node_impl**& up(){return impl_type::up();}
   181   random_access_index_node_impl**  up()const{return impl_type::up();}
   182 
   183   random_access_index_node_impl*       impl()
   184     {return static_cast<impl_type*>(this);}
   185   const random_access_index_node_impl* impl()const
   186     {return static_cast<const impl_type*>(this);}
   187 
   188   static random_access_index_node* from_impl(random_access_index_node_impl *x)
   189   {
   190     return static_cast<random_access_index_node*>(
   191       static_cast<impl_type*>(x));
   192   }
   193 
   194   static const random_access_index_node* from_impl(
   195     const random_access_index_node_impl* x)
   196   {
   197     return static_cast<const random_access_index_node*>(
   198       static_cast<const impl_type*>(x));
   199   }
   200 
   201   /* interoperability with rnd_node_iterator */
   202 
   203   static void increment(random_access_index_node*& x)
   204   {
   205     random_access_index_node_impl* xi=x->impl();
   206     impl_type::increment(xi);
   207     x=from_impl(xi);
   208   }
   209 
   210   static void decrement(random_access_index_node*& x)
   211   {
   212     random_access_index_node_impl* xi=x->impl();
   213     impl_type::decrement(xi);
   214     x=from_impl(xi);
   215   }
   216 
   217   static void advance(random_access_index_node*& x,std::ptrdiff_t n)
   218   {
   219     random_access_index_node_impl* xi=x->impl();
   220     impl_type::advance(xi,n);
   221     x=from_impl(xi);
   222   }
   223 
   224   static std::ptrdiff_t distance(
   225     random_access_index_node* x,random_access_index_node* y)
   226   {
   227     return impl_type::distance(x->impl(),y->impl());
   228   }
   229 
   230 private:
   231   typedef random_access_index_node_trampoline<Super> impl_type;
   232 };
   233 
   234 } /* namespace multi_index::detail */
   235 
   236 } /* namespace multi_index */
   237 
   238 } /* namespace boost */
   239 
   240 #endif