|
17 | 17 |
|
18 | 18 | #pragma once |
19 | 19 |
|
| 20 | +#include <algorithm> |
20 | 21 | #include <bit> |
21 | 22 | #include <cassert> |
22 | 23 | #include <cstdint> |
@@ -504,6 +505,89 @@ inline Status VisitSetBitRuns(const uint8_t* bitmap, int64_t offset, int64_t len |
504 | 505 | return Status::OK(); |
505 | 506 | } |
506 | 507 |
|
| 508 | +template <typename Visit> |
| 509 | +inline Status VisitTwoBitRuns(const uint8_t* left_bitmap, int64_t left_offset, |
| 510 | + const uint8_t* right_bitmap, int64_t right_offset, |
| 511 | + int64_t length, Visit&& visit) { |
| 512 | + if (length == 0) { |
| 513 | + return Status::OK(); |
| 514 | + } |
| 515 | + if (left_bitmap == NULLPTR) { |
| 516 | + return VisitBitRuns(right_bitmap, right_offset, length, std::forward<Visit>(visit)); |
| 517 | + } |
| 518 | + if (right_bitmap == NULLPTR) { |
| 519 | + return VisitBitRuns(left_bitmap, left_offset, length, std::forward<Visit>(visit)); |
| 520 | + } |
| 521 | + |
| 522 | + BitRunReader left_reader(left_bitmap, left_offset, length); |
| 523 | + BitRunReader right_reader(right_bitmap, right_offset, length); |
| 524 | + auto left_run = left_reader.NextRun(); |
| 525 | + auto right_run = right_reader.NextRun(); |
| 526 | + int64_t left_end = left_run.length; |
| 527 | + int64_t right_end = right_run.length; |
| 528 | + int64_t position = 0; |
| 529 | + int64_t output_start = 0; |
| 530 | + bool output_set = left_run.set && right_run.set; |
| 531 | + |
| 532 | + while (position < length) { |
| 533 | + const int64_t segment_end = std::min(left_end, right_end); |
| 534 | + const bool segment_set = left_run.set && right_run.set; |
| 535 | + if (segment_set != output_set) { |
| 536 | + ARROW_RETURN_NOT_OK(visit(output_start, position - output_start, output_set)); |
| 537 | + output_start = position; |
| 538 | + output_set = segment_set; |
| 539 | + } |
| 540 | + |
| 541 | + position = segment_end; |
| 542 | + if (position == left_end) { |
| 543 | + left_run = left_reader.NextRun(); |
| 544 | + left_end += left_run.length; |
| 545 | + } |
| 546 | + if (position == right_end) { |
| 547 | + right_run = right_reader.NextRun(); |
| 548 | + right_end += right_run.length; |
| 549 | + } |
| 550 | + } |
| 551 | + return visit(output_start, length - output_start, output_set); |
| 552 | +} |
| 553 | + |
| 554 | +template <typename Visit> |
| 555 | +inline Status VisitTwoSetBitRuns(const uint8_t* left_bitmap, int64_t left_offset, |
| 556 | + const uint8_t* right_bitmap, int64_t right_offset, |
| 557 | + int64_t length, Visit&& visit) { |
| 558 | + if (length == 0) { |
| 559 | + return Status::OK(); |
| 560 | + } |
| 561 | + if (left_bitmap == NULLPTR) { |
| 562 | + return VisitSetBitRuns(right_bitmap, right_offset, length, |
| 563 | + std::forward<Visit>(visit)); |
| 564 | + } |
| 565 | + if (right_bitmap == NULLPTR) { |
| 566 | + return VisitSetBitRuns(left_bitmap, left_offset, length, std::forward<Visit>(visit)); |
| 567 | + } |
| 568 | + |
| 569 | + SetBitRunReader left_reader(left_bitmap, left_offset, length); |
| 570 | + SetBitRunReader right_reader(right_bitmap, right_offset, length); |
| 571 | + auto left_run = left_reader.NextRun(); |
| 572 | + auto right_run = right_reader.NextRun(); |
| 573 | + while (!left_run.AtEnd() && !right_run.AtEnd()) { |
| 574 | + const int64_t start = std::max(left_run.position, right_run.position); |
| 575 | + const int64_t left_end = left_run.position + left_run.length; |
| 576 | + const int64_t right_end = right_run.position + right_run.length; |
| 577 | + const int64_t end = std::min(left_end, right_end); |
| 578 | + if (start < end) { |
| 579 | + ARROW_RETURN_NOT_OK(visit(start, end - start)); |
| 580 | + } |
| 581 | + if (left_end <= right_end) { |
| 582 | + left_run = left_reader.NextRun(); |
| 583 | + } |
| 584 | + if (right_end <= left_end) { |
| 585 | + right_run = right_reader.NextRun(); |
| 586 | + } |
| 587 | + } |
| 588 | + return Status::OK(); |
| 589 | +} |
| 590 | + |
507 | 591 | template <typename Visit> |
508 | 592 | inline void VisitSetBitRunsVoid(const uint8_t* bitmap, int64_t offset, int64_t length, |
509 | 593 | Visit&& visit) { |
|
0 commit comments