Commit bdf37414 authored by Philip Pronin's avatar Philip Pronin Committed by Facebook GitHub Bot

fix semantics of QMS::Iterator::skipTo

Summary: Passing large `key` doesn't correctly advance position to the end.

Reviewed By: ot

Differential Revision: D29712973

fbshipit-source-id: 7da7c49250753c12f3703ccf49107e56bf841131
parent ea91c9bc
...@@ -31,7 +31,7 @@ namespace folly { ...@@ -31,7 +31,7 @@ namespace folly {
namespace qms_detail { namespace qms_detail {
/* /**
* Reference: Faster Remainder by Direct Computation: Applications to Compilers * Reference: Faster Remainder by Direct Computation: Applications to Compilers
* and Software Libraries, Software: Practice and Experience 49 (6), 2019. * and Software Libraries, Software: Practice and Experience 49 (6), 2019.
*/ */
...@@ -287,13 +287,7 @@ uint64_t QuotientMultiSet<Instructions>::getBlockPayload( ...@@ -287,13 +287,7 @@ uint64_t QuotientMultiSet<Instructions>::getBlockPayload(
template <class Instructions> template <class Instructions>
QuotientMultiSet<Instructions>::Iterator::Iterator( QuotientMultiSet<Instructions>::Iterator::Iterator(
const QuotientMultiSet<Instructions>* qms) const QuotientMultiSet<Instructions>* qms)
: qms_(qms), : qms_(qms) {}
key_(0),
occBlockIndex_(-1),
occOffsetInBlock_(0),
occWord_(0),
occBlock_(nullptr),
pos_(-1) {}
template <class Instructions> template <class Instructions>
bool QuotientMultiSet<Instructions>::Iterator::next() { bool QuotientMultiSet<Instructions>::Iterator::next() {
...@@ -326,7 +320,7 @@ bool QuotientMultiSet<Instructions>::Iterator::next() { ...@@ -326,7 +320,7 @@ bool QuotientMultiSet<Instructions>::Iterator::next() {
template <class Instructions> template <class Instructions>
bool QuotientMultiSet<Instructions>::Iterator::skipTo(uint64_t key) { bool QuotientMultiSet<Instructions>::Iterator::skipTo(uint64_t key) {
if (key > qms_->maxKey_) { if (key > qms_->maxKey_) {
return false; return setEnd();
} }
const auto qr = const auto qr =
qms_detail::getQuotientAndRemainder(key, qms_->divisor_, qms_->fraction_); qms_detail::getQuotientAndRemainder(key, qms_->divisor_, qms_->fraction_);
......
...@@ -203,24 +203,24 @@ class QuotientMultiSet<Instructions>::Iterator { ...@@ -203,24 +203,24 @@ class QuotientMultiSet<Instructions>::Iterator {
bool nextOccupied(); bool nextOccupied();
const QuotientMultiSet<Instructions>* qms_; const QuotientMultiSet<Instructions>* qms_;
uint64_t key_; uint64_t key_ = 0;
// State members for the quotient occupied position. // State members for the quotient occupied position.
// Block index of key_'s occupied slot. // Block index of key_'s occupied slot.
size_t occBlockIndex_; size_t occBlockIndex_ = -1;
// Block offset of key_'s occupied slot. // Block offset of key_'s occupied slot.
uint64_t occOffsetInBlock_; uint64_t occOffsetInBlock_ = 0;
// Occupied words of the occupiedBlock_ after quotientBlockOffset_. // Occupied words of the occupiedBlock_ after quotientBlockOffset_.
uint64_t occWord_; uint64_t occWord_ = 0;
// Block of the current occupied slot. // Block of the current occupied slot.
const Block* occBlock_; const Block* occBlock_ = nullptr;
// State member for the actual key position. // State member for the actual key position.
// Position of the current key_. // Position of the current key_.
size_t pos_; size_t pos_ = -1;
}; };
/* /**
* Class to build a QuotientMultiSet. * Class to build a QuotientMultiSet.
* *
* The builder requires inserting elements in non-decreasing order. * The builder requires inserting elements in non-decreasing order.
......
...@@ -72,7 +72,7 @@ class QuotientMultiSetTest : public ::testing::Test { ...@@ -72,7 +72,7 @@ class QuotientMultiSetTest : public ::testing::Test {
pos = reader.getBlockPayload((range.end - 1) / kBlockSize); pos = reader.getBlockPayload((range.end - 1) / kBlockSize);
EXPECT_EQ(index - 1, pos + (range.end - 1) % kBlockSize) << debugInfo(); EXPECT_EQ(index - 1, pos + (range.end - 1) % kBlockSize) << debugInfo();
iter.skipTo(key); EXPECT_TRUE(iter.skipTo(key));
EXPECT_EQ(key, iter.key()) << debugInfo(); EXPECT_EQ(key, iter.key()) << debugInfo();
EXPECT_EQ(range.begin, iter.pos()) << debugInfo(); EXPECT_EQ(range.begin, iter.pos()) << debugInfo();
EXPECT_EQ( EXPECT_EQ(
...@@ -109,6 +109,7 @@ class QuotientMultiSetTest : public ::testing::Test { ...@@ -109,6 +109,7 @@ class QuotientMultiSetTest : public ::testing::Test {
if (keys.back() < maxKey) { if (keys.back() < maxKey) {
uint64_t key = folly::Random::rand64(keys.back(), maxKey, rng) + 1; uint64_t key = folly::Random::rand64(keys.back(), maxKey, rng) + 1;
EXPECT_FALSE(reader.equalRange(key)) << keys.back() << " " << key; EXPECT_FALSE(reader.equalRange(key)) << keys.back() << " " << key;
EXPECT_FALSE(iter.done());
EXPECT_FALSE(iter.skipTo(key)); EXPECT_FALSE(iter.skipTo(key));
EXPECT_TRUE(iter.done()); EXPECT_TRUE(iter.done());
} }
...@@ -120,6 +121,13 @@ class QuotientMultiSetTest : public ::testing::Test { ...@@ -120,6 +121,13 @@ class QuotientMultiSetTest : public ::testing::Test {
} }
EXPECT_FALSE(nextIter.next()); EXPECT_FALSE(nextIter.next());
EXPECT_TRUE(nextIter.done()); EXPECT_TRUE(nextIter.done());
if (maxKey + 1 != 0) {
folly::QuotientMultiSet<>::Iterator skipToEndIter(&reader);
EXPECT_FALSE(skipToEndIter.done());
EXPECT_FALSE(skipToEndIter.skipTo(maxKey + 1));
EXPECT_TRUE(skipToEndIter.done());
}
} }
std::mt19937 rng; std::mt19937 rng;
......
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