GCC Code Coverage Report


Directory: src/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 0.0% 0 / 0 / 57
Functions: -% 0 / 0 / 0
Branches: -% 0 / 0 / 0

ds/bit.hpp
Line Branch Exec Source
1 #pragma once
2
3 #include <vector>
4 #include <cassert>
5
6 namespace wala {
7
8 /** Binary-indexed tree
9 *
10 * A binary indexed tree with N nodes of type T provides the
11 * following two functions for 0 <= i <= N:
12 *
13 * prefix(int i) -> prefix_iterator<T>
14 * suffix(int i) -> suffix_iterator<T>
15 *
16 * such that size(suffix(i) intersect prefix(j)) = (1 if i < j else 0).
17 * Furthermore, the resulting lists always have size at most log_2(N).
18 *
19 * This can be used to implement either point-update/(prefix|suffix)-query or
20 * (prefix|suffix)-update/point-query over a virtual array of size N of a
21 * commutative monoid. This can be generalized to implement
22 * point-update/range-query or range-update/point-query over a virtual array
23 * of size N of a commutative group.
24 *
25 * With 0-indexed data, prefixes are more natural:
26 * * For range update/query, use for_prefix for the ranges and for_suffix for the points.
27 * * For prefix update/query, no change.
28 * * For suffix update/query, use for_prefix(point + 1); 1-index the data.
29 */
30 template <typename T> class binary_indexed_tree {
31 private:
32 std::vector<T> dat;
33
34 public:
35 ✗ binary_indexed_tree() {}
36 ✗ explicit binary_indexed_tree(size_t N) : dat(N) {}
37 ✗ binary_indexed_tree(size_t N, const T& t) : dat(N, t) {}
38
39 ✗ size_t size() const { return dat.size(); }
40 ✗ const std::vector<T>& data() const { return dat; }
41 ✗ std::vector<T>& data() { return dat; }
42
43 private:
44 template <typename I, typename S = I> struct iterator_range {
45 private:
46 I begin_;
47 S end_;
48
49 public:
50 ✗ iterator_range() : begin_(), end_() {}
51 ✗ iterator_range(const I& begin__, const S& end__) : begin_(begin__), end_(end__) {}
52 ✗ iterator_range(I&& begin__, S&& end__) : begin_(begin__), end_(end__) {}
53 ✗ I begin() const { return begin_; }
54 ✗ S end() const { return end_; }
55 };
56
57 public:
58 class const_suffix_iterator {
59 private:
60 const T* dat;
61 int a;
62 ✗ const_suffix_iterator(const T* dat_, int a_) : dat(dat_), a(a_) {}
63 friend class binary_indexed_tree;
64
65 public:
66 ✗ friend bool operator != (const const_suffix_iterator& i, const const_suffix_iterator& j) {
67 ✗ assert(j.dat == nullptr);
68 ✗ return i.a < j.a;
69 }
70 ✗ const_suffix_iterator& operator ++ () {
71 ✗ a |= a+1;
72 ✗ return *this;
73 }
74 ✗ const T& operator * () const {
75 ✗ return dat[a];
76 }
77 };
78 using const_suffix_range = iterator_range<const_suffix_iterator>;
79 ✗ const_suffix_range suffix(int a) const {
80 ✗ assert(0 <= a && a <= int(dat.size()));
81 ✗ return const_suffix_range{const_suffix_iterator{dat.data(), a}, const_suffix_iterator{nullptr, int(dat.size())}};
82 }
83
84 class suffix_iterator {
85 private:
86 T* dat;
87 int a;
88 ✗ suffix_iterator(T* dat_, int a_) : dat(dat_), a(a_) {}
89 friend class binary_indexed_tree;
90
91 public:
92 ✗ friend bool operator != (const suffix_iterator& i, const suffix_iterator& j) {
93 ✗ assert(j.dat == nullptr);
94 ✗ return i.a < j.a;
95 }
96 ✗ suffix_iterator& operator ++ () {
97 ✗ a |= a+1;
98 ✗ return *this;
99 }
100 ✗ T& operator * () const {
101 ✗ return dat[a];
102 }
103 };
104 using suffix_range = iterator_range<suffix_iterator>;
105 ✗ suffix_range suffix(int a) {
106 ✗ assert(0 <= a && a <= int(dat.size()));
107 ✗ return suffix_range{suffix_iterator{dat.data(), a}, suffix_iterator{nullptr, int(dat.size())}};
108 }
109
110 class const_prefix_iterator {
111 private:
112 const T* dat;
113 int a;
114 ✗ const_prefix_iterator(const T* dat_, int a_) : dat(dat_), a(a_) {}
115 friend class binary_indexed_tree;
116
117 public:
118 ✗ friend bool operator != (const const_prefix_iterator& i, const const_prefix_iterator& j) {
119 ✗ assert(j.dat == nullptr);
120 ✗ return i.a > 0;
121 }
122 ✗ const_prefix_iterator& operator ++ () {
123 ✗ a &= a-1;
124 ✗ return *this;
125 }
126 ✗ const T& operator * () const {
127 ✗ return dat[a-1];
128 }
129 };
130 using const_prefix_range = iterator_range<const_prefix_iterator>;
131 ✗ const_prefix_range prefix(int a) const {
132 ✗ return const_prefix_range{const_prefix_iterator{dat.data(), a}, const_prefix_iterator{nullptr, 0}};
133 }
134
135 class prefix_iterator {
136 private:
137 T* dat;
138 int a;
139 ✗ prefix_iterator(T* dat_, int a_) : dat(dat_), a(a_) {}
140 friend class binary_indexed_tree;
141
142 public:
143 ✗ friend bool operator != (const prefix_iterator& i, const prefix_iterator& j) {
144 ✗ assert(j.dat == nullptr);
145 ✗ return i.a > 0;
146 }
147 ✗ prefix_iterator& operator ++ () {
148 ✗ a &= a-1;
149 ✗ return *this;
150 }
151 ✗ T& operator * () const {
152 ✗ return dat[a-1];
153 }
154 };
155 using prefix_range = iterator_range<prefix_iterator>;
156 ✗ prefix_range prefix(int a) {
157 ✗ return prefix_range{prefix_iterator{dat.data(), a}, prefix_iterator{nullptr, 0}};
158 }
159 };
160
161 } // namespace wala
162