|
17 | 17 |
|
18 | 18 | // From Apache Impala (incubating) as of 2016-01-29 |
19 | 19 |
|
| 20 | +#include <algorithm> |
20 | 21 | #include <bit> |
21 | 22 | #include <cstdint> |
22 | 23 | #include <cstring> |
@@ -1196,6 +1197,58 @@ void CheckAdvance(const Array& data, int bit_width) { |
1196 | 1197 | // literal group to a multiple of 8 with zeros, leaving up to 7 extra values. |
1197 | 1198 | } |
1198 | 1199 |
|
| 1200 | +/// Check RleBitPackedDecoder::CountUpTo, which spans multiple runs through the |
| 1201 | +/// parser (unlike the per-run decoder CountUpTo). |
| 1202 | +/// |
| 1203 | +/// Nulls are treated as regular data (i.e. their raw value is encoded and |
| 1204 | +/// decoded). The counts returned over successive batches are compared against a |
| 1205 | +/// naive count over the original data. |
| 1206 | +template <typename Type> |
| 1207 | +void CheckCountUpTo(const Array& data, int bit_width, typename Type::c_type value) { |
| 1208 | + using ArrayType = typename TypeTraits<Type>::ArrayType; |
| 1209 | + using value_type = typename Type::c_type; |
| 1210 | + |
| 1211 | + const auto data_size = static_cast<rle_size_t>(data.length()); |
| 1212 | + const value_type* data_values = static_cast<const ArrayType&>(data).raw_values(); |
| 1213 | + |
| 1214 | + ARROW_SCOPED_TRACE("bit_width = ", bit_width, ", data_size = ", data_size, |
| 1215 | + ", value = ", value); |
| 1216 | + |
| 1217 | + // Encode all values into `buffer`. |
| 1218 | + const auto buffer = EncodeTestArray<Type>(data, bit_width); |
| 1219 | + |
| 1220 | + RleBitPackedDecoder<value_type> decoder(buffer.data(), static_cast<int>(buffer.size()), |
| 1221 | + bit_width); |
| 1222 | + |
| 1223 | + // Count in a `step` small relative to the data size, so we span many |
| 1224 | + // iterations and repeatedly cross run boundaries. |
| 1225 | + const rle_size_t step = std::max<rle_size_t>(data_size / 16, 1); |
| 1226 | + rle_size_t pos = 0; |
| 1227 | + rle_size_t total_matching = 0; |
| 1228 | + while (pos < data_size) { |
| 1229 | + const auto to_process = std::min(step, data_size - pos); |
| 1230 | + const auto res = decoder.CountUpTo(value, to_process); |
| 1231 | + ASSERT_EQ(res.processed_count, to_process); |
| 1232 | + |
| 1233 | + // The matching count of this batch must equal a naive count over the data. |
| 1234 | + const auto expected = |
| 1235 | + std::count(data_values + pos, data_values + pos + to_process, value); |
| 1236 | + EXPECT_EQ(res.matching_count, static_cast<rle_size_t>(expected)) |
| 1237 | + << "at position " << pos; |
| 1238 | + |
| 1239 | + pos += res.processed_count; |
| 1240 | + total_matching += res.matching_count; |
| 1241 | + } |
| 1242 | + EXPECT_EQ(pos, data_size) << "Total number of values processed is off"; |
| 1243 | + const auto total_expected = std::count(data_values, data_values + data_size, value); |
| 1244 | + EXPECT_EQ(total_matching, static_cast<rle_size_t>(total_expected)); |
| 1245 | + |
| 1246 | + // The decoder is exhausted of the values we requested: counting further only |
| 1247 | + // yields the padding values the encoder appended to the last literal group. |
| 1248 | + const auto res = decoder.CountUpTo(value, data_size); |
| 1249 | + EXPECT_LT(res.processed_count, 8); |
| 1250 | +} |
| 1251 | + |
1199 | 1252 | template <typename T> |
1200 | 1253 | struct DataTestRleBitPackedRandomPart { |
1201 | 1254 | using value_type = T; |
@@ -1355,6 +1408,15 @@ void DoTestGetBatchSpacedRoundtrip() { |
1355 | 1408 | CheckAdvance<ArrowType>(*array, case_.bit_width); |
1356 | 1409 | CheckAdvance<ArrowType>(*array->Slice(1), case_.bit_width); |
1357 | 1410 |
|
| 1411 | + // Tests for CountUpTo, counting a value present in the data (the first one) |
| 1412 | + // and a value that may not be (the max encodable one). |
| 1413 | + const auto first = static_cast<T>( |
| 1414 | + static_cast<const typename TypeTraits<ArrowType>::ArrayType&>(*array).Value(0)); |
| 1415 | + const auto max_value = static_cast<T>((T{1} << (case_.bit_width - 1)) - 1); |
| 1416 | + CheckCountUpTo<ArrowType>(*array, case_.bit_width, first); |
| 1417 | + CheckCountUpTo<ArrowType>(*array, case_.bit_width, max_value); |
| 1418 | + CheckCountUpTo<ArrowType>(*array->Slice(1), case_.bit_width, first); |
| 1419 | + |
1358 | 1420 | // Tests for GetBatchSpaced |
1359 | 1421 | CheckRoundTrip<ArrowType>(*array, case_.bit_width, /* spaced= */ true, |
1360 | 1422 | /* parts= */ 1); |
|
0 commit comments