-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
construct huffman table from symbol spans
Define class template `symbol_span` that represents an inclusive range from first to last. The `symbol_bitsize` constructor of `huffman::table` now takes a range of pair-likes of `symbol_span` and bitsize, allowin gthe same bitsize to be associated with a contiguous range of symbols. For example, the static Huffman tree corresponding to the literal/length alphabet in section 3.2.6 of the DEFLATE RFC can be defined as: constexpr auto table = huffman::table<std::uint16_t, 288>{ huffman::symbol_bitsize, {{{ 0, 143}, 8}, {{144, 255}, 9}, {{256, 279}, 7}, {{280, 287}, 8}}}; resolves #91 Change-Id: I50f7ea63561de0bb785c85467cdb943829b65edf Co-Authored-By: Gary Miguel <[email protected]>
- Loading branch information
Showing
9 changed files
with
344 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
#pragma once | ||
|
||
#include <cstddef> | ||
#include <iterator> | ||
#include <numeric> | ||
#include <ranges> | ||
|
||
namespace starflate::huffman::detail { | ||
|
||
template <std::ranges::view V> | ||
class flattened_symbol_bitsize_view | ||
: public std::ranges::view_interface<flattened_symbol_bitsize_view<V>> | ||
{ | ||
V base_; | ||
std::size_t size_; | ||
|
||
using child_view_type = std::remove_cvref_t<std::ranges::range_value_t<V>>; | ||
|
||
public: | ||
using base_type = V; | ||
|
||
class iterator | ||
{ | ||
const flattened_symbol_bitsize_view* parent_{}; | ||
std::size_t offset1_{}; | ||
std::size_t offset2_{}; | ||
|
||
public: | ||
using iterator_category = std::forward_iterator_tag; | ||
using difference_type = std::ranges::range_difference_t<child_view_type>; | ||
using value_type = std::ranges::range_value_t<child_view_type>; | ||
using reference = std::ranges::range_reference_t<child_view_type>; | ||
using pointer = void; | ||
|
||
iterator() = default; | ||
|
||
constexpr iterator( | ||
const flattened_symbol_bitsize_view& parent, | ||
std::size_t offset1, | ||
std::size_t offset2) | ||
: parent_{&parent}, offset1_{offset1}, offset2_{offset2} | ||
{} | ||
|
||
[[nodiscard]] | ||
constexpr auto | ||
operator*() const -> reference | ||
{ | ||
using D = difference_type; | ||
return parent_ | ||
->base()[static_cast<D>(offset1_)][static_cast<D>(offset2_)]; | ||
} | ||
|
||
constexpr auto operator++() & -> iterator& | ||
{ | ||
using D = difference_type; | ||
|
||
if (++offset2_ == | ||
static_cast<std::size_t>( | ||
parent_->base()[static_cast<D>(offset1_)].size())) { | ||
++offset1_; | ||
offset2_ = {}; | ||
} | ||
|
||
return *this; | ||
} | ||
|
||
constexpr auto operator++(int) -> iterator | ||
{ | ||
auto tmp = *this; | ||
++*this; | ||
return tmp; | ||
} | ||
|
||
friend constexpr auto | ||
operator==(const iterator&, const iterator&) -> bool = default; | ||
}; | ||
|
||
constexpr explicit flattened_symbol_bitsize_view(V base) | ||
: base_{std::move(base)}, | ||
size_{std::accumulate( | ||
std::ranges::cbegin(base_), | ||
std::ranges::cend(base_), | ||
0UZ, | ||
[](auto acc, const auto& subrange) { | ||
return acc + subrange.size(); | ||
})} | ||
{} | ||
|
||
[[nodiscard]] | ||
constexpr auto base() const -> base_type | ||
{ | ||
return base_; | ||
} | ||
|
||
[[nodiscard]] | ||
constexpr auto size() const -> std::size_t | ||
{ | ||
return size_; | ||
} | ||
|
||
[[nodiscard]] | ||
constexpr auto begin() const -> iterator | ||
{ | ||
return {*this, 0, 0}; | ||
} | ||
|
||
[[nodiscard]] | ||
constexpr auto end() const -> iterator | ||
{ | ||
return {*this, base().size(), 0}; | ||
} | ||
}; | ||
|
||
} // namespace starflate::huffman::detail | ||
|
||
// flattened_symbol_bitsize_view is only created to adapt an input range during | ||
// construction | ||
template <class V> | ||
inline constexpr bool std::ranges::enable_borrowed_range< | ||
::starflate::huffman::detail::flattened_symbol_bitsize_view<V>> = true; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#pragma once | ||
|
||
#include <type_traits> | ||
|
||
namespace starflate::huffman::detail { | ||
|
||
/// Checks if a type is a specialization of a class template | ||
/// @tparam T type | ||
/// @tparam primary class template | ||
/// | ||
/// @see https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2098r1.pdf | ||
/// | ||
/// | ||
|
||
template <class T, template <class...> class primary> | ||
struct is_specialization_of : std::false_type | ||
{}; | ||
|
||
template <template <class...> class primary, class... Args> | ||
struct is_specialization_of<primary<Args...>, primary> : std::true_type | ||
{}; | ||
|
||
template <class T, template <class...> class primary> | ||
inline constexpr auto is_specialization_of_v = | ||
is_specialization_of<T, primary>::value; | ||
|
||
} // namespace starflate::huffman::detail |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
#pragma once | ||
|
||
#include "huffman/src/utility.hpp" | ||
|
||
#include <concepts> | ||
#include <ranges> | ||
|
||
namespace starflate::huffman { | ||
|
||
/// An inclusive span of symbols | ||
/// | ||
template <symbol S> | ||
class symbol_span : public std::ranges::view_interface<symbol_span<S>> | ||
{ | ||
S first_; | ||
S last_; | ||
|
||
using range_type = std::ranges::iota_view<S, S>; | ||
|
||
constexpr auto as_range() const -> range_type | ||
{ | ||
auto tmp = last_; | ||
return range_type{first_, ++tmp}; | ||
} | ||
|
||
public: | ||
using symbol_type = S; | ||
|
||
using iterator = std::ranges::iterator_t<range_type>; | ||
|
||
/// Construct a symbol span of a single symbol | ||
/// @param first symbol | ||
/// | ||
constexpr symbol_span(symbol_type first) : symbol_span{first, first} {} | ||
|
||
/// Construct a symbol span from first to last, inclusive | ||
/// @param first, last inclusive symbol range | ||
/// @pre first <= last | ||
/// | ||
constexpr symbol_span(symbol_type first, symbol_type last) | ||
: first_{first}, last_{last} | ||
{ | ||
assert(first <= last); | ||
} | ||
|
||
[[nodiscard]] | ||
constexpr auto begin() const -> iterator | ||
{ | ||
return as_range().begin(); | ||
} | ||
|
||
[[nodiscard]] | ||
constexpr auto end() const -> iterator | ||
{ | ||
return as_range().end(); | ||
} | ||
}; | ||
|
||
} // namespace starflate::huffman |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.