Skip to content

Releases: harfbuzz/packtab

1.8.0

17 Mar 23:03

Choose a tag to compare

packtab 1.8.0

Highlights:

  • Align generated Rust lint attributes across arrays and functions, including better handling for public items and unsafe accessors.

  • No algorithm changes in this release; this is a Rust-codegen quality release.

packtab 1.7.0

03 Mar 16:46

Choose a tag to compare

packtab 1.7.0

Highlights:

  • Conditional Rust unused_unsafe suppression: safe output stays free of any unsafe text, while unsafe output silences redundant warnings.

  • No algorithm changes in this release; this is a small Rust-codegen quality release.

1.6.0

03 Mar 14:49

Choose a tag to compare

packtab 1.6.0

  • Support inferred defaults from boundary values when no default is provided
  • Preserve explicit-default behavior while merging candidate Pareto frontiers for inferred defaults
  • Document and test inferred-default behavior for list input

1.5.0

02 Mar 19:01

Choose a tag to compare

packtab 1.5.0 adds packtab shape comments to generated lookup functions.

Highlights:

  • Generated top-level lookup functions now include a compact packtab: comment describing the selected solution shape.
  • The annotation reports the split structure, including the leaf term, and includes base offset, palette size, and outer arithmetic when present.
  • This makes it easier to inspect and compare generated tables without reverse-engineering the lookup expression by hand.

Validation:

  • pytest -q packTab/test.py passed before release (206 passed).

1.4.0

01 Mar 19:41

Choose a tag to compare

packTab 1.4.0 focuses on better sparse-prefix compression, clearer compression modes, and simpler generation logic.

Highlights

  • Added explicit compression endpoints.
    • --compression 0 now selects a flat / unsplit encoding.
    • --compression 10 now minimizes raw table bytes.
    • --compression 1..9 keep the historical heuristic behavior.
  • Added aligned leading-default culling.
    • Tables with large power-of-two-aligned default prefixes can now be rebased to the smallest dyadic interval covering the live range.
    • This preserves the recursive split structure while avoiding storage for removable all-default left branches.
  • Added exact leading-default culling for inlineable spans.
    • When trimming to the first non-default index makes the remaining flat span small enough to inline as a constant, packTab now tries that exact rebase too.
  • Removed the identity optimization.
    • This simplifies the model and code generation, and makes rebased sparse-prefix handling easier to reason about.
  • Improved generated C and Rust lookups for rebased spans.
    • Rebased lookups use a single unsigned range check, including safe wrapping arithmetic on Rust.

Other changes

  • Updated documentation for the new compression semantics and sparse-prefix behavior.
  • Expanded tests for compression endpoint selection, aligned prefix culling, and exact-inline prefix culling.

Validation

  • Full test suite passes: 204 tests.

v1.3.0

18 Feb 03:49

Choose a tag to compare

Full Changelog: v1.2.0...v1.3.0

Release 1.2.0

13 Feb 01:08

Choose a tag to compare

New Features

Array Overlap Optimization

When extending arrays, packtab now automatically detects and merges common boundary runs where all overlapping elements share the same value, reducing total array size.

Example:

Existing: [1, 2, 7, 7, 7]  (3 trailing 7s)
New:      [7, 7, 8, 9]      (2 leading 7s)
Result:   [1, 2, 7, 7, 7, 8, 9]  (saved 2 elements)

Improvements

  • ~60 bytes saved on HarfBuzz UCD tables
  • O(N+M) linear scan - very cheap overhead
  • Automatic - only triggers when beneficial (matching boundary values)
  • Universal - works across all generated arrays

Technical Details

The optimization performs two linear scans from array boundaries:

  1. Count trailing run of value V in existing array
  2. Count leading run of value V in new data
  3. Overlap by min(trailing, leading) elements

Since the operation is done during array extension anyway, the overhead is negligible while providing measurable space savings on real-world data.

Installation

pip install --upgrade packtab

1.0.0

12 Feb 22:21

Choose a tag to compare

packtab 1.0.0

This is the first stable release of packtab! 🎉

What's New

Bug Fixes

  • Fixed mapping parameter to accept bidirectional mappings: The mapping parameter in pack_table() now correctly accepts
    bidirectional dictionaries (e.g., {0: "Cc", "Cc": 0}), which are commonly used in Unicode table generation. Previously, this would
    incorrectly raise a TypeError.

Recent Improvements (since 0.4.0)

  • Implemented frequency-based chunk sorting for better cache optimization
  • Fixed constant data optimization with comprehensive edge case tests
  • Implemented dual compression with #ifdef __OPTIMIZE_SIZE__
  • Fixed tests and enabled mapping validation
  • Removed black and flake8 linting in favor of simpler tooling

Development Status

  • Updated from Beta to Production/Stable

Installation

pip install packtab==1.0.0

Links


Full Changelog: 0.4.0...1.0.0

0.4.0

12 Feb 08:58

Choose a tag to compare

Optimizations

  • Identity subtraction: When data is near-linear (data[i] ≈ i), store compact residuals instead of full values
  • Inline small arrays: Arrays ≤ 64 bits are emitted as integer constants with bit extraction, eliminating array storage entirely
  • Bake in bias/multiplier: When bias or GCD multiplier can be folded into stored values without enlarging the data type, the runtime arithmetic is eliminated
  • Bake in shift: When pre-shifted block offsets fit in the same sub-byte bucket, the runtime shift is eliminated
  • O(N log N) Pareto pruning: Solution selection uses sort + scan instead of O(N²) pairwise dominance check

Rust code generation

  • Improved Rust output: pub(crate), static arrays, clippy-clean, proper usize literals
  • wrapping_add()/wrapping_sub() for identity subtraction (Rust panics on unsigned overflow in debug)
  • --unsafe flag for get_unchecked array access
  • End-to-end Rust compilation tests alongside C tests

CLI

  • Rewritten with argparse: --language, --default, --compression, --name, --help
  • --rust kept as shorthand for --language=rust

Bug fixes

  • Fix handling of constant and all-default data
  • Fix string/identifier data to store verbatim values
  • Fix negative unsigned literals from identity + bias interaction
  • Fix parentheses in generated expressions

Code quality

  • Drop Python 2 compatibility
  • Proper exceptions (ValueError, TypeError) instead of assert
  • Comprehensive test suite (172 tests) with C and Rust end-to-end compilation
  • Extracted _best_reduction() helper for bias+GCD logic
  • Extensive design comments throughout