diff --git a/src/bitarray.cpp b/src/bitarray.cpp index 3647f3e..77dfe2b 100644 --- a/src/bitarray.cpp +++ b/src/bitarray.cpp @@ -606,8 +606,32 @@ namespace bx return _endBit; } + inline uint32_t bitSetFindZero(const uint64_t* _ptr, uint32_t _beginBit, uint32_t _endBit) + { + const uint32_t begin = _beginBit/64; + + for (uint32_t ii = begin, end = alignUp(_endBit, 64)/64; ii < end; ++ii) + { + uint64_t zeros = ~_ptr[ii]; + zeros &= ii == begin ? UINT64_MAX << (_beginBit & 63) : UINT64_MAX; + + if (0 != zeros) + { + const uint32_t idx = ii*64 + countTrailingZeros(zeros); + return idx < _endBit ? idx : kInvalid; + } + } + + return kInvalid; + } + inline uint32_t bitSetFind(const uint64_t* _ptr, uint32_t _beginBit, uint32_t _endBit, uint32_t _numBits) { + if (1 == _numBits) + { + return bitSetFindZero(_ptr, _beginBit, _endBit); + } + if (_numBits >= 127) { const uint32_t idx = bitSetFindT(_ptr, _beginBit, _endBit, (_numBits+63)>>6); diff --git a/tests/bitarray_test.cpp b/tests/bitarray_test.cpp index 94936a4..4029cb9 100644 --- a/tests/bitarray_test.cpp +++ b/tests/bitarray_test.cpp @@ -293,6 +293,35 @@ TEST_CASE("BitArray-find-unset-bit", "[container]") } } +TEST_CASE("BitArray-find-unset-bit-in-range", "[container]") +{ + uint64_t bits[8]; + bx::MutableBitArrayView bs(bits, sizeof(bits) ); + + const uint32_t num = bs.getCount(); + + for (uint32_t ii = 0; ii < num; ++ii) + { + bs.set(0, num, true); + bs.set(ii, false); + + for (uint32_t begin : { 0u, 1u, 63u, 64u, 65u, 200u }) + { + for (uint32_t end : { 66u, 128u, 201u, 511u, 512u }) + { + if (begin >= end) + { + continue; + } + + const uint32_t expected = ii >= begin && ii < end ? ii : bx::kInvalid; + REQUIRE(expected == bs.find(begin, end, 1) ); + REQUIRE(expected == bs.findClear(begin, end) ); + } + } + } +} + TEST_CASE("BitArray-find-with-pattern", "[container]") { uint64_t bits[8];