// $Id$ // // Copyright (c) 2001-2008 greg Landrum and Rational Discovery LLC // Copyright (c) 2014, Novartis Institutes for BioMedical Research Inc. // // @@ All Rights Reserved @@ // This file is part of the RDKit. // The contents are covered by the terms of the BSD license // which is included in the file license.txt, found at the root // of the RDKit source tree. // #include #include #include "ExplicitBitVect.h" #include #include "base64.h" #include #include #ifdef WIN32 #include #endif #include ExplicitBitVect::ExplicitBitVect(unsigned int size, bool bitsSet) { d_size = 0; dp_bits = nullptr; d_numOnBits = 0; _initForSize(size); if (bitsSet) { dp_bits->set(); // set all bits to 1 d_numOnBits = size; } } ExplicitBitVect::ExplicitBitVect(const std::string &s) { d_size = 0; dp_bits = nullptr; d_numOnBits = 0; initFromText(s.c_str(), s.length()); } ExplicitBitVect::ExplicitBitVect(const char *data, const unsigned int dataLen) { d_size = 0; dp_bits = nullptr; d_numOnBits = 0; initFromText(data, dataLen); } ExplicitBitVect::ExplicitBitVect(const ExplicitBitVect &other) : BitVect(other) { d_size = other.d_size; dp_bits.reset(new boost::dynamic_bitset<>(*(other.dp_bits))); d_numOnBits = other.d_numOnBits; } ExplicitBitVect::ExplicitBitVect(ExplicitBitVect &&other) noexcept : dp_bits(std::move(other.dp_bits)), d_size(other.d_size), d_numOnBits(other.d_numOnBits) {} ExplicitBitVect &ExplicitBitVect::operator=(const ExplicitBitVect &other) { if (this == &other) { return *this; } d_size = other.d_size; dp_bits.reset(new boost::dynamic_bitset<>(*(other.dp_bits))); d_numOnBits = other.d_numOnBits; return *this; } ExplicitBitVect &ExplicitBitVect::operator=(ExplicitBitVect &&other) noexcept { if (this == &other) { return *this; } d_size = other.d_size; dp_bits = std::move(other.dp_bits); d_numOnBits = other.d_numOnBits; return *this; } bool ExplicitBitVect::operator[](const unsigned int which) const { if (which >= d_size) { throw IndexErrorException(which); } return (bool)(*dp_bits)[which]; } bool ExplicitBitVect::setBit(const unsigned int which) { if (which >= d_size) { throw IndexErrorException(which); } if ((bool)(*dp_bits)[which]) { return true; } else { (*dp_bits)[which] = 1; ++d_numOnBits; return false; } } bool ExplicitBitVect::unsetBit(const unsigned int which) { if (which >= d_size) { throw IndexErrorException(which); } if ((bool)(*dp_bits)[which]) { (*dp_bits)[which] = 0; --d_numOnBits; return true; } else { return false; } } bool ExplicitBitVect::getBit(const unsigned int which) const { if (which >= d_size) { throw IndexErrorException(which); } return ((bool)(*dp_bits)[which]); } ExplicitBitVect ExplicitBitVect::operator^(const ExplicitBitVect &other) const { ExplicitBitVect ans(d_size); *(ans.dp_bits) = (*dp_bits) ^ *(other.dp_bits); ans.d_numOnBits = ans.dp_bits->count(); return (ans); } ExplicitBitVect ExplicitBitVect::operator&(const ExplicitBitVect &other) const { ExplicitBitVect ans(d_size); *(ans.dp_bits) = (*dp_bits) & *(other.dp_bits); ans.d_numOnBits = ans.dp_bits->count(); return (ans); } ExplicitBitVect ExplicitBitVect::operator|(const ExplicitBitVect &other) const { ExplicitBitVect ans(d_size); *(ans.dp_bits) = (*dp_bits) | *(other.dp_bits); ans.d_numOnBits = ans.dp_bits->count(); return (ans); } ExplicitBitVect &ExplicitBitVect::operator^=(const ExplicitBitVect &other) { *(dp_bits) ^= *(other.dp_bits); d_numOnBits = dp_bits->count(); return *this; } ExplicitBitVect &ExplicitBitVect::operator&=(const ExplicitBitVect &other) { *(dp_bits) &= *(other.dp_bits); d_numOnBits = dp_bits->count(); return *this; } ExplicitBitVect &ExplicitBitVect::operator|=(const ExplicitBitVect &other) { *(dp_bits) |= *(other.dp_bits); d_numOnBits = dp_bits->count(); return *this; } ExplicitBitVect ExplicitBitVect::operator~() const { ExplicitBitVect ans(d_size); *(ans.dp_bits) = ~(*dp_bits); ans.d_numOnBits = ans.dp_bits->count(); return (ans); }; ExplicitBitVect &ExplicitBitVect::operator+=(const ExplicitBitVect &other) { dp_bits->resize(d_size + other.d_size); unsigned int original_size = d_size; d_size = dp_bits->size(); for (unsigned i = 0; i < other.d_size; i++) { if (other[i]) { setBit(i + original_size); } } d_numOnBits = dp_bits->count(); return *this; } ExplicitBitVect ExplicitBitVect::operator+(const ExplicitBitVect &other) const { ExplicitBitVect ans(*this); return ans += other; } unsigned int ExplicitBitVect::getNumBits() const { return d_size; }; unsigned int ExplicitBitVect::getNumOnBits() const { return d_numOnBits; }; unsigned int ExplicitBitVect::getNumOffBits() const { return d_size - d_numOnBits; } // the contents of v are blown out void ExplicitBitVect::getOnBits(IntVect &v) const { unsigned int nOn = getNumOnBits(); if (!v.empty()) { IntVect().swap(v); } v.reserve(nOn); for (unsigned int i = 0; i < d_size; i++) { if ((bool)(*dp_bits)[i]) { v.push_back(i); } } } void ExplicitBitVect::_initForSize(unsigned int size) { d_size = size; dp_bits.reset(new boost::dynamic_bitset<>(size)); d_numOnBits = 0; } ExplicitBitVect::~ExplicitBitVect() {} std::string ExplicitBitVect::toString() const { // This Function replaces the older version (version 16) of writing the onbits // to a string. The old version does not perform any run length encoding, it // only checks to see if the length of the bitvect can be short ints and // writes the on bits as shorts otherwise the onbits are all written as ints. // Here we do run length encoding and the version number has been bumped to 32 // as well. Only the reader needs to take care of reading all legacy versions. // Also in this scheme each bit number written to the string is checked to see // how many bytes it needs std::stringstream ss(std::ios_base::binary | std::ios_base::out | std::ios_base::in); std::int32_t tInt = ci_BITVECT_VERSION * -1; RDKit::streamWrite(ss, tInt); tInt = d_size; RDKit::streamWrite(ss, tInt); tInt = getNumOnBits(); RDKit::streamWrite(ss, tInt); int prev = -1; unsigned int zeroes; for (unsigned int i = 0; i < d_size; i++) { if ((bool)(*dp_bits)[i]) { zeroes = i - prev - 1; RDKit::appendPackedIntToStream(ss, zeroes); prev = i; } } zeroes = d_size - prev - 1; RDKit::appendPackedIntToStream(ss, zeroes); std::string res(ss.str()); return res; }