SDSL: Succinct Data Structure Library
A C++ template library for succinct data structures
 All Classes Namespaces Files Functions Variables Typedefs Friends
sdsl/include/sdsl/rank_support_v5.hpp
Go to the documentation of this file.
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