254 lines
8.4 KiB
Diff
254 lines
8.4 KiB
Diff
diff -Nuar a/src/core/util/BitSet.cpp b/src/core/util/BitSet.cpp
|
|
--- a/src/core/util/BitSet.cpp 2024-02-18 21:18:26.000000000 +0300
|
|
+++ b/src/core/util/BitSet.cpp 2026-02-14 13:50:04.395991563 +0300
|
|
@@ -7,6 +7,8 @@
|
|
#include "LuceneInc.h"
|
|
#include "BitSet.h"
|
|
#include "BitUtil.h"
|
|
+#include <boost/version.hpp>
|
|
+#include <boost/iterator/function_output_iterator.hpp>
|
|
|
|
namespace Lucene {
|
|
|
|
@@ -16,8 +18,12 @@
|
|
BitSet::~BitSet() {
|
|
}
|
|
|
|
-const uint64_t* BitSet::getBits() {
|
|
+BitSet::get_bits_result BitSet::getBits() {
|
|
+#if BOOST_VERSION < 109000
|
|
return bitSet.empty() ? NULL : static_cast<const uint64_t*>(&bitSet.m_bits[0]);
|
|
+#else
|
|
+ return bitSet;
|
|
+#endif
|
|
}
|
|
|
|
void BitSet::clear() {
|
|
@@ -35,16 +41,20 @@
|
|
}
|
|
|
|
void BitSet::clear(uint32_t fromIndex, uint32_t toIndex) {
|
|
+#if BOOST_VERSION >= 106900
|
|
+ fromIndex = std::min<bitset_type::size_type>(fromIndex, bitSet.size());
|
|
+ toIndex = std::min<bitset_type::size_type>(toIndex, bitSet.size());
|
|
+ bitSet.reset(fromIndex, toIndex - fromIndex);
|
|
+#else
|
|
toIndex = std::min(toIndex, (uint32_t)bitSet.size());
|
|
for (bitset_type::size_type i = std::min(fromIndex, (uint32_t)bitSet.size()); i < toIndex; ++i) {
|
|
bitSet.set(i, false);
|
|
}
|
|
+#endif
|
|
}
|
|
|
|
void BitSet::fastClear(uint32_t fromIndex, uint32_t toIndex) {
|
|
- for (bitset_type::size_type i = fromIndex; i < toIndex; ++i) {
|
|
- bitSet.set(i, false);
|
|
- }
|
|
+ fastSet(fromIndex, toIndex, false);
|
|
}
|
|
|
|
void BitSet::set(uint32_t bitIndex) {
|
|
@@ -70,33 +80,28 @@
|
|
}
|
|
|
|
void BitSet::set(uint32_t fromIndex, uint32_t toIndex) {
|
|
- if (toIndex >= bitSet.size()) {
|
|
- resize(toIndex + 1);
|
|
- }
|
|
- for (bitset_type::size_type i = fromIndex; i < toIndex; ++i) {
|
|
- bitSet.set(i, true);
|
|
- }
|
|
+ set(fromIndex, toIndex, true);
|
|
}
|
|
|
|
void BitSet::fastSet(uint32_t fromIndex, uint32_t toIndex) {
|
|
- for (bitset_type::size_type i = fromIndex; i < toIndex; ++i) {
|
|
- bitSet.set(i, true);
|
|
- }
|
|
+ fastSet(fromIndex, toIndex, true);
|
|
}
|
|
|
|
void BitSet::set(uint32_t fromIndex, uint32_t toIndex, bool value) {
|
|
if (toIndex >= bitSet.size()) {
|
|
resize(toIndex + 1);
|
|
}
|
|
- for (bitset_type::size_type i = fromIndex; i < toIndex; ++i) {
|
|
- bitSet.set(i, value);
|
|
- }
|
|
+ fastSet(fromIndex, toIndex, value);
|
|
}
|
|
|
|
void BitSet::fastSet(uint32_t fromIndex, uint32_t toIndex, bool value) {
|
|
+#if BOOST_VERSION >= 106900
|
|
+ bitSet.set(fromIndex, toIndex - fromIndex, value);
|
|
+#else
|
|
for (bitset_type::size_type i = fromIndex; i < toIndex; ++i) {
|
|
bitSet.set(i, value);
|
|
}
|
|
+#endif
|
|
}
|
|
|
|
void BitSet::flip(uint32_t bitIndex) {
|
|
@@ -114,15 +119,17 @@
|
|
if (toIndex >= bitSet.size()) {
|
|
resize(toIndex + 1);
|
|
}
|
|
- for (bitset_type::size_type i = fromIndex; i < toIndex; ++i) {
|
|
- bitSet.flip(i);
|
|
- }
|
|
+ fastFlip(fromIndex, toIndex);
|
|
}
|
|
|
|
void BitSet::fastFlip(uint32_t fromIndex, uint32_t toIndex) {
|
|
+#if BOOST_VERSION >= 106900
|
|
+ bitSet.flip(fromIndex, toIndex - fromIndex);
|
|
+#else
|
|
for (bitset_type::size_type i = fromIndex; i < toIndex; ++i) {
|
|
bitSet.flip(i);
|
|
}
|
|
+#endif
|
|
}
|
|
|
|
uint32_t BitSet::size() const {
|
|
@@ -146,51 +153,46 @@
|
|
}
|
|
|
|
int32_t BitSet::nextSetBit(uint32_t fromIndex) const {
|
|
+#if BOOST_VERSION >= 108800
|
|
+ return bitSet.find_first(fromIndex);
|
|
+#else
|
|
bitset_type::size_type next = fromIndex == 0 ? bitSet.find_first() : bitSet.find_next(fromIndex - 1);
|
|
return next == bitset_type::npos ? -1 : next;
|
|
+#endif
|
|
}
|
|
|
|
void BitSet::_and(const BitSetPtr& set) {
|
|
- bitset_type::size_type minBlocks = std::min(bitSet.num_blocks(), set->bitSet.num_blocks());
|
|
- for (bitset_type::size_type i = 0; i < minBlocks; ++i) {
|
|
- bitSet.m_bits[i] &= set->bitSet.m_bits[i];
|
|
- }
|
|
- if (bitSet.num_blocks() > minBlocks) {
|
|
- std::fill(bitSet.m_bits.begin() + minBlocks, bitSet.m_bits.end(), bitset_type::block_type(0));
|
|
- }
|
|
+ bitset_type other = set->bitSet;
|
|
+ other.resize(bitSet.size());
|
|
+ bitSet &= other;
|
|
}
|
|
|
|
void BitSet::_or(const BitSetPtr& set) {
|
|
- bitset_type::size_type minBlocks = std::min(bitSet.num_blocks(), set->bitSet.num_blocks());
|
|
if (set->bitSet.size() > bitSet.size()) {
|
|
resize(set->bitSet.size());
|
|
- }
|
|
- for (bitset_type::size_type i = 0; i < minBlocks; ++i) {
|
|
- bitSet.m_bits[i] |= set->bitSet.m_bits[i];
|
|
- }
|
|
- if (bitSet.num_blocks() > minBlocks) {
|
|
- std::copy(set->bitSet.m_bits.begin() + minBlocks, set->bitSet.m_bits.end(), bitSet.m_bits.begin() + minBlocks);
|
|
+ bitSet |= set->bitSet;
|
|
+ } else {
|
|
+ bitset_type other = set->bitSet;
|
|
+ other.resize(bitSet.size());
|
|
+ bitSet |= other;
|
|
}
|
|
}
|
|
|
|
void BitSet::_xor(const BitSetPtr& set) {
|
|
- bitset_type::size_type minBlocks = std::min(bitSet.num_blocks(), set->bitSet.num_blocks());
|
|
if (set->bitSet.size() > bitSet.size()) {
|
|
resize(set->bitSet.size());
|
|
- }
|
|
- for (bitset_type::size_type i = 0; i < minBlocks; ++i) {
|
|
- bitSet.m_bits[i] ^= set->bitSet.m_bits[i];
|
|
- }
|
|
- if (bitSet.num_blocks() > minBlocks) {
|
|
- std::copy(set->bitSet.m_bits.begin() + minBlocks, set->bitSet.m_bits.end(), bitSet.m_bits.begin() + minBlocks);
|
|
+ bitSet ^= set->bitSet;
|
|
+ } else {
|
|
+ bitset_type other = set->bitSet;
|
|
+ other.resize(bitSet.size());
|
|
+ bitSet ^= other;
|
|
}
|
|
}
|
|
|
|
void BitSet::andNot(const BitSetPtr& set) {
|
|
- bitset_type::size_type minBlocks = std::min(bitSet.num_blocks(), set->bitSet.num_blocks());
|
|
- for (bitset_type::size_type i = 0; i < minBlocks; ++i) {
|
|
- bitSet.m_bits[i] &= ~set->bitSet.m_bits[i];
|
|
- }
|
|
+ bitset_type other = set->bitSet;
|
|
+ other.resize(bitSet.size());
|
|
+ bitSet &= other.flip();
|
|
}
|
|
|
|
bool BitSet::intersectsBitSet(const BitSetPtr& set) const {
|
|
@@ -198,20 +200,11 @@
|
|
}
|
|
|
|
uint32_t BitSet::cardinality() {
|
|
- return bitSet.num_blocks() == 0 ? 0 : (uint32_t)BitUtil::pop_array((int64_t*)getBits(), 0, bitSet.num_blocks());
|
|
+ return bitSet.count();
|
|
}
|
|
|
|
void BitSet::resize(uint32_t size) {
|
|
- bitset_type::size_type old_num_blocks = bitSet.num_blocks();
|
|
- bitset_type::size_type required_blocks = bitSet.calc_num_blocks(size);
|
|
- if (required_blocks != old_num_blocks) {
|
|
- bitSet.m_bits.resize(required_blocks, bitset_type::block_type(0));
|
|
- }
|
|
- bitSet.m_num_bits = size;
|
|
- uint64_t extra_bits = static_cast<uint64_t>(bitSet.size() % bitSet.bits_per_block);
|
|
- if (extra_bits != 0) {
|
|
- bitSet.m_bits.back() &= ~(~static_cast<bitset_type::block_type>(0) << extra_bits);
|
|
- }
|
|
+ bitSet.resize(size);
|
|
}
|
|
|
|
bool BitSet::equals(const LuceneObjectPtr& other) {
|
|
@@ -224,31 +217,28 @@
|
|
}
|
|
BitSetPtr first = bitSet.num_blocks() < otherBitSet->bitSet.num_blocks() ? otherBitSet : shared_from_this();
|
|
BitSetPtr second = bitSet.num_blocks() < otherBitSet->bitSet.num_blocks() ? shared_from_this() : otherBitSet;
|
|
- bitset_type::size_type firstLength = first->bitSet.num_blocks();
|
|
- bitset_type::size_type secondLength = second->bitSet.num_blocks();
|
|
- for (bitset_type::size_type i = secondLength; i < firstLength; ++i) {
|
|
- if (first->bitSet.m_bits[i] != 0) {
|
|
- return false;
|
|
+ bitset_type::size_type f = first->bitSet.find_first();
|
|
+ bitset_type::size_type s = second->bitSet.find_first();
|
|
+ while (f == s) {
|
|
+ if (f == bitset_type::npos) {
|
|
+ return true;
|
|
}
|
|
+ f = first->bitSet.find_next(f);
|
|
+ s = second->bitSet.find_next(s);
|
|
}
|
|
- for (bitset_type::size_type i = 0; i < secondLength; ++i) {
|
|
- if (first->bitSet.m_bits[i] != second->bitSet.m_bits[i]) {
|
|
- return false;
|
|
- }
|
|
- }
|
|
- return true;
|
|
+ return false;
|
|
}
|
|
|
|
int32_t BitSet::hashCode() {
|
|
// Start with a zero hash and use a mix that results in zero if the input is zero.
|
|
// This effectively truncates trailing zeros without an explicit check.
|
|
int64_t hash = 0;
|
|
- uint32_t maxSize = bitSet.num_blocks();
|
|
- const uint64_t* bits = getBits();
|
|
- for (uint32_t bit = 0; bit < maxSize; ++bit) {
|
|
- hash ^= bits[bit];
|
|
- hash = (hash << 1) | (hash >> 63); // rotate left
|
|
- }
|
|
+ to_block_range(bitSet, boost::make_function_output_iterator(
|
|
+ [&hash](bitset_type::block_type block) {
|
|
+ hash ^= block;
|
|
+ hash = (hash << 1) | (hash >> 63); // rotate left
|
|
+ }
|
|
+ ));
|
|
// Fold leftmost bits into right and add a constant to prevent empty sets from
|
|
// returning 0, which is too common.
|
|
return (int32_t)((hash >> 32) ^ hash) + 0x98761234;
|