Sux
StrideDynRankSel.hpp
Go to the documentation of this file.
1 /*
2  * Sux: Succinct data structures
3  *
4  * Copyright (C) 2019-2020 Stefano Marchini
5  *
6  * This library is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as published by the Free
8  * Software Foundation; either version 3 of the License, or (at your option)
9  * any later version.
10  *
11  * This library is free software; you can redistribute it and/or modify it under
12  * the terms of the GNU General Public License as published by the Free Software
13  * Foundation; either version 3, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful, but WITHOUT ANY
16  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
17  * PARTICULAR PURPOSE. See the GNU General Public License for more details.
18  *
19  * Under Section 7 of GPL version 3, you are granted additional permissions
20  * described in the GCC Runtime Library Exception, version 3.1, as published by
21  * the Free Software Foundation.
22  *
23  * You should have received a copy of the GNU General Public License and a copy of
24  * the GCC Runtime Library Exception along with this program; see the files
25  * COPYING3 and COPYING.RUNTIME respectively. If not, see
26  * <http://www.gnu.org/licenses/>.
27  */
28 
29 #pragma once
30 
31 #include "../util/Vector.hpp"
32 #include "DynamicBitVector.hpp"
33 #include "Rank.hpp"
34 #include "Select.hpp"
35 #include "SelectZero.hpp"
36 
37 namespace sux::bits {
38 
51 template <template <size_t, util::AllocType AT> class SPS, size_t WORDS, util::AllocType AT = util::AllocType::MALLOC>
52 class StrideDynRankSel : public DynamicBitVector, public Rank, public Select, public SelectZero {
53  private:
54  static constexpr size_t BOUND = 64 * WORDS;
55  uint64_t *const Vector;
56  size_t Size;
57  SPS<BOUND, AT> SrcPrefSum;
58 
59  public:
74  StrideDynRankSel(uint64_t bitvector[], size_t size) : Vector(bitvector), Size(size), SrcPrefSum(buildSrcPrefSum(bitvector, divRoundup(size, 64))) {}
75 
76  uint64_t *bitvector() const { return Vector; }
77 
78  virtual uint64_t rank(size_t pos) {
79  size_t idx = pos / (64 * WORDS);
80  uint64_t value = SrcPrefSum.prefix(idx);
81 
82  for (size_t i = idx * WORDS; i < pos / 64; i++) value += nu(Vector[i]);
83 
84  return value + nu(Vector[pos / 64] & ((1ULL << (pos % 64)) - 1));
85  }
86 
87  using Rank::rank;
88  using Rank::rankZero;
89  virtual uint64_t rank(size_t from, size_t to) { return rank(to) - rank(from); }
90 
91  virtual size_t select(uint64_t rank) {
92  size_t idx = SrcPrefSum.find(&rank);
93 
94  for (size_t i = idx * WORDS; i < idx * WORDS + WORDS; i++) {
95  uint64_t rank_chunk = nu(Vector[i]);
96  if (rank < rank_chunk)
97  return i * 64 + select64(Vector[i], rank);
98  else
99  rank -= rank_chunk;
100  }
101 
102  return SIZE_MAX;
103  }
104 
105  virtual size_t selectZero(uint64_t rank) {
106  size_t idx = SrcPrefSum.compFind(&rank);
107 
108  for (size_t i = idx * WORDS; i < idx * WORDS + WORDS; i++) {
109  uint64_t rank_chunk = nu(~Vector[i]);
110  if (rank < rank_chunk)
111  return i * 64 + select64(~Vector[i], rank);
112  else
113  rank -= rank_chunk;
114  }
115 
116  return SIZE_MAX;
117  }
118 
119  virtual uint64_t update(size_t index, uint64_t word) {
120  uint64_t old = Vector[index];
121  Vector[index] = word;
122  SrcPrefSum.add(index / WORDS + 1, nu(word) - nu(old));
123 
124  return old;
125  }
126 
127  virtual bool set(size_t index) {
128  uint64_t old = Vector[index / 64];
129  Vector[index / 64] |= uint64_t(1) << (index % 64);
130 
131  if (Vector[index / 64] != old) {
132  SrcPrefSum.add(index / (WORDS * 64) + 1, 1);
133  return false;
134  }
135 
136  return true;
137  }
138 
139  virtual bool clear(size_t index) {
140  uint64_t old = Vector[index / 64];
141  Vector[index / 64] &= ~(uint64_t(1) << (index % 64));
142 
143  if (Vector[index / 64] != old) {
144  SrcPrefSum.add(index / (WORDS * 64) + 1, -1);
145  return true;
146  }
147 
148  return false;
149  }
150 
151  virtual bool toggle(size_t index) {
152  uint64_t old = Vector[index / 64];
153  Vector[index / 64] ^= uint64_t(1) << (index % 64);
154  bool was_set = Vector[index / 64] < old;
155  SrcPrefSum.add(index / (WORDS * 64) + 1, was_set ? -1 : 1);
156 
157  return was_set;
158  }
159 
160  virtual size_t size() const { return Size; }
161 
162  virtual size_t bitCount() const { return SrcPrefSum.bitCount() - sizeof(SrcPrefSum) * 8 + sizeof(*this) * 8 + ((Size + 63) & ~63); }
163 
164  private:
165  static size_t divRoundup(size_t x, size_t y) {
166  if (y > x) return 1;
167  return (x / y) + ((x % y != 0) ? 1 : 0);
168  }
169 
170  static SPS<BOUND, AT> buildSrcPrefSum(const uint64_t bitvector[], size_t size) {
171  unique_ptr<uint64_t[]> sequence = make_unique<uint64_t[]>(divRoundup(size, WORDS));
172  for (size_t i = 0; i < size; i++) sequence[i / WORDS] += nu(bitvector[i]);
173  return SPS<BOUND, AT>(sequence.get(), divRoundup(size, WORDS));
174  }
175 
176  friend std::ostream &operator<<(std::ostream &os, const StrideDynRankSel<SPS, WORDS, AT> &bv) {
177  os.write((char *)&bv.Size, sizeof(uint64_t));
178  return os << bv.SrcPrefSum << bv.Vector;
179  }
180 
181  friend std::istream &operator>>(std::istream &is, StrideDynRankSel<SPS, WORDS, AT> &bv) {
182  is.read((char *)&bv.Size, sizeof(uint64_t));
183  return is >> bv.SrcPrefSum >> bv.Vector;
184  }
185 };
186 
187 } // namespace sux::bits
sux::Rank
Definition: Rank.hpp:46
sux::util::AllocType
AllocType
Definition: Vector.hpp:45
sux::bits::StrideDynRankSel::select
virtual size_t select(uint64_t rank)
Definition: StrideDynRankSel.hpp:91
sux::bits::StrideDynRankSel::rank
virtual uint64_t rank(size_t from, size_t to)
Definition: StrideDynRankSel.hpp:89
sux::bits::StrideDynRankSel::clear
virtual bool clear(size_t index)
Definition: StrideDynRankSel.hpp:139
sux::bits::StrideDynRankSel::rank
virtual uint64_t rank(size_t pos)
Definition: StrideDynRankSel.hpp:78
sux::bits::StrideDynRankSel::StrideDynRankSel
StrideDynRankSel(uint64_t bitvector[], size_t size)
Definition: StrideDynRankSel.hpp:74
sux::bits::StrideDynRankSel::update
virtual uint64_t update(size_t index, uint64_t word)
Definition: StrideDynRankSel.hpp:119
Rank.hpp
sux::util::MALLOC
Definition: Vector.hpp:47
sux::bits::DynamicBitVector
Definition: DynamicBitVector.hpp:41
sux::Select
Definition: Select.hpp:38
sux::bits::StrideDynRankSel::toggle
virtual bool toggle(size_t index)
Definition: StrideDynRankSel.hpp:151
sux::bits
Definition: DynamicBitVector.hpp:31
sux::bits::StrideDynRankSel::bitvector
uint64_t * bitvector() const
Definition: StrideDynRankSel.hpp:76
Select.hpp
DynamicBitVector.hpp
sux::bits::StrideDynRankSel::size
virtual size_t size() const
Definition: StrideDynRankSel.hpp:160
sux::SelectZero
Definition: SelectZero.hpp:42
sux::bits::StrideDynRankSel::selectZero
virtual size_t selectZero(uint64_t rank)
Definition: StrideDynRankSel.hpp:105
sux::bits::StrideDynRankSel::operator>>
friend std::istream & operator>>(std::istream &is, StrideDynRankSel< SPS, WORDS, AT > &bv)
Definition: StrideDynRankSel.hpp:181
sux::Rank::rank
virtual uint64_t rank(std::size_t pos)=0
sux::nu
int nu(uint64_t word)
Definition: common.hpp:339
sux::bits::StrideDynRankSel::set
virtual bool set(size_t index)
Definition: StrideDynRankSel.hpp:127
sux::bits::StrideDynRankSel
Definition: StrideDynRankSel.hpp:52
SelectZero.hpp
sux::bits::StrideDynRankSel::operator<<
friend std::ostream & operator<<(std::ostream &os, const StrideDynRankSel< SPS, WORDS, AT > &bv)
Definition: StrideDynRankSel.hpp:176
sux::Rank::rankZero
virtual uint64_t rankZero(std::size_t pos)
Definition: Rank.hpp:70
sux::bits::StrideDynRankSel::bitCount
virtual size_t bitCount() const
Definition: StrideDynRankSel.hpp:162
sux::select64
uint64_t select64(uint64_t x, uint64_t k)
Definition: common.hpp:372