8#ifndef Sawyer_BitVector_H
9#define Sawyer_BitVector_H
11#include <Sawyer/Assert.h>
12#include <Sawyer/BitVectorSupport.h>
13#include <Sawyer/Optional.h>
14#include <Sawyer/Sawyer.h>
16#include <boost/algorithm/string/predicate.hpp>
17#include <boost/cstdint.hpp>
19#ifdef SAWYER_HAVE_BOOST_SERIALIZATION
20#include <boost/serialization/vector.hpp>
23#ifdef SAWYER_HAVE_CEREAL
24#include <cereal/types/vector.hpp>
34inline double log2(
double n) {
35 return log(n) / log(2.0);
75 std::vector<Word> words_;
78#ifdef SAWYER_HAVE_BOOST_SERIALIZATION
80 friend class boost::serialization::access;
83 void serialize(S &s,
const unsigned ) {
84 s & BOOST_SERIALIZATION_NVP(size_);
85 s & BOOST_SERIALIZATION_NVP(words_);
89#ifdef SAWYER_HAVE_CEREAL
91 friend class cereal::access;
93 template<
class Archive>
94 void CEREAL_SERIALIZE_FUNCTION_NAME(Archive &archive) {
95 archive(CEREAL_NVP(size_));
96 archive(CEREAL_NVP(words_));
110 explicit BitVector(
size_t nbits,
bool newBits =
false): size_(0) {
127 size_t bitsPerDigit = 0;
128 const char *digits = NULL;
129 if (boost::starts_with(str,
"0x")) {
131 digits =
"0123456789abcdefABCDEF";
133 }
else if (boost::starts_with(str,
"0b")) {
137 }
else if (boost::ends_with(str,
"h")) {
139 digits =
"0123456789abcdefABCDEF";
140 str = str.substr(0, str.size()-1);
141 }
else if (boost::starts_with(str,
"0")) {
147 digits =
"0123456789";
152 for (
const char *t=str.c_str(); *t; ++t) {
153 if (strchr(digits, *t))
157 throw std::runtime_error(
"BitVector::parse: no valid digits");
162 nBits = bitsPerDigit * nDigits;
164 nBits = ceil(log2(pow(10.0, (
double)nDigits)));
169 switch (bitsPerDigit) {
183 assert(!
"invalid radix");
195 words_ = other.words_;
208 size_t size()
const {
return size_; }
219 }
else if (newSize > size_) {
220 size_t nwords = BitVectorSupport::numberOfWords<Word>(newSize);
221 words_.resize(nwords,
Word(0));
225 size_t nwords = BitVectorSupport::numberOfWords<Word>(newSize);
226 words_.resize(nwords);
271 bool get(
size_t idx)
const {
946 for (
size_t i = 0; i <
size(); ++i) {
981 for (
size_t i = 0; i < a.
size(); ++i) {
988 if (aIsNeg != bIsNeg)
1328 return BitVectorSupport::toBytes(
data(),
hull());
1331 return BitVectorSupport::toBytes(
data(), range);
1475 BitVectorSupport::fromBytes(
data(),
hull(), input);
1479 BitVectorSupport::fromBytes(
data(), range, input);
1493 ASSERT_always_require(
hull().contains(range));
1503 return words_.empty() ? NULL : &words_[0];
1507 return words_.empty() ? NULL : &words_[0];
1515 return words_.size();
unsigned Word
Base storage type.
bool isAllSet() const
True if all bits are set.
BitVector & rotateLeft(size_t nShift)
Rotate bits left.
BitVector & clear(const BitRange &range)
Assign zero to some bits.
Optional< size_t > mostSignificantSetBit() const
Find the most significant set bit.
BitVector & shiftRight(size_t nShift, bool newBits=0)
Shift bits right.
BitVector()
Default construct an empty vector.
bool increment(const BitRange &range1)
Increment bits as integer.
BitVector & fromHex(const std::string &input)
Obtain bits from a hexadecimal representation.
BitVector & multiply10(const BitRange &range)
Multiply by 10.
BitVector & fromOctal(const BitRange &range, const std::string &input)
Obtain bits from an octal representation.
Optional< size_t > mostSignificantDifference(const BitVector &other) const
Find most significant difference.
std::string toOctal() const
Convert to an octal string.
bool isAllClear() const
True if all bits are clear.
bool increment()
Increment bits as integer.
BitVector & shiftRight(const BitRange &range, size_t nShift, bool newBits=0)
Shift bits right.
bool isAllClear(const BitRange &range) const
True if all bits are clear.
bool decrement()
Decrement bits as integer.
Optional< size_t > leastSignificantClearBit(const BitRange &range) const
Find the least significant clear bit.
BitVector & fromOctal(const std::string &input)
Obtain bits from an octal representation.
BitVector & bitwiseAnd(const BitRange &range1, const BitRange &range2)
Bit-wise AND.
BitVector & negate(const BitRange &range1)
Negates bits as integer.
size_t capacity() const
Maximum size before reallocation.
Optional< size_t > mostSignificantSetBit(const BitRange &range) const
Find the most significant set bit.
BitVector multiplySigned(const BitVector &other) const
Multiply two signed integers.
boost::uint64_t toInteger(const BitRange &range) const
Interpret bits as an unsigned integer.
bool equalTo(const BitRange &range1, const BitRange &range2) const
Checks whether the bits of two ranges are equal.
std::string toHex() const
Convert to a hexadecimal string.
bool isEqualToZero(const BitRange &range) const
Compare to zero.
BitVector & copy(const BitRange &to, const BitRange &from)
Copy some bits.
BitVector & negate()
Negates bits as integer.
BitVector & fromInteger(const BitRange &range, boost::uint64_t value)
Obtain bits from an integer.
BitVector & signExtend(const BitVector &other)
Copy bits and sign extend.
int compareSigned(const BitRange &range1, const BitRange &range2) const
Compare bits as signed integers.
BitVector & signExtend(const BitRange &range1, const BitVector &other, const BitRange &range2)
Copy bits and sign extend.
int compare(const BitVector &other) const
Compare bits as integers.
BitVector & bitwiseOr(const BitVector &other)
Bit-wise OR.
BitVector & rotateLeft(const BitRange &range, size_t nShift)
Rotate bits left.
size_t size() const
Size of vector in bits.
size_t nClear() const
Number of clear bits.
void checkRange(const BitRange &range) const
Assert valid range.
std::vector< uint8_t > toBytes() const
Convert to a vector of bytes.
std::string toOctal(const BitRange &range) const
Convert to an octal string.
Optional< size_t > leastSignificantSetBit(const BitRange &range) const
Find the least significant set bit.
static BitRange hull(size_t minOffset, size_t maxOffset)
Create a bit range from min and max positions.
BitVector & swap(const BitRange &range1, BitVector &other, const BitRange &range2)
Swap some bits.
boost::int64_t toSignedInteger() const
Interpret bits as a signed integer.
bool add(const BitRange &range1, const BitRange &range2)
Add bits as integers.
BitVector & multiply10()
Multiply by 10.
Optional< size_t > leastSignificantClearBit() const
Find the least significant clear bit.
BitVector & set()
Assign true to all bits.
bool subtract(const BitRange &range1, const BitVector &other, const BitRange &range2)
Subtract bits as integers.
std::string toBinary(const BitRange &range) const
Convert to a binary string.
size_t dataSize() const
Raw data size.
BitVector(size_t nbits, bool newBits=false)
Create a vector of specified size.
Optional< size_t > mostSignificantDifference(const BitRange &range1, const BitVector &other, const BitRange &range2) const
Find most significant difference.
BitVector & shiftRightArithmetic(size_t nShift)
Shift bits right.
int compareSigned(const BitRange &range1, const BitVector &other, const BitRange &range2) const
Compare bits as signed integers.
BitRange hull() const
Interval representing the entire vector.
BitVector & bitwiseAnd(const BitVector &other)
Bit-wise AND.
BitVector & resize(size_t newSize, bool newBits=false)
Change vector size.
BitVector & rotateRight(size_t nShift)
Rotate bits right.
static BitRange baseSize(size_t base, size_t size)
Create a bit range from a starting offset and size.
BitVector & bitwiseXor(const BitRange &range1, const BitVector &other, const BitRange &range2)
Bit-wise XOR.
BitVector & clear()
Assign zero to all bits.
Word * data()
Raw data for vector.
BitVector & invert(const BitRange &range)
Invert bits.
BitVector & setValue(const BitRange &range, bool value)
Assign true/false to some bits.
bool decrement(const BitRange &range1)
Decrement bits as integer.
bool equalTo(const BitVector &other) const
Checks whether the bits of one vector are equal to the bits of the other.
std::vector< uint8_t > toBytes(const BitRange &range) const
Convert to a vector of bytes.
BitVector & rotateRight(const BitRange &range, size_t nShift)
Rotate bits right.
bool subtract(const BitVector &other)
Subtract bits as integers.
BitVector & set(const BitRange &range)
Assign true to some bits.
bool get(size_t idx) const
Retrieve one bit.
BitVector & signExtend(const BitRange &range1, const BitRange &range2)
Copy bits and sign extend.
BitVector & bitwiseOr(const BitRange &range1, const BitVector &other, const BitRange &range2)
Bit-wise OR.
BitVector & bitwiseOr(const BitRange &range1, const BitRange &range2)
Bit-wise OR.
Optional< size_t > leastSignificantDifference(const BitRange &range1, const BitRange &range2) const
Find least significant difference.
BitVector & fromBinary(const BitRange &range, const std::string &input)
Obtain bits from a binary representation.
BitVector & fromHex(const BitRange &range, const std::string &input)
Obtain bits from a hexadecimal representation.
int compare(const BitRange &range1, const BitRange &range2) const
Compare bits as integers.
int compare(const BitRange &range1, const BitVector &other, const BitRange &range2) const
Compare bits as integers.
Optional< size_t > mostSignificantDifference(const BitRange &range1, const BitRange &range2) const
Find most significant difference.
static BitVector parse(std::string str)
Create a bit vector by reading a string.
BitVector(const BitVector &other)
Copy constructor.
BitVector & fromBytes(const std::vector< uint8_t > &input)
Obtain bits from a byte vector.
boost::uint64_t toInteger() const
Interpret bits as an unsigned integer.
BitVector & fromDecimal(const BitRange &range, const std::string &input)
Obtains bits from a decimal representation.
bool isEqualToZero() const
Compare to zero.
BitVector & setValue(bool value)
Assign true/false to all bits.
BitVector & fromInteger(boost::uint64_t value)
Obtain bits from an integer.
BitVector & bitwiseXor(const BitVector &other)
Bit-wise XOR.
BitVector multiply(const BitVector &other) const
Multiply two bit vectors.
Optional< size_t > mostSignificantClearBit() const
Find the most significant clear bit.
boost::int64_t toSignedInteger(const BitRange &range) const
Interpret bits as a signed integer.
std::string toHex(const BitRange &range) const
Convert to a hexadecimal string.
BitVector & operator=(const BitVector &other)
Assignment.
BitVector & fromBinary(const std::string &input)
Obtain bits from a binary representation.
size_t nSet() const
Number of set bits.
Optional< size_t > leastSignificantSetBit() const
Find the least significant set bit.
Optional< size_t > leastSignificantDifference(const BitVector &other) const
Find least significant difference.
BitVector & bitwiseXor(const BitRange &range1, const BitRange &range2)
Bit-wise XOR.
BitVector & shiftRightArithmetic(const BitRange &range, size_t nShift)
Shift bits right.
BitVectorSupport::BitRange BitRange
Describes an inclusive interval of bit indices.
std::string toBinary() const
Convert to an binary string.
bool add(const BitRange &range1, const BitVector &other, const BitRange &range2)
Add bits as integers.
bool isAllSet(const BitRange &range) const
True if all bits are set.
BitVector & shiftLeft(size_t nShift, bool newBits=0)
Shift bits left.
size_t nSet(const BitRange &range) const
Number of set bits.
const Word * data() const
Raw data for vector.
BitVector & copy(const BitRange &to, const BitVector &other, const BitRange &from)
Copy some bits.
bool subtract(const BitRange &range1, const BitRange &range2)
Subtract bits as integers.
Optional< size_t > leastSignificantDifference(const BitRange &range1, const BitVector &other, const BitRange &range2) const
Find least significant difference.
BitVector & swap(const BitRange &range1, const BitRange &range2)
Swap some bits.
BitVector & shiftLeft(const BitRange &range, size_t nShift, bool newBits=0)
Shift bits left.
bool add(const BitVector &other)
Add bits as integers.
size_t nClear(const BitRange &range) const
Number of clear bits.
bool equalTo(const BitRange &range1, BitVector &other, const BitRange &range2) const
Checks whether two ranges are equal.
Optional< size_t > mostSignificantClearBit(const BitRange &range) const
Find the most significant clear bit.
BitVector & fromBytes(const BitRange &range, const std::vector< uint8_t > &input)
Obtain bits from a byte vector.
bool isEmpty() const
Determines if the vector is empty.
BitVector & invert()
Invert bits.
BitVector & bitwiseAnd(const BitRange &range1, const BitVector &other, const BitRange &range2)
Bit-wise AND.
int compareSigned(const BitVector &other) const
Compare bits as signed integers.
BitVector & fromDecimal(const std::string &input)
Obtain bits from a decimal representation.
static Interval baseSize(size_t lo, size_t size)
Construct an interval from one endpoint and a size.
static Interval hull(size_t v1, size_t v2)
Construct an interval from two endpoints.
Holds a value or nothing.
bool isEqualToZero(const Word *vec1, const BitRange &range1)
Compares with zero.
bool isAllSet(const Word *words, const BitRange &range)
True if all bits are set.
void rotateLeft(Word *words, const BitRange &range, size_t nShift)
Rotate bits to the left.
Optional< size_t > mostSignificantDifference(const Word *vec1, const BitRange &range1, const Word *vec2, const BitRange &range2)
Find most significant different bits.
void negate(Word *vec1, const BitRange &range)
Negate bits as an integer.
std::string toBinary(const Word *vec, const BitRange &range)
Binary representation.
size_t nClear(const Word *words, const BitRange &range)
Number of clear bits.
bool signExtend(const Word *vec1, const BitRange &range1, Word *vec2, const BitRange &range2)
Sign extend.
bool decrement(Word *vec1, const BitRange &range1)
Decrement.
void bitwiseOr(const Word *vec1, const BitRange &range1, Word *vec2, const BitRange &range2)
Bit-wise OR.
void shiftLeft(Word *words, const BitRange &range, size_t nShift, bool newBits=0)
Shift bits left.
int compare(const Word *vec1, const BitRange &range1, const Word *vec2, const BitRange &range2)
Unsigned comparison.
boost::uint64_t toInteger(const Word *words, const BitRange &range)
Convert a bit vector to an integer.
void multiply10(Word *vec, const BitRange &range)
Multiply by 10.
bool subtract(const Word *vec1, const BitRange &range1, Word *vec2, const BitRange &range2)
Subtract bits.
void fromBinary(Word *vec, const BitRange &range, const std::string &input)
Obtain bits from a binary representation.
void fromOctal(Word *vec, const BitRange &range, const std::string &input)
Obtain bits from an octal representation.
void fromDecimal(Word *vec, const BitRange &range, const std::string &input)
Obtain bits from a decimal representation.
void shiftRightArithmetic(Word *words, const BitRange &range, size_t nShift)
Shift bits right arithmetically.
Optional< size_t > leastSignificantClearBit(const Word *words, const BitRange &range)
Index of least significant zero bit.
void swap(Word *vec1, const BitRange &range1, Word *vec2, const BitRange &range2)
Swap some bits.
size_t nSet(const Word *words, const BitRange &range)
Number of set bits.
void clear(Word *words, const BitRange &where)
Clear some bits.
Optional< size_t > mostSignificantClearBit(const Word *words, const BitRange &range)
Index of most significant clear bit.
void bitwiseAnd(const Word *vec1, const BitRange &range1, Word *vec2, const BitRange &range2)
Bit-wise AND.
void set(Word *words, const BitRange &where)
Set some bits.
void fromHex(Word *vec, const BitRange &range, const std::string &input)
Obtain bits from a hexadecimal representation.
bool get(const Word *words, size_t idx)
Return a single bit.
void rotateRight(Word *words, const BitRange &range, size_t nShift)
Rotate bits to the right.
void bitwiseXor(const Word *vec1, const BitRange &range1, Word *vec2, const BitRange &range2)
Bit-wise XOR.
bool equalTo(const Word *vec1, const BitRange &range1, const Word *vec2, const BitRange &range2)
Compare bits for equality.
boost::int64_t toSignedInteger(const Word *words, const BitRange &range)
Convert a bit vector to a signed integer.
bool increment(Word *vec1, const BitRange &range1)
Increment.
int compareSigned(const Word *vec1, const BitRange &range1, const Word *vec2, const BitRange &range2)
Signed comparison.
bool add(const Word *vec1, const BitRange &range1, Word *vec2, const BitRange &range2, bool carryIn=false)
Add bits.
Optional< size_t > leastSignificantSetBit(const Word *words, const BitRange &range)
Index of least significant set bit.
Optional< size_t > mostSignificantSetBit(const Word *words, const BitRange &range)
Index of most significant set bit.
std::string toOctal(const Word *vec, const BitRange &range)
Octal representation.
void fromInteger(Word *words, const BitRange &range, boost::uint64_t value)
Assign an unsigned value to a bit range.
void shiftRight(Word *words, const BitRange &range, size_t nShift, bool newBits=0)
Shift bits right.
void invert(Word *words, const BitRange &range)
Invert bits.
bool isAllClear(const Word *words, const BitRange &range)
True if all bits are clear.
Optional< size_t > leastSignificantDifference(const Word *vec1, const BitRange &range1, const Word *vec2, const BitRange &range2)
Find least significant different bits.
std::string toHex(const Word *vec, const BitRange &range)
Hexadecimal representation.
void setValue(Word *words, const BitRange &where, bool value)
Set or clear some bits.
void copy(const Word *src, const BitRange &srcRange, Word *dst, const BitRange &dstRange)
Copy some bits.