Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion include/lucene++/BitSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#define BITSET_H

#include <boost/dynamic_bitset.hpp>
#include <boost/version.hpp>
#include "LuceneObject.h"

namespace Lucene {
Expand All @@ -22,9 +23,14 @@ class LPPAPI BitSet : public LuceneObject {
protected:
typedef boost::dynamic_bitset<uint64_t> bitset_type;
bitset_type bitSet;
#if BOOST_VERSION >= 109000
typedef const bitset_type& get_bits_result;
#else
typedef const uint64_t* get_bits_result;
#endif

public:
const uint64_t* getBits();
get_bits_result getBits();
void clear();
void clear(uint32_t bitIndex);
void fastClear(uint32_t bitIndex);
Expand Down
134 changes: 62 additions & 72 deletions src/core/util/BitSet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand All @@ -16,8 +18,12 @@ BitSet::BitSet(uint32_t size) : bitSet(size) {
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() {
Expand All @@ -35,16 +41,20 @@ void BitSet::fastClear(uint32_t bitIndex) {
}

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) {
Expand All @@ -70,33 +80,28 @@ void BitSet::fastSet(uint32_t bitIndex, bool value) {
}

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) {
Expand All @@ -114,15 +119,17 @@ void BitSet::flip(uint32_t fromIndex, uint32_t toIndex) {
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 {
Expand All @@ -146,72 +153,58 @@ bool BitSet::fastGet(uint32_t bitIndex) const {
}

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 {
return bitSet.intersects(set->bitSet);
}

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) {
Expand All @@ -224,31 +217,28 @@ bool BitSet::equals(const LuceneObjectPtr& other) {
}
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;
Expand Down