SDSL: Succinct Data Structure Library
A C++ template library for succinct data structures
 All Classes Namespaces Files Functions Variables Typedefs Friends
sdsl/include/sdsl/select_support_mcl.hpp
Go to the documentation of this file.
00001 /* sdsl - succinct data structures library
00002     Copyright (C) 2008 Simon Gog
00003 
00004     This program is free software: you can redistribute it and/or modify
00005     it under the terms of the GNU General Public License as published by
00006     the Free Software Foundation, either version 3 of the License, or
00007     (at your option) any later version.
00008 
00009     This program is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012     GNU General Public License for more details.
00013 
00014     You should have received a copy of the GNU General Public License
00015     along with this program.  If not, see http://www.gnu.org/licenses/ .
00016 */
00021 #ifndef INCLUDED_SDSL_SELECT_SUPPORT_JMC
00022 #define INCLUDED_SDSL_SELECT_SUPPORT_JMC
00023 
00024 #include "int_vector.hpp"
00025 #include "select_support.hpp"
00026 
00027 //#define SDSL_DEBUG_SELECT_SUPPORT_JMC
00028 
00029 #ifdef SDSL_DEBUG_SELECT_SUPPORT_JMC
00030 #include "testutils.hpp"
00031 #endif
00032 
00034 namespace sdsl
00035 {
00036 
00037 
00038 template<uint8_t bit_pattern, uint8_t pattern_len>
00039 struct select_support_mcl_trait {
00040     typedef select_support::size_type   size_type;
00041 
00042     /* Count the number of arguments for the specific select support */
00043     static size_type arg_cnt(const bit_vector&) {
00044         return 0;
00045     }
00046 
00047     static size_type args_in_the_first_word(uint64_t, uint8_t, uint64_t) {
00048         return 0;
00049     }
00050 
00051     static size_type ith_arg_pos_in_the_first_word(uint64_t, size_type, uint8_t, uint64_t) {
00052         return 0;
00053     }
00054 
00055     static size_type args_in_the_word(uint64_t, uint64_t&) {
00056         return 0;
00057     }
00058 
00059     static size_type ith_arg_pos_in_the_word(uint64_t, size_type, uint64_t) {
00060         return 0;
00061     }
00062 
00063     static bool found_arg(size_type, const bit_vector&) {
00064         return 0;
00065     }
00066 
00067     static uint64_t init_carry(const uint64_t*, size_type) {
00068         return 0;
00069     }
00070     static uint64_t get_carry(uint64_t) {
00071         return 0;
00072     }
00073 };
00074 
00075 template<>
00076 struct select_support_mcl_trait<0,1> {
00077     typedef select_support::size_type   size_type;
00078 
00079     static size_type arg_cnt(const bit_vector& v) {
00080         return v.bit_size()-util::get_one_bits(v);
00081     }
00082 
00083     static size_type args_in_the_first_word(uint64_t w, uint8_t offset, uint64_t) {
00084         return bit_magic::b1Cnt((~w)& bit_magic::Li0Mask[offset]);
00085     }
00086 
00087     static size_type ith_arg_pos_in_the_first_word(uint64_t w, size_type i, uint8_t offset, uint64_t) {
00088         return bit_magic::i1BP(~w & bit_magic::Li0Mask[offset], i);
00089     }
00090     static size_type args_in_the_word(uint64_t w, uint64_t&) {
00091         return bit_magic::b1Cnt(~w);
00092     }
00093     static size_type ith_arg_pos_in_the_word(uint64_t w, size_type i, uint64_t) {
00094         return bit_magic::i1BP(~w, i);
00095     }
00096     static bool found_arg(size_type i, const bit_vector& v) {
00097         return !v[i];
00098     }
00099     static uint64_t init_carry(const uint64_t*, size_type) {
00100         return 0;
00101     }
00102     static uint64_t get_carry(uint64_t) {
00103         return 0;
00104     }
00105 };
00106 
00107 template<>
00108 struct select_support_mcl_trait<1,1> {
00109     typedef select_support::size_type   size_type;
00110 
00111     /* Count the number of arguments for the specific select support */
00112     static size_type arg_cnt(const bit_vector& v) {
00113         return util::get_one_bits(v);
00114     }
00115 
00116     static size_type args_in_the_first_word(uint64_t w, uint8_t offset, uint64_t) {
00117         return bit_magic::b1Cnt(w & bit_magic::Li0Mask[offset]);
00118     }
00119 
00120     static size_type ith_arg_pos_in_the_first_word(uint64_t w, size_type i, uint8_t offset, uint64_t) {
00121         return bit_magic::i1BP(w & bit_magic::Li0Mask[offset], i);
00122     }
00123 
00124     static size_type args_in_the_word(uint64_t w, uint64_t&) {
00125         return bit_magic::b1Cnt(w);
00126     }
00127 
00128     static size_type ith_arg_pos_in_the_word(uint64_t w, size_type i, uint64_t) {
00129         return bit_magic::i1BP(w, i);
00130     }
00131 
00132     static bool found_arg(size_type i, const bit_vector& v) {
00133         return v[i];
00134     }
00135 
00136     static uint64_t init_carry(const uint64_t*, size_type) {
00137         return 0;
00138     }
00139     static uint64_t get_carry(uint64_t) {
00140         return 0;
00141     }
00142 };
00143 
00144 template<>
00145 struct select_support_mcl_trait<10,2> {
00146     typedef select_support::size_type   size_type;
00147 
00148     /* Count the number of arguments for the specific select support */
00149     static size_type arg_cnt(const bit_vector& v) {
00150         return util::get_onezero_bits(v);
00151     }
00152 
00153     static size_type args_in_the_first_word(uint64_t w, uint8_t offset, uint64_t carry) {
00154         return bit_magic::b1Cnt(bit_magic::b10Map(w, carry) & bit_magic::Li0Mask[offset]);
00155     }
00156 
00157     static size_type ith_arg_pos_in_the_first_word(uint64_t w, size_type i, uint8_t offset, uint64_t carry) {
00158         return bit_magic::i1BP(bit_magic::b10Map(w, carry) & bit_magic::Li0Mask[offset], i);
00159     }
00160 
00161     static size_type args_in_the_word(uint64_t w, uint64_t& carry) {
00162         return bit_magic::b10Cnt(w, carry);
00163     }
00164 
00165     static size_type ith_arg_pos_in_the_word(uint64_t w, size_type i, uint64_t carry) {
00166         return bit_magic::i1BP(bit_magic::b10Map(w, carry), i);
00167     }
00168 
00169     static bool found_arg(size_type i, const bit_vector& v) {
00170         if (i > 0 and v[i-1] and !v[i])
00171             return true;
00172         return false;
00173     }
00174 
00175     static uint64_t init_carry(const uint64_t* data, size_type word_pos) {
00176         return word_pos ? (*(data-1)>>63) : 0;
00177     }
00178     static uint64_t get_carry(uint64_t w) {
00179         return w>>63;
00180     }
00181 };
00182 
00183 template<>
00184 struct select_support_mcl_trait<01,2> {
00185     typedef select_support::size_type   size_type;
00186 
00187     /* Count the number of arguments for the specific select support */
00188     static size_type arg_cnt(const bit_vector& v) {
00189         return util::get_zeroone_bits(v);
00190     }
00191 
00192     static size_type args_in_the_first_word(uint64_t w, uint8_t offset, uint64_t carry) {
00193         return bit_magic::b1Cnt(bit_magic::b01Map(w, carry) & bit_magic::Li0Mask[offset]);
00194     }
00195 
00196     static size_type ith_arg_pos_in_the_first_word(uint64_t w, size_type i, uint8_t offset, uint64_t carry) {
00197         return bit_magic::i1BP(bit_magic::b01Map(w, carry) & bit_magic::Li0Mask[offset], i);
00198     }
00199 
00200     static size_type args_in_the_word(uint64_t w, uint64_t& carry) {
00201         return bit_magic::b01Cnt(w, carry);
00202     }
00203 
00204     static size_type ith_arg_pos_in_the_word(uint64_t w, size_type i, uint64_t carry) {
00205         return bit_magic::i1BP(bit_magic::b01Map(w, carry), i);
00206     }
00207 
00208     static bool found_arg(size_type i, const bit_vector& v) {
00209         if (i > 0 and !v[i-1] and v[i])
00210             return true;
00211         return false;
00212     }
00213 
00214     static uint64_t init_carry(const uint64_t* data, size_type word_pos) {
00215         return word_pos ? (*(data-1)>>63) : 1;
00216     }
00217     static uint64_t get_carry(uint64_t w) {
00218         return w>>63;
00219     }
00220 };
00221 
00222 
00224 
00246 template<uint8_t b=1, uint8_t pattern_len=1>
00247 class select_support_mcl : public select_support
00248 {
00249     public:
00250         typedef bit_vector bit_vector_type;
00251     private:
00252         uint32_t m_logn, m_logn2, m_logn4; // log(size of the supported bit_vector), logn2=\f$ (\log n)^2\f$, \f$logn4=(\log n)^4\f$
00253         int_vector<0> m_superblock;        // there exists \f$\frac{n}{4096} < \frac{n}{\log n}\f$ entries
00254         // entry i equals the answer to select_1(B,i*4096)
00255         int_vector<0>* m_longsuperblock;
00256         int_vector<0>* m_miniblock;
00257         size_type m_arg_cnt;
00258         void copy(const select_support_mcl<b, pattern_len>& ss);
00259         void construct();
00260         void initData();
00261         void init_fast(const int_vector<1>* v=NULL);
00262     public:
00263         explicit select_support_mcl(const int_vector<1>* v=NULL);
00264         select_support_mcl(const select_support_mcl<b,pattern_len>& ss);
00265         ~select_support_mcl();
00266         void init(const int_vector<1>* v=NULL);
00267         void init_slow(const int_vector<1>* v=NULL);
00269 
00271         inline const size_type select(size_type i) const;
00273         inline const size_type operator()(size_type i)const;
00274         size_type serialize(std::ostream& out, structure_tree_node* v=NULL, std::string name="")const;
00275         void load(std::istream& in, const int_vector<1>* v=NULL);
00276         void set_vector(const int_vector<1>* v=NULL);
00277         select_support_mcl<b, pattern_len>& operator=(const select_support_mcl& ss);
00278 
00280 
00282         void swap(select_support_mcl<b, pattern_len>& ss);
00284 
00288         bool operator==(const select_support_mcl<b, pattern_len>& ss)const;
00290 
00294         bool operator!=(const select_support_mcl<b, pattern_len>& ss)const;
00295 };
00296 
00297 
00298 template<uint8_t b, uint8_t pattern_len>
00299 void select_support_mcl<b,pattern_len>::construct()
00300 {
00301     m_longsuperblock    = NULL;
00302     m_miniblock                 = NULL;
00303     m_arg_cnt                   = 0;
00304 }
00305 
00306 template<uint8_t b, uint8_t pattern_len>
00307 select_support_mcl<b,pattern_len>::select_support_mcl(const int_vector<1>* f_v):select_support(f_v)
00308 {
00309     construct();
00310     init(f_v);
00311 }
00312 
00313 template<uint8_t b, uint8_t pattern_len>
00314 select_support_mcl<b,pattern_len>::select_support_mcl(const select_support_mcl& ss):select_support(ss.m_v)
00315 {
00316     construct();
00317     copy(ss);
00318 }
00319 
00320 template<uint8_t b, uint8_t pattern_len>
00321 select_support_mcl<b, pattern_len>& select_support_mcl<b,pattern_len>::operator=(const select_support_mcl& ss)
00322 {
00323     if (this != &ss) {
00324         copy(ss);
00325     }
00326     return *this;
00327 }
00328 
00329 template<uint8_t b, uint8_t pattern_len>
00330 void select_support_mcl<b,pattern_len>::swap(select_support_mcl& ss)
00331 {
00332     std::swap(m_logn, ss.m_logn);
00333     std::swap(m_logn2, ss.m_logn2);
00334     std::swap(m_logn4, ss.m_logn4);
00335     m_superblock.swap(ss.m_superblock);
00336     std::swap(m_longsuperblock, ss.m_longsuperblock);
00337     std::swap(m_miniblock, ss.m_miniblock);
00338     std::swap(m_arg_cnt, ss.m_arg_cnt);
00339 //      std::swap(m_v, ss.m_v); // see rank_support_v swap.
00340 }
00341 
00342 template<uint8_t b, uint8_t pattern_len>
00343 void select_support_mcl<b,pattern_len>::copy(const select_support_mcl<b, pattern_len>& ss)
00344 {
00345     m_logn                      = ss.m_logn;            // copy log n
00346     m_logn2                     = ss.m_logn2;           // copy (logn)^2
00347     m_logn4                     = ss.m_logn4;           // copy (logn)^4
00348     m_superblock        = ss.m_superblock;  // copy long superblock
00349     m_arg_cnt           = ss.m_arg_cnt;     // copy count of 1-bits
00350     m_v                         = ss.m_v;                   // copy pointer to the supported bit vector
00351     size_type sb        = (m_arg_cnt+4095)>>12;
00352     if (m_longsuperblock!=NULL)
00353         delete [] m_longsuperblock;
00354     m_longsuperblock = NULL;
00355     if (ss.m_longsuperblock!=NULL) {
00356         m_longsuperblock = new int_vector<0>[sb]; //copy longsuperblocks
00357         for (size_type i=0; i<sb; ++i) {
00358             m_longsuperblock[i] = ss.m_longsuperblock[i];
00359         }
00360     }
00361     if (m_miniblock!=NULL)
00362         delete [] m_miniblock;
00363     m_miniblock = NULL;
00364     if (ss.m_miniblock!=NULL) {
00365         m_miniblock = new int_vector<0>[sb]; // copy miniblocks
00366         for (size_type i=0; i<sb; ++i) {
00367             m_miniblock[i] = ss.m_miniblock[i];
00368         }
00369     }
00370 }
00371 
00372 template<uint8_t b, uint8_t pattern_len>
00373 select_support_mcl<b,pattern_len>::~select_support_mcl()
00374 {
00375     if (m_longsuperblock!=NULL)
00376         delete[] m_longsuperblock;
00377     if (m_miniblock!=NULL)
00378         delete[] m_miniblock;
00379 }
00380 
00381 template<uint8_t b, uint8_t pattern_len>
00382 void select_support_mcl<b,pattern_len>::init_slow(const int_vector<1>* v)
00383 {
00384     set_vector(v);
00385     initData();
00386     if (m_v==NULL)
00387         return;
00388 #ifdef SDSL_DEBUG_SELECT_SUPPORT_JMC
00389     stop_watch sw;
00390     sw.start();
00391 #endif
00392     // Count the number of arguments in the bit vector
00393     m_arg_cnt = select_support_mcl_trait<b,pattern_len>::arg_cnt(*v);
00394 #ifdef SDSL_DEBUG_SELECT_SUPPORT_JMC
00395     sw.stop();
00396     std::cerr<<"Count arguments takes "<<sw.get_real_time()<<" ms"<<std::endl;
00397     sw.start();
00398 #endif
00399 
00400     const size_type SUPER_BLOCK_SIZE = 4096;
00401 
00402     if (m_arg_cnt==0) // if there are no arguments in the vector we are done...
00403         return;
00404 
00405     size_type sb = (m_arg_cnt+SUPER_BLOCK_SIZE-1)/SUPER_BLOCK_SIZE; // number of superblocks
00406     if (m_miniblock != NULL) delete [] m_miniblock;
00407     m_miniblock = new int_vector<0>[sb];
00408 
00409     m_superblock = int_vector<0>(sb, 0, m_logn);// TODO: hier koennte man logn noch optimieren...s
00410 
00411 
00412     size_type arg_position[SUPER_BLOCK_SIZE], arg_cnt=0;
00413     size_type sb_cnt=0;
00414     for (size_type i=0; i < v->size(); ++i) {
00415         if (select_support_mcl_trait<b,pattern_len>::found_arg(i, *v)) {
00416             arg_position[ arg_cnt%SUPER_BLOCK_SIZE ] = i;
00417             assert(arg_position[arg_cnt%SUPER_BLOCK_SIZE] == i);
00418             ++arg_cnt;
00419             if (arg_cnt % SUPER_BLOCK_SIZE == 0 or arg_cnt == m_arg_cnt) { //
00420                 assert(sb_cnt < sb);
00421                 m_superblock[sb_cnt] = arg_position[0];
00422 
00423                 size_type pos_diff = arg_position[(arg_cnt-1)%SUPER_BLOCK_SIZE]-arg_position[0];
00424                 if (pos_diff > m_logn4) { // longblock
00425                     if (m_longsuperblock == NULL) m_longsuperblock = new int_vector<0>[sb]; // create longsuperblock
00426                     m_longsuperblock[sb_cnt] = int_vector<0>(SUPER_BLOCK_SIZE, 0, bit_magic::l1BP(arg_position[(arg_cnt-1)%SUPER_BLOCK_SIZE]) + 1);
00427 
00428                     for (size_type j=0; j <= (arg_cnt-1)%SUPER_BLOCK_SIZE ; ++j) m_longsuperblock[sb_cnt][j] = arg_position[j]; // copy argument positions to longsuperblock
00429                 } else { // short block
00430                     m_miniblock[sb_cnt] = int_vector<0>(64, 0, bit_magic::l1BP(pos_diff)+1);
00431                     for (size_type j=0; j <= (arg_cnt-1)%SUPER_BLOCK_SIZE; j+=64) {
00432                         m_miniblock[sb_cnt][j/64] = arg_position[j]-arg_position[0];
00433                     }
00434                 }
00435                 ++sb_cnt;
00436             }
00437         }
00438     }
00439 //      std::cout<<"m_superblock[0]="<<m_superblock[0]<<std::endl;
00440 //      std::cout<<"sb_cnt="<<sb_cnt<<std::endl;
00441 //      std::cout<<"arg_position[0]="<<arg_position[0]<<std::endl;
00442 #ifdef SDSL_DEBUG_SELECT_SUPPORT_JMC
00443     sw.stop();
00444     std::cerr<<"Init tables  takes "<<sw.get_real_time()<<" ms"<<std::endl;
00445 #endif
00446 }
00447 
00448 // TODO: find bug, detected by valgrind
00449 template<uint8_t b, uint8_t pattern_len>
00450 void select_support_mcl<b,pattern_len>::init_fast(const int_vector<1>* v)
00451 {
00452     set_vector(v);
00453     initData();
00454     if (m_v==NULL)
00455         return;
00456 //#define SDSL_DEBUG_SELECT_SUPPORT_JMC
00457 #ifdef SDSL_DEBUG_SELECT_SUPPORT_JMC
00458     stop_watch sw;
00459     sw.start();
00460 #endif
00461     // Count the number of arguments in the bit vector
00462     m_arg_cnt = select_support_mcl_trait<b,pattern_len>::arg_cnt(*v);
00463 #ifdef SDSL_DEBUG_SELECT_SUPPORT_JMC
00464     sw.stop();
00465     std::cerr<<"Count arguments takes "<<sw.get_real_time()<<" ms"<<std::endl;
00466     std::cerr<<"m_arg_cnt="<<m_arg_cnt<<std::endl;
00467     sw.start();
00468 #endif
00469 
00470     const size_type SUPER_BLOCK_SIZE = 64*64;
00471 
00472     if (m_arg_cnt==0) // if there are no arguments in the vector we are done...
00473         return;
00474 
00475 //      size_type sb = (m_arg_cnt+63+SUPER_BLOCK_SIZE-1)/SUPER_BLOCK_SIZE; // number of superblocks, add 63 as the last block could contain 63 uninitialized bits
00476     size_type sb = (m_arg_cnt+SUPER_BLOCK_SIZE-1)/SUPER_BLOCK_SIZE; // number of superblocks
00477     if (m_miniblock != NULL) delete [] m_miniblock;
00478     m_miniblock = new int_vector<0>[sb];
00479 
00480     m_superblock = int_vector<0>(sb, 0, m_logn);// TODO: hier koennte man logn noch optimieren...s
00481 
00482 #ifdef SDSL_DEBUG_SELECT_SUPPORT_JMC
00483     std::cerr<<"H1"<<std::endl;
00484 #endif
00485 
00486     bit_vector::size_type arg_position[SUPER_BLOCK_SIZE];
00487     const uint64_t* data = v->data();
00488     uint64_t carry_new=0;
00489     size_type last_k64 = 1, sb_cnt=0;
00490     for (size_type i=0, cnt_old=0, cnt_new=0, last_k64_sum=1; i < v->capacity(); i+=64, ++data) {
00491         cnt_new += select_support_mcl_trait<b, pattern_len>::args_in_the_word(*data, carry_new);
00492         if (cnt_new >= last_k64_sum) {
00493             arg_position[last_k64-1] = i + select_support_mcl_trait<b, pattern_len>::ith_arg_pos_in_the_word(*data, last_k64_sum  - cnt_old, carry_new);
00494             last_k64 += 64;
00495             last_k64_sum += 64;
00496 
00497             if (last_k64 == SUPER_BLOCK_SIZE+1) {
00498                 m_superblock[sb_cnt] = arg_position[0];
00499                 size_type pos_of_last_arg_in_the_block = arg_position[last_k64-65];
00500 
00501                 for (size_type i=arg_position[last_k64-65]+1, j=last_k64-65; i < v->size() and j < SUPER_BLOCK_SIZE; ++i)
00502                     if (select_support_mcl_trait<b,pattern_len>::found_arg(i, *v)) {
00503                         pos_of_last_arg_in_the_block = i;
00504                         ++j;
00505                     }
00506                 size_type pos_diff = pos_of_last_arg_in_the_block - arg_position[0];
00507                 if (pos_diff > m_logn4) { // long block
00508                     if (m_longsuperblock == NULL) m_longsuperblock = new int_vector<0>[sb+1]; // create longsuperblock
00509                     // GEANDERT am 2010-07-17 +1 nach pos_of_last_arg..
00510                     m_longsuperblock[sb_cnt] = int_vector<0>(SUPER_BLOCK_SIZE, 0, bit_magic::l1BP(pos_of_last_arg_in_the_block) + 1);
00511                     for (size_type j=arg_position[0], k=0; j < pos_of_last_arg_in_the_block; ++j)
00512                         if (select_support_mcl_trait<b, pattern_len>::found_arg(j, *v)) {
00513 //                                                      if(k>=SUPER_BLOCK_SIZE){
00514 //                                                              std::cout<<"k="<<k<<" SUPER_BLOCK_SIZE="<<SUPER_BLOCK_SIZE<<std::endl;
00515 //                                                      }
00516                             m_longsuperblock[sb_cnt][k++] = j;
00517                         }
00518                 } else {
00519                     m_miniblock[sb_cnt] = int_vector<0>(64, 0, bit_magic::l1BP(pos_diff)+1);
00520                     for (size_type j=0; j < SUPER_BLOCK_SIZE; j+=64) {
00521                         m_miniblock[sb_cnt][j/64] = arg_position[j]-arg_position[0];
00522                     }
00523                 }
00524                 ++sb_cnt;
00525                 last_k64 = 1;
00526             }
00527         }
00528         cnt_old = cnt_new;
00529     }
00530     // TODO: handle last block!!! einfach ein longsuperblock anhaengen?
00531     if (last_k64 > 1) {
00532         // GEANDERT am 2010-09-27 +1 nach sb, da wir den superblock extra zu den existierenden anhaengen koennen
00533         if (m_longsuperblock == NULL) m_longsuperblock = new int_vector<0>[sb+1]; // create longsuperblock
00534         m_longsuperblock[sb_cnt] = int_vector<0>(SUPER_BLOCK_SIZE, 0, bit_magic::l1BP(v->size()-1) + 1);
00535         for (size_type i=arg_position[0],k=0; i < v->size(); ++i) {
00536             if (select_support_mcl_trait<b, pattern_len>::found_arg(i, *v)) {
00537                 m_longsuperblock[sb_cnt][k++] = i;
00538             }
00539         }
00540         ++sb_cnt;
00541     }
00542 #ifdef SDSL_DEBUG_SELECT_SUPPORT_JMC
00543     sw.stop();
00544     std::cerr<<"Init tables  takes "<<sw.get_real_time()<<" ms"<<std::endl;
00545 #endif
00546 }
00547 
00548 template<uint8_t b, uint8_t pattern_len>
00549 void select_support_mcl<b,pattern_len>::init(const int_vector<1>* v)
00550 {
00551     if (pattern_len>1 or (v!=NULL and  v->size() < 100000))
00552         init_slow(v);
00553     else
00554         init_fast(v);
00555     return;
00556 }
00557 
00558 template<uint8_t b, uint8_t pattern_len>
00559 inline const typename select_support_mcl<b,pattern_len>::size_type select_support_mcl<b,pattern_len>::select(size_type i)const
00560 {
00561     assert(i > 0 and i <= m_arg_cnt);
00562 
00563     i = i-1;
00564     size_type sb_idx = i>>12;   // i/4096
00565     size_type offset = i&0xFFF; // i%4096
00566     if (m_longsuperblock!=NULL and !m_longsuperblock[sb_idx].empty()) {
00567 //              std::cout<<"i="<<i<<" sb_idx="<<sb_idx<<" offset="<<offset<<std::endl;
00568 //              std::cout<<"sb_size"<<m_longsuperblock[sb_idx].size()<<std::endl;
00569         return m_longsuperblock[sb_idx][offset];
00570     } else {
00571         if ((offset&0x3F)==0) {
00572             assert(sb_idx < m_superblock.size());
00573 //                      if( (offset>>6) >= m_miniblock[sb_idx].size() ){
00574 //                              std::cerr<<" i="<<i<<std::endl;
00575 //                              std::cerr<<" "<< (offset>>6) <<" >= "<<  m_miniblock[sb_idx].size() << std::endl;
00576 //                      }
00577             assert((offset>>6) < m_miniblock[sb_idx].size());
00578             return m_superblock[sb_idx] + m_miniblock[sb_idx][offset>>6/*/64*/];
00579         } else {
00580             i = i-(sb_idx<<12)-((offset>>6)<<6);
00581             // now i > 0 and i <= 64
00582             assert(i > 0);
00583 //std::cout<<"sb_idx="<<sb_idx<<" "<<m_superblock.size()<<std::endl;
00584 //std::cout<<"offset>>6="<< (offset>>6) << " "<<m_miniblock[sb_idx].size()<< std::endl;
00585             size_type pos = m_superblock[sb_idx] + m_miniblock[sb_idx][offset>>6] + 1;
00586 
00587             // now pos is the position from where we search for the ith argument
00588             size_type word_pos = pos>>6;
00589             size_type word_off = pos&0x3F;
00590 //if( m_v->size() < word_pos*64 ){
00591 //      std::cout<<"m_v->size()="<<m_v->size()<<" 64*word_pos="<<64*word_pos<<std::endl;
00592 //}
00593             const uint64_t* data = m_v->data() + word_pos;
00594             uint64_t carry = select_support_mcl_trait<b,pattern_len>::init_carry(data, word_pos);
00595             size_type args = select_support_mcl_trait<b,pattern_len>::args_in_the_first_word(*data, word_off, carry);
00596 
00597             if (args >= i) {
00598                 return (word_pos<<6)+select_support_mcl_trait<b,pattern_len>::ith_arg_pos_in_the_first_word(*data, i, word_off, carry);
00599             }
00600             word_pos+=1;
00601             size_type sum_args = args;
00602             carry = select_support_mcl_trait<b,pattern_len>::get_carry(*data);
00603             uint64_t old_carry = carry;
00604             args = select_support_mcl_trait<b,pattern_len>::args_in_the_word(*(++data), carry);
00605             while (sum_args + args < i) {
00606                 sum_args += args;
00607                 assert(data+1 < m_v->data() + (m_v->capacity()>>6));
00608                 old_carry = carry;
00609                 args = select_support_mcl_trait<b,pattern_len>::args_in_the_word(*(++data), carry);
00610                 word_pos+=1;
00611             }
00612             return (word_pos<<6) +
00613                    select_support_mcl_trait<b,pattern_len>::ith_arg_pos_in_the_word(*data, i-sum_args, old_carry);
00614         }
00615     }
00616 }
00617 
00618 template<uint8_t b, uint8_t pattern_len>
00619 inline const typename select_support_mcl<b,pattern_len>::size_type select_support_mcl<b,pattern_len>::operator()(size_type i)const
00620 {
00621     return select(i);
00622 }
00623 
00624 template<uint8_t b, uint8_t pattern_len>
00625 void select_support_mcl<b,pattern_len>::initData()
00626 {
00627     m_arg_cnt = 0;
00628     if (m_v==NULL) {
00629         m_logn = m_logn2 = m_logn4 = 0;
00630     } else {
00631         m_logn = bit_magic::l1BP(m_v->capacity())+1; // TODO maybe it's better here to take a max(...,12)
00632         m_logn2 = m_logn*m_logn;
00633         m_logn4 = m_logn2*m_logn2;
00634     }
00635     if (m_longsuperblock!=NULL)
00636         delete[] m_longsuperblock;
00637     m_longsuperblock  = NULL;
00638     if (m_miniblock!=NULL)
00639         delete[] m_miniblock;
00640     m_miniblock                 = NULL;
00641 }
00642 
00643 template<uint8_t b, uint8_t pattern_len>
00644 void select_support_mcl<b,pattern_len>::set_vector(const int_vector<1>* v)
00645 {
00646     m_v = v;
00647 }
00648 
00649 template<uint8_t b, uint8_t pattern_len>
00650 typename select_support_mcl<b,pattern_len>::size_type select_support_mcl<b,pattern_len>::serialize(std::ostream& out, structure_tree_node* v, std::string name)const
00651 {
00652     structure_tree_node* child = structure_tree::add_child(v, name, util::class_name(*this));
00653     size_type written_bytes = 0;
00654     // write the number of 1-bits in the supported bit_vector
00655     out.write((char*) &m_arg_cnt, sizeof(size_type)/sizeof(char));
00656     written_bytes = sizeof(size_type)/sizeof(char);
00657     // number of superblocks in the data structure
00658     size_type sb = (m_arg_cnt+4095)>>12;
00659 
00660     if (m_arg_cnt) { // if there exists 1-bits to be supported
00661         written_bytes += m_superblock.serialize(out, child, "superblock"); // serialize superblocks
00662         int_vector<1> mini_or_long;// Helper vector: mini or long block?
00663         if (m_longsuperblock!=NULL) {
00664             mini_or_long.resize(sb); // resize indicator bit_vector to the number of superblocks
00665             for (size_type i=0; i< sb; ++i)
00666                 mini_or_long[i] = !m_miniblock[i].empty();
00667         }
00668         written_bytes += mini_or_long.serialize(out, child, "mini_or_long");
00669         size_type written_bytes_long = 0;
00670         size_type written_bytes_mini = 0;
00671         for (size_type i=0; i < sb; ++i)
00672             if (!mini_or_long.empty() and !mini_or_long[i]) {
00673                 written_bytes_long += m_longsuperblock[i].serialize(out);
00674             } else {
00675                 written_bytes_mini += m_miniblock[i].serialize(out);
00676             }
00677         written_bytes += written_bytes_long;
00678         written_bytes += written_bytes_mini;
00679         structure_tree_node* child_long = structure_tree::add_child(child, "longsuperblock", util::class_name(m_longsuperblock));
00680         structure_tree::add_size(child_long, written_bytes_long);
00681         structure_tree_node* child_mini = structure_tree::add_child(child, "minisuperblock", util::class_name(m_miniblock));
00682         structure_tree::add_size(child_mini, written_bytes_mini);
00683     }
00684     structure_tree::add_size(child, written_bytes);
00685     return written_bytes;
00686 }
00687 
00688 template<uint8_t b, uint8_t pattern_len>
00689 void select_support_mcl<b,pattern_len>::load(std::istream& in, const int_vector<1>* v)
00690 {
00691     set_vector(v);
00692     initData();
00693     // read the number of 1-bits in the supported bit_vector
00694     in.read((char*) &m_arg_cnt, sizeof(size_type)/sizeof(char));
00695     size_type sb = (m_arg_cnt+4095)>>12;
00696 
00697     if (m_arg_cnt) { // if there exists 1-bits to be supported
00698         m_superblock.load(in); // load superblocks
00699 
00700         if (m_miniblock!=NULL) {
00701             delete[] m_miniblock;
00702             m_miniblock = NULL;
00703         }
00704         if (m_longsuperblock!=NULL) {
00705             delete[] m_longsuperblock;
00706             m_longsuperblock = NULL;
00707         }
00708 
00709         int_vector<1> mini_or_long;// Helper vector: mini or long block?
00710         mini_or_long.load(in); // Load the helper vector
00711         m_miniblock = new int_vector<0>[sb]; // Create miniblock int_vector<0>
00712         if (!mini_or_long.empty())
00713             m_longsuperblock = new int_vector<0>[sb]; // Create longsuperblock int_vector<0>
00714 
00715         for (size_type i=0; i < sb; ++i)
00716             if (!mini_or_long.empty() and not mini_or_long[i]) {
00717                 m_longsuperblock[i].load(in);
00718             } else {
00719                 m_miniblock[i].load(in);
00720             }
00721     }
00722 }
00723 
00724 template<uint8_t b, uint8_t pattern_len>
00725 bool select_support_mcl<b,pattern_len>::operator==(const select_support_mcl& ss)const
00726 {
00727     if (this == &ss)
00728         return true;
00729     if (m_logn == ss.m_logn and m_logn2 == ss.m_logn2 and m_logn4 == ss.m_logn4
00730         and m_arg_cnt == ss.m_arg_cnt and  m_superblock == ss.m_superblock) {
00731         if (m_longsuperblock == NULL and ss.m_longsuperblock != NULL)
00732             return false;
00733         if (ss.m_longsuperblock == NULL and m_longsuperblock != NULL)
00734             return false;
00735         if (m_miniblock == NULL and ss.m_miniblock != NULL)
00736             return false;
00737         if (ss.m_miniblock == NULL and m_miniblock != NULL)
00738             return false;
00739         size_type sb            = (m_arg_cnt+4095)>>12;
00740         if (m_miniblock != NULL)
00741             for (size_type i=0; i < sb; ++i)
00742                 if (m_miniblock[i] != ss.m_miniblock[i])
00743                     return false;
00744         if (m_longsuperblock != NULL)
00745             for (size_type i=0; i < sb; ++i)
00746                 if (m_longsuperblock[i] != ss.m_longsuperblock[i])
00747                     return false;
00748         if (m_v == NULL and ss.m_v != NULL)
00749             return false;
00750         if (m_v != NULL and ss.m_v == NULL)
00751             return false;
00752         if (m_v == NULL and ss.m_v == NULL)
00753             return false;
00754         return *ss.m_v == *m_v;// supported vectors have to be equal. See docu!!!
00755     } else
00756         return false;
00757 }
00758 
00759 template<uint8_t b, uint8_t pattern_len>
00760 bool select_support_mcl<b,pattern_len>::operator!=(const select_support_mcl& ss)const
00761 {
00762     return !(*this == ss);
00763 }
00764 
00765 
00766 }
00767 
00768 #endif