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_RANK_SUPPORT_V 00022 #define INCLUDED_SDSL_RANK_SUPPORT_V 00023 00024 #include "rank_support.hpp" 00025 00027 namespace sdsl 00028 { 00029 00030 template<uint8_t bit_pattern, uint8_t pattern_len> 00031 struct rank_support_v_trait { 00032 typedef rank_support::size_type size_type; 00033 00034 static size_type args_in_the_word(uint64_t w, uint64_t& carry) { 00035 return 0; 00036 } 00037 00038 static uint32_t word_rank(const uint64_t* data, size_type idx) { 00039 return 0; 00040 } 00041 00042 static uint32_t full_word_rank(const uint64_t* data, size_type idx) { 00043 return 0; 00044 } 00045 00046 static uint64_t init_carry() { 00047 return 0; 00048 } 00049 }; 00050 00051 template<> 00052 struct rank_support_v_trait<0,1> { 00053 typedef rank_support::size_type size_type; 00054 00055 static size_type args_in_the_word(uint64_t w, uint64_t&) { 00056 return bit_magic::b1Cnt(~w); 00057 } 00058 00059 static uint32_t word_rank(const uint64_t* data, size_type idx) { 00060 return bit_magic::b1Cnt((~*(data+(idx>>6))) & bit_magic::Li1Mask[idx&0x3F]); 00061 } 00062 00063 static uint32_t full_word_rank(const uint64_t* data, size_type idx) { 00064 return bit_magic::b1Cnt((~*(data+(idx>>6)))); 00065 } 00066 00067 static uint64_t init_carry() { 00068 return 0; 00069 } 00070 }; 00071 00072 template<> 00073 struct rank_support_v_trait<1,1> { 00074 typedef rank_support::size_type size_type; 00075 00076 static size_type args_in_the_word(uint64_t w, uint64_t&) { 00077 return bit_magic::b1Cnt(w); 00078 } 00079 00080 static uint32_t word_rank(const uint64_t* data, size_type idx) { 00081 return bit_magic::b1Cnt(*(data+(idx>>6)) & bit_magic::Li1Mask[idx&0x3F]); 00082 } 00083 00084 static uint32_t full_word_rank(const uint64_t* data, size_type idx) { 00085 return bit_magic::b1Cnt(*(data+(idx>>6))); 00086 } 00087 00088 static uint64_t init_carry() { 00089 return 0; 00090 } 00091 }; 00092 00093 template<> 00094 struct rank_support_v_trait<10,2> { 00095 typedef rank_support::size_type size_type; 00096 00097 static size_type args_in_the_word(uint64_t w, uint64_t& carry) { 00098 return bit_magic::b10Cnt(w, carry); 00099 } 00100 00101 static uint32_t word_rank(const uint64_t* data, size_type idx) { 00102 data = data+(idx>>6); 00103 uint64_t carry = (idx>63) ? *(data-1)>>63 : 0; 00104 return bit_magic::b1Cnt(bit_magic::b10Map(*data, carry) & bit_magic::Li1Mask[idx&0x3F]); 00105 } 00106 00107 static uint32_t full_word_rank(const uint64_t* data, size_type idx) { 00108 data = data+(idx>>6); 00109 uint64_t carry = (idx>63) ? *(data-1)>>63 : 0; 00110 return bit_magic::b1Cnt(bit_magic::b10Map(*data, carry)); 00111 } 00112 00113 static uint64_t init_carry() { 00114 return 0; 00115 } 00116 }; 00117 00118 template<> 00119 struct rank_support_v_trait<01,2> { 00120 typedef rank_support::size_type size_type; 00121 00122 static size_type args_in_the_word(uint64_t w, uint64_t& carry) { 00123 return bit_magic::b01Cnt(w, carry); 00124 } 00125 00126 static uint32_t word_rank(const uint64_t* data, size_type idx) { 00127 data = data+(idx>>6); 00128 uint64_t carry = (idx>63) ? *(data-1)>>63 : 0; 00129 return bit_magic::b1Cnt(bit_magic::b01Map(*data, carry) & bit_magic::Li1Mask[idx&0x3F]); 00130 } 00131 00132 static uint32_t full_word_rank(const uint64_t* data, size_type idx) { 00133 data = data+(idx>>6); 00134 uint64_t carry = (idx>63) ? *(data-1)>>63 : 0; 00135 return bit_magic::b1Cnt(bit_magic::b01Map(*data, carry)); 00136 } 00137 00138 static uint64_t init_carry() { 00139 return 1; 00140 } 00141 }; 00142 00144 00157 template<uint8_t b=1, uint8_t pattern_len=1> 00158 class rank_support_v : public rank_support 00159 { 00160 public: 00161 typedef bit_vector bit_vector_type; 00162 private: 00163 int_vector<64> m_basic_block; // basic block for interleaved storage of superblockrank and blockrank 00164 public: 00165 explicit rank_support_v(const bit_vector* v = NULL); 00166 rank_support_v(const rank_support_v& rs); 00167 ~rank_support_v(); 00168 void init(const bit_vector* v=NULL); 00169 const size_type rank(size_type idx) const; 00170 const size_type operator()(size_type idx)const; 00171 const size_type size()const; 00172 size_type serialize(std::ostream& out, structure_tree_node* v=NULL, std::string name="")const; 00173 void load(std::istream& in, const int_vector<1>* v=NULL); 00174 void set_vector(const bit_vector* v=NULL); 00175 00177 00179 rank_support_v& operator=(const rank_support_v& rs); 00181 00185 void swap(rank_support_v& rs); 00187 00192 bool operator==(const rank_support_v& rs)const; 00194 00199 bool operator!=(const rank_support_v& rs)const; 00200 }; 00201 00202 template<uint8_t b, uint8_t pattern_len> 00203 inline rank_support_v<b, pattern_len>::rank_support_v(const bit_vector* v) 00204 { 00205 init(v); 00206 } 00207 00208 template<uint8_t b, uint8_t pattern_len> 00209 inline rank_support_v<b, pattern_len>::rank_support_v(const rank_support_v& rs) 00210 { 00211 m_v = rs.m_v; 00212 m_basic_block = rs.m_basic_block; 00213 } 00214 00215 00216 template<uint8_t b, uint8_t pattern_len> 00217 inline void rank_support_v<b, pattern_len>::set_vector(const bit_vector* v) 00218 { 00219 m_v = v; 00220 } 00221 00222 template<uint8_t b, uint8_t pattern_len> 00223 inline const typename rank_support_v<b, pattern_len>::size_type rank_support_v<b, pattern_len>::size()const 00224 { 00225 return m_v->size(); 00226 } 00227 00228 template<uint8_t b, uint8_t pattern_len> 00229 inline void rank_support_v<b, pattern_len>::init(const bit_vector* v) 00230 { 00231 set_vector(v); 00232 if (v == NULL) { 00233 return; 00234 } else if (v->empty()) { 00235 m_basic_block = int_vector<64>(2,0); // resize structure for basic_blocks 00236 return; 00237 } 00238 size_type basic_block_size = ((v->capacity() >> 9)+1)<<1; 00239 m_basic_block.resize(basic_block_size); // resize structure for basic_blocks 00240 if (m_basic_block.empty()) 00241 return; 00242 const uint64_t* data = m_v->data(); 00243 size_type i, j=0; 00244 m_basic_block[0] = m_basic_block[1] = 0; 00245 00246 uint64_t carry = rank_support_v_trait<b, pattern_len>::init_carry(); 00247 uint64_t sum = rank_support_v_trait<b, pattern_len>::args_in_the_word(*data, carry), second_level_cnt = 0; 00248 for (i = 1; i < (m_v->capacity()>>6) ; ++i) { 00249 if (!(i&0x7)) {// if i%8==0 00250 j += 2; 00251 m_basic_block[j-1] = second_level_cnt; 00252 m_basic_block[j] = m_basic_block[j-2] + sum; 00253 second_level_cnt = sum = 0; 00254 } else { 00255 second_level_cnt |= sum<<(63-9*(i&0x7));// 54, 45, 36, 27, 18, 9, 0 00256 } 00257 sum += rank_support_v_trait<b, pattern_len>::args_in_the_word(*(++data), carry); 00258 } 00259 if (i&0x7) { // if i%8 != 0 00260 second_level_cnt |= sum << (63-9*(i&0x7)); 00261 m_basic_block[j+1] = second_level_cnt; 00262 } else { // if i%8 == 0 00263 j += 2; 00264 m_basic_block[j-1] = second_level_cnt; 00265 m_basic_block[j] = m_basic_block[j-2] + sum; 00266 m_basic_block[j+1] = 0; 00267 } 00268 } 00269 00270 template<uint8_t b, uint8_t pattern_len> 00271 inline const typename rank_support_v<b, pattern_len>::size_type rank_support_v<b, pattern_len>::rank(size_type idx)const 00272 { 00273 const uint64_t* p = m_basic_block.data() + ((idx>>8)&0xFFFFFFFFFFFFFFFEULL);// (idx/512)*2 00274 if (idx&0x3F) // if (idx%64)!=0 00275 return *p + ((*(p+1)>>(63 - 9*((idx&0x1FF)>>6)))&0x1FF) + 00276 rank_support_v_trait<b, pattern_len>::word_rank(m_v->data(), idx); 00277 else 00278 return *p + ((*(p+1)>>(63 - 9*((idx&0x1FF)>>6)))&0x1FF); 00279 } 00280 00281 00282 template<uint8_t b, uint8_t pattern_len> 00283 inline const typename rank_support_v<b, pattern_len>::size_type rank_support_v<b, pattern_len>::operator()(size_type idx)const 00284 { 00285 return rank(idx); 00286 } 00287 00288 template<uint8_t b, uint8_t pattern_len> 00289 inline rank_support_v<b, pattern_len>::~rank_support_v() {} 00290 00291 00292 template<uint8_t b, uint8_t pattern_len> 00293 inline typename rank_support_v<b, pattern_len>::size_type rank_support_v<b, pattern_len>::serialize(std::ostream& out, structure_tree_node* v, std::string name)const 00294 { 00295 size_type written_bytes = 0; 00296 structure_tree_node* child = structure_tree::add_child(v, name, util::class_name(*this)); 00297 written_bytes += m_basic_block.serialize(out, child, "cumulative_counts"); 00298 structure_tree::add_size(child, written_bytes); 00299 return written_bytes; 00300 } 00301 00302 template<uint8_t b, uint8_t pattern_len> 00303 inline void rank_support_v<b, pattern_len>::load(std::istream& in, const int_vector<1>* v) 00304 { 00305 set_vector(v); 00306 assert(m_v != NULL); // supported bit vector should be known 00307 m_basic_block.load(in); 00308 } 00309 00310 template<uint8_t b, uint8_t pattern_len> 00311 inline rank_support_v<b, pattern_len>& rank_support_v<b, pattern_len>::operator=(const rank_support_v& rs) 00312 { 00313 if (this != &rs) { 00314 set_vector(rs.m_v); 00315 m_basic_block = rs.m_basic_block; 00316 } 00317 return *this; 00318 } 00319 00320 template<uint8_t b, uint8_t pattern_len> 00321 inline void rank_support_v<b, pattern_len>::swap(rank_support_v& rs) 00322 { 00323 if (this != &rs) { // if rs and _this_ are not the same object 00324 m_basic_block.swap(rs.m_basic_block); 00325 } 00326 } 00327 00328 // TODO: == operator remove pointer comparison 00329 template<uint8_t b, uint8_t pattern_len> 00330 inline bool rank_support_v<b, pattern_len>::operator==(const rank_support_v& rs)const 00331 { 00332 if (this == &rs) 00333 return true; 00334 return m_basic_block == rs.m_basic_block and *(rs.m_v) == *m_v; 00335 } 00336 00337 template<uint8_t b, uint8_t pattern_len> 00338 inline bool rank_support_v<b, pattern_len>::operator!=(const rank_support_v& rs)const 00339 { 00340 return !(*this == rs); 00341 } 00342 00343 }// end namespace sds 00344 00345 #endif // end file