SDSL: Succinct Data Structure Library
A C++ template library for succinct data structures
|
00001 /* sdsl - succinct data structures library 00002 Copyright (C) 2011 Timo Beller, 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 */ 00022 #ifndef INCLUDED_NN_DICT_DYNAMIC 00023 #define INCLUDED_NN_DICT_DYNAMIC 00024 00025 #include <sdsl/int_vector.hpp> 00026 #include <sdsl/util.hpp> 00027 00028 namespace sdsl 00029 { 00030 00031 class nn_dict_dynamic; // forward declaration 00032 00033 namespace util 00034 { 00035 void set_zero_bits(nn_dict_dynamic& nn); 00036 } 00037 00038 00039 // possible TODO: resize(size_type size) 00040 00042 class nn_dict_dynamic 00043 { 00044 public: 00045 typedef int_vector<64>::size_type size_type; 00046 class reference; // forward declaration of inner class 00047 00048 friend class reference; 00049 friend void util::set_zero_bits(nn_dict_dynamic& nn); 00050 private: 00051 uint64_t m_depth; // Depth of the tree (1 level corresonds to 0, 2 levels corresponds to 1,...) 00052 uint64_t m_v_begin_leaves; // Virtual begin of leaves 00053 size_type m_size; 00054 int_vector<64> m_offset; // Number of nodes to skip on each level 00055 int_vector<64> m_tree; // Tree 00056 00057 void copy(const nn_dict_dynamic& nn) { 00058 m_depth = nn.m_depth; 00059 m_v_begin_leaves = nn.m_v_begin_leaves; 00060 m_size = nn.m_size; 00061 m_offset = nn.m_offset; 00062 m_tree = nn.m_tree; 00063 } 00064 00065 public: 00066 00067 const uint64_t& depth; 00068 00069 size_type size()const { 00070 return m_size; 00071 } 00072 00073 00074 00076 00078 nn_dict_dynamic(const uint64_t n = 0):depth(m_depth) { 00079 m_size = n; 00080 if (n == 0) 00081 return; 00082 uint64_t level; // level indicator 00083 uint64_t nodes = 1; // number of nodes (=64 bit integer) 00084 uint64_t tmp; // tmp-variable 00085 00086 /* Calc depth and begin of leaves */ 00087 m_depth = bit_magic::l1BP(n)/6; // if, n>0 calculate \f$ \lfloor log_64(n) \rfloor \f$ 00088 m_v_begin_leaves = (1ULL<<(m_depth*6))/63; 00089 00090 /* Calc how many nodes to skip on each level */ 00091 m_offset = int_vector<64>(m_depth+2, 0); 00092 level = m_depth; 00093 tmp = n; 00094 while (level) { 00095 tmp = (tmp+63)/64; // get real number of nodes, of the next higher level 00096 // <number of nodes in the full tree> - <real number of nodes> 00097 m_offset[level+1] = (1ULL<<(6*level)) - tmp; 00098 nodes += tmp; 00099 --level; 00100 } 00101 00102 /* Calc how many nodes to skip up to each level*/ 00103 for (level = 1; level <= m_depth; ++level) { 00104 m_offset[level] += m_offset[level-1]; 00105 } 00106 00107 /* Create Tree incl. leaves */ 00108 m_tree = int_vector<64>(nodes); 00109 } 00110 00112 nn_dict_dynamic(const nn_dict_dynamic& nn):depth(m_depth) { 00113 copy(nn); 00114 } 00115 00117 nn_dict_dynamic& operator=(const nn_dict_dynamic& nn) { 00118 if (this != &nn) { 00119 copy(nn); 00120 } 00121 return *this; 00122 } 00123 00124 void swap(nn_dict_dynamic& nn) { 00125 if (this != &nn) { 00126 std::swap(m_depth, nn.m_depth); 00127 std::swap(m_v_begin_leaves, nn.m_v_begin_leaves); 00128 std::swap(m_size, nn.m_size); 00129 m_offset.swap(nn.m_offset); 00130 m_tree.swap(nn.m_tree); 00131 } 00132 } 00133 00135 00139 bool operator[](const size_type& idx)const { 00140 uint64_t node = m_tree[(m_v_begin_leaves + (idx>>6)) - m_offset[m_depth] ]; 00141 return (node >> (idx&0x3F)) & 1; 00142 } 00143 00144 inline reference operator[](const size_type& idx) { 00145 return reference(this, idx); 00146 } 00147 00148 00150 00155 size_type next(const size_type idx)const { 00156 uint64_t v_node_position; // virtual node position 00157 uint64_t node; // current node 00158 uint64_t depth = m_depth; // current depth of node 00159 uint64_t position; // position of the 1-bit 00160 00161 v_node_position = m_v_begin_leaves + (idx>>6); 00162 uint8_t off = idx & 0x3F; // mod 64 00163 00164 // Go up until a 1-bit is found 00165 node = m_tree[ v_node_position-m_offset[depth] ]>>off; 00166 while (!node or off==64) { 00167 // Not in the root 00168 if (v_node_position) { 00169 --depth; 00170 --v_node_position; 00171 off = (v_node_position&0x3F)+1; 00172 v_node_position >>= 6; 00173 node = m_tree[ v_node_position-m_offset[depth] ]>>off; 00174 } else { 00175 return size(); 00176 } 00177 } 00178 // Calculate the position of the 1-bit 00179 position = bit_magic::r1BP(node)+off; 00180 00181 // Go down to the leaf 00182 while (v_node_position < m_v_begin_leaves) { 00183 ++depth; 00184 v_node_position = (v_node_position<<6) + 1 + position; 00185 node = m_tree[ v_node_position-m_offset[depth] ]; 00186 00187 // Calculate the position of the 1-bit 00188 position = bit_magic::r1BP(node); 00189 } 00190 return ((v_node_position - m_v_begin_leaves)<<6) + position; 00191 } 00192 00194 00199 size_type prev(const size_type idx)const { 00200 uint64_t v_node_position; // virtual node position 00201 uint64_t node; // current node 00202 uint64_t depth = m_depth; // current depth of node 00203 uint64_t position; // position of the 1-bit 00204 00205 v_node_position = m_v_begin_leaves + (idx>>6); 00206 uint8_t off = idx & 0x3F; // mod 64 00207 00208 // Go up until a 1-bit is found 00209 node = m_tree[ v_node_position-m_offset[depth] ]<<(63-off); 00210 while (!node or off == (uint8_t)-1) { 00211 00212 // Not in the root 00213 if (v_node_position) { 00214 --depth; 00215 --v_node_position; 00216 00217 off = ((uint8_t)(v_node_position&0x3F))-1; 00218 v_node_position >>= 6; 00219 00220 node = m_tree[ v_node_position-m_offset[depth] ]<<(63-off); 00221 } else { 00222 return size(); 00223 } 00224 } 00225 // Calculate the position of the 1-bit 00226 position = bit_magic::l1BP(node)-(63-off); 00227 00228 // Go down to the leaf 00229 while (v_node_position < m_v_begin_leaves) { 00230 ++depth; 00231 v_node_position = (v_node_position<<6) + 1 + position; 00232 node = m_tree[ v_node_position-m_offset[depth] ]; 00233 00234 // Calculate the position of the 1-bit 00235 position = bit_magic::l1BP(node); //-(63-off) 00236 } 00237 return ((v_node_position - m_v_begin_leaves)<<6) + position; 00238 } 00239 00240 00242 void load(std::istream& in) { 00243 util::read_member(m_depth, in); 00244 util::read_member(m_v_begin_leaves, in); 00245 util::read_member(m_size, in); 00246 m_offset.load(in); 00247 m_tree.load(in); 00248 } 00249 00251 size_type serialize(std::ostream& out, structure_tree_node* v=NULL, std::string name="")const { 00252 structure_tree_node* child = structure_tree::add_child(v, name, util::class_name(*this)); 00253 size_type written_bytes = 0; 00254 written_bytes += util::write_member(m_depth, out, child, "depth"); 00255 written_bytes += util::write_member(m_v_begin_leaves, out, child, "v_begin_leaves"); 00256 written_bytes += util::write_member(m_size, out, child, "size"); 00257 written_bytes += m_offset.serialize(out, child, "offset"); 00258 written_bytes += m_tree.serialize(out, child, "tree"); 00259 structure_tree::add_size(child, written_bytes); 00260 return written_bytes; 00261 } 00262 00263 class reference 00264 { 00265 private: 00266 nn_dict_dynamic* m_pbv; // pointer to the bit_vector_nearest_neigbour 00267 size_type m_idx; // virtual node position 00268 public: 00270 reference(nn_dict_dynamic* pbv, 00271 nn_dict_dynamic::size_type idx):m_pbv(pbv),m_idx(idx) {}; 00272 00274 reference& operator=(bool x) { 00275 uint64_t v_node_position; // virtual node position 00276 uint64_t r_node_position; // real node position 00277 uint64_t depth = m_pbv->m_depth; // current depth of node 00278 00279 v_node_position = m_pbv->m_v_begin_leaves + (m_idx>>6); 00280 uint8_t offset = m_idx & 0x3F; // pos mod 64 00281 if (x) { 00282 while (true) { 00283 r_node_position = v_node_position - m_pbv->m_offset[depth]; 00284 uint64_t w = m_pbv->m_tree[r_node_position]; 00285 if ((w>>offset) & 1) { // if the bit was already set 00286 return *this; 00287 } else { 00288 m_pbv->m_tree[r_node_position] |= (1ULL<<offset); // set bit 00289 if (!w and depth) { // go up in the tree 00290 --depth; --v_node_position; 00291 offset = v_node_position&0x3F; 00292 v_node_position >>= 6; 00293 } else { 00294 return *this; 00295 } 00296 } 00297 } 00298 } else { 00299 while (true) { 00300 r_node_position = v_node_position - m_pbv->m_offset[depth]; 00301 uint64_t w = m_pbv->m_tree[r_node_position]; 00302 if (!((w>>offset) & 1)) { // if the bit is already 0 00303 return *this; 00304 } else { 00305 m_pbv->m_tree[r_node_position] &= (~(1ULL<<offset)); // unset bit 00306 if (!m_pbv->m_tree[r_node_position] and depth) { // go up in the tree 00307 --depth; --v_node_position; 00308 offset = v_node_position&0x3F; 00309 v_node_position >>= 6; 00310 } else { 00311 return *this; 00312 } 00313 } 00314 } 00315 } 00316 return *this; 00317 } 00318 00319 reference& operator=(const reference& x) { 00320 return *this = bool(x); 00321 } 00322 00324 operator bool()const { 00325 uint64_t node = m_pbv->m_tree[(m_pbv->m_v_begin_leaves + (m_idx>>6)) - m_pbv->m_offset[m_pbv->m_depth] ]; 00326 return (node >> (m_idx&0x3F)) & 1; 00327 } 00328 00329 bool operator==(const reference& x)const { 00330 return bool(*this) == bool(x); 00331 } 00332 00333 bool operator<(const reference& x)const { 00334 return !bool(*this) and bool(x); 00335 } 00336 }; 00337 00338 }; 00339 00340 00341 00342 } // end of namespace 00343 00344 #endif // end file