mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-21 23:20:20 +00:00
AK: Deal with unsigned integers in binary search.
This commit is contained in:
parent
febc8a5ac7
commit
e77031ce67
Notes:
sideshowbarker
2024-07-19 00:15:40 +09:00
Author: https://github.com/asynts Commit: https://github.com/SerenityOS/serenity/commit/e77031ce67b Pull-request: https://github.com/SerenityOS/serenity/pull/4722
3 changed files with 32 additions and 6 deletions
|
@ -32,11 +32,21 @@
|
|||
|
||||
namespace AK {
|
||||
|
||||
struct IntegralComparator {
|
||||
constexpr auto operator()(auto& lhs, auto& rhs) { return lhs - rhs; }
|
||||
struct DefaultComparator {
|
||||
template<typename T, typename S>
|
||||
constexpr int operator()(T& lhs, S& rhs)
|
||||
{
|
||||
if (lhs > rhs)
|
||||
return 1;
|
||||
|
||||
if (lhs < rhs)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Container, typename Needle, typename Comparator = IntegralComparator>
|
||||
template<typename Container, typename Needle, typename Comparator = DefaultComparator>
|
||||
constexpr auto binary_search(
|
||||
Container&& haystack,
|
||||
Needle&& needle,
|
||||
|
@ -52,8 +62,10 @@ constexpr auto binary_search(
|
|||
size_t low = 0;
|
||||
size_t high = haystack.size() - 1;
|
||||
while (low <= high) {
|
||||
size_t middle = low + ((high - low) / 2);
|
||||
auto comparison = comparator(needle, haystack[middle]);
|
||||
size_t middle = low + (high - low) / 2;
|
||||
|
||||
int comparison = comparator(needle, haystack[middle]);
|
||||
|
||||
if (comparison < 0)
|
||||
if (middle != 0)
|
||||
high = middle - 1;
|
||||
|
|
|
@ -125,4 +125,16 @@ TEST_CASE(constexpr_array_search)
|
|||
static_assert(binary_search(array, 3) == nullptr);
|
||||
}
|
||||
|
||||
TEST_CASE(unsigned_to_signed_regression)
|
||||
{
|
||||
const Array<u32, 5> input { 0, 1, 2, 3, 4 };
|
||||
|
||||
// The algorithm computes 1 - input[2] = -1, and if this is (incorrectly) cast
|
||||
// to an unsigned then it will look in the wrong direction and miss the 1.
|
||||
|
||||
size_t nearby_index = 1;
|
||||
EXPECT_EQ(binary_search(input, 1u, &nearby_index), &input[1]);
|
||||
EXPECT_EQ(nearby_index, 1u);
|
||||
}
|
||||
|
||||
TEST_MAIN(BinarySearch)
|
||||
|
|
|
@ -109,8 +109,10 @@ u32 CanonicalCode::read_symbol(InputBitStream& stream) const
|
|||
|
||||
for (;;) {
|
||||
code_bits = code_bits << 1 | stream.read_bits(1);
|
||||
ASSERT(code_bits < (1 << 16));
|
||||
|
||||
// FIXME: This seems really inefficient, this could be an index into an array instead.
|
||||
// FIXME: This is very inefficent and could greatly be improved by implementing this
|
||||
// algorithm: https://www.hanshq.net/zip.html#huffdec
|
||||
size_t index;
|
||||
if (AK::binary_search(m_symbol_codes.span(), code_bits, &index))
|
||||
return m_symbol_values[index];
|
||||
|
|
Loading…
Reference in a new issue