SDSL: Succinct Data Structure Library
A C++ template library for succinct data structures
|
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