Coverage Report

Created: 2026-03-31 06:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/rdkit/Code/DataStructs/ExplicitBitVect.cpp
Line
Count
Source
1
// $Id$
2
//
3
// Copyright (c) 2001-2008 greg Landrum and Rational Discovery LLC
4
//  Copyright (c) 2014, Novartis Institutes for BioMedical Research Inc.
5
//
6
//  @@ All Rights Reserved @@
7
//  This file is part of the RDKit.
8
//  The contents are covered by the terms of the BSD license
9
//  which is included in the file license.txt, found at the root
10
//  of the RDKit source tree.
11
//
12
#include <RDGeneral/Exceptions.h>
13
#include "ExplicitBitVect.h"
14
#include <RDGeneral/StreamOps.h>
15
#include "base64.h"
16
#include <sstream>
17
#include <limits>
18
#ifdef WIN32
19
#include <ios>
20
#endif
21
#include <cstdint>
22
23
0
ExplicitBitVect::ExplicitBitVect(unsigned int size, bool bitsSet) {
24
0
  d_size = 0;
25
0
  dp_bits = nullptr;
26
0
  d_numOnBits = 0;
27
0
  _initForSize(size);
28
0
  if (bitsSet) {
29
0
    dp_bits->set();  // set all bits to 1
30
0
    d_numOnBits = size;
31
0
  }
32
0
}
33
0
ExplicitBitVect::ExplicitBitVect(const std::string &s) {
34
0
  d_size = 0;
35
0
  dp_bits = nullptr;
36
0
  d_numOnBits = 0;
37
0
  initFromText(s.c_str(), s.length());
38
0
}
39
0
ExplicitBitVect::ExplicitBitVect(const char *data, const unsigned int dataLen) {
40
0
  d_size = 0;
41
0
  dp_bits = nullptr;
42
0
  d_numOnBits = 0;
43
0
  initFromText(data, dataLen);
44
0
}
45
46
ExplicitBitVect::ExplicitBitVect(const ExplicitBitVect &other)
47
0
    : BitVect(other) {
48
0
  d_size = other.d_size;
49
0
  dp_bits.reset(new boost::dynamic_bitset<>(*(other.dp_bits)));
50
0
  d_numOnBits = other.d_numOnBits;
51
0
}
52
53
ExplicitBitVect::ExplicitBitVect(ExplicitBitVect &&other) noexcept
54
0
    : dp_bits(std::move(other.dp_bits)),
55
0
      d_size(other.d_size),
56
0
      d_numOnBits(other.d_numOnBits) {}
57
58
0
ExplicitBitVect &ExplicitBitVect::operator=(const ExplicitBitVect &other) {
59
0
  if (this == &other) {
60
0
    return *this;
61
0
  }
62
0
  d_size = other.d_size;
63
0
  dp_bits.reset(new boost::dynamic_bitset<>(*(other.dp_bits)));
64
0
  d_numOnBits = other.d_numOnBits;
65
0
  return *this;
66
0
}
67
68
0
ExplicitBitVect &ExplicitBitVect::operator=(ExplicitBitVect &&other) noexcept {
69
0
  if (this == &other) {
70
0
    return *this;
71
0
  }
72
0
  d_size = other.d_size;
73
0
  dp_bits = std::move(other.dp_bits);
74
0
  d_numOnBits = other.d_numOnBits;
75
0
  return *this;
76
0
}
77
78
0
bool ExplicitBitVect::operator[](const unsigned int which) const {
79
0
  if (which >= d_size) {
80
0
    throw IndexErrorException(which);
81
0
  }
82
0
  return (bool)(*dp_bits)[which];
83
0
}
84
0
bool ExplicitBitVect::setBit(const unsigned int which) {
85
0
  if (which >= d_size) {
86
0
    throw IndexErrorException(which);
87
0
  }
88
0
  if ((bool)(*dp_bits)[which]) {
89
0
    return true;
90
0
  } else {
91
0
    (*dp_bits)[which] = 1;
92
0
    ++d_numOnBits;
93
0
    return false;
94
0
  }
95
0
}
96
0
bool ExplicitBitVect::unsetBit(const unsigned int which) {
97
0
  if (which >= d_size) {
98
0
    throw IndexErrorException(which);
99
0
  }
100
0
  if ((bool)(*dp_bits)[which]) {
101
0
    (*dp_bits)[which] = 0;
102
0
    --d_numOnBits;
103
0
    return true;
104
0
  } else {
105
0
    return false;
106
0
  }
107
0
}
108
0
bool ExplicitBitVect::getBit(const unsigned int which) const {
109
0
  if (which >= d_size) {
110
0
    throw IndexErrorException(which);
111
0
  }
112
0
  return ((bool)(*dp_bits)[which]);
113
0
}
114
115
0
ExplicitBitVect ExplicitBitVect::operator^(const ExplicitBitVect &other) const {
116
0
  ExplicitBitVect ans(d_size);
117
0
  *(ans.dp_bits) = (*dp_bits) ^ *(other.dp_bits);
118
0
  ans.d_numOnBits = ans.dp_bits->count();
119
0
  return (ans);
120
0
}
121
122
0
ExplicitBitVect ExplicitBitVect::operator&(const ExplicitBitVect &other) const {
123
0
  ExplicitBitVect ans(d_size);
124
0
  *(ans.dp_bits) = (*dp_bits) & *(other.dp_bits);
125
0
  ans.d_numOnBits = ans.dp_bits->count();
126
0
  return (ans);
127
0
}
128
129
0
ExplicitBitVect ExplicitBitVect::operator|(const ExplicitBitVect &other) const {
130
0
  ExplicitBitVect ans(d_size);
131
0
  *(ans.dp_bits) = (*dp_bits) | *(other.dp_bits);
132
0
  ans.d_numOnBits = ans.dp_bits->count();
133
0
  return (ans);
134
0
}
135
136
0
ExplicitBitVect &ExplicitBitVect::operator^=(const ExplicitBitVect &other) {
137
0
  *(dp_bits) ^= *(other.dp_bits);
138
0
  d_numOnBits = dp_bits->count();
139
0
  return *this;
140
0
}
141
142
0
ExplicitBitVect &ExplicitBitVect::operator&=(const ExplicitBitVect &other) {
143
0
  *(dp_bits) &= *(other.dp_bits);
144
0
  d_numOnBits = dp_bits->count();
145
0
  return *this;
146
0
}
147
148
0
ExplicitBitVect &ExplicitBitVect::operator|=(const ExplicitBitVect &other) {
149
0
  *(dp_bits) |= *(other.dp_bits);
150
0
  d_numOnBits = dp_bits->count();
151
0
  return *this;
152
0
}
153
154
0
ExplicitBitVect ExplicitBitVect::operator~() const {
155
0
  ExplicitBitVect ans(d_size);
156
0
  *(ans.dp_bits) = ~(*dp_bits);
157
0
  ans.d_numOnBits = ans.dp_bits->count();
158
0
  return (ans);
159
0
};
160
161
0
ExplicitBitVect &ExplicitBitVect::operator+=(const ExplicitBitVect &other) {
162
0
  dp_bits->resize(d_size + other.d_size);
163
0
  unsigned int original_size = d_size;
164
0
  d_size = dp_bits->size();
165
0
  for (unsigned i = 0; i < other.d_size; i++) {
166
0
    if (other[i]) {
167
0
      setBit(i + original_size);
168
0
    }
169
0
  }
170
0
  d_numOnBits = dp_bits->count();
171
0
  return *this;
172
0
}
173
174
0
ExplicitBitVect ExplicitBitVect::operator+(const ExplicitBitVect &other) const {
175
0
  ExplicitBitVect ans(*this);
176
0
  return ans += other;
177
0
}
178
179
0
unsigned int ExplicitBitVect::getNumBits() const { return d_size; };
180
0
unsigned int ExplicitBitVect::getNumOnBits() const { return d_numOnBits; };
181
0
unsigned int ExplicitBitVect::getNumOffBits() const {
182
0
  return d_size - d_numOnBits;
183
0
}
184
185
// the contents of v are blown out
186
0
void ExplicitBitVect::getOnBits(IntVect &v) const {
187
0
  unsigned int nOn = getNumOnBits();
188
0
  if (!v.empty()) {
189
0
    IntVect().swap(v);
190
0
  }
191
0
  v.reserve(nOn);
192
0
  for (unsigned int i = 0; i < d_size; i++) {
193
0
    if ((bool)(*dp_bits)[i]) {
194
0
      v.push_back(i);
195
0
    }
196
0
  }
197
0
}
198
199
0
void ExplicitBitVect::_initForSize(unsigned int size) {
200
0
  d_size = size;
201
0
  dp_bits.reset(new boost::dynamic_bitset<>(size));
202
0
  d_numOnBits = 0;
203
0
}
204
205
0
ExplicitBitVect::~ExplicitBitVect() {}
206
207
0
std::string ExplicitBitVect::toString() const {
208
  // This Function replaces the older version (version 16) of writing the onbits
209
  // to a string.  The old version does not perform any run length encoding, it
210
  // only checks to see if the length of the bitvect can be short ints and
211
  // writes the on bits as shorts otherwise the onbits are all written as ints.
212
213
  // Here we do run length encoding and the version number has been bumped to 32
214
  // as well. Only the reader needs to take care of reading all legacy versions.
215
  // Also in this scheme each bit number written to the string is checked to see
216
  // how many bytes it needs
217
0
  std::stringstream ss(std::ios_base::binary | std::ios_base::out |
218
0
                       std::ios_base::in);
219
220
0
  std::int32_t tInt = ci_BITVECT_VERSION * -1;
221
0
  RDKit::streamWrite(ss, tInt);
222
0
  tInt = d_size;
223
0
  RDKit::streamWrite(ss, tInt);
224
0
  tInt = getNumOnBits();
225
0
  RDKit::streamWrite(ss, tInt);
226
227
0
  int prev = -1;
228
0
  unsigned int zeroes;
229
0
  for (unsigned int i = 0; i < d_size; i++) {
230
0
    if ((bool)(*dp_bits)[i]) {
231
0
      zeroes = i - prev - 1;
232
0
      RDKit::appendPackedIntToStream(ss, zeroes);
233
0
      prev = i;
234
0
    }
235
0
  }
236
0
  zeroes = d_size - prev - 1;
237
0
  RDKit::appendPackedIntToStream(ss, zeroes);
238
0
  std::string res(ss.str());
239
0
  return res;
240
0
}