Find previous set bit starting from position (exclusive)
| 517 | |
| 518 | // Find previous set bit starting from position (exclusive) |
| 519 | int64_t find_prev_set(int64_t start_pos) const |
| 520 | { |
| 521 | if (start_pos == 0) { |
| 522 | return -1; |
| 523 | } |
| 524 | |
| 525 | int64_t search_pos = start_pos - 1; |
| 526 | if (search_pos >= size_) { |
| 527 | search_pos = size_ - 1; |
| 528 | } |
| 529 | |
| 530 | int64_t block_idx = search_pos / bits_per_block; |
| 531 | int64_t bit_idx = search_pos % bits_per_block; |
| 532 | |
| 533 | const auto& features = base::system_report::get_cpu_features(); |
| 534 | |
| 535 | // Check bits up to search position in current block |
| 536 | if (block_idx < blocks_.size()) { |
| 537 | block_type current_block = blocks_[block_idx]; |
| 538 | |
| 539 | // Mask out bits after search position |
| 540 | if (bit_idx != bits_per_block - 1) { |
| 541 | current_block &= ((block_type(1) << (bit_idx + 1)) - 1); |
| 542 | } |
| 543 | |
| 544 | // If there's a set bit in current block |
| 545 | if (current_block != 0) { |
| 546 | int offset; |
| 547 | |
| 548 | if (features.has_fast_bitops) { |
| 549 | #ifdef _MSC_VER |
| 550 | unsigned long index; |
| 551 | if (_BitScanReverse64(&index, current_block)) { |
| 552 | offset = static_cast<int>(index); |
| 553 | } else { |
| 554 | offset = clz_software(current_block); |
| 555 | } |
| 556 | #elif defined(__x86_64__) |
| 557 | #ifdef __BMI1__ |
| 558 | if (features.has_bmi1) { |
| 559 | offset = bits_per_block - 1 - _lzcnt_u64(current_block); |
| 560 | } else { |
| 561 | offset = clz_software(current_block); |
| 562 | } |
| 563 | #else |
| 564 | offset = clz_software(current_block); |
| 565 | #endif |
| 566 | #else |
| 567 | offset = bits_per_block - 1 - __builtin_clzll(current_block); |
| 568 | #endif |
| 569 | } else { |
| 570 | offset = clz_software(current_block); |
| 571 | } |
| 572 | |
| 573 | return block_idx * bits_per_block + offset; |
| 574 | } |
| 575 | } |
| 576 |
no test coverage detected