Sux
FenwickBitF.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 "SearchablePrefixSums.hpp"
32 #include "Vector.hpp"
33 #include <cstring>
34 
35 namespace sux::util {
36 
42 template <size_t BOUND, AllocType AT = MALLOC> class FenwickBitF : public SearchablePrefixSums, public Expandable {
43  public:
44  static constexpr size_t BOUNDSIZE = ceil_log2_plus1(BOUND);
45  static constexpr size_t STARTING_OFFSET = 1;
46  static constexpr size_t END_PADDING = 56;
47  static_assert(BOUNDSIZE >= 1 && BOUNDSIZE <= 55, "Some nodes will span on multiple words");
48 
49  protected:
51  size_t Size;
52 
53  public:
55  FenwickBitF() : Size(0) {}
56 
66  FenwickBitF(uint64_t sequence[], size_t size) : Tree((first_bit_after(size) + END_PADDING + 7) >> 3), Size(size) {
67  for (size_t idx = 1; idx <= Size; idx++) addToPartialFrequency(idx, sequence[idx - 1]);
68 
69  for (size_t m = 2; m <= Size; m <<= 1)
70  for (size_t idx = m; idx <= Size; idx += m) addToPartialFrequency(idx, getPartialFrequency(idx - m / 2));
71  }
72 
73  virtual uint64_t prefix(size_t idx) {
74  uint64_t sum = 0;
75 
76  while (idx != 0) {
77  sum += getPartialFrequency(idx);
78  idx = clear_rho(idx);
79  }
80 
81  return sum;
82  }
83 
84  virtual void add(size_t idx, int64_t inc) {
85  while (idx <= Size) {
86  addToPartialFrequency(idx, inc);
87  idx += mask_rho(idx);
88  }
89  }
90 
92  virtual size_t find(uint64_t *val) {
93  size_t node = 0;
94 
95  for (size_t m = mask_lambda(Size); m != 0; m >>= 1) {
96  if (node + m > Size) continue;
97 
98  const uint64_t value = getPartialFrequency(node + m);
99 
100  if (*val >= value) {
101  node += m;
102  *val -= value;
103  }
104  }
105 
106  return node;
107  }
108 
110  virtual size_t compFind(uint64_t *val) {
111  size_t node = 0;
112 
113  for (size_t m = mask_lambda(Size); m != 0; m >>= 1) {
114  if (node + m > Size) continue;
115 
116  const int height = rho(node + m);
117  const uint64_t value = (BOUND << height) - getPartialFrequency(node + m);
118 
119  if (*val >= value) {
120  node += m;
121  *val -= value;
122  }
123  }
124 
125  return node;
126  }
127 
128  virtual void push(uint64_t val) {
129  Tree.resize((first_bit_after(++Size) + END_PADDING + 7) >> 3);
130  addToPartialFrequency(Size, val);
131 
132  if ((Size & 1) == 0) {
133  for (size_t idx = Size - 1; rho(idx) < rho(Size); idx = clear_rho(idx)) addToPartialFrequency(Size, getPartialFrequency(idx));
134  }
135  }
136 
137  virtual void pop() { Tree.resize((first_bit_after(--Size) + END_PADDING + 7) >> 3); }
138 
139  virtual void grow(size_t space) { Tree.grow((first_bit_after(space) + END_PADDING + 7) >> 3); }
140 
141  virtual void reserve(size_t space) { Tree.reserve((first_bit_after(space) + END_PADDING + 7) >> 3); }
142 
143  virtual void trim(size_t space) { Tree.trim((first_bit_after(space) + END_PADDING + 7) >> 3); };
144 
145  virtual void trimToFit() { trim(Size); };
146 
147  virtual void resize(size_t space) { Tree.resize((first_bit_after(space) + END_PADDING + 7) >> 3); }
148 
149  virtual void size(size_t space) { Tree.size((first_bit_after(space) + END_PADDING + 7) >> 3); };
150 
151  virtual size_t size() const { return Size; }
152 
153  virtual size_t bitCount() const { return Tree.bitCount() - sizeof(Tree) * 8 + sizeof(*this) * 8; }
154 
155  private:
156  inline static size_t holes(size_t idx) { return STARTING_OFFSET + (idx >> 14) * 64; }
157 
158  inline static size_t first_bit_after(size_t idx) { return (BOUNDSIZE + 1) * idx - nu(idx) + holes(idx); }
159 
160  inline uint64_t getPartialFrequency(size_t idx) const {
161  const uint64_t mask = (UINT64_C(1) << (BOUNDSIZE + rho(idx))) - 1;
162  idx--;
163  const uint64_t prod = (BOUNDSIZE + 1) * idx;
164  const uint64_t pos = prod - nu(idx) + holes(idx);
165 
166  uint64_t t;
167  if ((prod + (BOUNDSIZE + 1)) % 64 == 0) {
168  memcpy(&t, (uint64_t *)&Tree[0] + pos / 64, 8);
169  return t >> (pos % 64) & mask;
170  } else {
171  memcpy(&t, &Tree[0] + pos / 8, 8);
172  return t >> (pos % 8) & mask;
173  }
174  }
175 
176  inline void addToPartialFrequency(size_t idx, uint64_t value) {
177  idx--;
178  const uint64_t prod = (BOUNDSIZE + 1) * idx;
179  const uint64_t pos = prod - nu(idx) + holes(idx);
180 
181  uint64_t t;
182  if ((prod + (BOUNDSIZE + 1)) % 64 == 0) {
183  uint64_t *const p = (uint64_t *)&Tree[0] + pos / 64;
184  memcpy(&t, p, 8);
185  t += value << (pos % 64);
186  memcpy(p, &t, 8);
187  } else {
188  uint8_t *const p = &Tree[0] + pos / 8;
189  memcpy(&t, p, 8);
190  t += value << (pos % 8);
191  memcpy(p, &t, 8);
192  }
193  }
194 
195  friend std::ostream &operator<<(std::ostream &os, const FenwickBitF<BOUND, AT> &ft) {
196  os.write((char *)&ft.Size, sizeof(uint64_t));
197  return os << ft.Tree;
198  }
199 
200  friend std::istream &operator>>(std::istream &is, FenwickBitF<BOUND, AT> &ft) {
201  is.read((char *)&ft.Size, sizeof(uint64_t));
202  return is >> ft.Tree;
203  }
204 };
205 
206 } // namespace sux::util
sux::util::FenwickBitF::add
virtual void add(size_t idx, int64_t inc)
Definition: FenwickBitF.hpp:84
sux::util::FenwickBitF::FenwickBitF
FenwickBitF(uint64_t sequence[], size_t size)
Definition: FenwickBitF.hpp:66
sux::rho
int rho(uint64_t word)
Definition: common.hpp:168
sux::util::FenwickBitF::operator>>
friend std::istream & operator>>(std::istream &is, FenwickBitF< BOUND, AT > &ft)
Definition: FenwickBitF.hpp:200
sux::util
Definition: Expandable.hpp:37
sux::util::FenwickBitF::size
virtual void size(size_t space)
Definition: FenwickBitF.hpp:149
Vector.hpp
sux::util::Expandable
Definition: Expandable.hpp:43
sux::util::FenwickBitF::trimToFit
virtual void trimToFit()
Definition: FenwickBitF.hpp:145
sux::util::FenwickBitF::push
virtual void push(uint64_t val)
Definition: FenwickBitF.hpp:128
sux::util::SearchablePrefixSums::find
virtual size_t find(uint64_t *val)=0
sux::mask_lambda
uint64_t mask_lambda(uint64_t word)
Definition: common.hpp:216
sux::util::FenwickBitF::reserve
virtual void reserve(size_t space)
Definition: FenwickBitF.hpp:141
sux::util::FenwickBitF::compFind
virtual size_t compFind(uint64_t *val)
Definition: FenwickBitF.hpp:110
sux::util::Vector::reserve
void reserve(size_t capacity)
Definition: Vector.hpp:141
sux::util::FenwickBitF::grow
virtual void grow(size_t space)
Definition: FenwickBitF.hpp:139
sux::util::Vector::size
void size(size_t size)
Definition: Vector.hpp:178
sux::util::FenwickBitF::STARTING_OFFSET
static constexpr size_t STARTING_OFFSET
Definition: FenwickBitF.hpp:45
sux::util::Vector::grow
void grow(size_t capacity)
Definition: Vector.hpp:153
sux::util::FenwickBitF::trim
virtual void trim(size_t space)
Definition: FenwickBitF.hpp:143
sux::util::FenwickBitF
Definition: FenwickBitF.hpp:42
sux::util::FenwickBitF::find
virtual size_t find(uint64_t *val)
Definition: FenwickBitF.hpp:92
SearchablePrefixSums.hpp
sux::util::FenwickBitF::END_PADDING
static constexpr size_t END_PADDING
Definition: FenwickBitF.hpp:46
sux::ceil_log2_plus1
constexpr size_t ceil_log2_plus1(size_t n)
Definition: common.hpp:100
sux::util::FenwickBitF::Tree
Vector< uint8_t, AT > Tree
Definition: FenwickBitF.hpp:47
sux::util::Vector::bitCount
size_t bitCount() const
Definition: Vector.hpp:231
sux::clear_rho
uint64_t clear_rho(uint64_t word)
Definition: common.hpp:194
sux::util::SearchablePrefixSums
Definition: SearchablePrefixSums.hpp:53
sux::nu
int nu(uint64_t word)
Definition: common.hpp:339
sux::util::Vector::resize
void resize(size_t size)
Definition: Vector.hpp:166
sux::util::FenwickBitF::FenwickBitF
FenwickBitF()
Definition: FenwickBitF.hpp:55
sux::util::FenwickBitF::bitCount
virtual size_t bitCount() const
Definition: FenwickBitF.hpp:153
sux::util::FenwickBitF::resize
virtual void resize(size_t space)
Definition: FenwickBitF.hpp:147
sux::mask_rho
uint64_t mask_rho(uint64_t word)
Definition: common.hpp:208
sux::util::FenwickBitF::BOUNDSIZE
static constexpr size_t BOUNDSIZE
Definition: FenwickBitF.hpp:44
sux::util::FenwickBitF::Size
size_t Size
Definition: FenwickBitF.hpp:51
sux::util::FenwickBitF::size
virtual size_t size() const
Definition: FenwickBitF.hpp:151
sux::util::Vector< uint8_t, AT >
sux::util::Vector::trim
void trim(size_t capacity)
Definition: Vector.hpp:127
sux::util::FenwickBitF::pop
virtual void pop()
Definition: FenwickBitF.hpp:137
sux::util::FenwickBitF::operator<<
friend std::ostream & operator<<(std::ostream &os, const FenwickBitF< BOUND, AT > &ft)
Definition: FenwickBitF.hpp:195
sux::util::SearchablePrefixSums::compFind
virtual size_t compFind(uint64_t *val)=0
sux::util::FenwickBitF::prefix
virtual uint64_t prefix(size_t idx)
Definition: FenwickBitF.hpp:73