Skip to content

feat(writer): cascade RLE like Rust's IntRLEScheme (issue #410) - #437

Merged
dfa1 merged 1 commit into
mainfrom
feat/410-rle-cascade
Oct 3, 2026
Merged

dfa1 merged 1 commit into
mainfrom
feat/410-rle-cascade

Conversation

@dfa1

@dfa1 dfa1 commented Oct 3, 2026

Copy link
Copy Markdown
Owner

Part of #410, Rust-parity port number 3 after RunEnd (#435) and ZigZag (#436).

RleEncodingEncoder.encodeCascade hands the three fastlanes.rle children to the compressor as open slots instead of raw buffers. Rust's ids (values=0, indices=1, offsets=2) happen to match our wire order:

child carrier excluded (Rust rle_descendant_exclusions)
values column carrier (fromLongsArray) RLE
indices U16, per padded row RLE, Dict, Sparse
offsets U64, per chunk RLE, Dict, Sparse
  • Rust's RunEnd rule on indices/offsets is commented out upstream ("TODO(connor): This is wrong for some reason?"), so it is not ported; parity means the live rule set.
  • RLE names itself on every child, matching Rust's is_excluded ("no scheme appears twice in any chain"). Our slot sets union down the chain, so the effect is the same as Rust's push rules.
  • Rust's ancestor rule (no RLE on a Dict's values pool) has nothing to attach to, as with RunEnd: primitive Dict values are an owned buffer.
  • Refactor: the chunked run loop moves into one Runs helper shared by encode, encodeBool and encodeCascade, so there are no longer three copies.

Parity gap noted, not addressed here: Rust also has a float RLE scheme; ours accepts integers only.

Size: byte-identical on every FileSizeComparison case.

Tests: RleEncodingEncoderTest.Cascade (values/indices/offsets across 2 FastLanes chunks, child dtypes, exclusions, empty input). Green: writer and reader unit suites, plus 367 integration tests including vortex-jni interop.

🤖 Generated with Claude Code

Parity with the reference compressor: fastlanes.rle overrides
encodeCascade and hands values, indices and offsets to the compressor as
open children (Rust ids values=0, indices=1, offsets=2 match our wire
order), with Rust's rle_descendant_exclusions: Dict and Sparse barred on
indices and offsets. Rust's RunEnd rule there is commented out upstream as
unsound, so it is not ported. RLE names itself on every child, matching
Rust's "no scheme twice in one chain".

The chunked run computation moves into one Runs helper shared by encode,
encodeBool and encodeCascade. Output is byte-identical on every size
comparison; all interop suites green.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@dfa1
dfa1 merged commit 91f710b into main Oct 3, 2026
6 checks passed
@dfa1
dfa1 deleted the feat/410-rle-cascade branch October 3, 2026 07:11
dfa1 added a commit that referenced this pull request Oct 3, 2026
Parity gap found while porting IntRLEScheme (#437): Rust also RLE-encodes
floats, while RleEncodingEncoder refused them. It now accepts every
primitive. Runs compare raw bits (as toLongs already did for floats), so
the encoding is lossless: -0.0, +0.0 and NaN payloads stay distinct. The
cascade's values child is the column's own float[]/double[], so ALP can
compete on the run values; Rust's float scheme shares the int one's
children and exclusions, so nothing else changes.

vortex-jni reads Java-written float RLE back bit for bit, forced and
through the cascade. Size comparisons are byte-identical.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
dfa1 added a commit that referenced this pull request Oct 3, 2026
Parity gap found while porting IntRLEScheme (#437): Rust also RLE-encodes
floats, while RleEncodingEncoder refused them. It now accepts every
primitive. Runs compare raw bits (as toLongs already did for floats), so
the encoding is lossless: -0.0, +0.0 and NaN payloads stay distinct. The
cascade's values child is the column's own float[]/double[], so ALP can
compete on the run values; Rust's float scheme shares the int one's
children and exclusions, so nothing else changes.

vortex-jni reads Java-written float RLE back bit for bit, forced and
through the cascade. Size comparisons are byte-identical.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
dfa1 added a commit that referenced this pull request Oct 3, 2026
Date the section, add decimal and compressor-parity highlights, cover the
zigzag/RLE cascade PRs (#436, #437), and bump the README snippets to 0.15.2
with a pointer to the Raincloud conformance result.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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