Skip to content

Commit

Permalink
decode dynamic blocks (#135)
Browse files Browse the repository at this point in the history
also:
* fix VS Code settings
* fix build on MacOS by disabling exceptions (build being broken is probably a bug in LLVM but we don't need exceptions anyways)
* update readme. no more work is planned beyond this PR
  • Loading branch information
garymm authored Jan 31, 2025
1 parent c6da155 commit 289b78a
Show file tree
Hide file tree
Showing 8 changed files with 211 additions and 85 deletions.
2 changes: 1 addition & 1 deletion .clangd
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ CompileFlags:
# incorrect system include paths. These fix that.
# Specifying non-existent include paths on other platforms doesn't cause issues
# (e.g. mentioning linux-gnu works on MacOS).
Add: [-nostdinc++, -isystem, external/llvm_toolchain_files/include/x86_64-unknown-linux-gnu/c++/v1, -isystem, external/llvm_toolchain_files/include/c++/v1]
Add: [-nostdinc++, -isystem, external/llvm_toolchain_llvm/include/x86_64-unknown-linux-gnu/c++/v1, -isystem, external/llvm_toolchain_llvm/include/c++/v1]
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@
"--compile-commands-dir=${workspaceFolder}/",
"--enable-config"
],
"clangd.path": "${workspaceFolder}/external/llvm_toolchain_files/bin/clangd"
"clangd.path": "${workspaceFolder}/external/llvm_toolchain_llvm/bin/clangd"
}
30 changes: 7 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
# starflate

Deflate on various hardware platforms
Deflate decompression in C++23.

This started with the goal of implenting deflate decompression on a GPU, but
it turns out that is basically impossible to parallelize. Compression is possible
to parallelize, but I have not yet implemented it.


## Set up

Should work on Linux and MacOS.
Should work on Linux x86_64 and MacOS.

* Install [bazelisk](https://github.com/bazelbuild/bazelisk/blob/master/README.md).

Expand Down Expand Up @@ -38,27 +43,6 @@ Otherwise, copy the clangd args from the [.vscode/settings.json](.vscode/setting

[![CI](https://github.com/garymm/starflate/actions/workflows/check.yml/badge.svg)](https://github.com/garymm/starflate/actions/workflows/check.yml) [![codecov](https://codecov.io/gh/garymm/starflate/graph/badge.svg?token=PGIMUPMNIF)](https://codecov.io/gh/garymm/starflate)

### Done

* Build Huffman code tables from given symbol frequencies.
* Huffman decoding with C++ std lib.

### TODO

#### Basic

* Implement Deflate decompression with C++ std lib.
* Benchmark it on CPU.
* Build system work to get it to run on GPU.
* Port Deflate to GPU.
* Benchmark it on GPU.

#### Nice to have

* Support chunked output. Started in
[2e6a83d622e](https://github.com/garymm/starflate/commit/2e6a83d622a0bbe6b65c757199b64511156b516c)
, but removed because it was adding too much complexity and I wanted to focus on getting the
basics working.

## References

Expand Down
3 changes: 3 additions & 0 deletions WORKSPACE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ COMMON_CXX_FLAGS = [
"-march=native",
"-std=c++23",
"-fdiagnostics-color=always",
# added to work around https://github.com/llvm/llvm-project/issues/79008
# but actually we probably don't want exceptions anyways.
"-fno-exceptions",
]

COMMON_CXX_WARNINGS = [
Expand Down
7 changes: 2 additions & 5 deletions huffman/src/detail/static_vector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#include <array>
#include <cstddef>
#include <iterator>
#include <stdexcept>
#include <utility>

namespace starflate::huffman::detail {
Expand Down Expand Up @@ -34,11 +33,9 @@ class static_vector : std::array<T, Capacity>
using base_type::data;
using base_type::front;

constexpr auto reserve(size_type new_cap) -> void
constexpr auto reserve(size_type new_cap [[maybe_unused]]) -> void
{
if (new_cap > Capacity) {
throw std::length_error{"`static_vector` capacity exceeded."};
}
assert(new_cap <= Capacity);
}

constexpr auto resize(size_type new_cap) -> void
Expand Down
73 changes: 32 additions & 41 deletions huffman/test/decode_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
#include <array>
#include <climits>
#include <cstddef>
#include <stdexcept>
#include <utility>

namespace {
Expand All @@ -32,19 +31,7 @@ constexpr auto code_table = [] {

} // namespace

namespace test {

namespace {

constexpr auto verify(bool cond)
{
if (not cond) {
throw std::runtime_error{""};
}
}
} // namespace
} // namespace test

// NOLINTNEXTLINE(readability-function-cognitive-complexity)
auto main() -> int
{
using ::boost::ut::eq;
Expand All @@ -62,7 +49,7 @@ auto main() -> int
return it == buf.begin();
}();

static_assert(result);
expect(result);
};

test("just `e` - beginning not byte aligned") = [] {
Expand All @@ -73,12 +60,14 @@ auto main() -> int

auto buf = std::array<char, expected.size()>{};

auto it = huffman::decode(
auto it [[maybe_unused]]
= huffman::decode(
code_table,
huffman::bit_span{encoded}.consume(CHAR_BIT - 1),
buf.begin());

::test::verify(it == buf.end());
// NOTE: using assert because expect() doesn't work inside constexpr.
assert(it == buf.end());
return buf;
}();

Expand All @@ -89,20 +78,17 @@ auto main() -> int
static constexpr auto expected = std::array{'e'};

constexpr auto decoded = [] {
constexpr auto encoded = std::array{
//
std::byte{0b0111'1111} // ^^^ ^^^^
// padding
};
constexpr auto encoded = std::array{std::byte{0b0111'1111}};

auto buf = std::array<char, expected.size()>{};

auto it = huffman::decode(
auto it [[maybe_unused]]
= huffman::decode(
code_table,
huffman::bit_span{encoded}.consume(CHAR_BIT - 1),
buf.begin());

::test::verify(it == buf.end());
assert(it == buf.end());
return buf;
}();

Expand All @@ -121,9 +107,10 @@ auto main() -> int

auto buf = std::array<char, expected.size()>{};

auto it = huffman::decode(code_table, encoded, buf.begin());
auto it [[maybe_unused]]
= huffman::decode(code_table, encoded, buf.begin());

::test::verify(it == buf.end());
assert(it == buf.end());
return buf;
}();

Expand Down Expand Up @@ -155,9 +142,10 @@ auto main() -> int
constexpr auto decoded = [] {
auto buf = std::array<char, expected.size()>{};

auto it = huffman::decode(different_table, encoded, buf.begin());
auto it [[maybe_unused]]
= huffman::decode(different_table, encoded, buf.begin());

::test::verify(it == buf.end());
assert(it == buf.end());
return buf;
}();

Expand All @@ -172,9 +160,10 @@ auto main() -> int

auto buf = std::array<char, expected.size()>{};

auto it = huffman::decode(code_table, encoded, buf.begin());
auto it [[maybe_unused]]
= huffman::decode(code_table, encoded, buf.begin());

::test::verify(it == buf.end());
assert(it == buf.end());
return buf;
}();

Expand All @@ -191,9 +180,10 @@ auto main() -> int

auto buf = std::array<char, expected.size()>{};

auto it = huffman::decode(code_table, encoded, buf.begin());
auto it [[maybe_unused]]
= huffman::decode(code_table, encoded, buf.begin());

::test::verify(it == buf.end());
assert(it == buf.end());
return buf;
}();

Expand All @@ -211,12 +201,13 @@ auto main() -> int

auto buf = std::array<char, expected.size()>{};

auto it = huffman::decode(
auto it [[maybe_unused]]
= huffman::decode(
code_table,
huffman::bit_span{encoded.data(), (encoded.size() * CHAR_BIT) - 2},
buf.begin());

::test::verify(it == buf.end());
assert(it == buf.end());
return buf;
}();

Expand All @@ -235,9 +226,10 @@ auto main() -> int

auto buf = std::array<char, expected.size()>{};

auto it = huffman::decode(code_table, encoded, buf.begin());
auto it [[maybe_unused]]
= huffman::decode(code_table, encoded, buf.begin());

::test::verify(it == buf.end());
assert(it == buf.end());
return buf;
}();

Expand All @@ -256,18 +248,17 @@ auto main() -> int
std::byte{0b0101'1111},
std::byte{0b0011'0111},
std::byte{0b0110'1001},
std::byte{0b0011'1101} // ^
// padding
};
std::byte{0b0011'1101}};

auto buf = std::array<char, expected.size()>{};

auto it = huffman::decode(
auto it [[maybe_unused]]
= huffman::decode(
code_table,
huffman::bit_span{encoded.data(), (encoded.size() * CHAR_BIT) - 1},
buf.begin());

::test::verify(it == buf.end());
assert(it == buf.end());
return buf;
}();

Expand Down
Loading

0 comments on commit 289b78a

Please sign in to comment.