Coverage Report

Created: 2026-11-12 07:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/rdkit/Code/DataStructs/SparseBitVect.cpp
Line
Count
Source
1
//
2
// Copyright (c) 2001-2024 greg Landrum and other RDKit contributors
3
//
4
//  @@ All Rights Reserved @@
5
//  This file is part of the RDKit.
6
//  The contents are covered by the terms of the BSD license
7
//  which is included in the file license.txt, found at the root
8
//  of the RDKit source tree.
9
//
10
#include "SparseBitVect.h"
11
#include <RDGeneral/Exceptions.h>
12
13
#include "base64.h"
14
#include <RDGeneral/StreamOps.h>
15
#include <sstream>
16
17
#ifdef WIN32
18
#include <ios>
19
#endif
20
#include <cstdint>
21
22
// """ -------------------------------------------------------
23
//
24
// Construct a SparseBitVect from a binary string.
25
//   The format of the string should be
26
//   the format produced by SparseBitVect::toString
27
//
28
// """ -------------------------------------------------------
29
0
SparseBitVect::SparseBitVect(const std::string &s) {
30
0
  d_size = 0;
31
0
  dp_bits = nullptr;
32
0
  initFromText(s.c_str(), s.length());
33
0
}
34
35
// """ -------------------------------------------------------
36
//
37
// Construct a SparseBitVect from a binary string stored as a char *.
38
//   The format of the string should be
39
//   the format produced by SparseBitVect::toString
40
//
41
// """ -------------------------------------------------------
42
0
SparseBitVect::SparseBitVect(const char *data, const unsigned int dataLen) {
43
0
  d_size = 0;
44
0
  dp_bits = nullptr;
45
0
  initFromText(data, dataLen);
46
0
}
47
48
// """ -------------------------------------------------------
49
//
50
//  Operator[]
51
//   Returns the state of the ith bit.
52
//
53
//   **C++ NOTE** The state of BitVects cannot be changed using
54
//    operator&.  So this will not work:
55
//     SBV[i] = 0;
56
//    In Python this type of assignment **is** valid.
57
//
58
// """ -------------------------------------------------------
59
0
bool SparseBitVect::operator[](const unsigned int which) const {
60
0
  if (which >= d_size) {
61
0
    throw IndexErrorException(which);
62
0
  }
63
0
  return dp_bits->count(which) > 0u;
64
0
}
65
66
// """ -------------------------------------------------------
67
//
68
//  Assignment operator
69
//    The bits of the other SBV are copied.
70
//
71
// """ -------------------------------------------------------
72
0
SparseBitVect &SparseBitVect::operator=(const SparseBitVect &other) {
73
0
  if (this == &other) {
74
0
    return *this;
75
0
  }
76
0
  IntSet *bv = other.dp_bits;
77
0
  delete dp_bits;
78
0
  d_size = other.getNumBits();
79
0
  dp_bits = new IntSet;
80
0
  std::copy(bv->begin(), bv->end(), std::inserter(*dp_bits, dp_bits->end()));
81
82
0
  return *this;
83
0
}
84
85
// -------------------------------------------------------
86
//
87
//  Operator|
88
//   allows SBV3 = SBV1|SBV2;
89
//
90
// -------------------------------------------------------
91
0
SparseBitVect SparseBitVect::operator|(const SparseBitVect &other) const {
92
0
  SparseBitVect ans(d_size);
93
0
  std::set_union(dp_bits->begin(), dp_bits->end(), other.dp_bits->begin(),
94
0
                 other.dp_bits->end(),
95
0
                 std::inserter(*(ans.dp_bits), ans.dp_bits->end()));
96
0
  return ans;
97
0
}
98
99
// """ -------------------------------------------------------
100
//
101
//  Operator&
102
//   allows SBV3 = SBV1&SBV2;
103
//
104
// """ -------------------------------------------------------
105
0
SparseBitVect SparseBitVect::operator&(const SparseBitVect &other) const {
106
0
  SparseBitVect ans(d_size);
107
0
  std::set_intersection(dp_bits->begin(), dp_bits->end(),
108
0
                        other.dp_bits->begin(), other.dp_bits->end(),
109
0
                        std::inserter(*(ans.dp_bits), ans.dp_bits->end()));
110
0
  return ans;
111
0
}
112
113
// """ -------------------------------------------------------
114
//
115
//  Operator^
116
//   allows SBV3 = SBV1^SBV2;
117
//
118
// """ -------------------------------------------------------
119
0
SparseBitVect SparseBitVect::operator^(const SparseBitVect &other) const {
120
0
  SparseBitVect ans(d_size);
121
0
  std::set_symmetric_difference(
122
0
      dp_bits->begin(), dp_bits->end(), other.dp_bits->begin(),
123
0
      other.dp_bits->end(), std::inserter(*(ans.dp_bits), ans.dp_bits->end()));
124
0
  return (ans);
125
0
}
126
127
// """ -------------------------------------------------------
128
//
129
//  Operator~  (the negation operator)
130
//   allows SBV2 = ~SBV1;
131
//
132
// """ -------------------------------------------------------
133
0
SparseBitVect SparseBitVect::operator~() const {
134
0
  SparseBitVect ans(d_size);
135
0
  for (unsigned int i = 0; i < d_size; i++) {
136
0
    if (!getBit(i)) {
137
0
      ans.setBit(i);
138
0
    }
139
0
  }
140
141
0
  return (ans);
142
0
}
143
144
// """ -------------------------------------------------------
145
//
146
// getBit(int which)
147
//   Returns the state of bit which
148
//
149
// """ -------------------------------------------------------
150
0
bool SparseBitVect::getBit(const unsigned int which) const {
151
0
  if (!checkIndex(which)) {
152
0
    throw IndexErrorException(which);
153
0
  }
154
0
  return dp_bits->count(which) > 0u;
155
0
}
156
157
// """ -------------------------------------------------------
158
//
159
// getBit(const IntVectIter which)  (C++ SPECIFIC)
160
//   Returns the state of bit which
161
//
162
// """ -------------------------------------------------------
163
0
bool SparseBitVect::getBit(const IntVectIter which) const {
164
0
  if (!checkIndex(which)) {
165
0
    throw IndexErrorException(*which);
166
0
  }
167
0
  return dp_bits->count(*which) > 0u;
168
0
}
169
170
// """ -------------------------------------------------------
171
//
172
// getBit(const IntSetIter which)  (C++ SPECIFIC)
173
//   Returns the state of bit which
174
//
175
// """ -------------------------------------------------------
176
0
bool SparseBitVect::getBit(const IntSetIter which) const {
177
0
  if (!checkIndex(which)) {
178
0
    throw IndexErrorException(*which);
179
0
  }
180
0
  return dp_bits->count(*which) > 0u;
181
0
}
182
183
// """ -------------------------------------------------------
184
//
185
//  Sets bit which to be on.
186
//
187
//  Returns the original state of the bit
188
//
189
// """ -------------------------------------------------------
190
0
bool SparseBitVect::setBit(const unsigned int which) {
191
0
  if (!dp_bits) {
192
0
    throw ValueErrorException("BitVect not properly initialized.");
193
0
  }
194
0
  if (!checkIndex(which)) {
195
0
    throw IndexErrorException(which);
196
0
  }
197
0
  auto res = dp_bits->insert(which);
198
0
  return !(res.second);
199
0
}
200
201
// """ -------------------------------------------------------
202
//
203
// setBit(const IntSetIter which)  (C++ SPECIFIC)
204
//  Sets bit which to be on.
205
//
206
//  Returns the original state of the bit
207
//
208
// """ -------------------------------------------------------
209
0
bool SparseBitVect::setBit(const IntSetIter which) {
210
0
  if (!dp_bits) {
211
0
    throw ValueErrorException("BitVect not properly initialized.");
212
0
  }
213
0
  if (!checkIndex(which)) {
214
0
    throw IndexErrorException(*which);
215
0
  }
216
0
  auto res = dp_bits->insert(*which);
217
0
  return !(res.second);
218
0
}
219
220
// """ -------------------------------------------------------
221
//
222
//  Sets bit which to be off.
223
//
224
//  Returns the original state of the bit
225
//
226
// """ -------------------------------------------------------
227
0
bool SparseBitVect::unsetBit(const unsigned int which) {
228
0
  if (!dp_bits) {
229
0
    throw ValueErrorException("BitVect not properly initialized.");
230
0
  }
231
0
  if (!checkIndex(which)) {
232
0
    throw IndexErrorException(which);
233
0
  }
234
235
0
  if (dp_bits->count(which)) {
236
0
    dp_bits->erase(dp_bits->find(which));
237
0
    return true;
238
0
  } else {
239
0
    return false;
240
0
  }
241
0
}
242
243
// """ -------------------------------------------------------
244
//
245
// getOnBits(IntVect &which)
246
//  C++: Passes the set of on bits out in the IntVect passed in.
247
//   The contents of IntVect are destroyed.
248
//
249
//  Python: Returns the tuple of on bits
250
//
251
// """ -------------------------------------------------------
252
0
void SparseBitVect::getOnBits(IntVect &v) const {
253
0
  if (!dp_bits) {
254
0
    throw ValueErrorException("BitVect not properly initialized.");
255
0
  }
256
0
  unsigned int nOn = getNumOnBits();
257
0
  if (!v.empty()) {
258
0
    IntVect().swap(v);
259
0
  }
260
0
  v.reserve(nOn);
261
0
  v.resize(nOn);
262
0
  std::copy(dp_bits->begin(), dp_bits->end(), v.begin());
263
0
};
264
265
// """ -------------------------------------------------------
266
//
267
// toString()
268
//  Returns a binary string with the contents of the BitVector
269
//
270
// """ -------------------------------------------------------
271
0
std::string SparseBitVect::toString() const {
272
  // This Function replaces the older version (version 16) of writing the onbits
273
  // to
274
  // a string
275
  // the old version does not perform any run length encoding, it only checks to
276
  // see if
277
  // the length of the bitvect can be short ints and writes the on bits as
278
  // shorts
279
  // other wise the onbits are all written as ints
280
281
  // here we do run length encoding and the version number has been bumped to 32
282
  // as well.
283
  // only the reader needs to take care of readinf all legacy versions
284
  // also in this scheme each bit number written to the string is checked to see
285
  // how many
286
  // bytes it needs
287
0
  std::stringstream ss(std::ios_base::binary | std::ios_base::out |
288
0
                       std::ios_base::in);
289
290
0
  std::int32_t tInt = ci_BITVECT_VERSION * -1;
291
0
  RDKit::streamWrite(ss, tInt);
292
0
  tInt = d_size;
293
0
  RDKit::streamWrite(ss, tInt);
294
0
  tInt = getNumOnBits();
295
0
  RDKit::streamWrite(ss, tInt);
296
297
0
  int prev = -1;
298
0
  unsigned int zeroes;
299
0
  for (int dp_bit : *dp_bits) {
300
0
    zeroes = dp_bit - prev - 1;
301
0
    RDKit::appendPackedIntToStream(ss, zeroes);
302
0
    prev = dp_bit;
303
0
  }
304
0
  zeroes = d_size - prev - 1;
305
0
  RDKit::appendPackedIntToStream(ss, zeroes);
306
307
0
  std::string res(ss.str());
308
0
  return res;
309
0
}
310
311
0
void SparseBitVect::_initForSize(unsigned int size) {
312
0
  d_size = size;
313
0
  delete dp_bits;
314
0
  dp_bits = new IntSet;
315
0
};