Commit a0776ffe authored by Giuseppe Ottaviano's avatar Giuseppe Ottaviano Committed by Facebook Github Bot

Reimplement EliasFanoReader::{jump,jumpTo} in terms of {skip, skipTo}

Summary:
Since D18140137 `reset()` doesn't perform any data reads, so we can simplify the implementation of the `jump*` functions to just reset the reader in case of a backward jump. The only tricky case we need to handle is when `jumpTo` is called from the middle of a run of identical values.

Delegating to `skip*` the additional benefit of inheriting the optimizations for small forward skips.

Differential Revision: D18496743

fbshipit-source-id: 73dc8b21534fba90f1ac2a924a7cebc56ffaba94
parent 60923bd6
......@@ -505,25 +505,6 @@ class UpperBitsReader : ForwardPointers<Encoder::forwardQuantum>,
return position;
}
ValueType jump(size_t n) {
if (Encoder::forwardQuantum == 0 || n <= Encoder::forwardQuantum) {
reset();
} else {
// Avoid reading the head, skip() will reposition.
position_ = std::numeric_limits<SizeType>::max();
}
return skip(n);
}
ValueType jumpToNext(ValueType v) {
if (Encoder::skipQuantum == 0 || v < Encoder::skipQuantum) {
reset();
} else {
value_ = 0; // Avoid reading the head, skipToNext() will reposition.
}
return skipToNext(v);
}
ValueType previousValue() const {
block_t block;
size_t inner;
......@@ -532,6 +513,17 @@ class UpperBitsReader : ForwardPointers<Encoder::forwardQuantum>,
return static_cast<ValueType>(8 * outer + inner - (position_ - 1));
}
// Returns true if we're at the beginning of the list, or previousValue() !=
// value().
bool isAtBeginningOfRun() const {
DCHECK_NE(position(), static_cast<SizeType>(-1));
if (position_ == 0) {
return true;
}
size_t bitPos = size_t(value_) + position_ - 1;
return (start_[bitPos / 8] & (1 << (bitPos % 8))) == 0;
}
void setDone(SizeType endPos) {
position_ = endPos;
}
......@@ -726,27 +718,46 @@ class EliasFanoReader {
* false if n >= size().
*/
bool jump(SizeType n) {
if (LIKELY(n < size_)) {
value_ = readLowerPart(n) | (upper_.jump(n + 1) << numLowerBits_);
return true;
if (n + 1 < upper_.position() + 1) { // Also works if position() == -1.
reset();
n += 1; // Initial position is -1.
} else {
n -= upper_.position();
}
return setDone();
return skip(n);
}
/**
* Jumps to the first element >= value. The reader can be in any
* state. Returns false if no such element exists.
*
* If all the values in the list can be assumed distinct, setting
* assumeDistinct = true can enable some optimizations.
*/
bool jumpTo(ValueType value) {
if (!kUnchecked && value > lastValue_) {
return setDone();
bool jumpTo(ValueType value, bool assumeDistinct = false) {
if (value == value_) {
if (assumeDistinct == true) {
return true;
}
upper_.jumpToNext(value >> numLowerBits_);
iterateTo(value);
// We might be in the middle of a run, iterate backwards to the beginning.
auto valueLower = Instructions::bzhi(value_, numLowerBits_);
while (!upper_.isAtBeginningOfRun() &&
readLowerPart(upper_.position() - 1) == valueLower) {
upper_.previous();
}
return true;
}
// We need to reset if we're not in the initial state and the jump is
// backwards.
if (position() != static_cast<SizeType>(-1) &&
value < value_) { // If position() == size() value_ is kInvalidValue.
reset();
}
return skipTo(value);
}
ValueType lastValue() const {
CHECK(!kUnchecked);
return lastValue_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment