Commit d0430b3e authored by Shawn Wu's avatar Shawn Wu Committed by Facebook GitHub Bot

EliasFano: fix an arithmetic error for ValueType=uint64_t and SkipValueType=uint32_t.

Summary:
The fix was part of D22249713 / D24571536. However, the error is not specific to
uint8/16 support. Let's fix it right away.

Reviewed By: ot

Differential Revision: D24629540

fbshipit-source-id: 8cbc3226259d49ec3e64c03ca55f3ef1ac5b981d
parent 1d8a0445
...@@ -460,7 +460,10 @@ class UpperBitsReader : ForwardPointers<Encoder::forwardQuantum>, ...@@ -460,7 +460,10 @@ class UpperBitsReader : ForwardPointers<Encoder::forwardQuantum>,
// Skip by blocks. // Skip by blocks.
size_t cnt; size_t cnt;
size_t skip = v - (8 * outer_ - position_ - 1); // outer_ and position_ rely on negative sentinel values. We enforce the
// overflown bits are dropped by explicitly casting the final value to
// SizeType first, followed by a potential implicit cast to size_t.
size_t skip = static_cast<SizeType>(v - (8 * outer_ - position_ - 1));
constexpr size_t kBitsPerBlock = 8 * sizeof(block_t); constexpr size_t kBitsPerBlock = 8 * sizeof(block_t);
while ((cnt = Instructions::popcount(~block_)) < skip) { while ((cnt = Instructions::popcount(~block_)) < skip) {
......
...@@ -93,14 +93,13 @@ class EliasFanoCodingTest : public ::testing::Test { ...@@ -93,14 +93,13 @@ class EliasFanoCodingTest : public ::testing::Test {
template < template <
size_t kSkipQuantum, size_t kSkipQuantum,
size_t kForwardQuantum, size_t kForwardQuantum,
class ValueType, typename ValueType,
typename SkipValueType,
bool kUpperFirst> bool kUpperFirst>
void doTestAll() { void doTest() {
// SkipValueType and SizeType could both be narrower than ValueType, but
// testing all combinations would be slow, so assume they are all the same.
typedef EliasFanoEncoderV2< typedef EliasFanoEncoderV2<
ValueType, ValueType,
ValueType, SkipValueType,
kSkipQuantum, kSkipQuantum,
kForwardQuantum, kForwardQuantum,
kUpperFirst> kUpperFirst>
...@@ -115,6 +114,21 @@ class EliasFanoCodingTest : public ::testing::Test { ...@@ -115,6 +114,21 @@ class EliasFanoCodingTest : public ::testing::Test {
// TODO(ott): It should be possible to lift this constraint. // TODO(ott): It should be possible to lift this constraint.
testAll<Reader, Encoder>({0, 1, std::numeric_limits<uint32_t>::max() - 1}); testAll<Reader, Encoder>({0, 1, std::numeric_limits<uint32_t>::max() - 1});
} }
template <size_t kSkipQuantum, size_t kForwardQuantum, typename ValueType>
void doTestAll() {
// Note: SkipValue of uint8/16 aren't well-supported. For now we only test
// ValueType for uint32/64.
static_assert(
std::is_same<ValueType, uint32_t>::value ||
std::is_same<ValueType, uint64_t>::value);
// TODO(ott): improve test coverage for SkipValue of uint8/16 once such
// types are well supported.
doTest<kSkipQuantum, kForwardQuantum, ValueType, uint32_t, true>();
doTest<kSkipQuantum, kForwardQuantum, ValueType, uint32_t, false>();
doTest<kSkipQuantum, kForwardQuantum, ValueType, uint64_t, true>();
doTest<kSkipQuantum, kForwardQuantum, ValueType, uint64_t, false>();
}
}; };
TEST_F(EliasFanoCodingTest, Empty) { TEST_F(EliasFanoCodingTest, Empty) {
...@@ -122,31 +136,23 @@ TEST_F(EliasFanoCodingTest, Empty) { ...@@ -122,31 +136,23 @@ TEST_F(EliasFanoCodingTest, Empty) {
} }
TEST_F(EliasFanoCodingTest, Simple) { TEST_F(EliasFanoCodingTest, Simple) {
doTestAll<0, 0, uint32_t, false>(); doTestAll<0, 0, uint32_t>();
doTestAll<0, 0, uint32_t, true>(); doTestAll<0, 0, uint64_t>();
doTestAll<0, 0, uint64_t, false>();
doTestAll<0, 0, uint64_t, true>();
} }
TEST_F(EliasFanoCodingTest, SkipPointers) { TEST_F(EliasFanoCodingTest, SkipPointers) {
doTestAll<128, 0, uint32_t, false>(); doTestAll<128, 0, uint32_t>();
doTestAll<128, 0, uint32_t, true>(); doTestAll<128, 0, uint64_t>();
doTestAll<128, 0, uint64_t, false>();
doTestAll<128, 0, uint64_t, true>();
} }
TEST_F(EliasFanoCodingTest, ForwardPointers) { TEST_F(EliasFanoCodingTest, ForwardPointers) {
doTestAll<0, 128, uint32_t, false>(); doTestAll<0, 128, uint32_t>();
doTestAll<0, 128, uint32_t, true>(); doTestAll<0, 128, uint64_t>();
doTestAll<0, 128, uint64_t, false>();
doTestAll<0, 128, uint64_t, true>();
} }
TEST_F(EliasFanoCodingTest, SkipForwardPointers) { TEST_F(EliasFanoCodingTest, SkipForwardPointers) {
doTestAll<128, 128, uint32_t, false>(); doTestAll<128, 128, uint32_t>();
doTestAll<128, 128, uint32_t, true>(); doTestAll<128, 128, uint64_t>();
doTestAll<128, 128, uint64_t, false>();
doTestAll<128, 128, uint64_t, true>();
} }
TEST_F(EliasFanoCodingTest, BugLargeGapInUpperBits) { // t16274876 TEST_F(EliasFanoCodingTest, BugLargeGapInUpperBits) { // t16274876
......
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