Improve bitmap::_calculateArea performance (#6572)
`bitmap::_calculateArea` performance can be improved by leveraging the optimized `find_first`/`find_next` methods instead of iterating through the bitmap manually.
This commit is contained in:
parent
b91430b64d
commit
15f2535752
|
@ -84,7 +84,10 @@
|
|||
|
||||
// Dynamic Bitset (optional dependency on LibPopCnt for perf at bit counting)
|
||||
// Variable-size compressed-storage header-only bit flag storage library.
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4702) // unreachable code
|
||||
#include <dynamic_bitset.hpp>
|
||||
#pragma warning(pop)
|
||||
|
||||
// {fmt}, a C++20-compatible formatting library
|
||||
#include <fmt/format.h>
|
||||
|
|
|
@ -81,16 +81,20 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
const ptrdiff_t _end;
|
||||
til::rectangle _run;
|
||||
|
||||
// Update _run to contain the next rectangle of consecutively set bits within this bitmap.
|
||||
// _calculateArea may be called repeatedly to yield all those rectangles.
|
||||
void _calculateArea()
|
||||
{
|
||||
// Backup the position as the next one.
|
||||
_nextPos = _pos;
|
||||
// The following logic first finds the next set bit in this bitmap and the next unset bit past that.
|
||||
// The area in between those positions are thus all set bits and will end up being the next _run.
|
||||
|
||||
// Seek forward until we find an on bit.
|
||||
while (_nextPos < _end && !_values[_nextPos])
|
||||
{
|
||||
++_nextPos;
|
||||
}
|
||||
// dynamic_bitset allows you to quickly find the next set bit using find_next(prev),
|
||||
// where "prev" is the position _past_ which should be searched (i.e. excluding position "prev").
|
||||
// If _pos is still 0, we thus need to use the counterpart find_first().
|
||||
const auto nextPos = _pos == 0 ? _values.find_first() : _values.find_next(_pos - 1);
|
||||
// If no next set bit can be found, npos is returned, which is SIZE_T_MAX.
|
||||
// saturated_cast can ensure that this will be converted to PTRDIFF_T_MAX (which is greater than _end).
|
||||
_nextPos = base::saturated_cast<ptrdiff_t>(nextPos);
|
||||
|
||||
// If we haven't reached the end yet...
|
||||
if (_nextPos < _end)
|
||||
|
@ -118,8 +122,10 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
}
|
||||
else
|
||||
{
|
||||
// If we reached the end, set the pos because the run is empty.
|
||||
_pos = _nextPos;
|
||||
// If we reached the end _nextPos may be >= _end (potentially even PTRDIFF_T_MAX).
|
||||
// ---> Mark the end of the iterator by updating the state with _end.
|
||||
_pos = _end;
|
||||
_nextPos = _end;
|
||||
_run = til::rectangle{};
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue