@@ -258,6 +258,18 @@ class RleBitPackedParser {
258258 std::pair<rle_size_t , ControlFlow> PeekImpl (Handler&&) const ;
259259};
260260
261+ template <typename T>
262+ struct RleCountUpToParams {
263+ T value;
264+ rle_size_t batch_size;
265+ rle_size_t value_bit_width;
266+ };
267+
268+ struct RleCountUpToResult {
269+ rle_size_t matching_count;
270+ rle_size_t processed_count;
271+ };
272+
261273// / Decoder class for a single run of RLE encoded data.
262274template <typename T>
263275class RleRunDecoder {
@@ -300,6 +312,15 @@ class RleRunDecoder {
300312 return steps;
301313 }
302314
315+ // / Advance and count the number of occurrences of a value.
316+ // /
317+ // / The count is limited to at most the next `batch_size` items.
318+ // / @return The matching value count and number of elements that were processed.
319+ RleCountUpToResult CountUpTo (const RleCountUpToParams<value_type>& p) {
320+ const auto steps = Advance (p.batch_size );
321+ return {.matching_count = steps * (p.value == value_), .processed_count = steps};
322+ }
323+
303324 // / Get the next value and return false if there are no more.
304325 [[nodiscard]] constexpr bool Get (value_type* out_value, rle_size_t value_bit_width) {
305326 return GetBatch (out_value, 1 , value_bit_width) == 1 ;
@@ -363,6 +384,29 @@ class BitPackedRunDecoder {
363384 return steps;
364385 }
365386
387+ // / Advance and count the number of occurrence of a values.
388+ // /
389+ // / The count is limited to at most the next `batch_size` items.
390+ // / @return The matching value count and number of of element that were processed.
391+ RleCountUpToResult CountUpTo (const RleCountUpToParams<value_type>& p) {
392+ // Decoding in a stack buffer of 512 values: 1KB for int16_t used in levels
393+ // and up to 4KB for uint64_t.
394+ constexpr rle_size_t kBufferValueCount = 512 ;
395+ alignas (16 ) value_type buffer[kBufferValueCount ]; // uninitialized
396+
397+ rle_size_t remaining = p.batch_size ;
398+ rle_size_t count = 0 ;
399+ rle_size_t read_iter = 0 ;
400+ do {
401+ const auto batch_iter = std::min (remaining, kBufferValueCount );
402+ read_iter = GetBatch (buffer, batch_iter, p.value_bit_width );
403+ count += static_cast <rle_size_t >(std::count (buffer, buffer + read_iter, p.value ));
404+ remaining -= read_iter;
405+ } while (remaining > 0 && read_iter > 0 );
406+
407+ return {.matching_count = count, .processed_count = p.batch_size - remaining};
408+ }
409+
366410 // / Get the next value and return false if there are no more.
367411 [[nodiscard]] constexpr bool Get (value_type* out_value, rle_size_t value_bit_width) {
368412 return GetBatch (out_value, 1 , value_bit_width) == 1 ;
@@ -448,6 +492,16 @@ class RleBitPackedDecoder {
448492 // / This is how one can check for errors.
449493 bool exhausted () const { return (run_remaining () == 0 ) && parser_.exhausted (); }
450494
495+ // / Advance by as many values as provided or until exhaustion of the decoder.
496+ // / Return the number of values skipped.
497+ [[nodiscard]] rle_size_t Advance (rle_size_t batch_size);
498+
499+ // / Advance and count the number of occurrence of a values.
500+ // /
501+ // / The count is limited to at most the next `batch_size` items.
502+ // / @return The matching value count and number of of element that were processed.
503+ RleCountUpToResult CountUpTo (value_type value, rle_size_t batch_size);
504+
451505 // / Gets the next value or returns false if there are no more or an error occurred.
452506 // /
453507 // / NB: Because the encoding only supports literal runs with lengths
@@ -500,12 +554,15 @@ class RleBitPackedDecoder {
500554 return std::visit ([](const auto & dec) { return dec.remaining (); }, decoder_);
501555 }
502556
503- // / Get a batch of values from the current run and return the number elements read.
504- [[nodiscard]] rle_size_t RunGetBatch (value_type* out, rle_size_t batch_size) {
505- return std::visit (
506- [&](auto & dec) { return dec.GetBatch (out, batch_size, value_bit_width_); },
507- decoder_);
508- }
557+ // / Process data in the current run and subsequent ones.
558+ // /
559+ // / `func` is called as `func(decoder, run_batch_size)` where `decoder` are
560+ // / statically-typed run decoder (not the variant).
561+ // / Must return the number of values it processed.
562+ // /
563+ // / Return the number of values processed.
564+ template <typename Callable>
565+ rle_size_t ProcessValues (Callable&& func, rle_size_t batch_size);
509566
510567 // / Utility methods for retrieving spaced values.
511568 template <typename Converter>
@@ -515,6 +572,82 @@ class RleBitPackedDecoder {
515572 int64_t valid_bits_offset, rle_size_t null_count);
516573};
517574
575+ // / Minimal decoder for legacy bit packed encoding (BIT_PACKED = 4).
576+ // /
577+ // / The number of values that the decoder can represent is up to 2^31 - 1.
578+ template <typename T>
579+ class BitPackedDecoder : private BitPackedRunDecoder <T> {
580+ private:
581+ using Base = BitPackedRunDecoder<T>;
582+
583+ public:
584+ // / The type in which the data should be decoded.
585+ using value_type = T;
586+
587+ using Base::Advance;
588+
589+ BitPackedDecoder () noexcept = default ;
590+
591+ // / Create a decoder object.
592+ // /
593+ // / Unless explicitly given, then number of values is deduced from the data size,
594+ // / in which case it may read more values from the input stream than the user
595+ // / intended (to reach final byte alignment). This option is mandatory if the
596+ // / `value_bit_width` is zero.
597+ // /
598+ // / @param data and data_size are the raw bytes to decode.
599+ // / @param value_bit_width is the size in bits of each encoded value.
600+ // / @param value_count is an optional number of values in the run.
601+ BitPackedDecoder (const uint8_t * data, rle_size_t data_size, rle_size_t value_bit_width,
602+ rle_size_t value_count) noexcept {
603+ Reset (data, data_size, value_bit_width, value_count);
604+ }
605+
606+ void Reset (const uint8_t * data, rle_size_t data_size, rle_size_t value_bit_width,
607+ rle_size_t value_count) noexcept {
608+ ARROW_DCHECK_GE (value_count, 0 );
609+ ARROW_DCHECK_GE (value_bit_width, 0 );
610+ ARROW_DCHECK_LE (value_bit_width, 64 );
611+
612+ value_bit_width_ = value_bit_width;
613+
614+ ARROW_DCHECK_LE (value_count, std::numeric_limits<rle_size_t >::max ());
615+ const auto run = BitPackedRun{
616+ /* data= */ data,
617+ /* value_count= */ value_count,
618+ /* value_bit_width= */ value_bit_width,
619+ /* max_read_bytes= */ data_size,
620+ };
621+ return Base::Reset (run, value_bit_width);
622+ }
623+
624+ // / Whether there is still values to iterate over.
625+ bool exhausted () const { return Base::remaining () == 0 ; }
626+
627+ // / Advance and count the number of occurrence of a values.
628+ // /
629+ // / The count is limited to at most the next `batch_size` items.
630+ // / @return The matching value count and number of of element that were processed.
631+ RleCountUpToResult CountUpTo (value_type value, rle_size_t batch_size) {
632+ return Base::CountUpTo ({
633+ .value = value,
634+ .batch_size = batch_size,
635+ .value_bit_width = value_bit_width_,
636+ });
637+ }
638+
639+ // / Gets the next value or returns false if there are no more or an error occurred.
640+ [[nodiscard]] bool Get (value_type* val) { return Base::Get (val, value_bit_width_); }
641+
642+ // / Get a batch of values return the number of decoded elements.
643+ [[nodiscard]] rle_size_t GetBatch (value_type* out, rle_size_t batch_size) {
644+ return Base::GetBatch (out, batch_size, value_bit_width_);
645+ }
646+
647+ private:
648+ rle_size_t value_bit_width_ = {};
649+ };
650+
518651// / Class to incrementally build the rle data. This class does not allocate any memory.
519652// / The encoding has two modes: encoding repeated runs and literal runs.
520653// / If the run is sufficiently short, it is more efficient to encode as a literal run.
@@ -782,30 +915,26 @@ struct RleBitPackedDecoderGetRunDecoder<T, BitPackedRun> {
782915};
783916
784917template <typename T>
785- bool RleBitPackedDecoder<T>::Get(value_type* val) {
786- return GetBatch (val, 1 ) == 1 ;
787- }
788-
789- template <typename T>
790- auto RleBitPackedDecoder<T>::GetBatch(value_type* out,
791- rle_size_t batch_size) -> rle_size_t {
918+ template <typename Callable>
919+ auto RleBitPackedDecoder<T>::ProcessValues(Callable&& func,
920+ rle_size_t batch_size) -> rle_size_t {
792921 using ControlFlow = RleBitPackedParser::ControlFlow;
793922
794923 if (ARROW_PREDICT_FALSE (batch_size == 0 || exhausted ())) {
795924 return 0 ;
796925 }
797926
798- rle_size_t values_read = 0 ;
927+ rle_size_t values_processed = 0 ;
799928
800929 // Remaining from a previous call that would have left some unread data from a run.
801930 if (ARROW_PREDICT_FALSE (run_remaining () > 0 )) {
802- const auto read = RunGetBatch (out, batch_size);
803- values_read += read ;
804- out += read ;
931+ const auto processed =
932+ std::visit ([&]( auto & decoder) { return func (decoder, batch_size); }, decoder_) ;
933+ values_processed += processed ;
805934
806935 // Either we fulfilled all the batch to be read or we finished remaining run.
807- if (ARROW_PREDICT_FALSE (values_read == batch_size)) {
808- return values_read ;
936+ if (ARROW_PREDICT_FALSE (values_processed == batch_size)) {
937+ return values_processed ;
809938 }
810939 ARROW_DCHECK (run_remaining () == 0 );
811940 }
@@ -814,23 +943,66 @@ auto RleBitPackedDecoder<T>::GetBatch(value_type* out,
814943 using RunDecoder =
815944 typename RleBitPackedDecoderGetRunDecoder<value_type, decltype (run)>::type;
816945
817- ARROW_DCHECK_LT (values_read, batch_size);
946+ ARROW_DCHECK_LT (values_processed, batch_size);
947+ // Local decoder to keep its type transparent to the compiler.
818948 RunDecoder decoder (run, value_bit_width_);
819- const auto read = decoder.GetBatch (out, batch_size - values_read, value_bit_width_);
820- ARROW_DCHECK_LE (read, batch_size - values_read);
821- values_read += read;
822- out += read;
949+ const auto read = func (decoder, batch_size - values_processed);
950+ ARROW_DCHECK_LE (read, batch_size - values_processed);
951+ values_processed += read;
823952
824- // Stop reading and store remaining decoder
825- if ( ARROW_PREDICT_FALSE (values_read == batch_size || read == 0 )) {
953+ if ( ARROW_PREDICT_FALSE (values_processed == batch_size || read == 0 )) {
954+ // Stop reading and store remaining decoder
826955 decoder_ = std::move (decoder);
827956 return ControlFlow::Break;
828957 }
829-
830958 return ControlFlow::Continue;
831959 });
832960
833- return values_read;
961+ return values_processed;
962+ }
963+
964+ template <typename T>
965+ auto RleBitPackedDecoder<T>::Advance(rle_size_t batch_size) -> rle_size_t {
966+ return ProcessValues (
967+ [](auto & decoder, rle_size_t run_batch_size) {
968+ return decoder.Advance (run_batch_size);
969+ },
970+ batch_size);
971+ }
972+
973+ template <typename T>
974+ RleCountUpToResult RleBitPackedDecoder<T>::CountUpTo(value_type value,
975+ rle_size_t batch_size) {
976+ rle_size_t count = 0 ;
977+ const rle_size_t processed_count = ProcessValues (
978+ [value, this , &count](auto & decoder, rle_size_t run_batch_size) {
979+ const auto result = decoder.CountUpTo ({
980+ .value = value,
981+ .batch_size = run_batch_size,
982+ .value_bit_width = value_bit_width_,
983+ });
984+ count += result.matching_count ;
985+ return result.processed_count ;
986+ },
987+ batch_size);
988+ return {.matching_count = count, .processed_count = processed_count};
989+ }
990+
991+ template <typename T>
992+ bool RleBitPackedDecoder<T>::Get(value_type* val) {
993+ return GetBatch (val, 1 ) == 1 ;
994+ }
995+
996+ template <typename T>
997+ auto RleBitPackedDecoder<T>::GetBatch(value_type* out,
998+ rle_size_t batch_size) -> rle_size_t {
999+ return ProcessValues (
1000+ [&out, this ](auto & decoder, rle_size_t run_batch_size) {
1001+ const auto read = decoder.GetBatch (out, run_batch_size, value_bit_width_);
1002+ out += read;
1003+ return read;
1004+ },
1005+ batch_size);
8341006}
8351007
8361008namespace internal {
@@ -1269,68 +1441,27 @@ template <typename V>
12691441auto RleBitPackedDecoder<T>::GetBatchWithDict(const V* dictionary,
12701442 int32_t dictionary_length, V* out,
12711443 rle_size_t batch_size) -> rle_size_t {
1272- using ControlFlow = RleBitPackedParser::ControlFlow;
1273-
12741444 if (ARROW_PREDICT_FALSE (batch_size <= 0 || dictionary_length == 0 )) {
12751445 // Either empty batch or invalid dictionary
12761446 return 0 ;
12771447 }
12781448
12791449 internal::DictionaryConverter<V, value_type> converter{dictionary, dictionary_length};
12801450
1281- // Make lightweight BitRun class to reuse previous methods .
1451+ // Make lightweight BitRun class to reuse the spaced code path with no nulls .
12821452 constexpr internal::UnreachableBitRunReader validity_reader{};
12831453 internal::AllSetBitRun validity_run = {batch_size};
12841454
1285- rle_size_t values_read = 0 ;
1286- auto batch_values_remaining = [&]() {
1287- ARROW_DCHECK_LE (values_read, batch_size);
1288- return batch_size - values_read;
1289- };
1290-
1291- if (ARROW_PREDICT_FALSE (run_remaining () > 0 )) {
1292- const auto read = internal::RunGetSpaced (&converter, out, batch_size,
1293- /* null_count= */ 0 , value_bit_width_,
1294- &validity_reader, &validity_run, &decoder_);
1295-
1296- ARROW_DCHECK_EQ (read.null_read , 0 );
1297- values_read += read.values_read ;
1298- out += read.values_read ;
1299-
1300- // Either we fulfilled all the batch values to be read
1301- if (ARROW_PREDICT_FALSE (values_read >= batch_size)) {
1302- // There may be remaining null if they are not greedily filled
1303- return values_read;
1304- }
1305-
1306- // We finished the remaining run
1307- ARROW_DCHECK (run_remaining () == 0 );
1308- }
1309-
1310- parser_.ParseWithCallable ([&](auto run) {
1311- using RunDecoder =
1312- typename RleBitPackedDecoderGetRunDecoder<value_type, decltype (run)>::type;
1313-
1314- RunDecoder decoder (run, value_bit_width_);
1315-
1316- const auto read = internal::RunGetSpaced (&converter, out, batch_values_remaining (),
1317- /* null_count= */ 0 , value_bit_width_,
1318- &validity_reader, &validity_run, &decoder);
1319-
1320- ARROW_DCHECK_EQ (read.null_read , 0 );
1321- values_read += read.values_read ;
1322- out += read.values_read ;
1323-
1324- // Stop reading and store remaining decoder
1325- if (ARROW_PREDICT_FALSE (read.values_read == 0 || values_read == batch_size)) {
1326- decoder_ = std::move (decoder);
1327- return ControlFlow::Break;
1328- }
1329-
1330- return ControlFlow::Continue;
1331- });
1332-
1333- return values_read;
1455+ return ProcessValues (
1456+ [&](auto & decoder, rle_size_t run_batch_size) {
1457+ const auto read = internal::RunGetSpaced (
1458+ &converter, out, run_batch_size, /* null_count= */ 0 , value_bit_width_,
1459+ &validity_reader, &validity_run, &decoder);
1460+ ARROW_DCHECK_EQ (read.null_read , 0 );
1461+ out += read.values_read ;
1462+ return read.values_read ;
1463+ },
1464+ batch_size);
13341465}
13351466
13361467template <typename T>
0 commit comments