more work on src/util, mainly on the bitset class
This commit is contained in:
@@ -30,6 +30,7 @@ namespace operations_research {
|
||||
|
||||
// Useful constants: word and double word will all bits set.
|
||||
static const uint64 kAllBits64 = GG_ULONGLONG(0xFFFFFFFFFFFFFFFF);
|
||||
static const uint64 kAllBitsButLsb64 = GG_ULONGLONG(0xFFFFFFFFFFFFFFFE);
|
||||
static const uint32 kAllBits32 = 0xFFFFFFFFU;
|
||||
|
||||
// Returns a word with only bit pos set.
|
||||
@@ -426,6 +427,11 @@ class Bitset64 {
|
||||
memset(data_.data(), 0, to_clear * sizeof(int64));
|
||||
}
|
||||
|
||||
// Sets all bits to 0.
|
||||
void ClearAll() {
|
||||
memset(data_.data(), 0, data_.size() * sizeof(int64));
|
||||
}
|
||||
|
||||
// Sets the bit at position i to 0.
|
||||
void Clear(IndexType i) {
|
||||
DCHECK_GE(Value(i), 0);
|
||||
@@ -433,6 +439,13 @@ class Bitset64 {
|
||||
data_[BitOffset64(Value(i))] &= ~OneBit64(BitPos64(Value(i)));
|
||||
}
|
||||
|
||||
// Sets bucket containing bit i to 0.
|
||||
void ClearBucket(IndexType i) {
|
||||
DCHECK_GE(Value(i), 0);
|
||||
DCHECK_LT(Value(i), size_);
|
||||
data_[BitOffset64(Value(i))] = 0;
|
||||
}
|
||||
|
||||
// Copies the bits at position i and i ^ 1 and then clear them.
|
||||
void CopyAndClearTwoBits(IndexType i, Bitset64* to) {
|
||||
DCHECK_GE(Value(i), 0);
|
||||
@@ -476,6 +489,35 @@ class Bitset64 {
|
||||
}
|
||||
}
|
||||
|
||||
// Copies bucket containing bit i from "other" to "this".
|
||||
void CopyBucket(const Bitset64<IndexType>& other, IndexType i) {
|
||||
const uint64 offset = BitOffset64(Value(i));
|
||||
data_[offset] = other.data_[offset];
|
||||
}
|
||||
|
||||
// Copies "other" to "this". The bitsets do not have to be of the same size.
|
||||
// If "other" is smaller, high order bits are not changed. If "other" is
|
||||
// larger, its high order bits are ignored. In any case "this" is not resized.
|
||||
void SetContentFromBitset(const Bitset64<IndexType>& other) {
|
||||
const int min_size = std::min(data_.size(), other.data_.size());
|
||||
if (min_size == 0) return;
|
||||
const uint64 last_common_bucket = data_[min_size - 1];
|
||||
memcpy(data_.data(), other.data_.data(), min_size * sizeof(uint64));
|
||||
if (data_.size() >= other.data_.size()) {
|
||||
const uint64 bitmask =
|
||||
kAllBitsButLsb64 << BitPos64(Value(other.size() - 1));
|
||||
data_[min_size - 1] &= ~bitmask;
|
||||
data_[min_size - 1] |= (bitmask & last_common_bucket);
|
||||
}
|
||||
}
|
||||
|
||||
// Same as SetContentFromBitset where "this" and "other" have the same size.
|
||||
void SetContentFromBitsetOfSameSize(const Bitset64<IndexType>& other) {
|
||||
DCHECK_EQ(size(), other.size());
|
||||
memcpy(data_.data(), other.data_.data(), data_.size() * sizeof(uint64));
|
||||
}
|
||||
|
||||
|
||||
// Sets "this" to be the intersection of "this" and "other". The
|
||||
// bitsets do not have to be the same size. If other is smaller, all
|
||||
// the higher order bits are assumed to be 0.
|
||||
@@ -585,6 +627,15 @@ class Bitset64 {
|
||||
((use2 << pos) & other2.data_[bucket]);
|
||||
}
|
||||
|
||||
// Returns a 0/1 std::string representing the bitset.
|
||||
std::string DebugString() const {
|
||||
std::string output;
|
||||
for (IndexType i(0); i < size(); ++i) {
|
||||
output += IsSet(i) ? "1" : "0";
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
private:
|
||||
// Returns the value of the index type.
|
||||
// This function is specialized below to work with IntType and int64.
|
||||
@@ -620,16 +671,24 @@ class SparseBitset {
|
||||
SparseBitset() {}
|
||||
explicit SparseBitset(IntegerType size) : bitset_(size) {}
|
||||
IntegerType size() const { return bitset_.size(); }
|
||||
void SparseClearAll() {
|
||||
for (const IntegerType i : to_clear_) bitset_.ClearBucket(i);
|
||||
to_clear_.clear();
|
||||
}
|
||||
void ClearAll() {
|
||||
bitset_.ClearAll();
|
||||
to_clear_.clear();
|
||||
}
|
||||
void ClearAndResize(IntegerType size) {
|
||||
// As of 19/03/2014, experiments show that this is a reasonable threshold.
|
||||
const int kSparseThreshold = 300;
|
||||
if (to_clear_.size() * kSparseThreshold < size) {
|
||||
for (const IntegerType i : to_clear_) Clear(i);
|
||||
SparseClearAll();
|
||||
bitset_.Resize(size);
|
||||
} else {
|
||||
bitset_.ClearAndResize(size);
|
||||
to_clear_.clear();
|
||||
}
|
||||
to_clear_.clear();
|
||||
}
|
||||
bool operator[](IntegerType index) const { return bitset_[index]; }
|
||||
void Set(IntegerType index) {
|
||||
|
||||
@@ -165,6 +165,13 @@ void GetBestScalingOfDoublesToInt64(const std::vector<double>& x,
|
||||
double* scaling_factor,
|
||||
double* relative_error);
|
||||
|
||||
// Returns the Greatest Common Divisor of the numbers
|
||||
// round(fabs(x[i] * scaling_factor)). The numbers 0 are ignored and if they are
|
||||
// all zero then the result is 1. Note that round(fabs()) is the same as
|
||||
// fabs(round()) since the numbers are rounded away from zero.
|
||||
int64 ComputeGcdOfRoundedDoubles(const std::vector<double>& x,
|
||||
double scaling_factor);
|
||||
|
||||
} // namespace operations_research
|
||||
|
||||
#endif // OR_TOOLS_UTIL_FP_UTILS_H_
|
||||
|
||||
@@ -21,12 +21,15 @@ namespace operations_research {
|
||||
// ---------- Overflow utility functions ----------
|
||||
|
||||
// Performs *b += a and returns false iff the addition overflow or underflow.
|
||||
// This function only works for typed integer type (IntType<>).
|
||||
template <typename IntegerType>
|
||||
bool SafeAddInto(IntegerType a, IntegerType* b) {
|
||||
if (a > 0) {
|
||||
if (*b > std::numeric_limits<IntegerType>::max() - a) return false;
|
||||
if (*b > std::numeric_limits<typename IntegerType::ValueType>::max() - a)
|
||||
return false;
|
||||
} else {
|
||||
if (*b < std::numeric_limits<IntegerType>::min() - a) return false;
|
||||
if (*b < std::numeric_limits<typename IntegerType::ValueType>::min() - a)
|
||||
return false;
|
||||
}
|
||||
*b += a;
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user