mirror of
https://github.com/SerenityOS/serenity
synced 2024-10-15 20:33:10 +00:00
AK: Deal with unsigned integers in binary search.
This commit is contained in:
parent
febc8a5ac7
commit
e77031ce67
|
@ -32,11 +32,21 @@
|
||||||
|
|
||||||
namespace AK {
|
namespace AK {
|
||||||
|
|
||||||
struct IntegralComparator {
|
struct DefaultComparator {
|
||||||
constexpr auto operator()(auto& lhs, auto& rhs) { return lhs - rhs; }
|
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(
|
constexpr auto binary_search(
|
||||||
Container&& haystack,
|
Container&& haystack,
|
||||||
Needle&& needle,
|
Needle&& needle,
|
||||||
|
@ -52,8 +62,10 @@ constexpr auto binary_search(
|
||||||
size_t low = 0;
|
size_t low = 0;
|
||||||
size_t high = haystack.size() - 1;
|
size_t high = haystack.size() - 1;
|
||||||
while (low <= high) {
|
while (low <= high) {
|
||||||
size_t middle = low + ((high - low) / 2);
|
size_t middle = low + (high - low) / 2;
|
||||||
auto comparison = comparator(needle, haystack[middle]);
|
|
||||||
|
int comparison = comparator(needle, haystack[middle]);
|
||||||
|
|
||||||
if (comparison < 0)
|
if (comparison < 0)
|
||||||
if (middle != 0)
|
if (middle != 0)
|
||||||
high = middle - 1;
|
high = middle - 1;
|
||||||
|
|
|
@ -125,4 +125,16 @@ TEST_CASE(constexpr_array_search)
|
||||||
static_assert(binary_search(array, 3) == nullptr);
|
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)
|
TEST_MAIN(BinarySearch)
|
||||||
|
|
|
@ -109,8 +109,10 @@ u32 CanonicalCode::read_symbol(InputBitStream& stream) const
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
code_bits = code_bits << 1 | stream.read_bits(1);
|
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;
|
size_t index;
|
||||||
if (AK::binary_search(m_symbol_codes.span(), code_bits, &index))
|
if (AK::binary_search(m_symbol_codes.span(), code_bits, &index))
|
||||||
return m_symbol_values[index];
|
return m_symbol_values[index];
|
||||||
|
|
Loading…
Reference in a new issue