Skip to content

Commit

Permalink
use random access indexing in huffman::table::find (#101)
Browse files Browse the repository at this point in the history
All DEFLATE canonical codes of a given bitsize are lexicographically
consecutive values in the same order as the symbols they represent. As
a result, the skip field for the first code of a given bitsize can be
used to determine if an input code exists in the table in constant time.

This commit replaces the linear time search of all codes of a given
bitsize in huffman::table::find. Instead, the find method does the
following:
* if the input code bitsize is greater than the iterator code bitsize,
  advance the iterator by the iterator skip field
* if the input code bitsize is less than the iterator code bitsize,
  return the iterator as an error
* if the input code bitsize is equal to the iterator code bitsize:
  - determine the distance from the iterator code value to the input
    code value. If it is less than the iterator skip field, advance the
    iterator by the calculated distance and return the iterator as a
    success; otherwise
  - advance the iterator by the iterator skip field and continue

resolves #90

Change-Id: Ic736c4d2e0150e53bd7bf1870104462294368a5c
  • Loading branch information
oliverlee authored Jan 6, 2024
1 parent 4b1d0c0 commit b4f1ad9
Showing 1 changed file with 9 additions and 10 deletions.
19 changes: 9 additions & 10 deletions huffman/src/table.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -426,26 +426,25 @@ class table
-> std::expected<const_iterator, const_iterator>
{
using R = std::expected<const_iterator, const_iterator>;
using D = std::iter_difference_t<const_iterator>;

while (pos != end()) {
if (pos->bitsize() > c.bitsize()) {
break;
}

if (pos->bitsize() < c.bitsize()) {
using D = std::iter_difference_t<const_iterator>;
assert(
pos.base()->skip() <= std::size_t{std::numeric_limits<D>::max()});
const auto skip = pos.base()->skip();

pos += static_cast<D>(pos.base()->skip());
continue;
}
if (pos->bitsize() == c.bitsize()) {
assert(pos->value() <= c.value());

if (static_cast<const code&>(*pos) == c) {
return R{std::in_place, pos};
if (const auto dist = c.value() - pos->value(); dist < skip) {
return R{std::in_place, pos + static_cast<D>(dist)};
}
}

++pos;
assert(skip <= std::size_t{std::numeric_limits<D>::max()});
pos += static_cast<D>(skip);
}

return R{std::unexpect, pos};
Expand Down

0 comments on commit b4f1ad9

Please sign in to comment.