Skip to content

Drop odd-length flat dead byte; make --analyze score consistent - #11

Merged
behdad merged 1 commit into
masterfrom
fix/flat-dead-byte-and-analyze
Jul 1, 2026
Merged

Drop odd-length flat dead byte; make --analyze score consistent#11
behdad merged 1 commit into
masterfrom
fix/flat-dead-byte-and-analyze

Conversation

@behdad

@behdad behdad commented Jul 1, 2026

Copy link
Copy Markdown
Member

Two low-severity cleanups from the earlier soundness review.

1. Odd-length flat "dead byte"

InnerLayer.split() padded self.data in place to make pairing work, but
the flat (unsplit) solution emits self.data directly — so odd-length flat
tables carried one unreachable trailing padding byte, and the reported
.cost (computed from the un-padded length) was one element short of the
emission.

Fix: pad a local copy instead. self.data stays the original array, so the
flat solution emits exactly len(data) elements. Split solutions are unchanged
(pairing still uses the optimally-padded copy), so solution costs — and
pick_solution's choices — are identical
; only the flat array for odd-length
tables loses its dead byte (one byte smaller, never larger). No runtime ops are
added to the generated code; generation cost is a negligible O(n) copy for odd
layers only.

2. --analyze score display

The displayed Score used floor(log2) (fullCost.bit_length() - 1) while
pick_solution uses exact log2, so the highlighted "Best solution" could
disagree with the minimum-score row (e.g. two solutions whose fullCosts share a
floor(log2) bucket). Use exact log2 and show two decimals so the ranking is
visibly consistent.

Verification

  • pytest: 236 passing (adds tests: flat odd-length emits no padding byte,
    split() doesn't mutate self.data, flat odd-length round-trips in C+Rust,
    and --analyze best-row == min-score-row).
  • A C+Rust round-trip fuzz over all Pareto solutions: zero failures.
  • Regenerating HarfBuzz's Unicode tables (make -f update-unicode-tables.make clean all) yields byte-identical output in ~10s (the flat fix is a no-op
    for HarfBuzz's multi-level tables).

🤖 Generated with Claude Code

InnerLayer.split() padded self.data in place to make pairing work, but the
flat (unsplit) solution emits self.data directly, so odd-length flat tables
carried one unreachable trailing padding byte (and the reported cost, computed
from the un-padded length, was one element short of the emission).  Pad a local
copy instead; self.data stays the original array, so the flat solution emits
exactly len(data) elements.  Split solutions are unchanged (pairing still uses
the optimally-padded copy), so solution costs — and pick_solution's choices —
are identical; only the flat array for odd-length tables loses its dead byte.

Separately, `--analyze` computed the displayed Score with floor(log2)
(bit_length()-1) while pick_solution uses exact log2, so the highlighted "Best
solution" could disagree with the minimum-score row.  Use exact log2 and show
two decimals so the ranking is visibly consistent.

Verified: 236 tests pass; a C+Rust round-trip fuzz over all Pareto solutions
reports zero failures; regenerating HarfBuzz's tables yields byte-identical
output in ~10s (the fix is a no-op for multi-level tables).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@behdad
behdad merged commit 310edfc into master Jul 1, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant