21 #include <type_traits> 31 #include <glog/logging.h> 34 #error BitVectorCoding.h requires x86_64 38 namespace compression {
40 static_assert(
kIsLittleEndian,
"BitVectorCoding.h requires little endianness");
42 template <
class Po
inter>
46 template <
class OtherPo
inter>
52 bits(reinterpret_cast<Pointer>(other.
bits)),
56 template <
class T = Po
inter>
77 size_t kSkipQuantum = 0,
78 size_t kForwardQuantum = 0>
82 "Value should be unsigned integral");
91 static constexpr
size_t skipQuantum = kSkipQuantum;
92 static constexpr
size_t forwardQuantum = kForwardQuantum;
94 template <
class RandomAccessIterator>
96 RandomAccessIterator
begin,
97 RandomAccessIterator
end) {
99 return MutableCompressedList();
109 : bits_(result.
bits),
118 Layout::fromUpperBoundAndSize(upperBound, size).allocList()) {}
123 CHECK_GT(value + 1, lastValue_ + 1)
124 <<
"BitVectorCoding only supports stricly monotone lists";
126 auto block = bits_ + (value / 64) *
sizeof(
uint64_t);
127 size_t inner = value % 64;
131 if (skipQuantum != 0) {
132 size_t nextSkipPointerSize = value / skipQuantum;
133 while (skipPointersSize_ < nextSkipPointerSize) {
134 auto pos = skipPointersSize_++;
135 folly::storeUnaligned<SkipValueType>(
136 skipPointers_ + pos *
sizeof(SkipValueType), size_);
140 if (forwardQuantum != 0) {
141 if (size_ != 0 && (size_ % forwardQuantum == 0)) {
142 const auto pos = size_ / forwardQuantum - 1;
143 folly::storeUnaligned<SkipValueType>(
144 forwardPointers_ + pos *
sizeof(SkipValueType), value);
152 const MutableCompressedList&
finish()
const {
153 CHECK_EQ(size_, result_.size);
155 CHECK_EQ(result_.upperBound, lastValue_);
164 ValueType lastValue_ = -1;
166 size_t skipPointersSize_ = 0;
175 size_t kForwardQuantum>
183 size_t bitVectorSizeInBytes = (upperBound / 8) + 1;
184 layout.
bits = bitVectorSizeInBytes;
186 if (skipQuantum != 0) {
187 size_t numSkipPointers = upperBound / skipQuantum;
190 if (forwardQuantum != 0) {
191 size_t numForwardPointers = size / forwardQuantum;
204 template <
class Range>
220 CHECK_EQ(buf.
data() - result.
data.data(), bytes());
228 buf =
static_cast<uint8_t*
>(malloc(bytes() + 7));
231 return openList(bufRange);
246 bool kUnchecked =
false>
267 block_ = (bits_ !=
nullptr) ? folly::loadUnaligned<uint64_t>(bits_) : 0;
270 value_ = kInvalidValue;
274 if (!kUnchecked &&
UNLIKELY(position() + 1 >= size_)) {
278 while (block_ == 0) {
280 block_ = folly::loadUnaligned<uint64_t>(bits_ + outer_);
284 auto inner = Instructions::ctz(block_);
285 block_ = Instructions::blsr(block_);
287 return setValue(inner);
293 if (!kUnchecked && position() + n >= size_) {
297 if (
LIKELY(n < kLinearScanThreshold)) {
298 for (
size_t i = 0;
i < n; ++
i) {
307 if (Encoder::forwardQuantum > 0 && n > Encoder::forwardQuantum) {
308 const size_t steps = position_ / Encoder::forwardQuantum;
309 const size_t dest = folly::loadUnaligned<SkipValueType>(
310 this->forwardPointers_ + (steps - 1) *
sizeof(SkipValueType));
313 n = position_ + 1 - steps * Encoder::forwardQuantum;
321 block_ = folly::loadUnaligned<uint64_t>(bits_ + outer_);
326 auto inner = select64<Instructions>(block_, n - 1);
327 block_ &= (
uint64_t(-1) << inner) << 1;
329 return setValue(inner);
334 if (v != kInvalidValue) {
335 DCHECK_GE(v + 1, value_ + 1);
338 if (!kUnchecked && v > upperBound_) {
340 }
else if (v == value_) {
345 if (v - value_ < kLinearScanThreshold) {
348 }
while (
value() < v);
353 if (Encoder::skipQuantum > 0 && v - value_ > Encoder::skipQuantum) {
354 size_t q = v / Encoder::skipQuantum;
355 auto skipPointer = folly::loadUnaligned<SkipValueType>(
356 this->skipPointers_ + (q - 1) *
sizeof(SkipValueType));
357 position_ =
static_cast<SizeType
>(skipPointer) - 1;
359 reposition(q * Encoder::skipQuantum);
363 size_t outer = v / 64 * 8;
365 while (outer_ < outer) {
368 block_ = folly::loadUnaligned<uint64_t>(bits_ + outer_);
371 DCHECK_EQ(outer_, outer);
376 while (block_ == 0) {
378 block_ = folly::loadUnaligned<uint64_t>(bits_ + outer_);
381 auto inner = Instructions::ctz(block_);
382 block_ = Instructions::blsr(block_);
393 return position() <
size();
415 value_ = kInvalidValue;
421 constexpr
static ValueType kInvalidValue =
426 value_ =
static_cast<ValueType
>(8 * outer_ + inner);
431 outer_ = dest / 64 * 8;
433 block_ = folly::loadUnaligned<uint64_t>(bits_ + outer_);
434 block_ &= ~((
uint64_t(1) << (dest % 64)) - 1);
437 constexpr
static size_t kLinearScanThreshold = 4;
const ValueType upperBound_
constexpr unsigned int popcount(T const v)
MutableBitVectorCompressedList MutableCompressedList
void add(ValueType value)
BitVectorCompressedListBase(const BitVectorCompressedListBase< OtherPointer > &other)
BitVectorEncoder< uint32_t, uint32_t, 128, 128 > Encoder
const MutableCompressedList & finish() const
Encoder::SkipValueType SkipValueType
BitVectorCompressedListBase< const uint8_t * > BitVectorCompressedList
const uint8_t *const bits_
void advance(size_type n)
MutableCompressedList allocList() const
BitVectorCompressedListBase< uint8_t * > MutableBitVectorCompressedList
constexpr size_type size() const
auto begin(TestAdlIterable &instance)
constexpr auto kIsLittleEndian
—— Concurrent Priority Queue Implementation ——
detail::Skip skip(size_t count)
BitVectorEncoder(const MutableCompressedList &result)
Encoder::ValueType SizeType
BitVectorEncoder(size_t size, ValueType upperBound)
folly::Range< Pointer > data
MutableCompressedList result_
static MutableCompressedList encode(RandomAccessIterator begin, RandomAccessIterator end)
Encoder::ValueType ValueType
bool Value(const T &value, M matcher)
auto end(TestAdlIterable &instance)
constexpr Iter data() const
Range subpiece(size_type first, size_type length=npos) const
Encoder::MutableCompressedList list
BitVectorCompressedList CompressedList
BitVectorReader(const typename Encoder::CompressedList &list)
static const char *const value
static Layout fromUpperBoundAndSize(size_t upperBound, size_t size)
bool setValue(size_t inner)
void reposition(size_t dest)
SizeType position() const
auto free() -> decltype(::free(T(nullptr)))
uint64_t value(const typename LockFreeRingBuffer< T, Atom >::Cursor &rbcursor)
BitVectorCompressedListBase< typename Range::iterator > openList(Range &buf) const
BitVectorCompressedListBase()=default