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