Sux
FenwickByteF.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 
34 namespace sux::util {
35 
41 template <size_t BOUND, AllocType AT = MALLOC> class FenwickByteF : public SearchablePrefixSums, public Expandable {
42  public:
43  static constexpr size_t BOUNDSIZE = ceil_log2_plus1(BOUND);
44  static_assert(BOUNDSIZE >= 1 && BOUNDSIZE <= 64, "Leaves can't be stored in a 64-bit word");
45 
46  protected:
48  size_t Size;
49 
50  public:
52  FenwickByteF() : Tree(0), Size(0) {}
53 
62  FenwickByteF(uint64_t sequence[], size_t size) : Tree(pos(size + 1) + 8), Size(size) {
63  for (size_t i = 1; i <= Size; i++) bytewrite(&Tree[pos(i)], bytesize(i), sequence[i - 1]);
64 
65  for (size_t m = 2; m <= Size; m <<= 1) {
66  for (size_t idx = m; idx <= Size; idx += m) {
67  const uint64_t left = byteread(&Tree[pos(idx)], bytesize(idx));
68  const uint64_t right = byteread(&Tree[pos(idx - m / 2)], bytesize(idx - m / 2));
69  bytewrite(&Tree[pos(idx)], bytesize(idx), left + right);
70  }
71  }
72  }
73 
74  virtual uint64_t prefix(size_t idx) {
75  uint64_t sum = 0;
76 
77  while (idx != 0) {
78  sum += byteread(&Tree[pos(idx)], bytesize(idx));
79  idx = clear_rho(idx);
80  }
81 
82  return sum;
83  }
84 
85  virtual void add(size_t idx, int64_t inc) {
86  while (idx <= Size) {
87  bytewrite_inc(&Tree[pos(idx)], inc);
88  idx += mask_rho(idx);
89  }
90  }
91 
93  virtual size_t find(uint64_t *val) {
94  size_t node = 0;
95 
96  for (size_t m = mask_lambda(Size); m != 0; m >>= 1) {
97  if (node + m > Size) continue;
98 
99  const uint64_t value = byteread(&Tree[pos(node + m)], bytesize(node + m));
100 
101  if (*val >= value) {
102  node += m;
103  *val -= value;
104  }
105  }
106 
107  return node;
108  }
109 
111  virtual size_t compFind(uint64_t *val) {
112  size_t node = 0;
113 
114  for (size_t m = mask_lambda(Size); m != 0; m >>= 1) {
115  if (node + m > Size) continue;
116 
117  const uint64_t value = (BOUND << rho(node + m)) - byteread(&Tree[pos(node + m)], bytesize(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  size_t p = pos(++Size);
130  Tree.resize(p + 8);
131  bytewrite(&Tree[p], bytesize(Size), val);
132 
133  if ((Size & 1) == 0) {
134  for (size_t idx = Size - 1; rho(idx) < rho(Size); idx = clear_rho(idx)) {
135  uint64_t inc = byteread(&Tree[pos(idx)], bytesize(idx));
136  bytewrite_inc(&Tree[p], inc);
137  }
138  }
139  }
140 
141  virtual void pop() { Size--; }
142 
143  virtual void grow(size_t space) { Tree.grow(pos(space) + 8); }
144 
145  virtual void reserve(size_t space) { Tree.reserve(pos(space) + 8); }
146 
147  virtual void trim(size_t space) { Tree.trim(pos(space) + 8); };
148 
149  virtual void trimToFit() { trim(Size); };
150 
151  virtual void resize(size_t space) { Tree.resize(pos(space) + 8); }
152 
153  virtual void size(size_t space) { Tree.size(pos(space) + 8); };
154 
155  virtual size_t size() const { return Size; }
156 
157  virtual size_t bitCount() const { return Tree.bitCount() - sizeof(Tree) * 8 - sizeof(*this) * 8; }
158 
159  private:
160  static inline size_t bytesize(size_t idx) { return ((rho(idx) + BOUNDSIZE - 1) >> 3) + 1; }
161 
162  static inline size_t holes(size_t idx) {
163  // Exhaustive benchmarking shows it is better to use no holes on (relatively) small trees,
164  // but we expect holes to be handy again in (very) big trees
165  if (BOUNDSIZE >= 32) return 0;
166 
167 #ifdef HFT_DISABLE_TRANSHUGE
168  return (idx >> (18 + (64 - BOUNDSIZE) % 8));
169 #else
170  return (idx >> (28 + (64 - BOUNDSIZE) % 8));
171 #endif
172  }
173 
174  static inline size_t pos(size_t idx) {
175  idx--;
176  constexpr size_t NEXTBYTE = ((BOUNDSIZE - 1) | (8 - 1)) + 1;
177 
178  constexpr size_t SMALL = ((BOUNDSIZE - 1) >> 3) + 1;
179  constexpr size_t MEDIUM = NEXTBYTE - BOUNDSIZE + 1;
180  constexpr size_t LARGE = MEDIUM + 8;
181 
182  constexpr size_t MULTIPLIER = 8 - SMALL - 1;
183 
184  return idx * SMALL + (idx >> MEDIUM) + (idx >> LARGE) * MULTIPLIER + holes(idx);
185  }
186 
187  friend std::ostream &operator<<(std::ostream &os, const FenwickByteF<BOUND, AT> &ft) {
188  os.write((char *)&ft.Size, sizeof(uint64_t));
189  return os << ft.Tree;
190  }
191 
192  friend std::istream &operator>>(std::istream &is, FenwickByteF<BOUND, AT> &ft) {
193  is.read((char *)(&ft.Size), sizeof(uint64_t));
194  return is >> ft.Tree;
195  }
196 };
197 
198 } // namespace sux::util
sux::util::FenwickByteF::add
virtual void add(size_t idx, int64_t inc)
Definition: FenwickByteF.hpp:85
sux::util::FenwickByteF::prefix
virtual uint64_t prefix(size_t idx)
Definition: FenwickByteF.hpp:74
sux::util::FenwickByteF::reserve
virtual void reserve(size_t space)
Definition: FenwickByteF.hpp:145
sux::rho
int rho(uint64_t word)
Definition: common.hpp:168
sux::util::FenwickByteF::bitCount
virtual size_t bitCount() const
Definition: FenwickByteF.hpp:157
sux::util
Definition: Expandable.hpp:37
Vector.hpp
sux::util::FenwickByteF::BOUNDSIZE
static constexpr size_t BOUNDSIZE
Definition: FenwickByteF.hpp:43
sux::util::Expandable
Definition: Expandable.hpp:43
sux::util::FenwickByteF::grow
virtual void grow(size_t space)
Definition: FenwickByteF.hpp:143
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::FenwickByteF::Tree
Vector< uint8_t, AT > Tree
Definition: FenwickByteF.hpp:44
sux::bytewrite
void bytewrite(void *const word, int length, uint64_t val)
Definition: common.hpp:265
sux::util::FenwickByteF::trimToFit
virtual void trimToFit()
Definition: FenwickByteF.hpp:149
sux::util::FenwickByteF::FenwickByteF
FenwickByteF()
Definition: FenwickByteF.hpp:52
sux::util::Vector::reserve
void reserve(size_t capacity)
Definition: Vector.hpp:141
sux::util::Vector::size
void size(size_t size)
Definition: Vector.hpp:178
sux::util::FenwickByteF::size
virtual size_t size() const
Definition: FenwickByteF.hpp:155
sux::util::Vector::grow
void grow(size_t capacity)
Definition: Vector.hpp:153
sux::util::FenwickByteF::operator<<
friend std::ostream & operator<<(std::ostream &os, const FenwickByteF< BOUND, AT > &ft)
Definition: FenwickByteF.hpp:187
sux::util::FenwickByteF::FenwickByteF
FenwickByteF(uint64_t sequence[], size_t size)
Definition: FenwickByteF.hpp:62
SearchablePrefixSums.hpp
sux::util::FenwickByteF
Definition: FenwickByteF.hpp:41
sux::ceil_log2_plus1
constexpr size_t ceil_log2_plus1(size_t n)
Definition: common.hpp:100
sux::util::Vector::bitCount
size_t bitCount() const
Definition: Vector.hpp:231
sux::util::FenwickByteF::push
virtual void push(uint64_t val)
Definition: FenwickByteF.hpp:128
sux::clear_rho
uint64_t clear_rho(uint64_t word)
Definition: common.hpp:194
sux::util::SearchablePrefixSums
Definition: SearchablePrefixSums.hpp:53
sux::util::Vector::resize
void resize(size_t size)
Definition: Vector.hpp:166
sux::util::FenwickByteF::operator>>
friend std::istream & operator>>(std::istream &is, FenwickByteF< BOUND, AT > &ft)
Definition: FenwickByteF.hpp:192
sux::util::FenwickByteF::size
virtual void size(size_t space)
Definition: FenwickByteF.hpp:153
sux::util::FenwickByteF::Size
size_t Size
Definition: FenwickByteF.hpp:48
sux::mask_rho
uint64_t mask_rho(uint64_t word)
Definition: common.hpp:208
sux::util::FenwickByteF::resize
virtual void resize(size_t space)
Definition: FenwickByteF.hpp:151
sux::bytewrite_inc
void bytewrite_inc(void *const word, uint64_t inc)
Definition: common.hpp:273
sux::util::FenwickByteF::trim
virtual void trim(size_t space)
Definition: FenwickByteF.hpp:147
sux::util::Vector< uint8_t, AT >
sux::util::Vector::trim
void trim(size_t capacity)
Definition: Vector.hpp:127
sux::util::FenwickByteF::pop
virtual void pop()
Definition: FenwickByteF.hpp:141
sux::util::FenwickByteF::compFind
virtual size_t compFind(uint64_t *val)
Definition: FenwickByteF.hpp:111
sux::util::SearchablePrefixSums::compFind
virtual size_t compFind(uint64_t *val)=0
sux::byteread
uint64_t byteread(const void *const word, int length)
Definition: common.hpp:259
sux::util::FenwickByteF::find
virtual size_t find(uint64_t *val)
Definition: FenwickByteF.hpp:93