SDSL: Succinct Data Structure Library
A C++ template library for succinct data structures
|
00001 /* sdsl - succinct data structures library 00002 Copyright (C) 2009 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_VFIVE 00022 #define INCLUDED_SDSL_RANK_SUPPORT_VFIVE 00023 00024 #include "rank_support.hpp" 00025 #include "rank_support_v.hpp" 00026 00028 namespace sdsl 00029 { 00030 00031 template<uint8_t, uint8_t> 00032 struct rank_support_v_trait; 00033 00035 00048 template<uint8_t b=1, uint8_t pattern_len=1> 00049 class rank_support_v5 : public rank_support 00050 { 00051 public: 00052 typedef bit_vector bit_vector_type; 00053 private: 00054 int_vector<64> m_basic_block; // basic block for interleaved storage of superblockrank and blockrank 00055 public: 00056 explicit rank_support_v5(const bit_vector* v = NULL); 00057 rank_support_v5(const rank_support_v5& rs); 00058 ~rank_support_v5(); 00059 void init(const bit_vector* v=NULL); 00060 const size_type rank(size_type idx) const; 00061 const size_type operator()(size_type idx)const; 00062 const size_type size()const; 00063 size_type serialize(std::ostream& out, structure_tree_node* v=NULL, std::string name="")const; 00064 void load(std::istream& in, const bit_vector* v=NULL); 00065 void set_vector(const bit_vector* v=NULL); 00066 00068 00070 rank_support_v5& operator=(const rank_support_v5& rs); 00072 00075 void swap(rank_support_v5& rs); 00077 00082 bool operator==(const rank_support_v5& rs)const; 00084 00089 bool operator!=(const rank_support_v5& rs)const; 00090 }; 00091 00092 template<uint8_t b, uint8_t pattern_len> 00093 inline rank_support_v5<b, pattern_len>::rank_support_v5(const bit_vector* v) 00094 { 00095 init(v); 00096 } 00097 00098 template<uint8_t b, uint8_t pattern_len> 00099 inline rank_support_v5<b, pattern_len>::rank_support_v5(const rank_support_v5& rs) 00100 { 00101 m_v = rs.m_v; 00102 m_basic_block = rs.m_basic_block; 00103 } 00104 00105 template<uint8_t b, uint8_t pattern_len> 00106 inline void rank_support_v5<b, pattern_len>::init(const bit_vector* v) 00107 { 00108 set_vector(v); 00109 if (v == NULL) { 00110 return; 00111 } else if (v->empty()) { 00112 m_basic_block = int_vector<64>(2,0); // resize structure for basic_blocks 00113 return; 00114 } 00115 size_type basic_block_size = ((v->capacity() >> 11)+1)<<1; 00116 m_basic_block.resize(basic_block_size); // resize structure for basic_blocks 00117 if (m_basic_block.empty()) 00118 return; 00119 const uint64_t* data = m_v->data(); 00120 size_type i, j=0; 00121 m_basic_block[0] = m_basic_block[1] = 0; 00122 // uint64_t carry = 0; 00123 00124 uint64_t carry = rank_support_v_trait<b, pattern_len>::init_carry(); 00125 uint64_t sum = rank_support_v_trait<b, pattern_len>::args_in_the_word(*data, carry), second_level_cnt = 0; 00126 uint64_t cnt_words=1; 00127 for (i = 1; i < (m_v->capacity()>>6) ; ++i, ++cnt_words) { 00128 if (cnt_words == 32) { 00129 j += 2; 00130 m_basic_block[j-1] = second_level_cnt; 00131 m_basic_block[j] = m_basic_block[j-2] + sum; 00132 second_level_cnt = sum = cnt_words = 0; 00133 } else if ((cnt_words%6)==0) { 00134 // pack the prefix sum for each 6x64bit block into the second_level_cnt 00135 second_level_cnt |= sum<<(60-12*(cnt_words/6));// 48, 36, 24, 12, 0 00136 } 00137 sum += rank_support_v_trait<b, pattern_len>::args_in_the_word(*(++data), carry); 00138 } 00139 00140 if ((cnt_words%6)==0) { 00141 second_level_cnt |= sum<<(60-12*(cnt_words/6)); 00142 } 00143 if (cnt_words == 32) { 00144 j += 2; 00145 m_basic_block[j-1] = second_level_cnt; 00146 m_basic_block[j] = m_basic_block[j-2] + sum; 00147 m_basic_block[j+1] = 0; 00148 } else { 00149 m_basic_block[j+1] = second_level_cnt; 00150 } 00151 00152 } 00153 00154 template<uint8_t b, uint8_t pattern_len> 00155 inline const typename rank_support_v5<b, pattern_len>::size_type rank_support_v5<b, pattern_len>::rank(size_type idx)const 00156 { 00157 const uint64_t* p = m_basic_block.data() + ((idx>>10)&0xFFFFFFFFFFFFFFFEULL);// (idx/2048)*2 00158 size_type result = *p + ((*(p+1)>>(60-12*((idx&0x7FF)/(64*6))))&0x7FFULL)+ // ( prefix sum of the 6x64bit blocks | (idx%2048)/(64*6) ) 00159 rank_support_v_trait<b, pattern_len>::word_rank(m_v->data(), idx); 00160 // std::cerr<<"idx="<<idx<<std::endl; 00161 idx -= (idx&0x3F); 00162 // uint32_t to_do = ((idx>>6)&0x1FULL)%6; 00163 uint8_t to_do = ((idx>>6)&0x1FULL)%6; 00164 --idx; 00165 while (to_do) { 00166 result += rank_support_v_trait<b, pattern_len>::full_word_rank(m_v->data(), idx); 00167 --to_do; 00168 idx-=64; 00169 } 00170 // could not be accelerated with switch command. 2009-12-04 00171 return result; 00172 00173 } 00174 00175 00176 template<uint8_t b, uint8_t pattern_len> 00177 inline const typename rank_support_v5<b, pattern_len>::size_type rank_support_v5<b, pattern_len>::operator()(size_type idx)const 00178 { 00179 return rank(idx); 00180 } 00181 00182 template<uint8_t b, uint8_t pattern_len> 00183 inline rank_support_v5<b, pattern_len>::~rank_support_v5() {} 00184 00185 template<uint8_t b, uint8_t pattern_len> 00186 inline void rank_support_v5<b, pattern_len>::set_vector(const bit_vector* v) 00187 { 00188 m_v = v; 00189 } 00190 00191 00192 template<uint8_t b, uint8_t pattern_len> 00193 inline const typename rank_support_v5<b,pattern_len>::size_type rank_support_v5<b, pattern_len>::size()const 00194 { 00195 return m_v->size(); 00196 } 00197 00198 template<uint8_t b, uint8_t pattern_len> 00199 inline typename rank_support_v5<b, pattern_len>::size_type rank_support_v5<b, pattern_len>::serialize(std::ostream& out, structure_tree_node* v, std::string name)const 00200 { 00201 size_type written_bytes = 0; 00202 structure_tree_node* child = structure_tree::add_child(v, name, util::class_name(*this)); 00203 written_bytes += m_basic_block.serialize(out, child, "cumulative_counts"); 00204 structure_tree::add_size(child, written_bytes); 00205 return written_bytes; 00206 } 00207 00208 template<uint8_t b, uint8_t pattern_len> 00209 inline void rank_support_v5<b, pattern_len>::load(std::istream& in, const bit_vector* v) 00210 { 00211 set_vector(v); 00212 assert(m_v != NULL); // supported bit vector should be known 00213 m_basic_block.load(in); 00214 } 00215 00216 template<uint8_t b, uint8_t pattern_len> 00217 inline rank_support_v5<b, pattern_len>& rank_support_v5<b, pattern_len>::operator=(const rank_support_v5& rs) 00218 { 00219 if (this != &rs) { 00220 set_vector(rs.m_v); 00221 m_basic_block = rs.m_basic_block; 00222 } 00223 return *this; 00224 } 00225 00226 template<uint8_t b, uint8_t pattern_len> 00227 inline void rank_support_v5<b, pattern_len>::swap(rank_support_v5& rs) 00228 { 00229 if (this != &rs) { // if rs and _this_ are not the same object 00230 m_basic_block.swap(rs.m_basic_block); 00231 } 00232 } 00233 00234 // TODO: == operator remove pointer comparison 00235 template<uint8_t b, uint8_t pattern_len> 00236 inline bool rank_support_v5<b, pattern_len>::operator==(const rank_support_v5& rs)const 00237 { 00238 if (this == &rs) 00239 return true; 00240 return m_basic_block == rs.m_basic_block and *(rs.m_v) == *m_v; 00241 } 00242 00243 template<uint8_t b, uint8_t pattern_len> 00244 inline bool rank_support_v5<b, pattern_len>::operator!=(const rank_support_v5& rs)const 00245 { 00246 return !(*this == rs); 00247 } 00248 00249 }// end namespace sds 00250 00251 #endif // end file