return value_;
}
- ValueType goTo(size_t n) {
+ ValueType jump(size_t n) {
if (Encoder::forwardQuantum == 0 || n <= Encoder::forwardQuantum) {
reset();
} else {
- position_ = -1; // Avoid reading the head, skip() will call reposition().
+ position_ = -1; // Avoid reading the head, skip() will reposition.
}
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);
+ }
+
private:
ValueType setValue() {
value_ = static_cast<ValueType>(8 * outer_ + inner_ - position_);
(lastUpperValue << list_.numLowerBits);
}
- size_t size() const { return list_.size; }
-
- size_t position() const { return progress_ - 1; }
- ValueType value() const { return value_; }
+ void reset() {
+ upper_.reset();
+ progress_ = 0;
+ value_ = 0;
+ }
bool next() {
if (UNLIKELY(progress_ == list_.size)) {
DCHECK_GE(value, value_);
if (value <= value_) {
return true;
- }
- if (value > lastValue_) {
+ } else if (value > lastValue_) {
progress_ = list_.size;
value_ = std::numeric_limits<ValueType>::max();
return false;
}
upper_.skipToNext(value >> list_.numLowerBits);
- progress_ = upper_.position();
- value_ = readLowerPart(progress_) |
- (upper_.value() << list_.numLowerBits);
- ++progress_;
- while (value_ < value) {
- value_ = readLowerPart(progress_) |
- (upper_.next() << list_.numLowerBits);
- ++progress_;
- }
-
+ iterateTo(value);
return true;
}
- bool goTo(size_t n) {
+ bool jump(size_t n) {
if (LIKELY(n - 1 < list_.size)) { // n > 0 && n <= list_.size
progress_ = n;
- value_ = readLowerPart(n - 1) | (upper_.goTo(n) << list_.numLowerBits);
+ value_ = readLowerPart(n - 1) | (upper_.jump(n) << list_.numLowerBits);
return true;
} else if (n == 0) {
- upper_.reset();
- progress_ = 0;
- value_ = 0;
+ reset();
return true;
}
progress_ = list_.size;
return false;
}
+ ValueType jumpTo(ValueType value) {
+ if (value <= 0) {
+ reset();
+ return true;
+ } else if (value > lastValue_) {
+ progress_ = list_.size;
+ value_ = std::numeric_limits<ValueType>::max();
+ return false;
+ }
+
+ upper_.jumpToNext(value >> list_.numLowerBits);
+ iterateTo(value);
+ return true;
+ }
+
+ size_t size() const { return list_.size; }
+
+ size_t position() const { return progress_ - 1; }
+ ValueType value() const { return value_; }
+
private:
ValueType readLowerPart(size_t i) const {
DCHECK_LT(i, list_.size);
return lowerMask_ & (ptrv >> (pos % 8));
}
+ void iterateTo(ValueType value) {
+ progress_ = upper_.position();
+ value_ = readLowerPart(progress_) | (upper_.value() << list_.numLowerBits);
+ ++progress_;
+ while (value_ < value) {
+ value_ = readLowerPart(progress_) | (upper_.next() << list_.numLowerBits);
+ ++progress_;
+ }
+ }
+
const EliasFanoCompressedList list_;
const ValueType lowerMask_;
detail::UpperBitsReader<Encoder, Instructions> upper_;
}
template <class Reader, class List>
-void testGoTo(const std::vector<uint32_t>& data, const List& list) {
+void testJump(const std::vector<uint32_t>& data, const List& list) {
std::mt19937 gen;
std::vector<size_t> is(data.size());
for (size_t i = 0; i < data.size(); ++i) {
}
Reader reader(list);
- EXPECT_TRUE(reader.goTo(0));
+ EXPECT_TRUE(reader.jump(0));
EXPECT_EQ(reader.value(), 0);
for (auto i : is) {
- EXPECT_TRUE(reader.goTo(i + 1));
+ EXPECT_TRUE(reader.jump(i + 1));
EXPECT_EQ(reader.value(), data[i]);
}
- EXPECT_FALSE(reader.goTo(data.size() + 1));
+ EXPECT_FALSE(reader.jump(data.size() + 1));
+ EXPECT_EQ(reader.value(), std::numeric_limits<uint32_t>::max());
+}
+
+template <class Reader, class List>
+void testJumpTo(const std::vector<uint32_t>& data, const List& list) {
+ CHECK(!data.empty());
+
+ Reader reader(list);
+
+ std::mt19937 gen;
+ std::uniform_int_distribution<> values(0, data.back());
+ const size_t iters = Reader::EncoderType::skipQuantum == 0 ? 100 : 10000;
+ for (size_t i = 0; i < iters; ++i) {
+ const uint32_t value = values(gen);
+ auto it = std::lower_bound(data.begin(), data.end(), value);
+ CHECK(it != data.end());
+ EXPECT_TRUE(reader.jumpTo(value));
+ EXPECT_EQ(reader.value(), *it);
+ }
+
+ EXPECT_TRUE(reader.jumpTo(0));
+ EXPECT_EQ(reader.value(), 0);
+
+ if (data.front() > 0) {
+ EXPECT_TRUE(reader.jumpTo(1));
+ EXPECT_EQ(reader.value(), data.front());
+ }
+
+ EXPECT_TRUE(reader.jumpTo(data.back()));
+ EXPECT_EQ(reader.value(), data.back());
+
+ EXPECT_FALSE(reader.jumpTo(data.back() + 1));
EXPECT_EQ(reader.value(), std::numeric_limits<uint32_t>::max());
}
Reader reader(list);
EXPECT_FALSE(reader.skip(1));
EXPECT_FALSE(reader.skip(10));
+ EXPECT_FALSE(reader.jump(1));
+ EXPECT_FALSE(reader.jump(10));
}
{
Reader reader(list);
EXPECT_FALSE(reader.skipTo(1));
+ EXPECT_FALSE(reader.jumpTo(1));
}
}
testNext<Reader>(data, list);
testSkip<Reader>(data, list);
testSkipTo<Reader>(data, list);
- testGoTo<Reader>(data, list);
+ testJump<Reader>(data, list);
+ testJumpTo<Reader>(data, list);
list.free();
}
for (size_t i = 0, j; i < iters; ) {
Reader reader(list);
for (j = 0; reader.next(); ++j, ++i) {
- const uint32_t value = reader.value();
- CHECK_EQ(value, data[j]) << j;
+ CHECK_EQ(reader.value(), data[j]) << j;
}
}
}
Reader reader(list);
for (j = skip - 1; j < data.size(); j += skip, ++i) {
reader.skip(skip);
- const uint32_t value = reader.value();
- CHECK_EQ(value, data[j]);
+ CHECK_EQ(reader.value(), data[j]);
}
}
}
Reader reader(list);
for (j = 0; j < data.size(); j += skip, ++i) {
reader.skipTo(data[j]);
- const uint32_t value = reader.value();
- CHECK_EQ(value, data[j]);
+ CHECK_EQ(reader.value(), data[j]);
}
}
}
template <class Reader, class List>
-void bmGoTo(const List& list, const std::vector<uint32_t>& data,
+void bmJump(const List& list, const std::vector<uint32_t>& data,
const std::vector<size_t>& order, size_t iters) {
CHECK(!data.empty());
CHECK_EQ(data.size(), order.size());
Reader reader(list);
for (size_t i = 0; i < iters; ) {
for (size_t j : order) {
- reader.goTo(j + 1);
- const uint32_t value = reader.value();
- CHECK_EQ(value, data[j]);
+ reader.jump(j + 1);
+ CHECK_EQ(reader.value(), data[j]);
+ ++i;
+ }
+ }
+}
+
+template <class Reader, class List>
+void bmJumpTo(const List& list, const std::vector<uint32_t>& data,
+ const std::vector<size_t>& order, size_t iters) {
+ CHECK(!data.empty());
+ CHECK_EQ(data.size(), order.size());
+
+ Reader reader(list);
+ for (size_t i = 0; i < iters; ) {
+ for (size_t j : order) {
+ reader.jumpTo(data[j]);
+ CHECK_EQ(reader.value(), data[j]);
++i;
}
}
bmSkip<bm::Reader>(bm::list, bm::data, 1000, bm::k1M);
}
-BENCHMARK(GoTo_ForwardQ128_1M) {
- bmGoTo<bm::Reader>(bm::list, bm::data, bm::order, bm::k1M);
+BENCHMARK(Jump_ForwardQ128_1M) {
+ bmJump<bm::Reader>(bm::list, bm::data, bm::order, bm::k1M);
}
+BENCHMARK_DRAW_LINE();
+
BENCHMARK(SkipTo1_SkipQ128_1M) {
bmSkipTo<bm::Reader>(bm::list, bm::data, 1, bm::k1M);
}
-BENCHMARK_DRAW_LINE();
-
BENCHMARK(SkipTo10_SkipQ128_1M) {
bmSkipTo<bm::Reader>(bm::list, bm::data, 10, bm::k1M);
}
bmSkipTo<bm::Reader>(bm::list, bm::data, 1000, bm::k1M);
}
+BENCHMARK(JumpTo_SkipQ128_1M) {
+ bmJumpTo<bm::Reader>(bm::list, bm::data, bm::order, bm::k1M);
+}
+
BENCHMARK_DRAW_LINE();
BENCHMARK(Encode_10) {
============================================================================
folly/experimental/test/EliasFanoCodingTest.cpp relative time/iter iters/s
============================================================================
-Next_1M 4.86ms 205.97
-Skip1_ForwarQ128_1M 5.17ms 193.36
-Skip10_ForwarQ128_1M 13.69ms 73.03
-Skip100_ForwardQ128_1M 26.76ms 37.37
-Skip1000_ForwardQ128_1M 20.66ms 48.40
-GoTo_ForwardQ128_1M 43.75ms 22.86
+Next_1M 4.61ms 216.70
+Skip1_ForwarQ128_1M 5.33ms 187.71
+Skip10_ForwarQ128_1M 14.23ms 70.26
+Skip100_ForwardQ128_1M 29.10ms 34.37
+Skip1000_ForwardQ128_1M 21.15ms 47.28
+Jump_ForwardQ128_1M 46.30ms 21.60
----------------------------------------------------------------------------
-SkipTo1_SkipQ128_1M 9.74ms 102.70
-SkipTo10_SkipQ128_1M 30.62ms 32.66
-SkipTo100_SkipQ128_1M 37.70ms 26.53
-SkipTo1000_SkipQ128_1M 31.14ms 32.11
+SkipTo1_SkipQ128_1M 12.03ms 83.15
+SkipTo10_SkipQ128_1M 36.11ms 27.69
+SkipTo100_SkipQ128_1M 42.91ms 23.30
+SkipTo1000_SkipQ128_1M 36.92ms 27.08
+JumpTo_SkipQ128_1M 78.51ms 12.74
----------------------------------------------------------------------------
-Encode_10 208.16ns 4.80M
-Encode_1M 8.90ms 112.37
+Encode_10 199.19ns 5.02M
+Encode_1M 8.82ms 113.37
============================================================================
#endif